blob: af65dbbadf6ccb52e9dc09ac5a7cfb2a4ba0fc06 [file] [log] [blame]
Kyösti Mälkki88decca2023-04-28 07:04:34 +03001/* SPDX-License-Identifier: GPL-2.0-only */
2
3#include <acpi/acpi.h>
4#include <console/console.h>
5#include <stdint.h>
6
7static void fill_x_pm_io(acpi_addr_t *x_pm_blk, int access_size, uint16_t ioport, uint8_t len)
8{
9 x_pm_blk->space_id = ACPI_ADDRESS_SPACE_IO;
10 x_pm_blk->bit_width = len * 8;
11 x_pm_blk->bit_offset = 0;
12 x_pm_blk->access_size = access_size;
13 x_pm_blk->addrl = ioport;
14 x_pm_blk->addrh = 0x0;
15}
16
17static void do_sanity_error(const char *func, const int line)
18{
19 printk(BIOS_ERR, "ACPI: FADT error detected, %s line %d.\n", func, line);
20}
21
22#define fadt_sanity(x) do { if (!(x)) do_sanity_error(__func__, __LINE__); } while (0)
23
24void fill_fadt_extended_pm_io(acpi_fadt_t *fadt)
25{
26 fadt_sanity(fadt->pm1a_evt_blk && (fadt->pm1_evt_len >= 4));
27
28 /* Upper word is reserved and Linux complains about 32 bit. */
29 fadt_sanity(fadt->pm1a_cnt_blk && (fadt->pm1_cnt_len == 2));
30
31 fill_x_pm_io(&fadt->x_pm1a_evt_blk, ACPI_ACCESS_SIZE_WORD_ACCESS,
32 fadt->pm1a_evt_blk, fadt->pm1_evt_len);
33
34 fill_x_pm_io(&fadt->x_pm1a_cnt_blk, ACPI_ACCESS_SIZE_WORD_ACCESS,
35 fadt->pm1a_cnt_blk, fadt->pm1_cnt_len);
36
37 if (fadt->pm1b_evt_blk)
38 fill_x_pm_io(&fadt->x_pm1b_evt_blk, ACPI_ACCESS_SIZE_WORD_ACCESS,
39 fadt->pm1b_evt_blk, fadt->pm1_evt_len);
40
41 if (fadt->pm1b_cnt_blk)
42 fill_x_pm_io(&fadt->x_pm1b_cnt_blk, ACPI_ACCESS_SIZE_WORD_ACCESS,
43 fadt->pm1b_cnt_blk, fadt->pm1_cnt_len);
44
45 if (fadt->pm_tmr_blk) {
46 fadt_sanity(fadt->pm_tmr_len == 4);
47 fill_x_pm_io(&fadt->x_pm_tmr_blk, ACPI_ACCESS_SIZE_DWORD_ACCESS,
48 fadt->pm_tmr_blk, fadt->pm_tmr_len);
49 }
50
51 if (fadt->pm2_cnt_blk)
52 fill_x_pm_io(&fadt->x_pm2_cnt_blk, ACPI_ACCESS_SIZE_BYTE_ACCESS,
53 fadt->pm2_cnt_blk, fadt->pm2_cnt_len);
54
55 /*
56 * Windows 10 requires x_gpe0_blk to be set starting with FADT revision 5.
57 * The bit_width field intentionally overflows here.
58 * The OSPM can instead use the values in `fadt->gpe0_blk{,_len}`, which
59 * seems to work fine on Linux 5.0 and Windows 10.
60 *
61 * FIXME: GPE1_BASE is not initialised.
62 *
63 */
64
65 if (fadt->gpe0_blk)
66 fill_x_pm_io(&fadt->x_gpe0_blk, ACPI_ACCESS_SIZE_BYTE_ACCESS,
67 fadt->gpe0_blk, fadt->gpe0_blk_len);
68
69 if (fadt->gpe1_blk)
70 fill_x_pm_io(&fadt->x_gpe1_blk, ACPI_ACCESS_SIZE_BYTE_ACCESS,
71 fadt->gpe1_blk, fadt->gpe1_blk_len);
72}