i2c-designware: lcnt/2 SDA hold default is a no-op on rpi-7.x (fs_lcnt still 0), regressing SSD1306 OLED on Pi 5

Offen
#7,740 2 Kommentare 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen

Maintainer antworten meist innerhalb von 1 Tag

Dieses Issue hat noch niemand übernommen.

Bewertung

Schwierigkeit
3/5
Geschätzter Aufwand
1-2 Tage
Anfängerfreundlichkeit
25/100
Issue-Typ
Bug
Klarheit
Klar beschrieben
Aktivitätsstatus
Veraltet
Tech-Stack
c, linux

Rechercherichtung

Start with drivers/i2c/busses/i2c-designware-common.c and trace the order of i2c_dw_probe_master() and i2c_dw_set_sda_hold() in i2c_dw_probe(). Check when fs_lcnt is computed and compare the configured SDA hold value with the reported IC_SDA_HOLD register. Done means the default uses the computed timing and the Pi 5 OLED works; the issue reports a linked pull request with the proposed change.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Beschreibung

Disclosure: this report was written by an AI assistant (GitHub Copilot CLI,
Claude Sonnet 5.5) working with a human engineer who owns the hardware and
reviewed the measurements. The kernel experiments were run on the engineer's
Pi 5.

Summary

The Pi-specific default "SDA hold = SCL low count / 2" (#6091, b74c3e122726 on
rpi-6.18.y) no longer takes effect on rpi-7.0.y .. rpi-7.3.y. In 7.x the line sits in
i2c_dw_probe() before i2c_dw_probe_master() has computed fs_lcnt, so it
evaluates to 0. The driver then keeps the hardware reset value (1 cycle, ~5 ns)
and the Pi 5 returns to the behaviour #6091 and #6056 fixed.

Impact

Adafruit PiOLED (128x32 SSD1306, 0x3c) on a Pi 5, no DT i2c-sda-hold-time-ns:

  • stock 6.18.60+rpt-rpi-2712: works
  • custom 7.3.1 (rpi-7.3.y): SDA stuck at low, OSError: [Errno 121] Remote I/O error
  • same Pi, same userspace, same DT, same cmdline

Same symptom as #6056 (AQM0802 LCD: lost arbitration / SDA stuck at low).
Another Pi 5 on 7.3.0-rc3 has the same IC_SDA_HOLD and its OLED happens to work,
so it is marginal and device dependent, not universal.

Root cause

rpi-6.18.y / 6.19.y: the default is set inside i2c_dw_set_timings_master()
right after dev->fs_lcnt = lcnt;.

rpi-7.0.y .. 7.3.y (first bad: bb68f1f3423b on rpi-7.0.y; later rebases
d2587dfeac41, 6b7c1f3d0028, 60199372c10d): the line is in i2c_dw_probe():

if (!dev->sda_hold_time)
    dev->sda_hold_time = dev->fs_lcnt / 2;   /* fs_lcnt == 0 here */
ret = i2c_dw_set_sda_hold(dev);
...
ret = i2c_dw_probe_master(dev);              /* computes fs_lcnt */

This follows mainline 38fa29b01a6a ("Combine the init functions"), which moved
i2c_dw_set_sda_hold() ahead of the timing calculation. Mainline has no such
default, so nothing upstream notices.

Evidence (printk on 7.3.1 + instrumented module)

probe: fs_lcnt=0, sda_hold_time=0 before default
default: sda_hold_time = fs_lcnt/2 = 0
set_sda_hold: sda_hold_time was 0 -> kept HW reset value 0x1
after set_timings_master: fs_lcnt=1186

Register (/dev/mem read of RP1 i2c1 at 0x1f00074000, clk_sys 200 MHz, 100 kHz):

kernel IC_SDA_HOLD OLED
6.18.60+rpt-rpi-2712 stock 0x10251 works
7.3.1 unpatched 0x10001 fails
7.3.1 with patch below 0x10251 works

