From dcddf31f2ffefc5fa68d748c6fcad3ff3dfb933c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Berkay=20K=C3=B6sebay?= Date: Fri, 13 Nov 2026 05:18:33 +0800 Subject: [PATCH] kernel: Turn USB data on for every unidentified attachment The Lightning charger keeps USB data off from attach until it has identified the source, at most one second; only the first attachment since boot got that bound. After an unplug and replug the PMIC can stay in a transitional state, and USB data then stayed off: no USB serial and no SSH until a reboot. Every attachment now gets the one-second bound, at the 500 mA fallback, and the hold starts when input returns. The charger poll moves to an unbound queue (a boot warning). This is the same driver on the iPad 5 and iPad 6. J71t USB serial and USB network are now tested by hand, including after a USB host session. From orchard PR #127 (commit 339bd296), folded into one patch that extends the existing hold instead of adding a second timer. --- chips/s8003.toml | 2 +- devices/j71t/device.toml | 4 +- docs/compatibility.md | 2 +- ...se-the-USB-hold-for-every-attachment.patch | 87 +++++++++++++++++++ 4 files changed, 91 insertions(+), 4 deletions(-) create mode 100644 kernel/patches/drivers/power/0026-power-supply-apple_tristar_charger-Release-the-USB-hold-for-every-attachment.patch diff --git a/chips/s8003.toml b/chips/s8003.toml index e152fbed..59e14302 100644 --- a/chips/s8003.toml +++ b/chips/s8003.toml @@ -13,5 +13,5 @@ stages = ["iBSS", "iBEC"] [evidence] page_size = "xnu-6153.141.1 osfmk/arm/proc_reg.h" -platform = "J71t on hardware" +platform = "J71t on hardware; USB serial and networking verified" stages = "remote_boot two-stage CPID list" diff --git a/devices/j71t/device.toml b/devices/j71t/device.toml index 50c7cd2e..35e0420b 100644 --- a/devices/j71t/device.toml +++ b/devices/j71t/device.toml @@ -49,8 +49,8 @@ charging = "untested" charging_control = "untested" suspend = "untested" resume = "untested" -usb_serial = "untested" -usb_network = "untested" +usb_serial = "working" +usb_network = "working" audio_output = "working" audio_input = "untested" camera = "missing" diff --git a/docs/compatibility.md b/docs/compatibility.md index a9730828..c04761ed 100644 --- a/docs/compatibility.md +++ b/docs/compatibility.md @@ -161,7 +161,7 @@ Boards Orchard builds for. States: working, untested, missing, none (no such har | `n66` | untested | missing | untested | missing | untested | missing | missing | missing | missing | missing | missing | missing | missing | missing | missing | missing | missing | missing | untested | untested | untested | untested | missing | missing | missing | missing | | `n69u` | untested | missing | untested | missing | untested | missing | missing | missing | missing | missing | missing | missing | missing | missing | missing | missing | missing | missing | untested | untested | untested | untested | missing | missing | missing | missing | | `n71` | untested | missing | untested | missing | untested | missing | missing | missing | missing | missing | missing | missing | missing | missing | missing | missing | missing | missing | untested | untested | untested | untested | missing | missing | missing | missing | -| `j71t` | untested | untested | untested | untested | untested | missing | missing | untested | missing | untested | untested | untested | untested | untested | none | untested | untested | untested | untested | untested | untested | untested | working | untested | missing | working | +| `j71t` | untested | untested | untested | untested | untested | missing | missing | untested | missing | untested | untested | untested | untested | untested | none | untested | untested | untested | untested | untested | working | working | working | untested | missing | working | | `j72t` | untested | untested | untested | untested | untested | missing | missing | untested | missing | untested | untested | untested | untested | untested | missing | untested | untested | untested | untested | untested | untested | untested | untested | untested | missing | untested | | `n66m` | untested | missing | untested | missing | untested | missing | missing | missing | missing | missing | missing | missing | missing | missing | missing | missing | missing | missing | untested | untested | untested | untested | missing | missing | missing | missing | | `n69` | untested | missing | untested | missing | untested | missing | missing | missing | missing | missing | missing | missing | missing | missing | missing | missing | missing | missing | untested | untested | untested | untested | missing | missing | missing | missing | diff --git a/kernel/patches/drivers/power/0026-power-supply-apple_tristar_charger-Release-the-USB-hold-for-every-attachment.patch b/kernel/patches/drivers/power/0026-power-supply-apple_tristar_charger-Release-the-USB-hold-for-every-attachment.patch new file mode 100644 index 00000000..d7983079 --- /dev/null +++ b/kernel/patches/drivers/power/0026-power-supply-apple_tristar_charger-Release-the-USB-hold-for-every-attachment.patch @@ -0,0 +1,87 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Berkay=20K=C3=B6sebay?= +Date: Thu, 12 Nov 2026 00:08:20 +0000 +Subject: [PATCH] power: supply: apple_tristar_charger: Release the USB hold + for every attachment + +USB data stays off from attach until the source is identified, at most +TRISTAR_HOLD_MS; only the first attachment since probe got that bound. +The PMIC can stay in a transitional state (e.g. 0x62) for any later +attachment too, and then USB data stayed off for good: no USB serial +and no USB network until a reboot. Release the hold for every +attachment, at the fallback limit, and start the hold when input +returns after an unplug, not when it went away, so a cable reinserted +after a long unplug is still identified first. + +The charger's queue asked for neither WQ_PERCPU nor WQ_UNBOUND, so every +boot warned in alloc_workqueue(). The poll sleeps on I2C and the HDQ +gauge and keeps no per-CPU state: make the queue unbound. + +[Orchard: from orchard PR #127 (commits 339bd296; patches 0031-0033 + there), folded into one patch that extends the existing hold instead + of adding a second timer] + +Assisted-by: LLM +--- +diff --git a/drivers/power/supply/apple_tristar_charger.c b/drivers/power/supply/apple_tristar_charger.c +index a953ced..f632874 100644 +--- a/drivers/power/supply/apple_tristar_charger.c ++++ b/drivers/power/supply/apple_tristar_charger.c +@@ -155,7 +155,6 @@ struct tristar_charger { + unsigned int source_ma; + /* USB data is on for this attachment: the mux must stay untouched. */ + bool usb_on; +- bool source_seen; /* an attachment since probe */ + /* What the USB host allows (vbus_draw), valid for usb_epoch only. */ + unsigned int usb_ma; + unsigned int usb_epoch; +@@ -698,7 +697,6 @@ static void tristar_new_attachment(struct tristar_charger *chg, u64 now) + { + /* Before anything else: a host must not start a session yet. */ + tristar_set_usb(chg, false); +- chg->source_seen = true; + chg->present = true; + chg->phase = TRISTAR_SETTLING; + chg->attach_ns = now; +@@ -910,12 +908,18 @@ static void tristar_guard(struct tristar_charger *chg, u64 now) + * up on the source: USB serial and SSH must not depend on charging. An attachment + * later holds USB data off again and identifies as usual. Caller holds lock. + */ ++/* ++ * Input is present but no source was identified: the PMIC can stay in a ++ * transitional state (e.g. 0x62) for any attachment, not only the first ++ * since probe. USB data must not stay off for it: after TRISTAR_HOLD_MS ++ * turn it on, at the fallback limit. Caller holds lock. ++ */ + static void tristar_no_source(struct tristar_charger *chg, unsigned int status, u64 now) + { +- if (chg->usb_on || chg->source_seen || ++ if (chg->usb_on || + (s64)(now - chg->hold_ns) < (s64)TRISTAR_HOLD_MS * NSEC_PER_MSEC) + return; +- dev_warn(chg->dev, "no source seen since probe (status %#x), turning USB data on\n", status); ++ dev_info(chg->dev, "no source identified (status %#x), turning USB data on\n", status); + tristar_set_usb(chg, true); + } + +@@ -939,6 +943,8 @@ static void tristar_poll(struct work_struct *work) + } + chg->online = status != 0; + if (!status) { ++ /* The hold of the next attachment starts when input returns. */ ++ chg->hold_ns = now; + if (chg->present) { + tristar_set_usb(chg, false); + chg->present = false; +@@ -1335,7 +1341,8 @@ static int tristar_probe(struct platform_device *pdev) + if (ret) + return ret; + init_completion(&chg->adc_done); +- chg->wq = devm_alloc_workqueue(dev, "tristar-charger", WQ_HIGHPRI | WQ_FREEZABLE, 1); ++ chg->wq = devm_alloc_workqueue(dev, "tristar-charger", ++ WQ_UNBOUND | WQ_HIGHPRI | WQ_FREEZABLE, 1); + if (!chg->wq) + return -ENOMEM; + INIT_DELAYED_WORK(&chg->poll_work, tristar_poll); +-- +2.54.0