blob: abfe665989111c271124bc88a34c8a066df8ef21 [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>
Arthur Heymans349e0852017-04-09 20:48:37 +020034#include "i82801jx.h"
Arthur Heymans7b9c1392017-04-09 20:40:39 +020035#include "nvs.h"
36#include <southbridge/intel/common/pciehp.h>
Arthur Heymansa8a9f342017-12-24 08:11:13 +010037#include <southbridge/intel/common/acpi_pirq_gen.h>
Arthur Heymans7b9c1392017-04-09 20:40:39 +020038#include <drivers/intel/gma/i915.h>
39
40#define NMI_OFF 0
41
42#define ENABLE_ACPI_MODE_IN_COREBOOT 0
43#define TEST_SMM_FLASH_LOCKDOWN 0
44
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
Julius Wernercd49cce2019-03-05 16:53:33 -0800375#if CONFIG(HAVE_SMI_HANDLER)
Arthur Heymans349e0852017-04-09 20:48:37 +0200376static void i82801jx_lock_smm(struct device *dev)
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200377{
378#if TEST_SMM_FLASH_LOCKDOWN
379 u8 reg8;
380#endif
381
382 if (!acpi_is_wakeup_s3()) {
383#if ENABLE_ACPI_MODE_IN_COREBOOT
384 printk(BIOS_DEBUG, "Enabling ACPI via APMC:\n");
385 outb(APM_CNT_ACPI_ENABLE, APM_CNT); // Enable ACPI mode
386 printk(BIOS_DEBUG, "done.\n");
387#else
388 printk(BIOS_DEBUG, "Disabling ACPI via APMC:\n");
389 outb(APM_CNT_ACPI_DISABLE, APM_CNT); // Disable ACPI mode
390 printk(BIOS_DEBUG, "done.\n");
391#endif
392 } else {
393 printk(BIOS_DEBUG, "S3 wakeup, enabling ACPI via APMC\n");
394 outb(APM_CNT_ACPI_ENABLE, APM_CNT);
395 }
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200396
397#if TEST_SMM_FLASH_LOCKDOWN
398 /* Now try this: */
399 printk(BIOS_DEBUG, "Locking BIOS to RO... ");
400 reg8 = pci_read_config8(dev, 0xdc); /* BIOS_CNTL */
401 printk(BIOS_DEBUG, " BLE: %s; BWE: %s\n", (reg8&2)?"on":"off",
402 (reg8&1)?"rw":"ro");
403 reg8 &= ~(1 << 0); /* clear BIOSWE */
404 pci_write_config8(dev, 0xdc, reg8);
405 reg8 |= (1 << 1); /* set BLE */
406 pci_write_config8(dev, 0xdc, reg8);
407 printk(BIOS_DEBUG, "ok.\n");
408 reg8 = pci_read_config8(dev, 0xdc); /* BIOS_CNTL */
409 printk(BIOS_DEBUG, " BLE: %s; BWE: %s\n", (reg8&2)?"on":"off",
410 (reg8&1)?"rw":"ro");
411
412 printk(BIOS_DEBUG, "Writing:\n");
413 *(volatile u8 *)0xfff00000 = 0x00;
414 printk(BIOS_DEBUG, "Testing:\n");
415 reg8 |= (1 << 0); /* set BIOSWE */
416 pci_write_config8(dev, 0xdc, reg8);
417
418 reg8 = pci_read_config8(dev, 0xdc); /* BIOS_CNTL */
419 printk(BIOS_DEBUG, " BLE: %s; BWE: %s\n", (reg8&2)?"on":"off",
420 (reg8&1)?"rw":"ro");
421 printk(BIOS_DEBUG, "Done.\n");
422#endif
423}
424#endif
425
426static void lpc_init(struct device *dev)
427{
Arthur Heymans349e0852017-04-09 20:48:37 +0200428 printk(BIOS_DEBUG, "i82801jx: lpc_init\n");
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200429
430 /* Set the value for PCI command register. */
431 pci_write_config16(dev, PCI_COMMAND, 0x000f);
432
433 /* IO APIC initialization. */
Arthur Heymans349e0852017-04-09 20:48:37 +0200434 i82801jx_enable_apic(dev);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200435
Arthur Heymans349e0852017-04-09 20:48:37 +0200436 i82801jx_enable_serial_irqs(dev);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200437
438 /* Setup the PIRQ. */
Arthur Heymans349e0852017-04-09 20:48:37 +0200439 i82801jx_pirq_init(dev);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200440
441 /* Setup power options. */
Arthur Heymans349e0852017-04-09 20:48:37 +0200442 i82801jx_power_options(dev);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200443
444 /* Configure Cx state registers */
445 if (LPC_IS_MOBILE(dev))
Arthur Heymans349e0852017-04-09 20:48:37 +0200446 i82801jx_configure_cstates(dev);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200447
448 /* Initialize the real time clock. */
Arthur Heymans349e0852017-04-09 20:48:37 +0200449 i82801jx_rtc_init(dev);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200450
451 /* Initialize ISA DMA. */
452 isa_dma_init();
453
454 /* Initialize the High Precision Event Timers, if present. */
455 enable_hpet();
456
457 /* Initialize Clock Gating */
458 enable_clock_gating();
459
460 setup_i8259();
461
462 /* The OS should do this? */
463 /* Interrupt 9 should be level triggered (SCI) */
464 i8259_configure_irq_trigger(9, 1);
465
Julius Wernercd49cce2019-03-05 16:53:33 -0800466#if CONFIG(HAVE_SMI_HANDLER)
Arthur Heymans349e0852017-04-09 20:48:37 +0200467 i82801jx_lock_smm(dev);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200468#endif
469}
470
Arthur Heymansad501492017-04-12 00:15:39 +0200471unsigned long acpi_fill_madt(unsigned long current)
472{
473 /* Local APICs */
474 current = acpi_create_madt_lapics(current);
475
476 /* IOAPIC */
477 current += acpi_create_madt_ioapic((acpi_madt_ioapic_t *) current,
478 2, IO_APIC_ADDR, 0);
479
480 /* LAPIC_NMI */
481 current += acpi_create_madt_lapic_nmi((acpi_madt_lapic_nmi_t *)
482 current, 0,
483 MP_IRQ_POLARITY_HIGH |
484 MP_IRQ_TRIGGER_EDGE, 0x01);
485 current += acpi_create_madt_lapic_nmi((acpi_madt_lapic_nmi_t *)
486 current, 1, MP_IRQ_POLARITY_HIGH |
487 MP_IRQ_TRIGGER_EDGE, 0x01);
488
489 /* INT_SRC_OVR */
490 current += acpi_create_madt_irqoverride((acpi_madt_irqoverride_t *)
491 current, 0, 0, 2, MP_IRQ_POLARITY_HIGH | MP_IRQ_TRIGGER_EDGE);
492 current += acpi_create_madt_irqoverride((acpi_madt_irqoverride_t *)
493 current, 0, 9, 9, MP_IRQ_POLARITY_HIGH | MP_IRQ_TRIGGER_LEVEL);
494
495
496 return current;
497}
498
499void acpi_fill_fadt(acpi_fadt_t *fadt)
500{
Kyösti Mälkkic70eed12018-05-22 02:18:00 +0300501 struct device *dev = pcidev_on_root(0x1f, 0);
Arthur Heymansad501492017-04-12 00:15:39 +0200502 config_t *chip = dev->chip_info;
503 u16 pmbase = pci_read_config16(dev, 0x40) & 0xfffe;
504
505 fadt->pm1a_evt_blk = pmbase;
506 fadt->pm1b_evt_blk = 0x0;
507 fadt->pm1a_cnt_blk = pmbase + 0x4;
508 fadt->pm1b_cnt_blk = 0x0;
509 fadt->pm2_cnt_blk = pmbase + 0x50;
510 fadt->pm_tmr_blk = pmbase + 0x8;
511 fadt->gpe0_blk = pmbase + 0x20;
512 fadt->gpe1_blk = 0;
513
514 fadt->pm1_evt_len = 4;
515 fadt->pm1_cnt_len = 2;
516 fadt->pm2_cnt_len = 1;
517 fadt->pm_tmr_len = 4;
518 fadt->gpe0_blk_len = 16;
519 fadt->gpe1_blk_len = 0;
520 fadt->gpe1_base = 0;
521
522 fadt->reset_reg.space_id = 1;
523 fadt->reset_reg.bit_width = 8;
524 fadt->reset_reg.bit_offset = 0;
525 fadt->reset_reg.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
526 fadt->reset_reg.addrl = 0xcf9;
527 fadt->reset_reg.addrh = 0;
528 fadt->reset_value = 6;
529
530 fadt->x_pm1a_evt_blk.space_id = 1;
531 fadt->x_pm1a_evt_blk.bit_width = 32;
532 fadt->x_pm1a_evt_blk.bit_offset = 0;
533 fadt->x_pm1a_evt_blk.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
534 fadt->x_pm1a_evt_blk.addrl = pmbase;
535 fadt->x_pm1a_evt_blk.addrh = 0x0;
536
537 fadt->x_pm1b_evt_blk.space_id = 0;
538 fadt->x_pm1b_evt_blk.bit_width = 0;
539 fadt->x_pm1b_evt_blk.bit_offset = 0;
540 fadt->x_pm1b_evt_blk.access_size = 0;
541 fadt->x_pm1b_evt_blk.addrl = 0x0;
542 fadt->x_pm1b_evt_blk.addrh = 0x0;
543
544 fadt->x_pm1a_cnt_blk.space_id = 1;
545 fadt->x_pm1a_cnt_blk.bit_width = 16;
546 fadt->x_pm1a_cnt_blk.bit_offset = 0;
547 fadt->x_pm1a_cnt_blk.access_size = ACPI_ACCESS_SIZE_WORD_ACCESS;
548 fadt->x_pm1a_cnt_blk.addrl = pmbase + 0x4;
549 fadt->x_pm1a_cnt_blk.addrh = 0x0;
550
551 fadt->x_pm1b_cnt_blk.space_id = 0;
552 fadt->x_pm1b_cnt_blk.bit_width = 0;
553 fadt->x_pm1b_cnt_blk.bit_offset = 0;
554 fadt->x_pm1b_cnt_blk.access_size = 0;
555 fadt->x_pm1b_cnt_blk.addrl = 0x0;
556 fadt->x_pm1b_cnt_blk.addrh = 0x0;
557
558 fadt->x_pm2_cnt_blk.space_id = 1;
559 fadt->x_pm2_cnt_blk.bit_width = 8;
560 fadt->x_pm2_cnt_blk.bit_offset = 0;
561 fadt->x_pm2_cnt_blk.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
Arthur Heymans3556ac52018-12-03 00:29:08 +0100562 fadt->x_pm2_cnt_blk.addrl = pmbase + 0x50;
Arthur Heymansad501492017-04-12 00:15:39 +0200563 fadt->x_pm2_cnt_blk.addrh = 0x0;
564
565 fadt->x_pm_tmr_blk.space_id = 1;
566 fadt->x_pm_tmr_blk.bit_width = 32;
567 fadt->x_pm_tmr_blk.bit_offset = 0;
568 fadt->x_pm_tmr_blk.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
569 fadt->x_pm_tmr_blk.addrl = pmbase + 0x8;
570 fadt->x_pm_tmr_blk.addrh = 0x0;
571
572 fadt->x_gpe0_blk.space_id = 1;
573 fadt->x_gpe0_blk.bit_width = 128;
574 fadt->x_gpe0_blk.bit_offset = 0;
575 fadt->x_gpe0_blk.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
576 fadt->x_gpe0_blk.addrl = pmbase + 0x20;
577 fadt->x_gpe0_blk.addrh = 0x0;
578
579 fadt->x_gpe1_blk.space_id = 0;
580 fadt->x_gpe1_blk.bit_width = 0;
581 fadt->x_gpe1_blk.bit_offset = 0;
582 fadt->x_gpe1_blk.access_size = 0;
583 fadt->x_gpe1_blk.addrl = 0x0;
584 fadt->x_gpe1_blk.addrh = 0x0;
585 fadt->day_alrm = 0xd;
586 fadt->mon_alrm = 0x00;
587 fadt->century = 0x32;
588
Elyes HAOUAS0d4de2a2019-02-28 13:04:29 +0100589 fadt->reserved = 0;
Arthur Heymansad501492017-04-12 00:15:39 +0200590 fadt->sci_int = 0x9;
591 fadt->smi_cmd = APM_CNT;
592 fadt->acpi_enable = APM_CNT_ACPI_ENABLE;
593 fadt->acpi_disable = APM_CNT_ACPI_DISABLE;
594 fadt->s4bios_req = 0x0;
595 fadt->pstate_cnt = APM_CNT_PST_CONTROL;
596
597 fadt->cst_cnt = APM_CNT_CST_CONTROL;
598 fadt->p_lvl2_lat = 1;
599 fadt->p_lvl3_lat = chip->c3_latency;
600 fadt->flush_size = 0;
601 fadt->flush_stride = 0;
602 fadt->duty_offset = 1;
603 if (chip->p_cnt_throttling_supported)
604 fadt->duty_width = 3;
605 else
606 fadt->duty_width = 0;
607 fadt->iapc_boot_arch = 0x03;
608 fadt->flags = (ACPI_FADT_WBINVD | ACPI_FADT_C1_SUPPORTED
609 | ACPI_FADT_SLEEP_BUTTON | ACPI_FADT_S4_RTC_WAKE
610 | ACPI_FADT_PLATFORM_CLOCK | ACPI_FADT_RESET_REGISTER
611 | ACPI_FADT_C2_MP_SUPPORTED);
612 if (chip->docking_supported)
613 fadt->flags |= ACPI_FADT_DOCKING_SUPPORTED;
614}
615
Elyes HAOUAS1a8c1df2018-05-13 13:36:44 +0200616static void i82801jx_lpc_read_resources(struct device *dev)
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200617{
Arthur Heymanse5dcaf12017-04-12 00:03:37 +0200618 int i, io_index = 0;
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200619 /*
620 * I/O Resources
621 *
622 * 0x0000 - 0x000f....ISA DMA
623 * 0x0010 - 0x001f....ISA DMA aliases
624 * 0x0020 ~ 0x003d....PIC
625 * 0x002e - 0x002f....Maybe Super I/O
626 * 0x0040 - 0x0043....Timer
627 * 0x004e - 0x004f....Maybe Super I/O
628 * 0x0050 - 0x0053....Timer aliases
629 * 0x0061.............NMI_SC
630 * 0x0070.............NMI_EN (readable in alternative access mode)
631 * 0x0070 - 0x0077....RTC
632 * 0x0080 - 0x008f....ISA DMA
633 * 0x0090 ~ 0x009f....ISA DMA aliases
634 * 0x0092.............Fast A20 and Init
635 * 0x00a0 ~ 0x00bd....PIC
636 * 0x00b2 - 0x00b3....APM
637 * 0x00c0 ~ 0x00de....ISA DMA
638 * 0x00c1 ~ 0x00df....ISA DMA aliases
639 * 0x00f0.............Coprocessor Error
640 * (0x0400-0x041f)....SMBus (SMBUS_IO_BASE, during raminit)
641 * 0x04d0 - 0x04d1....PIC
642 * 0x0500 - 0x057f....PM (DEFAULT_PMBASE)
643 * 0x0580 - 0x05bf....SB GPIO (DEFAULT_GPIOBASE)
644 * 0x05c0 - 0x05ff....SB GPIO cont. (mobile only)
645 * 0x0cf8 - 0x0cff....PCI
646 * 0x0cf9.............Reset Control
647 */
648
649 struct resource *res;
650
651 /* Get the normal PCI resources of this device. */
652 pci_dev_read_resources(dev);
653
654 /* Add an extra subtractive resource for both memory and I/O. */
Arthur Heymanse5dcaf12017-04-12 00:03:37 +0200655 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200656 res->base = 0;
657 res->size = 0x1000;
658 res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
659 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
660
Arthur Heymanse5dcaf12017-04-12 00:03:37 +0200661 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
662 res->base = 0xff000000;
663 res->size = 0x01000000; /* 16 MB for flash */
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200664 res->flags = IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE |
665 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
666
667 res = new_resource(dev, 3); /* IOAPIC */
668 res->base = IO_APIC_ADDR;
669 res->size = 0x00001000;
670 res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
Arthur Heymanse5dcaf12017-04-12 00:03:37 +0200671
672 /* Set IO decode ranges if required.*/
673 for (i = 0; i < 4; i++) {
674 u32 gen_dec;
675 gen_dec = pci_read_config32(dev, 0x84 + 4 * i);
676
677 if ((gen_dec & 0xFFFC) > 0x1000) {
678 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
679 res->base = gen_dec & 0xFFFC;
680 res->size = (gen_dec >> 16) & 0xFC;
681 res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
682 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
683 }
684 }
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200685}
686
Elyes HAOUAS1a8c1df2018-05-13 13:36:44 +0200687static void southbridge_inject_dsdt(struct device *dev)
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200688{
689 global_nvs_t *gnvs = cbmem_add (CBMEM_ID_ACPI_GNVS, sizeof(*gnvs));
690
691 if (gnvs) {
692 const struct i915_gpu_controller_info *gfx = intel_gma_get_controller_info();
693 memset(gnvs, 0, sizeof(*gnvs));
694 acpi_create_gnvs(gnvs);
695
Nico Huber744d6bd2019-01-12 14:58:20 +0100696 if (gfx) {
697 gnvs->ndid = gfx->ndid;
698 memcpy(gnvs->did, gfx->did, sizeof(gnvs->did));
699 }
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200700
701 /* And tell SMI about it */
702 smm_setup_structures(gnvs, NULL, NULL);
703
704 /* Add it to SSDT. */
705 acpigen_write_scope("\\");
706 acpigen_write_name_dword("NVSA", (u32) gnvs);
707 acpigen_pop_len();
708 }
709}
710
Arthur Heymansa8a9f342017-12-24 08:11:13 +0100711static const char *lpc_acpi_name(const struct device *dev)
712{
713 return "LPCB";
714}
715
Elyes HAOUAS1a8c1df2018-05-13 13:36:44 +0200716static void southbridge_fill_ssdt(struct device *device)
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200717{
Kyösti Mälkkic70eed12018-05-22 02:18:00 +0300718 struct device *dev = pcidev_on_root(0x1f, 0);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200719 config_t *chip = dev->chip_info;
720
721 intel_acpi_pcie_hotplug_generator(chip->pcie_hotplug_map, 8);
Arthur Heymansa8a9f342017-12-24 08:11:13 +0100722 intel_acpi_gen_def_acpi_pirq(device);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200723}
724
725static struct pci_operations pci_ops = {
Subrata Banik4a0f0712019-03-20 14:29:47 +0530726 .set_subsystem = pci_dev_set_subsystem,
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200727};
728
729static struct device_operations device_ops = {
Arthur Heymans349e0852017-04-09 20:48:37 +0200730 .read_resources = i82801jx_lpc_read_resources,
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200731 .set_resources = pci_dev_set_resources,
732 .enable_resources = pci_dev_enable_resources,
733 .acpi_inject_dsdt_generator = southbridge_inject_dsdt,
734 .write_acpi_tables = acpi_write_hpet,
735 .acpi_fill_ssdt_generator = southbridge_fill_ssdt,
Arthur Heymansa8a9f342017-12-24 08:11:13 +0100736 .acpi_name = lpc_acpi_name,
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200737 .init = lpc_init,
738 .scan_bus = scan_lpc_bus,
739 .ops_pci = &pci_ops,
740};
741
742static const unsigned short pci_device_ids[] = {
Arthur Heymans349e0852017-04-09 20:48:37 +0200743 0x3a10, /* ICH10R Eng. Sample */
744 0x3a14, /* ICH10DO */
745 0x3a16, /* ICH10R */
746 0x3a18, /* ICH10 */
747 0x3a1a, /* ICH10D */
748 0x3a1e, /* ICH10 Eng. Sample */
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200749 0
750};
751
Arthur Heymans349e0852017-04-09 20:48:37 +0200752static const struct pci_driver ich10_lpc __pci_driver = {
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200753 .ops = &device_ops,
754 .vendor = PCI_VENDOR_ID_INTEL,
755 .devices = pci_device_ids,
756};