1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * 8237A DMA controller suspend functions. |
4 | * |
5 | * Written by Pierre Ossman, 2005. |
6 | */ |
7 | |
8 | #include <linux/dmi.h> |
9 | #include <linux/init.h> |
10 | #include <linux/syscore_ops.h> |
11 | |
12 | #include <asm/dma.h> |
13 | #include <asm/x86_init.h> |
14 | |
15 | /* |
16 | * This module just handles suspend/resume issues with the |
17 | * 8237A DMA controller (used for ISA and LPC). |
18 | * Allocation is handled in kernel/dma.c and normal usage is |
19 | * in asm/dma.h. |
20 | */ |
21 | |
22 | static void i8237A_resume(void) |
23 | { |
24 | unsigned long flags; |
25 | int i; |
26 | |
27 | flags = claim_dma_lock(); |
28 | |
29 | dma_outb(value: 0, DMA1_RESET_REG); |
30 | dma_outb(value: 0, DMA2_RESET_REG); |
31 | |
32 | for (i = 0; i < 8; i++) { |
33 | set_dma_addr(dmanr: i, a: 0x000000); |
34 | /* DMA count is a bit weird so this is not 0 */ |
35 | set_dma_count(dmanr: i, count: 1); |
36 | } |
37 | |
38 | /* Enable cascade DMA or channel 0-3 won't work */ |
39 | enable_dma(dmanr: 4); |
40 | |
41 | release_dma_lock(flags); |
42 | } |
43 | |
44 | static struct syscore_ops i8237_syscore_ops = { |
45 | .resume = i8237A_resume, |
46 | }; |
47 | |
48 | static int __init i8237A_init_ops(void) |
49 | { |
50 | /* |
51 | * From SKL PCH onwards, the legacy DMA device is removed in which the |
52 | * I/O ports (81h-83h, 87h, 89h-8Bh, 8Fh) related to it are removed |
53 | * as well. All removed ports must return 0xff for a inb() request. |
54 | * |
55 | * Note: DMA_PAGE_2 (port 0x81) should not be checked for detecting |
56 | * the presence of DMA device since it may be used by BIOS to decode |
57 | * LPC traffic for POST codes. Original LPC only decodes one byte of |
58 | * port 0x80 but some BIOS may choose to enhance PCH LPC port 0x8x |
59 | * decoding. |
60 | */ |
61 | if (dma_inb(DMA_PAGE_0) == 0xFF) |
62 | return -ENODEV; |
63 | |
64 | /* |
65 | * It is not required to load this driver as newer SoC may not |
66 | * support 8237 DMA or bus mastering from LPC. Platform firmware |
67 | * must announce the support for such legacy devices via |
68 | * ACPI_FADT_LEGACY_DEVICES field in FADT table. |
69 | */ |
70 | if (x86_pnpbios_disabled() && dmi_get_bios_year() >= 2017) |
71 | return -ENODEV; |
72 | |
73 | register_syscore_ops(ops: &i8237_syscore_ops); |
74 | return 0; |
75 | } |
76 | device_initcall(i8237A_init_ops); |
77 | |