i3c: master: Add support for devices without PID

Devices using SETAASA for address assignment are not required to have
a 48-bit PID according to the I3C specification. Allow such devices to
register and use the static address where PID was required.

Reviewed-by: Frank Li <Frank.Li@nxp.com>
Signed-off-by: Akhil R <akhilrajeev@nvidia.com>
Link: https://patch.msgid.link/20260728065955.809445-6-akhilrajeev@nvidia.com
Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
This commit is contained in:
Akhil R 2026-07-28 06:59:47 +00:00 committed by Alexandre Belloni
parent bbaf8733b8
commit a1dd42fb82

View File

@ -2071,8 +2071,17 @@ i3c_master_register_new_i3c_devs(struct i3c_master_controller *master)
desc->dev->dev.type = &i3c_device_type;
desc->dev->dev.bus = &i3c_bus_type;
desc->dev->dev.release = i3c_device_release;
dev_set_name(&desc->dev->dev, "%d-%llx", master->bus.id,
desc->info.pid);
/*
* For devices without PID (e.g., SETAASA devices), use
* static address for naming instead.
*/
if (desc->info.pid)
dev_set_name(&desc->dev->dev, "%d-%llx", master->bus.id,
desc->info.pid);
else
dev_set_name(&desc->dev->dev, "%d-%02x", master->bus.id,
desc->info.static_addr);
if (desc->boardinfo)
device_set_node(&desc->dev->dev, desc->boardinfo->fwnode);
@ -2473,8 +2482,18 @@ static void i3c_master_attach_boardinfo(struct i3c_dev_desc *i3cdev)
struct i3c_dev_boardinfo *i3cboardinfo;
list_for_each_entry(i3cboardinfo, &master->boardinfo.i3c, node) {
if (i3cdev->info.pid != i3cboardinfo->pid)
continue;
/*
* For devices without PID (e.g., SETAASA devices), match by
* static address. For devices with PID, match by PID.
*/
if (i3cboardinfo->pid) {
if (i3cdev->info.pid != i3cboardinfo->pid)
continue;
} else {
if (!i3cboardinfo->static_addr ||
i3cdev->info.static_addr != i3cboardinfo->static_addr)
continue;
}
i3cdev->boardinfo = i3cboardinfo;
i3cdev->info.static_addr = i3cboardinfo->static_addr;
@ -2488,8 +2507,12 @@ i3c_master_search_i3c_dev_duplicate(struct i3c_dev_desc *refdev)
struct i3c_master_controller *master = i3c_dev_get_master(refdev);
struct i3c_dev_desc *i3cdev;
if (!refdev->info.pid)
return NULL;
i3c_bus_for_each_i3cdev(&master->bus, i3cdev) {
if (i3cdev != refdev && i3cdev->info.pid == refdev->info.pid)
if (i3cdev != refdev && i3cdev->info.pid &&
i3cdev->info.pid == refdev->info.pid)
return i3cdev;
}
@ -2932,9 +2955,16 @@ i3c_master_add_i3c_boardinfo(struct i3c_master_controller *master,
boardinfo->pid = ((u64)reg[1] << 32) | reg[2];
if ((boardinfo->pid & GENMASK_ULL(63, 48)) ||
I3C_PID_RND_LOWER_32BITS(boardinfo->pid))
return -EINVAL;
/* For SETAASA devices, validate the static address instead of PID */
if (boardinfo->static_addr_method & I3C_ADDR_METHOD_SETAASA) {
if (!boardinfo->static_addr)
return -EINVAL;
} else {
if (!I3C_PID_MANUF_ID(boardinfo->pid) ||
(boardinfo->pid & GENMASK_ULL(63, 48)) ||
I3C_PID_RND_LOWER_32BITS(boardinfo->pid))
return -EINVAL;
}
boardinfo->init_dyn_addr = init_dyn_addr;
boardinfo->fwnode = fwnode_handle_get(fwnode);
@ -2957,10 +2987,10 @@ static int i3c_master_add_of_dev(struct i3c_master_controller *master,
return ret;
/*
* The manufacturer ID can't be 0. If reg[1] == 0 that means we're
* dealing with an I2C device.
* I3C device should have either the manufacturer ID specified or the
* address discovery method specified. Else treat it as an I2C device.
*/
if (!reg[1])
if (!reg[1] && !fwnode_property_present(fwnode, "mipi-i3c-static-method"))
ret = i3c_master_add_i2c_boardinfo(master, fwnode, reg);
else
ret = i3c_master_add_i3c_boardinfo(master, fwnode, reg);