blob: 91d710e2a0d37c86b36b484742422bd43dd98d32 [file] [log] [blame]
Stefan Reinauer8e073822012-04-04 00:07:22 +02001/*
2 * This file is part of the coreboot project.
3 *
Stefan Reinauer8e073822012-04-04 00:07:22 +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.
Stefan Reinauer8e073822012-04-04 00:07:22 +020014 */
15
16#include <console/console.h>
17#include <device/device.h>
18#include <device/pci.h>
19#include <device/pci_ids.h>
Patrick Rudolphe56189c2018-04-18 10:11:59 +020020#include <device/pci_ops.h>
Patrick Rudolphef8c5592018-07-27 17:48:27 +020021#include <device/pci_def.h>
Kyösti Mälkkicbf95712020-01-05 08:05:45 +020022#include <option.h>
Stefan Reinauer8e073822012-04-04 00:07:22 +020023#include <pc80/isa-dma.h>
24#include <pc80/i8259.h>
25#include <arch/io.h>
26#include <arch/ioapic.h>
27#include <arch/acpi.h>
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +020028#include <arch/acpigen.h>
Vladimir Serbinenko5b044ae2014-10-25 15:20:55 +020029#include <cpu/x86/smm.h>
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +020030#include <cbmem.h>
Vladimir Serbinenko7309c642014-10-05 11:07:33 +020031#include <string.h>
Kyösti Mälkki12b121c2019-08-18 16:33:39 +030032#include "chip.h"
Stefan Reinauer8e073822012-04-04 00:07:22 +020033#include "pch.h"
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +020034#include "nvs.h"
Vladimir Serbinenko36fa5b82014-10-28 23:43:20 +010035#include <southbridge/intel/common/pciehp.h>
Tobias Diedrich7f5efd92017-12-14 00:29:01 +010036#include <southbridge/intel/common/acpi_pirq_gen.h>
Arthur Heymansa0508172018-01-25 11:30:22 +010037#include <southbridge/intel/common/pmutil.h>
Patrick Rudolph6b931122018-11-01 17:48:37 +010038#include <southbridge/intel/common/rtc.h>
Arthur Heymansebf201b2019-05-28 13:51:36 +020039#include <southbridge/intel/common/spi.h>
Stefan Reinauer8e073822012-04-04 00:07:22 +020040
41#define NMI_OFF 0
42
Stefan Reinauer8e073822012-04-04 00:07:22 +020043typedef struct southbridge_intel_bd82x6x_config config_t;
44
Paul Menzel9c50e6a2013-05-03 12:23:39 +020045/**
46 * Set miscellanous static southbridge features.
47 *
48 * @param dev PCI device with I/O APIC control registers
49 */
50static void pch_enable_ioapic(struct device *dev)
Stefan Reinauer8e073822012-04-04 00:07:22 +020051{
Stefan Reinauer8e073822012-04-04 00:07:22 +020052 u32 reg32;
Stefan Reinauer8e073822012-04-04 00:07:22 +020053
Nico Huberb2dae792015-10-26 12:34:02 +010054 /* Assign unique bus/dev/fn for I/O APIC */
55 pci_write_config16(dev, LPC_IBDF,
56 PCH_IOAPIC_PCI_BUS << 8 | PCH_IOAPIC_PCI_SLOT << 3);
57
Paul Menzel9c50e6a2013-05-03 12:23:39 +020058 /* Enable ACPI I/O range decode */
59 pci_write_config8(dev, ACPI_CNTL, ACPI_EN);
Stefan Reinauer8e073822012-04-04 00:07:22 +020060
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -080061 set_ioapic_id(VIO_APIC_VADDR, 0x02);
Stefan Reinauer8e073822012-04-04 00:07:22 +020062
63 /* affirm full set of redirection table entries ("write once") */
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -080064 reg32 = io_apic_read(VIO_APIC_VADDR, 0x01);
65 io_apic_write(VIO_APIC_VADDR, 0x01, reg32);
Stefan Reinauer8e073822012-04-04 00:07:22 +020066
Paul Menzel9c50e6a2013-05-03 12:23:39 +020067 /*
68 * Select Boot Configuration register (0x03) and
69 * use Processor System Bus (0x01) to deliver interrupts.
70 */
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -080071 io_apic_write(VIO_APIC_VADDR, 0x03, 0x01);
Stefan Reinauer8e073822012-04-04 00:07:22 +020072}
73
74static void pch_enable_serial_irqs(struct device *dev)
75{
76 /* Set packet length and toggle silent mode bit for one frame. */
77 pci_write_config8(dev, SERIRQ_CNTL,
78 (1 << 7) | (1 << 6) | ((21 - 17) << 2) | (0 << 0));
Julius Wernercd49cce2019-03-05 16:53:33 -080079#if !CONFIG(SERIRQ_CONTINUOUS_MODE)
Stefan Reinauer8e073822012-04-04 00:07:22 +020080 pci_write_config8(dev, SERIRQ_CNTL,
81 (1 << 7) | (0 << 6) | ((21 - 17) << 2) | (0 << 0));
82#endif
83}
84
85/* PIRQ[n]_ROUT[3:0] - PIRQ Routing Control
86 * 0x00 - 0000 = Reserved
87 * 0x01 - 0001 = Reserved
88 * 0x02 - 0010 = Reserved
89 * 0x03 - 0011 = IRQ3
90 * 0x04 - 0100 = IRQ4
91 * 0x05 - 0101 = IRQ5
92 * 0x06 - 0110 = IRQ6
93 * 0x07 - 0111 = IRQ7
94 * 0x08 - 1000 = Reserved
95 * 0x09 - 1001 = IRQ9
96 * 0x0A - 1010 = IRQ10
97 * 0x0B - 1011 = IRQ11
98 * 0x0C - 1100 = IRQ12
99 * 0x0D - 1101 = Reserved
100 * 0x0E - 1110 = IRQ14
101 * 0x0F - 1111 = IRQ15
102 * PIRQ[n]_ROUT[7] - PIRQ Routing Control
103 * 0x80 - The PIRQ is not routed.
104 */
105
Elyes HAOUAS4aec3402018-05-25 08:29:27 +0200106static void pch_pirq_init(struct device *dev)
Stefan Reinauer8e073822012-04-04 00:07:22 +0200107{
Elyes HAOUAS4aec3402018-05-25 08:29:27 +0200108 struct device *irq_dev;
Vladimir Serbinenko33b535f2014-10-19 10:13:14 +0200109 /* Interrupt 11 is not used by legacy devices and so can always be used for
110 PCI interrupts. Full legacy IRQ routing is complicated and hard to
111 get right. Fortunately all modern OS use MSI and so it's not that big of
112 an issue anyway. Still we have to provide a reasonable default. Using
113 interrupt 11 for it everywhere is a working default. ACPI-aware OS can
114 move it to any interrupt and others will just leave them at default.
Stefan Reinauer8e073822012-04-04 00:07:22 +0200115 */
Vladimir Serbinenko33b535f2014-10-19 10:13:14 +0200116 const u8 pirq_routing = 11;
117
118 pci_write_config8(dev, PIRQA_ROUT, pirq_routing);
119 pci_write_config8(dev, PIRQB_ROUT, pirq_routing);
120 pci_write_config8(dev, PIRQC_ROUT, pirq_routing);
121 pci_write_config8(dev, PIRQD_ROUT, pirq_routing);
122
123 pci_write_config8(dev, PIRQE_ROUT, pirq_routing);
124 pci_write_config8(dev, PIRQF_ROUT, pirq_routing);
125 pci_write_config8(dev, PIRQG_ROUT, pirq_routing);
126 pci_write_config8(dev, PIRQH_ROUT, pirq_routing);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200127
Elyes HAOUASba28e8d2016-08-31 19:22:16 +0200128 for (irq_dev = all_devices; irq_dev; irq_dev = irq_dev->next) {
Vladimir Serbinenko33b535f2014-10-19 10:13:14 +0200129 u8 int_pin=0;
Stefan Reinauer8e073822012-04-04 00:07:22 +0200130
131 if (!irq_dev->enabled || irq_dev->path.type != DEVICE_PATH_PCI)
132 continue;
133
134 int_pin = pci_read_config8(irq_dev, PCI_INTERRUPT_PIN);
135
Vladimir Serbinenko33b535f2014-10-19 10:13:14 +0200136 if (int_pin == 0)
Stefan Reinauer8e073822012-04-04 00:07:22 +0200137 continue;
138
Vladimir Serbinenko33b535f2014-10-19 10:13:14 +0200139 pci_write_config8(irq_dev, PCI_INTERRUPT_LINE, pirq_routing);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200140 }
141}
142
Elyes HAOUAS4aec3402018-05-25 08:29:27 +0200143static void pch_gpi_routing(struct device *dev)
Stefan Reinauer8e073822012-04-04 00:07:22 +0200144{
145 /* Get the chip configuration */
146 config_t *config = dev->chip_info;
147 u32 reg32 = 0;
148
149 /* An array would be much nicer here, or some
150 * other method of doing this.
151 */
152 reg32 |= (config->gpi0_routing & 0x03) << 0;
153 reg32 |= (config->gpi1_routing & 0x03) << 2;
154 reg32 |= (config->gpi2_routing & 0x03) << 4;
155 reg32 |= (config->gpi3_routing & 0x03) << 6;
156 reg32 |= (config->gpi4_routing & 0x03) << 8;
157 reg32 |= (config->gpi5_routing & 0x03) << 10;
158 reg32 |= (config->gpi6_routing & 0x03) << 12;
159 reg32 |= (config->gpi7_routing & 0x03) << 14;
160 reg32 |= (config->gpi8_routing & 0x03) << 16;
161 reg32 |= (config->gpi9_routing & 0x03) << 18;
162 reg32 |= (config->gpi10_routing & 0x03) << 20;
163 reg32 |= (config->gpi11_routing & 0x03) << 22;
164 reg32 |= (config->gpi12_routing & 0x03) << 24;
165 reg32 |= (config->gpi13_routing & 0x03) << 26;
166 reg32 |= (config->gpi14_routing & 0x03) << 28;
167 reg32 |= (config->gpi15_routing & 0x03) << 30;
168
Kyösti Mälkkib85a87b2014-12-29 11:32:27 +0200169 pci_write_config32(dev, GPIO_ROUT, reg32);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200170}
171
Elyes HAOUAS4aec3402018-05-25 08:29:27 +0200172static void pch_power_options(struct device *dev)
Stefan Reinauer8e073822012-04-04 00:07:22 +0200173{
174 u8 reg8;
175 u16 reg16, pmbase;
176 u32 reg32;
177 const char *state;
178 /* Get the chip configuration */
179 config_t *config = dev->chip_info;
180
Nico Huber9faae2b2018-11-14 00:00:35 +0100181 int pwr_on = CONFIG_MAINBOARD_POWER_FAILURE_STATE;
Stefan Reinauer8e073822012-04-04 00:07:22 +0200182 int nmi_option;
183
184 /* Which state do we want to goto after g3 (power restored)?
185 * 0 == S0 Full On
186 * 1 == S5 Soft Off
187 *
188 * If the option is not existent (Laptops), use Kconfig setting.
189 */
190 get_option(&pwr_on, "power_on_after_fail");
191
192 reg16 = pci_read_config16(dev, GEN_PMCON_3);
193 reg16 &= 0xfffe;
194 switch (pwr_on) {
195 case MAINBOARD_POWER_OFF:
196 reg16 |= 1;
197 state = "off";
198 break;
199 case MAINBOARD_POWER_ON:
200 reg16 &= ~1;
201 state = "on";
202 break;
203 case MAINBOARD_POWER_KEEP:
204 reg16 &= ~1;
205 state = "state keep";
206 break;
207 default:
208 state = "undefined";
209 }
210
211 reg16 &= ~(3 << 4); /* SLP_S4# Assertion Stretch 4s */
212 reg16 |= (1 << 3); /* SLP_S4# Assertion Stretch Enable */
213
214 reg16 &= ~(1 << 10);
215 reg16 |= (1 << 11); /* SLP_S3# Min Assertion Width 50ms */
216
217 reg16 |= (1 << 12); /* Disable SLP stretch after SUS well */
218
219 pci_write_config16(dev, GEN_PMCON_3, reg16);
220 printk(BIOS_INFO, "Set power %s after power failure.\n", state);
221
222 /* Set up NMI on errors. */
223 reg8 = inb(0x61);
224 reg8 &= 0x0f; /* Higher Nibble must be 0 */
225 reg8 &= ~(1 << 3); /* IOCHK# NMI Enable */
226 // reg8 &= ~(1 << 2); /* PCI SERR# Enable */
227 reg8 |= (1 << 2); /* PCI SERR# Disable for now */
228 outb(reg8, 0x61);
229
230 reg8 = inb(0x70);
231 nmi_option = NMI_OFF;
232 get_option(&nmi_option, "nmi");
233 if (nmi_option) {
234 printk(BIOS_INFO, "NMI sources enabled.\n");
235 reg8 &= ~(1 << 7); /* Set NMI. */
236 } else {
237 printk(BIOS_INFO, "NMI sources disabled.\n");
Elyes HAOUAS9c5d4632018-04-26 22:21:21 +0200238 reg8 |= (1 << 7); /* Can't mask NMI from PCI-E and NMI_NOW */
Stefan Reinauer8e073822012-04-04 00:07:22 +0200239 }
240 outb(reg8, 0x70);
241
242 /* Enable CPU_SLP# and Intel Speedstep, set SMI# rate down */
243 reg16 = pci_read_config16(dev, GEN_PMCON_1);
244 reg16 &= ~(3 << 0); // SMI# rate 1 minute
245 reg16 &= ~(1 << 10); // Disable BIOS_PCI_EXP_EN for native PME
246#if DEBUG_PERIODIC_SMIS
247 /* Set DEBUG_PERIODIC_SMIS in pch.h to debug using
248 * periodic SMIs.
249 */
250 reg16 |= (3 << 0); // Periodic SMI every 8s
251#endif
252 pci_write_config16(dev, GEN_PMCON_1, reg16);
253
254 // Set the board's GPI routing.
255 pch_gpi_routing(dev);
256
257 pmbase = pci_read_config16(dev, 0x40) & 0xfffe;
258
259 outl(config->gpe0_en, pmbase + GPE0_EN);
260 outw(config->alt_gp_smi_en, pmbase + ALT_GP_SMI_EN);
261
262 /* Set up power management block and determine sleep mode */
263 reg32 = inl(pmbase + 0x04); // PM1_CNT
264 reg32 &= ~(7 << 10); // SLP_TYP
265 reg32 |= (1 << 0); // SCI_EN
266 outl(reg32, pmbase + 0x04);
267
268 /* Clear magic status bits to prevent unexpected wake */
Patrick Rudolph4f8b1082019-07-14 11:54:58 +0200269 reg32 = RCBA32(PRSTS);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200270 reg32 |= (1 << 4)|(1 << 5)|(1 << 0);
Patrick Rudolph4f8b1082019-07-14 11:54:58 +0200271 RCBA32(PRSTS) = reg32;
Stefan Reinauer8e073822012-04-04 00:07:22 +0200272
273 reg32 = RCBA32(0x3f02);
274 reg32 &= ~0xf;
275 RCBA32(0x3f02) = reg32;
276}
277
Duncan Laurie3f6a4d72012-06-28 13:03:40 -0700278/* CougarPoint PCH Power Management init */
279static void cpt_pm_init(struct device *dev)
Stefan Reinauer8e073822012-04-04 00:07:22 +0200280{
Duncan Laurie3f6a4d72012-06-28 13:03:40 -0700281 printk(BIOS_DEBUG, "CougarPoint PM init\n");
Stefan Reinauer8e073822012-04-04 00:07:22 +0200282 pci_write_config8(dev, 0xa9, 0x47);
Patrick Rudolph4f8b1082019-07-14 11:54:58 +0200283 RCBA32_AND_OR(CIR30, ~0UL, (1 << 6)|(1 << 0));
284 RCBA32_AND_OR(CIR5, ~0UL, (1 << 0));
285 RCBA16_AND_OR(CIR3, ~0UL, (1 << 13)|(1 << 14));
286 RCBA16_AND_OR(CIR2, ~0UL, (1 << 14));
287 RCBA32(DMC) = 0xc0388400;
288 RCBA32_AND_OR(CIR6, ~0UL, (1 << 5)|(1 << 18));
289 RCBA32_AND_OR(CIR9, ~0UL, (1 << 15)|(1 << 1));
290 RCBA32_AND_OR(CIR7, ~0x1f, 0xf);
291 RCBA32(PM_CFG) = 0x050f0000;
292 RCBA32(CIR8) = 0x04000000;
293 RCBA32_AND_OR(CIR10, ~0UL, 0xfffff);
294 RCBA32_AND_OR(CIR11, ~0UL, (1 << 1));
295 RCBA32(CIR12) = 0x0001c000;
296 RCBA32(CIR14) = 0x00061100;
297 RCBA32(CIR15) = 0x7f8fdfff;
298 RCBA32(CIR13) = 0x000003fc;
299 RCBA32(CIR16) = 0x00001000;
300 RCBA32(CIR18) = 0x0001c000;
301 RCBA32(CIR17) = 0x00000800;
302 RCBA32(CIR23) = 0x00001000;
303 RCBA32(CIR19) = 0x00093900;
304 RCBA32(CIR20) = 0x24653002;
305 RCBA32(CIR21) = 0x062108fe;
306 RCBA32_AND_OR(CIR22, 0xf000f000, 0x00670060);
307 RCBA32(CIR24) = 0x01010000;
308 RCBA32(CIR25) = 0x01010404;
309 RCBA32(CIR27) = 0x01041041;
310 RCBA32_AND_OR(CIR28, ~0x0000ffff, 0x00001001);
311 RCBA32_AND_OR(CIR28, ~0UL, (1 << 24)); /* SATA 2/3 disabled */
312 RCBA32_AND_OR(CIR29, ~0UL, (1 << 0)); /* SATA 4/5 disabled */
313 RCBA32(CIR26) = 0x00000001;
Stefan Reinauer8e073822012-04-04 00:07:22 +0200314 RCBA32_AND_OR(0x2344, 0x00ffff00, 0xff00000c);
315 RCBA32_AND_OR(0x80c, ~(0xff << 20), 0x11 << 20);
Patrick Rudolph4f8b1082019-07-14 11:54:58 +0200316 RCBA32(PMSYNC_CFG) = 0;
Stefan Reinauer8e073822012-04-04 00:07:22 +0200317 RCBA32_AND_OR(0x21b0, ~0UL, 0xf);
318}
319
Duncan Laurie3f6a4d72012-06-28 13:03:40 -0700320/* PantherPoint PCH Power Management init */
321static void ppt_pm_init(struct device *dev)
322{
323 printk(BIOS_DEBUG, "PantherPoint PM init\n");
324 pci_write_config8(dev, 0xa9, 0x47);
Patrick Rudolph4f8b1082019-07-14 11:54:58 +0200325 RCBA32_AND_OR(CIR30, ~0UL, (1 << 0));
326 RCBA32_AND_OR(CIR5, ~0UL, (1 << 0));
327 RCBA16_AND_OR(CIR3, ~0UL, (1 << 13)|(1 << 14));
328 RCBA16_AND_OR(CIR2, ~0UL, (1 << 14));
329 RCBA32(DMC) = 0xc03b8400;
330 RCBA32_AND_OR(CIR6, ~0UL, (1 << 5)|(1 << 18));
331 RCBA32_AND_OR(CIR9, ~0UL, (1 << 15)|(1 << 1));
332 RCBA32_AND_OR(CIR7, ~0x1f, 0xf);
333 RCBA32(PM_CFG) = 0x054f0000;
334 RCBA32(CIR8) = 0x04000000;
335 RCBA32_AND_OR(CIR10, ~0UL, 0xfffff);
336 RCBA32_AND_OR(CIR11, ~0UL, (1 << 1)|(1 << 0));
337 RCBA32(CIR12) = 0x0001c000;
338 RCBA32(CIR14) = 0x00061100;
339 RCBA32(CIR15) = 0x7f8fdfff;
340 RCBA32(CIR13) = 0x000003fd;
341 RCBA32(CIR16) = 0x00001000;
342 RCBA32(CIR18) = 0x0001c000;
343 RCBA32(CIR17) = 0x00000800;
344 RCBA32(CIR23) = 0x00001000;
345 RCBA32(CIR19) = 0x00093900;
346 RCBA32(CIR20) = 0x24653002;
347 RCBA32(CIR21) = 0x067388fe;
348 RCBA32_AND_OR(CIR22, 0xf000f000, 0x00670060);
349 RCBA32(CIR24) = 0x01010000;
350 RCBA32(CIR25) = 0x01010404;
351 RCBA32(CIR27) = 0x01040000;
352 RCBA32_AND_OR(CIR28, ~0x0000ffff, 0x00001001);
353 RCBA32_AND_OR(CIR28, ~0UL, (1 << 24)); /* SATA 2/3 disabled */
354 RCBA32_AND_OR(CIR29, ~0UL, (1 << 0)); /* SATA 4/5 disabled */
355 RCBA32(CIR26) = 0x00000001;
Duncan Laurie3f6a4d72012-06-28 13:03:40 -0700356 RCBA32_AND_OR(0x2344, 0x00ffff00, 0xff00000c);
357 RCBA32_AND_OR(0x80c, ~(0xff << 20), 0x11 << 20);
358 RCBA32_AND_OR(0x33a4, ~0UL, (1 << 0));
Patrick Rudolph4f8b1082019-07-14 11:54:58 +0200359 RCBA32(PMSYNC_CFG) = 0;
Duncan Laurie3f6a4d72012-06-28 13:03:40 -0700360 RCBA32_AND_OR(0x21b0, ~0UL, 0xf);
361}
362
Nico Huberb2dae792015-10-26 12:34:02 +0100363static void enable_hpet(struct device *const dev)
Stefan Reinauer8e073822012-04-04 00:07:22 +0200364{
365 u32 reg32;
Nico Huberb2dae792015-10-26 12:34:02 +0100366 size_t i;
367
368 /* Assign unique bus/dev/fn for each HPET */
369 for (i = 0; i < 8; ++i)
370 pci_write_config16(dev, LPC_HnBDF(i),
371 PCH_HPET_PCI_BUS << 8 | PCH_HPET_PCI_SLOT << 3 | i);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200372
373 /* Move HPET to default address 0xfed00000 and enable it */
374 reg32 = RCBA32(HPTC);
375 reg32 |= (1 << 7); // HPET Address Enable
376 reg32 &= ~(3 << 0);
377 RCBA32(HPTC) = reg32;
378}
379
Elyes HAOUAS4aec3402018-05-25 08:29:27 +0200380static void enable_clock_gating(struct device *dev)
Stefan Reinauer8e073822012-04-04 00:07:22 +0200381{
382 u32 reg32;
383 u16 reg16;
384
Patrick Rudolph4f8b1082019-07-14 11:54:58 +0200385 RCBA32_AND_OR(DMIC, ~0UL, 0xf);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200386
387 reg16 = pci_read_config16(dev, GEN_PMCON_1);
388 reg16 |= (1 << 2) | (1 << 11);
389 pci_write_config16(dev, GEN_PMCON_1, reg16);
390
391 pch_iobp_update(0xEB007F07, ~0UL, (1 << 31));
392 pch_iobp_update(0xEB004000, ~0UL, (1 << 7));
393 pch_iobp_update(0xEC007F07, ~0UL, (1 << 31));
394 pch_iobp_update(0xEC004000, ~0UL, (1 << 7));
395
396 reg32 = RCBA32(CG);
397 reg32 |= (1 << 31);
398 reg32 |= (1 << 29) | (1 << 28);
399 reg32 |= (1 << 27) | (1 << 26) | (1 << 25) | (1 << 24);
400 reg32 |= (1 << 16);
401 reg32 |= (1 << 17);
402 reg32 |= (1 << 18);
403 reg32 |= (1 << 22);
404 reg32 |= (1 << 23);
405 reg32 &= ~(1 << 20);
406 reg32 |= (1 << 19);
407 reg32 |= (1 << 0);
408 reg32 |= (0xf << 1);
409 RCBA32(CG) = reg32;
410
411 RCBA32_OR(0x38c0, 0x7);
412 RCBA32_OR(0x36d4, 0x6680c004);
413 RCBA32_OR(0x3564, 0x3);
414}
415
Vladimir Serbinenkoa3e41c02015-05-28 16:04:17 +0200416static void pch_set_acpi_mode(void)
Stefan Reinauer8e073822012-04-04 00:07:22 +0200417{
Julius Werner5d1f9a02019-03-07 17:07:26 -0800418 if (!acpi_is_wakeup_s3() && CONFIG(HAVE_SMI_HANDLER)) {
Duncan Laurie95be1d62012-04-09 12:31:43 -0700419 printk(BIOS_DEBUG, "Disabling ACPI via APMC:\n");
Vladimir Serbinenkoa3e41c02015-05-28 16:04:17 +0200420 outb(APM_CNT_ACPI_DISABLE, APM_CNT); // Disable ACPI mode
Duncan Laurie95be1d62012-04-09 12:31:43 -0700421 printk(BIOS_DEBUG, "done.\n");
Duncan Laurie95be1d62012-04-09 12:31:43 -0700422 }
Stefan Reinauer8e073822012-04-04 00:07:22 +0200423}
Stefan Reinauer8e073822012-04-04 00:07:22 +0200424
425static void pch_disable_smm_only_flashing(struct device *dev)
426{
427 u8 reg8;
428
429 printk(BIOS_SPEW, "Enabling BIOS updates outside of SMM... ");
Elyes HAOUAS0c22d2f2018-12-01 12:19:52 +0100430 reg8 = pci_read_config8(dev, BIOS_CNTL);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200431 reg8 &= ~(1 << 5);
Elyes HAOUAS0c22d2f2018-12-01 12:19:52 +0100432 pci_write_config8(dev, BIOS_CNTL, reg8);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200433}
434
435static void pch_fixups(struct device *dev)
436{
437 u8 gen_pmcon_2;
438
439 /* Indicate DRAM init done for MRC S3 to know it can resume */
440 gen_pmcon_2 = pci_read_config8(dev, GEN_PMCON_2);
441 gen_pmcon_2 |= (1 << 7);
442 pci_write_config8(dev, GEN_PMCON_2, gen_pmcon_2);
443
444 /*
445 * Enable DMI ASPM in the PCH
446 */
Patrick Rudolph4f8b1082019-07-14 11:54:58 +0200447 RCBA32_AND_OR(DMC, ~(1 << 10), 0);
448 RCBA32_OR(LCAP, (1 << 11)|(1 << 10));
449 RCBA32_OR(LCTL, 0x3);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200450}
451
Nico Huber7b2f9f62015-10-01 19:00:51 +0200452static void pch_spi_init(const struct device *const dev)
453{
454 const config_t *const config = dev->chip_info;
455
456 printk(BIOS_DEBUG, "pch_spi_init\n");
457
458 if (config->spi_uvscc)
459 RCBA32(0x3800 + 0xc8) = config->spi_uvscc;
460 if (config->spi_lvscc)
461 RCBA32(0x3800 + 0xc4) = config->spi_lvscc;
462
463 if (config->spi_uvscc || config->spi_lvscc)
464 RCBA32_OR(0x3800 + 0xc4, 1 << 23); /* lock both UVSCC + LVSCC */
465}
466
Patrick Rudolphef8c5592018-07-27 17:48:27 +0200467static const struct {
468 u16 dev_id;
469 const char *dev_name;
470} pch_table[] = {
471 /* 6-series PCI ids from
472 * Intel® 6 Series Chipset and
473 * Intel® C200 Series Chipset
474 * Specification Update - NDA
475 * October 2013
476 * CDI / IBP#: 440377
477 */
478 {0x1C41, "SFF Sample"},
479 {0x1C42, "Desktop Sample"},
480 {0x1C43, "Mobile Sample"},
481 {0x1C44, "Z68"},
482 {0x1C46, "P67"},
483 {0x1C47, "UM67"},
484 {0x1C49, "HM65"},
485 {0x1C4A, "H67"},
486 {0x1C4B, "HM67"},
487 {0x1C4C, "Q65"},
488 {0x1C4D, "QS67"},
489 {0x1C4E, "Q67"},
490 {0x1C4F, "QM67"},
491 {0x1C50, "B65"},
492 {0x1C52, "C202"},
493 {0x1C54, "C204"},
494 {0x1C56, "C206"},
495 {0x1C5C, "H61"},
496 /* 7-series PCI ids from Intel document 472178 */
497 {0x1E41, "Desktop Sample"},
498 {0x1E42, "Mobile Sample"},
499 {0x1E43, "SFF Sample"},
500 {0x1E44, "Z77"},
501 {0x1E45, "H71"},
502 {0x1E46, "Z75"},
503 {0x1E47, "Q77"},
504 {0x1E48, "Q75"},
505 {0x1E49, "B75"},
506 {0x1E4A, "H77"},
507 {0x1E53, "C216"},
508 {0x1E55, "QM77"},
509 {0x1E56, "QS77"},
510 {0x1E58, "UM77"},
511 {0x1E57, "HM77"},
512 {0x1E59, "HM76"},
513 {0x1E5D, "HM75"},
514 {0x1E5E, "HM70"},
515 {0x1E5F, "NM70"},
516};
517
518static void report_pch_info(struct device *dev)
519{
520 const u16 dev_id = pci_read_config16(dev, PCI_DEVICE_ID);
521 int i;
522
523 const char *pch_type = "Unknown";
524 for (i = 0; i < ARRAY_SIZE(pch_table); i++) {
525 if (pch_table[i].dev_id == dev_id) {
526 pch_type = pch_table[i].dev_name;
527 break;
528 }
529 }
530 printk(BIOS_INFO, "PCH: detected %s, device id: 0x%x, rev id 0x%x\n",
531 pch_type, dev_id, pci_read_config8(dev, PCI_CLASS_REVISION));
532}
533
Stefan Reinauer8e073822012-04-04 00:07:22 +0200534static void lpc_init(struct device *dev)
535{
536 printk(BIOS_DEBUG, "pch: lpc_init\n");
537
Patrick Rudolphef8c5592018-07-27 17:48:27 +0200538 /* Print detected platform */
539 report_pch_info(dev);
540
Stefan Reinauer8e073822012-04-04 00:07:22 +0200541 /* Set the value for PCI command register. */
542 pci_write_config16(dev, PCI_COMMAND, 0x000f);
543
544 /* IO APIC initialization. */
Paul Menzel9c50e6a2013-05-03 12:23:39 +0200545 pch_enable_ioapic(dev);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200546
547 pch_enable_serial_irqs(dev);
548
549 /* Setup the PIRQ. */
550 pch_pirq_init(dev);
551
552 /* Setup power options. */
553 pch_power_options(dev);
554
555 /* Initialize power management */
Duncan Laurie3f6a4d72012-06-28 13:03:40 -0700556 switch (pch_silicon_type()) {
557 case PCH_TYPE_CPT: /* CougarPoint */
558 cpt_pm_init(dev);
559 break;
560 case PCH_TYPE_PPT: /* PantherPoint */
561 ppt_pm_init(dev);
562 break;
563 default:
564 printk(BIOS_ERR, "Unknown Chipset: 0x%04x\n", dev->device);
565 }
Stefan Reinauer8e073822012-04-04 00:07:22 +0200566
567 /* Set the state of the GPIO lines. */
568 //gpio_init(dev);
569
570 /* Initialize the real time clock. */
Patrick Rudolph6b931122018-11-01 17:48:37 +0100571 sb_rtc_init();
Stefan Reinauer8e073822012-04-04 00:07:22 +0200572
573 /* Initialize ISA DMA. */
574 isa_dma_init();
575
576 /* Initialize the High Precision Event Timers, if present. */
Nico Huberb2dae792015-10-26 12:34:02 +0100577 enable_hpet(dev);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200578
579 /* Initialize Clock Gating */
580 enable_clock_gating(dev);
581
582 setup_i8259();
583
584 /* The OS should do this? */
585 /* Interrupt 9 should be level triggered (SCI) */
586 i8259_configure_irq_trigger(9, 1);
587
588 pch_disable_smm_only_flashing(dev);
589
Vladimir Serbinenkoa3e41c02015-05-28 16:04:17 +0200590 pch_set_acpi_mode();
Stefan Reinauer8e073822012-04-04 00:07:22 +0200591
592 pch_fixups(dev);
Nico Huber7b2f9f62015-10-01 19:00:51 +0200593
594 pch_spi_init(dev);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200595}
596
Elyes HAOUAS4aec3402018-05-25 08:29:27 +0200597static void pch_lpc_read_resources(struct device *dev)
Stefan Reinauer8e073822012-04-04 00:07:22 +0200598{
599 struct resource *res;
Marc Jonesa0bec172012-07-13 14:14:34 -0600600 config_t *config = dev->chip_info;
601 u8 io_index = 0;
Stefan Reinauer8e073822012-04-04 00:07:22 +0200602
603 /* Get the normal PCI resources of this device. */
604 pci_dev_read_resources(dev);
605
606 /* Add an extra subtractive resource for both memory and I/O. */
Marc Jonesa0bec172012-07-13 14:14:34 -0600607 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
Stefan Reinauer8e073822012-04-04 00:07:22 +0200608 res->base = 0;
609 res->size = 0x1000;
610 res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
611 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
612
Marc Jonesa0bec172012-07-13 14:14:34 -0600613 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
Vladimir Serbinenko0650cd02014-02-05 15:03:50 +0100614 res->base = 0xff000000;
615 /* Some systems (e.g. X230) have 12 MiB flash.
616 SPI controller supports up to 2 x 16 MiB of flash but
617 address map limits this to 16MiB. */
618 res->size = 0x01000000; /* 16 MB for flash */
Stefan Reinauer8e073822012-04-04 00:07:22 +0200619 res->flags = IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE |
620 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
621
622 res = new_resource(dev, 3); /* IOAPIC */
623 res->base = IO_APIC_ADDR;
624 res->size = 0x00001000;
625 res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
Marc Jonesa0bec172012-07-13 14:14:34 -0600626
627 /* Set PCH IO decode ranges if required.*/
628 if ((config->gen1_dec & 0xFFFC) > 0x1000) {
629 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
630 res->base = config->gen1_dec & 0xFFFC;
631 res->size = (config->gen1_dec >> 16) & 0xFC;
632 res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
633 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
634 }
635
636 if ((config->gen2_dec & 0xFFFC) > 0x1000) {
637 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
638 res->base = config->gen2_dec & 0xFFFC;
639 res->size = (config->gen2_dec >> 16) & 0xFC;
640 res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
641 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
642 }
643
644 if ((config->gen3_dec & 0xFFFC) > 0x1000) {
645 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
646 res->base = config->gen3_dec & 0xFFFC;
647 res->size = (config->gen3_dec >> 16) & 0xFC;
648 res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
649 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
650 }
651
652 if ((config->gen4_dec & 0xFFFC) > 0x1000) {
653 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
654 res->base = config->gen4_dec & 0xFFFC;
655 res->size = (config->gen4_dec >> 16) & 0xFC;
656 res->flags = IORESOURCE_IO| IORESOURCE_SUBTRACTIVE |
657 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
658 }
Stefan Reinauer8e073822012-04-04 00:07:22 +0200659}
660
Elyes HAOUAS4aec3402018-05-25 08:29:27 +0200661static void pch_lpc_enable(struct device *dev)
Stefan Reinauer8e073822012-04-04 00:07:22 +0200662{
663 /* Enable PCH Display Port */
664 RCBA16(DISPBDF) = 0x0010;
665 RCBA32_OR(FD2, PCH_ENABLE_DBDF);
666
667 pch_enable(dev);
668}
669
Elyes HAOUAS4aec3402018-05-25 08:29:27 +0200670static void southbridge_inject_dsdt(struct device *dev)
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +0200671{
Elyes HAOUAS035df002016-10-03 21:54:16 +0200672 global_nvs_t *gnvs = cbmem_add (CBMEM_ID_ACPI_GNVS, sizeof(*gnvs));
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +0200673
674 if (gnvs) {
Elyes HAOUAS035df002016-10-03 21:54:16 +0200675 memset(gnvs, 0, sizeof(*gnvs));
Vladimir Serbinenko7309c642014-10-05 11:07:33 +0200676
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +0200677 acpi_create_gnvs(gnvs);
Vladimir Serbinenko06c788d2014-10-12 00:17:11 +0200678
679 gnvs->apic = 1;
680 gnvs->mpen = 1; /* Enable Multi Processing */
681 gnvs->pcnt = dev_count_cpu();
682
Julius Wernercd49cce2019-03-05 16:53:33 -0800683#if CONFIG(CHROMEOS)
Joel Kitching6fbd8742018-08-23 14:56:25 +0800684 chromeos_init_chromeos_acpi(&(gnvs->chromeos));
Vladimir Serbinenko06c788d2014-10-12 00:17:11 +0200685#endif
686
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +0200687 /* And tell SMI about it */
688 smm_setup_structures(gnvs, NULL, NULL);
689
Vladimir Serbinenko334fd8e2014-10-05 11:10:35 +0200690 /* Add it to DSDT. */
Vladimir Serbinenko226d7842014-11-04 21:09:23 +0100691 acpigen_write_scope("\\");
692 acpigen_write_name_dword("NVSA", (u32) gnvs);
693 acpigen_pop_len();
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +0200694 }
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +0200695}
696
Vladimir Serbinenko5b044ae2014-10-25 15:20:55 +0200697void acpi_fill_fadt(acpi_fadt_t *fadt)
698{
Kyösti Mälkkic70eed12018-05-22 02:18:00 +0300699 struct device *dev = pcidev_on_root(0x1f, 0);
Vladimir Serbinenko5b044ae2014-10-25 15:20:55 +0200700 config_t *chip = dev->chip_info;
701 u16 pmbase = pci_read_config16(dev, 0x40) & 0xfffe;
702 int c2_latency;
703
Elyes HAOUAS0d4de2a2019-02-28 13:04:29 +0100704 fadt->reserved = 0;
Vladimir Serbinenko5b044ae2014-10-25 15:20:55 +0200705
706 fadt->sci_int = 0x9;
707 fadt->smi_cmd = APM_CNT;
708 fadt->acpi_enable = APM_CNT_ACPI_ENABLE;
709 fadt->acpi_disable = APM_CNT_ACPI_DISABLE;
710 fadt->s4bios_req = 0x0;
711 fadt->pstate_cnt = 0;
712
713 fadt->pm1a_evt_blk = pmbase;
714 fadt->pm1b_evt_blk = 0x0;
715 fadt->pm1a_cnt_blk = pmbase + 0x4;
716 fadt->pm1b_cnt_blk = 0x0;
717 fadt->pm2_cnt_blk = pmbase + 0x50;
718 fadt->pm_tmr_blk = pmbase + 0x8;
719 fadt->gpe0_blk = pmbase + 0x20;
720 fadt->gpe1_blk = 0;
721
722 fadt->pm1_evt_len = 4;
723 fadt->pm1_cnt_len = 2;
724 fadt->pm2_cnt_len = 1;
725 fadt->pm_tmr_len = 4;
726 fadt->gpe0_blk_len = 16;
727 fadt->gpe1_blk_len = 0;
728 fadt->gpe1_base = 0;
729 fadt->cst_cnt = 0;
730 c2_latency = chip->c2_latency;
731 if (!c2_latency) {
732 c2_latency = 101; /* c2 unsupported */
733 }
734 fadt->p_lvl2_lat = c2_latency;
735 fadt->p_lvl3_lat = 87;
736 fadt->flush_size = 1024;
737 fadt->flush_stride = 16;
Patrick Rudolphb30a47b2019-07-15 18:04:23 +0200738 /* P_CNT not supported */
739 fadt->duty_offset = 0;
740 fadt->duty_width = 0;
741
Vladimir Serbinenko5b044ae2014-10-25 15:20:55 +0200742 fadt->day_alrm = 0xd;
743 fadt->mon_alrm = 0x00;
744 fadt->century = 0x00;
745 fadt->iapc_boot_arch = ACPI_FADT_LEGACY_DEVICES | ACPI_FADT_8042;
746
747 fadt->flags = ACPI_FADT_WBINVD |
748 ACPI_FADT_C1_SUPPORTED |
749 ACPI_FADT_SLEEP_BUTTON |
750 ACPI_FADT_RESET_REGISTER |
751 ACPI_FADT_SEALED_CASE |
752 ACPI_FADT_S4_RTC_WAKE |
753 ACPI_FADT_PLATFORM_CLOCK;
754 if (chip->docking_supported) {
755 fadt->flags |= ACPI_FADT_DOCKING_SUPPORTED;
756 }
757 if (c2_latency < 100) {
758 fadt->flags |= ACPI_FADT_C2_MP_SUPPORTED;
759 }
760
761 fadt->reset_reg.space_id = 1;
762 fadt->reset_reg.bit_width = 8;
763 fadt->reset_reg.bit_offset = 0;
764 fadt->reset_reg.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
765 fadt->reset_reg.addrl = 0xcf9;
766 fadt->reset_reg.addrh = 0;
767
768 fadt->reset_value = 6;
769
770 fadt->x_pm1a_evt_blk.space_id = 1;
771 fadt->x_pm1a_evt_blk.bit_width = 32;
772 fadt->x_pm1a_evt_blk.bit_offset = 0;
773 fadt->x_pm1a_evt_blk.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
774 fadt->x_pm1a_evt_blk.addrl = pmbase;
775 fadt->x_pm1a_evt_blk.addrh = 0x0;
776
777 fadt->x_pm1b_evt_blk.space_id = 1;
778 fadt->x_pm1b_evt_blk.bit_width = 0;
779 fadt->x_pm1b_evt_blk.bit_offset = 0;
780 fadt->x_pm1b_evt_blk.access_size = 0;
781 fadt->x_pm1b_evt_blk.addrl = 0x0;
782 fadt->x_pm1b_evt_blk.addrh = 0x0;
783
784 fadt->x_pm1a_cnt_blk.space_id = 1;
785 fadt->x_pm1a_cnt_blk.bit_width = 16;
786 fadt->x_pm1a_cnt_blk.bit_offset = 0;
787 fadt->x_pm1a_cnt_blk.access_size = ACPI_ACCESS_SIZE_WORD_ACCESS;
788 fadt->x_pm1a_cnt_blk.addrl = pmbase + 0x4;
789 fadt->x_pm1a_cnt_blk.addrh = 0x0;
790
791 fadt->x_pm1b_cnt_blk.space_id = 1;
792 fadt->x_pm1b_cnt_blk.bit_width = 0;
793 fadt->x_pm1b_cnt_blk.bit_offset = 0;
794 fadt->x_pm1b_cnt_blk.access_size = 0;
795 fadt->x_pm1b_cnt_blk.addrl = 0x0;
796 fadt->x_pm1b_cnt_blk.addrh = 0x0;
797
798 fadt->x_pm2_cnt_blk.space_id = 1;
799 fadt->x_pm2_cnt_blk.bit_width = 8;
800 fadt->x_pm2_cnt_blk.bit_offset = 0;
801 fadt->x_pm2_cnt_blk.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
802 fadt->x_pm2_cnt_blk.addrl = pmbase + 0x50;
803 fadt->x_pm2_cnt_blk.addrh = 0x0;
804
805 fadt->x_pm_tmr_blk.space_id = 1;
806 fadt->x_pm_tmr_blk.bit_width = 32;
807 fadt->x_pm_tmr_blk.bit_offset = 0;
808 fadt->x_pm_tmr_blk.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
809 fadt->x_pm_tmr_blk.addrl = pmbase + 0x8;
810 fadt->x_pm_tmr_blk.addrh = 0x0;
811
812 fadt->x_gpe0_blk.space_id = 1;
813 fadt->x_gpe0_blk.bit_width = 128;
814 fadt->x_gpe0_blk.bit_offset = 0;
815 fadt->x_gpe0_blk.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
816 fadt->x_gpe0_blk.addrl = pmbase + 0x20;
817 fadt->x_gpe0_blk.addrh = 0x0;
818
819 fadt->x_gpe1_blk.space_id = 1;
820 fadt->x_gpe1_blk.bit_width = 0;
821 fadt->x_gpe1_blk.bit_offset = 0;
822 fadt->x_gpe1_blk.access_size = 0;
823 fadt->x_gpe1_blk.addrl = 0x0;
824 fadt->x_gpe1_blk.addrh = 0x0;
825}
826
Aaron Durbinaa090cb2017-09-13 16:01:52 -0600827static const char *lpc_acpi_name(const struct device *dev)
Patrick Rudolph604f6982017-06-07 09:46:52 +0200828{
829 return "LPCB";
830}
831
Elyes HAOUAS4aec3402018-05-25 08:29:27 +0200832static void southbridge_fill_ssdt(struct device *device)
Vladimir Serbinenko36fa5b82014-10-28 23:43:20 +0100833{
Kyösti Mälkkic70eed12018-05-22 02:18:00 +0300834 struct device *dev = pcidev_on_root(0x1f, 0);
Vladimir Serbinenko36fa5b82014-10-28 23:43:20 +0100835 config_t *chip = dev->chip_info;
836
837 intel_acpi_pcie_hotplug_generator(chip->pcie_hotplug_map, 8);
Tobias Diedrich7f5efd92017-12-14 00:29:01 +0100838 intel_acpi_gen_def_acpi_pirq(dev);
Vladimir Serbinenko36fa5b82014-10-28 23:43:20 +0100839}
840
Vladimir Serbinenkob06a2492015-05-21 10:32:59 +0200841static void lpc_final(struct device *dev)
842{
Arthur Heymansebf201b2019-05-28 13:51:36 +0200843 spi_finalize_ops();
Nico Huber8e50b6d2018-02-04 15:52:18 +0100844
Bill XIEd533b162017-08-22 16:26:22 +0800845 /* Call SMM finalize() handlers before resume */
Julius Wernercd49cce2019-03-05 16:53:33 -0800846 if (CONFIG(HAVE_SMI_HANDLER)) {
847 if (CONFIG(INTEL_CHIPSET_LOCKDOWN) ||
Bill XIEd533b162017-08-22 16:26:22 +0800848 acpi_is_wakeup_s3()) {
849 outb(APM_CNT_FINALIZE, APM_CNT);
850 }
Vladimir Serbinenkob06a2492015-05-21 10:32:59 +0200851 }
852}
853
Arthur Heymansebf201b2019-05-28 13:51:36 +0200854void intel_southbridge_override_spi(
855 struct intel_swseq_spi_config *spi_config)
856{
857 struct device *dev = pcidev_on_root(0x1f, 0);
858
859 if (!dev)
860 return;
861 /* Devicetree may override defaults. */
862 const config_t *const config = dev->chip_info;
863
864 if (!config)
865 return;
866
867 if (config->spi.ops[0].op != 0)
868 memcpy(spi_config, &config->spi, sizeof(*spi_config));
869}
870
Stefan Reinauer8e073822012-04-04 00:07:22 +0200871static struct pci_operations pci_ops = {
Subrata Banik4a0f0712019-03-20 14:29:47 +0530872 .set_subsystem = pci_dev_set_subsystem,
Stefan Reinauer8e073822012-04-04 00:07:22 +0200873};
874
875static struct device_operations device_ops = {
876 .read_resources = pch_lpc_read_resources,
877 .set_resources = pci_dev_set_resources,
Arthur Heymans3cde4942019-08-18 10:02:10 +0200878 .enable_resources = pci_dev_enable_resources,
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +0200879 .write_acpi_tables = acpi_write_hpet,
Nico Huber68680dd2020-03-31 17:34:52 +0200880 .acpi_inject_dsdt = southbridge_inject_dsdt,
881 .acpi_fill_ssdt = southbridge_fill_ssdt,
Patrick Rudolph604f6982017-06-07 09:46:52 +0200882 .acpi_name = lpc_acpi_name,
Stefan Reinauer8e073822012-04-04 00:07:22 +0200883 .init = lpc_init,
Vladimir Serbinenkob06a2492015-05-21 10:32:59 +0200884 .final = lpc_final,
Stefan Reinauer8e073822012-04-04 00:07:22 +0200885 .enable = pch_lpc_enable,
Nico Huber51b75ae2019-03-14 16:02:05 +0100886 .scan_bus = scan_static_bus,
Stefan Reinauer8e073822012-04-04 00:07:22 +0200887 .ops_pci = &pci_ops,
888};
889
890
Kimarie Hoote6f459c2012-07-14 08:26:08 -0600891/* IDs for LPC device of Intel 6 Series Chipset, Intel 7 Series Chipset, and
892 * Intel C200 Series Chipset
Stefan Reinauer8e073822012-04-04 00:07:22 +0200893 */
894
Vladimir Serbinenko42d55e02016-01-02 01:47:26 +0100895static const unsigned short pci_device_ids[] = {
896 0x1c40, 0x1c41, 0x1c42, 0x1c43, 0x1c44, 0x1c45, 0x1c46, 0x1c47, 0x1c48,
897 0x1c49, 0x1c4a, 0x1c4b, 0x1c4c, 0x1c4d, 0x1c4e, 0x1c4f, 0x1c50, 0x1c51,
898 0x1c52, 0x1c53, 0x1c54, 0x1c55, 0x1c56, 0x1c57, 0x1c58, 0x1c59, 0x1c5a,
899 0x1c5b, 0x1c5c, 0x1c5d, 0x1c5e, 0x1c5f,
900
901 0x1e41, 0x1e42, 0x1e43, 0x1e44, 0x1e45, 0x1e46, 0x1e47, 0x1e48, 0x1e49,
902 0x1e4a, 0x1e4b, 0x1e4c, 0x1e4d, 0x1e4e, 0x1e4f, 0x1e50, 0x1e51, 0x1e52,
903 0x1e53, 0x1e54, 0x1e55, 0x1e56, 0x1e57, 0x1e58, 0x1e59, 0x1e5a, 0x1e5b,
904 0x1e5c, 0x1e5d, 0x1e5e, 0x1e5f,
905
906 0 };
Stefan Reinauer9a380ab2012-06-22 13:16:11 -0700907
908static const struct pci_driver pch_lpc __pci_driver = {
909 .ops = &device_ops,
910 .vendor = PCI_VENDOR_ID_INTEL,
911 .devices = pci_device_ids,
Stefan Reinauer8e073822012-04-04 00:07:22 +0200912};