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