blob: 072f60b106b7e866b08bdfefabe2a5dc4ee194a8 [file] [log] [blame]
Angel Pons182dbde2020-04-02 23:49:05 +02001/* SPDX-License-Identifier: GPL-2.0-only */
2/* This file is part of the coreboot project. */
Patrick Georgie72a8a32012-11-06 11:05:09 +01003
4#include <console/console.h>
5#include <device/device.h>
6#include <device/pci.h>
7#include <device/pci_ids.h>
Kyösti Mälkkicbf95712020-01-05 08:05:45 +02008#include <option.h>
Patrick Georgie72a8a32012-11-06 11:05:09 +01009#include <pc80/mc146818rtc.h>
10#include <pc80/isa-dma.h>
11#include <pc80/i8259.h>
12#include <arch/io.h>
Kyösti Mälkkif1b58b72019-03-01 13:43:02 +020013#include <device/pci_ops.h>
Patrick Georgie72a8a32012-11-06 11:05:09 +010014#include <arch/ioapic.h>
Furquan Shaikh76cedd22020-05-02 10:24:23 -070015#include <acpi/acpi.h>
Patrick Georgie72a8a32012-11-06 11:05:09 +010016#include <cpu/x86/smm.h>
Furquan Shaikh76cedd22020-05-02 10:24:23 -070017#include <acpi/acpigen.h>
Vladimir Serbinenko33769a52014-08-30 22:39:20 +020018#include <cbmem.h>
19#include <string.h>
Kyösti Mälkki12b121c2019-08-18 16:33:39 +030020#include "chip.h"
Patrick Georgie72a8a32012-11-06 11:05:09 +010021#include "i82801ix.h"
Vladimir Serbinenko33769a52014-08-30 22:39:20 +020022#include "nvs.h"
Vladimir Serbinenko36fa5b82014-10-28 23:43:20 +010023#include <southbridge/intel/common/pciehp.h>
Arthur Heymanse798e6a2017-12-23 23:09:54 +010024#include <southbridge/intel/common/acpi_pirq_gen.h>
Patrick Georgie72a8a32012-11-06 11:05:09 +010025
26#define NMI_OFF 0
27
Patrick Georgie72a8a32012-11-06 11:05:09 +010028typedef struct southbridge_intel_i82801ix_config config_t;
29
30static void i82801ix_enable_apic(struct device *dev)
31{
Patrick Georgie72a8a32012-11-06 11:05:09 +010032 u32 reg32;
33 volatile u32 *ioapic_index = (volatile u32 *)(IO_APIC_ADDR);
34 volatile u32 *ioapic_data = (volatile u32 *)(IO_APIC_ADDR + 0x10);
35
36 /* Enable IOAPIC. Keep APIC Range Select at zero. */
37 RCBA8(0x31ff) = 0x03;
38 /* We have to read 0x31ff back if bit0 changed. */
Paul Menzeld0299e42013-10-21 09:28:19 +020039 RCBA8(0x31ff);
Patrick Georgie72a8a32012-11-06 11:05:09 +010040
41 /* Lock maximum redirection entries (MRE), R/WO register. */
42 *ioapic_index = 0x01;
43 reg32 = *ioapic_data;
44 *ioapic_index = 0x01;
45 *ioapic_data = reg32;
46
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -080047 setup_ioapic(VIO_APIC_VADDR, 2); /* ICH7 code uses id 2. */
Patrick Georgie72a8a32012-11-06 11:05:09 +010048}
49
50static void i82801ix_enable_serial_irqs(struct device *dev)
51{
52 /* Set packet length and toggle silent mode bit for one frame. */
53 pci_write_config8(dev, D31F0_SERIRQ_CNTL,
54 (1 << 7) | (1 << 6) | ((21 - 17) << 2) | (0 << 0));
55}
56
57/* PIRQ[n]_ROUT[3:0] - PIRQ Routing Control
58 * 0x00 - 0000 = Reserved
59 * 0x01 - 0001 = Reserved
60 * 0x02 - 0010 = Reserved
61 * 0x03 - 0011 = IRQ3
62 * 0x04 - 0100 = IRQ4
63 * 0x05 - 0101 = IRQ5
64 * 0x06 - 0110 = IRQ6
65 * 0x07 - 0111 = IRQ7
66 * 0x08 - 1000 = Reserved
67 * 0x09 - 1001 = IRQ9
68 * 0x0A - 1010 = IRQ10
69 * 0x0B - 1011 = IRQ11
70 * 0x0C - 1100 = IRQ12
71 * 0x0D - 1101 = Reserved
72 * 0x0E - 1110 = IRQ14
73 * 0x0F - 1111 = IRQ15
74 * PIRQ[n]_ROUT[7] - PIRQ Routing Control
75 * 0x80 - The PIRQ is not routed.
76 */
77
Elyes HAOUAS8aa50732018-05-13 13:34:58 +020078static void i82801ix_pirq_init(struct device *dev)
Patrick Georgie72a8a32012-11-06 11:05:09 +010079{
Elyes HAOUAS8aa50732018-05-13 13:34:58 +020080 struct device *irq_dev;
Patrick Georgie72a8a32012-11-06 11:05:09 +010081 /* Get the chip configuration */
82 config_t *config = dev->chip_info;
83
84 pci_write_config8(dev, D31F0_PIRQA_ROUT, config->pirqa_routing);
85 pci_write_config8(dev, D31F0_PIRQB_ROUT, config->pirqb_routing);
86 pci_write_config8(dev, D31F0_PIRQC_ROUT, config->pirqc_routing);
87 pci_write_config8(dev, D31F0_PIRQD_ROUT, config->pirqd_routing);
88
89 pci_write_config8(dev, D31F0_PIRQE_ROUT, config->pirqe_routing);
90 pci_write_config8(dev, D31F0_PIRQF_ROUT, config->pirqf_routing);
91 pci_write_config8(dev, D31F0_PIRQG_ROUT, config->pirqg_routing);
92 pci_write_config8(dev, D31F0_PIRQH_ROUT, config->pirqh_routing);
93
94 /* Eric Biederman once said we should let the OS do this.
95 * I am not so sure anymore he was right.
96 */
97
Elyes HAOUASba28e8d2016-08-31 19:22:16 +020098 for (irq_dev = all_devices; irq_dev; irq_dev = irq_dev->next) {
Patrick Georgie72a8a32012-11-06 11:05:09 +010099 u8 int_pin=0, int_line=0;
100
101 if (!irq_dev->enabled || irq_dev->path.type != DEVICE_PATH_PCI)
102 continue;
103
104 int_pin = pci_read_config8(irq_dev, PCI_INTERRUPT_PIN);
105
106 switch (int_pin) {
107 case 1: /* INTA# */ int_line = config->pirqa_routing; break;
108 case 2: /* INTB# */ int_line = config->pirqb_routing; break;
109 case 3: /* INTC# */ int_line = config->pirqc_routing; break;
110 case 4: /* INTD# */ int_line = config->pirqd_routing; break;
111 }
112
113 if (!int_line)
114 continue;
115
116 pci_write_config8(irq_dev, PCI_INTERRUPT_LINE, int_line);
117 }
118}
119
Elyes HAOUAS8aa50732018-05-13 13:34:58 +0200120static void i82801ix_gpi_routing(struct device *dev)
Patrick Georgie72a8a32012-11-06 11:05:09 +0100121{
122 /* Get the chip configuration */
123 config_t *config = dev->chip_info;
124 u32 reg32 = 0;
125
126 /* An array would be much nicer here, or some
127 * other method of doing this.
128 */
129 reg32 |= (config->gpi0_routing & 0x03) << 0;
130 reg32 |= (config->gpi1_routing & 0x03) << 2;
131 reg32 |= (config->gpi2_routing & 0x03) << 4;
132 reg32 |= (config->gpi3_routing & 0x03) << 6;
133 reg32 |= (config->gpi4_routing & 0x03) << 8;
134 reg32 |= (config->gpi5_routing & 0x03) << 10;
135 reg32 |= (config->gpi6_routing & 0x03) << 12;
136 reg32 |= (config->gpi7_routing & 0x03) << 14;
137 reg32 |= (config->gpi8_routing & 0x03) << 16;
138 reg32 |= (config->gpi9_routing & 0x03) << 18;
139 reg32 |= (config->gpi10_routing & 0x03) << 20;
140 reg32 |= (config->gpi11_routing & 0x03) << 22;
141 reg32 |= (config->gpi12_routing & 0x03) << 24;
142 reg32 |= (config->gpi13_routing & 0x03) << 26;
143 reg32 |= (config->gpi14_routing & 0x03) << 28;
144 reg32 |= (config->gpi15_routing & 0x03) << 30;
145
146 pci_write_config32(dev, D31F0_GPIO_ROUT, reg32);
147}
148
Elyes HAOUAS8aa50732018-05-13 13:34:58 +0200149static void i82801ix_power_options(struct device *dev)
Patrick Georgie72a8a32012-11-06 11:05:09 +0100150{
151 u8 reg8;
152 u16 reg16, pmbase;
153 u32 reg32;
154 const char *state;
155 /* Get the chip configuration */
156 config_t *config = dev->chip_info;
157
Nico Huber9faae2b2018-11-14 00:00:35 +0100158 int pwr_on = CONFIG_MAINBOARD_POWER_FAILURE_STATE;
Patrick Georgie72a8a32012-11-06 11:05:09 +0100159 int nmi_option;
160
161 /* BIOS must program... */
162 reg32 = pci_read_config32(dev, 0xac);
163 pci_write_config32(dev, 0xac, reg32 | (1 << 30) | (3 << 8));
164
165 /* Which state do we want to goto after g3 (power restored)?
166 * 0 == S0 Full On
167 * 1 == S5 Soft Off
168 *
169 * If the option is not existent (Laptops), use MAINBOARD_POWER_ON.
170 */
Varad Gautam06ef0462015-03-11 09:54:41 +0530171 pwr_on = MAINBOARD_POWER_ON;
172 get_option(&pwr_on, "power_on_after_fail");
Patrick Georgie72a8a32012-11-06 11:05:09 +0100173
174 reg8 = pci_read_config8(dev, D31F0_GEN_PMCON_3);
175 reg8 &= 0xfe;
176 switch (pwr_on) {
177 case MAINBOARD_POWER_OFF:
178 reg8 |= 1;
179 state = "off";
180 break;
181 case MAINBOARD_POWER_ON:
182 reg8 &= ~1;
183 state = "on";
184 break;
185 case MAINBOARD_POWER_KEEP:
186 reg8 &= ~1;
187 state = "state keep";
188 break;
189 default:
190 state = "undefined";
191 }
192
193 reg8 |= (3 << 4); /* avoid #S4 assertions */
194 reg8 &= ~(1 << 3); /* minimum asssertion is 1 to 2 RTCCLK */
195
196 pci_write_config8(dev, D31F0_GEN_PMCON_3, reg8);
197 printk(BIOS_INFO, "Set power %s after power failure.\n", state);
198
199 /* Set up NMI on errors. */
200 reg8 = inb(0x61);
201 reg8 &= 0x0f; /* Higher Nibble must be 0 */
202 reg8 &= ~(1 << 3); /* IOCHK# NMI Enable */
203 // reg8 &= ~(1 << 2); /* PCI SERR# Enable */
204 reg8 |= (1 << 2); /* PCI SERR# Disable for now */
205 outb(reg8, 0x61);
206
207 reg8 = inb(0x74); /* Read from 0x74 as 0x70 is write only. */
208 nmi_option = NMI_OFF;
209 get_option(&nmi_option, "nmi");
210 if (nmi_option) {
211 printk(BIOS_INFO, "NMI sources enabled.\n");
212 reg8 &= ~(1 << 7); /* Set NMI. */
213 } else {
214 printk(BIOS_INFO, "NMI sources disabled.\n");
Elyes HAOUAS9c5d4632018-04-26 22:21:21 +0200215 reg8 |= (1 << 7); /* Can't mask NMI from PCI-E and NMI_NOW */
Patrick Georgie72a8a32012-11-06 11:05:09 +0100216 }
217 outb(reg8, 0x70);
218
219 /* Enable CPU_SLP# and Intel Speedstep, set SMI# rate down */
220 reg16 = pci_read_config16(dev, D31F0_GEN_PMCON_1);
221 reg16 &= ~(3 << 0); // SMI# rate 1 minute
222 reg16 |= (1 << 2); // CLKRUN_EN - Mobile/Ultra only
223 reg16 |= (1 << 3); // Speedstep Enable - Mobile/Ultra only
224 reg16 |= (1 << 5); // CPUSLP_EN Desktop only
225
226 if (config->c4onc3_enable)
227 reg16 |= (1 << 7);
228
229 // another laptop wants this?
230 // reg16 &= ~(1 << 10); // BIOS_PCI_EXP_EN - Desktop/Mobile only
231 reg16 |= (1 << 10); // BIOS_PCI_EXP_EN - Desktop/Mobile only
232#if DEBUG_PERIODIC_SMIS
233 /* Set DEBUG_PERIODIC_SMIS in i82801ix.h to debug using
234 * periodic SMIs.
235 */
236 reg16 |= (3 << 0); // Periodic SMI every 8s
237#endif
238 if (config->c5_enable)
239 reg16 |= (1 << 11); /* Enable C5, C6 and PMSYNC# */
240 pci_write_config16(dev, D31F0_GEN_PMCON_1, reg16);
241
242 /* Set exit timings for C5/C6. */
243 if (config->c5_enable) {
244 reg8 = pci_read_config8(dev, D31F0_C5_EXIT_TIMING);
245 reg8 &= ~((7 << 3) | (7 << 0));
246 if (config->c6_enable)
247 reg8 |= (5 << 3) | (3 << 0); /* 38-44us PMSYNC# to STPCLK#,
248 95-102us DPRSTP# to STP_CPU# */
249 else
250 reg8 |= (0 << 3) | (1 << 0); /* 16-17us PMSYNC# to STPCLK#,
251 34-40us DPRSTP# to STP_CPU# */
252 pci_write_config8(dev, D31F0_C5_EXIT_TIMING, reg8);
253 }
254
255 // Set the board's GPI routing.
256 i82801ix_gpi_routing(dev);
257
258 pmbase = pci_read_config16(dev, 0x40) & 0xfffe;
259
260 outl(config->gpe0_en, pmbase + 0x28);
261 outw(config->alt_gp_smi_en, pmbase + 0x38);
262
263 /* Set up power management block and determine sleep mode */
264 reg16 = inw(pmbase + 0x00); /* PM1_STS */
265 outw(reg16, pmbase + 0x00); /* Clear status bits. At least bit11 (power
266 button override) must be cleared or SCI
267 will be constantly fired and OSPM must
268 not know about it (ACPI spec says to
269 ignore the bit). */
Patrick Georgie72a8a32012-11-06 11:05:09 +0100270
271 /* Set duty cycle for hardware throttling (defaults to 0x0: 50%). */
272 reg32 = inl(pmbase + 0x10);
273 reg32 &= ~(7 << 5);
274 reg32 |= (config->throttle_duty & 7) << 5;
275 outl(reg32, pmbase + 0x10);
276}
277
Elyes HAOUAS8aa50732018-05-13 13:34:58 +0200278static void i82801ix_configure_cstates(struct device *dev)
Patrick Georgie72a8a32012-11-06 11:05:09 +0100279{
280 u8 reg8;
281
282 reg8 = pci_read_config8(dev, D31F0_CxSTATE_CNF);
283 reg8 |= (1 << 4) | (1 << 3) | (1 << 2); // Enable Popup & Popdown
284 pci_write_config8(dev, D31F0_CxSTATE_CNF, reg8);
285
286 // Set Deeper Sleep configuration to recommended values
287 reg8 = pci_read_config8(dev, D31F0_C4TIMING_CNT);
288 reg8 &= 0xf0;
289 reg8 |= (2 << 2); // Deeper Sleep to Stop CPU: 34-40us
290 reg8 |= (2 << 0); // Deeper Sleep to Sleep: 15us
291 pci_write_config8(dev, D31F0_C4TIMING_CNT, reg8);
292
293 /* We could enable slow-C4 exit here, if someone needs it? */
294}
295
296static void i82801ix_rtc_init(struct device *dev)
297{
298 u8 reg8;
299 int rtc_failed;
300
301 reg8 = pci_read_config8(dev, D31F0_GEN_PMCON_3);
302 rtc_failed = reg8 & RTC_BATTERY_DEAD;
303 if (rtc_failed) {
304 reg8 &= ~RTC_BATTERY_DEAD;
305 pci_write_config8(dev, D31F0_GEN_PMCON_3, reg8);
306 }
307 printk(BIOS_DEBUG, "rtc_failed = 0x%x\n", rtc_failed);
308
Gabe Blackb3f08c62014-04-30 17:12:25 -0700309 cmos_init(rtc_failed);
Patrick Georgie72a8a32012-11-06 11:05:09 +0100310}
311
312static void enable_hpet(void)
313{
314 u32 reg32;
315
316 /* Move HPET to default address 0xfed00000 and enable it */
317 reg32 = RCBA32(RCBA_HPTC);
318 reg32 |= (1 << 7); // HPET Address Enable
319 reg32 &= ~(3 << 0);
320 RCBA32(RCBA_HPTC) = reg32;
321}
322
323static void enable_clock_gating(void)
324{
325 u32 reg32;
326
327 /* Enable DMI dynamic clock gating. */
328 RCBA32(RCBA_DMIC) |= 3;
329
330 /* Enable Clock Gating for most devices. */
331 reg32 = RCBA32(RCBA_CG);
332 reg32 |= (1 << 31); /* LPC dynamic clock gating */
333 /* USB UHCI dynamic clock gating: */
334 reg32 |= (1 << 29) | (1 << 28);
335 /* SATA dynamic clock gating [0-3]: */
336 reg32 |= (1 << 27) | (1 << 26) | (1 << 25) | (1 << 24);
337 reg32 |= (1 << 23); /* LAN static clock gating (if LAN disabled) */
338 reg32 |= (1 << 22); /* HD audio dynamic clock gating */
339 reg32 &= ~(1 << 21); /* No HD audio static clock gating */
340 reg32 &= ~(1 << 20); /* No USB EHCI static clock gating */
341 reg32 |= (1 << 19); /* USB EHCI dynamic clock gating */
342 /* More SATA dynamic clock gating [4-5]: */
343 reg32 |= (1 << 18) | (1 << 17);
344 reg32 |= (1 << 16); /* PCI dynamic clock gating */
345 /* PCIe, DMI dynamic clock gating: */
346 reg32 |= (1 << 4) | (1 << 3) | (1 << 2) | (1 << 1);
347 reg32 |= (1 << 0); /* PCIe root port static clock gating */
348 RCBA32(RCBA_CG) = reg32;
349
350 /* Enable SPI dynamic clock gating. */
351 RCBA32(0x38c0) |= 7;
352}
353
Kyösti Mälkki6feb4da2019-07-13 17:28:37 +0300354static void i82801ix_set_acpi_mode(struct device *dev)
Patrick Georgie72a8a32012-11-06 11:05:09 +0100355{
Kyösti Mälkki44da9e72019-10-09 12:32:16 +0300356 if (CONFIG(HAVE_SMI_HANDLER)) {
357 if (!acpi_is_wakeup_s3()) {
358 printk(BIOS_DEBUG, "Disabling ACPI via APMC:\n");
359 outb(APM_CNT_ACPI_DISABLE, APM_CNT); // Disable ACPI mode
360 printk(BIOS_DEBUG, "done.\n");
361 } else {
362 printk(BIOS_DEBUG, "S3 wakeup, enabling ACPI via APMC\n");
363 outb(APM_CNT_ACPI_ENABLE, APM_CNT);
364 }
Patrick Georgie72a8a32012-11-06 11:05:09 +0100365 }
Patrick Georgie72a8a32012-11-06 11:05:09 +0100366}
Patrick Georgie72a8a32012-11-06 11:05:09 +0100367
368static void lpc_init(struct device *dev)
369{
370 printk(BIOS_DEBUG, "i82801ix: lpc_init\n");
371
372 /* Set the value for PCI command register. */
373 pci_write_config16(dev, PCI_COMMAND, 0x000f);
374
375 /* IO APIC initialization. */
376 i82801ix_enable_apic(dev);
377
378 i82801ix_enable_serial_irqs(dev);
379
380 /* Setup the PIRQ. */
381 i82801ix_pirq_init(dev);
382
383 /* Setup power options. */
384 i82801ix_power_options(dev);
385
386 /* Configure Cx state registers */
387 if (LPC_IS_MOBILE(dev))
388 i82801ix_configure_cstates(dev);
389
390 /* Initialize the real time clock. */
391 i82801ix_rtc_init(dev);
392
393 /* Initialize ISA DMA. */
394 isa_dma_init();
395
396 /* Initialize the High Precision Event Timers, if present. */
397 enable_hpet();
398
399 /* Initialize Clock Gating */
400 enable_clock_gating();
401
402 setup_i8259();
403
404 /* The OS should do this? */
405 /* Interrupt 9 should be level triggered (SCI) */
406 i8259_configure_irq_trigger(9, 1);
407
Kyösti Mälkki44da9e72019-10-09 12:32:16 +0300408 i82801ix_set_acpi_mode(dev);
Kyösti Mälkki6feb4da2019-07-13 17:28:37 +0300409
410 /* Don't allow evil boot loaders, kernels, or
411 * userspace applications to deceive us:
412 */
Kyösti Mälkkicd0b67b2019-10-09 07:52:40 +0300413 if (CONFIG(HAVE_SMI_HANDLER) && !CONFIG(PARALLEL_MP))
Kyösti Mälkki6feb4da2019-07-13 17:28:37 +0300414 aseg_smm_lock();
Patrick Georgie72a8a32012-11-06 11:05:09 +0100415}
416
Elyes HAOUAS8aa50732018-05-13 13:34:58 +0200417static void i82801ix_lpc_read_resources(struct device *dev)
Patrick Georgie72a8a32012-11-06 11:05:09 +0100418{
419 /*
420 * I/O Resources
421 *
422 * 0x0000 - 0x000f....ISA DMA
423 * 0x0010 - 0x001f....ISA DMA aliases
424 * 0x0020 ~ 0x003d....PIC
425 * 0x002e - 0x002f....Maybe Super I/O
426 * 0x0040 - 0x0043....Timer
427 * 0x004e - 0x004f....Maybe Super I/O
428 * 0x0050 - 0x0053....Timer aliases
429 * 0x0061.............NMI_SC
430 * 0x0070.............NMI_EN (readable in alternative access mode)
431 * 0x0070 - 0x0077....RTC
432 * 0x0080 - 0x008f....ISA DMA
433 * 0x0090 ~ 0x009f....ISA DMA aliases
434 * 0x0092.............Fast A20 and Init
435 * 0x00a0 ~ 0x00bd....PIC
436 * 0x00b2 - 0x00b3....APM
437 * 0x00c0 ~ 0x00de....ISA DMA
438 * 0x00c1 ~ 0x00df....ISA DMA aliases
439 * 0x00f0.............Coprocessor Error
440 * (0x0400-0x041f)....SMBus (SMBUS_IO_BASE, during raminit)
441 * 0x04d0 - 0x04d1....PIC
442 * 0x0500 - 0x057f....PM (DEFAULT_PMBASE)
443 * 0x0580 - 0x05bf....SB GPIO (DEFAULT_GPIOBASE)
444 * 0x05c0 - 0x05ff....SB GPIO cont. (mobile only)
445 * 0x0cf8 - 0x0cff....PCI
446 * 0x0cf9.............Reset Control
447 */
448
449 struct resource *res;
450
451 /* Get the normal PCI resources of this device. */
452 pci_dev_read_resources(dev);
453
454 /* Add an extra subtractive resource for both memory and I/O. */
455 res = new_resource(dev, IOINDEX_SUBTRACTIVE(0, 0));
456 res->base = 0;
457 res->size = 0x1000;
458 res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
459 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
460
461 res = new_resource(dev, IOINDEX_SUBTRACTIVE(1, 0));
462 res->base = 0xff800000;
463 res->size = 0x00800000; /* 8 MB for flash */
464 res->flags = IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE |
465 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
466
467 res = new_resource(dev, 3); /* IOAPIC */
468 res->base = IO_APIC_ADDR;
469 res->size = 0x00001000;
470 res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
471}
472
Furquan Shaikh338fd9a2020-04-24 22:57:05 -0700473static void southbridge_inject_dsdt(const struct device *dev)
Vladimir Serbinenko33769a52014-08-30 22:39:20 +0200474{
Elyes HAOUAS035df002016-10-03 21:54:16 +0200475 global_nvs_t *gnvs = cbmem_add (CBMEM_ID_ACPI_GNVS, sizeof(*gnvs));
Vladimir Serbinenko33769a52014-08-30 22:39:20 +0200476
477 if (gnvs) {
Elyes HAOUAS035df002016-10-03 21:54:16 +0200478 memset(gnvs, 0, sizeof(*gnvs));
Vladimir Serbinenko33769a52014-08-30 22:39:20 +0200479 acpi_create_gnvs(gnvs);
Vladimir Serbinenkodd2bc3f2014-10-31 09:16:31 +0100480
Vladimir Serbinenko33769a52014-08-30 22:39:20 +0200481 /* And tell SMI about it */
482 smm_setup_structures(gnvs, NULL, NULL);
483
484 /* Add it to SSDT. */
Vladimir Serbinenkof7c75db2014-11-04 21:21:06 +0100485 acpigen_write_scope("\\");
Patrick Rudolph4af2add2018-11-26 15:56:11 +0100486 acpigen_write_name_dword("NVSA", (uintptr_t)gnvs);
Vladimir Serbinenkof7c75db2014-11-04 21:21:06 +0100487 acpigen_pop_len();
Vladimir Serbinenko33769a52014-08-30 22:39:20 +0200488 }
489}
Vladimir Serbinenko36fa5b82014-10-28 23:43:20 +0100490
Arthur Heymanse798e6a2017-12-23 23:09:54 +0100491
492static const char *lpc_acpi_name(const struct device *dev)
493{
494 return "LPCB";
495}
496
Furquan Shaikh7536a392020-04-24 21:59:21 -0700497static void southbridge_fill_ssdt(const struct device *device)
Vladimir Serbinenko36fa5b82014-10-28 23:43:20 +0100498{
Kyösti Mälkkic70eed12018-05-22 02:18:00 +0300499 struct device *dev = pcidev_on_root(0x1f, 0);
Vladimir Serbinenko36fa5b82014-10-28 23:43:20 +0100500 config_t *chip = dev->chip_info;
501
502 intel_acpi_pcie_hotplug_generator(chip->pcie_hotplug_map, 8);
Arthur Heymanse798e6a2017-12-23 23:09:54 +0100503 intel_acpi_gen_def_acpi_pirq(device);
Vladimir Serbinenko36fa5b82014-10-28 23:43:20 +0100504}
Vladimir Serbinenko33769a52014-08-30 22:39:20 +0200505
Patrick Georgie72a8a32012-11-06 11:05:09 +0100506static struct pci_operations pci_ops = {
Subrata Banik4a0f0712019-03-20 14:29:47 +0530507 .set_subsystem = pci_dev_set_subsystem,
Patrick Georgie72a8a32012-11-06 11:05:09 +0100508};
509
510static struct device_operations device_ops = {
511 .read_resources = i82801ix_lpc_read_resources,
512 .set_resources = pci_dev_set_resources,
513 .enable_resources = pci_dev_enable_resources,
Nico Huber68680dd2020-03-31 17:34:52 +0200514 .acpi_inject_dsdt = southbridge_inject_dsdt,
Vladimir Serbinenko33769a52014-08-30 22:39:20 +0200515 .write_acpi_tables = acpi_write_hpet,
Nico Huber68680dd2020-03-31 17:34:52 +0200516 .acpi_fill_ssdt = southbridge_fill_ssdt,
Arthur Heymanse798e6a2017-12-23 23:09:54 +0100517 .acpi_name = lpc_acpi_name,
Patrick Georgie72a8a32012-11-06 11:05:09 +0100518 .init = lpc_init,
Nico Huber51b75ae2019-03-14 16:02:05 +0100519 .scan_bus = scan_static_bus,
Patrick Georgie72a8a32012-11-06 11:05:09 +0100520 .ops_pci = &pci_ops,
521};
522
523static const unsigned short pci_device_ids[] = {
Felix Singer7f8b0cd2019-11-10 11:04:08 +0100524 PCI_DEVICE_ID_INTEL_82801IH_LPC, /* ICH9DH */
525 PCI_DEVICE_ID_INTEL_82801IO_LPC, /* ICH9DO */
526 PCI_DEVICE_ID_INTEL_82801IR_LPC, /* ICH9R */
527 PCI_DEVICE_ID_INTEL_82801IEM_LPC, /* ICH9M-E */
528 PCI_DEVICE_ID_INTEL_82801IB_LPC, /* ICH9 */
529 PCI_DEVICE_ID_INTEL_82801IBM_LPC, /* ICH9M */
Patrick Georgie72a8a32012-11-06 11:05:09 +0100530 0
531};
532
533static const struct pci_driver ich9_lpc __pci_driver = {
534 .ops = &device_ops,
535 .vendor = PCI_VENDOR_ID_INTEL,
536 .devices = pci_device_ids,
537};