blob: 61a11b30db07b8a56b630655b7fb345c8ad886be [file] [log] [blame]
Patrick Georgie72a8a32012-11-06 11:05:09 +01001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2008-2009 coresystems GmbH
5 * 2012 secunet Security Networks AG
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; version 2 of
10 * the License.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
Paul Menzela46a7122013-02-23 18:37:27 +010019 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Patrick Georgie72a8a32012-11-06 11:05:09 +010020 */
21
22#include <console/console.h>
23#include <device/device.h>
24#include <device/pci.h>
25#include <device/pci_ids.h>
26#include <pc80/mc146818rtc.h>
27#include <pc80/isa-dma.h>
28#include <pc80/i8259.h>
29#include <arch/io.h>
30#include <arch/ioapic.h>
31#include <arch/acpi.h>
32#include <cpu/cpu.h>
33#include <cpu/x86/smm.h>
34#include "i82801ix.h"
35
36#define NMI_OFF 0
37
38#define ENABLE_ACPI_MODE_IN_COREBOOT 0
39#define TEST_SMM_FLASH_LOCKDOWN 0
40
41typedef struct southbridge_intel_i82801ix_config config_t;
42
43static void i82801ix_enable_apic(struct device *dev)
44{
Patrick Georgie72a8a32012-11-06 11:05:09 +010045 u32 reg32;
46 volatile u32 *ioapic_index = (volatile u32 *)(IO_APIC_ADDR);
47 volatile u32 *ioapic_data = (volatile u32 *)(IO_APIC_ADDR + 0x10);
48
49 /* Enable IOAPIC. Keep APIC Range Select at zero. */
50 RCBA8(0x31ff) = 0x03;
51 /* We have to read 0x31ff back if bit0 changed. */
Paul Menzeld0299e42013-10-21 09:28:19 +020052 RCBA8(0x31ff);
Patrick Georgie72a8a32012-11-06 11:05:09 +010053
54 /* Lock maximum redirection entries (MRE), R/WO register. */
55 *ioapic_index = 0x01;
56 reg32 = *ioapic_data;
57 *ioapic_index = 0x01;
58 *ioapic_data = reg32;
59
60 setup_ioapic(IO_APIC_ADDR, 2); /* ICH7 code uses id 2. */
61}
62
63static void i82801ix_enable_serial_irqs(struct device *dev)
64{
65 /* Set packet length and toggle silent mode bit for one frame. */
66 pci_write_config8(dev, D31F0_SERIRQ_CNTL,
67 (1 << 7) | (1 << 6) | ((21 - 17) << 2) | (0 << 0));
68}
69
70/* PIRQ[n]_ROUT[3:0] - PIRQ Routing Control
71 * 0x00 - 0000 = Reserved
72 * 0x01 - 0001 = Reserved
73 * 0x02 - 0010 = Reserved
74 * 0x03 - 0011 = IRQ3
75 * 0x04 - 0100 = IRQ4
76 * 0x05 - 0101 = IRQ5
77 * 0x06 - 0110 = IRQ6
78 * 0x07 - 0111 = IRQ7
79 * 0x08 - 1000 = Reserved
80 * 0x09 - 1001 = IRQ9
81 * 0x0A - 1010 = IRQ10
82 * 0x0B - 1011 = IRQ11
83 * 0x0C - 1100 = IRQ12
84 * 0x0D - 1101 = Reserved
85 * 0x0E - 1110 = IRQ14
86 * 0x0F - 1111 = IRQ15
87 * PIRQ[n]_ROUT[7] - PIRQ Routing Control
88 * 0x80 - The PIRQ is not routed.
89 */
90
91static void i82801ix_pirq_init(device_t dev)
92{
93 device_t irq_dev;
94 /* Get the chip configuration */
95 config_t *config = dev->chip_info;
96
97 pci_write_config8(dev, D31F0_PIRQA_ROUT, config->pirqa_routing);
98 pci_write_config8(dev, D31F0_PIRQB_ROUT, config->pirqb_routing);
99 pci_write_config8(dev, D31F0_PIRQC_ROUT, config->pirqc_routing);
100 pci_write_config8(dev, D31F0_PIRQD_ROUT, config->pirqd_routing);
101
102 pci_write_config8(dev, D31F0_PIRQE_ROUT, config->pirqe_routing);
103 pci_write_config8(dev, D31F0_PIRQF_ROUT, config->pirqf_routing);
104 pci_write_config8(dev, D31F0_PIRQG_ROUT, config->pirqg_routing);
105 pci_write_config8(dev, D31F0_PIRQH_ROUT, config->pirqh_routing);
106
107 /* Eric Biederman once said we should let the OS do this.
108 * I am not so sure anymore he was right.
109 */
110
111 for(irq_dev = all_devices; irq_dev; irq_dev = irq_dev->next) {
112 u8 int_pin=0, int_line=0;
113
114 if (!irq_dev->enabled || irq_dev->path.type != DEVICE_PATH_PCI)
115 continue;
116
117 int_pin = pci_read_config8(irq_dev, PCI_INTERRUPT_PIN);
118
119 switch (int_pin) {
120 case 1: /* INTA# */ int_line = config->pirqa_routing; break;
121 case 2: /* INTB# */ int_line = config->pirqb_routing; break;
122 case 3: /* INTC# */ int_line = config->pirqc_routing; break;
123 case 4: /* INTD# */ int_line = config->pirqd_routing; break;
124 }
125
126 if (!int_line)
127 continue;
128
129 pci_write_config8(irq_dev, PCI_INTERRUPT_LINE, int_line);
130 }
131}
132
133static void i82801ix_gpi_routing(device_t dev)
134{
135 /* Get the chip configuration */
136 config_t *config = dev->chip_info;
137 u32 reg32 = 0;
138
139 /* An array would be much nicer here, or some
140 * other method of doing this.
141 */
142 reg32 |= (config->gpi0_routing & 0x03) << 0;
143 reg32 |= (config->gpi1_routing & 0x03) << 2;
144 reg32 |= (config->gpi2_routing & 0x03) << 4;
145 reg32 |= (config->gpi3_routing & 0x03) << 6;
146 reg32 |= (config->gpi4_routing & 0x03) << 8;
147 reg32 |= (config->gpi5_routing & 0x03) << 10;
148 reg32 |= (config->gpi6_routing & 0x03) << 12;
149 reg32 |= (config->gpi7_routing & 0x03) << 14;
150 reg32 |= (config->gpi8_routing & 0x03) << 16;
151 reg32 |= (config->gpi9_routing & 0x03) << 18;
152 reg32 |= (config->gpi10_routing & 0x03) << 20;
153 reg32 |= (config->gpi11_routing & 0x03) << 22;
154 reg32 |= (config->gpi12_routing & 0x03) << 24;
155 reg32 |= (config->gpi13_routing & 0x03) << 26;
156 reg32 |= (config->gpi14_routing & 0x03) << 28;
157 reg32 |= (config->gpi15_routing & 0x03) << 30;
158
159 pci_write_config32(dev, D31F0_GPIO_ROUT, reg32);
160}
161
162static void i82801ix_power_options(device_t dev)
163{
164 u8 reg8;
165 u16 reg16, pmbase;
166 u32 reg32;
167 const char *state;
168 /* Get the chip configuration */
169 config_t *config = dev->chip_info;
170
171 int pwr_on=CONFIG_MAINBOARD_POWER_ON_AFTER_POWER_FAIL;
172 int nmi_option;
173
174 /* BIOS must program... */
175 reg32 = pci_read_config32(dev, 0xac);
176 pci_write_config32(dev, 0xac, reg32 | (1 << 30) | (3 << 8));
177
178 /* Which state do we want to goto after g3 (power restored)?
179 * 0 == S0 Full On
180 * 1 == S5 Soft Off
181 *
182 * If the option is not existent (Laptops), use MAINBOARD_POWER_ON.
183 */
Alexandru Gagniuc72dccce2013-11-23 19:22:53 -0600184 if (get_option(&pwr_on, "power_on_after_fail") != CB_SUCCESS)
Patrick Georgie72a8a32012-11-06 11:05:09 +0100185 pwr_on = MAINBOARD_POWER_ON;
186
187 reg8 = pci_read_config8(dev, D31F0_GEN_PMCON_3);
188 reg8 &= 0xfe;
189 switch (pwr_on) {
190 case MAINBOARD_POWER_OFF:
191 reg8 |= 1;
192 state = "off";
193 break;
194 case MAINBOARD_POWER_ON:
195 reg8 &= ~1;
196 state = "on";
197 break;
198 case MAINBOARD_POWER_KEEP:
199 reg8 &= ~1;
200 state = "state keep";
201 break;
202 default:
203 state = "undefined";
204 }
205
206 reg8 |= (3 << 4); /* avoid #S4 assertions */
207 reg8 &= ~(1 << 3); /* minimum asssertion is 1 to 2 RTCCLK */
208
209 pci_write_config8(dev, D31F0_GEN_PMCON_3, reg8);
210 printk(BIOS_INFO, "Set power %s after power failure.\n", state);
211
212 /* Set up NMI on errors. */
213 reg8 = inb(0x61);
214 reg8 &= 0x0f; /* Higher Nibble must be 0 */
215 reg8 &= ~(1 << 3); /* IOCHK# NMI Enable */
216 // reg8 &= ~(1 << 2); /* PCI SERR# Enable */
217 reg8 |= (1 << 2); /* PCI SERR# Disable for now */
218 outb(reg8, 0x61);
219
220 reg8 = inb(0x74); /* Read from 0x74 as 0x70 is write only. */
221 nmi_option = NMI_OFF;
222 get_option(&nmi_option, "nmi");
223 if (nmi_option) {
224 printk(BIOS_INFO, "NMI sources enabled.\n");
225 reg8 &= ~(1 << 7); /* Set NMI. */
226 } else {
227 printk(BIOS_INFO, "NMI sources disabled.\n");
228 reg8 |= ( 1 << 7); /* Can't mask NMI from PCI-E and NMI_NOW */
229 }
230 outb(reg8, 0x70);
231
232 /* Enable CPU_SLP# and Intel Speedstep, set SMI# rate down */
233 reg16 = pci_read_config16(dev, D31F0_GEN_PMCON_1);
234 reg16 &= ~(3 << 0); // SMI# rate 1 minute
235 reg16 |= (1 << 2); // CLKRUN_EN - Mobile/Ultra only
236 reg16 |= (1 << 3); // Speedstep Enable - Mobile/Ultra only
237 reg16 |= (1 << 5); // CPUSLP_EN Desktop only
238
239 if (config->c4onc3_enable)
240 reg16 |= (1 << 7);
241
242 // another laptop wants this?
243 // reg16 &= ~(1 << 10); // BIOS_PCI_EXP_EN - Desktop/Mobile only
244 reg16 |= (1 << 10); // BIOS_PCI_EXP_EN - Desktop/Mobile only
245#if DEBUG_PERIODIC_SMIS
246 /* Set DEBUG_PERIODIC_SMIS in i82801ix.h to debug using
247 * periodic SMIs.
248 */
249 reg16 |= (3 << 0); // Periodic SMI every 8s
250#endif
251 if (config->c5_enable)
252 reg16 |= (1 << 11); /* Enable C5, C6 and PMSYNC# */
253 pci_write_config16(dev, D31F0_GEN_PMCON_1, reg16);
254
255 /* Set exit timings for C5/C6. */
256 if (config->c5_enable) {
257 reg8 = pci_read_config8(dev, D31F0_C5_EXIT_TIMING);
258 reg8 &= ~((7 << 3) | (7 << 0));
259 if (config->c6_enable)
260 reg8 |= (5 << 3) | (3 << 0); /* 38-44us PMSYNC# to STPCLK#,
261 95-102us DPRSTP# to STP_CPU# */
262 else
263 reg8 |= (0 << 3) | (1 << 0); /* 16-17us PMSYNC# to STPCLK#,
264 34-40us DPRSTP# to STP_CPU# */
265 pci_write_config8(dev, D31F0_C5_EXIT_TIMING, reg8);
266 }
267
268 // Set the board's GPI routing.
269 i82801ix_gpi_routing(dev);
270
271 pmbase = pci_read_config16(dev, 0x40) & 0xfffe;
272
273 outl(config->gpe0_en, pmbase + 0x28);
274 outw(config->alt_gp_smi_en, pmbase + 0x38);
275
276 /* Set up power management block and determine sleep mode */
277 reg16 = inw(pmbase + 0x00); /* PM1_STS */
278 outw(reg16, pmbase + 0x00); /* Clear status bits. At least bit11 (power
279 button override) must be cleared or SCI
280 will be constantly fired and OSPM must
281 not know about it (ACPI spec says to
282 ignore the bit). */
283 reg32 = inl(pmbase + 0x04); // PM1_CNT
284 reg32 &= ~(7 << 10); // SLP_TYP
285 outl(reg32, pmbase + 0x04);
286
287 /* Set duty cycle for hardware throttling (defaults to 0x0: 50%). */
288 reg32 = inl(pmbase + 0x10);
289 reg32 &= ~(7 << 5);
290 reg32 |= (config->throttle_duty & 7) << 5;
291 outl(reg32, pmbase + 0x10);
292}
293
294static void i82801ix_configure_cstates(device_t dev)
295{
296 u8 reg8;
297
298 reg8 = pci_read_config8(dev, D31F0_CxSTATE_CNF);
299 reg8 |= (1 << 4) | (1 << 3) | (1 << 2); // Enable Popup & Popdown
300 pci_write_config8(dev, D31F0_CxSTATE_CNF, reg8);
301
302 // Set Deeper Sleep configuration to recommended values
303 reg8 = pci_read_config8(dev, D31F0_C4TIMING_CNT);
304 reg8 &= 0xf0;
305 reg8 |= (2 << 2); // Deeper Sleep to Stop CPU: 34-40us
306 reg8 |= (2 << 0); // Deeper Sleep to Sleep: 15us
307 pci_write_config8(dev, D31F0_C4TIMING_CNT, reg8);
308
309 /* We could enable slow-C4 exit here, if someone needs it? */
310}
311
312static void i82801ix_rtc_init(struct device *dev)
313{
314 u8 reg8;
315 int rtc_failed;
316
317 reg8 = pci_read_config8(dev, D31F0_GEN_PMCON_3);
318 rtc_failed = reg8 & RTC_BATTERY_DEAD;
319 if (rtc_failed) {
320 reg8 &= ~RTC_BATTERY_DEAD;
321 pci_write_config8(dev, D31F0_GEN_PMCON_3, reg8);
322 }
323 printk(BIOS_DEBUG, "rtc_failed = 0x%x\n", rtc_failed);
324
325 rtc_init(rtc_failed);
326}
327
328static void enable_hpet(void)
329{
330 u32 reg32;
331
332 /* Move HPET to default address 0xfed00000 and enable it */
333 reg32 = RCBA32(RCBA_HPTC);
334 reg32 |= (1 << 7); // HPET Address Enable
335 reg32 &= ~(3 << 0);
336 RCBA32(RCBA_HPTC) = reg32;
337}
338
339static void enable_clock_gating(void)
340{
341 u32 reg32;
342
343 /* Enable DMI dynamic clock gating. */
344 RCBA32(RCBA_DMIC) |= 3;
345
346 /* Enable Clock Gating for most devices. */
347 reg32 = RCBA32(RCBA_CG);
348 reg32 |= (1 << 31); /* LPC dynamic clock gating */
349 /* USB UHCI dynamic clock gating: */
350 reg32 |= (1 << 29) | (1 << 28);
351 /* SATA dynamic clock gating [0-3]: */
352 reg32 |= (1 << 27) | (1 << 26) | (1 << 25) | (1 << 24);
353 reg32 |= (1 << 23); /* LAN static clock gating (if LAN disabled) */
354 reg32 |= (1 << 22); /* HD audio dynamic clock gating */
355 reg32 &= ~(1 << 21); /* No HD audio static clock gating */
356 reg32 &= ~(1 << 20); /* No USB EHCI static clock gating */
357 reg32 |= (1 << 19); /* USB EHCI dynamic clock gating */
358 /* More SATA dynamic clock gating [4-5]: */
359 reg32 |= (1 << 18) | (1 << 17);
360 reg32 |= (1 << 16); /* PCI dynamic clock gating */
361 /* PCIe, DMI dynamic clock gating: */
362 reg32 |= (1 << 4) | (1 << 3) | (1 << 2) | (1 << 1);
363 reg32 |= (1 << 0); /* PCIe root port static clock gating */
364 RCBA32(RCBA_CG) = reg32;
365
366 /* Enable SPI dynamic clock gating. */
367 RCBA32(0x38c0) |= 7;
368}
369
370#if CONFIG_HAVE_SMI_HANDLER
371static void i82801ix_lock_smm(struct device *dev)
372{
373#if TEST_SMM_FLASH_LOCKDOWN
374 u8 reg8;
375#endif
376
377 if (acpi_slp_type != 3) {
378#if ENABLE_ACPI_MODE_IN_COREBOOT
379 printk(BIOS_DEBUG, "Enabling ACPI via APMC:\n");
380 outb(APM_CNT_ACPI_ENABLE, APM_CNT); // Enable ACPI mode
381 printk(BIOS_DEBUG, "done.\n");
382#else
383 printk(BIOS_DEBUG, "Disabling ACPI via APMC:\n");
384 outb(APM_CNT_ACPI_DISABLE, APM_CNT); // Disable ACPI mode
385 printk(BIOS_DEBUG, "done.\n");
386#endif
387 } else {
388 printk(BIOS_DEBUG, "S3 wakeup, enabling ACPI via APMC\n");
389 outb(APM_CNT_ACPI_ENABLE, APM_CNT);
390 }
391 /* Don't allow evil boot loaders, kernels, or
392 * userspace applications to deceive us:
393 */
394 smm_lock();
395
396#if TEST_SMM_FLASH_LOCKDOWN
397 /* Now try this: */
398 printk(BIOS_DEBUG, "Locking BIOS to RO... ");
399 reg8 = pci_read_config8(dev, 0xdc); /* BIOS_CNTL */
400 printk(BIOS_DEBUG, " BLE: %s; BWE: %s\n", (reg8&2)?"on":"off",
401 (reg8&1)?"rw":"ro");
402 reg8 &= ~(1 << 0); /* clear BIOSWE */
403 pci_write_config8(dev, 0xdc, reg8);
404 reg8 |= (1 << 1); /* set BLE */
405 pci_write_config8(dev, 0xdc, reg8);
406 printk(BIOS_DEBUG, "ok.\n");
407 reg8 = pci_read_config8(dev, 0xdc); /* BIOS_CNTL */
408 printk(BIOS_DEBUG, " BLE: %s; BWE: %s\n", (reg8&2)?"on":"off",
409 (reg8&1)?"rw":"ro");
410
411 printk(BIOS_DEBUG, "Writing:\n");
412 *(volatile u8 *)0xfff00000 = 0x00;
413 printk(BIOS_DEBUG, "Testing:\n");
414 reg8 |= (1 << 0); /* set BIOSWE */
415 pci_write_config8(dev, 0xdc, reg8);
416
417 reg8 = pci_read_config8(dev, 0xdc); /* BIOS_CNTL */
418 printk(BIOS_DEBUG, " BLE: %s; BWE: %s\n", (reg8&2)?"on":"off",
419 (reg8&1)?"rw":"ro");
420 printk(BIOS_DEBUG, "Done.\n");
421#endif
422}
423#endif
424
425static void lpc_init(struct device *dev)
426{
427 printk(BIOS_DEBUG, "i82801ix: lpc_init\n");
428
429 /* Set the value for PCI command register. */
430 pci_write_config16(dev, PCI_COMMAND, 0x000f);
431
432 /* IO APIC initialization. */
433 i82801ix_enable_apic(dev);
434
435 i82801ix_enable_serial_irqs(dev);
436
437 /* Setup the PIRQ. */
438 i82801ix_pirq_init(dev);
439
440 /* Setup power options. */
441 i82801ix_power_options(dev);
442
443 /* Configure Cx state registers */
444 if (LPC_IS_MOBILE(dev))
445 i82801ix_configure_cstates(dev);
446
447 /* Initialize the real time clock. */
448 i82801ix_rtc_init(dev);
449
450 /* Initialize ISA DMA. */
451 isa_dma_init();
452
453 /* Initialize the High Precision Event Timers, if present. */
454 enable_hpet();
455
456 /* Initialize Clock Gating */
457 enable_clock_gating();
458
459 setup_i8259();
460
461 /* The OS should do this? */
462 /* Interrupt 9 should be level triggered (SCI) */
463 i8259_configure_irq_trigger(9, 1);
464
465#if CONFIG_HAVE_SMI_HANDLER
466 i82801ix_lock_smm(dev);
467#endif
468}
469
470static void i82801ix_lpc_read_resources(device_t dev)
471{
472 /*
473 * I/O Resources
474 *
475 * 0x0000 - 0x000f....ISA DMA
476 * 0x0010 - 0x001f....ISA DMA aliases
477 * 0x0020 ~ 0x003d....PIC
478 * 0x002e - 0x002f....Maybe Super I/O
479 * 0x0040 - 0x0043....Timer
480 * 0x004e - 0x004f....Maybe Super I/O
481 * 0x0050 - 0x0053....Timer aliases
482 * 0x0061.............NMI_SC
483 * 0x0070.............NMI_EN (readable in alternative access mode)
484 * 0x0070 - 0x0077....RTC
485 * 0x0080 - 0x008f....ISA DMA
486 * 0x0090 ~ 0x009f....ISA DMA aliases
487 * 0x0092.............Fast A20 and Init
488 * 0x00a0 ~ 0x00bd....PIC
489 * 0x00b2 - 0x00b3....APM
490 * 0x00c0 ~ 0x00de....ISA DMA
491 * 0x00c1 ~ 0x00df....ISA DMA aliases
492 * 0x00f0.............Coprocessor Error
493 * (0x0400-0x041f)....SMBus (SMBUS_IO_BASE, during raminit)
494 * 0x04d0 - 0x04d1....PIC
495 * 0x0500 - 0x057f....PM (DEFAULT_PMBASE)
496 * 0x0580 - 0x05bf....SB GPIO (DEFAULT_GPIOBASE)
497 * 0x05c0 - 0x05ff....SB GPIO cont. (mobile only)
498 * 0x0cf8 - 0x0cff....PCI
499 * 0x0cf9.............Reset Control
500 */
501
502 struct resource *res;
503
504 /* Get the normal PCI resources of this device. */
505 pci_dev_read_resources(dev);
506
507 /* Add an extra subtractive resource for both memory and I/O. */
508 res = new_resource(dev, IOINDEX_SUBTRACTIVE(0, 0));
509 res->base = 0;
510 res->size = 0x1000;
511 res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
512 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
513
514 res = new_resource(dev, IOINDEX_SUBTRACTIVE(1, 0));
515 res->base = 0xff800000;
516 res->size = 0x00800000; /* 8 MB for flash */
517 res->flags = IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE |
518 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
519
520 res = new_resource(dev, 3); /* IOAPIC */
521 res->base = IO_APIC_ADDR;
522 res->size = 0x00001000;
523 res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
524}
525
526static void set_subsystem(device_t dev, unsigned vendor, unsigned device)
527{
528 if (!vendor || !device) {
529 pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
530 pci_read_config32(dev, PCI_VENDOR_ID));
531 } else {
532 pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
533 ((device & 0xffff) << 16) | (vendor & 0xffff));
534 }
535}
536
537static struct pci_operations pci_ops = {
538 .set_subsystem = set_subsystem,
539};
540
541static struct device_operations device_ops = {
542 .read_resources = i82801ix_lpc_read_resources,
543 .set_resources = pci_dev_set_resources,
544 .enable_resources = pci_dev_enable_resources,
545 .init = lpc_init,
546 .scan_bus = scan_static_bus,
547 .ops_pci = &pci_ops,
548};
549
550static const unsigned short pci_device_ids[] = {
551 0x2912, /* ICH9DH */
552 0x2914, /* ICH9DO */
553 0x2916, /* ICH9R */
554 0x2918, /* ICH9 */
555 0x2917, /* ICH9M-E */
556 0x2919, /* ICH9M */
557 0
558};
559
560static const struct pci_driver ich9_lpc __pci_driver = {
561 .ops = &device_ops,
562 .vendor = PCI_VENDOR_ID_INTEL,
563 .devices = pci_device_ids,
564};
565