-
Notifications
You must be signed in to change notification settings - Fork 5k
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
Use i2c-bcm2835 as default #1716
Use i2c-bcm2835 as default #1716
Conversation
Writing messages larger than the FIFO size results in a hang, rendering the machine unusable. This is because the RXD status flag is set on the first interrupt which results in bcm2835_drain_rxfifo() stealing bytes from the buffer. The controller continues to trigger interrupts waiting for the missing bytes, but bcm2835_fill_txfifo() has none to give. In this situation wait_for_completion_timeout() apparently is unable to stop the madness. The BCM2835 ARM Peripherals datasheet has this to say about the flags: TXD: is set when the FIFO has space for at least one byte of data. RXD: is set when the FIFO contains at least one byte of data. TXW: is set during a write transfer and the FIFO is less than full. RXR: is set during a read transfer and the FIFO is or more full. Implementing the logic from the downstream i2c-bcm2708 driver solved the hang problem. Signed-off-by: Noralf Trønnes <noralf@tronnes.org> Reviewed-by: Eric Anholt <eric@anholt.net> Reviewed-by: Martin Sperl <kernel@martin.sperl.org>
If an unexpected TXW or RXR interrupt occurs (msg_buf_remaining == 0), the driver has no way to fill/drain the FIFO to stop the interrupts. In this case the controller has to be disabled and the transfer completed to avoid hang. (CLKT | ERR) and DONE interrupts are completed in their own paths, and the controller is disabled in the transfer function after completion. Unite the code paths and do disabling inside the interrupt routine. Clear interrupt status bits in the united completion path instead of trying to do it on every interrupt which isn't necessary. Only CLKT, ERR and DONE can be cleared that way. Add the status value to the error value in case of TXW/RXR errors to distinguish them from the other S_LEN error. Signed-off-by: Noralf Trønnes <noralf@tronnes.org> Reviewed-by: Eric Anholt <eric@anholt.net>
Writing to an AT24C32 generates on average 2x i2c transfer errors per 32-byte page write. Which amounts to a lot for a 4k write. This is due to the fact that the chip doesn't respond during it's internal write cycle when the at24 driver tries and retries the next write. Only a handful drivers use dev_err() on transfer error, so switch to dev_dbg() instead. Signed-off-by: Noralf Trønnes <noralf@tronnes.org> Reviewed-by: Eric Anholt <eric@anholt.net>
The controller can't support this flag, so remove it. Documentation/i2c/i2c-protocol states that all of the message is sent: I2C_M_IGNORE_NAK: Normally message is interrupted immediately if there is [NA] from the client. Setting this flag treats any [NA] as [A], and all of message is sent. From the BCM2835 ARM Peripherals datasheet: The ERR field is set when the slave fails to acknowledge either its address or a data byte written to it. So when the controller doesn't receive an ack, it sets ERR and raises an interrupt. In other words, the whole message is not sent. Signed-off-by: Noralf Trønnes <noralf@tronnes.org> Reviewed-by: Eric Anholt <eric@anholt.net>
Documentation/i2c/i2c-protocol states that Combined transactions should separate messages with a Start bit and end the whole transaction with a Stop bit. This patch adds support for issuing only a Start between messages instead of a Stop followed by a Start. This implementation differs from downstream i2c-bcm2708 in 2 respects: - it uses an interrupt to detect that the transfer is active instead of using polling. There is no interrupt for Transfer Active, but by not prefilling the FIFO it's possible to use the TXW interrupt. - when resetting/disabling the controller between transfers it writes CLEAR to the control register instead of just zero. Using just zero gave many errors. This might be the reason why downstream had to disable this feature and make it available with a module parameter. I have run thousands of transfers to a DS1307 (rtc), MMA8451 (accel) and AT24C32 (eeprom) in parallel without problems. Signed-off-by: Noralf Trønnes <noralf@tronnes.org> Acked-by: Eric Anholt <eric@anholt.net>
Use i2c_adapter->timeout for the completion timeout value. The core default is 1 second. Signed-off-by: Noralf Trønnes <noralf@tronnes.org> Reviewed-by: Eric Anholt <eric@anholt.net>
Support a dynamic clock by reading the frequency and setting the divisor in the transfer function instead of during probe. Signed-off-by: Noralf Trønnes <noralf@tronnes.org> Reviewed-by: Martin Sperl <kernel@martin.sperl.org>
This adds a debug module parameter to aid in debugging transfer issues by printing info to the kernel log. When enabled, status values are collected in the interrupt routine and msg info in bcm2835_i2c_start_transfer(). This is done in a way that tries to avoid affecting timing. Having printk in the isr can mask issues. debug values (additive): 1: Print info on error 2: Print info on all transfers 3: Print messages before transfer is started The value can be changed at runtime: /sys/module/i2c_bcm2835/parameters/debug Example output, debug=3: [ 747.114448] bcm2835_i2c_xfer: msg(1/2) write addr=0x54, len=2 flags= [i2c1] [ 747.114463] bcm2835_i2c_xfer: msg(2/2) read addr=0x54, len=32 flags= [i2c1] [ 747.117809] start_transfer: msg(1/2) write addr=0x54, len=2 flags= [i2c1] [ 747.117825] isr: remain=2, status=0x30000055 : TA TXW TXD TXE [i2c1] [ 747.117839] start_transfer: msg(2/2) read addr=0x54, len=32 flags= [i2c1] [ 747.117849] isr: remain=32, status=0xd0000039 : TA RXR TXD RXD [i2c1] [ 747.117861] isr: remain=20, status=0xd0000039 : TA RXR TXD RXD [i2c1] [ 747.117870] isr: remain=8, status=0x32 : DONE TXD RXD [i2c1] Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
i2c-bcm2835 has gotten an overhaul so we can now use as default. Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
For the overlay, use |
Added i2c-bcm2708 fallback overlay |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Two nitpicks.
@@ -520,6 +520,12 @@ Params: ds1307 Select the DS1307 device | |||
source | |||
|
|||
|
|||
Name: i2c-bcm2708 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As with the Makefile, this item needs to move before i2c-gpio.
@@ -41,6 +41,7 @@ dtbo-$(RPI_DT_OVERLAYS) += i2c-gpio.dtbo | |||
dtbo-$(RPI_DT_OVERLAYS) += i2c-mux.dtbo | |||
dtbo-$(RPI_DT_OVERLAYS) += i2c-pwm-pca9685a.dtbo | |||
dtbo-$(RPI_DT_OVERLAYS) += i2c-rtc.dtbo | |||
dtbo-$(RPI_DT_OVERLAYS) += i2c-bcm2708.dtbo |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, notro, my script complains this entry should come before i2c-gpio.
Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
1cd440f
to
69b0760
Compare
Fixed |
My alphabet looks a bit different - I've pushed some changes to be squashed. |
Sorry, the hyphen messed up my head. Can you squash this when pulling/merging? |
If I go through github we can only merge as-is or squash down to one. Since most of these are upstream patches, it's easier if we keep them separate. If we are in agreement to apply your patches, we can always squash and apply them manually. |
@pelwell okay to merge this? |
I've not had chance to test the new code, but my tests would be limited anyway and I trust @notro. Yes, no objections. |
I have submitted some patches upstream (now in linux-next) which tries to bring i2c-bcm2835 up to speed so we can start to use it. And the only way to know if it really can replace i2c-bcm2708 is to make it default, since "no one" will try it otherwise.
I have added a debug patch that hopefully can be of aid in tracking down the cause if some device stops working.
There's one thing missing here and that's a fallback to i2c-bcm2708. Initially I planned to make a i2c-bcm2708-overlay.dts, but we have i2c{0,1}-bcm2708-overlay.dts, so I'm not sure what to do.