From cae22bd965bbee732993f3df1337c9b4167f943d Mon Sep 17 00:00:00 2001 From: Adrian Ng Ho Yin Date: Wed, 8 Jul 2026 00:17:37 -0700 Subject: i3c: ccc: Add actual_len to struct i3c_ccc_cmd_payload Add actual_len to struct i3c_ccc_cmd_payload so drivers can report how many bytes were received on a GET CCC without overwriting the requested buffer length in len. Signed-off-by: Adrian Ng Ho Yin Signed-off-by: Tze Yee Ng Reviewed-by: Alexandre Mergnat Reviewed-by: Frank Li Tested-by: Tommaso Merciai Tested-by: Claudiu Beznea # on RZ/G3S Link: https://patch.msgid.link/e452777c3a9be734a97e20b9822d8a4264ceadba.1783493868.git.tze.yee.ng@altera.com Signed-off-by: Alexandre Belloni --- include/linux/i3c/ccc.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/i3c/ccc.h b/include/linux/i3c/ccc.h index ad59a4ae60d1..d8052949e57e 100644 --- a/include/linux/i3c/ccc.h +++ b/include/linux/i3c/ccc.h @@ -343,11 +343,13 @@ struct i3c_ccc_getxtime { /** * struct i3c_ccc_cmd_payload - CCC payload * - * @len: payload length + * @len: requested payload length + * @actual_len: number of bytes received on a GET CCC (filled by the driver) * @data: payload data. This buffer must be DMA-able */ struct i3c_ccc_cmd_payload { u16 len; + u16 actual_len; void *data; }; -- cgit v1.2.3 From 09361ed979e68622977751f6274f280d7aec5cb6 Mon Sep 17 00:00:00 2001 From: Adrian Ng Ho Yin Date: Wed, 8 Jul 2026 00:17:40 -0700 Subject: i3c: master: Validate GET CCC payload length and retry Direct GET once Add retries to struct i3c_ccc_cmd. Validate GET payload length in i3c_master_send_ccc_cmd_locked() after a successful transfer. Retry failed Direct GET CCCs up to cmd->retries times when the driver reports failure or an I3C error; validation failures are not retried. SET CCCs are not retried by default. Signed-off-by: Adrian Ng Ho Yin Signed-off-by: Tze Yee Ng Reviewed-by: Alexandre Mergnat Reviewed-by: Frank Li Tested-by: Tommaso Merciai Tested-by: Claudiu Beznea # on RZ/G3S Link: https://patch.msgid.link/b467f01edfaaa0710f30e719ce7f2753b06c1a3f.1783493868.git.tze.yee.ng@altera.com Signed-off-by: Alexandre Belloni --- include/linux/i3c/ccc.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'include/linux') diff --git a/include/linux/i3c/ccc.h b/include/linux/i3c/ccc.h index d8052949e57e..2506d83b8255 100644 --- a/include/linux/i3c/ccc.h +++ b/include/linux/i3c/ccc.h @@ -12,6 +12,8 @@ #include /* I3C CCC (Common Command Codes) related definitions */ +#define I3C_CCC_RETRIES 1 + #define I3C_CCC_DIRECT BIT(7) #define I3C_CCC_ID(id, broadcast) \ @@ -374,12 +376,15 @@ struct i3c_ccc_cmd_dest { * @ndests: number of destinations. Should always be one for broadcast commands * @dests: array of destinations and associated payload for this CCC. Most of * the time, only one destination is provided + * @retries: number of times to retry a failed Direct GET CCC (see + * &I3C_CCC_RETRIES) * @err: I3C error code */ struct i3c_ccc_cmd { u8 rnw; u8 id; unsigned int ndests; + unsigned int retries; struct i3c_ccc_cmd_dest *dests; enum i3c_error_code err; }; -- cgit v1.2.3 From b32f4ed0cc069206cb7b6baa0654b14410a91440 Mon Sep 17 00:00:00 2001 From: Adrian Ng Ho Yin Date: Wed, 8 Jul 2026 00:17:41 -0700 Subject: i3c: master: Add optional_bytes for variable-length GET CCC validation Add optional_bytes to struct i3c_ccc_cmd_payload so callers describe variable-length GET CCC responses. GETMRL and GETMXDS set optional_bytes at the call site. Extend i3c_ccc_validate_payload_len() to honour it. Signed-off-by: Adrian Ng Ho Yin Signed-off-by: Tze Yee Ng Reviewed-by: Alexandre Mergnat Reviewed-by: Frank Li Tested-by: Tommaso Merciai Tested-by: Claudiu Beznea # on RZ/G3S Link: https://patch.msgid.link/2e07dc944eab1c4358be1da87fa5000e711ac8bd.1783493868.git.tze.yee.ng@altera.com Signed-off-by: Alexandre Belloni --- include/linux/i3c/ccc.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include/linux') diff --git a/include/linux/i3c/ccc.h b/include/linux/i3c/ccc.h index 2506d83b8255..7ad677baf761 100644 --- a/include/linux/i3c/ccc.h +++ b/include/linux/i3c/ccc.h @@ -347,11 +347,13 @@ struct i3c_ccc_getxtime { * * @len: requested payload length * @actual_len: number of bytes received on a GET CCC (filled by the driver) + * @optional_bytes: GET CCCs may return up to this many fewer bytes than @len * @data: payload data. This buffer must be DMA-able */ struct i3c_ccc_cmd_payload { u16 len; u16 actual_len; + u16 optional_bytes; void *data; }; -- cgit v1.2.3 From ee170021bee17124c13f42813607bca553a6b48a Mon Sep 17 00:00:00 2001 From: Akhil R Date: Tue, 28 Jul 2026 06:59:44 +0000 Subject: i3c: master: Use unified device property interface Replace all OF-specific functions with unified device property functions as a prerequisite to support both ACPI and device tree. Reviewed-by: Frank Li Signed-off-by: Akhil R Link: https://patch.msgid.link/20260728065955.809445-3-akhilrajeev@nvidia.com Signed-off-by: Alexandre Belloni --- include/linux/i3c/master.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'include/linux') diff --git a/include/linux/i3c/master.h b/include/linux/i3c/master.h index 4d2a68793324..a16deb04b2e1 100644 --- a/include/linux/i3c/master.h +++ b/include/linux/i3c/master.h @@ -177,7 +177,8 @@ struct i3c_device_ibi_info { * @pid: I3C Provisioned ID exposed by the device. This is a unique identifier * that may be used to attach boardinfo to i3c_dev_desc when the device * does not have a static address - * @of_node: optional DT node in case the device has been described in the DT + * @fwnode: Firmware node (DT or ACPI) in case the device has been + * described in firmware * * This structure is used to attach board-level information to an I3C device. * Not all I3C devices connected on the bus will have a boardinfo. It's only @@ -189,7 +190,7 @@ struct i3c_dev_boardinfo { u8 init_dyn_addr; u8 static_addr; u64 pid; - struct device_node *of_node; + struct fwnode_handle *fwnode; }; /** -- cgit v1.2.3 From bbaf8733b84846897d2d3b997ce650dd2d2539a4 Mon Sep 17 00:00:00 2001 From: Akhil R Date: Tue, 28 Jul 2026 06:59:46 +0000 Subject: i3c: master: Add support for devices using SETAASA Add support for devices using SETAASA, such as SPD5118 and SPD5108 attached to DDR5 memory modules that do not support ENTDAA. Follow the guidelines proposed by the MIPI Discovery and Configuration Specification [1] for discovering such devices. SETAASA (Set All Addresses to Static Address) differs from standard I3C address assignment that uses ENTDAA or SETDASA to assign dynamic addresses. Devices using SETAASA assign their pre-defined static addresses as their dynamic addresses during DAA, and it is not mandatory for these devices to implement standard CCC commands like GETPID, GETDCR, or GETBCR. For such devices, it is generally recommended to issue SETHID (specified by JEDEC JESD300) as a prerequisite for SETAASA to stop HID bit flipping. [1] https://www.mipi.org/mipi-disco-for-i3c-download Signed-off-by: Akhil R Link: https://www.mipi.org/mipi-disco-for-i3c-download Link: https://patch.msgid.link/20260728065955.809445-5-akhilrajeev@nvidia.com Signed-off-by: Alexandre Belloni --- include/linux/i3c/ccc.h | 1 + include/linux/i3c/master.h | 15 +++++++++++++++ 2 files changed, 16 insertions(+) (limited to 'include/linux') diff --git a/include/linux/i3c/ccc.h b/include/linux/i3c/ccc.h index 7ad677baf761..c6947dcb0f57 100644 --- a/include/linux/i3c/ccc.h +++ b/include/linux/i3c/ccc.h @@ -34,6 +34,7 @@ #define I3C_CCC_DEFSLVS I3C_CCC_ID(0x8, true) #define I3C_CCC_ENTTM I3C_CCC_ID(0xb, true) #define I3C_CCC_ENTHDR(x) I3C_CCC_ID(0x20 + (x), true) +#define I3C_CCC_SETAASA I3C_CCC_ID(0x29, true) /* Unicast-only commands */ #define I3C_CCC_SETDASA I3C_CCC_ID(0x7, false) diff --git a/include/linux/i3c/master.h b/include/linux/i3c/master.h index a16deb04b2e1..2dc139a217bf 100644 --- a/include/linux/i3c/master.h +++ b/include/linux/i3c/master.h @@ -174,6 +174,14 @@ struct i3c_device_ibi_info { * assigned a dynamic address by the master. Will be used during * bus initialization to assign it a specific dynamic address * before starting DAA (Dynamic Address Assignment) + * @static_addr_method: Bitmap describing which methods of Dynamic Address + * Assignment from a Static Address are supported by this I3C Target. + * A value of 1 in a bit position indicates that the I3C target + * supports that method, and a value of 0 indicates that the I3C + * target does not support that method. + * Bit 0: SETDASA + * Bit 1: SETAASA + * All other bits are reserved. * @pid: I3C Provisioned ID exposed by the device. This is a unique identifier * that may be used to attach boardinfo to i3c_dev_desc when the device * does not have a static address @@ -189,6 +197,7 @@ struct i3c_dev_boardinfo { struct list_head node; u8 init_dyn_addr; u8 static_addr; + u8 static_addr_method; u64 pid; struct fwnode_handle *fwnode; }; @@ -517,6 +526,11 @@ struct i3c_master_controller_ops { * @boardinfo.i2c: list of I2C boardinfo objects * @boardinfo: board-level information attached to devices connected on the bus * @bus: I3C bus exposed by this master + * @addr_method: Bitmap describing which methods of Address Assignment required + * to be run for discovering all the devices on the bus. + * Bit 0: SETDASA + * Bit 1: SETAASA + * All other bits are reserved. * @wq: freezable workqueue which can be used by master * drivers if they need to postpone operations that need to take place * in a thread context. Typical examples are Hot Join processing which @@ -552,6 +566,7 @@ struct i3c_master_controller { struct list_head i2c; } boardinfo; struct i3c_bus bus; + u8 addr_method; struct workqueue_struct *wq; struct work_struct hj_work; struct work_struct reg_work; -- cgit v1.2.3 From 456f832e5fc26fbfd3b8200fd4553eee520cc377 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Fri, 7 Aug 2026 17:56:25 +0300 Subject: i3c: master: Fix recursive locking during device registration i3c_master_register_new_i3c_devs() registers newly discovered devices while holding i3c_bus_normaluse_lock(), a down_read(). device_register() can immediately probe the device, and probe callbacks typically invoke I3C helpers that take i3c_bus_normaluse_lock() again, leading to a recursive acquisition of the same rwsem. rwsems do not support recursive read locking and can deadlock when a writer is waiting. See the "Recursive read locks" section of Documentation/locking/lockdep-design.rst. For example, with Intel LPSS I3C, LOCKDEP generates a WARNING like: # echo intel-lpss-i3c.0 > /sys/bus/platform/drivers/mipi-i3c-hci/unbind # echo intel-lpss-i3c.0 > /sys/bus/platform/drivers/mipi-i3c-hci/bind WARNING: possible recursive locking detected kworker/5:1/94 is trying to acquire lock: ffff88811c810d78 (&i3cbus->lock){++++}-{4:4}, at: i3c_device_match_id+0x45/0x370 but task is already holding lock: ffff88811c810d78 (&i3cbus->lock){++++}-{4:4}, at: i3c_master_reg_work_fn+0x21/0x5f0 Fix this by separating device creation from device registration. Populate desc->dev under the maintenance lock, collect the devices that still need registration into a local list, then release the lock before calling device_register(). Finally retake the lock and clean up any devices that failed to register. Use the maintenance lock rather than the normal-use lock while adding device objects. A write-side maintenance lock prevents readers from observing a partially initialized desc->dev during initial device population, or desc->dev disappearing if registration fails. The local list requires a list node, so add a list node member to struct i3c_device. Fixes: 3a379bbcea0a ("i3c: Add core I3C infrastructure") Cc: stable@vger.kernel.org Signed-off-by: Adrian Hunter Reviewed-by: Frank Li Link: https://patch.msgid.link/20260807145638.168865-2-adrian.hunter@intel.com Signed-off-by: Alexandre Belloni --- include/linux/i3c/master.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'include/linux') diff --git a/include/linux/i3c/master.h b/include/linux/i3c/master.h index 2dc139a217bf..26535beb1e77 100644 --- a/include/linux/i3c/master.h +++ b/include/linux/i3c/master.h @@ -238,6 +238,8 @@ struct i3c_dev_desc { * every time the I3C device is rediscovered with a different dynamic * address assigned * @bus: I3C bus this device is attached to + * @node: unregistered device list node, only for use by + * i3c_master_register_new_i3c_devs(), it is not protected by a lock * * I3C device object exposed to I3C device drivers. The takes care of linking * this object to the relevant &struct_i3c_dev_desc one. @@ -248,6 +250,7 @@ struct i3c_device { struct device dev; struct i3c_dev_desc *desc; struct i3c_bus *bus; + struct list_head node; }; /* -- cgit v1.2.3 From 9fd18a865591d981c0081a3e663a65dbe4a64eb9 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Fri, 7 Aug 2026 17:56:32 +0300 Subject: i3c: master: Support IBI-based wakeup capability An I3C controller acts as a bus controller for one or more I3C devices. If the controller can wake the system in response to an In-Band Interrupt (IBI), then any device on that bus that is capable of generating IBIs can potentially be used as a wakeup source. Add an ibi_wakeup flag to struct i3c_master_controller so controller drivers can advertise support for IBI-based wakeup. If set, mark IBI-capable I3C devices as wakeup capable when they are registered, allowing wakeup management through the standard device wakeup framework. Signed-off-by: Adrian Hunter Reviewed-by: Frank Li Acked-by: Mukesh Savaliya Link: https://patch.msgid.link/20260807145638.168865-9-adrian.hunter@intel.com Signed-off-by: Alexandre Belloni --- include/linux/i3c/master.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include/linux') diff --git a/include/linux/i3c/master.h b/include/linux/i3c/master.h index 26535beb1e77..9d675d01522c 100644 --- a/include/linux/i3c/master.h +++ b/include/linux/i3c/master.h @@ -524,6 +524,7 @@ struct i3c_master_controller_ops { * @hotjoin: true if the master support hotjoin * @rpm_allowed: true if Runtime PM allowed * @rpm_ibi_allowed: true if IBI and Hot-Join allowed while runtime suspended + * @ibi_wakeup: IBI can wakeup the system * @shutting_down: set to true when master begins shutdown or unregister * @boardinfo.i3c: list of I3C boardinfo objects * @boardinfo.i2c: list of I2C boardinfo objects @@ -563,6 +564,7 @@ struct i3c_master_controller { unsigned int hotjoin: 1; unsigned int rpm_allowed: 1; unsigned int rpm_ibi_allowed: 1; + unsigned int ibi_wakeup: 1; bool shutting_down; struct { struct list_head i3c; -- cgit v1.2.3 From 60ff731f06909f9b54af27d70f00a41bd84c6246 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Fri, 7 Aug 2026 17:56:34 +0300 Subject: i3c: master: Add helper to query bus wakeup requirements Add i3c_master_has_wakeup_enabled_devs(), which iterates over the devices on an I3C bus and reports whether any of them are enabled for system wakeup and have IBI enabled. Controller drivers can use this helper to determine whether wakeup support must remain available while the system is suspended. Acked-by : Mukesh Savaliya Signed-off-by: Adrian Hunter Reviewed-by: Frank Li Link: https://patch.msgid.link/20260807145638.168865-11-adrian.hunter@intel.com Signed-off-by: Alexandre Belloni --- include/linux/i3c/master.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include/linux') diff --git a/include/linux/i3c/master.h b/include/linux/i3c/master.h index 9d675d01522c..82d9886e7f12 100644 --- a/include/linux/i3c/master.h +++ b/include/linux/i3c/master.h @@ -765,6 +765,7 @@ void i3c_generic_ibi_recycle_slot(struct i3c_generic_ibi_pool *pool, struct i3c_ibi_slot *slot); void i3c_master_queue_ibi(struct i3c_dev_desc *dev, struct i3c_ibi_slot *slot); +bool i3c_master_has_wakeup_enabled_devs(struct i3c_master_controller *master); struct i3c_ibi_slot *i3c_master_get_free_ibi_slot(struct i3c_dev_desc *dev); -- cgit v1.2.3 From 7315aad228c29508ec77ab64a7c75377981e8c4f Mon Sep 17 00:00:00 2001 From: Tze Yee Ng Date: Fri, 31 Jul 2026 01:01:39 -0700 Subject: i3c: master: dw-i3c-master: fix OD timing for first broadcast Implement ->set_speed() so the I3C core can switch open-drain timing for the first broadcast address per spec: I3C_OPEN_DRAIN_SLOW_SPEED programs tHIGH_INIT (200 ns) before RSTDAA, and I3C_OPEN_DRAIN_NORMAL_SPEED restores normal OD timing afterward. Cache the normal OD register value during bus init and use a separate od_hcnt for the slow path so SDR extended timing remains derived from the normal PP hcnt. For AMD_I3C_OD_PP_TIMING, cache AMD_I3C_OD_TIMING as the normal OD baseline and stop rewriting OD timing in send_ccc_cmd()/runtime resume so I3C_OPEN_DRAIN_SLOW_SPEED is preserved through RSTDAA. Use PM_RUNTIME_ACQUIRE_AUTOSUSPEND() in set_speed(). Compute od_hcnt with DIV_ROUND_UP_ULL() for 32-bit safety and clamp it to U8_MAX to match the 8-bit I3C_OD_HCNT field. Fixes I2C devices with spike filters not being detected on mixed buses. Signed-off-by: Tze Yee Ng Reviewed-by: Frank Li Link: https://patch.msgid.link/d789219ca0418898a1ef2bf9295b4f96ca7b4209.1785484707.git.tze.yee.ng@altera.com Signed-off-by: Alexandre Belloni --- include/linux/i3c/master.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include/linux') diff --git a/include/linux/i3c/master.h b/include/linux/i3c/master.h index 82d9886e7f12..f7ceec2b4477 100644 --- a/include/linux/i3c/master.h +++ b/include/linux/i3c/master.h @@ -272,6 +272,7 @@ struct i3c_device { #define I3C_BUS_THIGH_MIXED_MAX_NS 41 #define I3C_BUS_TIDLE_MIN_NS 200000 #define I3C_BUS_TLOW_OD_MIN_NS 200 +#define I3C_BUS_THIGH_INIT_OD_MIN_NS 200 /** * enum i3c_bus_mode - I3C bus mode -- cgit v1.2.3