0x251 = 593 = 1186 / 2 cycles, about 3 us.

What was checked

  • Ruled out userspace: same Blinka 9.2.0 / ssd1306 libs and daemon on a second, working Pi 5 (7.3.0-rc3), same 100 kHz bus, same GPIO2/3 pinmux, identical DT I2C properties.
  • Ruled out hardware: stock 6.18.60+rpt-rpi-2712 on the same Pi and OLED works; the bad kernels fail on the same board.
  • Booted the 7.3.0-rc3 kernel from the other Pi on the failing Pi: also fails, IC_SDA_HOLD=0x10001. The working Pi has the same value, so its OLED just tolerates it.
  • Compared kernel config and i2c_designware sources between the two Pis: identical (only an unrelated led-modes DT line differs).
  • Checked the lcnt / 2 line on current heads: rpi-6.18.y (a4985478de14) and rpi-6.19.y (597a84a013b2) have it in i2c_dw_set_timings_master(); rpi-7.0.y (42d9bb9081f1), 7.1.y (49246ab8cb8a), 7.2.y (dbb0de2b7b04) and 7.3.y (5f369cb6094a) have it in i2c_dw_probe().
  • Searched raspberrypi/linux issues and PRs for this symptom on 7.x: found #6091 (the original patch), #6056, #6043, #5784 and #7104 (6.x, different cause) but no report of this regression.
  • Not done: a real build bisect (the rpi branches are rebased), tests on other boards, slave mode.

Proposed fix

Compute the default after the timings are known, then run i2c_dw_set_sda_hold()
(which also adds the RX hold bit). Keeps all existing logic; only reorders:

--- a/drivers/i2c/busses/i2c-designware-common.c
+++ b/drivers/i2c/busses/i2c-designware-common.c
@@ -949,18 +949,18 @@ int i2c_dw_probe(struct dw_i2c_dev *dev)
 	if (ret)
 		return ret;
 
-	if (!dev->sda_hold_time)
-		dev->sda_hold_time = dev->fs_lcnt / 2;
-
-	ret = i2c_dw_set_sda_hold(dev);
+	ret = i2c_dw_set_fifo_size(dev);
 	if (ret)
 		return ret;
 
-	ret = i2c_dw_set_fifo_size(dev);
+	ret = i2c_dw_probe_master(dev);
 	if (ret)
 		return ret;
 
-	ret = i2c_dw_probe_master(dev);
+	if (!dev->sda_hold_time)
+		dev->sda_hold_time = dev->fs_lcnt / 2;
+
+	ret = i2c_dw_set_sda_hold(dev);
 	if (ret)
 		return ret;

Tested on Pi 5 with 7.3.1: IC_SDA_HOLD = 0x10251, OLED connects and refreshes,
no restarts. Not tested on other boards or with slave mode.

Caveats: "first bad" comes from reading the branch history (rebased, non-linear),
not a build bisect.

PR with the same change: see the linked pull request from jflecool2:i2c-designware-sda-hold-fix.

Vorherrschende Sprache
C
Sterne
13.3k
Forks
5.5k
Ø Merge
1 T. 4 Std.
Gemergte PRs (30 T.)
21

Entwicklungsumgebung

Dieses Projekt bietet weder Dev-Container noch Dockerfile noch Beitragsleitfaden – die Einrichtung liegt bei Ihnen. Beginnen Sie mit der README; die allgemeinen Schritte stehen in unserem Leitfaden für den ersten Beitrag.

Erste Schritte

  1. Lesen Sie das ganze Issue und danach den Beitragsleitfaden des Projekts.
  2. Schreiben Sie ins Issue, dass Sie es übernehmen — das erspart doppelte Arbeit.
  3. Forken Sie das Repository und arbeiten Sie in einem Branch.
  4. Öffnen Sie einen Pull Request, der die Issue-Nummer nennt.

Mehr aus raspberrypi/linux

Alle Issues in raspberrypi/linux

Ähnliche Issues

Weitere Issues zu C

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.