Skip to content

Commit

Permalink
Add I3C Slave Support
Browse files Browse the repository at this point in the history
Signed-off-by: su-shih-hsin <[email protected]>
  • Loading branch information
su-shih-hsin authored and maxdog988 committed Sep 6, 2023
1 parent 5b3e264 commit 2f5fe91
Show file tree
Hide file tree
Showing 27 changed files with 2,458 additions and 349 deletions.
8 changes: 4 additions & 4 deletions drivers/i3c/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ zephyr_library()

zephyr_library_sources(i3c_common.c)

zephyr_library_sources_ifdef(CONFIG_I3C_ASPEED i3c_global_aspeed.c)
#zephyr_library_sources_ifdef(CONFIG_I3C_ASPEED i3c_global_aspeed.c)
#zephyr_library_sources_ifdef(CONFIG_I3C_ASPEED i3c_aspeed.c)

add_subdirectory_ifdef(CONFIG_I3C_NPCM4XX NPCM4XX)
add_subdirectory_ifdef(CONFIG_I3C_NPCM4XX NPCM4XX)
add_subdirectory_ifdef(CONFIG_I3C_SLAVE slave)
zephyr_library_sources_ifdef(CONFIG_I3C_NPCM4XX i3c_npcm4xx.c)
#zephyr_library_sources_ifdef(CONFIG_I3C_SHELL i3c_shell.c)
#add_subdirectory_ifdef(CONFIG_I3C_SLAVE slave)
zephyr_library_sources_ifdef(CONFIG_I3C_SHELL i3c_shell.c)
2 changes: 1 addition & 1 deletion drivers/i3c/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ module = I3C
module-str = i3c
source "subsys/logging/Kconfig.template.log_config"

#source "drivers/i3c/slave/Kconfig"
source "drivers/i3c/slave/Kconfig"

# Include these first so that any properties (e.g. defaults) below can be
# overridden (by defining symbols in multiple locations)
Expand Down
5 changes: 5 additions & 0 deletions drivers/i3c/NPCM4XX/api_i3c.c
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,11 @@ void api_I3C_Master_Stop(__u32 Parm)
I3C_Master_Stop_Request(Parm);
}

void api_I3C_Master_Retry(__u32 Parm)
{
I3C_Master_Retry_Frame(Parm);
}

