blob: 91b1bde93a5306675bd61675a57e277c09c25480 [file] [log] [blame]
Arthur Heymans7b9c1392017-04-09 20:40:39 +02001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2008-2009 coresystems GmbH
5 * 2012 secunet Security Networks AG
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; version 2 of
10 * the License.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 */
17
18#include <console/console.h>
19#include <device/device.h>
20#include <device/pci.h>
21#include <device/pci_ids.h>
Kyösti Mälkkicbf95712020-01-05 08:05:45 +020022#include <option.h>
Arthur Heymans7b9c1392017-04-09 20:40:39 +020023#include <pc80/mc146818rtc.h>
24#include <pc80/isa-dma.h>
25#include <pc80/i8259.h>
26#include <arch/io.h>
Kyösti Mälkkif1b58b72019-03-01 13:43:02 +020027#include <device/pci_ops.h>
Arthur Heymans7b9c1392017-04-09 20:40:39 +020028#include <arch/ioapic.h>
29#include <arch/acpi.h>
Arthur Heymans7b9c1392017-04-09 20:40:39 +020030#include <cpu/x86/smm.h>
31#include <arch/acpigen.h>
Arthur Heymansad501492017-04-12 00:15:39 +020032#include <arch/smp/mpspec.h>
Arthur Heymans7b9c1392017-04-09 20:40:39 +020033#include <cbmem.h>
34#include <string.h>
Kyösti Mälkki12b121c2019-08-18 16:33:39 +030035#include "chip.h"
Arthur Heymans349e0852017-04-09 20:48:37 +020036#include "i82801jx.h"
Arthur Heymans7b9c1392017-04-09 20:40:39 +020037#include "nvs.h"
38#include <southbridge/intel/common/pciehp.h>
Arthur Heymansa8a9f342017-12-24 08:11:13 +010039#include <southbridge/intel/common/acpi_pirq_gen.h>
Arthur Heymans7b9c1392017-04-09 20:40:39 +020040#include <drivers/intel/gma/i915.h>
41
42#define NMI_OFF 0
43
Arthur Heymans349e0852017-04-09 20:48:37 +020044typedef struct southbridge_intel_i82801jx_config config_t;
Arthur Heymans7b9c1392017-04-09 20:40:39 +020045
Arthur Heymans349e0852017-04-09 20:48:37 +020046static void i82801jx_enable_apic(struct device *dev)
Arthur Heymans7b9c1392017-04-09 20:40:39 +020047{
48 u32 reg32;
49 volatile u32 *ioapic_index = (volatile u32 *)(IO_APIC_ADDR);
50 volatile u32 *ioapic_data = (volatile u32 *)(IO_APIC_ADDR + 0x10);
51
52 /* Enable IOAPIC. Keep APIC Range Select at zero. */
53 RCBA8(0x31ff) = 0x03;
54 /* We have to read 0x31ff back if bit0 changed. */
55 RCBA8(0x31ff);
56
57 /* Lock maximum redirection entries (MRE), R/WO register. */
58 *ioapic_index = 0x01;
59 reg32 = *ioapic_data;
60 *ioapic_index = 0x01;
61 *ioapic_data = reg32;
62
63 setup_ioapic(VIO_APIC_VADDR, 2); /* ICH7 code uses id 2. */
64}
65
Arthur Heymans349e0852017-04-09 20:48:37 +020066static void i82801jx_enable_serial_irqs(struct device *dev)
Arthur Heymans7b9c1392017-04-09 20:40:39 +020067{
68 /* Set packet length and toggle silent mode bit for one frame. */
69 pci_write_config8(dev, D31F0_SERIRQ_CNTL,
70 (1 << 7) | (1 << 6) | ((21 - 17) << 2) | (0 << 0));
71}
72
73/* PIRQ[n]_ROUT[3:0] - PIRQ Routing Control
74 * 0x00 - 0000 = Reserved
75 * 0x01 - 0001 = Reserved
76 * 0x02 - 0010 = Reserved
77 * 0x03 - 0011 = IRQ3
78 * 0x04 - 0100 = IRQ4
79 * 0x05 - 0101 = IRQ5
80 * 0x06 - 0110 = IRQ6
81 * 0x07 - 0111 = IRQ7
82 * 0x08 - 1000 = Reserved
83 * 0x09 - 1001 = IRQ9
84 * 0x0A - 1010 = IRQ10
85 * 0x0B - 1011 = IRQ11
86 * 0x0C - 1100 = IRQ12
87 * 0x0D - 1101 = Reserved
88 * 0x0E - 1110 = IRQ14
89 * 0x0F - 1111 = IRQ15
90 * PIRQ[n]_ROUT[7] - PIRQ Routing Control
91 * 0x80 - The PIRQ is not routed.
92 */
93
Elyes HAOUAS1a8c1df2018-05-13 13:36:44 +020094static void i82801jx_pirq_init(struct device *dev)
Arthur Heymans7b9c1392017-04-09 20:40:39 +020095{
Elyes HAOUAS1a8c1df2018-05-13 13:36:44 +020096 struct device *irq_dev;
Arthur Heymans7b9c1392017-04-09 20:40:39 +020097
Arthur Heymans87af36a2017-04-12 10:53:30 +020098 /* Interrupt 11 is not used by legacy devices and so can always be used
99 * for PCI interrupts. Full legacy IRQ routing is complicated and hard
100 * to get right. Fortunately all modern OS use MSI and so it's not that
101 * big of an issue anyway. Still we have to provide a reasonable
102 * default. Using interrupt 11 for it everywhere is a working default.
103 * ACPI-aware OS can move it to any interrupt and others will just leave
104 * them at default.
105 */
106 const u8 pirq_routing = 11;
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200107
Arthur Heymans87af36a2017-04-12 10:53:30 +0200108 pci_write_config8(dev, D31F0_PIRQA_ROUT, pirq_routing);
109 pci_write_config8(dev, D31F0_PIRQB_ROUT, pirq_routing);
110 pci_write_config8(dev, D31F0_PIRQC_ROUT, pirq_routing);
111 pci_write_config8(dev, D31F0_PIRQD_ROUT, pirq_routing);
112
113 pci_write_config8(dev, D31F0_PIRQE_ROUT, pirq_routing);
114 pci_write_config8(dev, D31F0_PIRQF_ROUT, pirq_routing);
115 pci_write_config8(dev, D31F0_PIRQG_ROUT, pirq_routing);
116 pci_write_config8(dev, D31F0_PIRQH_ROUT, pirq_routing);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200117
118 /* Eric Biederman once said we should let the OS do this.
119 * I am not so sure anymore he was right.
120 */
121
122 for (irq_dev = all_devices; irq_dev; irq_dev = irq_dev->next) {
Arthur Heymans87af36a2017-04-12 10:53:30 +0200123 u8 int_pin = 0;
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200124
125 if (!irq_dev->enabled || irq_dev->path.type != DEVICE_PATH_PCI)
126 continue;
127
128 int_pin = pci_read_config8(irq_dev, PCI_INTERRUPT_PIN);
129
Arthur Heymans87af36a2017-04-12 10:53:30 +0200130 if (int_pin == 0)
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200131 continue;
132
Arthur Heymans87af36a2017-04-12 10:53:30 +0200133 pci_write_config8(irq_dev, PCI_INTERRUPT_LINE, pirq_routing);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200134 }
135}
136
Elyes HAOUAS1a8c1df2018-05-13 13:36:44 +0200137static void i82801jx_gpi_routing(struct device *dev)
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200138{
139 /* Get the chip configuration */
140 config_t *config = dev->chip_info;
141 u32 reg32 = 0;
142
143 /* An array would be much nicer here, or some
144 * other method of doing this.
145 */
146 reg32 |= (config->gpi0_routing & 0x03) << 0;
147 reg32 |= (config->gpi1_routing & 0x03) << 2;
148 reg32 |= (config->gpi2_routing & 0x03) << 4;
149 reg32 |= (config->gpi3_routing & 0x03) << 6;
150 reg32 |= (config->gpi4_routing & 0x03) << 8;
151 reg32 |= (config->gpi5_routing & 0x03) << 10;
152 reg32 |= (config->gpi6_routing & 0x03) << 12;
153 reg32 |= (config->gpi7_routing & 0x03) << 14;
154 reg32 |= (config->gpi8_routing & 0x03) << 16;
155 reg32 |= (config->gpi9_routing & 0x03) << 18;
156 reg32 |= (config->gpi10_routing & 0x03) << 20;
157 reg32 |= (config->gpi11_routing & 0x03) << 22;
158 reg32 |= (config->gpi12_routing & 0x03) << 24;
159 reg32 |= (config->gpi13_routing & 0x03) << 26;
160 reg32 |= (config->gpi14_routing & 0x03) << 28;
161 reg32 |= (config->gpi15_routing & 0x03) << 30;
162
163 pci_write_config32(dev, D31F0_GPIO_ROUT, reg32);
164}
165
Elyes HAOUAS1a8c1df2018-05-13 13:36:44 +0200166static void i82801jx_power_options(struct device *dev)
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200167{
168 u8 reg8;
169 u16 reg16, pmbase;
170 u32 reg32;
171 const char *state;
172 /* Get the chip configuration */
173 config_t *config = dev->chip_info;
174
Nico Huber9faae2b2018-11-14 00:00:35 +0100175 int pwr_on = CONFIG_MAINBOARD_POWER_FAILURE_STATE;
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200176 int nmi_option;
177
178 /* BIOS must program... */
179 reg32 = pci_read_config32(dev, 0xac);
180 pci_write_config32(dev, 0xac, reg32 | (1 << 30) | (3 << 8));
181
182 /* Which state do we want to goto after g3 (power restored)?
183 * 0 == S0 Full On
184 * 1 == S5 Soft Off
185 *
186 * If the option is not existent (Laptops), use MAINBOARD_POWER_ON.
187 */
188 pwr_on = MAINBOARD_POWER_ON;
189 get_option(&pwr_on, "power_on_after_fail");
190
191 reg8 = pci_read_config8(dev, D31F0_GEN_PMCON_3);
192 reg8 &= 0xfe;
193 switch (pwr_on) {
194 case MAINBOARD_POWER_OFF:
195 reg8 |= 1;
196 state = "off";
197 break;
198 case MAINBOARD_POWER_ON:
199 reg8 &= ~1;
200 state = "on";
201 break;
202 case MAINBOARD_POWER_KEEP:
203 reg8 &= ~1;
204 state = "state keep";
205 break;
206 default:
207 state = "undefined";
208 }
209
210 reg8 |= (3 << 4); /* avoid #S4 assertions */
211 reg8 &= ~(1 << 3); /* minimum asssertion is 1 to 2 RTCCLK */
212
213 pci_write_config8(dev, D31F0_GEN_PMCON_3, reg8);
214 printk(BIOS_INFO, "Set power %s after power failure.\n", state);
215
216 /* Set up NMI on errors. */
217 reg8 = inb(0x61);
218 reg8 &= 0x0f; /* Higher Nibble must be 0 */
219 reg8 &= ~(1 << 3); /* IOCHK# NMI Enable */
220 // reg8 &= ~(1 << 2); /* PCI SERR# Enable */
221 reg8 |= (1 << 2); /* PCI SERR# Disable for now */
222 outb(reg8, 0x61);
223
224 reg8 = inb(0x74); /* Read from 0x74 as 0x70 is write only. */
225 nmi_option = NMI_OFF;
226 get_option(&nmi_option, "nmi");
227 if (nmi_option) {
228 printk(BIOS_INFO, "NMI sources enabled.\n");
229 reg8 &= ~(1 << 7); /* Set NMI. */
230 } else {
231 printk(BIOS_INFO, "NMI sources disabled.\n");
Elyes HAOUAS9c5d4632018-04-26 22:21:21 +0200232 reg8 |= (1 << 7); /* Can't mask NMI from PCI-E and NMI_NOW */
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200233 }
234 outb(reg8, 0x70);
235
236 /* Enable CPU_SLP# and Intel Speedstep, set SMI# rate down */
237 reg16 = pci_read_config16(dev, D31F0_GEN_PMCON_1);
238 reg16 &= ~(3 << 0); // SMI# rate 1 minute
239 reg16 |= (1 << 2); // CLKRUN_EN - Mobile/Ultra only
240 reg16 |= (1 << 3); // Speedstep Enable - Mobile/Ultra only
241 reg16 |= (1 << 5); // CPUSLP_EN Desktop only
242
243 if (config->c4onc3_enable)
244 reg16 |= (1 << 7);
245
246 // another laptop wants this?
247 // reg16 &= ~(1 << 10); // BIOS_PCI_EXP_EN - Desktop/Mobile only
248 reg16 |= (1 << 10); // BIOS_PCI_EXP_EN - Desktop/Mobile only
249#if DEBUG_PERIODIC_SMIS
Arthur Heymans349e0852017-04-09 20:48:37 +0200250 /* Set DEBUG_PERIODIC_SMIS in i82801jx.h to debug using
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200251 * periodic SMIs.
252 */
253 reg16 |= (3 << 0); // Periodic SMI every 8s
254#endif
255 if (config->c5_enable)
256 reg16 |= (1 << 11); /* Enable C5, C6 and PMSYNC# */
257 pci_write_config16(dev, D31F0_GEN_PMCON_1, reg16);
258
259 /* Set exit timings for C5/C6. */
260 if (config->c5_enable) {
261 reg8 = pci_read_config8(dev, D31F0_C5_EXIT_TIMING);
262 reg8 &= ~((7 << 3) | (7 << 0));
263 if (config->c6_enable)
264 reg8 |= (5 << 3) | (3 << 0); /* 38-44us PMSYNC# to STPCLK#,
265 95-102us DPRSTP# to STP_CPU# */
266 else
267 reg8 |= (0 << 3) | (1 << 0); /* 16-17us PMSYNC# to STPCLK#,
268 34-40us DPRSTP# to STP_CPU# */
269 pci_write_config8(dev, D31F0_C5_EXIT_TIMING, reg8);
270 }
271
272 // Set the board's GPI routing.
Arthur Heymans349e0852017-04-09 20:48:37 +0200273 i82801jx_gpi_routing(dev);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200274
275 pmbase = pci_read_config16(dev, 0x40) & 0xfffe;
276
277 outl(config->gpe0_en, pmbase + 0x28);
278 outw(config->alt_gp_smi_en, pmbase + 0x38);
279
280 /* Set up power management block and determine sleep mode */
281 reg16 = inw(pmbase + 0x00); /* PM1_STS */
282 outw(reg16, pmbase + 0x00); /* Clear status bits. At least bit11 (power
283 button override) must be cleared or SCI
284 will be constantly fired and OSPM must
285 not know about it (ACPI spec says to
286 ignore the bit). */
287 reg32 = inl(pmbase + 0x04); // PM1_CNT
288 reg32 &= ~(7 << 10); // SLP_TYP
289 outl(reg32, pmbase + 0x04);
290
291 /* Set duty cycle for hardware throttling (defaults to 0x0: 50%). */
292 reg32 = inl(pmbase + 0x10);
293 reg32 &= ~(7 << 5);
294 reg32 |= (config->throttle_duty & 7) << 5;
295 outl(reg32, pmbase + 0x10);
296}
297
Elyes HAOUAS1a8c1df2018-05-13 13:36:44 +0200298static void i82801jx_configure_cstates(struct device *dev)
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200299{
300 u8 reg8;
301
302 reg8 = pci_read_config8(dev, D31F0_CxSTATE_CNF);
303 reg8 |= (1 << 4) | (1 << 3) | (1 << 2); // Enable Popup & Popdown
304 pci_write_config8(dev, D31F0_CxSTATE_CNF, reg8);
305
306 // Set Deeper Sleep configuration to recommended values
307 reg8 = pci_read_config8(dev, D31F0_C4TIMING_CNT);
308 reg8 &= 0xf0;
309 reg8 |= (2 << 2); // Deeper Sleep to Stop CPU: 34-40us
310 reg8 |= (2 << 0); // Deeper Sleep to Sleep: 15us
311 pci_write_config8(dev, D31F0_C4TIMING_CNT, reg8);
312
313 /* We could enable slow-C4 exit here, if someone needs it? */
314}
315
Arthur Heymans349e0852017-04-09 20:48:37 +0200316static void i82801jx_rtc_init(struct device *dev)
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200317{
318 u8 reg8;
319 int rtc_failed;
320
321 reg8 = pci_read_config8(dev, D31F0_GEN_PMCON_3);
322 rtc_failed = reg8 & RTC_BATTERY_DEAD;
323 if (rtc_failed) {
324 reg8 &= ~RTC_BATTERY_DEAD;
325 pci_write_config8(dev, D31F0_GEN_PMCON_3, reg8);
326 }
327 printk(BIOS_DEBUG, "rtc_failed = 0x%x\n", rtc_failed);
328
329 cmos_init(rtc_failed);
330}
331
332static void enable_hpet(void)
333{
334 u32 reg32;
335
336 /* Move HPET to default address 0xfed00000 and enable it */
337 reg32 = RCBA32(RCBA_HPTC);
338 reg32 |= (1 << 7); // HPET Address Enable
339 reg32 &= ~(3 << 0);
340 RCBA32(RCBA_HPTC) = reg32;
341}
342
343static void enable_clock_gating(void)
344{
345 u32 reg32;
346
347 /* Enable DMI dynamic clock gating. */
348 RCBA32(RCBA_DMIC) |= 3;
349
350 /* Enable Clock Gating for most devices. */
351 reg32 = RCBA32(RCBA_CG);
352 reg32 |= (1 << 31); /* LPC dynamic clock gating */
353 /* USB UHCI dynamic clock gating: */
354 reg32 |= (1 << 29) | (1 << 28);
355 /* SATA dynamic clock gating [0-3]: */
356 reg32 |= (1 << 27) | (1 << 26) | (1 << 25) | (1 << 24);
357 reg32 |= (1 << 23); /* LAN static clock gating (if LAN disabled) */
358 reg32 |= (1 << 22); /* HD audio dynamic clock gating */
359 reg32 &= ~(1 << 21); /* No HD audio static clock gating */
360 reg32 &= ~(1 << 20); /* No USB EHCI static clock gating */
361 reg32 |= (1 << 19); /* USB EHCI dynamic clock gating */
362 /* More SATA dynamic clock gating [4-5]: */
363 reg32 |= (1 << 18) | (1 << 17);
364 reg32 |= (1 << 16); /* PCI dynamic clock gating */
365 /* PCIe, DMI dynamic clock gating: */
366 reg32 |= (1 << 4) | (1 << 3) | (1 << 2) | (1 << 1);
367 reg32 |= (1 << 0); /* PCIe root port static clock gating */
368 RCBA32(RCBA_CG) = reg32;
369
370 /* Enable SPI dynamic clock gating. */
371 RCBA32(0x38c0) |= 7;
372}
373
Kyösti Mälkki83d6a8a2019-07-12 08:16:53 +0300374static void i82801jx_set_acpi_mode(struct device *dev)
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200375{
Kyösti Mälkki44da9e72019-10-09 12:32:16 +0300376 if (CONFIG(HAVE_SMI_HANDLER)) {
377 if (!acpi_is_wakeup_s3()) {
378 printk(BIOS_DEBUG, "Disabling ACPI via APMC:\n");
379 outb(APM_CNT_ACPI_DISABLE, APM_CNT); // Disable ACPI mode
380 printk(BIOS_DEBUG, "done.\n");
381 } else {
382 printk(BIOS_DEBUG, "S3 wakeup, enabling ACPI via APMC\n");
383 outb(APM_CNT_ACPI_ENABLE, APM_CNT);
384 }
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200385 }
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200386}
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200387
388static void lpc_init(struct device *dev)
389{
Arthur Heymans349e0852017-04-09 20:48:37 +0200390 printk(BIOS_DEBUG, "i82801jx: lpc_init\n");
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200391
392 /* Set the value for PCI command register. */
393 pci_write_config16(dev, PCI_COMMAND, 0x000f);
394
395 /* IO APIC initialization. */
Arthur Heymans349e0852017-04-09 20:48:37 +0200396 i82801jx_enable_apic(dev);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200397
Arthur Heymans349e0852017-04-09 20:48:37 +0200398 i82801jx_enable_serial_irqs(dev);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200399
400 /* Setup the PIRQ. */
Arthur Heymans349e0852017-04-09 20:48:37 +0200401 i82801jx_pirq_init(dev);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200402
403 /* Setup power options. */
Arthur Heymans349e0852017-04-09 20:48:37 +0200404 i82801jx_power_options(dev);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200405
406 /* Configure Cx state registers */
407 if (LPC_IS_MOBILE(dev))
Arthur Heymans349e0852017-04-09 20:48:37 +0200408 i82801jx_configure_cstates(dev);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200409
410 /* Initialize the real time clock. */
Arthur Heymans349e0852017-04-09 20:48:37 +0200411 i82801jx_rtc_init(dev);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200412
413 /* Initialize ISA DMA. */
414 isa_dma_init();
415
416 /* Initialize the High Precision Event Timers, if present. */
417 enable_hpet();
418
419 /* Initialize Clock Gating */
420 enable_clock_gating();
421
422 setup_i8259();
423
424 /* The OS should do this? */
425 /* Interrupt 9 should be level triggered (SCI) */
426 i8259_configure_irq_trigger(9, 1);
427
Kyösti Mälkki44da9e72019-10-09 12:32:16 +0300428 i82801jx_set_acpi_mode(dev);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200429}
430
Arthur Heymansad501492017-04-12 00:15:39 +0200431unsigned long acpi_fill_madt(unsigned long current)
432{
433 /* Local APICs */
434 current = acpi_create_madt_lapics(current);
435
436 /* IOAPIC */
437 current += acpi_create_madt_ioapic((acpi_madt_ioapic_t *) current,
438 2, IO_APIC_ADDR, 0);
439
440 /* LAPIC_NMI */
441 current += acpi_create_madt_lapic_nmi((acpi_madt_lapic_nmi_t *)
442 current, 0,
443 MP_IRQ_POLARITY_HIGH |
444 MP_IRQ_TRIGGER_EDGE, 0x01);
445 current += acpi_create_madt_lapic_nmi((acpi_madt_lapic_nmi_t *)
446 current, 1, MP_IRQ_POLARITY_HIGH |
447 MP_IRQ_TRIGGER_EDGE, 0x01);
448
449 /* INT_SRC_OVR */
450 current += acpi_create_madt_irqoverride((acpi_madt_irqoverride_t *)
451 current, 0, 0, 2, MP_IRQ_POLARITY_HIGH | MP_IRQ_TRIGGER_EDGE);
452 current += acpi_create_madt_irqoverride((acpi_madt_irqoverride_t *)
453 current, 0, 9, 9, MP_IRQ_POLARITY_HIGH | MP_IRQ_TRIGGER_LEVEL);
454
455
456 return current;
457}
458
459void acpi_fill_fadt(acpi_fadt_t *fadt)
460{
Kyösti Mälkkic70eed12018-05-22 02:18:00 +0300461 struct device *dev = pcidev_on_root(0x1f, 0);
Arthur Heymansad501492017-04-12 00:15:39 +0200462 config_t *chip = dev->chip_info;
463 u16 pmbase = pci_read_config16(dev, 0x40) & 0xfffe;
464
465 fadt->pm1a_evt_blk = pmbase;
466 fadt->pm1b_evt_blk = 0x0;
467 fadt->pm1a_cnt_blk = pmbase + 0x4;
468 fadt->pm1b_cnt_blk = 0x0;
469 fadt->pm2_cnt_blk = pmbase + 0x50;
470 fadt->pm_tmr_blk = pmbase + 0x8;
471 fadt->gpe0_blk = pmbase + 0x20;
472 fadt->gpe1_blk = 0;
473
474 fadt->pm1_evt_len = 4;
475 fadt->pm1_cnt_len = 2;
476 fadt->pm2_cnt_len = 1;
477 fadt->pm_tmr_len = 4;
478 fadt->gpe0_blk_len = 16;
479 fadt->gpe1_blk_len = 0;
480 fadt->gpe1_base = 0;
481
482 fadt->reset_reg.space_id = 1;
483 fadt->reset_reg.bit_width = 8;
484 fadt->reset_reg.bit_offset = 0;
485 fadt->reset_reg.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
486 fadt->reset_reg.addrl = 0xcf9;
487 fadt->reset_reg.addrh = 0;
488 fadt->reset_value = 6;
489
490 fadt->x_pm1a_evt_blk.space_id = 1;
491 fadt->x_pm1a_evt_blk.bit_width = 32;
492 fadt->x_pm1a_evt_blk.bit_offset = 0;
493 fadt->x_pm1a_evt_blk.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
494 fadt->x_pm1a_evt_blk.addrl = pmbase;
495 fadt->x_pm1a_evt_blk.addrh = 0x0;
496
497 fadt->x_pm1b_evt_blk.space_id = 0;
498 fadt->x_pm1b_evt_blk.bit_width = 0;
499 fadt->x_pm1b_evt_blk.bit_offset = 0;
500 fadt->x_pm1b_evt_blk.access_size = 0;
501 fadt->x_pm1b_evt_blk.addrl = 0x0;
502 fadt->x_pm1b_evt_blk.addrh = 0x0;
503
504 fadt->x_pm1a_cnt_blk.space_id = 1;
505 fadt->x_pm1a_cnt_blk.bit_width = 16;
506 fadt->x_pm1a_cnt_blk.bit_offset = 0;
507 fadt->x_pm1a_cnt_blk.access_size = ACPI_ACCESS_SIZE_WORD_ACCESS;
508 fadt->x_pm1a_cnt_blk.addrl = pmbase + 0x4;
509 fadt->x_pm1a_cnt_blk.addrh = 0x0;
510
511 fadt->x_pm1b_cnt_blk.space_id = 0;
512 fadt->x_pm1b_cnt_blk.bit_width = 0;
513 fadt->x_pm1b_cnt_blk.bit_offset = 0;
514 fadt->x_pm1b_cnt_blk.access_size = 0;
515 fadt->x_pm1b_cnt_blk.addrl = 0x0;
516 fadt->x_pm1b_cnt_blk.addrh = 0x0;
517
518 fadt->x_pm2_cnt_blk.space_id = 1;
519 fadt->x_pm2_cnt_blk.bit_width = 8;
520 fadt->x_pm2_cnt_blk.bit_offset = 0;
521 fadt->x_pm2_cnt_blk.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
Arthur Heymans3556ac52018-12-03 00:29:08 +0100522 fadt->x_pm2_cnt_blk.addrl = pmbase + 0x50;
Arthur Heymansad501492017-04-12 00:15:39 +0200523 fadt->x_pm2_cnt_blk.addrh = 0x0;
524
525 fadt->x_pm_tmr_blk.space_id = 1;
526 fadt->x_pm_tmr_blk.bit_width = 32;
527 fadt->x_pm_tmr_blk.bit_offset = 0;
528 fadt->x_pm_tmr_blk.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
529 fadt->x_pm_tmr_blk.addrl = pmbase + 0x8;
530 fadt->x_pm_tmr_blk.addrh = 0x0;
531
532 fadt->x_gpe0_blk.space_id = 1;
533 fadt->x_gpe0_blk.bit_width = 128;
534 fadt->x_gpe0_blk.bit_offset = 0;
535 fadt->x_gpe0_blk.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
536 fadt->x_gpe0_blk.addrl = pmbase + 0x20;
537 fadt->x_gpe0_blk.addrh = 0x0;
538
539 fadt->x_gpe1_blk.space_id = 0;
540 fadt->x_gpe1_blk.bit_width = 0;
541 fadt->x_gpe1_blk.bit_offset = 0;
542 fadt->x_gpe1_blk.access_size = 0;
543 fadt->x_gpe1_blk.addrl = 0x0;
544 fadt->x_gpe1_blk.addrh = 0x0;
545 fadt->day_alrm = 0xd;
546 fadt->mon_alrm = 0x00;
547 fadt->century = 0x32;
548
Elyes HAOUAS0d4de2a2019-02-28 13:04:29 +0100549 fadt->reserved = 0;
Arthur Heymansad501492017-04-12 00:15:39 +0200550 fadt->sci_int = 0x9;
551 fadt->smi_cmd = APM_CNT;
552 fadt->acpi_enable = APM_CNT_ACPI_ENABLE;
553 fadt->acpi_disable = APM_CNT_ACPI_DISABLE;
554 fadt->s4bios_req = 0x0;
555 fadt->pstate_cnt = APM_CNT_PST_CONTROL;
556
557 fadt->cst_cnt = APM_CNT_CST_CONTROL;
558 fadt->p_lvl2_lat = 1;
559 fadt->p_lvl3_lat = chip->c3_latency;
560 fadt->flush_size = 0;
561 fadt->flush_stride = 0;
562 fadt->duty_offset = 1;
563 if (chip->p_cnt_throttling_supported)
564 fadt->duty_width = 3;
565 else
566 fadt->duty_width = 0;
567 fadt->iapc_boot_arch = 0x03;
568 fadt->flags = (ACPI_FADT_WBINVD | ACPI_FADT_C1_SUPPORTED
569 | ACPI_FADT_SLEEP_BUTTON | ACPI_FADT_S4_RTC_WAKE
570 | ACPI_FADT_PLATFORM_CLOCK | ACPI_FADT_RESET_REGISTER
571 | ACPI_FADT_C2_MP_SUPPORTED);
572 if (chip->docking_supported)
573 fadt->flags |= ACPI_FADT_DOCKING_SUPPORTED;
574}
575
Elyes HAOUAS1a8c1df2018-05-13 13:36:44 +0200576static void i82801jx_lpc_read_resources(struct device *dev)
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200577{
Arthur Heymanse5dcaf12017-04-12 00:03:37 +0200578 int i, io_index = 0;
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200579 /*
580 * I/O Resources
581 *
582 * 0x0000 - 0x000f....ISA DMA
583 * 0x0010 - 0x001f....ISA DMA aliases
584 * 0x0020 ~ 0x003d....PIC
585 * 0x002e - 0x002f....Maybe Super I/O
586 * 0x0040 - 0x0043....Timer
587 * 0x004e - 0x004f....Maybe Super I/O
588 * 0x0050 - 0x0053....Timer aliases
589 * 0x0061.............NMI_SC
590 * 0x0070.............NMI_EN (readable in alternative access mode)
591 * 0x0070 - 0x0077....RTC
592 * 0x0080 - 0x008f....ISA DMA
593 * 0x0090 ~ 0x009f....ISA DMA aliases
594 * 0x0092.............Fast A20 and Init
595 * 0x00a0 ~ 0x00bd....PIC
596 * 0x00b2 - 0x00b3....APM
597 * 0x00c0 ~ 0x00de....ISA DMA
598 * 0x00c1 ~ 0x00df....ISA DMA aliases
599 * 0x00f0.............Coprocessor Error
600 * (0x0400-0x041f)....SMBus (SMBUS_IO_BASE, during raminit)
601 * 0x04d0 - 0x04d1....PIC
602 * 0x0500 - 0x057f....PM (DEFAULT_PMBASE)
603 * 0x0580 - 0x05bf....SB GPIO (DEFAULT_GPIOBASE)
604 * 0x05c0 - 0x05ff....SB GPIO cont. (mobile only)
605 * 0x0cf8 - 0x0cff....PCI
606 * 0x0cf9.............Reset Control
607 */
608
609 struct resource *res;
610
611 /* Get the normal PCI resources of this device. */
612 pci_dev_read_resources(dev);
613
614 /* Add an extra subtractive resource for both memory and I/O. */
Arthur Heymanse5dcaf12017-04-12 00:03:37 +0200615 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200616 res->base = 0;
617 res->size = 0x1000;
618 res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
619 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
620
Arthur Heymanse5dcaf12017-04-12 00:03:37 +0200621 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
622 res->base = 0xff000000;
623 res->size = 0x01000000; /* 16 MB for flash */
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200624 res->flags = IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE |
625 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
626
627 res = new_resource(dev, 3); /* IOAPIC */
628 res->base = IO_APIC_ADDR;
629 res->size = 0x00001000;
630 res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
Arthur Heymanse5dcaf12017-04-12 00:03:37 +0200631
632 /* Set IO decode ranges if required.*/
633 for (i = 0; i < 4; i++) {
634 u32 gen_dec;
635 gen_dec = pci_read_config32(dev, 0x84 + 4 * i);
636
637 if ((gen_dec & 0xFFFC) > 0x1000) {
638 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
639 res->base = gen_dec & 0xFFFC;
640 res->size = (gen_dec >> 16) & 0xFC;
641 res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
642 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
643 }
644 }
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200645}
646
Elyes HAOUAS1a8c1df2018-05-13 13:36:44 +0200647static void southbridge_inject_dsdt(struct device *dev)
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200648{
649 global_nvs_t *gnvs = cbmem_add (CBMEM_ID_ACPI_GNVS, sizeof(*gnvs));
650
651 if (gnvs) {
652 const struct i915_gpu_controller_info *gfx = intel_gma_get_controller_info();
653 memset(gnvs, 0, sizeof(*gnvs));
654 acpi_create_gnvs(gnvs);
655
Nico Huber744d6bd2019-01-12 14:58:20 +0100656 if (gfx) {
657 gnvs->ndid = gfx->ndid;
658 memcpy(gnvs->did, gfx->did, sizeof(gnvs->did));
659 }
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200660
661 /* And tell SMI about it */
662 smm_setup_structures(gnvs, NULL, NULL);
663
664 /* Add it to SSDT. */
665 acpigen_write_scope("\\");
666 acpigen_write_name_dword("NVSA", (u32) gnvs);
667 acpigen_pop_len();
668 }
669}
670
Arthur Heymansa8a9f342017-12-24 08:11:13 +0100671static const char *lpc_acpi_name(const struct device *dev)
672{
673 return "LPCB";
674}
675
Elyes HAOUAS1a8c1df2018-05-13 13:36:44 +0200676static void southbridge_fill_ssdt(struct device *device)
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200677{
Kyösti Mälkkic70eed12018-05-22 02:18:00 +0300678 struct device *dev = pcidev_on_root(0x1f, 0);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200679 config_t *chip = dev->chip_info;
680
681 intel_acpi_pcie_hotplug_generator(chip->pcie_hotplug_map, 8);
Arthur Heymansa8a9f342017-12-24 08:11:13 +0100682 intel_acpi_gen_def_acpi_pirq(device);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200683}
684
685static struct pci_operations pci_ops = {
Subrata Banik4a0f0712019-03-20 14:29:47 +0530686 .set_subsystem = pci_dev_set_subsystem,
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200687};
688
689static struct device_operations device_ops = {
Arthur Heymans349e0852017-04-09 20:48:37 +0200690 .read_resources = i82801jx_lpc_read_resources,
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200691 .set_resources = pci_dev_set_resources,
692 .enable_resources = pci_dev_enable_resources,
693 .acpi_inject_dsdt_generator = southbridge_inject_dsdt,
694 .write_acpi_tables = acpi_write_hpet,
695 .acpi_fill_ssdt_generator = southbridge_fill_ssdt,
Arthur Heymansa8a9f342017-12-24 08:11:13 +0100696 .acpi_name = lpc_acpi_name,
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200697 .init = lpc_init,
Nico Huber51b75ae2019-03-14 16:02:05 +0100698 .scan_bus = scan_static_bus,
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200699 .ops_pci = &pci_ops,
700};
701
702static const unsigned short pci_device_ids[] = {
Arthur Heymans349e0852017-04-09 20:48:37 +0200703 0x3a10, /* ICH10R Eng. Sample */
704 0x3a14, /* ICH10DO */
705 0x3a16, /* ICH10R */
706 0x3a18, /* ICH10 */
707 0x3a1a, /* ICH10D */
708 0x3a1e, /* ICH10 Eng. Sample */
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200709 0
710};
711
Arthur Heymans349e0852017-04-09 20:48:37 +0200712static const struct pci_driver ich10_lpc __pci_driver = {
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200713 .ops = &device_ops,
714 .vendor = PCI_VENDOR_ID_INTEL,
715 .devices = pci_device_ids,
716};