blob: 2bfc1e3374e7b4c6d0f9ef653718c01956117798 [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>
Stefan Reinauer8e073822012-04-04 00:07:22 +020038
39#define NMI_OFF 0
40
41#define ENABLE_ACPI_MODE_IN_COREBOOT 0
Stefan Reinauer8e073822012-04-04 00:07:22 +020042
43typedef 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));
Martin Roth7a1a3ad2017-06-24 21:29:38 -060079#if !IS_ENABLED(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
106static void pch_pirq_init(device_t dev)
107{
108 device_t 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
143static void pch_gpi_routing(device_t dev)
144{
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
172static void pch_power_options(device_t dev)
173{
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
181 int pwr_on=CONFIG_MAINBOARD_POWER_ON_AFTER_POWER_FAIL;
182 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");
238 reg8 |= ( 1 << 7); /* Can't mask NMI from PCI-E and NMI_NOW */
239 }
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 */
269 reg32 = RCBA32(0x3310);
270 reg32 |= (1 << 4)|(1 << 5)|(1 << 0);
271 RCBA32(0x3310) = reg32;
272
273 reg32 = RCBA32(0x3f02);
274 reg32 &= ~0xf;
275 RCBA32(0x3f02) = reg32;
276}
277
278static void pch_rtc_init(struct device *dev)
279{
Aaron Durbin976200382017-09-15 15:19:32 -0600280 int rtc_failed = rtc_failure();
Stefan Reinauer8e073822012-04-04 00:07:22 +0200281
Stefan Reinauer8e073822012-04-04 00:07:22 +0200282 if (rtc_failed) {
Aaron Durbin976200382017-09-15 15:19:32 -0600283 if (IS_ENABLED(CONFIG_ELOG))
284 elog_add_event(ELOG_TYPE_RTC_RESET);
285 pci_update_config8(dev, GEN_PMCON_3, ~RTC_BATTERY_DEAD, 0);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200286 }
Aaron Durbin976200382017-09-15 15:19:32 -0600287
Stefan Reinauer8e073822012-04-04 00:07:22 +0200288 printk(BIOS_DEBUG, "rtc_failed = 0x%x\n", rtc_failed);
289
Gabe Blackb3f08c62014-04-30 17:12:25 -0700290 cmos_init(rtc_failed);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200291}
292
Duncan Laurie3f6a4d72012-06-28 13:03:40 -0700293/* CougarPoint PCH Power Management init */
294static void cpt_pm_init(struct device *dev)
Stefan Reinauer8e073822012-04-04 00:07:22 +0200295{
Duncan Laurie3f6a4d72012-06-28 13:03:40 -0700296 printk(BIOS_DEBUG, "CougarPoint PM init\n");
Stefan Reinauer8e073822012-04-04 00:07:22 +0200297 pci_write_config8(dev, 0xa9, 0x47);
298 RCBA32_AND_OR(0x2238, ~0UL, (1 << 6)|(1 << 0));
299 RCBA32_AND_OR(0x228c, ~0UL, (1 << 0));
300 RCBA16_AND_OR(0x1100, ~0UL, (1 << 13)|(1 << 14));
301 RCBA16_AND_OR(0x0900, ~0UL, (1 << 14));
302 RCBA32(0x2304) = 0xc0388400;
303 RCBA32_AND_OR(0x2314, ~0UL, (1 << 5)|(1 << 18));
304 RCBA32_AND_OR(0x2320, ~0UL, (1 << 15)|(1 << 1));
305 RCBA32_AND_OR(0x3314, ~0x1f, 0xf);
306 RCBA32(0x3318) = 0x050f0000;
307 RCBA32(0x3324) = 0x04000000;
308 RCBA32_AND_OR(0x3340, ~0UL, 0xfffff);
309 RCBA32_AND_OR(0x3344, ~0UL, (1 << 1));
310 RCBA32(0x3360) = 0x0001c000;
311 RCBA32(0x3368) = 0x00061100;
312 RCBA32(0x3378) = 0x7f8fdfff;
313 RCBA32(0x337c) = 0x000003fc;
314 RCBA32(0x3388) = 0x00001000;
315 RCBA32(0x3390) = 0x0001c000;
316 RCBA32(0x33a0) = 0x00000800;
317 RCBA32(0x33b0) = 0x00001000;
318 RCBA32(0x33c0) = 0x00093900;
319 RCBA32(0x33cc) = 0x24653002;
320 RCBA32(0x33d0) = 0x062108fe;
321 RCBA32_AND_OR(0x33d4, 0xf000f000, 0x00670060);
322 RCBA32(0x3a28) = 0x01010000;
323 RCBA32(0x3a2c) = 0x01010404;
324 RCBA32(0x3a80) = 0x01041041;
325 RCBA32_AND_OR(0x3a84, ~0x0000ffff, 0x00001001);
326 RCBA32_AND_OR(0x3a84, ~0UL, (1 << 24)); /* SATA 2/3 disabled */
327 RCBA32_AND_OR(0x3a88, ~0UL, (1 << 0)); /* SATA 4/5 disabled */
328 RCBA32(0x3a6c) = 0x00000001;
329 RCBA32_AND_OR(0x2344, 0x00ffff00, 0xff00000c);
330 RCBA32_AND_OR(0x80c, ~(0xff << 20), 0x11 << 20);
331 RCBA32(0x33c8) = 0;
332 RCBA32_AND_OR(0x21b0, ~0UL, 0xf);
333}
334
Duncan Laurie3f6a4d72012-06-28 13:03:40 -0700335/* PantherPoint PCH Power Management init */
336static void ppt_pm_init(struct device *dev)
337{
338 printk(BIOS_DEBUG, "PantherPoint PM init\n");
339 pci_write_config8(dev, 0xa9, 0x47);
340 RCBA32_AND_OR(0x2238, ~0UL, (1 << 0));
341 RCBA32_AND_OR(0x228c, ~0UL, (1 << 0));
342 RCBA16_AND_OR(0x1100, ~0UL, (1 << 13)|(1 << 14));
343 RCBA16_AND_OR(0x0900, ~0UL, (1 << 14));
344 RCBA32(0x2304) = 0xc03b8400;
345 RCBA32_AND_OR(0x2314, ~0UL, (1 << 5)|(1 << 18));
346 RCBA32_AND_OR(0x2320, ~0UL, (1 << 15)|(1 << 1));
347 RCBA32_AND_OR(0x3314, ~0x1f, 0xf);
348 RCBA32(0x3318) = 0x054f0000;
349 RCBA32(0x3324) = 0x04000000;
350 RCBA32_AND_OR(0x3340, ~0UL, 0xfffff);
351 RCBA32_AND_OR(0x3344, ~0UL, (1 << 1)|(1 << 0));
352 RCBA32(0x3360) = 0x0001c000;
353 RCBA32(0x3368) = 0x00061100;
354 RCBA32(0x3378) = 0x7f8fdfff;
355 RCBA32(0x337c) = 0x000003fd;
356 RCBA32(0x3388) = 0x00001000;
357 RCBA32(0x3390) = 0x0001c000;
358 RCBA32(0x33a0) = 0x00000800;
359 RCBA32(0x33b0) = 0x00001000;
360 RCBA32(0x33c0) = 0x00093900;
361 RCBA32(0x33cc) = 0x24653002;
362 RCBA32(0x33d0) = 0x067388fe;
363 RCBA32_AND_OR(0x33d4, 0xf000f000, 0x00670060);
364 RCBA32(0x3a28) = 0x01010000;
365 RCBA32(0x3a2c) = 0x01010404;
366 RCBA32(0x3a80) = 0x01040000;
367 RCBA32_AND_OR(0x3a84, ~0x0000ffff, 0x00001001);
368 RCBA32_AND_OR(0x3a84, ~0UL, (1 << 24)); /* SATA 2/3 disabled */
369 RCBA32_AND_OR(0x3a88, ~0UL, (1 << 0)); /* SATA 4/5 disabled */
370 RCBA32(0x3a6c) = 0x00000001;
371 RCBA32_AND_OR(0x2344, 0x00ffff00, 0xff00000c);
372 RCBA32_AND_OR(0x80c, ~(0xff << 20), 0x11 << 20);
373 RCBA32_AND_OR(0x33a4, ~0UL, (1 << 0));
374 RCBA32(0x33c8) = 0;
375 RCBA32_AND_OR(0x21b0, ~0UL, 0xf);
376}
377
Nico Huberb2dae792015-10-26 12:34:02 +0100378static void enable_hpet(struct device *const dev)
Stefan Reinauer8e073822012-04-04 00:07:22 +0200379{
380 u32 reg32;
Nico Huberb2dae792015-10-26 12:34:02 +0100381 size_t i;
382
383 /* Assign unique bus/dev/fn for each HPET */
384 for (i = 0; i < 8; ++i)
385 pci_write_config16(dev, LPC_HnBDF(i),
386 PCH_HPET_PCI_BUS << 8 | PCH_HPET_PCI_SLOT << 3 | i);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200387
388 /* Move HPET to default address 0xfed00000 and enable it */
389 reg32 = RCBA32(HPTC);
390 reg32 |= (1 << 7); // HPET Address Enable
391 reg32 &= ~(3 << 0);
392 RCBA32(HPTC) = reg32;
393}
394
395static void enable_clock_gating(device_t dev)
396{
397 u32 reg32;
398 u16 reg16;
399
400 RCBA32_AND_OR(0x2234, ~0UL, 0xf);
401
402 reg16 = pci_read_config16(dev, GEN_PMCON_1);
403 reg16 |= (1 << 2) | (1 << 11);
404 pci_write_config16(dev, GEN_PMCON_1, reg16);
405
406 pch_iobp_update(0xEB007F07, ~0UL, (1 << 31));
407 pch_iobp_update(0xEB004000, ~0UL, (1 << 7));
408 pch_iobp_update(0xEC007F07, ~0UL, (1 << 31));
409 pch_iobp_update(0xEC004000, ~0UL, (1 << 7));
410
411 reg32 = RCBA32(CG);
412 reg32 |= (1 << 31);
413 reg32 |= (1 << 29) | (1 << 28);
414 reg32 |= (1 << 27) | (1 << 26) | (1 << 25) | (1 << 24);
415 reg32 |= (1 << 16);
416 reg32 |= (1 << 17);
417 reg32 |= (1 << 18);
418 reg32 |= (1 << 22);
419 reg32 |= (1 << 23);
420 reg32 &= ~(1 << 20);
421 reg32 |= (1 << 19);
422 reg32 |= (1 << 0);
423 reg32 |= (0xf << 1);
424 RCBA32(CG) = reg32;
425
426 RCBA32_OR(0x38c0, 0x7);
427 RCBA32_OR(0x36d4, 0x6680c004);
428 RCBA32_OR(0x3564, 0x3);
429}
430
Vladimir Serbinenkoa3e41c02015-05-28 16:04:17 +0200431static void pch_set_acpi_mode(void)
Stefan Reinauer8e073822012-04-04 00:07:22 +0200432{
Vladimir Serbinenkoa3e41c02015-05-28 16:04:17 +0200433 if (!acpi_is_wakeup_s3() && CONFIG_HAVE_SMI_HANDLER) {
Stefan Reinauer8e073822012-04-04 00:07:22 +0200434#if ENABLE_ACPI_MODE_IN_COREBOOT
Duncan Laurie95be1d62012-04-09 12:31:43 -0700435 printk(BIOS_DEBUG, "Enabling ACPI via APMC:\n");
Vladimir Serbinenkoa3e41c02015-05-28 16:04:17 +0200436 outb(APM_CNT_ACPI_ENABLE, APM_CNT); // Enable ACPI mode
Duncan Laurie95be1d62012-04-09 12:31:43 -0700437 printk(BIOS_DEBUG, "done.\n");
Stefan Reinauer8e073822012-04-04 00:07:22 +0200438#else
Duncan Laurie95be1d62012-04-09 12:31:43 -0700439 printk(BIOS_DEBUG, "Disabling ACPI via APMC:\n");
Vladimir Serbinenkoa3e41c02015-05-28 16:04:17 +0200440 outb(APM_CNT_ACPI_DISABLE, APM_CNT); // Disable ACPI mode
Duncan Laurie95be1d62012-04-09 12:31:43 -0700441 printk(BIOS_DEBUG, "done.\n");
Stefan Reinauer8e073822012-04-04 00:07:22 +0200442#endif
Duncan Laurie95be1d62012-04-09 12:31:43 -0700443 }
Stefan Reinauer8e073822012-04-04 00:07:22 +0200444}
Stefan Reinauer8e073822012-04-04 00:07:22 +0200445
446static void pch_disable_smm_only_flashing(struct device *dev)
447{
448 u8 reg8;
449
450 printk(BIOS_SPEW, "Enabling BIOS updates outside of SMM... ");
451 reg8 = pci_read_config8(dev, 0xdc); /* BIOS_CNTL */
452 reg8 &= ~(1 << 5);
453 pci_write_config8(dev, 0xdc, reg8);
454}
455
456static void pch_fixups(struct device *dev)
457{
458 u8 gen_pmcon_2;
459
460 /* Indicate DRAM init done for MRC S3 to know it can resume */
461 gen_pmcon_2 = pci_read_config8(dev, GEN_PMCON_2);
462 gen_pmcon_2 |= (1 << 7);
463 pci_write_config8(dev, GEN_PMCON_2, gen_pmcon_2);
464
465 /*
466 * Enable DMI ASPM in the PCH
467 */
468 RCBA32_AND_OR(0x2304, ~(1 << 10), 0);
469 RCBA32_OR(0x21a4, (1 << 11)|(1 << 10));
470 RCBA32_OR(0x21a8, 0x3);
471}
472
473static void pch_decode_init(struct device *dev)
474{
475 config_t *config = dev->chip_info;
476
477 printk(BIOS_DEBUG, "pch_decode_init\n");
478
479 pci_write_config32(dev, LPC_GEN1_DEC, config->gen1_dec);
480 pci_write_config32(dev, LPC_GEN2_DEC, config->gen2_dec);
481 pci_write_config32(dev, LPC_GEN3_DEC, config->gen3_dec);
482 pci_write_config32(dev, LPC_GEN4_DEC, config->gen4_dec);
483}
484
Nico Huber7b2f9f62015-10-01 19:00:51 +0200485static void pch_spi_init(const struct device *const dev)
486{
487 const config_t *const config = dev->chip_info;
488
489 printk(BIOS_DEBUG, "pch_spi_init\n");
490
491 if (config->spi_uvscc)
492 RCBA32(0x3800 + 0xc8) = config->spi_uvscc;
493 if (config->spi_lvscc)
494 RCBA32(0x3800 + 0xc4) = config->spi_lvscc;
495
496 if (config->spi_uvscc || config->spi_lvscc)
497 RCBA32_OR(0x3800 + 0xc4, 1 << 23); /* lock both UVSCC + LVSCC */
498}
499
Stefan Reinauer8e073822012-04-04 00:07:22 +0200500static void lpc_init(struct device *dev)
501{
502 printk(BIOS_DEBUG, "pch: lpc_init\n");
503
504 /* Set the value for PCI command register. */
505 pci_write_config16(dev, PCI_COMMAND, 0x000f);
506
507 /* IO APIC initialization. */
Paul Menzel9c50e6a2013-05-03 12:23:39 +0200508 pch_enable_ioapic(dev);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200509
510 pch_enable_serial_irqs(dev);
511
512 /* Setup the PIRQ. */
513 pch_pirq_init(dev);
514
515 /* Setup power options. */
516 pch_power_options(dev);
517
518 /* Initialize power management */
Duncan Laurie3f6a4d72012-06-28 13:03:40 -0700519 switch (pch_silicon_type()) {
520 case PCH_TYPE_CPT: /* CougarPoint */
521 cpt_pm_init(dev);
522 break;
523 case PCH_TYPE_PPT: /* PantherPoint */
524 ppt_pm_init(dev);
525 break;
526 default:
527 printk(BIOS_ERR, "Unknown Chipset: 0x%04x\n", dev->device);
528 }
Stefan Reinauer8e073822012-04-04 00:07:22 +0200529
530 /* Set the state of the GPIO lines. */
531 //gpio_init(dev);
532
533 /* Initialize the real time clock. */
534 pch_rtc_init(dev);
535
536 /* Initialize ISA DMA. */
537 isa_dma_init();
538
539 /* Initialize the High Precision Event Timers, if present. */
Nico Huberb2dae792015-10-26 12:34:02 +0100540 enable_hpet(dev);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200541
542 /* Initialize Clock Gating */
543 enable_clock_gating(dev);
544
545 setup_i8259();
546
547 /* The OS should do this? */
548 /* Interrupt 9 should be level triggered (SCI) */
549 i8259_configure_irq_trigger(9, 1);
550
551 pch_disable_smm_only_flashing(dev);
552
Vladimir Serbinenkoa3e41c02015-05-28 16:04:17 +0200553 pch_set_acpi_mode();
Stefan Reinauer8e073822012-04-04 00:07:22 +0200554
555 pch_fixups(dev);
Nico Huber7b2f9f62015-10-01 19:00:51 +0200556
557 pch_spi_init(dev);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200558}
559
560static void pch_lpc_read_resources(device_t dev)
561{
562 struct resource *res;
Marc Jonesa0bec172012-07-13 14:14:34 -0600563 config_t *config = dev->chip_info;
564 u8 io_index = 0;
Stefan Reinauer8e073822012-04-04 00:07:22 +0200565
566 /* Get the normal PCI resources of this device. */
567 pci_dev_read_resources(dev);
568
569 /* Add an extra subtractive resource for both memory and I/O. */
Marc Jonesa0bec172012-07-13 14:14:34 -0600570 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
Stefan Reinauer8e073822012-04-04 00:07:22 +0200571 res->base = 0;
572 res->size = 0x1000;
573 res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
574 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
575
Marc Jonesa0bec172012-07-13 14:14:34 -0600576 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
Vladimir Serbinenko0650cd02014-02-05 15:03:50 +0100577 res->base = 0xff000000;
578 /* Some systems (e.g. X230) have 12 MiB flash.
579 SPI controller supports up to 2 x 16 MiB of flash but
580 address map limits this to 16MiB. */
581 res->size = 0x01000000; /* 16 MB for flash */
Stefan Reinauer8e073822012-04-04 00:07:22 +0200582 res->flags = IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE |
583 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
584
585 res = new_resource(dev, 3); /* IOAPIC */
586 res->base = IO_APIC_ADDR;
587 res->size = 0x00001000;
588 res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
Marc Jonesa0bec172012-07-13 14:14:34 -0600589
590 /* Set PCH IO decode ranges if required.*/
591 if ((config->gen1_dec & 0xFFFC) > 0x1000) {
592 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
593 res->base = config->gen1_dec & 0xFFFC;
594 res->size = (config->gen1_dec >> 16) & 0xFC;
595 res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
596 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
597 }
598
599 if ((config->gen2_dec & 0xFFFC) > 0x1000) {
600 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
601 res->base = config->gen2_dec & 0xFFFC;
602 res->size = (config->gen2_dec >> 16) & 0xFC;
603 res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
604 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
605 }
606
607 if ((config->gen3_dec & 0xFFFC) > 0x1000) {
608 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
609 res->base = config->gen3_dec & 0xFFFC;
610 res->size = (config->gen3_dec >> 16) & 0xFC;
611 res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
612 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
613 }
614
615 if ((config->gen4_dec & 0xFFFC) > 0x1000) {
616 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
617 res->base = config->gen4_dec & 0xFFFC;
618 res->size = (config->gen4_dec >> 16) & 0xFC;
619 res->flags = IORESOURCE_IO| IORESOURCE_SUBTRACTIVE |
620 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
621 }
Stefan Reinauer8e073822012-04-04 00:07:22 +0200622}
623
624static void pch_lpc_enable_resources(device_t dev)
625{
626 pch_decode_init(dev);
627 return pci_dev_enable_resources(dev);
628}
629
630static void pch_lpc_enable(device_t dev)
631{
632 /* Enable PCH Display Port */
633 RCBA16(DISPBDF) = 0x0010;
634 RCBA32_OR(FD2, PCH_ENABLE_DBDF);
635
636 pch_enable(dev);
637}
638
639static void set_subsystem(device_t dev, unsigned vendor, unsigned device)
640{
641 if (!vendor || !device) {
642 pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
643 pci_read_config32(dev, PCI_VENDOR_ID));
644 } else {
645 pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
646 ((device & 0xffff) << 16) | (vendor & 0xffff));
647 }
648}
649
Alexander Couzensa90dad12015-04-12 21:49:46 +0200650static void southbridge_inject_dsdt(device_t dev)
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +0200651{
Elyes HAOUAS035df002016-10-03 21:54:16 +0200652 global_nvs_t *gnvs = cbmem_add (CBMEM_ID_ACPI_GNVS, sizeof(*gnvs));
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +0200653
654 if (gnvs) {
Vladimir Serbinenkodd2bc3f2014-10-31 09:16:31 +0100655 const struct i915_gpu_controller_info *gfx = intel_gma_get_controller_info();
Elyes HAOUAS035df002016-10-03 21:54:16 +0200656 memset(gnvs, 0, sizeof(*gnvs));
Vladimir Serbinenko7309c642014-10-05 11:07:33 +0200657
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +0200658 acpi_create_gnvs(gnvs);
Vladimir Serbinenko06c788d2014-10-12 00:17:11 +0200659
660 gnvs->apic = 1;
661 gnvs->mpen = 1; /* Enable Multi Processing */
662 gnvs->pcnt = dev_count_cpu();
663
Vladimir Serbinenkodd2bc3f2014-10-31 09:16:31 +0100664 gnvs->ndid = gfx->ndid;
665 memcpy(gnvs->did, gfx->did, sizeof(gnvs->did));
666
Martin Roth7a1a3ad2017-06-24 21:29:38 -0600667#if IS_ENABLED(CONFIG_CHROMEOS)
Vladimir Serbinenko06c788d2014-10-12 00:17:11 +0200668 chromeos_init_vboot(&(gnvs->chromeos));
669#endif
670
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +0200671 /* And tell SMI about it */
672 smm_setup_structures(gnvs, NULL, NULL);
673
Vladimir Serbinenko334fd8e2014-10-05 11:10:35 +0200674 /* Add it to DSDT. */
Vladimir Serbinenko226d7842014-11-04 21:09:23 +0100675 acpigen_write_scope("\\");
676 acpigen_write_name_dword("NVSA", (u32) gnvs);
677 acpigen_pop_len();
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +0200678 }
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +0200679}
680
Vladimir Serbinenko5b044ae2014-10-25 15:20:55 +0200681void acpi_fill_fadt(acpi_fadt_t *fadt)
682{
683 device_t dev = dev_find_slot(0, PCI_DEVFN(0x1f,0));
684 config_t *chip = dev->chip_info;
685 u16 pmbase = pci_read_config16(dev, 0x40) & 0xfffe;
686 int c2_latency;
687
688 fadt->model = 1;
689
690 fadt->sci_int = 0x9;
691 fadt->smi_cmd = APM_CNT;
692 fadt->acpi_enable = APM_CNT_ACPI_ENABLE;
693 fadt->acpi_disable = APM_CNT_ACPI_DISABLE;
694 fadt->s4bios_req = 0x0;
695 fadt->pstate_cnt = 0;
696
697 fadt->pm1a_evt_blk = pmbase;
698 fadt->pm1b_evt_blk = 0x0;
699 fadt->pm1a_cnt_blk = pmbase + 0x4;
700 fadt->pm1b_cnt_blk = 0x0;
701 fadt->pm2_cnt_blk = pmbase + 0x50;
702 fadt->pm_tmr_blk = pmbase + 0x8;
703 fadt->gpe0_blk = pmbase + 0x20;
704 fadt->gpe1_blk = 0;
705
706 fadt->pm1_evt_len = 4;
707 fadt->pm1_cnt_len = 2;
708 fadt->pm2_cnt_len = 1;
709 fadt->pm_tmr_len = 4;
710 fadt->gpe0_blk_len = 16;
711 fadt->gpe1_blk_len = 0;
712 fadt->gpe1_base = 0;
713 fadt->cst_cnt = 0;
714 c2_latency = chip->c2_latency;
715 if (!c2_latency) {
716 c2_latency = 101; /* c2 unsupported */
717 }
718 fadt->p_lvl2_lat = c2_latency;
719 fadt->p_lvl3_lat = 87;
720 fadt->flush_size = 1024;
721 fadt->flush_stride = 16;
722 fadt->duty_offset = 1;
723 if (chip->p_cnt_throttling_supported) {
724 fadt->duty_width = 3;
725 } else {
726 fadt->duty_width = 0;
727 }
728 fadt->day_alrm = 0xd;
729 fadt->mon_alrm = 0x00;
730 fadt->century = 0x00;
731 fadt->iapc_boot_arch = ACPI_FADT_LEGACY_DEVICES | ACPI_FADT_8042;
732
733 fadt->flags = ACPI_FADT_WBINVD |
734 ACPI_FADT_C1_SUPPORTED |
735 ACPI_FADT_SLEEP_BUTTON |
736 ACPI_FADT_RESET_REGISTER |
737 ACPI_FADT_SEALED_CASE |
738 ACPI_FADT_S4_RTC_WAKE |
739 ACPI_FADT_PLATFORM_CLOCK;
740 if (chip->docking_supported) {
741 fadt->flags |= ACPI_FADT_DOCKING_SUPPORTED;
742 }
743 if (c2_latency < 100) {
744 fadt->flags |= ACPI_FADT_C2_MP_SUPPORTED;
745 }
746
747 fadt->reset_reg.space_id = 1;
748 fadt->reset_reg.bit_width = 8;
749 fadt->reset_reg.bit_offset = 0;
750 fadt->reset_reg.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
751 fadt->reset_reg.addrl = 0xcf9;
752 fadt->reset_reg.addrh = 0;
753
754 fadt->reset_value = 6;
755
756 fadt->x_pm1a_evt_blk.space_id = 1;
757 fadt->x_pm1a_evt_blk.bit_width = 32;
758 fadt->x_pm1a_evt_blk.bit_offset = 0;
759 fadt->x_pm1a_evt_blk.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
760 fadt->x_pm1a_evt_blk.addrl = pmbase;
761 fadt->x_pm1a_evt_blk.addrh = 0x0;
762
763 fadt->x_pm1b_evt_blk.space_id = 1;
764 fadt->x_pm1b_evt_blk.bit_width = 0;
765 fadt->x_pm1b_evt_blk.bit_offset = 0;
766 fadt->x_pm1b_evt_blk.access_size = 0;
767 fadt->x_pm1b_evt_blk.addrl = 0x0;
768 fadt->x_pm1b_evt_blk.addrh = 0x0;
769
770 fadt->x_pm1a_cnt_blk.space_id = 1;
771 fadt->x_pm1a_cnt_blk.bit_width = 16;
772 fadt->x_pm1a_cnt_blk.bit_offset = 0;
773 fadt->x_pm1a_cnt_blk.access_size = ACPI_ACCESS_SIZE_WORD_ACCESS;
774 fadt->x_pm1a_cnt_blk.addrl = pmbase + 0x4;
775 fadt->x_pm1a_cnt_blk.addrh = 0x0;
776
777 fadt->x_pm1b_cnt_blk.space_id = 1;
778 fadt->x_pm1b_cnt_blk.bit_width = 0;
779 fadt->x_pm1b_cnt_blk.bit_offset = 0;
780 fadt->x_pm1b_cnt_blk.access_size = 0;
781 fadt->x_pm1b_cnt_blk.addrl = 0x0;
782 fadt->x_pm1b_cnt_blk.addrh = 0x0;
783
784 fadt->x_pm2_cnt_blk.space_id = 1;
785 fadt->x_pm2_cnt_blk.bit_width = 8;
786 fadt->x_pm2_cnt_blk.bit_offset = 0;
787 fadt->x_pm2_cnt_blk.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
788 fadt->x_pm2_cnt_blk.addrl = pmbase + 0x50;
789 fadt->x_pm2_cnt_blk.addrh = 0x0;
790
791 fadt->x_pm_tmr_blk.space_id = 1;
792 fadt->x_pm_tmr_blk.bit_width = 32;
793 fadt->x_pm_tmr_blk.bit_offset = 0;
794 fadt->x_pm_tmr_blk.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
795 fadt->x_pm_tmr_blk.addrl = pmbase + 0x8;
796 fadt->x_pm_tmr_blk.addrh = 0x0;
797
798 fadt->x_gpe0_blk.space_id = 1;
799 fadt->x_gpe0_blk.bit_width = 128;
800 fadt->x_gpe0_blk.bit_offset = 0;
801 fadt->x_gpe0_blk.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
802 fadt->x_gpe0_blk.addrl = pmbase + 0x20;
803 fadt->x_gpe0_blk.addrh = 0x0;
804
805 fadt->x_gpe1_blk.space_id = 1;
806 fadt->x_gpe1_blk.bit_width = 0;
807 fadt->x_gpe1_blk.bit_offset = 0;
808 fadt->x_gpe1_blk.access_size = 0;
809 fadt->x_gpe1_blk.addrl = 0x0;
810 fadt->x_gpe1_blk.addrh = 0x0;
811}
812
Aaron Durbinaa090cb2017-09-13 16:01:52 -0600813static const char *lpc_acpi_name(const struct device *dev)
Patrick Rudolph604f6982017-06-07 09:46:52 +0200814{
815 return "LPCB";
816}
817
Alexander Couzens5eea4582015-04-12 22:18:55 +0200818static void southbridge_fill_ssdt(device_t device)
Vladimir Serbinenko36fa5b82014-10-28 23:43:20 +0100819{
820 device_t dev = dev_find_slot(0, PCI_DEVFN(0x1f,0));
821 config_t *chip = dev->chip_info;
822
823 intel_acpi_pcie_hotplug_generator(chip->pcie_hotplug_map, 8);
824}
825
Vladimir Serbinenkob06a2492015-05-21 10:32:59 +0200826static void lpc_final(struct device *dev)
827{
Bill XIEd533b162017-08-22 16:26:22 +0800828 /* Call SMM finalize() handlers before resume */
829 if (IS_ENABLED(CONFIG_HAVE_SMI_HANDLER)) {
830 if (IS_ENABLED(CONFIG_INTEL_CHIPSET_LOCKDOWN) ||
831 acpi_is_wakeup_s3()) {
832 outb(APM_CNT_FINALIZE, APM_CNT);
833 }
Vladimir Serbinenkob06a2492015-05-21 10:32:59 +0200834 }
835}
836
Stefan Reinauer8e073822012-04-04 00:07:22 +0200837static struct pci_operations pci_ops = {
838 .set_subsystem = set_subsystem,
839};
840
841static struct device_operations device_ops = {
842 .read_resources = pch_lpc_read_resources,
843 .set_resources = pci_dev_set_resources,
844 .enable_resources = pch_lpc_enable_resources,
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +0200845 .write_acpi_tables = acpi_write_hpet,
Vladimir Serbinenko334fd8e2014-10-05 11:10:35 +0200846 .acpi_inject_dsdt_generator = southbridge_inject_dsdt,
Vladimir Serbinenko36fa5b82014-10-28 23:43:20 +0100847 .acpi_fill_ssdt_generator = southbridge_fill_ssdt,
Patrick Rudolph604f6982017-06-07 09:46:52 +0200848 .acpi_name = lpc_acpi_name,
Stefan Reinauer8e073822012-04-04 00:07:22 +0200849 .init = lpc_init,
Vladimir Serbinenkob06a2492015-05-21 10:32:59 +0200850 .final = lpc_final,
Stefan Reinauer8e073822012-04-04 00:07:22 +0200851 .enable = pch_lpc_enable,
Kyösti Mälkkid0e212c2015-02-26 20:47:47 +0200852 .scan_bus = scan_lpc_bus,
Stefan Reinauer8e073822012-04-04 00:07:22 +0200853 .ops_pci = &pci_ops,
854};
855
856
Kimarie Hoote6f459c2012-07-14 08:26:08 -0600857/* IDs for LPC device of Intel 6 Series Chipset, Intel 7 Series Chipset, and
858 * Intel C200 Series Chipset
Stefan Reinauer8e073822012-04-04 00:07:22 +0200859 */
860
Vladimir Serbinenko42d55e02016-01-02 01:47:26 +0100861static const unsigned short pci_device_ids[] = {
862 0x1c40, 0x1c41, 0x1c42, 0x1c43, 0x1c44, 0x1c45, 0x1c46, 0x1c47, 0x1c48,
863 0x1c49, 0x1c4a, 0x1c4b, 0x1c4c, 0x1c4d, 0x1c4e, 0x1c4f, 0x1c50, 0x1c51,
864 0x1c52, 0x1c53, 0x1c54, 0x1c55, 0x1c56, 0x1c57, 0x1c58, 0x1c59, 0x1c5a,
865 0x1c5b, 0x1c5c, 0x1c5d, 0x1c5e, 0x1c5f,
866
867 0x1e41, 0x1e42, 0x1e43, 0x1e44, 0x1e45, 0x1e46, 0x1e47, 0x1e48, 0x1e49,
868 0x1e4a, 0x1e4b, 0x1e4c, 0x1e4d, 0x1e4e, 0x1e4f, 0x1e50, 0x1e51, 0x1e52,
869 0x1e53, 0x1e54, 0x1e55, 0x1e56, 0x1e57, 0x1e58, 0x1e59, 0x1e5a, 0x1e5b,
870 0x1e5c, 0x1e5d, 0x1e5e, 0x1e5f,
871
872 0 };
Stefan Reinauer9a380ab2012-06-22 13:16:11 -0700873
874static const struct pci_driver pch_lpc __pci_driver = {
875 .ops = &device_ops,
876 .vendor = PCI_VENDOR_ID_INTEL,
877 .devices = pci_device_ids,
Stefan Reinauer8e073822012-04-04 00:07:22 +0200878};