diff options
| author | Frank Li <Frank.Li@nxp.com> | 2025-11-06 12:36:00 -0500 |
|---|---|---|
| committer | Alexandre Belloni <alexandre.belloni@bootlin.com> | 2025-11-29 00:39:07 +0100 |
| commit | 256a21743d911f94ce92fe28f793cd586f3860b2 (patch) | |
| tree | 4e0bda02fa7a51ea94b0dad752b73a2efff778a0 /drivers/i3c/master.c | |
| parent | de53ad6ca49e5d73bba72d24b49ec5d40f33ee01 (diff) | |
i3c: Add HDR API support
Rename struct i3c_priv_xfer to struct i3c_xfer, since private xfer in the
I3C spec refers only to SDR transfers. Ref: i3c spec ver1.2, section 3,
Technical Overview.
i3c_xfer will be used for both SDR and HDR.
Rename enum i3c_hdr_mode to i3c_xfer_mode. Previous definition need match
CCC GET_CAP1 bit position. Use 31 as SDR transfer mode.
Add i3c_device_do_xfers() with an xfer mode argument, while keeping
i3c_device_do_priv_xfers() as a wrapper that calls i3c_device_do_xfers()
with I3C_SDR for backward compatibility.
Introduce a 'cmd' field in struct i3c_xfer as an anonymous union with
'rnw', since HDR mode uses read/write commands instead of the SDR address
bit.
Add .i3c_xfers() callback for master controllers. If not implemented, fall
back to SDR with .priv_xfers(). The .priv_xfers() API can be removed once
all controllers switch to .i3c_xfers().
Add 'mode_mask' bitmask to advertise controller capability.
Signed-off-by: Frank Li <Frank.Li@nxp.com>
Link: https://patch.msgid.link/20251106-i3c_ddr-v11-1-33a6a66ed095@nxp.com
Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
Diffstat (limited to 'drivers/i3c/master.c')
| -rw-r--r-- | drivers/i3c/master.c | 19 |
1 files changed, 14 insertions, 5 deletions
diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c index 823661a81f5e..f88f7e19203a 100644 --- a/drivers/i3c/master.c +++ b/drivers/i3c/master.c @@ -2819,10 +2819,14 @@ EXPORT_SYMBOL_GPL(i3c_generic_ibi_recycle_slot); static int i3c_master_check_ops(const struct i3c_master_controller_ops *ops) { - if (!ops || !ops->bus_init || !ops->priv_xfers || + if (!ops || !ops->bus_init || !ops->send_ccc_cmd || !ops->do_daa || !ops->i2c_xfers) return -EINVAL; + /* Must provide one of priv_xfers (SDR only) or i3c_xfers (all modes) */ + if (!ops->priv_xfers && !ops->i3c_xfers) + return -EINVAL; + if (ops->request_ibi && (!ops->enable_ibi || !ops->disable_ibi || !ops->free_ibi || !ops->recycle_ibi_slot)) @@ -3012,9 +3016,8 @@ int i3c_dev_setdasa_locked(struct i3c_dev_desc *dev) dev->boardinfo->init_dyn_addr); } -int i3c_dev_do_priv_xfers_locked(struct i3c_dev_desc *dev, - struct i3c_priv_xfer *xfers, - int nxfers) +int i3c_dev_do_xfers_locked(struct i3c_dev_desc *dev, struct i3c_xfer *xfers, + int nxfers, enum i3c_xfer_mode mode) { struct i3c_master_controller *master; @@ -3025,9 +3028,15 @@ int i3c_dev_do_priv_xfers_locked(struct i3c_dev_desc *dev, if (!master || !xfers) return -EINVAL; - if (!master->ops->priv_xfers) + if (mode != I3C_SDR && !(master->this->info.hdr_cap & BIT(mode))) return -EOPNOTSUPP; + if (master->ops->i3c_xfers) + return master->ops->i3c_xfers(dev, xfers, nxfers, mode); + + if (mode != I3C_SDR) + return -EINVAL; + return master->ops->priv_xfers(dev, xfers, nxfers); } |
