Skip to content

drivers/i2c: ite: Add handling for read operation with 0-byte length #90202

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged

Conversation

GTLin08
Copy link
Collaborator

@GTLin08 GTLin08 commented May 20, 2025

The current I2C driver assumes that at least one byte will be read in CQ (command queue) mode. However, when a 0-byte read is issued(e.g., i2c read <bus> <addr> <reg> 0), the driver fails to handle it correctly.
The read handler uses (len - 1) to set the command queue length. When len is 0, this underflows to 0xFF, leading to an incorrect transfer length and possible crash.

To fix this, add a check in cq_mode_allowed() for reads with length 0:
-Fallback to PIO mode in such cases.
-Properly handle 0-byte reads by issuing STOP (E_FINISH) when the slave address is acknowledged.
-Add appropriate handling for NACK conditions when the slave address is not acknowledged.

andyross
andyross previously approved these changes May 21, 2025
@@ -408,6 +411,7 @@ static int enhanced_i2c_error(const struct device *dev)
} else if ((i2c_str & E_HOSTA_BDS_AND_ACK) == E_HOSTA_BDS) {
if (IT8XXX2_I2C_CTR(base) & E_ACK) {
data->err = E_HOSTA_ACK;
data->nack = 1;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nack is a bool type.

Suggested change
data->nack = 1;
data->nack = true;

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

* following i2c_reset.
*/
if (data->nack) {
data->nack = 0;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
data->nack = 0;
data->nack = false;

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@@ -659,6 +682,8 @@ static int i2c_enhance_pio_transfer(const struct device *dev,
if (data->err || (data->active_msg->flags & I2C_MSG_STOP)) {
data->i2ccs = I2C_CH_NORMAL;
}
/* Clear the flag */
data->nack = 0;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
data->nack = 0;
data->nack = false;

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@GTLin08 GTLin08 force-pushed the it8xxx2_i2c_eh_handle_read_0 branch from 2f4d205 to ffefb47 Compare May 22, 2025 01:49
Copy link
Collaborator

@teburd teburd left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The commit message could use with a bit more elaboration here as to what the problem is, why the change is needed, how this change solves the problem.

The changes themselves, from what I can tell, look ok.

Would highly recommend reducing the nesting level of the if/else dealing with what appears to be a hardware state machine flow into something more easily read by naming/assigning perhaps intermediate states in a more meaningful way.

The current I2C driver assumes that at least one byte will be read in CQ
(command queue) mode. However, when a 0-byte read is issued
(e.g., by cmd_i2c_scan),
The read handler uses (len - 1) to set the command queue length.
When len is 0, this underflows to 0xFF, leading to an incorrect transfer
length and possible crash.

To fix this, add a check in cq_mode_allowed() for reads with length 0:

-Fallback to PIO mode in such cases.
-Properly handle 0-byte reads by issuing STOP (E_FINISH) when the slave
 address is acknowledged.
-Add appropriate handling for NACK conditions when the slave address is
 not acknowledged.

Signed-off-by: Tim Lin <tim2.lin@ite.corp-partner.google.com>
@GTLin08 GTLin08 force-pushed the it8xxx2_i2c_eh_handle_read_0 branch from ffefb47 to 137521a Compare May 22, 2025 03:23
@GTLin08
Copy link
Collaborator Author

GTLin08 commented May 22, 2025

The commit message could use with a bit more elaboration here as to what the problem is, why the change is needed, how this change solves the problem.

The changes themselves, from what I can tell, look ok.

Would highly recommend reducing the nesting level of the if/else dealing with what appears to be a hardware state machine flow into something more easily read by naming/assigning perhaps intermediate states in a more meaningful way.

Thank you for the feedback!
I've updated the commit message to better describe the issue, the reason for the fix, and how it's addressed.

Copy link

@kartben kartben merged commit e1b5b8b into zephyrproject-rtos:main May 29, 2025
32 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants