blob: c8b0760a27dedbc13839f2723e8a6ee1a54630df [file] [log] [blame]
Kyösti Mälkki7b73e8522022-11-08 04:43:41 +00001/* SPDX-License-Identifier: GPL-2.0-only */
2
3#include <arch/hpet.h>
4#include <arch/io.h>
5#include <arch/ioapic.h>
6#include <console/console.h>
Kyösti Mälkki560c3f52022-01-18 04:25:48 +02007#include <cpu/x86/smm.h>
Kyösti Mälkki7b73e8522022-11-08 04:43:41 +00008#include <device/device.h>
9#include <device/pci.h>
10#include <device/pci_ids.h>
11#include <device/pci_ops.h>
12#include <option.h>
Kyösti Mälkki7b73e8522022-11-08 04:43:41 +000013#include <pc80/i8259.h>
Elyes Haouas357c2292022-11-10 08:50:22 +010014#include <pc80/isa-dma.h>
15#include <pc80/mc146818rtc.h>
16#include <types.h>
17
Kyösti Mälkki7b73e8522022-11-08 04:43:41 +000018#include "chip.h"
19#include "i82801dx.h"
20
21#define NMI_OFF 0
22
23typedef struct southbridge_intel_i82801dx_config config_t;
24
25/**
Kyösti Mälkki7b73e8522022-11-08 04:43:41 +000026 * Set miscellaneous static southbridge features.
27 *
28 * @param dev PCI device with I/O APIC control registers
29 */
30static void i82801dx_enable_ioapic(struct device *dev)
31{
32 u32 reg32;
33
34 reg32 = pci_read_config32(dev, GEN_CNTL);
35 reg32 |= (1 << 13); /* Coprocessor error enable (COPR_ERR_EN) */
36 reg32 |= (3 << 7); /* IOAPIC enable (APIC_EN) */
37 reg32 |= (1 << 2); /* DMA collection buffer enable (DCB_EN) */
38 reg32 |= (1 << 1); /* Delayed transaction enable (DTE) */
39 pci_write_config32(dev, GEN_CNTL, reg32);
40 printk(BIOS_DEBUG, "IOAPIC Southbridge enabled %x\n", reg32);
41
Felix Held0d192892024-02-06 16:55:29 +010042 register_new_ioapic_gsi0(IO_APIC_ADDR);
Kyösti Mälkki7b73e8522022-11-08 04:43:41 +000043
Felix Held0d192892024-02-06 16:55:29 +010044 ioapic_set_boot_config(IO_APIC_ADDR, true);
Kyösti Mälkki7b73e8522022-11-08 04:43:41 +000045}
46
47static void i82801dx_enable_serial_irqs(struct device *dev)
48{
49 /* Set packet length and toggle silent mode bit. */
50 pci_write_config8(dev, SERIRQ_CNTL,
51 (1 << 7) | (1 << 6) | ((21 - 17) << 2) | (0 << 0));
52 pci_write_config8(dev, SERIRQ_CNTL,
53 (1 << 7) | (0 << 6) | ((21 - 17) << 2) | (0 << 0));
54}
55
56static void i82801dx_pirq_init(struct device *dev)
57{
58 /* Get the chip configuration */
59 config_t *config = dev->chip_info;
60
61 pci_write_config8(dev, PIRQA_ROUT, config->pirqa_routing);
62 pci_write_config8(dev, PIRQB_ROUT, config->pirqb_routing);
63 pci_write_config8(dev, PIRQC_ROUT, config->pirqc_routing);
64 pci_write_config8(dev, PIRQD_ROUT, config->pirqd_routing);
65 pci_write_config8(dev, PIRQE_ROUT, config->pirqe_routing);
66 pci_write_config8(dev, PIRQF_ROUT, config->pirqf_routing);
67 pci_write_config8(dev, PIRQG_ROUT, config->pirqg_routing);
68 pci_write_config8(dev, PIRQH_ROUT, config->pirqh_routing);
69}
70
71static void i82801dx_power_options(struct device *dev)
72{
73 u8 reg8;
74 u16 reg16, pmbase;
75 u32 reg32;
76 const char *state;
77
78 /* Which state do we want to goto after g3 (power restored)?
79 * 0 == S0 Full On
80 * 1 == S5 Soft Off
81 *
82 * If the option is not existent (Laptops), use MAINBOARD_POWER_ON.
83 */
84 const unsigned int pwr_on = get_uint_option("power_on_after_fail", MAINBOARD_POWER_ON);
85
86 reg8 = pci_read_config8(dev, GEN_PMCON_3);
87 reg8 &= 0xfe;
88 switch (pwr_on) {
89 case MAINBOARD_POWER_OFF:
90 reg8 |= 1;
91 state = "off";
92 break;
93 case MAINBOARD_POWER_ON:
94 reg8 &= ~1;
95 state = "on";
96 break;
97 case MAINBOARD_POWER_KEEP:
98 reg8 &= ~1;
99 state = "state keep";
100 break;
101 default:
102 state = "undefined";
103 }
104
105 reg8 &= ~(1 << 3); /* minimum assertion is 1 to 2 RTCCLK */
106
107 pci_write_config8(dev, GEN_PMCON_3, reg8);
108 printk(BIOS_INFO, "Set power %s after power failure.\n", state);
109
110 /* Set up NMI on errors. */
111 reg8 = inb(0x61);
112 reg8 &= 0x0f; /* Higher Nibble must be 0 */
113 reg8 &= ~(1 << 3); /* IOCHK# NMI Enable */
114 // reg8 &= ~(1 << 2); /* PCI SERR# Enable */
115 reg8 |= (1 << 2); /* PCI SERR# Disable for now */
116 outb(reg8, 0x61);
117
118 reg8 = inb(0x70);
119 const unsigned int nmi_option = get_uint_option("nmi", NMI_OFF);
120 if (nmi_option) {
121 printk(BIOS_INFO, "NMI sources enabled.\n");
122 reg8 &= ~(1 << 7); /* Set NMI. */
123 } else {
124 printk(BIOS_INFO, "NMI sources disabled.\n");
125 reg8 |= (1 << 7); /* Disable NMI. */
126 }
127 outb(reg8, 0x70);
128
129 /* Set SMI# rate down and enable CPU_SLP# */
130 reg16 = pci_read_config16(dev, GEN_PMCON_1);
131 reg16 &= ~(3 << 0); // SMI# rate 1 minute
132 reg16 |= (1 << 5); // CPUSLP_EN Desktop only
133 pci_write_config16(dev, GEN_PMCON_1, reg16);
134
135 pmbase = pci_read_config16(dev, 0x40) & 0xfffe;
136
137 /* Set up power management block and determine sleep mode */
138 reg32 = inl(pmbase + 0x04); // PM1_CNT
139
140 reg32 &= ~(7 << 10); // SLP_TYP
141 reg32 |= (1 << 0); // SCI_EN
142 outl(reg32, pmbase + 0x04);
143}
144
Kyösti Mälkki7b73e8522022-11-08 04:43:41 +0000145
146static void i82801dx_rtc_init(struct device *dev)
147{
148 u8 reg8;
149 u32 reg32;
150 int rtc_failed;
151
152 reg8 = pci_read_config8(dev, GEN_PMCON_3);
153 rtc_failed = reg8 & RTC_BATTERY_DEAD;
154 if (rtc_failed) {
155 reg8 &= ~(1 << 1); /* Preserve the power fail state. */
156 pci_write_config8(dev, GEN_PMCON_3, reg8);
157 }
158 reg32 = pci_read_config32(dev, GEN_STS);
159 rtc_failed |= reg32 & (1 << 2);
160 cmos_init(rtc_failed);
161
162 /* Enable access to the upper 128 byte bank of CMOS RAM. */
163 pci_write_config8(dev, RTC_CONF, 0x04);
164}
165
Kyösti Mälkki560c3f52022-01-18 04:25:48 +0200166static void i82801dx_set_acpi_mode(struct device *dev)
167{
168 if (!acpi_is_wakeup_s3()) {
169 apm_control(APM_CNT_ACPI_DISABLE);
170 } else {
171 apm_control(APM_CNT_ACPI_ENABLE);
172 }
173}
174
Kyösti Mälkki7b73e8522022-11-08 04:43:41 +0000175static void i82801dx_lpc_route_dma(struct device *dev, u8 mask)
176{
177 u16 reg16;
178 int i;
179
180 reg16 = pci_read_config16(dev, PCI_DMA_CFG);
181 reg16 &= 0x300;
182 for (i = 0; i < 8; i++) {
183 if (i == 4)
184 continue;
185 reg16 |= ((mask & (1 << i)) ? 3 : 1) << (i * 2);
186 }
187 pci_write_config16(dev, PCI_DMA_CFG, reg16);
188}
189
Kyösti Mälkki7b73e8522022-11-08 04:43:41 +0000190/* ICH4 does not mention HPET in the docs, but
191 * all ICH3 and ICH4 do have HPETs built in.
192 */
193static void enable_hpet(struct device *dev)
194{
195 u32 reg32, hpet, val;
196
197 /* Set HPET base address and enable it */
198 printk(BIOS_DEBUG, "Enabling HPET at 0x%x\n", HPET_BASE_ADDRESS);
199 reg32 = pci_read_config32(dev, GEN_CNTL);
200 /*
201 * Bit 17 is HPET enable bit.
202 * Bit 16:15 control the HPET base address.
203 */
204 reg32 &= ~(3 << 15); /* Clear it */
205
206 hpet = HPET_BASE_ADDRESS >> 12;
207 hpet &= 0x3;
208
209 reg32 |= (hpet << 15);
210 reg32 |= (1 << 17); /* Enable HPET. */
211 pci_write_config32(dev, GEN_CNTL, reg32);
212
213 /* Check to see whether it took */
214 reg32 = pci_read_config32(dev, GEN_CNTL);
215 val = reg32 >> 15;
216 val &= 0x7;
217
218 if ((val & 0x4) && (hpet == (val & 0x3))) {
219 printk(BIOS_INFO, "HPET enabled at 0x%x\n", HPET_BASE_ADDRESS);
220 } else {
221 printk(BIOS_WARNING, "HPET was not enabled correctly\n");
222 reg32 &= ~(1 << 17); /* Clear Enable */
223 pci_write_config32(dev, GEN_CNTL, reg32);
224 }
225}
226
227static void lpc_init(struct device *dev)
228{
Kyösti Mälkki7b73e8522022-11-08 04:43:41 +0000229 /* IO APIC initialization. */
230 i82801dx_enable_ioapic(dev);
231
232 i82801dx_enable_serial_irqs(dev);
233
234 /* Setup the PIRQ. */
235 i82801dx_pirq_init(dev);
236
237 /* Setup power options. */
238 i82801dx_power_options(dev);
239
Kyösti Mälkki7b73e8522022-11-08 04:43:41 +0000240 /* Initialize the real time clock. */
241 i82801dx_rtc_init(dev);
242
243 /* Route DMA. */
244 i82801dx_lpc_route_dma(dev, 0xff);
245
246 /* Initialize ISA DMA. */
247 isa_dma_init();
248
Kyösti Mälkki7b73e8522022-11-08 04:43:41 +0000249 /* Initialize the High Precision Event Timers */
250 enable_hpet(dev);
251
252 setup_i8259();
Kyösti Mälkki560c3f52022-01-18 04:25:48 +0200253
254 i82801dx_set_acpi_mode(dev);
Kyösti Mälkki7b73e8522022-11-08 04:43:41 +0000255}
256
257static void i82801dx_lpc_read_resources(struct device *dev)
258{
259 struct resource *res;
260
261 /* Get the normal PCI resources of this device. */
262 pci_dev_read_resources(dev);
263
264 /* Add an extra subtractive resource for both memory and I/O. */
265 res = new_resource(dev, IOINDEX_SUBTRACTIVE(0, 0));
266 res->base = 0;
267 res->size = 0x1000;
268 res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
269 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
270
271 res = new_resource(dev, IOINDEX_SUBTRACTIVE(1, 0));
272 res->base = 0xff800000;
273 res->size = 0x00800000; /* 8 MB for flash */
274 res->flags = IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE |
275 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
276
277 res = new_resource(dev, 3); /* IOAPIC */
278 res->base = IO_APIC_ADDR;
279 res->size = 0x00001000;
280 res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
281}
282
283static struct device_operations lpc_ops = {
284 .read_resources = i82801dx_lpc_read_resources,
285 .set_resources = pci_dev_set_resources,
286 .enable_resources = pci_dev_enable_resources,
287 .init = lpc_init,
288 .scan_bus = scan_static_bus,
289 .enable = i82801dx_enable,
290};
291
292/* 82801DB/DBL */
293static const struct pci_driver lpc_driver_db __pci_driver = {
294 .ops = &lpc_ops,
295 .vendor = PCI_VID_INTEL,
296 .device = PCI_DID_INTEL_82801DB_LPC,
297};
298
299/* 82801DBM */
300static const struct pci_driver lpc_driver_dbm __pci_driver = {
301 .ops = &lpc_ops,
302 .vendor = PCI_VID_INTEL,
303 .device = PCI_DID_INTEL_82801DBM_LPC,
304};