drivers: i3c: npcx: add support for target reset request handling
This patch introduces handling for the target reset request (RSTACT) in the I3C controller. It enables the controller to send a broadcast RSTACT command along with the target reset pattern in a single frame. Signed-off-by: Alvis Sun <yfsun@nuvoton.com>
This commit is contained in:
parent
e70765391f
commit
c2f45ca588
1 changed files with 36 additions and 3 deletions
|
@ -35,6 +35,7 @@ LOG_MODULE_REGISTER(npcx_i3c, CONFIG_I3C_LOG_LEVEL);
|
||||||
#define MCTRL_REQUEST_IBIACKNACK 3 /* Manually ACK or NACK an IBI */
|
#define MCTRL_REQUEST_IBIACKNACK 3 /* Manually ACK or NACK an IBI */
|
||||||
#define MCTRL_REQUEST_PROCESSDAA 4 /* Starts the DAA process */
|
#define MCTRL_REQUEST_PROCESSDAA 4 /* Starts the DAA process */
|
||||||
#define MCTRL_REQUEST_FORCEEXIT 6 /* Emit HDR Exit Pattern */
|
#define MCTRL_REQUEST_FORCEEXIT 6 /* Emit HDR Exit Pattern */
|
||||||
|
#define MCTRL_REQUEST_TGT_RST 6 /* Emit Target Reset Pattern */
|
||||||
/* Emits a START with address 7Eh when a slave pulls I3C_SDA low to request an IBI */
|
/* Emits a START with address 7Eh when a slave pulls I3C_SDA low to request an IBI */
|
||||||
#define MCTRL_REQUEST_AUTOIBI 7
|
#define MCTRL_REQUEST_AUTOIBI 7
|
||||||
|
|
||||||
|
@ -577,6 +578,24 @@ static inline int npcx_i3c_request_hdr_exit(struct i3c_reg *inst)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int npcx_i3c_request_tgt_reset(struct i3c_reg *inst)
|
||||||
|
{
|
||||||
|
uint32_t val = 0;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
LOG_WRN("Send target reset pattern");
|
||||||
|
SET_FIELD(val, NPCX_I3C_MCTRL_TYPE, MCTRL_TYPE_TGT_RESTART);
|
||||||
|
SET_FIELD(val, NPCX_I3C_MCTRL_REQUEST, MCTRL_REQUEST_TGT_RST);
|
||||||
|
|
||||||
|
ret = npcx_i3c_send_request(inst, val);
|
||||||
|
if (ret != 0) {
|
||||||
|
LOG_ERR("Sending tgt reset pattern error %d", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static inline int npcx_i3c_xfer_stop(struct i3c_reg *inst)
|
static inline int npcx_i3c_xfer_stop(struct i3c_reg *inst)
|
||||||
{
|
{
|
||||||
uint32_t state;
|
uint32_t state;
|
||||||
|
@ -1525,9 +1544,9 @@ static int npcx_i3c_do_ccc(const struct device *dev, struct i3c_ccc_payload *pay
|
||||||
npcx_i3c_errwarn_clear_all(inst);
|
npcx_i3c_errwarn_clear_all(inst);
|
||||||
xfered_len = npcx_i3c_xfer_write_fifo(inst, &payload->ccc.id, 1, payload->ccc.data_len > 0);
|
xfered_len = npcx_i3c_xfer_write_fifo(inst, &payload->ccc.id, 1, payload->ccc.data_len > 0);
|
||||||
if (xfered_len < 0) {
|
if (xfered_len < 0) {
|
||||||
|
ret = xfered_len;
|
||||||
LOG_ERR("CCC[0x%02x] %s command error (%d)", payload->ccc.id,
|
LOG_ERR("CCC[0x%02x] %s command error (%d)", payload->ccc.id,
|
||||||
i3c_ccc_is_payload_broadcast(payload) ? "broadcast" : "direct", ret);
|
i3c_ccc_is_payload_broadcast(payload) ? "broadcast" : "direct", ret);
|
||||||
ret = xfered_len;
|
|
||||||
|
|
||||||
goto out_do_ccc;
|
goto out_do_ccc;
|
||||||
}
|
}
|
||||||
|
@ -1539,10 +1558,10 @@ static int npcx_i3c_do_ccc(const struct device *dev, struct i3c_ccc_payload *pay
|
||||||
xfered_len = npcx_i3c_xfer_write_fifo(inst, payload->ccc.data,
|
xfered_len = npcx_i3c_xfer_write_fifo(inst, payload->ccc.data,
|
||||||
payload->ccc.data_len, false);
|
payload->ccc.data_len, false);
|
||||||
if (xfered_len < 0) {
|
if (xfered_len < 0) {
|
||||||
|
ret = xfered_len;
|
||||||
LOG_ERR("CCC[0x%02x] %s command payload error (%d)", payload->ccc.id,
|
LOG_ERR("CCC[0x%02x] %s command payload error (%d)", payload->ccc.id,
|
||||||
i3c_ccc_is_payload_broadcast(payload) ? "broadcast" : "direct",
|
i3c_ccc_is_payload_broadcast(payload) ? "broadcast" : "direct",
|
||||||
ret);
|
ret);
|
||||||
ret = xfered_len;
|
|
||||||
|
|
||||||
goto out_do_ccc;
|
goto out_do_ccc;
|
||||||
}
|
}
|
||||||
|
@ -1577,9 +1596,9 @@ static int npcx_i3c_do_ccc(const struct device *dev, struct i3c_ccc_payload *pay
|
||||||
inst, tgt_payload->addr, NPCX_I3C_MCTRL_TYPE_I3C, tgt_payload->data,
|
inst, tgt_payload->addr, NPCX_I3C_MCTRL_TYPE_I3C, tgt_payload->data,
|
||||||
tgt_payload->data_len, is_read, true, false, false);
|
tgt_payload->data_len, is_read, true, false, false);
|
||||||
if (xfered_len < 0) {
|
if (xfered_len < 0) {
|
||||||
|
ret = xfered_len;
|
||||||
LOG_ERR("CCC[0x%02x] target payload error (%d)", payload->ccc.id,
|
LOG_ERR("CCC[0x%02x] target payload error (%d)", payload->ccc.id,
|
||||||
ret);
|
ret);
|
||||||
ret = xfered_len;
|
|
||||||
|
|
||||||
goto out_do_ccc;
|
goto out_do_ccc;
|
||||||
}
|
}
|
||||||
|
@ -1589,6 +1608,20 @@ static int npcx_i3c_do_ccc(const struct device *dev, struct i3c_ccc_payload *pay
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Currently handle broadcast RSTACT command only */
|
||||||
|
if (payload->ccc.id == I3C_CCC_RSTACT(true)) {
|
||||||
|
/* Handle invalid or unsupported defining bytes */
|
||||||
|
if (payload->ccc.data[0] > I3C_CCC_RSTACT_VIRTUAL_TARGET_DETECT) {
|
||||||
|
LOG_ERR("Invalid or unsupported RSTACT defining byte: %#x",
|
||||||
|
payload->ccc.data[0]);
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto out_do_ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Emit target reset pattern */
|
||||||
|
ret = npcx_i3c_request_tgt_reset(inst);
|
||||||
|
}
|
||||||
|
|
||||||
out_do_ccc:
|
out_do_ccc:
|
||||||
npcx_i3c_request_emit_stop(inst);
|
npcx_i3c_request_emit_stop(inst);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue