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