Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

update i3c driver #100

Merged
merged 2 commits into from
May 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
244 changes: 180 additions & 64 deletions drivers/i3c/i3c_npcm4xx.c
Original file line number Diff line number Diff line change
Expand Up @@ -873,8 +873,6 @@ int8_t LoadBaudrateSetting(I3C_TRANSFER_TYPE_Enum type, uint32_t baudrate, uint3
*/
void I3C_SetXferRate(I3C_TASK_INFO_t *pTaskInfo)
{
bool bBroadcast = FALSE;
bool bSlaveFound = FALSE;
uint32_t PPBAUD;
uint32_t PPLOW;
uint32_t ODBAUD;
Expand All @@ -884,14 +882,18 @@ void I3C_SetXferRate(I3C_TASK_INFO_t *pTaskInfo)

uint32_t mconfig;
I3C_TRANSFER_TASK_t *pTask;
I3C_TRANSFER_PROTOCOL_Enum protocol;
I3C_TRANSFER_FRAME_t *pFrame;
I3C_DEVICE_INFO_SHORT_t *pSlaveDevInfo = NULL;

if (pTaskInfo == NULL)
return;

mconfig = I3C_GET_REG_MCONFIG(pTaskInfo->Port);

PPBAUD = (mconfig & I3C_MCONFIG_PPBAUD_MASK) >> I3C_MCONFIG_PPBAUD_SHIFT;
PPLOW = (mconfig & I3C_MCONFIG_PPLOW_MASK) >> I3C_MCONFIG_PPLOW_SHIFT;
ODBAUD = (mconfig & I3C_MCONFIG_ODBAUD_MASK) >> I3C_MCONFIG_ODBAUD_SHIFT;
I2CBAUD = (mconfig & I3C_MCONFIG_I2CBAUD_MASK) >> I3C_MCONFIG_I2CBAUD_SHIFT;

mconfig &= ~(I3C_MCONFIG_I2CBAUD_MASK | I3C_MCONFIG_ODHPP_MASK | I3C_MCONFIG_ODBAUD_MASK
| I3C_MCONFIG_PPLOW_MASK | I3C_MCONFIG_PPBAUD_MASK);

Expand All @@ -901,49 +903,131 @@ void I3C_SetXferRate(I3C_TASK_INFO_t *pTaskInfo)
if (pTask->frame_idx != 0)
return;

protocol = pTask->protocol;
pFrame = &(pTask->pFrameList[pTask->frame_idx]);

bBroadcast = (pTask->address == I3C_BROADCAST_ADDR)
|| (protocol == I3C_TRANSFER_PROTOCOL_CCCb)
|| (protocol == I3C_TRANSFER_PROTOCOL_CCCw)
|| (protocol == I3C_TRANSFER_PROTOCOL_CCCr)
|| (protocol == I3C_TRANSFER_PROTOCOL_ENTDAA)
|| (protocol == I3C_TRANSFER_PROTOCOL_EVENT);

if (bBroadcast && (pFrame->type != I3C_TRANSFER_TYPE_I2C)
&& ((pFrame->flag & I3C_TRANSFER_REPEAT_START) == 0)) {
// update by frame setting
if ((pTask->frame_idx == 0) && ((pFrame->flag & I3C_TRANSFER_REPEAT_START) == 0) &&
(pFrame->type != I3C_TRANSFER_TYPE_I2C) && (pFrame->address == 0x7E)) {
ODHPP = 0;
}

if (!bBroadcast) {
pSlaveDevInfo = pMasterDevice->pOwner->pDevList;
while (pSlaveDevInfo != NULL) {
if (pSlaveDevInfo->attr.b.runI3C) {
if (pSlaveDevInfo->dynamicAddr == pTask->address)
break;
} else {
if (pSlaveDevInfo->staticAddr == pTask->address)
break;
}

pSlaveDevInfo = pSlaveDevInfo->pNextDev;
if (pFrame->type == I3C_TRANSFER_TYPE_I2C) {
switch(pFrame->baudrate) {
case I3C_TRANSFER_SPEED_I2C_1MHZ:
if (APB3_CLK == 96000000) { // 926 - 922 KHz
PPBAUD = 3;
PPLOW = 0;
ODBAUD = 12;
I2CBAUD = 0;
} else if (APB3_CLK == 48000000) { // 878 - 880 KHz
PPBAUD = 2;
PPLOW = 0;
ODBAUD = 8;
I2CBAUD = 0;
}
break;
case I3C_TRANSFER_SPEED_I2C_400KHZ:
if (APB3_CLK == 96000000) { // 371 - 369 KHz
PPBAUD = 9;
PPLOW = 0;
ODBAUD = 12;
I2CBAUD = 0;
} else if (APB3_CLK == 48000000) { // 340 - 338 KHz
PPBAUD = 9;
PPLOW = 0;
ODBAUD = 6;
I2CBAUD = 0;
}
break;
default:
if (APB3_CLK == 96000000) { // 98 - 96 KHz
PPBAUD = 15;
PPLOW = 0;
ODBAUD = 30;
I2CBAUD = 0;
} else if (APB3_CLK == 48000000) { // 98 - 97 KHz
PPBAUD = 2;
PPLOW = 0;
ODBAUD = 80;
I2CBAUD = 0;
}
break;
}

bSlaveFound = (pSlaveDevInfo != NULL);
}

if (bBroadcast) {
/* Can't make sure all slave device run in i3c mode ?*/
/* PP=4MHz, OD Freq = 1MHz for I3C device before get dynamic address */
PPBAUD = 5;
PPLOW = 0;
ODBAUD = 3;
I2CBAUD = 8;
} else if (bSlaveFound) {
if ((pSlaveDevInfo->attr.b.runI3C) == (pFrame->type != I3C_TRANSFER_TYPE_I2C)) {
LoadBaudrateSetting(pFrame->type, pFrame->baudrate, &PPBAUD, &PPLOW,
&ODBAUD, &I2CBAUD);
else
{
switch(pFrame->baudrate) {
case I3C_TRANSFER_SPEED_SDR_12p5MHZ:
// I3C PP=12.5MHz, OD Freq = 1MHz if ODHPP = 0
if (APB3_CLK == 96000000) {
PPBAUD = 2;
PPLOW = 2;
ODBAUD = 15;
} else if (APB3_CLK == 48000000) {
PPBAUD = 0;
PPLOW = 2;
ODBAUD = 23;
}
break;
case I3C_TRANSFER_SPEED_SDR_8MHZ:
// I3C PP=8MHz, OD Freq = 1MHz if ODHPP = 0
if (APB3_CLK == 96000000) {
PPBAUD = 2;
PPLOW = 6;
ODBAUD = 15;
} else if (APB3_CLK == 48000000) {
PPBAUD = 0;
PPLOW = 4;
ODBAUD = 23;
}
break;
case I3C_TRANSFER_SPEED_SDR_6MHZ:
// I3C PP=6MHz, OD Freq = 1MHz if ODHPP = 0
if (APB3_CLK == 96000000) {
PPBAUD = 2;
PPLOW = 10;
ODBAUD = 15;
} else if (APB3_CLK == 48000000) {
PPBAUD = 1;
PPLOW = 4;
ODBAUD = 11;
}
break;
case I3C_TRANSFER_SPEED_SDR_4MHZ:
// I3C PP=4MHz, OD Freq = 1MHz if ODHPP = 0
if (APB3_CLK == 96000000) {
PPBAUD = 5;
PPLOW = 12;
ODBAUD = 7;
} else if (APB3_CLK == 48000000) {
PPBAUD = 0;
PPLOW = 10;
ODBAUD = 23;
}
break;
case I3C_TRANSFER_SPEED_SDR_2MHZ:
// I3C PP=2MHz, OD Freq = 1MHz if ODHPP = 0
if (APB3_CLK == 96000000) {
PPBAUD = 15;
PPLOW = 15;
ODBAUD = 2;
} else if (APB3_CLK == 48000000) {
PPBAUD = 4;
PPLOW = 14;
ODBAUD = 4;
}
break;
default:
if (APB3_CLK == 96000000) {
PPBAUD = 15;
PPLOW = 15;
ODBAUD = 5;
} else if (APB3_CLK == 48000000) {
PPBAUD = 15;
PPLOW = 15;
ODBAUD = 1;
}
break;
}
}

Expand Down Expand Up @@ -2381,6 +2465,23 @@ int i3c_npcm4xx_slave_register(const struct device *dev, struct i3c_slave_setup
return 0;
}

int i3c_npcm4xx_slave_set_static_addr(const struct device *dev, uint8_t static_addr)
{
struct i3c_npcm4xx_config *config = DEV_CFG(dev);
I3C_PORT_Enum port = config->inst_id;
I3C_DEVICE_INFO_t *pDevice;
uint32_t sconfig;

pDevice = &gI3c_dev_node_internal[port];
pDevice->staticAddr = static_addr;

sconfig = I3C_GET_REG_CONFIG(port);
SET_FIELD(sconfig, NPCM4XX_I3C_CONFIG_SADDR, static_addr);
I3C_SET_REG_CONFIG(port, sconfig);

return 0;
}

/*
* slave send mdb
*/
Expand Down Expand Up @@ -2537,6 +2638,28 @@ int i3c_npcm4xx_slave_get_event_enabling(const struct device *dev, uint32_t *eve
return 0;
}

int i3c_npcm4xx_set_pid_extra_info(const struct device *dev, uint16_t extra_info)
{
struct i3c_npcm4xx_config *config = DEV_CFG(dev);
I3C_PORT_Enum port = config->inst_id;
I3C_DEVICE_INFO_t *pDevice;
uint32_t partno;

partno = I3C_GET_REG_PARTNO(port);

SET_FIELD(partno, NPCM4XX_I3C_PARTNO_VENDOR_DEF, extra_info);
I3C_SET_REG_PARTNO(port, partno);

pDevice = &gI3c_dev_node_internal[port];
pDevice->partNumber = partno;

pDevice->pid[4] = ((port & 0x0F) << 4) |
((uint8_t)(extra_info >> 8) & 0x0F);
pDevice->pid[5] = (uint8_t)extra_info;

return 0;
}

static void i3c_npcm4xx_master_rx_ibi(struct i3c_npcm4xx_obj *obj)
{
struct i3c_dev_desc *i3cdev;
Expand Down Expand Up @@ -2901,7 +3024,7 @@ int i3c_npcm4xx_master_priv_xfer(struct i3c_dev_desc *i3cdev, struct i3c_priv_xf

I3C_BUS_INFO_t *pBus;
I3C_DEVICE_INFO_t *pMaster;
I3C_DEVICE_INFO_SHORT_t *pSlaveDev;
struct i3c_dev_desc *pSlaveDev;

if (!nxfers) {
return 0;
Expand All @@ -2923,20 +3046,10 @@ int i3c_npcm4xx_master_priv_xfer(struct i3c_dev_desc *i3cdev, struct i3c_priv_xf
}

Addr = obj->dev_addr_tbl[pos];
pSlaveDev = obj->dev_descs[pos];

/* find device node */
pSlaveDev = pBus->pDevList;
while (pSlaveDev != NULL) {
if ((pSlaveDev->dynamicAddr == Addr) && (pSlaveDev->attr.b.runI3C == TRUE))
break;
if ((pSlaveDev->staticAddr == Addr) && (pSlaveDev->attr.b.runI3C == FALSE))
break;
pSlaveDev = pSlaveDev->pNextDev;
}

if (pSlaveDev == NULL) {
if (pSlaveDev == NULL)
return DEVICE_COUNT_MAX;
}

cmds = (struct i3c_npcm4xx_cmd *)k_calloc(sizeof(struct i3c_npcm4xx_cmd), nxfers);
__ASSERT(cmds, "failed to allocat cmd\n");
Expand Down Expand Up @@ -2976,31 +3089,31 @@ int i3c_npcm4xx_master_priv_xfer(struct i3c_dev_desc *i3cdev, struct i3c_priv_xf
for (i = 0; i < nxfers; i++) {
bWnR = (((i + 1) < nxfers) && (xfers[i].rnw == 0) && (xfers[i + 1].rnw == 1));

Baudrate = (pSlaveDev->attr.b.runI3C) ? I3C_TRANSFER_SPEED_SDR_12p5MHZ :
I3C_TRANSFER_SPEED_I2C_100KHZ;
Baudrate = (pSlaveDev->info.i2c_mode) ? I3C_TRANSFER_SPEED_I2C_100KHZ :
I3C_TRANSFER_SPEED_SDR_12p5MHZ;

/* 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) ?
I3C_TRANSFER_PROTOCOL_I3C_READ :
I3C_TRANSFER_PROTOCOL_I2C_READ;
Protocol = (pSlaveDev->info.i2c_mode) ?
I3C_TRANSFER_PROTOCOL_I2C_READ :
I3C_TRANSFER_PROTOCOL_I3C_READ;
RxBuf = xfers[i].data.in;
RxLen = xfers[i].len;
} else {
Protocol = (pSlaveDev->attr.b.runI3C) ?
I3C_TRANSFER_PROTOCOL_I3C_WRITE :
I3C_TRANSFER_PROTOCOL_I2C_WRITE;
Protocol = (pSlaveDev->info.i2c_mode) ?
I3C_TRANSFER_PROTOCOL_I2C_WRITE :
I3C_TRANSFER_PROTOCOL_I3C_WRITE;
TxBuf = xfers[i].data.out;
TxLen = xfers[i].len;
}
} else {
Protocol = (pSlaveDev->attr.b.runI3C) ?
I3C_TRANSFER_PROTOCOL_I3C_WRITEnREAD :
I3C_TRANSFER_PROTOCOL_I2C_WRITEnREAD;
Protocol = (pSlaveDev->info.i2c_mode) ?
I3C_TRANSFER_PROTOCOL_I2C_WRITEnREAD :
I3C_TRANSFER_PROTOCOL_I3C_WRITEnREAD;
TxBuf = xfers[i].data.out;
TxLen = xfers[i].len;
RxBuf = xfers[i + 1].data.in;
Expand All @@ -3023,6 +3136,9 @@ int i3c_npcm4xx_master_priv_xfer(struct i3c_dev_desc *i3cdev, struct i3c_priv_xf
if (bWnR) {
i++;
}

if (xfers[i].rnw == 1)
xfers[i].len = xfer.rx_len;
}
}

Expand Down
1 change: 1 addition & 0 deletions drivers/i3c/npcm4xx/i3c_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ struct i3c_npcm4xx_cmd {
};
struct i3c_npcm4xx_xfer {
int ret;
int rx_len;
int ncmds;
struct i3c_npcm4xx_cmd *cmds;
struct k_sem sem;
Expand Down
1 change: 1 addition & 0 deletions drivers/i3c/npcm4xx/i3c_master.c
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,7 @@ __u32 I3C_Master_Callback(__u32 TaskInfo, __u32 ErrDetail)
}

ret = pTaskInfo->result;
xfer->rx_len = *pTask->pRdLen;
I3C_Complete_Task(pTaskInfo);
pBus->pCurrentTask = NULL;
pBus->busState = I3C_BUS_STATE_IDLE;
Expand Down
18 changes: 18 additions & 0 deletions include/drivers/i3c/i3c.h
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,14 @@ int i3c_npcm4xx_slave_get_event_enabling(const struct device *dev, uint32_t *eve
*/
int i3c_npcm4xx_slave_send_sir(const struct device *dev, struct i3c_ibi_payload *payload);

/**
* @brief set the static address of the i3c controller in slave mode
* @param dev the I3C controller in slave mode
* @param static_addr the new static address
* @return 0 if the static address is set
*/
int i3c_npcm4xx_slave_set_static_addr(const struct device *dev, uint8_t static_addr);

/**
* @brief slave device prepares the data for master private read transfer
*
Expand All @@ -212,6 +220,14 @@ int i3c_npcm4xx_slave_send_sir(const struct device *dev, struct i3c_ibi_payload
int i3c_npcm4xx_slave_put_read_data(const struct device *dev, struct i3c_slave_payload *data,
struct i3c_ibi_payload *ibi_notify);

/**
* @brief set the pid extra info of the i3c controller
* @param dev the I3C controller
* @param extra_info the extra info of the pid bits[11:0]
* @return int 0 = success
*/
int i3c_npcm4xx_set_pid_extra_info(const struct device *dev, uint16_t extra_info);

/* common API */
int i3c_master_send_enec(const struct device *master, uint8_t addr, uint8_t evt);
int i3c_master_send_disec(const struct device *master, uint8_t addr, uint8_t evt);
Expand All @@ -231,10 +247,12 @@ int i3c_master_send_getbcr(const struct device *master, uint8_t addr, uint8_t *b
#define i3c_master_enable_ibi i3c_npcm4xx_master_enable_ibi
#define i3c_master_send_entdaa i3c_npcm4xx_master_send_entdaa
#define i3c_slave_register i3c_npcm4xx_slave_register
#define i3c_slave_set_static_addr i3c_npcm4xx_slave_set_static_addr
#define i3c_slave_send_sir i3c_npcm4xx_slave_send_sir
#define i3c_slave_put_read_data i3c_npcm4xx_slave_put_read_data
#define i3c_slave_get_dynamic_addr i3c_npcm4xx_slave_get_dynamic_addr
#define i3c_slave_get_event_enabling i3c_npcm4xx_slave_get_event_enabling
#define i3c_set_pid_extra_info i3c_npcm4xx_set_pid_extra_info

int i3c_jesd403_read(struct i3c_dev_desc *slave, uint8_t *addr, int addr_size, uint8_t *data,
int data_size);
Expand Down
Loading
Loading