Repository navigation
[Deepin-Kernel-SIG] [linux 6.6.y] Input: i8042 - skip a KBC that has no ports behind it - #2223
Conversation
The latch registers live in the SoC's LPC window, and that window does not necessarily start where the firmware places resource 0, which only describes the legacy port aperture. Reading the latch at the firmware base misses the register, so the source is never acknowledged and the level irq re-fires. Use the SoC address for the window and keep the latch offsets absolute. The firmware base stays the anchor for phytium_pio_is_lpc_mem(), which matches children against the window the firmware publishes. Signed-off-by: Wentao Guan <guanwentao@uniontech.com>
The controller reports all legacy sources in one status register and raises a single interrupt. The children used to share that irq and acknowledge their own latch bit, which only works while everyone agrees on which bit is whose and breaks whenever a bit is pending without an owner: the handler acks a latch nobody will drain and the level irq re-fires forever. Own the irq here instead. The latch is acknowledged once and the status register is demultiplexed through an irq domain, so every bit becomes a Linux irq of its own; the children are back to plain request_irq()/free_irq() and never touch the register again. A source that stays asserted after the ack shuts the line down instead of looping. The bit masks and the EC helper left over from the polling ack have no users since the shared-latch rework, so drop them too. Signed-off-by: Wentao Guan <guanwentao@uniontech.com>
A KBCI8042 node whose _CRS describes no I/O ports means nothing decodes 0x60/0x64, and the first access in i8042_probe() hangs the machine before anything can be reported. Keep probing as before by default and skip only on positive evidence: a board on the list, or a non-laptop whose ACPI node documents the controller without its ports. Signed-off-by: Wentao Guan <guanwentao@uniontech.com>
Reviewer's GuideThe PR replaces Phytium's shared PIO interrupt mechanism with a chained IRQ-domain implementation that independently dispatches and acknowledges latch sources, updates all affected consumers to use per-source IRQs, and avoids i8042 hangs by skipping firmware-described KBCs that have no backing ports. Sequence diagram for Phytium latch interrupt dispatchsequenceDiagram
participant Source as Interrupt source
participant PIO as Phytium PIO
participant Domain as IRQ domain
participant Handler as Per-source handler
Source->>PIO: Assert latch bit
PIO->>PIO: phytium_pio_irq_dispatch
PIO->>PIO: Read int_status_reg
PIO->>PIO: Write ~pending to int_clear_reg
PIO->>Domain: generic_handle_domain_irq(bit)
Domain->>Handler: Dispatch mapped Linux IRQ
PIO->>PIO: Read latch again
alt Source remains asserted repeatedly
PIO->>PIO: disable_irq_nosync
end
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
There was a problem hiding this comment.
Hey - I've found 9 issues
Prompt for AI Agents
Please address the comments from this code review:
## Individual Comments
### Comment 1
<location path="drivers/bus/phytium_pio.c" line_range="85-91" />
<code_context>
+ * A source that is still asserted after its latch was cleared cannot
+ * be acknowledged; shut the line down instead of looping forever.
+ */
+ if (again & pending && ++pio->stuck_acks > PHYTIUM_PIO_STUCK_LIMIT) {
+ pr_err("phytium-pio: latch bit 0x%x stuck, disabling irq %d\n",
+ again & pending, pio->irq);
+ disable_irq_nosync(pio->irq);
+ } else if (!(again & pending)) {
+ pio->stuck_acks = 0;
+ }
+out:
+ chained_irq_exit(chip, desc);
</code_context>
<issue_to_address>
**Normal interrupts eventually disable PIO**
When a latch bit remains asserted until its child IRQ handler services it, `again` is read before `generic_handle_domain_irq()` lets the child clear its source, so a normally serviced level-triggered interrupt increments `stuck_acks`. Since the counter resets only when that pre-dispatch read has no matching bits, ordinary interrupts accumulate until the parent IRQ is disabled, stopping all PIO children.
Check whether the source remains asserted after child dispatch, and reset the stuck counter when the child has cleared it.
</issue_to_address>
### Comment 2
<location path="drivers/input/serio/i8042-phytio.h" line_range="90-91" />
<code_context>
+{
+ bool *found = data;
+
+ if (ares->type == ACPI_RESOURCE_TYPE_IO &&
+ ares->data.io.minimum <= 0x60 && ares->data.io.maximum >= 0x64)
+ *found = true;
+
</code_context>
<issue_to_address>
**Working KBC ports go undetected**
When the KBC `_CRS` describes its ports in separate resources, uses `FIXED_IO`, or uses an I/O descriptor whose range is described by `address_length`, `phytium_i8042_io_cb()` only recognizes one `ACPI_RESOURCE_TYPE_IO` descriptor whose minimum and maximum span both ports, so `phytium_i8042_acpi_has_ports()` returns false and `i8042_platform_init()` skips the working controller, leaving keyboard or touchpad input unavailable.
Recognize the covered ports across the supported I/O and fixed-I/O resource descriptors, using their actual lengths.
Also at `drivers/input/serio/i8042-phytio.h:108`.
</issue_to_address>
### Comment 3
<location path="drivers/bus/phytium_pio.c" line_range="75-78" />
<code_context>
- unsigned long flags;
+ /* The latch is write-zero-to-clear. */
+ writel(~pending, pio->regbase + pio->int_clear_reg);
+ again = readl(pio->regbase + pio->int_status_reg);
- if (!ppio || bit >= 32)
- return;
+ bits = pending;
+ for_each_set_bit(bit, &bits, PHYTIUM_PIO_IRQ_NR)
+ generic_handle_domain_irq(pio->domain, bit);
</code_context>
<issue_to_address>
**Stuck parent interrupt keeps firing**
When a latch bit remains asserted after the stuck-ack limit is exceeded, `disable_irq_nosync()` masks the parent, but `chained_irq_exit()` unconditionally unmasks it, so the stuck interrupt storm continues.
Handle a stuck source with a mechanism that remains effective after `chained_irq_exit()` unmasks the parent.
Also at `drivers/bus/phytium_pio.c:88-93`.
</issue_to_address>
### Comment 4
<location path="drivers/bus/phytium_pio.c" line_range="85-89" />
<code_context>
+ * A source that is still asserted after its latch was cleared cannot
+ * be acknowledged; shut the line down instead of looping forever.
+ */
+ if (again & pending && ++pio->stuck_acks > PHYTIUM_PIO_STUCK_LIMIT) {
+ pr_err("phytium-pio: latch bit 0x%x stuck, disabling irq %d\n",
+ again & pending, pio->irq);
+ disable_irq_nosync(pio->irq);
+ } else if (!(again & pending)) {
+ pio->stuck_acks = 0;
+ }
</code_context>
<issue_to_address>
**One stuck source silences every device**
When any latch source remains asserted for more than `PHYTIUM_PIO_STUCK_LIMIT` acknowledgements, the handler disables `pio->irq` after a latch remains asserted, but that is the single chained parent for all latch bits; one stuck source therefore stops delivery to unrelated keyboard, UART, and EC sources too.
Quarantine the stuck source without permanently disabling delivery for the other latch bits, or provide a recovery path that reenables the parent IRQ.
Also at `drivers/bus/phytium_pio.c:339`.
</issue_to_address>
### Comment 5
<location path="drivers/tty/serial/8250/8250_pnp.c" line_range="476-478" />
<code_context>
+ if (irq >= 0) {
+ uart.port.irq = irq;
+ uart.port.flags |= UPF_SHARE_IRQ;
+ } else if (pnp_irq_valid(dev, 0)) {
+ uart.port.irq = pnp_irq(dev, 0);
+ }
}
#else
</code_context>
<issue_to_address>
**UART falls back to chained parent IRQ**
When a PNP0501 UART qualifies as a PIO UART, `phytium_pio_irq_get()` fails while the firmware IRQ is the PIO parent, and the PIO driver later claims that parent, `phytium_pnp_uart_irq()` can fail to obtain the PIO child IRQ, but `serial_pnp_probe()` then assigns the firmware IRQ directly. If that IRQ is the PIO parent and the PIO driver later installs its chained handler, the UART's direct handler is bypassed and the UART stops receiving interrupts.
Do not use the firmware parent IRQ as a fallback for a UART identified as PIO-backed; defer probing or propagate the PIO IRQ lookup failure instead.
</issue_to_address>
### Comment 6
<location path="drivers/bus/phytium_pio.c" line_range="360-368" />
<code_context>
+ if (pio && pio->domain) {
+ int bit;
+
+ irq_set_chained_handler_and_data(pio->irq, NULL, NULL);
+ for (bit = 0; bit < PHYTIUM_PIO_IRQ_NR; bit++) {
+ unsigned int virq = irq_find_mapping(pio->domain, bit);
+
+ if (virq)
+ irq_dispose_mapping(virq);
+ }
+ irq_domain_remove(pio->domain);
+ pio->domain = NULL;
+ }
+
</code_context>
<issue_to_address>
**PIO removal leaves child IRQ users active**
When the PIO ACPI device is removed while a child still has a requested IRQ, or while another child is obtaining one, `phytium_pio_remove()` detaches the parent handler and disposes the domain mappings without first stopping consumers that requested those IRQs. An active i8042, EC, or UART can therefore retain a registered action for a removed mapping, while a concurrent `phytium_pio_irq_get()` can use the domain as it is being removed; child interrupts or teardown then fail.
Ensure consumers are quiesced before removing the domain, and synchronize IRQ lookup with PIO teardown.
Also at `drivers/bus/phytium_pio.c:122-124`.
</issue_to_address>
### Comment 7
<location path="drivers/bus/phytium_pio.c" line_range="360-367" />
<code_context>
+ if (pio && pio->domain) {
+ int bit;
+
+ irq_set_chained_handler_and_data(pio->irq, NULL, NULL);
+ for (bit = 0; bit < PHYTIUM_PIO_IRQ_NR; bit++) {
+ unsigned int virq = irq_find_mapping(pio->domain, bit);
+
+ if (virq)
+ irq_dispose_mapping(virq);
+ }
+ irq_domain_remove(pio->domain);
+ pio->domain = NULL;
+ }
</code_context>
<issue_to_address>
**Removal races active latch dispatch**
When the PIO device is removed while its parent interrupt is being dispatched, `phytium_pio_remove()` clears the chained handler and immediately disposes its mappings and domain without synchronizing the parent IRQ. An already-running `phytium_pio_irq_dispatch()` can still use `pio` and `pio->domain` as teardown proceeds, causing access to released state during removal.
Disable the parent IRQ and synchronize it after detaching the chained handler, before disposing mappings or releasing the PIO state.
</issue_to_address>
### Comment 8
<location path="drivers/bus/phytium_pio.c" line_range="51-56" />
<code_context>
-EXPORT_SYMBOL(phytium_pio_clear_interrupt);
-void phytium_pio_handle_interrupt_bit(unsigned int bit)
+static struct irq_chip phytium_pio_irq_chip = {
+ .name = PHYT_PIO_DRIVER_NAME,
+ .irq_mask = phytium_pio_irq_noop,
+ .irq_unmask = phytium_pio_irq_noop,
+ .irq_ack = phytium_pio_irq_noop,
+};
+
+/* One Linux irq per latch bit, acknowledged once before the dispatch. */
</code_context>
<issue_to_address>
**Keyboard IRQs cannot wake the system**
When a Phytium i8042 port is configured as a wake source for suspend, the virtual IRQ chip has no `.irq_set_wake` callback, so `enable_irq_wake()` on the new per-source i8042 IRQs fails instead of configuring wake on the PIO parent. Phytium keyboard or touchpad input therefore cannot wake the system from suspend.
Add wake handling for the child IRQs that propagates wake configuration to the PIO parent IRQ.
</issue_to_address>
### Comment 9
<location path="drivers/bus/phytium_pio.c" line_range="292-298" />
<code_context>
- pio->regbase = devm_ioremap(dev, reg_start, reg_size);
+ /* The latch window is a SoC property, not what resource 0 describes. */
+ if (cpu_is_ft_d2000()) {
+ reg_start = PHYTIUM_PIO_D2000_BASE;
+ } else if (is_pd2408()) {
+ reg_start = PHYTIUM_PIO_D3000M_BASE;
+ } else {
+ reg_start = res->start;
+ if (resource_size(res) < PHYTIUM_PIO_LENGTH_LONG)
+ dev_warn(dev, "short window on an unknown SoC, the latch address may be wrong\n");
+ }
</code_context>
<issue_to_address>
**D3000 latch reads use firmware base**
When a D3000 is not identified by either special-case predicate and its firmware resource 0 is shorter than the LPC window, on a D3000 that is neither classified as FT D2000 nor PD2408, `phytium_pio_probe()` selects `res->start` even when resource 0 is shorter than the LPC window. The latch is then accessed at the wrong physical address, so PIO child interrupts are not acknowledged or dispatched.
Select the 0x20000000 latch base for D3000 systems as well as D2000 systems, using a reliable SoC predicate.
</issue_to_address>| if (again & pending && ++pio->stuck_acks > PHYTIUM_PIO_STUCK_LIMIT) { | ||
| pr_err("phytium-pio: latch bit 0x%x stuck, disabling irq %d\n", | ||
| again & pending, pio->irq); | ||
| disable_irq_nosync(pio->irq); | ||
| } else if (!(again & pending)) { | ||
| pio->stuck_acks = 0; | ||
| } |
There was a problem hiding this comment.
🟠 High · Normal interrupts eventually disable PIO
When a latch bit remains asserted until its child IRQ handler services it, again is read before generic_handle_domain_irq() lets the child clear its source, so a normally serviced level-triggered interrupt increments stuck_acks. Since the counter resets only when that pre-dispatch read has no matching bits, ordinary interrupts accumulate until the parent IRQ is disabled, stopping all PIO children.
Check whether the source remains asserted after child dispatch, and reset the stuck counter when the child has cleared it.
Prompt for AI agents
In `drivers/bus/phytium_pio.c` at lines 85-91:
**Normal interrupts eventually disable PIO**
When a latch bit remains asserted until its child IRQ handler services it, `again` is read before `generic_handle_domain_irq()` lets the child clear its source, so a normally serviced level-triggered interrupt increments `stuck_acks`. Since the counter resets only when that pre-dispatch read has no matching bits, ordinary interrupts accumulate until the parent IRQ is disabled, stopping all PIO children.
Check whether the source remains asserted after child dispatch, and reset the stuck counter when the child has cleared it.| if (ares->type == ACPI_RESOURCE_TYPE_IO && | ||
| ares->data.io.minimum <= 0x60 && ares->data.io.maximum >= 0x64) |
There was a problem hiding this comment.
🟠 High · Working KBC ports go undetected
When the KBC _CRS describes its ports in separate resources, uses FIXED_IO, or uses an I/O descriptor whose range is described by address_length, phytium_i8042_io_cb() only recognizes one ACPI_RESOURCE_TYPE_IO descriptor whose minimum and maximum span both ports, so phytium_i8042_acpi_has_ports() returns false and i8042_platform_init() skips the working controller, leaving keyboard or touchpad input unavailable.
Recognize the covered ports across the supported I/O and fixed-I/O resource descriptors, using their actual lengths.
Also at drivers/input/serio/i8042-phytio.h:108.
Prompt for AI agents
In `drivers/input/serio/i8042-phytio.h` at lines 90-91:
**Working KBC ports go undetected**
When the KBC `_CRS` describes its ports in separate resources, uses `FIXED_IO`, or uses an I/O descriptor whose range is described by `address_length`, `phytium_i8042_io_cb()` only recognizes one `ACPI_RESOURCE_TYPE_IO` descriptor whose minimum and maximum span both ports, so `phytium_i8042_acpi_has_ports()` returns false and `i8042_platform_init()` skips the working controller, leaving keyboard or touchpad input unavailable.
Recognize the covered ports across the supported I/O and fixed-I/O resource descriptors, using their actual lengths.
Also at `drivers/input/serio/i8042-phytio.h:108`.| again = readl(pio->regbase + pio->int_status_reg); | ||
|
|
||
| if (!ppio || bit >= 32) | ||
| return; | ||
| bits = pending; | ||
| for_each_set_bit(bit, &bits, PHYTIUM_PIO_IRQ_NR) |
There was a problem hiding this comment.
🟠 High · Stuck parent interrupt keeps firing
When a latch bit remains asserted after the stuck-ack limit is exceeded, disable_irq_nosync() masks the parent, but chained_irq_exit() unconditionally unmasks it, so the stuck interrupt storm continues.
Handle a stuck source with a mechanism that remains effective after chained_irq_exit() unmasks the parent.
Also at drivers/bus/phytium_pio.c:88-93.
Prompt for AI agents
In `drivers/bus/phytium_pio.c` at lines 75-78:
**Stuck parent interrupt keeps firing**
When a latch bit remains asserted after the stuck-ack limit is exceeded, `disable_irq_nosync()` masks the parent, but `chained_irq_exit()` unconditionally unmasks it, so the stuck interrupt storm continues.
Handle a stuck source with a mechanism that remains effective after `chained_irq_exit()` unmasks the parent.
Also at `drivers/bus/phytium_pio.c:88-93`.| if (again & pending && ++pio->stuck_acks > PHYTIUM_PIO_STUCK_LIMIT) { | ||
| pr_err("phytium-pio: latch bit 0x%x stuck, disabling irq %d\n", | ||
| again & pending, pio->irq); | ||
| disable_irq_nosync(pio->irq); | ||
| } else if (!(again & pending)) { |
There was a problem hiding this comment.
🟡 Medium · One stuck source silences every device
When any latch source remains asserted for more than PHYTIUM_PIO_STUCK_LIMIT acknowledgements, the handler disables pio->irq after a latch remains asserted, but that is the single chained parent for all latch bits; one stuck source therefore stops delivery to unrelated keyboard, UART, and EC sources too.
Quarantine the stuck source without permanently disabling delivery for the other latch bits, or provide a recovery path that reenables the parent IRQ.
Also at drivers/bus/phytium_pio.c:339.
Prompt for AI agents
In `drivers/bus/phytium_pio.c` at lines 85-89:
**One stuck source silences every device**
When any latch source remains asserted for more than `PHYTIUM_PIO_STUCK_LIMIT` acknowledgements, the handler disables `pio->irq` after a latch remains asserted, but that is the single chained parent for all latch bits; one stuck source therefore stops delivery to unrelated keyboard, UART, and EC sources too.
Quarantine the stuck source without permanently disabling delivery for the other latch bits, or provide a recovery path that reenables the parent IRQ.
Also at `drivers/bus/phytium_pio.c:339`.| } else if (pnp_irq_valid(dev, 0)) { | ||
| uart.port.irq = pnp_irq(dev, 0); | ||
| } |
There was a problem hiding this comment.
🟠 High · UART falls back to chained parent IRQ
When a PNP0501 UART qualifies as a PIO UART, phytium_pio_irq_get() fails while the firmware IRQ is the PIO parent, and the PIO driver later claims that parent, phytium_pnp_uart_irq() can fail to obtain the PIO child IRQ, but serial_pnp_probe() then assigns the firmware IRQ directly. If that IRQ is the PIO parent and the PIO driver later installs its chained handler, the UART's direct handler is bypassed and the UART stops receiving interrupts.
Do not use the firmware parent IRQ as a fallback for a UART identified as PIO-backed; defer probing or propagate the PIO IRQ lookup failure instead.
Prompt for AI agents
In `drivers/tty/serial/8250/8250_pnp.c` at lines 476-478:
**UART falls back to chained parent IRQ**
When a PNP0501 UART qualifies as a PIO UART, `phytium_pio_irq_get()` fails while the firmware IRQ is the PIO parent, and the PIO driver later claims that parent, `phytium_pnp_uart_irq()` can fail to obtain the PIO child IRQ, but `serial_pnp_probe()` then assigns the firmware IRQ directly. If that IRQ is the PIO parent and the PIO driver later installs its chained handler, the UART's direct handler is bypassed and the UART stops receiving interrupts.
Do not use the firmware parent IRQ as a fallback for a UART identified as PIO-backed; defer probing or propagate the PIO IRQ lookup failure instead.| irq_set_chained_handler_and_data(pio->irq, NULL, NULL); | ||
| for (bit = 0; bit < PHYTIUM_PIO_IRQ_NR; bit++) { | ||
| unsigned int virq = irq_find_mapping(pio->domain, bit); | ||
|
|
||
| if (virq) | ||
| irq_dispose_mapping(virq); | ||
| } | ||
| irq_domain_remove(pio->domain); | ||
| pio->domain = NULL; |
There was a problem hiding this comment.
🟡 Medium · PIO removal leaves child IRQ users active
When the PIO ACPI device is removed while a child still has a requested IRQ, or while another child is obtaining one, phytium_pio_remove() detaches the parent handler and disposes the domain mappings without first stopping consumers that requested those IRQs. An active i8042, EC, or UART can therefore retain a registered action for a removed mapping, while a concurrent phytium_pio_irq_get() can use the domain as it is being removed; child interrupts or teardown then fail.
Ensure consumers are quiesced before removing the domain, and synchronize IRQ lookup with PIO teardown.
Also at drivers/bus/phytium_pio.c:122-124.
Prompt for AI agents
In `drivers/bus/phytium_pio.c` at lines 360-368:
**PIO removal leaves child IRQ users active**
When the PIO ACPI device is removed while a child still has a requested IRQ, or while another child is obtaining one, `phytium_pio_remove()` detaches the parent handler and disposes the domain mappings without first stopping consumers that requested those IRQs. An active i8042, EC, or UART can therefore retain a registered action for a removed mapping, while a concurrent `phytium_pio_irq_get()` can use the domain as it is being removed; child interrupts or teardown then fail.
Ensure consumers are quiesced before removing the domain, and synchronize IRQ lookup with PIO teardown.
Also at `drivers/bus/phytium_pio.c:122-124`.| irq_set_chained_handler_and_data(pio->irq, NULL, NULL); | ||
| for (bit = 0; bit < PHYTIUM_PIO_IRQ_NR; bit++) { | ||
| unsigned int virq = irq_find_mapping(pio->domain, bit); | ||
|
|
||
| if (virq) | ||
| irq_dispose_mapping(virq); | ||
| } | ||
| irq_domain_remove(pio->domain); |
There was a problem hiding this comment.
🟡 Medium · Removal races active latch dispatch
When the PIO device is removed while its parent interrupt is being dispatched, phytium_pio_remove() clears the chained handler and immediately disposes its mappings and domain without synchronizing the parent IRQ. An already-running phytium_pio_irq_dispatch() can still use pio and pio->domain as teardown proceeds, causing access to released state during removal.
Disable the parent IRQ and synchronize it after detaching the chained handler, before disposing mappings or releasing the PIO state.
Prompt for AI agents
In `drivers/bus/phytium_pio.c` at lines 360-367:
**Removal races active latch dispatch**
When the PIO device is removed while its parent interrupt is being dispatched, `phytium_pio_remove()` clears the chained handler and immediately disposes its mappings and domain without synchronizing the parent IRQ. An already-running `phytium_pio_irq_dispatch()` can still use `pio` and `pio->domain` as teardown proceeds, causing access to released state during removal.
Disable the parent IRQ and synchronize it after detaching the chained handler, before disposing mappings or releasing the PIO state.| static struct irq_chip phytium_pio_irq_chip = { | ||
| .name = PHYT_PIO_DRIVER_NAME, | ||
| .irq_mask = phytium_pio_irq_noop, | ||
| .irq_unmask = phytium_pio_irq_noop, | ||
| .irq_ack = phytium_pio_irq_noop, | ||
| }; |
There was a problem hiding this comment.
🟠 High · Keyboard IRQs cannot wake the system
When a Phytium i8042 port is configured as a wake source for suspend, the virtual IRQ chip has no .irq_set_wake callback, so enable_irq_wake() on the new per-source i8042 IRQs fails instead of configuring wake on the PIO parent. Phytium keyboard or touchpad input therefore cannot wake the system from suspend.
Add wake handling for the child IRQs that propagates wake configuration to the PIO parent IRQ.
Prompt for AI agents
In `drivers/bus/phytium_pio.c` at lines 51-56:
**Keyboard IRQs cannot wake the system**
When a Phytium i8042 port is configured as a wake source for suspend, the virtual IRQ chip has no `.irq_set_wake` callback, so `enable_irq_wake()` on the new per-source i8042 IRQs fails instead of configuring wake on the PIO parent. Phytium keyboard or touchpad input therefore cannot wake the system from suspend.
Add wake handling for the child IRQs that propagates wake configuration to the PIO parent IRQ.| if (cpu_is_ft_d2000()) { | ||
| reg_start = PHYTIUM_PIO_D2000_BASE; | ||
| } else if (is_pd2408()) { | ||
| reg_start = PHYTIUM_PIO_D3000M_BASE; | ||
| } else { | ||
| reg_start = res->start; | ||
| if (resource_size(res) < PHYTIUM_PIO_LENGTH_LONG) |
There was a problem hiding this comment.
🟠 High · D3000 latch reads use firmware base
When a D3000 is not identified by either special-case predicate and its firmware resource 0 is shorter than the LPC window, on a D3000 that is neither classified as FT D2000 nor PD2408, phytium_pio_probe() selects res->start even when resource 0 is shorter than the LPC window. The latch is then accessed at the wrong physical address, so PIO child interrupts are not acknowledged or dispatched.
Select the 0x20000000 latch base for D3000 systems as well as D2000 systems, using a reliable SoC predicate.
Prompt for AI agents
In `drivers/bus/phytium_pio.c` at lines 292-298:
**D3000 latch reads use firmware base**
When a D3000 is not identified by either special-case predicate and its firmware resource 0 is shorter than the LPC window, on a D3000 that is neither classified as FT D2000 nor PD2408, `phytium_pio_probe()` selects `res->start` even when resource 0 is shorter than the LPC window. The latch is then accessed at the wrong physical address, so PIO child interrupts are not acknowledged or dispatched.
Select the 0x20000000 latch base for D3000 systems as well as D2000 systems, using a reliable SoC predicate.
Summary by Sourcery
Prevent Phytium systems with portless KBCs from probing i8042 and modernize PIO interrupt delivery for legacy devices.
New Features:
Bug Fixes:
Enhancements:
Chores: