drivers: i3c: add v1.0 support flag

This adds a v1.0 support dts flag for devices. This also makes it so it
doesn't try to send a GETCAPS (GETHDRCAP) ccc if this flag is set and it
doesn't support any HDR modes.

Signed-off-by: Ryan McClelland <ryanmcclelland@meta.com>
This commit is contained in:
Ryan McClelland 2025-03-20 23:09:39 -07:00 committed by Benjamin Cabé
commit 2e8c911fa3
5 changed files with 52 additions and 31 deletions

View file

@ -777,28 +777,28 @@ int i3c_device_adv_info_get(struct i3c_device_desc *target)
/* GETMRL */
if (i3c_ccc_do_getmrl(target, &mrl) != 0) {
/* GETMRL may be optionally supported if no settable limit */
LOG_DBG("No settable limit for GETMRL");
LOG_DBG("%s: No settable limit for GETMRL", target->dev->name);
}
/* GETMWL */
if (i3c_ccc_do_getmwl(target, &mwl) != 0) {
/* GETMWL may be optionally supported if no settable limit */
LOG_DBG("No settable limit for GETMWL");
LOG_DBG("%s: No settable limit for GETMWL", target->dev->name);
}
/* GETCAPS */
ret = i3c_ccc_do_getcaps_fmt1(target, &caps);
if (((target->flags & I3C_V1P0_SUPPORT) && (target->bcr & I3C_BCR_ADV_CAPABILITIES)) ||
(!(target->flags & I3C_V1P0_SUPPORT))) {
/*
* GETCAPS (GETHDRCAP) is required to be supported for I3C v1.0 targets that support HDR
* modes and required if the Target's I3C version is v1.1 or later, but which the version it
* supports it can't be known ahead of time. So if the BCR bit for Advanced capabilities is
* set, then it is expected for GETCAPS to always be supported. Otherwise, then it's a I3C
* v1.0 device without any HDR modes so do not treat as an error if no valid response.
* GETCAPS (GETHDRCAP) is required to be supported for I3C v1.0 targets that support
* HDR modes and required if the Target's I3C version is v1.1 or later.
* It is also possible for this function to be called on an 'unknown' device such as
* from a secondary controller gathering info about a target it found about through
* DEFTGTS, and it can't be known ahead of time if it is a v1.0 or v1.1 device.
*/
if ((ret != 0) && (target->bcr & I3C_BCR_ADV_CAPABILITIES)) {
return ret;
} else {
ret = 0;
if (i3c_ccc_do_getcaps_fmt1(target, &caps) != 0) {
LOG_DBG("%s: GETCAPS not received", target->dev->name);
}
}
/* CRCAPS */
@ -873,7 +873,8 @@ static int i3c_bus_setdasa(const struct device *dev, const struct i3c_dev_list *
* address as its static address if a different dynamic address
* is not requested
*/
if ((desc->supports_setaasa) && ((desc->init_dynamic_addr == 0) ||
if ((desc->flags & I3C_SUPPORTS_SETAASA) &&
((desc->init_dynamic_addr == 0) ||
desc->init_dynamic_addr == desc->static_addr)) {
*need_aasa = true;
continue;
@ -1079,7 +1080,8 @@ int i3c_bus_init(const struct device *dev, const struct i3c_dev_list *dev_list)
* Only set for devices that support SETAASA and do not
* request a different dynamic address than its SA
*/
if ((desc->supports_setaasa) && (desc->static_addr != 0) &&
if ((desc->flags & I3C_SUPPORTS_SETAASA) &&
(desc->static_addr != 0) &&
((desc->init_dynamic_addr == 0) ||
desc->init_dynamic_addr == desc->static_addr)) {
desc->dynamic_addr = desc->static_addr;

View file

@ -629,7 +629,7 @@ static int cmd_i3c_ccc_setaasa(const struct shell *sh, size_t argc, char **argv)
/* set all devices DA to SA */
I3C_BUS_FOR_EACH_I3CDEV(dev, desc) {
if ((desc->supports_setaasa) && (desc->dynamic_addr == 0) &&
if (((desc->flags) & I3C_SUPPORTS_SETAASA) && (desc->dynamic_addr == 0) &&
(desc->static_addr != 0)) {
desc->dynamic_addr = desc->static_addr;
}

View file

@ -67,3 +67,8 @@ properties:
description: |
Indicates if the device supports the CCC SETAASA. If true, it will
be used as an optimization for bus initialization.
v1p0-support:
type: boolean
description: |
Indicates if the device compiles to I3C v1.0.

View file

@ -929,12 +929,13 @@ struct i3c_device_desc {
const uint8_t init_dynamic_addr;
/**
* Device support for SETAASA
* Device Flags
*
* This will be used as an optimization for bus initializtion if the
* BIT[0]: This shall be used as an optimization for bus initializtion if the
* device supports SETAASA.
* BIT[1]: This shall be used to indicate if the device is a I3C v1.0 device
*/
const bool supports_setaasa;
const uint8_t flags;
/**
* Dynamic Address for this target device used for communication.

View file

@ -52,6 +52,19 @@ extern "C" {
#define I3C_DEVICE_ID_DT_INST(inst) \
I3C_DEVICE_ID_DT(DT_DRV_INST(inst))
/**
* @name I3C device flags.
* @anchor I3C_DEVICE_FLAGS
* @{
*/
/** Device supports SETAASA CCC */
#define I3C_SUPPORTS_SETAASA BIT(0)
/** Device supports I3C v1.0 */
#define I3C_V1P0_SUPPORT BIT(1)
/** @} */
/**
* @brief Structure initializer for i3c_device_desc from devicetree
*
@ -67,11 +80,11 @@ extern "C" {
.bus = DEVICE_DT_GET(DT_BUS(node_id)), \
.dev = DEVICE_DT_GET(node_id), \
.static_addr = DT_PROP_BY_IDX(node_id, reg, 0), \
.pid = ((uint64_t)DT_PROP_BY_IDX(node_id, reg, 1) << 32)\
| DT_PROP_BY_IDX(node_id, reg, 2), \
.init_dynamic_addr = \
DT_PROP_OR(node_id, assigned_address, 0), \
.supports_setaasa = DT_PROP(node_id, supports_setaasa), \
.pid = ((uint64_t)DT_PROP_BY_IDX(node_id, reg, 1) << 32) | \
DT_PROP_BY_IDX(node_id, reg, 2), \
.init_dynamic_addr = DT_PROP_OR(node_id, assigned_address, 0), \
.flags = FIELD_PREP(I3C_SUPPORTS_SETAASA, DT_PROP(node_id, supports_setaasa)) | \
FIELD_PREP(I3C_V1P0_SUPPORT, DT_PROP(node_id, v1p0_support)), \
},
/**