void api_I3C_Master_Run_Next_Frame(__u32 Parm)
{
I3C_Master_Run_Next_Frame(Parm);
Expand Down
19 changes: 18 additions & 1 deletion drivers/i3c/NPCM4XX/i3c_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,10 @@ I3C_ErrCode_Enum I3C_Port_Default_Setting(I3C_PORT_Enum port)
pDevice->vendorID = 0;
pDevice->partNumber = 0;

pDevice->max_rd_len = hal_I3C_get_MAXRD(port);
pDevice->max_wr_len = hal_I3C_get_MAXWR(port);

pDevice->regCnt = 0;
pDevice->pReg = NULL;
pDevice->cmdIndex = CMD_DEFAULT;
pDevice->stopSplitRead = FALSE;
Expand Down Expand Up @@ -3064,6 +3068,7 @@ I3C_ErrCode_Enum I3C_Master_Insert_Task_CCCw(__u8 CCC, __u8 HSize, __u16 buf_siz
__u16 i;
__u8 fmt;
__u16 dev_count;
__u8 remainder;

if (HSize < 1) {
return I3C_ERR_PARAMETER_INVALID;
Expand Down Expand Up @@ -3118,6 +3123,7 @@ I3C_ErrCode_Enum I3C_Master_Insert_Task_CCCw(__u8 CCC, __u8 HSize, __u16 buf_siz
} else if (CCC == CCC_DIRECT_SETMWL) {
fmt = 3;
} else if (CCC == CCC_DIRECT_SETMRL) {
/*fmt = 3;*/
fmt = 4;
} else if ((CCC == CCC_DIRECT_SETBRGTGT) || (CCC == CCC_DIRECT_SETROUTE) ||
(CCC == CCC_DIRECT_SETXTIME)) {
Expand All @@ -3128,7 +3134,18 @@ I3C_ErrCode_Enum I3C_Master_Insert_Task_CCCw(__u8 CCC, __u8 HSize, __u16 buf_siz
return I3C_ERR_HW_NOT_SUPPORT;
}

dev_count = buf_size - (HSize - 1) / fmt;
RETRY:
dev_count = (buf_size - (HSize - 1)) / fmt;
remainder = (buf_size - (HSize - 1)) % fmt;

if (remainder != 0) {
/* try another fmt */
if ((CCC == CCC_DIRECT_SETMRL) && (fmt == 4)) {
fmt = 3;
goto RETRY;
}
}

if (dev_count < 1) {
return I3C_ERR_PARAMETER_INVALID;
}
Expand Down
97 changes: 83 additions & 14 deletions drivers/i3c/NPCM4XX/i3c_master.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@

LOG_MODULE_REGISTER(npcm4xx_i3c_master, CONFIG_I3C_LOG_LEVEL);

extern struct k_work_q npcm4xx_i3c_work_q[I3C_PORT_MAX];
extern struct k_work work_retry[I3C_PORT_MAX];
extern struct k_work work_rcv_ibi[I3C_PORT_MAX];

/**
* @brief Callback for I3C master
* @param [in] TaskInfo Pointer to the running task
Expand Down Expand Up @@ -64,6 +68,11 @@ __u32 I3C_Master_Callback(__u32 TaskInfo, __u32 ErrDetail)
return I3C_DO_SW_TIMEOUT(pTaskInfo);
}

/*
* IBI / Hot-Join / MasterRequest tasks are forked by SLV_START
* So, there is no xfer to return status and data.
* We should define callback functions for these cases.
*/
if (ErrDetail == I3C_ERR_IBI) {
return I3C_DO_IBI(pTaskInfo);
}
Expand Down Expand Up @@ -427,9 +436,7 @@ __u32 I3C_DO_SW_TIMEOUT(I3C_TASK_INFO_t *pTaskInfo)
/*------------------------------------------------------------------------------*/
__u32 I3C_DO_IBI(I3C_TASK_INFO_t *pTaskInfo)
{
I3C_TRANSFER_TASK_t *pTask;
I3C_BUS_INFO_t *pBus;
I3C_DEVICE_INFO_SHORT_t *pDev;

if (pTaskInfo == NULL) {
return I3C_ERR_PARAMETER_INVALID;
Expand All @@ -441,17 +448,13 @@ __u32 I3C_DO_IBI(I3C_TASK_INFO_t *pTaskInfo)
return I3C_ERR_PARAMETER_INVALID;
}

pTask = pTaskInfo->pTask;
pBus = Get_Bus_From_Port(pTaskInfo->Port);
pDev = GetDevInfoByDynamicAddr(pBus, pTask->address);
if (pDev == NULL) {
return I3C_ERR_TASK_INVALID;
}

if (pTaskInfo->callback != NULL) {
/* pTaskInfo->callback(TaskInfo, ErrDetail); */
}

pBus = Get_Bus_From_Port(pTaskInfo->Port);
pBus->pCurrentMaster->bAbort = FALSE;

I3C_Complete_Task(pTaskInfo);
pBus->pCurrentTask = NULL;
pBus->busState = I3C_BUS_STATE_IDLE;
Expand Down Expand Up @@ -771,12 +774,24 @@ __u32 I3C_DO_SETAASA(I3C_TASK_INFO_t *pTaskInfo)
pDev = pBus->pDevList;

while (pDev != NULL) {
/* only SPD5118 support SETAASA */
if ((pDev->attr.b.present) && /* IS_SPD5118_DEVICE(pDev->pDeviceInfo) */
(pDev->staticAddr >= 0x50) && (pDev->staticAddr <= 0x57) &&
(pDev->attr.b.reqSETAASA)) {
/* SPD5118_DO_SETAASA(pDev->dynamicAddr & 0x07); */

pDev->attr.b.runI3C = TRUE;
pDev->dynamicAddr = pDev->staticAddr;

if ((pDev->attr.b.reqSETAASA) && (pDev->attr.b.doneSETAASA == 0))
pDev->attr.b.doneSETAASA = 1;
}

pDev = pDev->pNextDev;
}

/* Remove from master's task */
pBus->pCurrentTask = NULL;
pBus->busState = I3C_BUS_STATE_INIT;
/* pBus->busState = I3C_BUS_STATE_INIT; */
return I3C_ERR_OK;
}

Expand Down Expand Up @@ -978,7 +993,8 @@ void I3C_Master_Start_Request(__u32 Parm)
} else if (I3C_IS_BUS_WAIT_STOP_OR_RETRY(pBus)) {
hal_I3C_Process_Task(pTaskInfo);
} else {
hal_I3C_Master_Stall(pBus, pTaskInfo->Port);
/* run retry after isr, let slave's isr can complete its task in time */
/* hal_I3C_Master_Stall(pBus, pTaskInfo->Port); */

if (I3C_IS_BUS_DETECT_SLVSTART(pBus) && (protocol != I3C_TRANSFER_PROTOCOL_EVENT)) {
pBus->pCurrentTask = NULL;
Expand All @@ -1001,6 +1017,8 @@ void I3C_Master_Stop_Request(__u32 Parm)
I3C_TRANSFER_TASK_t *pTask;
I3C_TASK_INFO_t *pTaskInfo;
__u8 port;
I3C_DEVICE_INFO_t *pDevice;
I3C_ErrCode_Enum result;

if (Parm == 0) {
return;
Expand All @@ -1017,13 +1035,65 @@ void I3C_Master_Stop_Request(__u32 Parm)
}

port = pTaskInfo->Port;
pDevice = I3C_Get_INODE(port);
result = pTaskInfo->result;

if (pTaskInfo->result == I3C_ERR_IBI) {
if (result == I3C_ERR_IBI) {
pTask->address = hal_I3C_get_ibiAddr(port);
}

I3C_Master_Callback((uint32_t) pTaskInfo, pTaskInfo->result);
hal_I3C_Stop(port);
pDevice->bAbort = FALSE;

if (result == I3C_ERR_IBI) {
k_work_submit_to_queue(&npcm4xx_i3c_work_q[port], &work_rcv_ibi[port]);
}
}

/*---------------------------------------------------------------------------------*/
/**
* @brief Retry master task
* @param [in] Parm Pointer to task
* @return none
*/
/*---------------------------------------------------------------------------------*/
void I3C_Master_Retry_Frame(__u32 Parm)
{
I3C_TRANSFER_TASK_t *pTask;
I3C_TRANSFER_FRAME_t *pFrame;
I3C_TASK_INFO_t *pTaskInfo;

if (Parm == 0)
return;

pTask = (I3C_TRANSFER_TASK_t *)Parm;

if (pTask->frame_idx >= pTask->frame_count)
return;

if (pTask->pTaskInfo == NULL)
return;

pTaskInfo = pTask->pTaskInfo;

pFrame = &pTask->pFrameList[pTask->frame_idx];
if ((pFrame->flag & I3C_TRANSFER_RETRY_ENABLE) && (pFrame->retry_count >= 1)) {
pFrame->retry_count--;

if (pFrame->flag & I3C_TRANSFER_RETRY_WITHOUT_STOP) {
pFrame->flag |= I3C_TRANSFER_REPEAT_START;
} else {
I3C_Master_Stop_Request((__u32) pTask);

/* wait a moment for slave to prepare response data */
/* k_usleep(WAIT_SLAVE_PREPARE_RESPONSE_TIME); */
}

I3C_Master_Start_Request((__u32) pTaskInfo);
} else {
I3C_Master_Stop_Request((__u32) pTask);
}
}

/*------------------------------------------------------------------------------*/
Expand Down Expand Up @@ -1130,7 +1200,6 @@ void I3C_Master_Run_Next_Frame(__u32 Parm)
pDev = pDev->pNextDev;
}
}
#undef ASSIGN_NEW_ADDRESS

pTask->frame_idx++;
I3C_Master_Start_Request((__u32)pTaskInfo);
Expand Down
16 changes: 13 additions & 3 deletions drivers/i3c/NPCM4XX/i3c_slave.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,16 @@
#include <drivers/i3c/NPCM4XX/i3c_drv.h>
#include <drivers/i3c/NPCM4XX/api_i3c.h>

I3C_REG_ITEM_t *pSlaveReg[I3C_PORT_MAX] = { NULL, NULL };
I3C_REG_ITEM_t *pSlaveReg[I3C_PORT_MAX] = {
NULL,
NULL,
#if (I3C_PORT_MAX > 2)
NULL,
NULL,
NULL,
NULL,
#endif
};

/*------------------------------------------------------------------------------*/
/**
Expand Down Expand Up @@ -371,15 +380,16 @@ I3C_ErrCode_Enum Setup_Slave_IBI_DMA(I3C_DEVICE_INFO_t *pDevice)
return I3C_ERR_OK;
}

void I3C_Update_Dynamic_Address(__u32 Parm)
uint8_t I3C_Update_Dynamic_Address(__u32 Parm)
{
I3C_PORT_Enum port;
I3C_DEVICE_INFO_t *pDevice;

port = (I3C_PORT_Enum)Parm;
pDevice = api_I3C_Get_INODE(port);
pDevice->dynamicAddr = hal_i3c_get_dynamic_address(port);
pDevice->bRunI3C = TRUE;
pDevice->bRunI3C = (pDevice->dynamicAddr) ? TRUE : FALSE;
return pDevice->dynamicAddr;
}

void I3C_Prepare_To_Read_Command(__u32 Parm)
Expand Down
Loading

0 comments on commit 2f5fe91

Please sign in to comment.