From 4503cd1351c1f1500ea07d735fbca91858d0a57e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Berkay=20K=C3=B6sebay?= Date: Fri, 13 Nov 2026 04:45:08 +0800 Subject: [PATCH 1/2] kernel: Wake the iPad 5 from sleep when the Smart Cover opens The Smart Cover hall sensors (PMIC GPIO 0 and 10) cannot be interrupt consumers while awake: unmasked, every change of the magnet field holds the PMU line. The D2365 driver now takes a list of wake-only events, keeps them masked while awake and arms them only for a sleep, so opening the cover wakes the iPad. A failed write of the sleep mask now refuses the suspend instead of sleeping with the wrong events armed. From orchard PR #118 (commit e8b5e4b7) and the D2365 part of PR #117 (commit 40a8b18d), folded into one driver patch without the diagnostic logging; the device tree part moved from the J71t board file to the shared iPad 5 file, so all four iPad 5 models get it. Boards without apple,wake-events behave as before. --- ...5-Wake-from-sleep-on-the-Smart-Cover.patch | 30 ++ ...-pmic-gpio-Describe-wake-only-events.patch | 71 ++++ ...ake-from-sleep-on-listed-GPIO-events.patch | 374 ++++++++++++++++++ 3 files changed, 475 insertions(+) create mode 100644 kernel/patches/devices/s8000/0008-arm64-dts-apple-ipad5-Wake-from-sleep-on-the-Smart-Cover.patch create mode 100644 kernel/patches/drivers/gpio/0006-dt-bindings-gpio-apple-d2365-pmic-gpio-Describe-wake-only-events.patch create mode 100644 kernel/patches/drivers/gpio/0007-gpio-apple-d2365-Wake-from-sleep-on-listed-GPIO-events.patch diff --git a/kernel/patches/devices/s8000/0008-arm64-dts-apple-ipad5-Wake-from-sleep-on-the-Smart-Cover.patch b/kernel/patches/devices/s8000/0008-arm64-dts-apple-ipad5-Wake-from-sleep-on-the-Smart-Cover.patch new file mode 100644 index 00000000..6ca37da8 --- /dev/null +++ b/kernel/patches/devices/s8000/0008-arm64-dts-apple-ipad5-Wake-from-sleep-on-the-Smart-Cover.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Berkay=20K=C3=B6sebay?= +Date: Tue, 10 Nov 2026 17:27:23 +0000 +Subject: [PATCH] arm64: dts: apple: ipad5: Wake from sleep on the Smart Cover + +PMIC GPIO lines 0 and 10 are the Smart Cover hall sensors. Their events, +0x30 and 0x3a, latch while the iPad sleeps; list them as wake-only so +that opening the cover wakes the iPad. The polled switches are +unchanged: lines 0 and 10 are already outside gpio-reserved-ranges. + +[Orchard: from orchard PR #118, commit e8b5e4b7; moved from the J71t + board file to the shared iPad 5 file, so every iPad 5 model has it] + +Assisted-by: LLM +--- +diff --git a/arch/arm64/boot/dts/apple/s800x-ipad5.dtsi b/arch/arm64/boot/dts/apple/s800x-ipad5.dtsi +index 2ce40b4..fc06d53 100644 +--- a/arch/arm64/boot/dts/apple/s800x-ipad5.dtsi ++++ b/arch/arm64/boot/dts/apple/s800x-ipad5.dtsi +@@ -182,6 +182,8 @@ + interrupt-controller; + #interrupt-cells = <2>; + interrupts-extended = <&pinctrl_ap 76 IRQ_TYPE_LEVEL_LOW>; ++ /* Smart Cover hall sensors (lines 0 and 10): wake only. */ ++ apple,wake-events = <0x30 0x3a>; + }; + + tristar_charger: charger@180 { +-- +2.54.0 diff --git a/kernel/patches/drivers/gpio/0006-dt-bindings-gpio-apple-d2365-pmic-gpio-Describe-wake-only-events.patch b/kernel/patches/drivers/gpio/0006-dt-bindings-gpio-apple-d2365-pmic-gpio-Describe-wake-only-events.patch new file mode 100644 index 00000000..75eebf61 --- /dev/null +++ b/kernel/patches/drivers/gpio/0006-dt-bindings-gpio-apple-d2365-pmic-gpio-Describe-wake-only-events.patch @@ -0,0 +1,71 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Berkay=20K=C3=B6sebay?= +Date: Tue, 10 Nov 2026 17:27:23 +0000 +Subject: [PATCH] dt-bindings: gpio: apple,d2365-pmic-gpio: Describe wake-only + events + +Add apple,wake-events: GPIO events (0x30 plus the line) that end system +sleep and have no interrupt consumer, such as the iPad Smart Cover hall +sensors on lines 0 and 10. A hall sensor that is unmasked while the +system is awake drives the PMU line on every change of the magnet field, +so these events are unmasked only for the duration of a sleep and cannot +be mapped as interrupts. Only the D2365 has the event controller they +need. + +[Orchard: from orchard PR #118, commit e8b5e4b7; example text names + every iPad with the cover, not only the iPad 5] + +Assisted-by: LLM +--- +diff --git a/Documentation/devicetree/bindings/gpio/apple,d2365-pmic-gpio.yaml b/Documentation/devicetree/bindings/gpio/apple,d2365-pmic-gpio.yaml +index c1cae13..a962bb0 100644 +--- a/Documentation/devicetree/bindings/gpio/apple,d2365-pmic-gpio.yaml ++++ b/Documentation/devicetree/bindings/gpio/apple,d2365-pmic-gpio.yaml +@@ -54,6 +54,21 @@ properties: + maxItems: 1 + description: PMU event output of the PMIC, active low. + ++ apple,wake-events: ++ $ref: /schemas/types.yaml#/definitions/uint32-array ++ minItems: 1 ++ maxItems: 24 ++ items: ++ minimum: 0x30 ++ maximum: 0x47 ++ description: | ++ GPIO events (0x30 plus the line number) that end system sleep and have ++ no interrupt consumer, such as the iPad Smart Cover hall sensors on ++ lines 0 and 10 (events 0x30 and 0x3a). They stay masked while the ++ system is awake, where the line is read through the GPIO instead, and ++ are unmasked only while it sleeps: a hall sensor drives the PMU line on ++ every change of the magnet field. They cannot be mapped as interrupts. ++ + required: + - compatible + - gpio-controller +@@ -61,6 +76,7 @@ required: + + dependencies: + interrupt-controller: ["#interrupt-cells"] ++ apple,wake-events: [interrupt-controller] + + allOf: + - if: +@@ -74,6 +90,7 @@ allOf: + interrupt-controller: false + "#interrupt-cells": false + interrupts: false ++ apple,wake-events: false + + additionalProperties: false + +@@ -92,6 +109,7 @@ examples: + #interrupt-cells = <2>; + interrupt-controller; + interrupts = <38 IRQ_TYPE_LEVEL_LOW>; ++ apple,wake-events = <0x30 0x3a>; + }; + }; + ... +-- +2.54.0 diff --git a/kernel/patches/drivers/gpio/0007-gpio-apple-d2365-Wake-from-sleep-on-listed-GPIO-events.patch b/kernel/patches/drivers/gpio/0007-gpio-apple-d2365-Wake-from-sleep-on-listed-GPIO-events.patch new file mode 100644 index 00000000..ec1ab722 --- /dev/null +++ b/kernel/patches/drivers/gpio/0007-gpio-apple-d2365-Wake-from-sleep-on-listed-GPIO-events.patch @@ -0,0 +1,374 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Berkay=20K=C3=B6sebay?= +Date: Tue, 10 Nov 2026 17:27:23 +0000 +Subject: [PATCH] gpio: apple-d2365: Wake from sleep on listed GPIO events + +The Smart Cover hall sensors cannot be interrupt consumers: unmasked +while the system is awake, they keep the PMU line asserted (an +interrupt-driven gpio-keys caused an interrupt storm). The cover +switches stay polled; make the halls wake-only instead. + +Events in apple,wake-events get no interrupt mapping and stay masked +while awake. Every event latches whether masked or not, so ->suspend +stops the event thread and reads the block before it unmasks them, or +the cover close that started the suspend would end it at once. Consumer +events in that read are dispatched as the thread would have, and a wake +source among them ends the transition. ->suspend then unmasks the wake +and wake-only events and takes a wake reference on the PMU line, which +no child interrupt holds for these events. ->resume masks them again +and, while the thread is still gated, reads the latched events and +dispatches the consumers. + +A failed write of the sleep mask now refuses the suspend instead of +sleeping with the wrong events armed, and restores the awake mask +first, because ->resume will not run. + +The read of the event block is factored out of the thread and shared; +the line interrupt's consumers and the storm accounting stay in the +thread. Without apple,wake-events nothing changes. + +[Orchard: from orchard PR #117 (gpio 0006, commit 40a8b18d) and PR #118 + (gpio 0008, commit e8b5e4b7), folded into one patch; the boot-time and + per-sleep diagnostic logging is left out] + +Assisted-by: LLM +--- +diff --git a/drivers/gpio/gpio-apple-d2365.c b/drivers/gpio/gpio-apple-d2365.c +index ba66e8e..39d6b79 100644 +--- a/drivers/gpio/gpio-apple-d2365.c ++++ b/drivers/gpio/gpio-apple-d2365.c +@@ -11,6 +11,12 @@ + * One more interrupt, numbered after the last event, is the line itself: its + * consumers run before the block is read, for a consumer that must act + * within the shortest time after an assertion (charger withdrawal). ++ * ++ * GPIO events listed in apple,wake-events have no consumer: they stay ++ * masked while the system is awake and are unmasked only while it sleeps. ++ * An event latches whether it is masked or not, so the block is read ++ * before they are unmasked, or a move from before the suspend (the cover ++ * close that started it) would end the sleep at once. + */ + + #include +@@ -116,6 +122,7 @@ struct apple_pmic_gpio { + struct delayed_work irq_retry; + DECLARE_BITMAP(enabled, APPLE_PMIC_IRQS_MAX); /* unmasked while awake */ + DECLARE_BITMAP(wake, APPLE_PMIC_EVENTS_MAX); /* unmasked while asleep */ ++ DECLARE_BITMAP(wake_only, APPLE_PMIC_EVENTS_MAX); /* apple,wake-events */ + u8 mask[APPLE_PMIC_EVENT_BYTES_MAX]; /* as last written */ + u8 boot_mask[APPLE_PMIC_EVENT_BYTES_MAX]; + int wake_delta; /* parent wake references to apply */ +@@ -126,6 +133,8 @@ struct apple_pmic_gpio { + bool irq_held; + bool removing; + bool shutting_down; ++ bool wake_only_armed; /* wake_only unmasked for this sleep */ ++ bool parent_wake_armed; /* our own wake reference on the line */ + }; + + static unsigned int d2207_gpio_config_reg(unsigned int offset) +@@ -285,6 +294,9 @@ static int apple_pmic_irq_map(struct irq_domain *domain, unsigned int irq, + + if (hwirq > gpio->nevents) + return -EINVAL; ++ /* Unmasked while awake, a hall sensor holds the PMU line. */ ++ if (hwirq < gpio->nevents && test_bit(hwirq, gpio->wake_only)) ++ return -EINVAL; + + irq_set_chip_data(irq, gpio); + irq_set_chip_and_handler(irq, &apple_pmic_irq_chip, handle_simple_irq); +@@ -346,7 +358,8 @@ static bool apple_pmic_event_gate(struct apple_pmic_gpio *gpio) + * suspend_device_irqs() must abort the transition, as the armed + * interrupt does afterwards. + */ +- if (!bitmap_empty(gpio->wake, gpio->nevents)) ++ if (!bitmap_empty(gpio->wake, gpio->nevents) || ++ gpio->wake_only_armed) + pm_system_wakeup(); + apple_pmic_irq_hold(gpio, false); + return false; +@@ -363,6 +376,41 @@ static void apple_pmic_dispatch(struct apple_pmic_gpio *gpio, + handle_nested_irq(child); + } + ++/* ++ * Read (and so clear) the event block: @latched gets every set event, ++ * @pending the ones with a consumer. Caller holds irq_lock. ++ */ ++static int apple_pmic_event_read(struct apple_pmic_gpio *gpio, ++ unsigned long *latched, unsigned long *pending) ++{ ++ const struct apple_pmic_event_info *ev = gpio->info->events; ++ u8 events[APPLE_PMIC_EVENT_BYTES_MAX]; ++ unsigned int hwirq; ++ int ret; ++ ++ bitmap_zero(latched, APPLE_PMIC_EVENTS_MAX); ++ bitmap_zero(pending, APPLE_PMIC_EVENTS_MAX); ++ ret = regmap_bulk_read(gpio->regmap, ev->status_base, events, ev->bytes); ++ if (ret) ++ return ret; ++ ++ for (hwirq = 0; hwirq < gpio->nevents; hwirq++) ++ if (events[hwirq / 8] & BIT(hwirq % 8)) ++ __set_bit(hwirq, latched); ++ bitmap_and(pending, latched, gpio->enabled, gpio->nevents); ++ return 0; ++} ++ ++/* Consumers may mask their interrupt, which takes the bus lock. */ ++static void apple_pmic_dispatch_events(struct apple_pmic_gpio *gpio, ++ const unsigned long *pending) ++{ ++ unsigned int hwirq; ++ ++ for_each_set_bit(hwirq, pending, gpio->nevents) ++ apple_pmic_dispatch(gpio, hwirq); ++} ++ + /* + * Per assertion of the PMU line: first the consumers of the line itself, + * then one read of the event block; every set event with a consumer is then +@@ -377,10 +425,8 @@ static void apple_pmic_dispatch(struct apple_pmic_gpio *gpio, + static irqreturn_t apple_pmic_event_thread(int irq, void *data) + { + struct apple_pmic_gpio *gpio = data; +- const struct apple_pmic_event_info *ev = gpio->info->events; ++ DECLARE_BITMAP(latched, APPLE_PMIC_EVENTS_MAX); + DECLARE_BITMAP(pending, APPLE_PMIC_EVENTS_MAX); +- u8 events[APPLE_PMIC_EVENT_BYTES_MAX]; +- unsigned int hwirq; + int ret; + + bitmap_zero(pending, APPLE_PMIC_EVENTS_MAX); +@@ -408,15 +454,10 @@ static irqreturn_t apple_pmic_event_thread(int irq, void *data) + } + + /* Reading the events clears them and releases the line. */ +- ret = regmap_bulk_read(gpio->regmap, ev->status_base, events, ev->bytes); ++ ret = apple_pmic_event_read(gpio, latched, pending); + if (ret) + goto hold; + gpio->retries = 0; +- +- for (hwirq = 0; hwirq < gpio->nevents; hwirq++) +- if (events[hwirq / 8] & BIT(hwirq % 8) && +- test_bit(hwirq, gpio->enabled)) +- __set_bit(hwirq, pending); + mutex_unlock(&gpio->irq_lock); + goto dispatch; + +@@ -429,9 +470,7 @@ hold: + mutex_unlock(&gpio->irq_lock); + + dispatch: +- /* Consumers may mask their interrupt, which takes the bus lock. */ +- for_each_set_bit(hwirq, pending, gpio->nevents) +- apple_pmic_dispatch(gpio, hwirq); ++ apple_pmic_dispatch_events(gpio, pending); + return IRQ_HANDLED; + + unlock: +@@ -481,6 +520,34 @@ static void apple_pmic_event_stop(void *data) + free_irq(gpio->parent_irq, gpio); + } + ++static void apple_pmic_wake_only_parse(struct apple_pmic_gpio *gpio) ++{ ++ const struct apple_pmic_event_info *ev = gpio->info->events; ++ struct device *dev = gpio->chip.parent; ++ u32 events[APPLE_PMIC_EVENTS_MAX / 8]; ++ int count, i; ++ ++ count = device_property_count_u32(dev, "apple,wake-events"); ++ if (count <= 0) ++ return; ++ if (count > gpio->info->ngpio || ++ device_property_read_u32_array(dev, "apple,wake-events", events, ++ count)) { ++ dev_warn(dev, "ignoring unreadable apple,wake-events\n"); ++ return; ++ } ++ for (i = 0; i < count; i++) { ++ if (events[i] < ev->gpio_event || ++ events[i] >= ev->gpio_event + gpio->info->ngpio || ++ events[i] >= gpio->nevents) { ++ dev_warn(dev, "ignoring wake event 0x%x: not a GPIO event\n", ++ events[i]); ++ continue; ++ } ++ __set_bit(events[i], gpio->wake_only); ++ } ++} ++ + static int apple_pmic_event_probe(struct platform_device *pdev, + struct apple_pmic_gpio *gpio) + { +@@ -496,6 +563,7 @@ static int apple_pmic_event_probe(struct platform_device *pdev, + if (gpio->parent_irq < 0) + return gpio->parent_irq; + gpio->nevents = ev->bytes * 8; ++ apple_pmic_wake_only_parse(gpio); + + ret = devm_mutex_init(dev, &gpio->irq_lock); + if (ret) +@@ -576,30 +644,100 @@ void apple_d2365_gpio_quiesce(struct device *dev) + } + EXPORT_SYMBOL_GPL(apple_d2365_gpio_quiesce); + ++/* ++ * Drop what latched while awake before the wake-only events are unmasked, ++ * with the event thread stopped. Consumer events in that read are run as ++ * the thread would have run them; a wake source among them ends this ++ * transition, as it would once the line is armed. ++ */ ++static void apple_pmic_wake_only_drop(struct apple_pmic_gpio *gpio) ++{ ++ struct device *dev = gpio->chip.parent; ++ DECLARE_BITMAP(latched, APPLE_PMIC_EVENTS_MAX); ++ DECLARE_BITMAP(pending, APPLE_PMIC_EVENTS_MAX); ++ int ret; ++ ++ mutex_lock(&gpio->irq_lock); ++ ret = apple_pmic_event_read(gpio, latched, pending); ++ mutex_unlock(&gpio->irq_lock); ++ if (ret) { ++ /* Unknown: as the thread does, every consumer may have an event. */ ++ dev_warn(dev, "cannot drop the latched events: %d\n", ret); ++ bitmap_copy(pending, gpio->enabled, gpio->nevents); ++ } ++ if (bitmap_intersects(pending, gpio->wake, gpio->nevents)) ++ pm_system_wakeup(); ++ apple_pmic_dispatch_events(gpio, pending); ++} ++ + static int apple_pmic_gpio_suspend(struct device *dev) + { + struct apple_pmic_gpio *gpio = dev_get_drvdata(dev); ++ DECLARE_BITMAP(armed, APPLE_PMIC_EVENTS_MAX); ++ bool wake_only = false; + int ret; + + if (!gpio->domain) + return 0; + + cancel_delayed_work_sync(&gpio->irq_retry); ++ if (!bitmap_empty(gpio->wake_only, gpio->nevents)) { ++ wake_only = true; ++ disable_irq(gpio->parent_irq); ++ apple_pmic_wake_only_drop(gpio); ++ } ++ + mutex_lock(&gpio->irq_lock); + /* Only wake-enabled events may pull the line while asleep. */ +- ret = apple_pmic_event_sync(gpio, gpio->wake); ++ bitmap_or(armed, gpio->wake, gpio->wake_only, gpio->nevents); ++ ret = apple_pmic_event_sync(gpio, armed); + if (ret) +- dev_warn(dev, "event wake mask write failed: %d\n", ret); ++ goto unwind; + gpio->suspended = true; ++ gpio->wake_only_armed = wake_only; + mutex_unlock(&gpio->irq_lock); ++ if (wake_only) ++ enable_irq(gpio->parent_irq); + /* A thread that passed the gate before it closed has finished now. */ + synchronize_irq(gpio->parent_irq); ++ ++ if (wake_only) { ++ /* No child interrupt takes a wake reference for these. */ ++ ret = irq_set_irq_wake(gpio->parent_irq, 1); ++ if (ret) { ++ dev_err(dev, "cannot arm the PMU interrupt for wake: %d\n", ++ ret); ++ mutex_lock(&gpio->irq_lock); ++ gpio->suspended = false; ++ gpio->wake_only_armed = false; ++ goto unwind_enabled; ++ } ++ gpio->parent_wake_armed = true; ++ } + return 0; ++ ++unwind: ++ /* resume() will not run for this device: mask the halls again here. */ ++ if (wake_only) ++ enable_irq(gpio->parent_irq); ++unwind_enabled: ++ if (apple_pmic_event_sync(gpio, gpio->enabled)) ++ dev_err(dev, "event mask restore failed\n"); ++ /* A line held while gated is not re-enabled by a resume of ours. */ ++ if (gpio->irq_held) { ++ gpio->irq_held = false; ++ enable_irq(gpio->parent_irq); ++ } ++ mutex_unlock(&gpio->irq_lock); ++ return ret; + } + + static int apple_pmic_gpio_resume(struct device *dev) + { + struct apple_pmic_gpio *gpio = dev_get_drvdata(dev); ++ DECLARE_BITMAP(latched, APPLE_PMIC_EVENTS_MAX); ++ DECLARE_BITMAP(pending, APPLE_PMIC_EVENTS_MAX); ++ bool armed, read = false; + int ret; + + if (!gpio->domain) +@@ -607,17 +745,36 @@ static int apple_pmic_gpio_resume(struct device *dev) + + /* Our I2C ancestors have completed their resume callbacks. */ + mutex_lock(&gpio->irq_lock); +- gpio->suspended = false; +- gpio->retries = 0; + ret = apple_pmic_event_sync(gpio, gpio->enabled); + if (ret) + dev_warn(dev, "event mask write failed: %d\n", ret); +- /* An event that arrived while gated is still latched. */ ++ armed = gpio->wake_only_armed; ++ gpio->wake_only_armed = false; ++ bitmap_zero(pending, APPLE_PMIC_EVENTS_MAX); ++ if (armed) { ++ /* Still gated: the thread cannot take the wake reason first. */ ++ read = !apple_pmic_event_read(gpio, latched, pending); ++ } ++ gpio->suspended = false; ++ gpio->retries = 0; ++ /* An event that arrived while gated is still latched, unless read here. */ + if (gpio->irq_held) { + gpio->irq_held = false; + enable_irq(gpio->parent_irq); + } + mutex_unlock(&gpio->irq_lock); ++ ++ if (armed) { ++ if (!read) { ++ /* Unknown: every consumer may have an event. */ ++ bitmap_copy(pending, gpio->enabled, gpio->nevents); ++ } ++ if (gpio->parent_wake_armed) { ++ irq_set_irq_wake(gpio->parent_irq, 0); ++ gpio->parent_wake_armed = false; ++ } ++ apple_pmic_dispatch_events(gpio, pending); ++ } + return 0; + } + +@@ -726,13 +883,13 @@ static int apple_pmic_gpio_probe(struct platform_device *pdev) + gpio->regmap = dev_get_regmap(dev->parent, NULL); + if (!gpio->regmap) + return dev_err_probe(dev, -ENODEV, "parent regmap unavailable\n"); ++ gpio->chip.parent = dev; + + ret = apple_pmic_event_probe(pdev, gpio); + if (ret) + return ret; + + gpio->chip.label = gpio->info->label; +- gpio->chip.parent = dev; + gpio->chip.owner = THIS_MODULE; + gpio->chip.base = -1; + gpio->chip.ngpio = gpio->info->ngpio; +-- +2.54.0 From 2d5a9ab9540a9c617b54576ebf769cf86128c32a Mon Sep 17 00:00:00 2001 From: Henrik Klee Date: Fri, 13 Nov 2026 04:45:08 +0800 Subject: [PATCH 2/2] kernel: Add the Smart Cover to the iPad 6 Apple's device trees put the iPad 6 cover sensors on the same PMIC lines as the iPad 5 (GPIO 0 "halleffect", GPIO 10 "halleffect1", same flags), so the iPad 6 gets the iPad 5 description: two cover switches and wake from sleep when the cover opens. --- ...-dts-apple-ipad6-Add-the-Smart-Cover.patch | 82 +++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 kernel/patches/devices/t8010/0022-arm64-dts-apple-ipad6-Add-the-Smart-Cover.patch diff --git a/kernel/patches/devices/t8010/0022-arm64-dts-apple-ipad6-Add-the-Smart-Cover.patch b/kernel/patches/devices/t8010/0022-arm64-dts-apple-ipad6-Add-the-Smart-Cover.patch new file mode 100644 index 00000000..deb0673a --- /dev/null +++ b/kernel/patches/devices/t8010/0022-arm64-dts-apple-ipad6-Add-the-Smart-Cover.patch @@ -0,0 +1,82 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Henrik Klee +Date: Fri, 13 Nov 2026 05:00:00 +0800 +Subject: [PATCH] arm64: dts: apple: ipad6: Add the Smart Cover + +The iPad 6 has the iPad 5's Smart Cover hall sensors on the same PMIC +lines: Apple's device tree for both boards names PMIC GPIO 0 +"halleffect" and GPIO 10 "halleffect1" (/arm-io/i2c0/pmu event names, +/buttons function-button_halleffect{,1} with the same flags). Describe +them as on the iPad 5: two polled SW_MACHINE_COVER switches, +the two lines taken out of the reserved ranges, and their events 0x30 +and 0x3a as wake-only, so that opening the cover wakes the iPad. + +Measured on a J71b by reading the PMIC input register (0x186): both +lines read 1 with the cover open and 0 with it closed, so the assumed +active-low polarity is right. + +Assisted-by: LLM +--- +diff --git a/arch/arm64/boot/dts/apple/t8010-ipad6.dtsi b/arch/arm64/boot/dts/apple/t8010-ipad6.dtsi +index cd4e184..d6ec2b6 100644 +--- a/arch/arm64/boot/dts/apple/t8010-ipad6.dtsi ++++ b/arch/arm64/boot/dts/apple/t8010-ipad6.dtsi +@@ -59,6 +59,42 @@ + }; + }; + ++ /* ++ * Smart Cover hall sensors: PMIC GPIO 0 ("halleffect") and 10 ++ * ("halleffect1") in the ADT /buttons node. Both read low while the ++ * cover is closed (measured on a J71b). Reported as ++ * SW_MACHINE_COVER, not as a lid switch, so that closing the cover ++ * doesn't suspend the system. Each line is its own device, so that ++ * one the PMIC keeps for itself can't take the other down. ++ */ ++ smart-cover { ++ compatible = "gpio-keys-polled"; ++ poll-interval = <50>; ++ label = "iPad Smart Cover"; ++ ++ cover-switch { ++ label = "Smart Cover (PMIC GPIO 0)"; ++ gpios = <&pmu_gpio 0 GPIO_ACTIVE_LOW>; ++ linux,input-type = ; ++ linux,code = ; ++ debounce-interval = <50>; ++ }; ++ }; ++ ++ smart-cover-aux { ++ compatible = "gpio-keys-polled"; ++ poll-interval = <50>; ++ label = "iPad Smart Cover 2"; ++ ++ cover-switch { ++ label = "Smart Cover (PMIC GPIO 10)"; ++ gpios = <&pmu_gpio 10 GPIO_ACTIVE_LOW>; ++ linux,input-type = ; ++ linux,code = ; ++ debounce-interval = <50>; ++ }; ++ }; ++ + battery_info: battery { + compatible = "simple-battery"; + charge-full-design-microamp-hours = <8827000>; +@@ -136,10 +172,12 @@ + compatible = "apple,d2365-pmic-gpio"; + gpio-controller; + #gpio-cells = <2>; +- gpio-reserved-ranges = <0 13>, <15 9>; ++ gpio-reserved-ranges = <1 9>, <11 2>, <15 9>; + interrupt-controller; + #interrupt-cells = <2>; + interrupts-extended = <&pinctrl_ap 38 IRQ_TYPE_LEVEL_LOW>; ++ /* Smart Cover hall sensors (lines 0 and 10): wake only. */ ++ apple,wake-events = <0x30 0x3a>; + }; + + rtc@500 { +-- +2.54.0