blob: 7f61669cf9abd3b193f9b8dd93dddefce265211d [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>
21#include <pc80/mc146818rtc.h>
22#include <pc80/isa-dma.h>
23#include <pc80/i8259.h>
24#include <arch/io.h>
25#include <arch/ioapic.h>
26#include <arch/acpi.h>
27#include <cpu/cpu.h>
Duncan Laurie800e9502012-06-23 17:06:47 -070028#include <elog.h>
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +020029#include <arch/acpigen.h>
30#include <drivers/intel/gma/i915.h>
Vladimir Serbinenko5b044ae2014-10-25 15:20:55 +020031#include <cpu/x86/smm.h>
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +020032#include <cbmem.h>
Vladimir Serbinenko7309c642014-10-05 11:07:33 +020033#include <string.h>
Vladimir Serbinenko5b044ae2014-10-25 15:20:55 +020034#include <cpu/x86/smm.h>
Stefan Reinauer8e073822012-04-04 00:07:22 +020035#include "pch.h"
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +020036#include "nvs.h"
Vladimir Serbinenko36fa5b82014-10-28 23:43:20 +010037#include <southbridge/intel/common/pciehp.h>
Tobias Diedrich7f5efd92017-12-14 00:29:01 +010038#include <southbridge/intel/common/acpi_pirq_gen.h>
Stefan Reinauer8e073822012-04-04 00:07:22 +020039
40#define NMI_OFF 0
41
42#define ENABLE_ACPI_MODE_IN_COREBOOT 0
Stefan Reinauer8e073822012-04-04 00:07:22 +020043
44typedef struct southbridge_intel_bd82x6x_config config_t;
45
Paul Menzel9c50e6a2013-05-03 12:23:39 +020046/**
47 * Set miscellanous static southbridge features.
48 *
49 * @param dev PCI device with I/O APIC control registers
50 */
51static void pch_enable_ioapic(struct device *dev)
Stefan Reinauer8e073822012-04-04 00:07:22 +020052{
Stefan Reinauer8e073822012-04-04 00:07:22 +020053 u32 reg32;
Stefan Reinauer8e073822012-04-04 00:07:22 +020054
Nico Huberb2dae792015-10-26 12:34:02 +010055 /* Assign unique bus/dev/fn for I/O APIC */
56 pci_write_config16(dev, LPC_IBDF,
57 PCH_IOAPIC_PCI_BUS << 8 | PCH_IOAPIC_PCI_SLOT << 3);
58
Paul Menzel9c50e6a2013-05-03 12:23:39 +020059 /* Enable ACPI I/O range decode */
60 pci_write_config8(dev, ACPI_CNTL, ACPI_EN);
Stefan Reinauer8e073822012-04-04 00:07:22 +020061
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -080062 set_ioapic_id(VIO_APIC_VADDR, 0x02);
Stefan Reinauer8e073822012-04-04 00:07:22 +020063
64 /* affirm full set of redirection table entries ("write once") */
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -080065 reg32 = io_apic_read(VIO_APIC_VADDR, 0x01);
66 io_apic_write(VIO_APIC_VADDR, 0x01, reg32);
Stefan Reinauer8e073822012-04-04 00:07:22 +020067
Paul Menzel9c50e6a2013-05-03 12:23:39 +020068 /*
69 * Select Boot Configuration register (0x03) and
70 * use Processor System Bus (0x01) to deliver interrupts.
71 */
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -080072 io_apic_write(VIO_APIC_VADDR, 0x03, 0x01);
Stefan Reinauer8e073822012-04-04 00:07:22 +020073}
74
75static void pch_enable_serial_irqs(struct device *dev)
76{
77 /* Set packet length and toggle silent mode bit for one frame. */
78 pci_write_config8(dev, SERIRQ_CNTL,
79 (1 << 7) | (1 << 6) | ((21 - 17) << 2) | (0 << 0));
Martin Roth7a1a3ad2017-06-24 21:29:38 -060080#if !IS_ENABLED(CONFIG_SERIRQ_CONTINUOUS_MODE)
Stefan Reinauer8e073822012-04-04 00:07:22 +020081 pci_write_config8(dev, SERIRQ_CNTL,
82 (1 << 7) | (0 << 6) | ((21 - 17) << 2) | (0 << 0));
83#endif
84}
85
86/* PIRQ[n]_ROUT[3:0] - PIRQ Routing Control
87 * 0x00 - 0000 = Reserved
88 * 0x01 - 0001 = Reserved
89 * 0x02 - 0010 = Reserved
90 * 0x03 - 0011 = IRQ3
91 * 0x04 - 0100 = IRQ4
92 * 0x05 - 0101 = IRQ5
93 * 0x06 - 0110 = IRQ6
94 * 0x07 - 0111 = IRQ7
95 * 0x08 - 1000 = Reserved
96 * 0x09 - 1001 = IRQ9
97 * 0x0A - 1010 = IRQ10
98 * 0x0B - 1011 = IRQ11
99 * 0x0C - 1100 = IRQ12
100 * 0x0D - 1101 = Reserved
101 * 0x0E - 1110 = IRQ14
102 * 0x0F - 1111 = IRQ15
103 * PIRQ[n]_ROUT[7] - PIRQ Routing Control
104 * 0x80 - The PIRQ is not routed.
105 */
106
107static void pch_pirq_init(device_t dev)
108{
109 device_t irq_dev;
Vladimir Serbinenko33b535f2014-10-19 10:13:14 +0200110 /* Interrupt 11 is not used by legacy devices and so can always be used for
111 PCI interrupts. Full legacy IRQ routing is complicated and hard to
112 get right. Fortunately all modern OS use MSI and so it's not that big of
113 an issue anyway. Still we have to provide a reasonable default. Using
114 interrupt 11 for it everywhere is a working default. ACPI-aware OS can
115 move it to any interrupt and others will just leave them at default.
Stefan Reinauer8e073822012-04-04 00:07:22 +0200116 */
Vladimir Serbinenko33b535f2014-10-19 10:13:14 +0200117 const u8 pirq_routing = 11;
118
119 pci_write_config8(dev, PIRQA_ROUT, pirq_routing);
120 pci_write_config8(dev, PIRQB_ROUT, pirq_routing);
121 pci_write_config8(dev, PIRQC_ROUT, pirq_routing);
122 pci_write_config8(dev, PIRQD_ROUT, pirq_routing);
123
124 pci_write_config8(dev, PIRQE_ROUT, pirq_routing);
125 pci_write_config8(dev, PIRQF_ROUT, pirq_routing);
126 pci_write_config8(dev, PIRQG_ROUT, pirq_routing);
127 pci_write_config8(dev, PIRQH_ROUT, pirq_routing);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200128
Elyes HAOUASba28e8d2016-08-31 19:22:16 +0200129 for (irq_dev = all_devices; irq_dev; irq_dev = irq_dev->next) {
Vladimir Serbinenko33b535f2014-10-19 10:13:14 +0200130 u8 int_pin=0;
Stefan Reinauer8e073822012-04-04 00:07:22 +0200131
132 if (!irq_dev->enabled || irq_dev->path.type != DEVICE_PATH_PCI)
133 continue;
134
135 int_pin = pci_read_config8(irq_dev, PCI_INTERRUPT_PIN);
136
Vladimir Serbinenko33b535f2014-10-19 10:13:14 +0200137 if (int_pin == 0)
Stefan Reinauer8e073822012-04-04 00:07:22 +0200138 continue;
139
Vladimir Serbinenko33b535f2014-10-19 10:13:14 +0200140 pci_write_config8(irq_dev, PCI_INTERRUPT_LINE, pirq_routing);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200141 }
142}
143
144static void pch_gpi_routing(device_t dev)
145{
146 /* Get the chip configuration */
147 config_t *config = dev->chip_info;
148 u32 reg32 = 0;
149
150 /* An array would be much nicer here, or some
151 * other method of doing this.
152 */
153 reg32 |= (config->gpi0_routing & 0x03) << 0;
154 reg32 |= (config->gpi1_routing & 0x03) << 2;
155 reg32 |= (config->gpi2_routing & 0x03) << 4;
156 reg32 |= (config->gpi3_routing & 0x03) << 6;
157 reg32 |= (config->gpi4_routing & 0x03) << 8;
158 reg32 |= (config->gpi5_routing & 0x03) << 10;
159 reg32 |= (config->gpi6_routing & 0x03) << 12;
160 reg32 |= (config->gpi7_routing & 0x03) << 14;
161 reg32 |= (config->gpi8_routing & 0x03) << 16;
162 reg32 |= (config->gpi9_routing & 0x03) << 18;
163 reg32 |= (config->gpi10_routing & 0x03) << 20;
164 reg32 |= (config->gpi11_routing & 0x03) << 22;
165 reg32 |= (config->gpi12_routing & 0x03) << 24;
166 reg32 |= (config->gpi13_routing & 0x03) << 26;
167 reg32 |= (config->gpi14_routing & 0x03) << 28;
168 reg32 |= (config->gpi15_routing & 0x03) << 30;
169
Kyösti Mälkkib85a87b2014-12-29 11:32:27 +0200170 pci_write_config32(dev, GPIO_ROUT, reg32);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200171}
172
173static void pch_power_options(device_t dev)
174{
175 u8 reg8;
176 u16 reg16, pmbase;
177 u32 reg32;
178 const char *state;
179 /* Get the chip configuration */
180 config_t *config = dev->chip_info;
181
182 int pwr_on=CONFIG_MAINBOARD_POWER_ON_AFTER_POWER_FAIL;
183 int nmi_option;
184
185 /* Which state do we want to goto after g3 (power restored)?
186 * 0 == S0 Full On
187 * 1 == S5 Soft Off
188 *
189 * If the option is not existent (Laptops), use Kconfig setting.
190 */
191 get_option(&pwr_on, "power_on_after_fail");
192
193 reg16 = pci_read_config16(dev, GEN_PMCON_3);
194 reg16 &= 0xfffe;
195 switch (pwr_on) {
196 case MAINBOARD_POWER_OFF:
197 reg16 |= 1;
198 state = "off";
199 break;
200 case MAINBOARD_POWER_ON:
201 reg16 &= ~1;
202 state = "on";
203 break;
204 case MAINBOARD_POWER_KEEP:
205 reg16 &= ~1;
206 state = "state keep";
207 break;
208 default:
209 state = "undefined";
210 }
211
212 reg16 &= ~(3 << 4); /* SLP_S4# Assertion Stretch 4s */
213 reg16 |= (1 << 3); /* SLP_S4# Assertion Stretch Enable */
214
215 reg16 &= ~(1 << 10);
216 reg16 |= (1 << 11); /* SLP_S3# Min Assertion Width 50ms */
217
218 reg16 |= (1 << 12); /* Disable SLP stretch after SUS well */
219
220 pci_write_config16(dev, GEN_PMCON_3, reg16);
221 printk(BIOS_INFO, "Set power %s after power failure.\n", state);
222
223 /* Set up NMI on errors. */
224 reg8 = inb(0x61);
225 reg8 &= 0x0f; /* Higher Nibble must be 0 */
226 reg8 &= ~(1 << 3); /* IOCHK# NMI Enable */
227 // reg8 &= ~(1 << 2); /* PCI SERR# Enable */
228 reg8 |= (1 << 2); /* PCI SERR# Disable for now */
229 outb(reg8, 0x61);
230
231 reg8 = inb(0x70);
232 nmi_option = NMI_OFF;
233 get_option(&nmi_option, "nmi");
234 if (nmi_option) {
235 printk(BIOS_INFO, "NMI sources enabled.\n");
236 reg8 &= ~(1 << 7); /* Set NMI. */
237 } else {
238 printk(BIOS_INFO, "NMI sources disabled.\n");
239 reg8 |= ( 1 << 7); /* Can't mask NMI from PCI-E and NMI_NOW */
240 }
241 outb(reg8, 0x70);
242
243 /* Enable CPU_SLP# and Intel Speedstep, set SMI# rate down */
244 reg16 = pci_read_config16(dev, GEN_PMCON_1);
245 reg16 &= ~(3 << 0); // SMI# rate 1 minute
246 reg16 &= ~(1 << 10); // Disable BIOS_PCI_EXP_EN for native PME
247#if DEBUG_PERIODIC_SMIS
248 /* Set DEBUG_PERIODIC_SMIS in pch.h to debug using
249 * periodic SMIs.
250 */
251 reg16 |= (3 << 0); // Periodic SMI every 8s
252#endif
253 pci_write_config16(dev, GEN_PMCON_1, reg16);
254
255 // Set the board's GPI routing.
256 pch_gpi_routing(dev);
257
258 pmbase = pci_read_config16(dev, 0x40) & 0xfffe;
259
260 outl(config->gpe0_en, pmbase + GPE0_EN);
261 outw(config->alt_gp_smi_en, pmbase + ALT_GP_SMI_EN);
262
263 /* Set up power management block and determine sleep mode */
264 reg32 = inl(pmbase + 0x04); // PM1_CNT
265 reg32 &= ~(7 << 10); // SLP_TYP
266 reg32 |= (1 << 0); // SCI_EN
267 outl(reg32, pmbase + 0x04);
268
269 /* Clear magic status bits to prevent unexpected wake */
270 reg32 = RCBA32(0x3310);
271 reg32 |= (1 << 4)|(1 << 5)|(1 << 0);
272 RCBA32(0x3310) = reg32;
273
274 reg32 = RCBA32(0x3f02);
275 reg32 &= ~0xf;
276 RCBA32(0x3f02) = reg32;
277}
278
279static void pch_rtc_init(struct device *dev)
280{
Aaron Durbin976200382017-09-15 15:19:32 -0600281 int rtc_failed = rtc_failure();
Stefan Reinauer8e073822012-04-04 00:07:22 +0200282
Stefan Reinauer8e073822012-04-04 00:07:22 +0200283 if (rtc_failed) {
Aaron Durbin976200382017-09-15 15:19:32 -0600284 if (IS_ENABLED(CONFIG_ELOG))
285 elog_add_event(ELOG_TYPE_RTC_RESET);
286 pci_update_config8(dev, GEN_PMCON_3, ~RTC_BATTERY_DEAD, 0);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200287 }
Aaron Durbin976200382017-09-15 15:19:32 -0600288
Stefan Reinauer8e073822012-04-04 00:07:22 +0200289 printk(BIOS_DEBUG, "rtc_failed = 0x%x\n", rtc_failed);
290
Gabe Blackb3f08c62014-04-30 17:12:25 -0700291 cmos_init(rtc_failed);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200292}
293
Duncan Laurie3f6a4d72012-06-28 13:03:40 -0700294/* CougarPoint PCH Power Management init */
295static void cpt_pm_init(struct device *dev)
Stefan Reinauer8e073822012-04-04 00:07:22 +0200296{
Duncan Laurie3f6a4d72012-06-28 13:03:40 -0700297 printk(BIOS_DEBUG, "CougarPoint PM init\n");
Stefan Reinauer8e073822012-04-04 00:07:22 +0200298 pci_write_config8(dev, 0xa9, 0x47);
299 RCBA32_AND_OR(0x2238, ~0UL, (1 << 6)|(1 << 0));
300 RCBA32_AND_OR(0x228c, ~0UL, (1 << 0));
301 RCBA16_AND_OR(0x1100, ~0UL, (1 << 13)|(1 << 14));
302 RCBA16_AND_OR(0x0900, ~0UL, (1 << 14));
303 RCBA32(0x2304) = 0xc0388400;
304 RCBA32_AND_OR(0x2314, ~0UL, (1 << 5)|(1 << 18));
305 RCBA32_AND_OR(0x2320, ~0UL, (1 << 15)|(1 << 1));
306 RCBA32_AND_OR(0x3314, ~0x1f, 0xf);
307 RCBA32(0x3318) = 0x050f0000;
308 RCBA32(0x3324) = 0x04000000;
309 RCBA32_AND_OR(0x3340, ~0UL, 0xfffff);
310 RCBA32_AND_OR(0x3344, ~0UL, (1 << 1));
311 RCBA32(0x3360) = 0x0001c000;
312 RCBA32(0x3368) = 0x00061100;
313 RCBA32(0x3378) = 0x7f8fdfff;
314 RCBA32(0x337c) = 0x000003fc;
315 RCBA32(0x3388) = 0x00001000;
316 RCBA32(0x3390) = 0x0001c000;
317 RCBA32(0x33a0) = 0x00000800;
318 RCBA32(0x33b0) = 0x00001000;
319 RCBA32(0x33c0) = 0x00093900;
320 RCBA32(0x33cc) = 0x24653002;
321 RCBA32(0x33d0) = 0x062108fe;
322 RCBA32_AND_OR(0x33d4, 0xf000f000, 0x00670060);
323 RCBA32(0x3a28) = 0x01010000;
324 RCBA32(0x3a2c) = 0x01010404;
325 RCBA32(0x3a80) = 0x01041041;
326 RCBA32_AND_OR(0x3a84, ~0x0000ffff, 0x00001001);
327 RCBA32_AND_OR(0x3a84, ~0UL, (1 << 24)); /* SATA 2/3 disabled */
328 RCBA32_AND_OR(0x3a88, ~0UL, (1 << 0)); /* SATA 4/5 disabled */
329 RCBA32(0x3a6c) = 0x00000001;
330 RCBA32_AND_OR(0x2344, 0x00ffff00, 0xff00000c);
331 RCBA32_AND_OR(0x80c, ~(0xff << 20), 0x11 << 20);
332 RCBA32(0x33c8) = 0;
333 RCBA32_AND_OR(0x21b0, ~0UL, 0xf);
334}
335
Duncan Laurie3f6a4d72012-06-28 13:03:40 -0700336/* PantherPoint PCH Power Management init */
337static void ppt_pm_init(struct device *dev)
338{
339 printk(BIOS_DEBUG, "PantherPoint PM init\n");
340 pci_write_config8(dev, 0xa9, 0x47);
341 RCBA32_AND_OR(0x2238, ~0UL, (1 << 0));
342 RCBA32_AND_OR(0x228c, ~0UL, (1 << 0));
343 RCBA16_AND_OR(0x1100, ~0UL, (1 << 13)|(1 << 14));
344 RCBA16_AND_OR(0x0900, ~0UL, (1 << 14));
345 RCBA32(0x2304) = 0xc03b8400;
346 RCBA32_AND_OR(0x2314, ~0UL, (1 << 5)|(1 << 18));
347 RCBA32_AND_OR(0x2320, ~0UL, (1 << 15)|(1 << 1));
348 RCBA32_AND_OR(0x3314, ~0x1f, 0xf);
349 RCBA32(0x3318) = 0x054f0000;
350 RCBA32(0x3324) = 0x04000000;
351 RCBA32_AND_OR(0x3340, ~0UL, 0xfffff);
352 RCBA32_AND_OR(0x3344, ~0UL, (1 << 1)|(1 << 0));
353 RCBA32(0x3360) = 0x0001c000;
354 RCBA32(0x3368) = 0x00061100;
355 RCBA32(0x3378) = 0x7f8fdfff;
356 RCBA32(0x337c) = 0x000003fd;
357 RCBA32(0x3388) = 0x00001000;
358 RCBA32(0x3390) = 0x0001c000;
359 RCBA32(0x33a0) = 0x00000800;
360 RCBA32(0x33b0) = 0x00001000;
361 RCBA32(0x33c0) = 0x00093900;
362 RCBA32(0x33cc) = 0x24653002;
363 RCBA32(0x33d0) = 0x067388fe;
364 RCBA32_AND_OR(0x33d4, 0xf000f000, 0x00670060);
365 RCBA32(0x3a28) = 0x01010000;
366 RCBA32(0x3a2c) = 0x01010404;
367 RCBA32(0x3a80) = 0x01040000;
368 RCBA32_AND_OR(0x3a84, ~0x0000ffff, 0x00001001);
369 RCBA32_AND_OR(0x3a84, ~0UL, (1 << 24)); /* SATA 2/3 disabled */
370 RCBA32_AND_OR(0x3a88, ~0UL, (1 << 0)); /* SATA 4/5 disabled */
371 RCBA32(0x3a6c) = 0x00000001;
372 RCBA32_AND_OR(0x2344, 0x00ffff00, 0xff00000c);
373 RCBA32_AND_OR(0x80c, ~(0xff << 20), 0x11 << 20);
374 RCBA32_AND_OR(0x33a4, ~0UL, (1 << 0));
375 RCBA32(0x33c8) = 0;
376 RCBA32_AND_OR(0x21b0, ~0UL, 0xf);
377}
378
Nico Huberb2dae792015-10-26 12:34:02 +0100379static void enable_hpet(struct device *const dev)
Stefan Reinauer8e073822012-04-04 00:07:22 +0200380{
381 u32 reg32;
Nico Huberb2dae792015-10-26 12:34:02 +0100382 size_t i;
383
384 /* Assign unique bus/dev/fn for each HPET */
385 for (i = 0; i < 8; ++i)
386 pci_write_config16(dev, LPC_HnBDF(i),
387 PCH_HPET_PCI_BUS << 8 | PCH_HPET_PCI_SLOT << 3 | i);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200388
389 /* Move HPET to default address 0xfed00000 and enable it */
390 reg32 = RCBA32(HPTC);
391 reg32 |= (1 << 7); // HPET Address Enable
392 reg32 &= ~(3 << 0);
393 RCBA32(HPTC) = reg32;
394}
395
396static void enable_clock_gating(device_t dev)
397{
398 u32 reg32;
399 u16 reg16;
400
401 RCBA32_AND_OR(0x2234, ~0UL, 0xf);
402
403 reg16 = pci_read_config16(dev, GEN_PMCON_1);
404 reg16 |= (1 << 2) | (1 << 11);
405 pci_write_config16(dev, GEN_PMCON_1, reg16);
406
407 pch_iobp_update(0xEB007F07, ~0UL, (1 << 31));
408 pch_iobp_update(0xEB004000, ~0UL, (1 << 7));
409 pch_iobp_update(0xEC007F07, ~0UL, (1 << 31));
410 pch_iobp_update(0xEC004000, ~0UL, (1 << 7));
411
412 reg32 = RCBA32(CG);
413 reg32 |= (1 << 31);
414 reg32 |= (1 << 29) | (1 << 28);
415 reg32 |= (1 << 27) | (1 << 26) | (1 << 25) | (1 << 24);
416 reg32 |= (1 << 16);
417 reg32 |= (1 << 17);
418 reg32 |= (1 << 18);
419 reg32 |= (1 << 22);
420 reg32 |= (1 << 23);
421 reg32 &= ~(1 << 20);
422 reg32 |= (1 << 19);
423 reg32 |= (1 << 0);
424 reg32 |= (0xf << 1);
425 RCBA32(CG) = reg32;
426
427 RCBA32_OR(0x38c0, 0x7);
428 RCBA32_OR(0x36d4, 0x6680c004);
429 RCBA32_OR(0x3564, 0x3);
430}
431
Vladimir Serbinenkoa3e41c02015-05-28 16:04:17 +0200432static void pch_set_acpi_mode(void)
Stefan Reinauer8e073822012-04-04 00:07:22 +0200433{
Vladimir Serbinenkoa3e41c02015-05-28 16:04:17 +0200434 if (!acpi_is_wakeup_s3() && CONFIG_HAVE_SMI_HANDLER) {
Stefan Reinauer8e073822012-04-04 00:07:22 +0200435#if ENABLE_ACPI_MODE_IN_COREBOOT
Duncan Laurie95be1d62012-04-09 12:31:43 -0700436 printk(BIOS_DEBUG, "Enabling ACPI via APMC:\n");
Vladimir Serbinenkoa3e41c02015-05-28 16:04:17 +0200437 outb(APM_CNT_ACPI_ENABLE, APM_CNT); // Enable ACPI mode
Duncan Laurie95be1d62012-04-09 12:31:43 -0700438 printk(BIOS_DEBUG, "done.\n");
Stefan Reinauer8e073822012-04-04 00:07:22 +0200439#else
Duncan Laurie95be1d62012-04-09 12:31:43 -0700440 printk(BIOS_DEBUG, "Disabling ACPI via APMC:\n");
Vladimir Serbinenkoa3e41c02015-05-28 16:04:17 +0200441 outb(APM_CNT_ACPI_DISABLE, APM_CNT); // Disable ACPI mode
Duncan Laurie95be1d62012-04-09 12:31:43 -0700442 printk(BIOS_DEBUG, "done.\n");
Stefan Reinauer8e073822012-04-04 00:07:22 +0200443#endif
Duncan Laurie95be1d62012-04-09 12:31:43 -0700444 }
Stefan Reinauer8e073822012-04-04 00:07:22 +0200445}
Stefan Reinauer8e073822012-04-04 00:07:22 +0200446
447static void pch_disable_smm_only_flashing(struct device *dev)
448{
449 u8 reg8;
450
451 printk(BIOS_SPEW, "Enabling BIOS updates outside of SMM... ");
452 reg8 = pci_read_config8(dev, 0xdc); /* BIOS_CNTL */
453 reg8 &= ~(1 << 5);
454 pci_write_config8(dev, 0xdc, reg8);
455}
456
457static void pch_fixups(struct device *dev)
458{
459 u8 gen_pmcon_2;
460
461 /* Indicate DRAM init done for MRC S3 to know it can resume */
462 gen_pmcon_2 = pci_read_config8(dev, GEN_PMCON_2);
463 gen_pmcon_2 |= (1 << 7);
464 pci_write_config8(dev, GEN_PMCON_2, gen_pmcon_2);
465
466 /*
467 * Enable DMI ASPM in the PCH
468 */
469 RCBA32_AND_OR(0x2304, ~(1 << 10), 0);
470 RCBA32_OR(0x21a4, (1 << 11)|(1 << 10));
471 RCBA32_OR(0x21a8, 0x3);
472}
473
474static void pch_decode_init(struct device *dev)
475{
476 config_t *config = dev->chip_info;
477
478 printk(BIOS_DEBUG, "pch_decode_init\n");
479
480 pci_write_config32(dev, LPC_GEN1_DEC, config->gen1_dec);
481 pci_write_config32(dev, LPC_GEN2_DEC, config->gen2_dec);
482 pci_write_config32(dev, LPC_GEN3_DEC, config->gen3_dec);
483 pci_write_config32(dev, LPC_GEN4_DEC, config->gen4_dec);
484}
485
Nico Huber7b2f9f62015-10-01 19:00:51 +0200486static void pch_spi_init(const struct device *const dev)
487{
488 const config_t *const config = dev->chip_info;
489
490 printk(BIOS_DEBUG, "pch_spi_init\n");
491
492 if (config->spi_uvscc)
493 RCBA32(0x3800 + 0xc8) = config->spi_uvscc;
494 if (config->spi_lvscc)
495 RCBA32(0x3800 + 0xc4) = config->spi_lvscc;
496
497 if (config->spi_uvscc || config->spi_lvscc)
498 RCBA32_OR(0x3800 + 0xc4, 1 << 23); /* lock both UVSCC + LVSCC */
499}
500
Stefan Reinauer8e073822012-04-04 00:07:22 +0200501static void lpc_init(struct device *dev)
502{
503 printk(BIOS_DEBUG, "pch: lpc_init\n");
504
505 /* Set the value for PCI command register. */
506 pci_write_config16(dev, PCI_COMMAND, 0x000f);
507
508 /* IO APIC initialization. */
Paul Menzel9c50e6a2013-05-03 12:23:39 +0200509 pch_enable_ioapic(dev);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200510
511 pch_enable_serial_irqs(dev);
512
513 /* Setup the PIRQ. */
514 pch_pirq_init(dev);
515
516 /* Setup power options. */
517 pch_power_options(dev);
518
519 /* Initialize power management */
Duncan Laurie3f6a4d72012-06-28 13:03:40 -0700520 switch (pch_silicon_type()) {
521 case PCH_TYPE_CPT: /* CougarPoint */
522 cpt_pm_init(dev);
523 break;
524 case PCH_TYPE_PPT: /* PantherPoint */
525 ppt_pm_init(dev);
526 break;
527 default:
528 printk(BIOS_ERR, "Unknown Chipset: 0x%04x\n", dev->device);
529 }
Stefan Reinauer8e073822012-04-04 00:07:22 +0200530
531 /* Set the state of the GPIO lines. */
532 //gpio_init(dev);
533
534 /* Initialize the real time clock. */
535 pch_rtc_init(dev);
536
537 /* Initialize ISA DMA. */
538 isa_dma_init();
539
540 /* Initialize the High Precision Event Timers, if present. */
Nico Huberb2dae792015-10-26 12:34:02 +0100541 enable_hpet(dev);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200542
543 /* Initialize Clock Gating */
544 enable_clock_gating(dev);
545
546 setup_i8259();
547
548 /* The OS should do this? */
549 /* Interrupt 9 should be level triggered (SCI) */
550 i8259_configure_irq_trigger(9, 1);
551
552 pch_disable_smm_only_flashing(dev);
553
Vladimir Serbinenkoa3e41c02015-05-28 16:04:17 +0200554 pch_set_acpi_mode();
Stefan Reinauer8e073822012-04-04 00:07:22 +0200555
556 pch_fixups(dev);
Nico Huber7b2f9f62015-10-01 19:00:51 +0200557
558 pch_spi_init(dev);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200559}
560
561static void pch_lpc_read_resources(device_t dev)
562{
563 struct resource *res;
Marc Jonesa0bec172012-07-13 14:14:34 -0600564 config_t *config = dev->chip_info;
565 u8 io_index = 0;
Stefan Reinauer8e073822012-04-04 00:07:22 +0200566
567 /* Get the normal PCI resources of this device. */
568 pci_dev_read_resources(dev);
569
570 /* Add an extra subtractive resource for both memory and I/O. */
Marc Jonesa0bec172012-07-13 14:14:34 -0600571 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
Stefan Reinauer8e073822012-04-04 00:07:22 +0200572 res->base = 0;
573 res->size = 0x1000;
574 res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
575 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
576
Marc Jonesa0bec172012-07-13 14:14:34 -0600577 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
Vladimir Serbinenko0650cd02014-02-05 15:03:50 +0100578 res->base = 0xff000000;
579 /* Some systems (e.g. X230) have 12 MiB flash.
580 SPI controller supports up to 2 x 16 MiB of flash but
581 address map limits this to 16MiB. */
582 res->size = 0x01000000; /* 16 MB for flash */
Stefan Reinauer8e073822012-04-04 00:07:22 +0200583 res->flags = IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE |
584 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
585
586 res = new_resource(dev, 3); /* IOAPIC */
587 res->base = IO_APIC_ADDR;
588 res->size = 0x00001000;
589 res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
Marc Jonesa0bec172012-07-13 14:14:34 -0600590
591 /* Set PCH IO decode ranges if required.*/
592 if ((config->gen1_dec & 0xFFFC) > 0x1000) {
593 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
594 res->base = config->gen1_dec & 0xFFFC;
595 res->size = (config->gen1_dec >> 16) & 0xFC;
596 res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
597 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
598 }
599
600 if ((config->gen2_dec & 0xFFFC) > 0x1000) {
601 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
602 res->base = config->gen2_dec & 0xFFFC;
603 res->size = (config->gen2_dec >> 16) & 0xFC;
604 res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
605 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
606 }
607
608 if ((config->gen3_dec & 0xFFFC) > 0x1000) {
609 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
610 res->base = config->gen3_dec & 0xFFFC;
611 res->size = (config->gen3_dec >> 16) & 0xFC;
612 res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
613 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
614 }
615
616 if ((config->gen4_dec & 0xFFFC) > 0x1000) {
617 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
618 res->base = config->gen4_dec & 0xFFFC;
619 res->size = (config->gen4_dec >> 16) & 0xFC;
620 res->flags = IORESOURCE_IO| IORESOURCE_SUBTRACTIVE |
621 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
622 }
Stefan Reinauer8e073822012-04-04 00:07:22 +0200623}
624
625static void pch_lpc_enable_resources(device_t dev)
626{
627 pch_decode_init(dev);
628 return pci_dev_enable_resources(dev);
629}
630
631static void pch_lpc_enable(device_t dev)
632{
633 /* Enable PCH Display Port */
634 RCBA16(DISPBDF) = 0x0010;
635 RCBA32_OR(FD2, PCH_ENABLE_DBDF);
636
637 pch_enable(dev);
638}
639
640static void set_subsystem(device_t dev, unsigned vendor, unsigned device)
641{
642 if (!vendor || !device) {
643 pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
644 pci_read_config32(dev, PCI_VENDOR_ID));
645 } else {
646 pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
647 ((device & 0xffff) << 16) | (vendor & 0xffff));
648 }
649}
650
Alexander Couzensa90dad12015-04-12 21:49:46 +0200651static void southbridge_inject_dsdt(device_t dev)
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +0200652{
Elyes HAOUAS035df002016-10-03 21:54:16 +0200653 global_nvs_t *gnvs = cbmem_add (CBMEM_ID_ACPI_GNVS, sizeof(*gnvs));
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +0200654
655 if (gnvs) {
Vladimir Serbinenkodd2bc3f2014-10-31 09:16:31 +0100656 const struct i915_gpu_controller_info *gfx = intel_gma_get_controller_info();
Elyes HAOUAS035df002016-10-03 21:54:16 +0200657 memset(gnvs, 0, sizeof(*gnvs));
Vladimir Serbinenko7309c642014-10-05 11:07:33 +0200658
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +0200659 acpi_create_gnvs(gnvs);
Vladimir Serbinenko06c788d2014-10-12 00:17:11 +0200660
661 gnvs->apic = 1;
662 gnvs->mpen = 1; /* Enable Multi Processing */
663 gnvs->pcnt = dev_count_cpu();
664
Vladimir Serbinenkodd2bc3f2014-10-31 09:16:31 +0100665 gnvs->ndid = gfx->ndid;
666 memcpy(gnvs->did, gfx->did, sizeof(gnvs->did));
667
Martin Roth7a1a3ad2017-06-24 21:29:38 -0600668#if IS_ENABLED(CONFIG_CHROMEOS)
Vladimir Serbinenko06c788d2014-10-12 00:17:11 +0200669 chromeos_init_vboot(&(gnvs->chromeos));
670#endif
671
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +0200672 /* And tell SMI about it */
673 smm_setup_structures(gnvs, NULL, NULL);
674
Vladimir Serbinenko334fd8e2014-10-05 11:10:35 +0200675 /* Add it to DSDT. */
Vladimir Serbinenko226d7842014-11-04 21:09:23 +0100676 acpigen_write_scope("\\");
677 acpigen_write_name_dword("NVSA", (u32) gnvs);
678 acpigen_pop_len();
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +0200679 }
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +0200680}
681
Vladimir Serbinenko5b044ae2014-10-25 15:20:55 +0200682void acpi_fill_fadt(acpi_fadt_t *fadt)
683{
684 device_t dev = dev_find_slot(0, PCI_DEVFN(0x1f,0));
685 config_t *chip = dev->chip_info;
686 u16 pmbase = pci_read_config16(dev, 0x40) & 0xfffe;
687 int c2_latency;
688
689 fadt->model = 1;
690
691 fadt->sci_int = 0x9;
692 fadt->smi_cmd = APM_CNT;
693 fadt->acpi_enable = APM_CNT_ACPI_ENABLE;
694 fadt->acpi_disable = APM_CNT_ACPI_DISABLE;
695 fadt->s4bios_req = 0x0;
696 fadt->pstate_cnt = 0;
697
698 fadt->pm1a_evt_blk = pmbase;
699 fadt->pm1b_evt_blk = 0x0;
700 fadt->pm1a_cnt_blk = pmbase + 0x4;
701 fadt->pm1b_cnt_blk = 0x0;
702 fadt->pm2_cnt_blk = pmbase + 0x50;
703 fadt->pm_tmr_blk = pmbase + 0x8;
704 fadt->gpe0_blk = pmbase + 0x20;
705 fadt->gpe1_blk = 0;
706
707 fadt->pm1_evt_len = 4;
708 fadt->pm1_cnt_len = 2;
709 fadt->pm2_cnt_len = 1;
710 fadt->pm_tmr_len = 4;
711 fadt->gpe0_blk_len = 16;
712 fadt->gpe1_blk_len = 0;
713 fadt->gpe1_base = 0;
714 fadt->cst_cnt = 0;
715 c2_latency = chip->c2_latency;
716 if (!c2_latency) {
717 c2_latency = 101; /* c2 unsupported */
718 }
719 fadt->p_lvl2_lat = c2_latency;
720 fadt->p_lvl3_lat = 87;
721 fadt->flush_size = 1024;
722 fadt->flush_stride = 16;
723 fadt->duty_offset = 1;
724 if (chip->p_cnt_throttling_supported) {
725 fadt->duty_width = 3;
726 } else {
727 fadt->duty_width = 0;
728 }
729 fadt->day_alrm = 0xd;
730 fadt->mon_alrm = 0x00;
731 fadt->century = 0x00;
732 fadt->iapc_boot_arch = ACPI_FADT_LEGACY_DEVICES | ACPI_FADT_8042;
733
734 fadt->flags = ACPI_FADT_WBINVD |
735 ACPI_FADT_C1_SUPPORTED |
736 ACPI_FADT_SLEEP_BUTTON |
737 ACPI_FADT_RESET_REGISTER |
738 ACPI_FADT_SEALED_CASE |
739 ACPI_FADT_S4_RTC_WAKE |
740 ACPI_FADT_PLATFORM_CLOCK;
741 if (chip->docking_supported) {
742 fadt->flags |= ACPI_FADT_DOCKING_SUPPORTED;
743 }
744 if (c2_latency < 100) {
745 fadt->flags |= ACPI_FADT_C2_MP_SUPPORTED;
746 }
747
748 fadt->reset_reg.space_id = 1;
749 fadt->reset_reg.bit_width = 8;
750 fadt->reset_reg.bit_offset = 0;
751 fadt->reset_reg.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
752 fadt->reset_reg.addrl = 0xcf9;
753 fadt->reset_reg.addrh = 0;
754
755 fadt->reset_value = 6;
756
757 fadt->x_pm1a_evt_blk.space_id = 1;
758 fadt->x_pm1a_evt_blk.bit_width = 32;
759 fadt->x_pm1a_evt_blk.bit_offset = 0;
760 fadt->x_pm1a_evt_blk.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
761 fadt->x_pm1a_evt_blk.addrl = pmbase;
762 fadt->x_pm1a_evt_blk.addrh = 0x0;
763
764 fadt->x_pm1b_evt_blk.space_id = 1;
765 fadt->x_pm1b_evt_blk.bit_width = 0;
766 fadt->x_pm1b_evt_blk.bit_offset = 0;
767 fadt->x_pm1b_evt_blk.access_size = 0;
768 fadt->x_pm1b_evt_blk.addrl = 0x0;
769 fadt->x_pm1b_evt_blk.addrh = 0x0;
770
771 fadt->x_pm1a_cnt_blk.space_id = 1;
772 fadt->x_pm1a_cnt_blk.bit_width = 16;
773 fadt->x_pm1a_cnt_blk.bit_offset = 0;
774 fadt->x_pm1a_cnt_blk.access_size = ACPI_ACCESS_SIZE_WORD_ACCESS;
775 fadt->x_pm1a_cnt_blk.addrl = pmbase + 0x4;
776 fadt->x_pm1a_cnt_blk.addrh = 0x0;
777
778 fadt->x_pm1b_cnt_blk.space_id = 1;
779 fadt->x_pm1b_cnt_blk.bit_width = 0;
780 fadt->x_pm1b_cnt_blk.bit_offset = 0;
781 fadt->x_pm1b_cnt_blk.access_size = 0;
782 fadt->x_pm1b_cnt_blk.addrl = 0x0;
783 fadt->x_pm1b_cnt_blk.addrh = 0x0;
784
785 fadt->x_pm2_cnt_blk.space_id = 1;
786 fadt->x_pm2_cnt_blk.bit_width = 8;
787 fadt->x_pm2_cnt_blk.bit_offset = 0;
788 fadt->x_pm2_cnt_blk.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
789 fadt->x_pm2_cnt_blk.addrl = pmbase + 0x50;
790 fadt->x_pm2_cnt_blk.addrh = 0x0;
791
792 fadt->x_pm_tmr_blk.space_id = 1;
793 fadt->x_pm_tmr_blk.bit_width = 32;
794 fadt->x_pm_tmr_blk.bit_offset = 0;
795 fadt->x_pm_tmr_blk.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
796 fadt->x_pm_tmr_blk.addrl = pmbase + 0x8;
797 fadt->x_pm_tmr_blk.addrh = 0x0;
798
799 fadt->x_gpe0_blk.space_id = 1;
800 fadt->x_gpe0_blk.bit_width = 128;
801 fadt->x_gpe0_blk.bit_offset = 0;
802 fadt->x_gpe0_blk.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
803 fadt->x_gpe0_blk.addrl = pmbase + 0x20;
804 fadt->x_gpe0_blk.addrh = 0x0;
805
806 fadt->x_gpe1_blk.space_id = 1;
807 fadt->x_gpe1_blk.bit_width = 0;
808 fadt->x_gpe1_blk.bit_offset = 0;
809 fadt->x_gpe1_blk.access_size = 0;
810 fadt->x_gpe1_blk.addrl = 0x0;
811 fadt->x_gpe1_blk.addrh = 0x0;
812}
813
Aaron Durbinaa090cb2017-09-13 16:01:52 -0600814static const char *lpc_acpi_name(const struct device *dev)
Patrick Rudolph604f6982017-06-07 09:46:52 +0200815{
816 return "LPCB";
817}
818
Alexander Couzens5eea4582015-04-12 22:18:55 +0200819static void southbridge_fill_ssdt(device_t device)
Vladimir Serbinenko36fa5b82014-10-28 23:43:20 +0100820{
821 device_t dev = dev_find_slot(0, PCI_DEVFN(0x1f,0));
822 config_t *chip = dev->chip_info;
823
824 intel_acpi_pcie_hotplug_generator(chip->pcie_hotplug_map, 8);
Tobias Diedrich7f5efd92017-12-14 00:29:01 +0100825 intel_acpi_gen_def_acpi_pirq(dev);
Vladimir Serbinenko36fa5b82014-10-28 23:43:20 +0100826}
827
Vladimir Serbinenkob06a2492015-05-21 10:32:59 +0200828static void lpc_final(struct device *dev)
829{
Bill XIEd533b162017-08-22 16:26:22 +0800830 /* Call SMM finalize() handlers before resume */
831 if (IS_ENABLED(CONFIG_HAVE_SMI_HANDLER)) {
832 if (IS_ENABLED(CONFIG_INTEL_CHIPSET_LOCKDOWN) ||
833 acpi_is_wakeup_s3()) {
834 outb(APM_CNT_FINALIZE, APM_CNT);
835 }
Vladimir Serbinenkob06a2492015-05-21 10:32:59 +0200836 }
837}
838
Stefan Reinauer8e073822012-04-04 00:07:22 +0200839static struct pci_operations pci_ops = {
840 .set_subsystem = set_subsystem,
841};
842
843static struct device_operations device_ops = {
844 .read_resources = pch_lpc_read_resources,
845 .set_resources = pci_dev_set_resources,
846 .enable_resources = pch_lpc_enable_resources,
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +0200847 .write_acpi_tables = acpi_write_hpet,
Vladimir Serbinenko334fd8e2014-10-05 11:10:35 +0200848 .acpi_inject_dsdt_generator = southbridge_inject_dsdt,
Vladimir Serbinenko36fa5b82014-10-28 23:43:20 +0100849 .acpi_fill_ssdt_generator = southbridge_fill_ssdt,
Patrick Rudolph604f6982017-06-07 09:46:52 +0200850 .acpi_name = lpc_acpi_name,
Stefan Reinauer8e073822012-04-04 00:07:22 +0200851 .init = lpc_init,
Vladimir Serbinenkob06a2492015-05-21 10:32:59 +0200852 .final = lpc_final,
Stefan Reinauer8e073822012-04-04 00:07:22 +0200853 .enable = pch_lpc_enable,
Kyösti Mälkkid0e212c2015-02-26 20:47:47 +0200854 .scan_bus = scan_lpc_bus,
Stefan Reinauer8e073822012-04-04 00:07:22 +0200855 .ops_pci = &pci_ops,
856};
857
858
Kimarie Hoote6f459c2012-07-14 08:26:08 -0600859/* IDs for LPC device of Intel 6 Series Chipset, Intel 7 Series Chipset, and
860 * Intel C200 Series Chipset
Stefan Reinauer8e073822012-04-04 00:07:22 +0200861 */
862
Vladimir Serbinenko42d55e02016-01-02 01:47:26 +0100863static const unsigned short pci_device_ids[] = {
864 0x1c40, 0x1c41, 0x1c42, 0x1c43, 0x1c44, 0x1c45, 0x1c46, 0x1c47, 0x1c48,
865 0x1c49, 0x1c4a, 0x1c4b, 0x1c4c, 0x1c4d, 0x1c4e, 0x1c4f, 0x1c50, 0x1c51,
866 0x1c52, 0x1c53, 0x1c54, 0x1c55, 0x1c56, 0x1c57, 0x1c58, 0x1c59, 0x1c5a,
867 0x1c5b, 0x1c5c, 0x1c5d, 0x1c5e, 0x1c5f,
868
869 0x1e41, 0x1e42, 0x1e43, 0x1e44, 0x1e45, 0x1e46, 0x1e47, 0x1e48, 0x1e49,
870 0x1e4a, 0x1e4b, 0x1e4c, 0x1e4d, 0x1e4e, 0x1e4f, 0x1e50, 0x1e51, 0x1e52,
871 0x1e53, 0x1e54, 0x1e55, 0x1e56, 0x1e57, 0x1e58, 0x1e59, 0x1e5a, 0x1e5b,
872 0x1e5c, 0x1e5d, 0x1e5e, 0x1e5f,
873
874 0 };
Stefan Reinauer9a380ab2012-06-22 13:16:11 -0700875
876static const struct pci_driver pch_lpc __pci_driver = {
877 .ops = &device_ops,
878 .vendor = PCI_VENDOR_ID_INTEL,
879 .devices = pci_device_ids,
Stefan Reinauer8e073822012-04-04 00:07:22 +0200880};