blob: b8df7aad106a07b12130600b89ec57e30144e737 [file] [log] [blame]
Stefan Reinauer8e073822012-04-04 00:07:22 +02001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2008-2009 coresystems GmbH
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; version 2 of
9 * the License.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
Stefan Reinauer8e073822012-04-04 00:07:22 +020015 */
16
17#include <console/console.h>
18#include <device/device.h>
19#include <device/pci.h>
20#include <device/pci_ids.h>
Patrick Rudolphe56189c2018-04-18 10:11:59 +020021#include <device/pci_ops.h>
Patrick Rudolphef8c5592018-07-27 17:48:27 +020022#include <device/pci_def.h>
Stefan Reinauer8e073822012-04-04 00:07:22 +020023#include <pc80/mc146818rtc.h>
24#include <pc80/isa-dma.h>
25#include <pc80/i8259.h>
26#include <arch/io.h>
27#include <arch/ioapic.h>
28#include <arch/acpi.h>
Elyes HAOUASd2b9ec12018-10-27 09:41:02 +020029#include <arch/cpu.h>
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +020030#include <arch/acpigen.h>
31#include <drivers/intel/gma/i915.h>
Vladimir Serbinenko5b044ae2014-10-25 15:20:55 +020032#include <cpu/x86/smm.h>
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +020033#include <cbmem.h>
Vladimir Serbinenko7309c642014-10-05 11:07:33 +020034#include <string.h>
Kyösti Mälkki12b121c2019-08-18 16:33:39 +030035#include "chip.h"
Stefan Reinauer8e073822012-04-04 00:07:22 +020036#include "pch.h"
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +020037#include "nvs.h"
Vladimir Serbinenko36fa5b82014-10-28 23:43:20 +010038#include <southbridge/intel/common/pciehp.h>
Tobias Diedrich7f5efd92017-12-14 00:29:01 +010039#include <southbridge/intel/common/acpi_pirq_gen.h>
Arthur Heymansa0508172018-01-25 11:30:22 +010040#include <southbridge/intel/common/pmutil.h>
Patrick Rudolph6b931122018-11-01 17:48:37 +010041#include <southbridge/intel/common/rtc.h>
Arthur Heymansebf201b2019-05-28 13:51:36 +020042#include <southbridge/intel/common/spi.h>
Stefan Reinauer8e073822012-04-04 00:07:22 +020043
44#define NMI_OFF 0
45
46#define ENABLE_ACPI_MODE_IN_COREBOOT 0
Stefan Reinauer8e073822012-04-04 00:07:22 +020047
48typedef struct southbridge_intel_bd82x6x_config config_t;
49
Paul Menzel9c50e6a2013-05-03 12:23:39 +020050/**
51 * Set miscellanous static southbridge features.
52 *
53 * @param dev PCI device with I/O APIC control registers
54 */
55static void pch_enable_ioapic(struct device *dev)
Stefan Reinauer8e073822012-04-04 00:07:22 +020056{
Stefan Reinauer8e073822012-04-04 00:07:22 +020057 u32 reg32;
Stefan Reinauer8e073822012-04-04 00:07:22 +020058
Nico Huberb2dae792015-10-26 12:34:02 +010059 /* Assign unique bus/dev/fn for I/O APIC */
60 pci_write_config16(dev, LPC_IBDF,
61 PCH_IOAPIC_PCI_BUS << 8 | PCH_IOAPIC_PCI_SLOT << 3);
62
Paul Menzel9c50e6a2013-05-03 12:23:39 +020063 /* Enable ACPI I/O range decode */
64 pci_write_config8(dev, ACPI_CNTL, ACPI_EN);
Stefan Reinauer8e073822012-04-04 00:07:22 +020065
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -080066 set_ioapic_id(VIO_APIC_VADDR, 0x02);
Stefan Reinauer8e073822012-04-04 00:07:22 +020067
68 /* affirm full set of redirection table entries ("write once") */
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -080069 reg32 = io_apic_read(VIO_APIC_VADDR, 0x01);
70 io_apic_write(VIO_APIC_VADDR, 0x01, reg32);
Stefan Reinauer8e073822012-04-04 00:07:22 +020071
Paul Menzel9c50e6a2013-05-03 12:23:39 +020072 /*
73 * Select Boot Configuration register (0x03) and
74 * use Processor System Bus (0x01) to deliver interrupts.
75 */
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -080076 io_apic_write(VIO_APIC_VADDR, 0x03, 0x01);
Stefan Reinauer8e073822012-04-04 00:07:22 +020077}
78
79static void pch_enable_serial_irqs(struct device *dev)
80{
81 /* Set packet length and toggle silent mode bit for one frame. */
82 pci_write_config8(dev, SERIRQ_CNTL,
83 (1 << 7) | (1 << 6) | ((21 - 17) << 2) | (0 << 0));
Julius Wernercd49cce2019-03-05 16:53:33 -080084#if !CONFIG(SERIRQ_CONTINUOUS_MODE)
Stefan Reinauer8e073822012-04-04 00:07:22 +020085 pci_write_config8(dev, SERIRQ_CNTL,
86 (1 << 7) | (0 << 6) | ((21 - 17) << 2) | (0 << 0));
87#endif
88}
89
90/* PIRQ[n]_ROUT[3:0] - PIRQ Routing Control
91 * 0x00 - 0000 = Reserved
92 * 0x01 - 0001 = Reserved
93 * 0x02 - 0010 = Reserved
94 * 0x03 - 0011 = IRQ3
95 * 0x04 - 0100 = IRQ4
96 * 0x05 - 0101 = IRQ5
97 * 0x06 - 0110 = IRQ6
98 * 0x07 - 0111 = IRQ7
99 * 0x08 - 1000 = Reserved
100 * 0x09 - 1001 = IRQ9
101 * 0x0A - 1010 = IRQ10
102 * 0x0B - 1011 = IRQ11
103 * 0x0C - 1100 = IRQ12
104 * 0x0D - 1101 = Reserved
105 * 0x0E - 1110 = IRQ14
106 * 0x0F - 1111 = IRQ15
107 * PIRQ[n]_ROUT[7] - PIRQ Routing Control
108 * 0x80 - The PIRQ is not routed.
109 */
110
Elyes HAOUAS4aec3402018-05-25 08:29:27 +0200111static void pch_pirq_init(struct device *dev)
Stefan Reinauer8e073822012-04-04 00:07:22 +0200112{
Elyes HAOUAS4aec3402018-05-25 08:29:27 +0200113 struct device *irq_dev;
Vladimir Serbinenko33b535f2014-10-19 10:13:14 +0200114 /* Interrupt 11 is not used by legacy devices and so can always be used for
115 PCI interrupts. Full legacy IRQ routing is complicated and hard to
116 get right. Fortunately all modern OS use MSI and so it's not that big of
117 an issue anyway. Still we have to provide a reasonable default. Using
118 interrupt 11 for it everywhere is a working default. ACPI-aware OS can
119 move it to any interrupt and others will just leave them at default.
Stefan Reinauer8e073822012-04-04 00:07:22 +0200120 */
Vladimir Serbinenko33b535f2014-10-19 10:13:14 +0200121 const u8 pirq_routing = 11;
122
123 pci_write_config8(dev, PIRQA_ROUT, pirq_routing);
124 pci_write_config8(dev, PIRQB_ROUT, pirq_routing);
125 pci_write_config8(dev, PIRQC_ROUT, pirq_routing);
126 pci_write_config8(dev, PIRQD_ROUT, pirq_routing);
127
128 pci_write_config8(dev, PIRQE_ROUT, pirq_routing);
129 pci_write_config8(dev, PIRQF_ROUT, pirq_routing);
130 pci_write_config8(dev, PIRQG_ROUT, pirq_routing);
131 pci_write_config8(dev, PIRQH_ROUT, pirq_routing);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200132
Elyes HAOUASba28e8d2016-08-31 19:22:16 +0200133 for (irq_dev = all_devices; irq_dev; irq_dev = irq_dev->next) {
Vladimir Serbinenko33b535f2014-10-19 10:13:14 +0200134 u8 int_pin=0;
Stefan Reinauer8e073822012-04-04 00:07:22 +0200135
136 if (!irq_dev->enabled || irq_dev->path.type != DEVICE_PATH_PCI)
137 continue;
138
139 int_pin = pci_read_config8(irq_dev, PCI_INTERRUPT_PIN);
140
Vladimir Serbinenko33b535f2014-10-19 10:13:14 +0200141 if (int_pin == 0)
Stefan Reinauer8e073822012-04-04 00:07:22 +0200142 continue;
143
Vladimir Serbinenko33b535f2014-10-19 10:13:14 +0200144 pci_write_config8(irq_dev, PCI_INTERRUPT_LINE, pirq_routing);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200145 }
146}
147
Elyes HAOUAS4aec3402018-05-25 08:29:27 +0200148static void pch_gpi_routing(struct device *dev)
Stefan Reinauer8e073822012-04-04 00:07:22 +0200149{
150 /* Get the chip configuration */
151 config_t *config = dev->chip_info;
152 u32 reg32 = 0;
153
154 /* An array would be much nicer here, or some
155 * other method of doing this.
156 */
157 reg32 |= (config->gpi0_routing & 0x03) << 0;
158 reg32 |= (config->gpi1_routing & 0x03) << 2;
159 reg32 |= (config->gpi2_routing & 0x03) << 4;
160 reg32 |= (config->gpi3_routing & 0x03) << 6;
161 reg32 |= (config->gpi4_routing & 0x03) << 8;
162 reg32 |= (config->gpi5_routing & 0x03) << 10;
163 reg32 |= (config->gpi6_routing & 0x03) << 12;
164 reg32 |= (config->gpi7_routing & 0x03) << 14;
165 reg32 |= (config->gpi8_routing & 0x03) << 16;
166 reg32 |= (config->gpi9_routing & 0x03) << 18;
167 reg32 |= (config->gpi10_routing & 0x03) << 20;
168 reg32 |= (config->gpi11_routing & 0x03) << 22;
169 reg32 |= (config->gpi12_routing & 0x03) << 24;
170 reg32 |= (config->gpi13_routing & 0x03) << 26;
171 reg32 |= (config->gpi14_routing & 0x03) << 28;
172 reg32 |= (config->gpi15_routing & 0x03) << 30;
173
Kyösti Mälkkib85a87b2014-12-29 11:32:27 +0200174 pci_write_config32(dev, GPIO_ROUT, reg32);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200175}
176
Elyes HAOUAS4aec3402018-05-25 08:29:27 +0200177static void pch_power_options(struct device *dev)
Stefan Reinauer8e073822012-04-04 00:07:22 +0200178{
179 u8 reg8;
180 u16 reg16, pmbase;
181 u32 reg32;
182 const char *state;
183 /* Get the chip configuration */
184 config_t *config = dev->chip_info;
185
Nico Huber9faae2b2018-11-14 00:00:35 +0100186 int pwr_on = CONFIG_MAINBOARD_POWER_FAILURE_STATE;
Stefan Reinauer8e073822012-04-04 00:07:22 +0200187 int nmi_option;
188
189 /* Which state do we want to goto after g3 (power restored)?
190 * 0 == S0 Full On
191 * 1 == S5 Soft Off
192 *
193 * If the option is not existent (Laptops), use Kconfig setting.
194 */
195 get_option(&pwr_on, "power_on_after_fail");
196
197 reg16 = pci_read_config16(dev, GEN_PMCON_3);
198 reg16 &= 0xfffe;
199 switch (pwr_on) {
200 case MAINBOARD_POWER_OFF:
201 reg16 |= 1;
202 state = "off";
203 break;
204 case MAINBOARD_POWER_ON:
205 reg16 &= ~1;
206 state = "on";
207 break;
208 case MAINBOARD_POWER_KEEP:
209 reg16 &= ~1;
210 state = "state keep";
211 break;
212 default:
213 state = "undefined";
214 }
215
216 reg16 &= ~(3 << 4); /* SLP_S4# Assertion Stretch 4s */
217 reg16 |= (1 << 3); /* SLP_S4# Assertion Stretch Enable */
218
219 reg16 &= ~(1 << 10);
220 reg16 |= (1 << 11); /* SLP_S3# Min Assertion Width 50ms */
221
222 reg16 |= (1 << 12); /* Disable SLP stretch after SUS well */
223
224 pci_write_config16(dev, GEN_PMCON_3, reg16);
225 printk(BIOS_INFO, "Set power %s after power failure.\n", state);
226
227 /* Set up NMI on errors. */
228 reg8 = inb(0x61);
229 reg8 &= 0x0f; /* Higher Nibble must be 0 */
230 reg8 &= ~(1 << 3); /* IOCHK# NMI Enable */
231 // reg8 &= ~(1 << 2); /* PCI SERR# Enable */
232 reg8 |= (1 << 2); /* PCI SERR# Disable for now */
233 outb(reg8, 0x61);
234
235 reg8 = inb(0x70);
236 nmi_option = NMI_OFF;
237 get_option(&nmi_option, "nmi");
238 if (nmi_option) {
239 printk(BIOS_INFO, "NMI sources enabled.\n");
240 reg8 &= ~(1 << 7); /* Set NMI. */
241 } else {
242 printk(BIOS_INFO, "NMI sources disabled.\n");
Elyes HAOUAS9c5d4632018-04-26 22:21:21 +0200243 reg8 |= (1 << 7); /* Can't mask NMI from PCI-E and NMI_NOW */
Stefan Reinauer8e073822012-04-04 00:07:22 +0200244 }
245 outb(reg8, 0x70);
246
247 /* Enable CPU_SLP# and Intel Speedstep, set SMI# rate down */
248 reg16 = pci_read_config16(dev, GEN_PMCON_1);
249 reg16 &= ~(3 << 0); // SMI# rate 1 minute
250 reg16 &= ~(1 << 10); // Disable BIOS_PCI_EXP_EN for native PME
251#if DEBUG_PERIODIC_SMIS
252 /* Set DEBUG_PERIODIC_SMIS in pch.h to debug using
253 * periodic SMIs.
254 */
255 reg16 |= (3 << 0); // Periodic SMI every 8s
256#endif
257 pci_write_config16(dev, GEN_PMCON_1, reg16);
258
259 // Set the board's GPI routing.
260 pch_gpi_routing(dev);
261
262 pmbase = pci_read_config16(dev, 0x40) & 0xfffe;
263
264 outl(config->gpe0_en, pmbase + GPE0_EN);
265 outw(config->alt_gp_smi_en, pmbase + ALT_GP_SMI_EN);
266
267 /* Set up power management block and determine sleep mode */
268 reg32 = inl(pmbase + 0x04); // PM1_CNT
269 reg32 &= ~(7 << 10); // SLP_TYP
270 reg32 |= (1 << 0); // SCI_EN
271 outl(reg32, pmbase + 0x04);
272
273 /* Clear magic status bits to prevent unexpected wake */
Patrick Rudolph4f8b1082019-07-14 11:54:58 +0200274 reg32 = RCBA32(PRSTS);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200275 reg32 |= (1 << 4)|(1 << 5)|(1 << 0);
Patrick Rudolph4f8b1082019-07-14 11:54:58 +0200276 RCBA32(PRSTS) = reg32;
Stefan Reinauer8e073822012-04-04 00:07:22 +0200277
278 reg32 = RCBA32(0x3f02);
279 reg32 &= ~0xf;
280 RCBA32(0x3f02) = reg32;
281}
282
Duncan Laurie3f6a4d72012-06-28 13:03:40 -0700283/* CougarPoint PCH Power Management init */
284static void cpt_pm_init(struct device *dev)
Stefan Reinauer8e073822012-04-04 00:07:22 +0200285{
Duncan Laurie3f6a4d72012-06-28 13:03:40 -0700286 printk(BIOS_DEBUG, "CougarPoint PM init\n");
Stefan Reinauer8e073822012-04-04 00:07:22 +0200287 pci_write_config8(dev, 0xa9, 0x47);
Patrick Rudolph4f8b1082019-07-14 11:54:58 +0200288 RCBA32_AND_OR(CIR30, ~0UL, (1 << 6)|(1 << 0));
289 RCBA32_AND_OR(CIR5, ~0UL, (1 << 0));
290 RCBA16_AND_OR(CIR3, ~0UL, (1 << 13)|(1 << 14));
291 RCBA16_AND_OR(CIR2, ~0UL, (1 << 14));
292 RCBA32(DMC) = 0xc0388400;
293 RCBA32_AND_OR(CIR6, ~0UL, (1 << 5)|(1 << 18));
294 RCBA32_AND_OR(CIR9, ~0UL, (1 << 15)|(1 << 1));
295 RCBA32_AND_OR(CIR7, ~0x1f, 0xf);
296 RCBA32(PM_CFG) = 0x050f0000;
297 RCBA32(CIR8) = 0x04000000;
298 RCBA32_AND_OR(CIR10, ~0UL, 0xfffff);
299 RCBA32_AND_OR(CIR11, ~0UL, (1 << 1));
300 RCBA32(CIR12) = 0x0001c000;
301 RCBA32(CIR14) = 0x00061100;
302 RCBA32(CIR15) = 0x7f8fdfff;
303 RCBA32(CIR13) = 0x000003fc;
304 RCBA32(CIR16) = 0x00001000;
305 RCBA32(CIR18) = 0x0001c000;
306 RCBA32(CIR17) = 0x00000800;
307 RCBA32(CIR23) = 0x00001000;
308 RCBA32(CIR19) = 0x00093900;
309 RCBA32(CIR20) = 0x24653002;
310 RCBA32(CIR21) = 0x062108fe;
311 RCBA32_AND_OR(CIR22, 0xf000f000, 0x00670060);
312 RCBA32(CIR24) = 0x01010000;
313 RCBA32(CIR25) = 0x01010404;
314 RCBA32(CIR27) = 0x01041041;
315 RCBA32_AND_OR(CIR28, ~0x0000ffff, 0x00001001);
316 RCBA32_AND_OR(CIR28, ~0UL, (1 << 24)); /* SATA 2/3 disabled */
317 RCBA32_AND_OR(CIR29, ~0UL, (1 << 0)); /* SATA 4/5 disabled */
318 RCBA32(CIR26) = 0x00000001;
Stefan Reinauer8e073822012-04-04 00:07:22 +0200319 RCBA32_AND_OR(0x2344, 0x00ffff00, 0xff00000c);
320 RCBA32_AND_OR(0x80c, ~(0xff << 20), 0x11 << 20);
Patrick Rudolph4f8b1082019-07-14 11:54:58 +0200321 RCBA32(PMSYNC_CFG) = 0;
Stefan Reinauer8e073822012-04-04 00:07:22 +0200322 RCBA32_AND_OR(0x21b0, ~0UL, 0xf);
323}
324
Duncan Laurie3f6a4d72012-06-28 13:03:40 -0700325/* PantherPoint PCH Power Management init */
326static void ppt_pm_init(struct device *dev)
327{
328 printk(BIOS_DEBUG, "PantherPoint PM init\n");
329 pci_write_config8(dev, 0xa9, 0x47);
Patrick Rudolph4f8b1082019-07-14 11:54:58 +0200330 RCBA32_AND_OR(CIR30, ~0UL, (1 << 0));
331 RCBA32_AND_OR(CIR5, ~0UL, (1 << 0));
332 RCBA16_AND_OR(CIR3, ~0UL, (1 << 13)|(1 << 14));
333 RCBA16_AND_OR(CIR2, ~0UL, (1 << 14));
334 RCBA32(DMC) = 0xc03b8400;
335 RCBA32_AND_OR(CIR6, ~0UL, (1 << 5)|(1 << 18));
336 RCBA32_AND_OR(CIR9, ~0UL, (1 << 15)|(1 << 1));
337 RCBA32_AND_OR(CIR7, ~0x1f, 0xf);
338 RCBA32(PM_CFG) = 0x054f0000;
339 RCBA32(CIR8) = 0x04000000;
340 RCBA32_AND_OR(CIR10, ~0UL, 0xfffff);
341 RCBA32_AND_OR(CIR11, ~0UL, (1 << 1)|(1 << 0));
342 RCBA32(CIR12) = 0x0001c000;
343 RCBA32(CIR14) = 0x00061100;
344 RCBA32(CIR15) = 0x7f8fdfff;
345 RCBA32(CIR13) = 0x000003fd;
346 RCBA32(CIR16) = 0x00001000;
347 RCBA32(CIR18) = 0x0001c000;
348 RCBA32(CIR17) = 0x00000800;
349 RCBA32(CIR23) = 0x00001000;
350 RCBA32(CIR19) = 0x00093900;
351 RCBA32(CIR20) = 0x24653002;
352 RCBA32(CIR21) = 0x067388fe;
353 RCBA32_AND_OR(CIR22, 0xf000f000, 0x00670060);
354 RCBA32(CIR24) = 0x01010000;
355 RCBA32(CIR25) = 0x01010404;
356 RCBA32(CIR27) = 0x01040000;
357 RCBA32_AND_OR(CIR28, ~0x0000ffff, 0x00001001);
358 RCBA32_AND_OR(CIR28, ~0UL, (1 << 24)); /* SATA 2/3 disabled */
359 RCBA32_AND_OR(CIR29, ~0UL, (1 << 0)); /* SATA 4/5 disabled */
360 RCBA32(CIR26) = 0x00000001;
Duncan Laurie3f6a4d72012-06-28 13:03:40 -0700361 RCBA32_AND_OR(0x2344, 0x00ffff00, 0xff00000c);
362 RCBA32_AND_OR(0x80c, ~(0xff << 20), 0x11 << 20);
363 RCBA32_AND_OR(0x33a4, ~0UL, (1 << 0));
Patrick Rudolph4f8b1082019-07-14 11:54:58 +0200364 RCBA32(PMSYNC_CFG) = 0;
Duncan Laurie3f6a4d72012-06-28 13:03:40 -0700365 RCBA32_AND_OR(0x21b0, ~0UL, 0xf);
366}
367
Nico Huberb2dae792015-10-26 12:34:02 +0100368static void enable_hpet(struct device *const dev)
Stefan Reinauer8e073822012-04-04 00:07:22 +0200369{
370 u32 reg32;
Nico Huberb2dae792015-10-26 12:34:02 +0100371 size_t i;
372
373 /* Assign unique bus/dev/fn for each HPET */
374 for (i = 0; i < 8; ++i)
375 pci_write_config16(dev, LPC_HnBDF(i),
376 PCH_HPET_PCI_BUS << 8 | PCH_HPET_PCI_SLOT << 3 | i);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200377
378 /* Move HPET to default address 0xfed00000 and enable it */
379 reg32 = RCBA32(HPTC);
380 reg32 |= (1 << 7); // HPET Address Enable
381 reg32 &= ~(3 << 0);
382 RCBA32(HPTC) = reg32;
383}
384
Elyes HAOUAS4aec3402018-05-25 08:29:27 +0200385static void enable_clock_gating(struct device *dev)
Stefan Reinauer8e073822012-04-04 00:07:22 +0200386{
387 u32 reg32;
388 u16 reg16;
389
Patrick Rudolph4f8b1082019-07-14 11:54:58 +0200390 RCBA32_AND_OR(DMIC, ~0UL, 0xf);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200391
392 reg16 = pci_read_config16(dev, GEN_PMCON_1);
393 reg16 |= (1 << 2) | (1 << 11);
394 pci_write_config16(dev, GEN_PMCON_1, reg16);
395
396 pch_iobp_update(0xEB007F07, ~0UL, (1 << 31));
397 pch_iobp_update(0xEB004000, ~0UL, (1 << 7));
398 pch_iobp_update(0xEC007F07, ~0UL, (1 << 31));
399 pch_iobp_update(0xEC004000, ~0UL, (1 << 7));
400
401 reg32 = RCBA32(CG);
402 reg32 |= (1 << 31);
403 reg32 |= (1 << 29) | (1 << 28);
404 reg32 |= (1 << 27) | (1 << 26) | (1 << 25) | (1 << 24);
405 reg32 |= (1 << 16);
406 reg32 |= (1 << 17);
407 reg32 |= (1 << 18);
408 reg32 |= (1 << 22);
409 reg32 |= (1 << 23);
410 reg32 &= ~(1 << 20);
411 reg32 |= (1 << 19);
412 reg32 |= (1 << 0);
413 reg32 |= (0xf << 1);
414 RCBA32(CG) = reg32;
415
416 RCBA32_OR(0x38c0, 0x7);
417 RCBA32_OR(0x36d4, 0x6680c004);
418 RCBA32_OR(0x3564, 0x3);
419}
420
Vladimir Serbinenkoa3e41c02015-05-28 16:04:17 +0200421static void pch_set_acpi_mode(void)
Stefan Reinauer8e073822012-04-04 00:07:22 +0200422{
Julius Werner5d1f9a02019-03-07 17:07:26 -0800423 if (!acpi_is_wakeup_s3() && CONFIG(HAVE_SMI_HANDLER)) {
Stefan Reinauer8e073822012-04-04 00:07:22 +0200424#if ENABLE_ACPI_MODE_IN_COREBOOT
Duncan Laurie95be1d62012-04-09 12:31:43 -0700425 printk(BIOS_DEBUG, "Enabling ACPI via APMC:\n");
Vladimir Serbinenkoa3e41c02015-05-28 16:04:17 +0200426 outb(APM_CNT_ACPI_ENABLE, APM_CNT); // Enable ACPI mode
Duncan Laurie95be1d62012-04-09 12:31:43 -0700427 printk(BIOS_DEBUG, "done.\n");
Stefan Reinauer8e073822012-04-04 00:07:22 +0200428#else
Duncan Laurie95be1d62012-04-09 12:31:43 -0700429 printk(BIOS_DEBUG, "Disabling ACPI via APMC:\n");
Vladimir Serbinenkoa3e41c02015-05-28 16:04:17 +0200430 outb(APM_CNT_ACPI_DISABLE, APM_CNT); // Disable ACPI mode
Duncan Laurie95be1d62012-04-09 12:31:43 -0700431 printk(BIOS_DEBUG, "done.\n");
Stefan Reinauer8e073822012-04-04 00:07:22 +0200432#endif
Duncan Laurie95be1d62012-04-09 12:31:43 -0700433 }
Stefan Reinauer8e073822012-04-04 00:07:22 +0200434}
Stefan Reinauer8e073822012-04-04 00:07:22 +0200435
436static void pch_disable_smm_only_flashing(struct device *dev)
437{
438 u8 reg8;
439
440 printk(BIOS_SPEW, "Enabling BIOS updates outside of SMM... ");
Elyes HAOUAS0c22d2f2018-12-01 12:19:52 +0100441 reg8 = pci_read_config8(dev, BIOS_CNTL);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200442 reg8 &= ~(1 << 5);
Elyes HAOUAS0c22d2f2018-12-01 12:19:52 +0100443 pci_write_config8(dev, BIOS_CNTL, reg8);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200444}
445
446static void pch_fixups(struct device *dev)
447{
448 u8 gen_pmcon_2;
449
450 /* Indicate DRAM init done for MRC S3 to know it can resume */
451 gen_pmcon_2 = pci_read_config8(dev, GEN_PMCON_2);
452 gen_pmcon_2 |= (1 << 7);
453 pci_write_config8(dev, GEN_PMCON_2, gen_pmcon_2);
454
455 /*
456 * Enable DMI ASPM in the PCH
457 */
Patrick Rudolph4f8b1082019-07-14 11:54:58 +0200458 RCBA32_AND_OR(DMC, ~(1 << 10), 0);
459 RCBA32_OR(LCAP, (1 << 11)|(1 << 10));
460 RCBA32_OR(LCTL, 0x3);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200461}
462
463static void pch_decode_init(struct device *dev)
464{
465 config_t *config = dev->chip_info;
466
467 printk(BIOS_DEBUG, "pch_decode_init\n");
468
469 pci_write_config32(dev, LPC_GEN1_DEC, config->gen1_dec);
470 pci_write_config32(dev, LPC_GEN2_DEC, config->gen2_dec);
471 pci_write_config32(dev, LPC_GEN3_DEC, config->gen3_dec);
472 pci_write_config32(dev, LPC_GEN4_DEC, config->gen4_dec);
473}
474
Nico Huber7b2f9f62015-10-01 19:00:51 +0200475static void pch_spi_init(const struct device *const dev)
476{
477 const config_t *const config = dev->chip_info;
478
479 printk(BIOS_DEBUG, "pch_spi_init\n");
480
481 if (config->spi_uvscc)
482 RCBA32(0x3800 + 0xc8) = config->spi_uvscc;
483 if (config->spi_lvscc)
484 RCBA32(0x3800 + 0xc4) = config->spi_lvscc;
485
486 if (config->spi_uvscc || config->spi_lvscc)
487 RCBA32_OR(0x3800 + 0xc4, 1 << 23); /* lock both UVSCC + LVSCC */
488}
489
Patrick Rudolphef8c5592018-07-27 17:48:27 +0200490static const struct {
491 u16 dev_id;
492 const char *dev_name;
493} pch_table[] = {
494 /* 6-series PCI ids from
495 * Intel® 6 Series Chipset and
496 * Intel® C200 Series Chipset
497 * Specification Update - NDA
498 * October 2013
499 * CDI / IBP#: 440377
500 */
501 {0x1C41, "SFF Sample"},
502 {0x1C42, "Desktop Sample"},
503 {0x1C43, "Mobile Sample"},
504 {0x1C44, "Z68"},
505 {0x1C46, "P67"},
506 {0x1C47, "UM67"},
507 {0x1C49, "HM65"},
508 {0x1C4A, "H67"},
509 {0x1C4B, "HM67"},
510 {0x1C4C, "Q65"},
511 {0x1C4D, "QS67"},
512 {0x1C4E, "Q67"},
513 {0x1C4F, "QM67"},
514 {0x1C50, "B65"},
515 {0x1C52, "C202"},
516 {0x1C54, "C204"},
517 {0x1C56, "C206"},
518 {0x1C5C, "H61"},
519 /* 7-series PCI ids from Intel document 472178 */
520 {0x1E41, "Desktop Sample"},
521 {0x1E42, "Mobile Sample"},
522 {0x1E43, "SFF Sample"},
523 {0x1E44, "Z77"},
524 {0x1E45, "H71"},
525 {0x1E46, "Z75"},
526 {0x1E47, "Q77"},
527 {0x1E48, "Q75"},
528 {0x1E49, "B75"},
529 {0x1E4A, "H77"},
530 {0x1E53, "C216"},
531 {0x1E55, "QM77"},
532 {0x1E56, "QS77"},
533 {0x1E58, "UM77"},
534 {0x1E57, "HM77"},
535 {0x1E59, "HM76"},
536 {0x1E5D, "HM75"},
537 {0x1E5E, "HM70"},
538 {0x1E5F, "NM70"},
539};
540
541static void report_pch_info(struct device *dev)
542{
543 const u16 dev_id = pci_read_config16(dev, PCI_DEVICE_ID);
544 int i;
545
546 const char *pch_type = "Unknown";
547 for (i = 0; i < ARRAY_SIZE(pch_table); i++) {
548 if (pch_table[i].dev_id == dev_id) {
549 pch_type = pch_table[i].dev_name;
550 break;
551 }
552 }
553 printk(BIOS_INFO, "PCH: detected %s, device id: 0x%x, rev id 0x%x\n",
554 pch_type, dev_id, pci_read_config8(dev, PCI_CLASS_REVISION));
555}
556
Stefan Reinauer8e073822012-04-04 00:07:22 +0200557static void lpc_init(struct device *dev)
558{
559 printk(BIOS_DEBUG, "pch: lpc_init\n");
560
Patrick Rudolphef8c5592018-07-27 17:48:27 +0200561 /* Print detected platform */
562 report_pch_info(dev);
563
Stefan Reinauer8e073822012-04-04 00:07:22 +0200564 /* Set the value for PCI command register. */
565 pci_write_config16(dev, PCI_COMMAND, 0x000f);
566
567 /* IO APIC initialization. */
Paul Menzel9c50e6a2013-05-03 12:23:39 +0200568 pch_enable_ioapic(dev);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200569
570 pch_enable_serial_irqs(dev);
571
572 /* Setup the PIRQ. */
573 pch_pirq_init(dev);
574
575 /* Setup power options. */
576 pch_power_options(dev);
577
578 /* Initialize power management */
Duncan Laurie3f6a4d72012-06-28 13:03:40 -0700579 switch (pch_silicon_type()) {
580 case PCH_TYPE_CPT: /* CougarPoint */
581 cpt_pm_init(dev);
582 break;
583 case PCH_TYPE_PPT: /* PantherPoint */
584 ppt_pm_init(dev);
585 break;
586 default:
587 printk(BIOS_ERR, "Unknown Chipset: 0x%04x\n", dev->device);
588 }
Stefan Reinauer8e073822012-04-04 00:07:22 +0200589
590 /* Set the state of the GPIO lines. */
591 //gpio_init(dev);
592
593 /* Initialize the real time clock. */
Patrick Rudolph6b931122018-11-01 17:48:37 +0100594 sb_rtc_init();
Stefan Reinauer8e073822012-04-04 00:07:22 +0200595
596 /* Initialize ISA DMA. */
597 isa_dma_init();
598
599 /* Initialize the High Precision Event Timers, if present. */
Nico Huberb2dae792015-10-26 12:34:02 +0100600 enable_hpet(dev);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200601
602 /* Initialize Clock Gating */
603 enable_clock_gating(dev);
604
605 setup_i8259();
606
607 /* The OS should do this? */
608 /* Interrupt 9 should be level triggered (SCI) */
609 i8259_configure_irq_trigger(9, 1);
610
611 pch_disable_smm_only_flashing(dev);
612
Vladimir Serbinenkoa3e41c02015-05-28 16:04:17 +0200613 pch_set_acpi_mode();
Stefan Reinauer8e073822012-04-04 00:07:22 +0200614
615 pch_fixups(dev);
Nico Huber7b2f9f62015-10-01 19:00:51 +0200616
617 pch_spi_init(dev);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200618}
619
Elyes HAOUAS4aec3402018-05-25 08:29:27 +0200620static void pch_lpc_read_resources(struct device *dev)
Stefan Reinauer8e073822012-04-04 00:07:22 +0200621{
622 struct resource *res;
Marc Jonesa0bec172012-07-13 14:14:34 -0600623 config_t *config = dev->chip_info;
624 u8 io_index = 0;
Stefan Reinauer8e073822012-04-04 00:07:22 +0200625
626 /* Get the normal PCI resources of this device. */
627 pci_dev_read_resources(dev);
628
629 /* Add an extra subtractive resource for both memory and I/O. */
Marc Jonesa0bec172012-07-13 14:14:34 -0600630 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
Stefan Reinauer8e073822012-04-04 00:07:22 +0200631 res->base = 0;
632 res->size = 0x1000;
633 res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
634 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
635
Marc Jonesa0bec172012-07-13 14:14:34 -0600636 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
Vladimir Serbinenko0650cd02014-02-05 15:03:50 +0100637 res->base = 0xff000000;
638 /* Some systems (e.g. X230) have 12 MiB flash.
639 SPI controller supports up to 2 x 16 MiB of flash but
640 address map limits this to 16MiB. */
641 res->size = 0x01000000; /* 16 MB for flash */
Stefan Reinauer8e073822012-04-04 00:07:22 +0200642 res->flags = IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE |
643 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
644
645 res = new_resource(dev, 3); /* IOAPIC */
646 res->base = IO_APIC_ADDR;
647 res->size = 0x00001000;
648 res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
Marc Jonesa0bec172012-07-13 14:14:34 -0600649
650 /* Set PCH IO decode ranges if required.*/
651 if ((config->gen1_dec & 0xFFFC) > 0x1000) {
652 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
653 res->base = config->gen1_dec & 0xFFFC;
654 res->size = (config->gen1_dec >> 16) & 0xFC;
655 res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
656 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
657 }
658
659 if ((config->gen2_dec & 0xFFFC) > 0x1000) {
660 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
661 res->base = config->gen2_dec & 0xFFFC;
662 res->size = (config->gen2_dec >> 16) & 0xFC;
663 res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
664 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
665 }
666
667 if ((config->gen3_dec & 0xFFFC) > 0x1000) {
668 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
669 res->base = config->gen3_dec & 0xFFFC;
670 res->size = (config->gen3_dec >> 16) & 0xFC;
671 res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
672 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
673 }
674
675 if ((config->gen4_dec & 0xFFFC) > 0x1000) {
676 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
677 res->base = config->gen4_dec & 0xFFFC;
678 res->size = (config->gen4_dec >> 16) & 0xFC;
679 res->flags = IORESOURCE_IO| IORESOURCE_SUBTRACTIVE |
680 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
681 }
Stefan Reinauer8e073822012-04-04 00:07:22 +0200682}
683
Elyes HAOUAS4aec3402018-05-25 08:29:27 +0200684static void pch_lpc_enable_resources(struct device *dev)
Stefan Reinauer8e073822012-04-04 00:07:22 +0200685{
686 pch_decode_init(dev);
687 return pci_dev_enable_resources(dev);
688}
689
Elyes HAOUAS4aec3402018-05-25 08:29:27 +0200690static void pch_lpc_enable(struct device *dev)
Stefan Reinauer8e073822012-04-04 00:07:22 +0200691{
692 /* Enable PCH Display Port */
693 RCBA16(DISPBDF) = 0x0010;
694 RCBA32_OR(FD2, PCH_ENABLE_DBDF);
695
696 pch_enable(dev);
697}
698
Elyes HAOUAS4aec3402018-05-25 08:29:27 +0200699static void southbridge_inject_dsdt(struct device *dev)
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +0200700{
Elyes HAOUAS035df002016-10-03 21:54:16 +0200701 global_nvs_t *gnvs = cbmem_add (CBMEM_ID_ACPI_GNVS, sizeof(*gnvs));
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +0200702
703 if (gnvs) {
Vladimir Serbinenkodd2bc3f2014-10-31 09:16:31 +0100704 const struct i915_gpu_controller_info *gfx = intel_gma_get_controller_info();
Elyes HAOUAS035df002016-10-03 21:54:16 +0200705 memset(gnvs, 0, sizeof(*gnvs));
Vladimir Serbinenko7309c642014-10-05 11:07:33 +0200706
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +0200707 acpi_create_gnvs(gnvs);
Vladimir Serbinenko06c788d2014-10-12 00:17:11 +0200708
709 gnvs->apic = 1;
710 gnvs->mpen = 1; /* Enable Multi Processing */
711 gnvs->pcnt = dev_count_cpu();
712
Nico Huber744d6bd2019-01-12 14:58:20 +0100713 if (gfx) {
714 gnvs->ndid = gfx->ndid;
715 memcpy(gnvs->did, gfx->did, sizeof(gnvs->did));
716 }
Vladimir Serbinenkodd2bc3f2014-10-31 09:16:31 +0100717
Julius Wernercd49cce2019-03-05 16:53:33 -0800718#if CONFIG(CHROMEOS)
Joel Kitching6fbd8742018-08-23 14:56:25 +0800719 chromeos_init_chromeos_acpi(&(gnvs->chromeos));
Vladimir Serbinenko06c788d2014-10-12 00:17:11 +0200720#endif
721
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +0200722 /* And tell SMI about it */
723 smm_setup_structures(gnvs, NULL, NULL);
724
Vladimir Serbinenko334fd8e2014-10-05 11:10:35 +0200725 /* Add it to DSDT. */
Vladimir Serbinenko226d7842014-11-04 21:09:23 +0100726 acpigen_write_scope("\\");
727 acpigen_write_name_dword("NVSA", (u32) gnvs);
728 acpigen_pop_len();
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +0200729 }
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +0200730}
731
Vladimir Serbinenko5b044ae2014-10-25 15:20:55 +0200732void acpi_fill_fadt(acpi_fadt_t *fadt)
733{
Kyösti Mälkkic70eed12018-05-22 02:18:00 +0300734 struct device *dev = pcidev_on_root(0x1f, 0);
Vladimir Serbinenko5b044ae2014-10-25 15:20:55 +0200735 config_t *chip = dev->chip_info;
736 u16 pmbase = pci_read_config16(dev, 0x40) & 0xfffe;
737 int c2_latency;
738
Elyes HAOUAS0d4de2a2019-02-28 13:04:29 +0100739 fadt->reserved = 0;
Vladimir Serbinenko5b044ae2014-10-25 15:20:55 +0200740
741 fadt->sci_int = 0x9;
742 fadt->smi_cmd = APM_CNT;
743 fadt->acpi_enable = APM_CNT_ACPI_ENABLE;
744 fadt->acpi_disable = APM_CNT_ACPI_DISABLE;
745 fadt->s4bios_req = 0x0;
746 fadt->pstate_cnt = 0;
747
748 fadt->pm1a_evt_blk = pmbase;
749 fadt->pm1b_evt_blk = 0x0;
750 fadt->pm1a_cnt_blk = pmbase + 0x4;
751 fadt->pm1b_cnt_blk = 0x0;
752 fadt->pm2_cnt_blk = pmbase + 0x50;
753 fadt->pm_tmr_blk = pmbase + 0x8;
754 fadt->gpe0_blk = pmbase + 0x20;
755 fadt->gpe1_blk = 0;
756
757 fadt->pm1_evt_len = 4;
758 fadt->pm1_cnt_len = 2;
759 fadt->pm2_cnt_len = 1;
760 fadt->pm_tmr_len = 4;
761 fadt->gpe0_blk_len = 16;
762 fadt->gpe1_blk_len = 0;
763 fadt->gpe1_base = 0;
764 fadt->cst_cnt = 0;
765 c2_latency = chip->c2_latency;
766 if (!c2_latency) {
767 c2_latency = 101; /* c2 unsupported */
768 }
769 fadt->p_lvl2_lat = c2_latency;
770 fadt->p_lvl3_lat = 87;
771 fadt->flush_size = 1024;
772 fadt->flush_stride = 16;
Patrick Rudolphb30a47b2019-07-15 18:04:23 +0200773 /* P_CNT not supported */
774 fadt->duty_offset = 0;
775 fadt->duty_width = 0;
776
Vladimir Serbinenko5b044ae2014-10-25 15:20:55 +0200777 fadt->day_alrm = 0xd;
778 fadt->mon_alrm = 0x00;
779 fadt->century = 0x00;
780 fadt->iapc_boot_arch = ACPI_FADT_LEGACY_DEVICES | ACPI_FADT_8042;
781
782 fadt->flags = ACPI_FADT_WBINVD |
783 ACPI_FADT_C1_SUPPORTED |
784 ACPI_FADT_SLEEP_BUTTON |
785 ACPI_FADT_RESET_REGISTER |
786 ACPI_FADT_SEALED_CASE |
787 ACPI_FADT_S4_RTC_WAKE |
788 ACPI_FADT_PLATFORM_CLOCK;
789 if (chip->docking_supported) {
790 fadt->flags |= ACPI_FADT_DOCKING_SUPPORTED;
791 }
792 if (c2_latency < 100) {
793 fadt->flags |= ACPI_FADT_C2_MP_SUPPORTED;
794 }
795
796 fadt->reset_reg.space_id = 1;
797 fadt->reset_reg.bit_width = 8;
798 fadt->reset_reg.bit_offset = 0;
799 fadt->reset_reg.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
800 fadt->reset_reg.addrl = 0xcf9;
801 fadt->reset_reg.addrh = 0;
802
803 fadt->reset_value = 6;
804
805 fadt->x_pm1a_evt_blk.space_id = 1;
806 fadt->x_pm1a_evt_blk.bit_width = 32;
807 fadt->x_pm1a_evt_blk.bit_offset = 0;
808 fadt->x_pm1a_evt_blk.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
809 fadt->x_pm1a_evt_blk.addrl = pmbase;
810 fadt->x_pm1a_evt_blk.addrh = 0x0;
811
812 fadt->x_pm1b_evt_blk.space_id = 1;
813 fadt->x_pm1b_evt_blk.bit_width = 0;
814 fadt->x_pm1b_evt_blk.bit_offset = 0;
815 fadt->x_pm1b_evt_blk.access_size = 0;
816 fadt->x_pm1b_evt_blk.addrl = 0x0;
817 fadt->x_pm1b_evt_blk.addrh = 0x0;
818
819 fadt->x_pm1a_cnt_blk.space_id = 1;
820 fadt->x_pm1a_cnt_blk.bit_width = 16;
821 fadt->x_pm1a_cnt_blk.bit_offset = 0;
822 fadt->x_pm1a_cnt_blk.access_size = ACPI_ACCESS_SIZE_WORD_ACCESS;
823 fadt->x_pm1a_cnt_blk.addrl = pmbase + 0x4;
824 fadt->x_pm1a_cnt_blk.addrh = 0x0;
825
826 fadt->x_pm1b_cnt_blk.space_id = 1;
827 fadt->x_pm1b_cnt_blk.bit_width = 0;
828 fadt->x_pm1b_cnt_blk.bit_offset = 0;
829 fadt->x_pm1b_cnt_blk.access_size = 0;
830 fadt->x_pm1b_cnt_blk.addrl = 0x0;
831 fadt->x_pm1b_cnt_blk.addrh = 0x0;
832
833 fadt->x_pm2_cnt_blk.space_id = 1;
834 fadt->x_pm2_cnt_blk.bit_width = 8;
835 fadt->x_pm2_cnt_blk.bit_offset = 0;
836 fadt->x_pm2_cnt_blk.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
837 fadt->x_pm2_cnt_blk.addrl = pmbase + 0x50;
838 fadt->x_pm2_cnt_blk.addrh = 0x0;
839
840 fadt->x_pm_tmr_blk.space_id = 1;
841 fadt->x_pm_tmr_blk.bit_width = 32;
842 fadt->x_pm_tmr_blk.bit_offset = 0;
843 fadt->x_pm_tmr_blk.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
844 fadt->x_pm_tmr_blk.addrl = pmbase + 0x8;
845 fadt->x_pm_tmr_blk.addrh = 0x0;
846
847 fadt->x_gpe0_blk.space_id = 1;
848 fadt->x_gpe0_blk.bit_width = 128;
849 fadt->x_gpe0_blk.bit_offset = 0;
850 fadt->x_gpe0_blk.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
851 fadt->x_gpe0_blk.addrl = pmbase + 0x20;
852 fadt->x_gpe0_blk.addrh = 0x0;
853
854 fadt->x_gpe1_blk.space_id = 1;
855 fadt->x_gpe1_blk.bit_width = 0;
856 fadt->x_gpe1_blk.bit_offset = 0;
857 fadt->x_gpe1_blk.access_size = 0;
858 fadt->x_gpe1_blk.addrl = 0x0;
859 fadt->x_gpe1_blk.addrh = 0x0;
860}
861
Aaron Durbinaa090cb2017-09-13 16:01:52 -0600862static const char *lpc_acpi_name(const struct device *dev)
Patrick Rudolph604f6982017-06-07 09:46:52 +0200863{
864 return "LPCB";
865}
866
Elyes HAOUAS4aec3402018-05-25 08:29:27 +0200867static void southbridge_fill_ssdt(struct device *device)
Vladimir Serbinenko36fa5b82014-10-28 23:43:20 +0100868{
Kyösti Mälkkic70eed12018-05-22 02:18:00 +0300869 struct device *dev = pcidev_on_root(0x1f, 0);
Vladimir Serbinenko36fa5b82014-10-28 23:43:20 +0100870 config_t *chip = dev->chip_info;
871
872 intel_acpi_pcie_hotplug_generator(chip->pcie_hotplug_map, 8);
Tobias Diedrich7f5efd92017-12-14 00:29:01 +0100873 intel_acpi_gen_def_acpi_pirq(dev);
Vladimir Serbinenko36fa5b82014-10-28 23:43:20 +0100874}
875
Vladimir Serbinenkob06a2492015-05-21 10:32:59 +0200876static void lpc_final(struct device *dev)
877{
Arthur Heymansebf201b2019-05-28 13:51:36 +0200878 spi_finalize_ops();
Nico Huber8e50b6d2018-02-04 15:52:18 +0100879
Bill XIEd533b162017-08-22 16:26:22 +0800880 /* Call SMM finalize() handlers before resume */
Julius Wernercd49cce2019-03-05 16:53:33 -0800881 if (CONFIG(HAVE_SMI_HANDLER)) {
882 if (CONFIG(INTEL_CHIPSET_LOCKDOWN) ||
Bill XIEd533b162017-08-22 16:26:22 +0800883 acpi_is_wakeup_s3()) {
884 outb(APM_CNT_FINALIZE, APM_CNT);
885 }
Vladimir Serbinenkob06a2492015-05-21 10:32:59 +0200886 }
887}
888
Arthur Heymansebf201b2019-05-28 13:51:36 +0200889void intel_southbridge_override_spi(
890 struct intel_swseq_spi_config *spi_config)
891{
892 struct device *dev = pcidev_on_root(0x1f, 0);
893
894 if (!dev)
895 return;
896 /* Devicetree may override defaults. */
897 const config_t *const config = dev->chip_info;
898
899 if (!config)
900 return;
901
902 if (config->spi.ops[0].op != 0)
903 memcpy(spi_config, &config->spi, sizeof(*spi_config));
904}
905
Stefan Reinauer8e073822012-04-04 00:07:22 +0200906static struct pci_operations pci_ops = {
Subrata Banik4a0f0712019-03-20 14:29:47 +0530907 .set_subsystem = pci_dev_set_subsystem,
Stefan Reinauer8e073822012-04-04 00:07:22 +0200908};
909
910static struct device_operations device_ops = {
911 .read_resources = pch_lpc_read_resources,
912 .set_resources = pci_dev_set_resources,
913 .enable_resources = pch_lpc_enable_resources,
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +0200914 .write_acpi_tables = acpi_write_hpet,
Vladimir Serbinenko334fd8e2014-10-05 11:10:35 +0200915 .acpi_inject_dsdt_generator = southbridge_inject_dsdt,
Vladimir Serbinenko36fa5b82014-10-28 23:43:20 +0100916 .acpi_fill_ssdt_generator = southbridge_fill_ssdt,
Patrick Rudolph604f6982017-06-07 09:46:52 +0200917 .acpi_name = lpc_acpi_name,
Stefan Reinauer8e073822012-04-04 00:07:22 +0200918 .init = lpc_init,
Vladimir Serbinenkob06a2492015-05-21 10:32:59 +0200919 .final = lpc_final,
Stefan Reinauer8e073822012-04-04 00:07:22 +0200920 .enable = pch_lpc_enable,
Kyösti Mälkkid0e212c2015-02-26 20:47:47 +0200921 .scan_bus = scan_lpc_bus,
Stefan Reinauer8e073822012-04-04 00:07:22 +0200922 .ops_pci = &pci_ops,
923};
924
925
Kimarie Hoote6f459c2012-07-14 08:26:08 -0600926/* IDs for LPC device of Intel 6 Series Chipset, Intel 7 Series Chipset, and
927 * Intel C200 Series Chipset
Stefan Reinauer8e073822012-04-04 00:07:22 +0200928 */
929
Vladimir Serbinenko42d55e02016-01-02 01:47:26 +0100930static const unsigned short pci_device_ids[] = {
931 0x1c40, 0x1c41, 0x1c42, 0x1c43, 0x1c44, 0x1c45, 0x1c46, 0x1c47, 0x1c48,
932 0x1c49, 0x1c4a, 0x1c4b, 0x1c4c, 0x1c4d, 0x1c4e, 0x1c4f, 0x1c50, 0x1c51,
933 0x1c52, 0x1c53, 0x1c54, 0x1c55, 0x1c56, 0x1c57, 0x1c58, 0x1c59, 0x1c5a,
934 0x1c5b, 0x1c5c, 0x1c5d, 0x1c5e, 0x1c5f,
935
936 0x1e41, 0x1e42, 0x1e43, 0x1e44, 0x1e45, 0x1e46, 0x1e47, 0x1e48, 0x1e49,
937 0x1e4a, 0x1e4b, 0x1e4c, 0x1e4d, 0x1e4e, 0x1e4f, 0x1e50, 0x1e51, 0x1e52,
938 0x1e53, 0x1e54, 0x1e55, 0x1e56, 0x1e57, 0x1e58, 0x1e59, 0x1e5a, 0x1e5b,
939 0x1e5c, 0x1e5d, 0x1e5e, 0x1e5f,
940
941 0 };
Stefan Reinauer9a380ab2012-06-22 13:16:11 -0700942
943static const struct pci_driver pch_lpc __pci_driver = {
944 .ops = &device_ops,
945 .vendor = PCI_VENDOR_ID_INTEL,
946 .devices = pci_device_ids,
Stefan Reinauer8e073822012-04-04 00:07:22 +0200947};