Skip to content

SMBus block process call and block read feature not supported. #1812

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

Closed
davesliu opened this issue May 15, 2023 · 5 comments
Closed

SMBus block process call and block read feature not supported. #1812

davesliu opened this issue May 15, 2023 · 5 comments

Comments

@davesliu
Copy link

I'm using the raspberry pi OS with kernel 6.1.21-v8+ on raspberry 4B, found that it doesn't support the SMBus block process call and SMBus block read with i2cdetect -F command.
pi@raspberrypi:~ $ i2cdetect -F 1
Functionalities implemented by /dev/i2c-1:
I2C yes
SMBus Quick Command yes
SMBus Send Byte yes
SMBus Receive Byte yes
SMBus Write Byte yes
SMBus Read Byte yes
SMBus Write Word yes
SMBus Read Word yes
SMBus Process Call yes
SMBus Block Write yes
SMBus Block Read no
SMBus Block Process Call no
SMBus PEC yes
I2C Block Write yes
I2C Block Read yes

It seems that in function static u32 bcm2835_i2c_func(struct i2c_adapter *adap), it doesn't set the I2C_SMBUS_BLOCK_PROC_CALL and I2C_FUNC_SMBUS_READ_BLOCK_DATA
return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;

Can I add above two macro definitons directly in above line to let raspberry OS support SMBus block process call and SMBus block read ?

Or some extra work should be done to support above two features?

BTW, Per my understanding, the I2C_FUNC_SMBUS_READ_BLOCK_DATA is very similar as I2C_FUNC_SMBUS_READ_I2C_BLOCK , the only difference is the first byte response from I2C slave refers to data length for I2C_FUNC_SMBUS_READ_BLOCK_DATA

@6by9
Copy link

6by9 commented May 15, 2023

(Linux kernel issue, not firmware)

Both I2C_SMBUS_BLOCK_PROC_CALL and I2C_FUNC_SMBUS_READ_BLOCK_DATA rely on the read length being controlled by the first byte of the response. The flag I2C_M_RECV_LEN is passed in to the driver to signify that the first byte should be taken as the length. https://elixir.free-electrons.com/linux/latest/source/drivers/i2c/i2c-core-smbus.c#L395

Currently for i2c-bcm2835 the read length MUST be configured as part of the request, and read data is stored in a FIFO within the hardware block.
Whilst it might be possible to reconfigure the read pipeline such that an interrupt is always generated after the first byte (reading the datasheet I'm not convinced that is possible), I wouldn't like to guarantee that all conditions can be handled from that point. How would you handle 0 bytes being reported for the transfer for the read, as the I2C transaction should already have been concluded?

Whilst not technically within the SMBus protocol, I would suspect that configuring the read for the maximum length expected, and then looking at the first word to find out how many bytes were actually supplied by the peripheral may work. You may get the peripheral NAKing later bytes which could stop that working (the FIFO won't be read).
There is a flag I2C_M_IGNORE_NAK to ask the driver to ignore the NAK, but i2c-bcm2835 currently doesn't implement that (raspberrypi/linux#5280), and it needs I2C_FUNC_PROTOCOL_MANGLING set too which may have knock on implications.

@pelwell
Copy link
Contributor

pelwell commented May 15, 2023

And to answer your question directly:

Can I add above two macro definitons directly in above line to let raspberry OS support SMBus block process call and SMBus block read ?

Yes, but no. Adding the flag to the .functionality advertises support but doesn't add it - as @6by9 has explained, the hardware is unlikely to work in the required way, which is why the capability is not being advertised.

@davesliu
Copy link
Author

davesliu commented May 19, 2023

@6by9 and @pelwell
Thanks for your detail suggestions.
so do you mean it is impossible to implement SMBus Block read or block process call due to current i2c-bcm2835 not implement the I2C_M_IGNORE_NAK and not set the I2C_FUNC_PROTOCOL_MANGLING?

If so, is it possible to do bit-bang control of I2C on Linux application level to implement SMBus block read or SMBus block process call?

I mean that operate the I2C controller register directly with mapping the memory of it.

With this way, it seems the key issue is when will it send out NACK bit based on the value of first readout bytes in the FIFO.
If using bit-bang and set a maximum value in DLEN register of BCM2711, is it possible for application to decide when to send out NACK?

@6by9
Copy link

6by9 commented May 19, 2023

There is the i2c-gpio driver to bit bang the full I2C protocol. It does support I2C_FUNC_SMBUS_READ_BLOCK_DATA and I2C_FUNC_SMBUS_BLOCK_PROC_CALL.
Use dtoverlay=i2c-gpio,i2c_gpio_sda=N,i2c_gpio_scl=M to instantiate a bus on GPIOs M & N. Don't expect to mix and match the hardware and bit-banged drivers - use one or the other.

As I've said, you may find that your device allows you to do just an overlong read and it doesn't NAK the additional bytes, but that will be down to the implementation in your specific SMBus device.
I will be looking at the I2C driver for other reasons today, so may look at adding I2C_M_IGNORE_NAK. I don't have any SMBus devices needing block read or proc call, so I can't test out anything for your specific case.

@davesliu
Copy link
Author

@6by9 Thanks a lot
I will try with your suggestion to use i2c-gpio.

@davesliu davesliu closed this as completed Jun 1, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants