i3c: master: Add sysfs option to rescan bus via entdaa

Allow userspace to request dynamic address assignment, which is
useful for i3cdev devices with broken hot-join support.
This will assign dynamic addresses to all devices on the I3C bus
which are currently unassigned.

Signed-off-by: David Nyström <david.nystrom@est.tech>
Reviewed-by: Frank Li <Frank.Li@nxp.com>
Reviewed-by: Meagan Lloyd <meaganlloyd@linux.microsoft.com>
Link: https://patch.msgid.link/20260219-i3c_rescan-v6-1-b81d6cc3cb30@est.tech
Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
This commit is contained in:
David Nyström
2026-02-19 21:58:03 +01:00
committed by Alexandre Belloni
parent 335c21a2bb
commit 8ea0b60bc0
2 changed files with 47 additions and 0 deletions

View File

@@ -172,3 +172,23 @@ Description:
the automatic retries. Exist only when I3C constroller supports
this retry on nack feature.
What: /sys/bus/i3c/devices/i3c-<bus-id>/do_daa
KernelVersion: 7.0
Contact: linux-i3c@vger.kernel.org
Description:
Write-only attribute that triggers a Dynamic Address Assignment
(DAA) procedure which discovers new I3C devices on the bus.
Writing a boolean true value (1, y, yes, true, on) to this
attribute causes the master controller to perform DAA, which
includes broadcasting an ENTDAA (Enter Dynamic Address Assignment)
Common Command Code (CCC) on the bus. Writing a false value
returns -EINVAL.
This is useful for discovering I3C devices that were not present
during initial bus initialization and are unable to issue
Hot-Join. Only devices without a currently assigned dynamic address
will respond to the ENTDAA broadcast and be assigned addresses.
Note that this mechanism is distinct from Hot-Join, since this is
controller-initiated discovery, while Hot-Join is device-initiated
method to provoke controller discovery procedure.

View File

@@ -758,6 +758,32 @@ static ssize_t dev_nack_retry_count_store(struct device *dev,
static DEVICE_ATTR_RW(dev_nack_retry_count);
static ssize_t do_daa_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct i3c_master_controller *master = dev_to_i3cmaster(dev);
bool val;
int ret;
if (kstrtobool(buf, &val))
return -EINVAL;
if (!val)
return -EINVAL;
if (!master->init_done)
return -EAGAIN;
ret = i3c_master_do_daa(master);
if (ret)
return ret;
return count;
}
static DEVICE_ATTR_WO(do_daa);
static struct attribute *i3c_masterdev_attrs[] = {
&dev_attr_mode.attr,
&dev_attr_current_master.attr,
@@ -769,6 +795,7 @@ static struct attribute *i3c_masterdev_attrs[] = {
&dev_attr_dynamic_address.attr,
&dev_attr_hdrcap.attr,
&dev_attr_hotjoin.attr,
&dev_attr_do_daa.attr,
NULL,
};
ATTRIBUTE_GROUPS(i3c_masterdev);