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