1 /* SPDX-License-Identifier: GPL-2.0-only */
2
3 #include <acpi/acpi.h>
4 #include <arch/io.h>
5 #include <arch/ioapic.h>
6 #include <assert.h>
7 #include <bootmode.h>
8 #include <device/pci_ops.h>
9 #include <device/pci_type.h>
10 #include <halt.h>
11 #include <stdint.h>
12
13 #include "pmbase.h"
14 #include "pmutil.h"
15
16 /* LPC PM Base Address Register */
17 #define PMBASE 0x40
18 #define PMSIZE 0x80
19
lpc_get_pmbase(void)20 u16 lpc_get_pmbase(void)
21 {
22 #ifdef __SIMPLE_DEVICE__
23 /* Don't assume PMBASE is still the same */
24 return pci_read_config16(PCI_DEV(0, 0x1f, 0), PMBASE) & 0xfffc;
25 #else
26 static u16 pmbase;
27
28 if (pmbase)
29 return pmbase;
30
31 pmbase = pci_read_config16(pcidev_on_root(0x1f, 0), PMBASE) & 0xfffc;
32
33 return pmbase;
34 #endif
35 }
36
write_pmbase32(const u8 addr,const u32 val)37 void write_pmbase32(const u8 addr, const u32 val)
38 {
39 ASSERT(addr <= (PMSIZE - sizeof(u32)));
40
41 outl(val, lpc_get_pmbase() + addr);
42 }
43
write_pmbase16(const u8 addr,const u16 val)44 void write_pmbase16(const u8 addr, const u16 val)
45 {
46 ASSERT(addr <= (PMSIZE - sizeof(u16)));
47
48 outw(val, lpc_get_pmbase() + addr);
49 }
50
write_pmbase8(const u8 addr,const u8 val)51 void write_pmbase8(const u8 addr, const u8 val)
52 {
53 ASSERT(addr <= (PMSIZE - sizeof(u8)));
54
55 outb(val, lpc_get_pmbase() + addr);
56 }
57
read_pmbase32(const u8 addr)58 u32 read_pmbase32(const u8 addr)
59 {
60 ASSERT(addr <= (PMSIZE - sizeof(u32)));
61
62 return inl(lpc_get_pmbase() + addr);
63 }
64
read_pmbase16(const u8 addr)65 u16 read_pmbase16(const u8 addr)
66 {
67 ASSERT(addr <= (PMSIZE - sizeof(u16)));
68
69 return inw(lpc_get_pmbase() + addr);
70 }
71
read_pmbase8(const u8 addr)72 u8 read_pmbase8(const u8 addr)
73 {
74 ASSERT(addr <= (PMSIZE - sizeof(u8)));
75
76 return inb(lpc_get_pmbase() + addr);
77 }
78
acpi_get_sleep_type(void)79 int acpi_get_sleep_type(void)
80 {
81 return acpi_sleep_from_pm1(read_pmbase32(PM1_CNT));
82 }
83
84 /*
85 * Note that southbridge_detect_s3_resume clears the sleep state,
86 * so this may not be used reliable throughout romstage.
87 */
platform_is_resuming(void)88 int platform_is_resuming(void)
89 {
90 u16 reg16 = read_pmbase16(PM1_STS);
91
92 if (!(reg16 & WAK_STS))
93 return 0;
94
95 return acpi_get_sleep_type() == ACPI_S3;
96 }
97
poweroff(void)98 void poweroff(void)
99 {
100 uint32_t pm1_cnt;
101
102 /* Go to S5 */
103 pm1_cnt = read_pmbase32(PM1_CNT);
104 pm1_cnt |= (0xf << 10);
105 write_pmbase32(PM1_CNT, pm1_cnt);
106 }
107
108 #define ACPI_SCI_IRQ 9
109
ioapic_get_sci_pin(u8 * gsi,u8 * irq,u8 * flags)110 void ioapic_get_sci_pin(u8 *gsi, u8 *irq, u8 *flags)
111 {
112 *gsi = ACPI_SCI_IRQ;
113 *irq = ACPI_SCI_IRQ;
114 *flags = MP_IRQ_TRIGGER_LEVEL | MP_IRQ_POLARITY_HIGH;
115 }
116