blob: c57eeca769f4caa4879176458ac41fa07b0fdc5c [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>
Arthur Heymansd2d2aef2018-01-16 14:19:37 +010035#include <southbridge/intel/common/rcba.h>
Stefan Reinauer8e073822012-04-04 00:07:22 +020036#include "pch.h"
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +020037#include "nvs.h"
Vladimir Serbinenko36fa5b82014-10-28 23:43:20 +010038#include <southbridge/intel/common/pciehp.h>
Tobias Diedrich7f5efd92017-12-14 00:29:01 +010039#include <southbridge/intel/common/acpi_pirq_gen.h>
Arthur Heymansa0508172018-01-25 11:30:22 +010040#include <southbridge/intel/common/pmutil.h>
Stefan Reinauer8e073822012-04-04 00:07:22 +020041
42#define NMI_OFF 0
43
44#define ENABLE_ACPI_MODE_IN_COREBOOT 0
Stefan Reinauer8e073822012-04-04 00:07:22 +020045
46typedef struct southbridge_intel_bd82x6x_config config_t;
47
Paul Menzel9c50e6a2013-05-03 12:23:39 +020048/**
49 * Set miscellanous static southbridge features.
50 *
51 * @param dev PCI device with I/O APIC control registers
52 */
53static void pch_enable_ioapic(struct device *dev)
Stefan Reinauer8e073822012-04-04 00:07:22 +020054{
Stefan Reinauer8e073822012-04-04 00:07:22 +020055 u32 reg32;
Stefan Reinauer8e073822012-04-04 00:07:22 +020056
Nico Huberb2dae792015-10-26 12:34:02 +010057 /* Assign unique bus/dev/fn for I/O APIC */
58 pci_write_config16(dev, LPC_IBDF,
59 PCH_IOAPIC_PCI_BUS << 8 | PCH_IOAPIC_PCI_SLOT << 3);
60
Paul Menzel9c50e6a2013-05-03 12:23:39 +020061 /* Enable ACPI I/O range decode */
62 pci_write_config8(dev, ACPI_CNTL, ACPI_EN);
Stefan Reinauer8e073822012-04-04 00:07:22 +020063
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -080064 set_ioapic_id(VIO_APIC_VADDR, 0x02);
Stefan Reinauer8e073822012-04-04 00:07:22 +020065
66 /* affirm full set of redirection table entries ("write once") */
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -080067 reg32 = io_apic_read(VIO_APIC_VADDR, 0x01);
68 io_apic_write(VIO_APIC_VADDR, 0x01, reg32);
Stefan Reinauer8e073822012-04-04 00:07:22 +020069
Paul Menzel9c50e6a2013-05-03 12:23:39 +020070 /*
71 * Select Boot Configuration register (0x03) and
72 * use Processor System Bus (0x01) to deliver interrupts.
73 */
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -080074 io_apic_write(VIO_APIC_VADDR, 0x03, 0x01);
Stefan Reinauer8e073822012-04-04 00:07:22 +020075}
76
77static void pch_enable_serial_irqs(struct device *dev)
78{
79 /* Set packet length and toggle silent mode bit for one frame. */
80 pci_write_config8(dev, SERIRQ_CNTL,
81 (1 << 7) | (1 << 6) | ((21 - 17) << 2) | (0 << 0));
Martin Roth7a1a3ad2017-06-24 21:29:38 -060082#if !IS_ENABLED(CONFIG_SERIRQ_CONTINUOUS_MODE)
Stefan Reinauer8e073822012-04-04 00:07:22 +020083 pci_write_config8(dev, SERIRQ_CNTL,
84 (1 << 7) | (0 << 6) | ((21 - 17) << 2) | (0 << 0));
85#endif
86}
87
88/* PIRQ[n]_ROUT[3:0] - PIRQ Routing Control
89 * 0x00 - 0000 = Reserved
90 * 0x01 - 0001 = Reserved
91 * 0x02 - 0010 = Reserved
92 * 0x03 - 0011 = IRQ3
93 * 0x04 - 0100 = IRQ4
94 * 0x05 - 0101 = IRQ5
95 * 0x06 - 0110 = IRQ6
96 * 0x07 - 0111 = IRQ7
97 * 0x08 - 1000 = Reserved
98 * 0x09 - 1001 = IRQ9
99 * 0x0A - 1010 = IRQ10
100 * 0x0B - 1011 = IRQ11
101 * 0x0C - 1100 = IRQ12
102 * 0x0D - 1101 = Reserved
103 * 0x0E - 1110 = IRQ14
104 * 0x0F - 1111 = IRQ15
105 * PIRQ[n]_ROUT[7] - PIRQ Routing Control
106 * 0x80 - The PIRQ is not routed.
107 */
108
109static void pch_pirq_init(device_t dev)
110{
111 device_t irq_dev;
Vladimir Serbinenko33b535f2014-10-19 10:13:14 +0200112 /* Interrupt 11 is not used by legacy devices and so can always be used for
113 PCI interrupts. Full legacy IRQ routing is complicated and hard to
114 get right. Fortunately all modern OS use MSI and so it's not that big of
115 an issue anyway. Still we have to provide a reasonable default. Using
116 interrupt 11 for it everywhere is a working default. ACPI-aware OS can
117 move it to any interrupt and others will just leave them at default.
Stefan Reinauer8e073822012-04-04 00:07:22 +0200118 */
Vladimir Serbinenko33b535f2014-10-19 10:13:14 +0200119 const u8 pirq_routing = 11;
120
121 pci_write_config8(dev, PIRQA_ROUT, pirq_routing);
122 pci_write_config8(dev, PIRQB_ROUT, pirq_routing);
123 pci_write_config8(dev, PIRQC_ROUT, pirq_routing);
124 pci_write_config8(dev, PIRQD_ROUT, pirq_routing);
125
126 pci_write_config8(dev, PIRQE_ROUT, pirq_routing);
127 pci_write_config8(dev, PIRQF_ROUT, pirq_routing);
128 pci_write_config8(dev, PIRQG_ROUT, pirq_routing);
129 pci_write_config8(dev, PIRQH_ROUT, pirq_routing);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200130
Elyes HAOUASba28e8d2016-08-31 19:22:16 +0200131 for (irq_dev = all_devices; irq_dev; irq_dev = irq_dev->next) {
Vladimir Serbinenko33b535f2014-10-19 10:13:14 +0200132 u8 int_pin=0;
Stefan Reinauer8e073822012-04-04 00:07:22 +0200133
134 if (!irq_dev->enabled || irq_dev->path.type != DEVICE_PATH_PCI)
135 continue;
136
137 int_pin = pci_read_config8(irq_dev, PCI_INTERRUPT_PIN);
138
Vladimir Serbinenko33b535f2014-10-19 10:13:14 +0200139 if (int_pin == 0)
Stefan Reinauer8e073822012-04-04 00:07:22 +0200140 continue;
141
Vladimir Serbinenko33b535f2014-10-19 10:13:14 +0200142 pci_write_config8(irq_dev, PCI_INTERRUPT_LINE, pirq_routing);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200143 }
144}
145
146static void pch_gpi_routing(device_t dev)
147{
148 /* Get the chip configuration */
149 config_t *config = dev->chip_info;
150 u32 reg32 = 0;
151
152 /* An array would be much nicer here, or some
153 * other method of doing this.
154 */
155 reg32 |= (config->gpi0_routing & 0x03) << 0;
156 reg32 |= (config->gpi1_routing & 0x03) << 2;
157 reg32 |= (config->gpi2_routing & 0x03) << 4;
158 reg32 |= (config->gpi3_routing & 0x03) << 6;
159 reg32 |= (config->gpi4_routing & 0x03) << 8;
160 reg32 |= (config->gpi5_routing & 0x03) << 10;
161 reg32 |= (config->gpi6_routing & 0x03) << 12;
162 reg32 |= (config->gpi7_routing & 0x03) << 14;
163 reg32 |= (config->gpi8_routing & 0x03) << 16;
164 reg32 |= (config->gpi9_routing & 0x03) << 18;
165 reg32 |= (config->gpi10_routing & 0x03) << 20;
166 reg32 |= (config->gpi11_routing & 0x03) << 22;
167 reg32 |= (config->gpi12_routing & 0x03) << 24;
168 reg32 |= (config->gpi13_routing & 0x03) << 26;
169 reg32 |= (config->gpi14_routing & 0x03) << 28;
170 reg32 |= (config->gpi15_routing & 0x03) << 30;
171
Kyösti Mälkkib85a87b2014-12-29 11:32:27 +0200172 pci_write_config32(dev, GPIO_ROUT, reg32);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200173}
174
175static void pch_power_options(device_t dev)
176{
177 u8 reg8;
178 u16 reg16, pmbase;
179 u32 reg32;
180 const char *state;
181 /* Get the chip configuration */
182 config_t *config = dev->chip_info;
183
184 int pwr_on=CONFIG_MAINBOARD_POWER_ON_AFTER_POWER_FAIL;
185 int nmi_option;
186
187 /* Which state do we want to goto after g3 (power restored)?
188 * 0 == S0 Full On
189 * 1 == S5 Soft Off
190 *
191 * If the option is not existent (Laptops), use Kconfig setting.
192 */
193 get_option(&pwr_on, "power_on_after_fail");
194
195 reg16 = pci_read_config16(dev, GEN_PMCON_3);
196 reg16 &= 0xfffe;
197 switch (pwr_on) {
198 case MAINBOARD_POWER_OFF:
199 reg16 |= 1;
200 state = "off";
201 break;
202 case MAINBOARD_POWER_ON:
203 reg16 &= ~1;
204 state = "on";
205 break;
206 case MAINBOARD_POWER_KEEP:
207 reg16 &= ~1;
208 state = "state keep";
209 break;
210 default:
211 state = "undefined";
212 }
213
214 reg16 &= ~(3 << 4); /* SLP_S4# Assertion Stretch 4s */
215 reg16 |= (1 << 3); /* SLP_S4# Assertion Stretch Enable */
216
217 reg16 &= ~(1 << 10);
218 reg16 |= (1 << 11); /* SLP_S3# Min Assertion Width 50ms */
219
220 reg16 |= (1 << 12); /* Disable SLP stretch after SUS well */
221
222 pci_write_config16(dev, GEN_PMCON_3, reg16);
223 printk(BIOS_INFO, "Set power %s after power failure.\n", state);
224
225 /* Set up NMI on errors. */
226 reg8 = inb(0x61);
227 reg8 &= 0x0f; /* Higher Nibble must be 0 */
228 reg8 &= ~(1 << 3); /* IOCHK# NMI Enable */
229 // reg8 &= ~(1 << 2); /* PCI SERR# Enable */
230 reg8 |= (1 << 2); /* PCI SERR# Disable for now */
231 outb(reg8, 0x61);
232
233 reg8 = inb(0x70);
234 nmi_option = NMI_OFF;
235 get_option(&nmi_option, "nmi");
236 if (nmi_option) {
237 printk(BIOS_INFO, "NMI sources enabled.\n");
238 reg8 &= ~(1 << 7); /* Set NMI. */
239 } else {
240 printk(BIOS_INFO, "NMI sources disabled.\n");
241 reg8 |= ( 1 << 7); /* Can't mask NMI from PCI-E and NMI_NOW */
242 }
243 outb(reg8, 0x70);
244
245 /* Enable CPU_SLP# and Intel Speedstep, set SMI# rate down */
246 reg16 = pci_read_config16(dev, GEN_PMCON_1);
247 reg16 &= ~(3 << 0); // SMI# rate 1 minute
248 reg16 &= ~(1 << 10); // Disable BIOS_PCI_EXP_EN for native PME
249#if DEBUG_PERIODIC_SMIS
250 /* Set DEBUG_PERIODIC_SMIS in pch.h to debug using
251 * periodic SMIs.
252 */
253 reg16 |= (3 << 0); // Periodic SMI every 8s
254#endif
255 pci_write_config16(dev, GEN_PMCON_1, reg16);
256
257 // Set the board's GPI routing.
258 pch_gpi_routing(dev);
259
260 pmbase = pci_read_config16(dev, 0x40) & 0xfffe;
261
262 outl(config->gpe0_en, pmbase + GPE0_EN);
263 outw(config->alt_gp_smi_en, pmbase + ALT_GP_SMI_EN);
264
265 /* Set up power management block and determine sleep mode */
266 reg32 = inl(pmbase + 0x04); // PM1_CNT
267 reg32 &= ~(7 << 10); // SLP_TYP
268 reg32 |= (1 << 0); // SCI_EN
269 outl(reg32, pmbase + 0x04);
270
271 /* Clear magic status bits to prevent unexpected wake */
272 reg32 = RCBA32(0x3310);
273 reg32 |= (1 << 4)|(1 << 5)|(1 << 0);
274 RCBA32(0x3310) = reg32;
275
276 reg32 = RCBA32(0x3f02);
277 reg32 &= ~0xf;
278 RCBA32(0x3f02) = reg32;
279}
280
281static void pch_rtc_init(struct device *dev)
282{
Aaron Durbin976200382017-09-15 15:19:32 -0600283 int rtc_failed = rtc_failure();
Stefan Reinauer8e073822012-04-04 00:07:22 +0200284
Stefan Reinauer8e073822012-04-04 00:07:22 +0200285 if (rtc_failed) {
Aaron Durbin976200382017-09-15 15:19:32 -0600286 if (IS_ENABLED(CONFIG_ELOG))
287 elog_add_event(ELOG_TYPE_RTC_RESET);
288 pci_update_config8(dev, GEN_PMCON_3, ~RTC_BATTERY_DEAD, 0);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200289 }
Aaron Durbin976200382017-09-15 15:19:32 -0600290
Stefan Reinauer8e073822012-04-04 00:07:22 +0200291 printk(BIOS_DEBUG, "rtc_failed = 0x%x\n", rtc_failed);
292
Gabe Blackb3f08c62014-04-30 17:12:25 -0700293 cmos_init(rtc_failed);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200294}
295
Duncan Laurie3f6a4d72012-06-28 13:03:40 -0700296/* CougarPoint PCH Power Management init */
297static void cpt_pm_init(struct device *dev)
Stefan Reinauer8e073822012-04-04 00:07:22 +0200298{
Duncan Laurie3f6a4d72012-06-28 13:03:40 -0700299 printk(BIOS_DEBUG, "CougarPoint PM init\n");
Stefan Reinauer8e073822012-04-04 00:07:22 +0200300 pci_write_config8(dev, 0xa9, 0x47);
301 RCBA32_AND_OR(0x2238, ~0UL, (1 << 6)|(1 << 0));
302 RCBA32_AND_OR(0x228c, ~0UL, (1 << 0));
303 RCBA16_AND_OR(0x1100, ~0UL, (1 << 13)|(1 << 14));
304 RCBA16_AND_OR(0x0900, ~0UL, (1 << 14));
305 RCBA32(0x2304) = 0xc0388400;
306 RCBA32_AND_OR(0x2314, ~0UL, (1 << 5)|(1 << 18));
307 RCBA32_AND_OR(0x2320, ~0UL, (1 << 15)|(1 << 1));
308 RCBA32_AND_OR(0x3314, ~0x1f, 0xf);
309 RCBA32(0x3318) = 0x050f0000;
310 RCBA32(0x3324) = 0x04000000;
311 RCBA32_AND_OR(0x3340, ~0UL, 0xfffff);
312 RCBA32_AND_OR(0x3344, ~0UL, (1 << 1));
313 RCBA32(0x3360) = 0x0001c000;
314 RCBA32(0x3368) = 0x00061100;
315 RCBA32(0x3378) = 0x7f8fdfff;
316 RCBA32(0x337c) = 0x000003fc;
317 RCBA32(0x3388) = 0x00001000;
318 RCBA32(0x3390) = 0x0001c000;
319 RCBA32(0x33a0) = 0x00000800;
320 RCBA32(0x33b0) = 0x00001000;
321 RCBA32(0x33c0) = 0x00093900;
322 RCBA32(0x33cc) = 0x24653002;
323 RCBA32(0x33d0) = 0x062108fe;
324 RCBA32_AND_OR(0x33d4, 0xf000f000, 0x00670060);
325 RCBA32(0x3a28) = 0x01010000;
326 RCBA32(0x3a2c) = 0x01010404;
327 RCBA32(0x3a80) = 0x01041041;
328 RCBA32_AND_OR(0x3a84, ~0x0000ffff, 0x00001001);
329 RCBA32_AND_OR(0x3a84, ~0UL, (1 << 24)); /* SATA 2/3 disabled */
330 RCBA32_AND_OR(0x3a88, ~0UL, (1 << 0)); /* SATA 4/5 disabled */
331 RCBA32(0x3a6c) = 0x00000001;
332 RCBA32_AND_OR(0x2344, 0x00ffff00, 0xff00000c);
333 RCBA32_AND_OR(0x80c, ~(0xff << 20), 0x11 << 20);
334 RCBA32(0x33c8) = 0;
335 RCBA32_AND_OR(0x21b0, ~0UL, 0xf);
336}
337
Duncan Laurie3f6a4d72012-06-28 13:03:40 -0700338/* PantherPoint PCH Power Management init */
339static void ppt_pm_init(struct device *dev)
340{
341 printk(BIOS_DEBUG, "PantherPoint PM init\n");
342 pci_write_config8(dev, 0xa9, 0x47);
343 RCBA32_AND_OR(0x2238, ~0UL, (1 << 0));
344 RCBA32_AND_OR(0x228c, ~0UL, (1 << 0));
345 RCBA16_AND_OR(0x1100, ~0UL, (1 << 13)|(1 << 14));
346 RCBA16_AND_OR(0x0900, ~0UL, (1 << 14));
347 RCBA32(0x2304) = 0xc03b8400;
348 RCBA32_AND_OR(0x2314, ~0UL, (1 << 5)|(1 << 18));
349 RCBA32_AND_OR(0x2320, ~0UL, (1 << 15)|(1 << 1));
350 RCBA32_AND_OR(0x3314, ~0x1f, 0xf);
351 RCBA32(0x3318) = 0x054f0000;
352 RCBA32(0x3324) = 0x04000000;
353 RCBA32_AND_OR(0x3340, ~0UL, 0xfffff);
354 RCBA32_AND_OR(0x3344, ~0UL, (1 << 1)|(1 << 0));
355 RCBA32(0x3360) = 0x0001c000;
356 RCBA32(0x3368) = 0x00061100;
357 RCBA32(0x3378) = 0x7f8fdfff;
358 RCBA32(0x337c) = 0x000003fd;
359 RCBA32(0x3388) = 0x00001000;
360 RCBA32(0x3390) = 0x0001c000;
361 RCBA32(0x33a0) = 0x00000800;
362 RCBA32(0x33b0) = 0x00001000;
363 RCBA32(0x33c0) = 0x00093900;
364 RCBA32(0x33cc) = 0x24653002;
365 RCBA32(0x33d0) = 0x067388fe;
366 RCBA32_AND_OR(0x33d4, 0xf000f000, 0x00670060);
367 RCBA32(0x3a28) = 0x01010000;
368 RCBA32(0x3a2c) = 0x01010404;
369 RCBA32(0x3a80) = 0x01040000;
370 RCBA32_AND_OR(0x3a84, ~0x0000ffff, 0x00001001);
371 RCBA32_AND_OR(0x3a84, ~0UL, (1 << 24)); /* SATA 2/3 disabled */
372 RCBA32_AND_OR(0x3a88, ~0UL, (1 << 0)); /* SATA 4/5 disabled */
373 RCBA32(0x3a6c) = 0x00000001;
374 RCBA32_AND_OR(0x2344, 0x00ffff00, 0xff00000c);
375 RCBA32_AND_OR(0x80c, ~(0xff << 20), 0x11 << 20);
376 RCBA32_AND_OR(0x33a4, ~0UL, (1 << 0));
377 RCBA32(0x33c8) = 0;
378 RCBA32_AND_OR(0x21b0, ~0UL, 0xf);
379}
380
Nico Huberb2dae792015-10-26 12:34:02 +0100381static void enable_hpet(struct device *const dev)
Stefan Reinauer8e073822012-04-04 00:07:22 +0200382{
383 u32 reg32;
Nico Huberb2dae792015-10-26 12:34:02 +0100384 size_t i;
385
386 /* Assign unique bus/dev/fn for each HPET */
387 for (i = 0; i < 8; ++i)
388 pci_write_config16(dev, LPC_HnBDF(i),
389 PCH_HPET_PCI_BUS << 8 | PCH_HPET_PCI_SLOT << 3 | i);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200390
391 /* Move HPET to default address 0xfed00000 and enable it */
392 reg32 = RCBA32(HPTC);
393 reg32 |= (1 << 7); // HPET Address Enable
394 reg32 &= ~(3 << 0);
395 RCBA32(HPTC) = reg32;
396}
397
398static void enable_clock_gating(device_t dev)
399{
400 u32 reg32;
401 u16 reg16;
402
403 RCBA32_AND_OR(0x2234, ~0UL, 0xf);
404
405 reg16 = pci_read_config16(dev, GEN_PMCON_1);
406 reg16 |= (1 << 2) | (1 << 11);
407 pci_write_config16(dev, GEN_PMCON_1, reg16);
408
409 pch_iobp_update(0xEB007F07, ~0UL, (1 << 31));
410 pch_iobp_update(0xEB004000, ~0UL, (1 << 7));
411 pch_iobp_update(0xEC007F07, ~0UL, (1 << 31));
412 pch_iobp_update(0xEC004000, ~0UL, (1 << 7));
413
414 reg32 = RCBA32(CG);
415 reg32 |= (1 << 31);
416 reg32 |= (1 << 29) | (1 << 28);
417 reg32 |= (1 << 27) | (1 << 26) | (1 << 25) | (1 << 24);
418 reg32 |= (1 << 16);
419 reg32 |= (1 << 17);
420 reg32 |= (1 << 18);
421 reg32 |= (1 << 22);
422 reg32 |= (1 << 23);
423 reg32 &= ~(1 << 20);
424 reg32 |= (1 << 19);
425 reg32 |= (1 << 0);
426 reg32 |= (0xf << 1);
427 RCBA32(CG) = reg32;
428
429 RCBA32_OR(0x38c0, 0x7);
430 RCBA32_OR(0x36d4, 0x6680c004);
431 RCBA32_OR(0x3564, 0x3);
432}
433
Vladimir Serbinenkoa3e41c02015-05-28 16:04:17 +0200434static void pch_set_acpi_mode(void)
Stefan Reinauer8e073822012-04-04 00:07:22 +0200435{
Vladimir Serbinenkoa3e41c02015-05-28 16:04:17 +0200436 if (!acpi_is_wakeup_s3() && CONFIG_HAVE_SMI_HANDLER) {
Stefan Reinauer8e073822012-04-04 00:07:22 +0200437#if ENABLE_ACPI_MODE_IN_COREBOOT
Duncan Laurie95be1d62012-04-09 12:31:43 -0700438 printk(BIOS_DEBUG, "Enabling ACPI via APMC:\n");
Vladimir Serbinenkoa3e41c02015-05-28 16:04:17 +0200439 outb(APM_CNT_ACPI_ENABLE, APM_CNT); // Enable ACPI mode
Duncan Laurie95be1d62012-04-09 12:31:43 -0700440 printk(BIOS_DEBUG, "done.\n");
Stefan Reinauer8e073822012-04-04 00:07:22 +0200441#else
Duncan Laurie95be1d62012-04-09 12:31:43 -0700442 printk(BIOS_DEBUG, "Disabling ACPI via APMC:\n");
Vladimir Serbinenkoa3e41c02015-05-28 16:04:17 +0200443 outb(APM_CNT_ACPI_DISABLE, APM_CNT); // Disable ACPI mode
Duncan Laurie95be1d62012-04-09 12:31:43 -0700444 printk(BIOS_DEBUG, "done.\n");
Stefan Reinauer8e073822012-04-04 00:07:22 +0200445#endif
Duncan Laurie95be1d62012-04-09 12:31:43 -0700446 }
Stefan Reinauer8e073822012-04-04 00:07:22 +0200447}
Stefan Reinauer8e073822012-04-04 00:07:22 +0200448
449static void pch_disable_smm_only_flashing(struct device *dev)
450{
451 u8 reg8;
452
453 printk(BIOS_SPEW, "Enabling BIOS updates outside of SMM... ");
454 reg8 = pci_read_config8(dev, 0xdc); /* BIOS_CNTL */
455 reg8 &= ~(1 << 5);
456 pci_write_config8(dev, 0xdc, reg8);
457}
458
459static void pch_fixups(struct device *dev)
460{
461 u8 gen_pmcon_2;
462
463 /* Indicate DRAM init done for MRC S3 to know it can resume */
464 gen_pmcon_2 = pci_read_config8(dev, GEN_PMCON_2);
465 gen_pmcon_2 |= (1 << 7);
466 pci_write_config8(dev, GEN_PMCON_2, gen_pmcon_2);
467
468 /*
469 * Enable DMI ASPM in the PCH
470 */
471 RCBA32_AND_OR(0x2304, ~(1 << 10), 0);
472 RCBA32_OR(0x21a4, (1 << 11)|(1 << 10));
473 RCBA32_OR(0x21a8, 0x3);
474}
475
476static void pch_decode_init(struct device *dev)
477{
478 config_t *config = dev->chip_info;
479
480 printk(BIOS_DEBUG, "pch_decode_init\n");
481
482 pci_write_config32(dev, LPC_GEN1_DEC, config->gen1_dec);
483 pci_write_config32(dev, LPC_GEN2_DEC, config->gen2_dec);
484 pci_write_config32(dev, LPC_GEN3_DEC, config->gen3_dec);
485 pci_write_config32(dev, LPC_GEN4_DEC, config->gen4_dec);
486}
487
Nico Huber7b2f9f62015-10-01 19:00:51 +0200488static void pch_spi_init(const struct device *const dev)
489{
490 const config_t *const config = dev->chip_info;
491
492 printk(BIOS_DEBUG, "pch_spi_init\n");
493
494 if (config->spi_uvscc)
495 RCBA32(0x3800 + 0xc8) = config->spi_uvscc;
496 if (config->spi_lvscc)
497 RCBA32(0x3800 + 0xc4) = config->spi_lvscc;
498
499 if (config->spi_uvscc || config->spi_lvscc)
500 RCBA32_OR(0x3800 + 0xc4, 1 << 23); /* lock both UVSCC + LVSCC */
501}
502
Stefan Reinauer8e073822012-04-04 00:07:22 +0200503static void lpc_init(struct device *dev)
504{
505 printk(BIOS_DEBUG, "pch: lpc_init\n");
506
507 /* Set the value for PCI command register. */
508 pci_write_config16(dev, PCI_COMMAND, 0x000f);
509
510 /* IO APIC initialization. */
Paul Menzel9c50e6a2013-05-03 12:23:39 +0200511 pch_enable_ioapic(dev);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200512
513 pch_enable_serial_irqs(dev);
514
515 /* Setup the PIRQ. */
516 pch_pirq_init(dev);
517
518 /* Setup power options. */
519 pch_power_options(dev);
520
521 /* Initialize power management */
Duncan Laurie3f6a4d72012-06-28 13:03:40 -0700522 switch (pch_silicon_type()) {
523 case PCH_TYPE_CPT: /* CougarPoint */
524 cpt_pm_init(dev);
525 break;
526 case PCH_TYPE_PPT: /* PantherPoint */
527 ppt_pm_init(dev);
528 break;
529 default:
530 printk(BIOS_ERR, "Unknown Chipset: 0x%04x\n", dev->device);
531 }
Stefan Reinauer8e073822012-04-04 00:07:22 +0200532
533 /* Set the state of the GPIO lines. */
534 //gpio_init(dev);
535
536 /* Initialize the real time clock. */
537 pch_rtc_init(dev);
538
539 /* Initialize ISA DMA. */
540 isa_dma_init();
541
542 /* Initialize the High Precision Event Timers, if present. */
Nico Huberb2dae792015-10-26 12:34:02 +0100543 enable_hpet(dev);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200544
545 /* Initialize Clock Gating */
546 enable_clock_gating(dev);
547
548 setup_i8259();
549
550 /* The OS should do this? */
551 /* Interrupt 9 should be level triggered (SCI) */
552 i8259_configure_irq_trigger(9, 1);
553
554 pch_disable_smm_only_flashing(dev);
555
Vladimir Serbinenkoa3e41c02015-05-28 16:04:17 +0200556 pch_set_acpi_mode();
Stefan Reinauer8e073822012-04-04 00:07:22 +0200557
558 pch_fixups(dev);
Nico Huber7b2f9f62015-10-01 19:00:51 +0200559
560 pch_spi_init(dev);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200561}
562
563static void pch_lpc_read_resources(device_t dev)
564{
565 struct resource *res;
Marc Jonesa0bec172012-07-13 14:14:34 -0600566 config_t *config = dev->chip_info;
567 u8 io_index = 0;
Stefan Reinauer8e073822012-04-04 00:07:22 +0200568
569 /* Get the normal PCI resources of this device. */
570 pci_dev_read_resources(dev);
571
572 /* Add an extra subtractive resource for both memory and I/O. */
Marc Jonesa0bec172012-07-13 14:14:34 -0600573 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
Stefan Reinauer8e073822012-04-04 00:07:22 +0200574 res->base = 0;
575 res->size = 0x1000;
576 res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
577 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
578
Marc Jonesa0bec172012-07-13 14:14:34 -0600579 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
Vladimir Serbinenko0650cd02014-02-05 15:03:50 +0100580 res->base = 0xff000000;
581 /* Some systems (e.g. X230) have 12 MiB flash.
582 SPI controller supports up to 2 x 16 MiB of flash but
583 address map limits this to 16MiB. */
584 res->size = 0x01000000; /* 16 MB for flash */
Stefan Reinauer8e073822012-04-04 00:07:22 +0200585 res->flags = IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE |
586 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
587
588 res = new_resource(dev, 3); /* IOAPIC */
589 res->base = IO_APIC_ADDR;
590 res->size = 0x00001000;
591 res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
Marc Jonesa0bec172012-07-13 14:14:34 -0600592
593 /* Set PCH IO decode ranges if required.*/
594 if ((config->gen1_dec & 0xFFFC) > 0x1000) {
595 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
596 res->base = config->gen1_dec & 0xFFFC;
597 res->size = (config->gen1_dec >> 16) & 0xFC;
598 res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
599 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
600 }
601
602 if ((config->gen2_dec & 0xFFFC) > 0x1000) {
603 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
604 res->base = config->gen2_dec & 0xFFFC;
605 res->size = (config->gen2_dec >> 16) & 0xFC;
606 res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
607 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
608 }
609
610 if ((config->gen3_dec & 0xFFFC) > 0x1000) {
611 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
612 res->base = config->gen3_dec & 0xFFFC;
613 res->size = (config->gen3_dec >> 16) & 0xFC;
614 res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
615 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
616 }
617
618 if ((config->gen4_dec & 0xFFFC) > 0x1000) {
619 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
620 res->base = config->gen4_dec & 0xFFFC;
621 res->size = (config->gen4_dec >> 16) & 0xFC;
622 res->flags = IORESOURCE_IO| IORESOURCE_SUBTRACTIVE |
623 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
624 }
Stefan Reinauer8e073822012-04-04 00:07:22 +0200625}
626
627static void pch_lpc_enable_resources(device_t dev)
628{
629 pch_decode_init(dev);
630 return pci_dev_enable_resources(dev);
631}
632
633static void pch_lpc_enable(device_t dev)
634{
635 /* Enable PCH Display Port */
636 RCBA16(DISPBDF) = 0x0010;
637 RCBA32_OR(FD2, PCH_ENABLE_DBDF);
638
639 pch_enable(dev);
640}
641
642static void set_subsystem(device_t dev, unsigned vendor, unsigned device)
643{
644 if (!vendor || !device) {
645 pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
646 pci_read_config32(dev, PCI_VENDOR_ID));
647 } else {
648 pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
649 ((device & 0xffff) << 16) | (vendor & 0xffff));
650 }
651}
652
Alexander Couzensa90dad12015-04-12 21:49:46 +0200653static void southbridge_inject_dsdt(device_t dev)
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +0200654{
Elyes HAOUAS035df002016-10-03 21:54:16 +0200655 global_nvs_t *gnvs = cbmem_add (CBMEM_ID_ACPI_GNVS, sizeof(*gnvs));
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +0200656
657 if (gnvs) {
Vladimir Serbinenkodd2bc3f2014-10-31 09:16:31 +0100658 const struct i915_gpu_controller_info *gfx = intel_gma_get_controller_info();
Elyes HAOUAS035df002016-10-03 21:54:16 +0200659 memset(gnvs, 0, sizeof(*gnvs));
Vladimir Serbinenko7309c642014-10-05 11:07:33 +0200660
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +0200661 acpi_create_gnvs(gnvs);
Vladimir Serbinenko06c788d2014-10-12 00:17:11 +0200662
663 gnvs->apic = 1;
664 gnvs->mpen = 1; /* Enable Multi Processing */
665 gnvs->pcnt = dev_count_cpu();
666
Vladimir Serbinenkodd2bc3f2014-10-31 09:16:31 +0100667 gnvs->ndid = gfx->ndid;
668 memcpy(gnvs->did, gfx->did, sizeof(gnvs->did));
669
Martin Roth7a1a3ad2017-06-24 21:29:38 -0600670#if IS_ENABLED(CONFIG_CHROMEOS)
Vladimir Serbinenko06c788d2014-10-12 00:17:11 +0200671 chromeos_init_vboot(&(gnvs->chromeos));
672#endif
673
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +0200674 /* And tell SMI about it */
675 smm_setup_structures(gnvs, NULL, NULL);
676
Vladimir Serbinenko334fd8e2014-10-05 11:10:35 +0200677 /* Add it to DSDT. */
Vladimir Serbinenko226d7842014-11-04 21:09:23 +0100678 acpigen_write_scope("\\");
679 acpigen_write_name_dword("NVSA", (u32) gnvs);
680 acpigen_pop_len();
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +0200681 }
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +0200682}
683
Vladimir Serbinenko5b044ae2014-10-25 15:20:55 +0200684void acpi_fill_fadt(acpi_fadt_t *fadt)
685{
686 device_t dev = dev_find_slot(0, PCI_DEVFN(0x1f,0));
687 config_t *chip = dev->chip_info;
688 u16 pmbase = pci_read_config16(dev, 0x40) & 0xfffe;
689 int c2_latency;
690
691 fadt->model = 1;
692
693 fadt->sci_int = 0x9;
694 fadt->smi_cmd = APM_CNT;
695 fadt->acpi_enable = APM_CNT_ACPI_ENABLE;
696 fadt->acpi_disable = APM_CNT_ACPI_DISABLE;
697 fadt->s4bios_req = 0x0;
698 fadt->pstate_cnt = 0;
699
700 fadt->pm1a_evt_blk = pmbase;
701 fadt->pm1b_evt_blk = 0x0;
702 fadt->pm1a_cnt_blk = pmbase + 0x4;
703 fadt->pm1b_cnt_blk = 0x0;
704 fadt->pm2_cnt_blk = pmbase + 0x50;
705 fadt->pm_tmr_blk = pmbase + 0x8;
706 fadt->gpe0_blk = pmbase + 0x20;
707 fadt->gpe1_blk = 0;
708
709 fadt->pm1_evt_len = 4;
710 fadt->pm1_cnt_len = 2;
711 fadt->pm2_cnt_len = 1;
712 fadt->pm_tmr_len = 4;
713 fadt->gpe0_blk_len = 16;
714 fadt->gpe1_blk_len = 0;
715 fadt->gpe1_base = 0;
716 fadt->cst_cnt = 0;
717 c2_latency = chip->c2_latency;
718 if (!c2_latency) {
719 c2_latency = 101; /* c2 unsupported */
720 }
721 fadt->p_lvl2_lat = c2_latency;
722 fadt->p_lvl3_lat = 87;
723 fadt->flush_size = 1024;
724 fadt->flush_stride = 16;
725 fadt->duty_offset = 1;
726 if (chip->p_cnt_throttling_supported) {
727 fadt->duty_width = 3;
728 } else {
729 fadt->duty_width = 0;
730 }
731 fadt->day_alrm = 0xd;
732 fadt->mon_alrm = 0x00;
733 fadt->century = 0x00;
734 fadt->iapc_boot_arch = ACPI_FADT_LEGACY_DEVICES | ACPI_FADT_8042;
735
736 fadt->flags = ACPI_FADT_WBINVD |
737 ACPI_FADT_C1_SUPPORTED |
738 ACPI_FADT_SLEEP_BUTTON |
739 ACPI_FADT_RESET_REGISTER |
740 ACPI_FADT_SEALED_CASE |
741 ACPI_FADT_S4_RTC_WAKE |
742 ACPI_FADT_PLATFORM_CLOCK;
743 if (chip->docking_supported) {
744 fadt->flags |= ACPI_FADT_DOCKING_SUPPORTED;
745 }
746 if (c2_latency < 100) {
747 fadt->flags |= ACPI_FADT_C2_MP_SUPPORTED;
748 }
749
750 fadt->reset_reg.space_id = 1;
751 fadt->reset_reg.bit_width = 8;
752 fadt->reset_reg.bit_offset = 0;
753 fadt->reset_reg.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
754 fadt->reset_reg.addrl = 0xcf9;
755 fadt->reset_reg.addrh = 0;
756
757 fadt->reset_value = 6;
758
759 fadt->x_pm1a_evt_blk.space_id = 1;
760 fadt->x_pm1a_evt_blk.bit_width = 32;
761 fadt->x_pm1a_evt_blk.bit_offset = 0;
762 fadt->x_pm1a_evt_blk.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
763 fadt->x_pm1a_evt_blk.addrl = pmbase;
764 fadt->x_pm1a_evt_blk.addrh = 0x0;
765
766 fadt->x_pm1b_evt_blk.space_id = 1;
767 fadt->x_pm1b_evt_blk.bit_width = 0;
768 fadt->x_pm1b_evt_blk.bit_offset = 0;
769 fadt->x_pm1b_evt_blk.access_size = 0;
770 fadt->x_pm1b_evt_blk.addrl = 0x0;
771 fadt->x_pm1b_evt_blk.addrh = 0x0;
772
773 fadt->x_pm1a_cnt_blk.space_id = 1;
774 fadt->x_pm1a_cnt_blk.bit_width = 16;
775 fadt->x_pm1a_cnt_blk.bit_offset = 0;
776 fadt->x_pm1a_cnt_blk.access_size = ACPI_ACCESS_SIZE_WORD_ACCESS;
777 fadt->x_pm1a_cnt_blk.addrl = pmbase + 0x4;
778 fadt->x_pm1a_cnt_blk.addrh = 0x0;
779
780 fadt->x_pm1b_cnt_blk.space_id = 1;
781 fadt->x_pm1b_cnt_blk.bit_width = 0;
782 fadt->x_pm1b_cnt_blk.bit_offset = 0;
783 fadt->x_pm1b_cnt_blk.access_size = 0;
784 fadt->x_pm1b_cnt_blk.addrl = 0x0;
785 fadt->x_pm1b_cnt_blk.addrh = 0x0;
786
787 fadt->x_pm2_cnt_blk.space_id = 1;
788 fadt->x_pm2_cnt_blk.bit_width = 8;
789 fadt->x_pm2_cnt_blk.bit_offset = 0;
790 fadt->x_pm2_cnt_blk.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
791 fadt->x_pm2_cnt_blk.addrl = pmbase + 0x50;
792 fadt->x_pm2_cnt_blk.addrh = 0x0;
793
794 fadt->x_pm_tmr_blk.space_id = 1;
795 fadt->x_pm_tmr_blk.bit_width = 32;
796 fadt->x_pm_tmr_blk.bit_offset = 0;
797 fadt->x_pm_tmr_blk.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
798 fadt->x_pm_tmr_blk.addrl = pmbase + 0x8;
799 fadt->x_pm_tmr_blk.addrh = 0x0;
800
801 fadt->x_gpe0_blk.space_id = 1;
802 fadt->x_gpe0_blk.bit_width = 128;
803 fadt->x_gpe0_blk.bit_offset = 0;
804 fadt->x_gpe0_blk.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
805 fadt->x_gpe0_blk.addrl = pmbase + 0x20;
806 fadt->x_gpe0_blk.addrh = 0x0;
807
808 fadt->x_gpe1_blk.space_id = 1;
809 fadt->x_gpe1_blk.bit_width = 0;
810 fadt->x_gpe1_blk.bit_offset = 0;
811 fadt->x_gpe1_blk.access_size = 0;
812 fadt->x_gpe1_blk.addrl = 0x0;
813 fadt->x_gpe1_blk.addrh = 0x0;
814}
815
Aaron Durbinaa090cb2017-09-13 16:01:52 -0600816static const char *lpc_acpi_name(const struct device *dev)
Patrick Rudolph604f6982017-06-07 09:46:52 +0200817{
818 return "LPCB";
819}
820
Alexander Couzens5eea4582015-04-12 22:18:55 +0200821static void southbridge_fill_ssdt(device_t device)
Vladimir Serbinenko36fa5b82014-10-28 23:43:20 +0100822{
823 device_t dev = dev_find_slot(0, PCI_DEVFN(0x1f,0));
824 config_t *chip = dev->chip_info;
825
826 intel_acpi_pcie_hotplug_generator(chip->pcie_hotplug_map, 8);
Tobias Diedrich7f5efd92017-12-14 00:29:01 +0100827 intel_acpi_gen_def_acpi_pirq(dev);
Vladimir Serbinenko36fa5b82014-10-28 23:43:20 +0100828}
829
Vladimir Serbinenkob06a2492015-05-21 10:32:59 +0200830static void lpc_final(struct device *dev)
831{
Nico Huber8e50b6d2018-02-04 15:52:18 +0100832 u16 spi_opprefix = SPI_OPPREFIX;
833 u16 spi_optype = SPI_OPTYPE;
834 u32 spi_opmenu[2] = { SPI_OPMENU_LOWER, SPI_OPMENU_UPPER };
835
836 /* Configure SPI opcode menu; devicetree may override defaults. */
837 const config_t *const config = dev->chip_info;
838 if (config && config->spi.ops[0].op) {
839 unsigned int i;
840
841 spi_opprefix = 0;
842 spi_optype = 0;
843 spi_opmenu[0] = 0;
844 spi_opmenu[1] = 0;
845 for (i = 0; i < sizeof(spi_opprefix); ++i)
846 spi_opprefix |= config->spi.opprefixes[i] << i * 8;
847 for (i = 0; i < sizeof(spi_opmenu); ++i) {
848 spi_optype |=
849 config->spi.ops[i].is_write << 2 * i |
850 config->spi.ops[i].needs_address << (2 * i + 1);
851 spi_opmenu[i / 4] |=
852 config->spi.ops[i].op << (i % 4) * 8;
853 }
854 }
855 RCBA16(0x3894) = spi_opprefix;
856 RCBA16(0x3896) = spi_optype;
857 RCBA32(0x3898) = spi_opmenu[0];
858 RCBA32(0x389c) = spi_opmenu[1];
859
Bill XIEd533b162017-08-22 16:26:22 +0800860 /* Call SMM finalize() handlers before resume */
861 if (IS_ENABLED(CONFIG_HAVE_SMI_HANDLER)) {
862 if (IS_ENABLED(CONFIG_INTEL_CHIPSET_LOCKDOWN) ||
863 acpi_is_wakeup_s3()) {
864 outb(APM_CNT_FINALIZE, APM_CNT);
865 }
Vladimir Serbinenkob06a2492015-05-21 10:32:59 +0200866 }
867}
868
Stefan Reinauer8e073822012-04-04 00:07:22 +0200869static struct pci_operations pci_ops = {
870 .set_subsystem = set_subsystem,
871};
872
873static struct device_operations device_ops = {
874 .read_resources = pch_lpc_read_resources,
875 .set_resources = pci_dev_set_resources,
876 .enable_resources = pch_lpc_enable_resources,
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +0200877 .write_acpi_tables = acpi_write_hpet,
Vladimir Serbinenko334fd8e2014-10-05 11:10:35 +0200878 .acpi_inject_dsdt_generator = southbridge_inject_dsdt,
Vladimir Serbinenko36fa5b82014-10-28 23:43:20 +0100879 .acpi_fill_ssdt_generator = southbridge_fill_ssdt,
Patrick Rudolph604f6982017-06-07 09:46:52 +0200880 .acpi_name = lpc_acpi_name,
Stefan Reinauer8e073822012-04-04 00:07:22 +0200881 .init = lpc_init,
Vladimir Serbinenkob06a2492015-05-21 10:32:59 +0200882 .final = lpc_final,
Stefan Reinauer8e073822012-04-04 00:07:22 +0200883 .enable = pch_lpc_enable,
Kyösti Mälkkid0e212c2015-02-26 20:47:47 +0200884 .scan_bus = scan_lpc_bus,
Stefan Reinauer8e073822012-04-04 00:07:22 +0200885 .ops_pci = &pci_ops,
886};
887
888
Kimarie Hoote6f459c2012-07-14 08:26:08 -0600889/* IDs for LPC device of Intel 6 Series Chipset, Intel 7 Series Chipset, and
890 * Intel C200 Series Chipset
Stefan Reinauer8e073822012-04-04 00:07:22 +0200891 */
892
Vladimir Serbinenko42d55e02016-01-02 01:47:26 +0100893static const unsigned short pci_device_ids[] = {
894 0x1c40, 0x1c41, 0x1c42, 0x1c43, 0x1c44, 0x1c45, 0x1c46, 0x1c47, 0x1c48,
895 0x1c49, 0x1c4a, 0x1c4b, 0x1c4c, 0x1c4d, 0x1c4e, 0x1c4f, 0x1c50, 0x1c51,
896 0x1c52, 0x1c53, 0x1c54, 0x1c55, 0x1c56, 0x1c57, 0x1c58, 0x1c59, 0x1c5a,
897 0x1c5b, 0x1c5c, 0x1c5d, 0x1c5e, 0x1c5f,
898
899 0x1e41, 0x1e42, 0x1e43, 0x1e44, 0x1e45, 0x1e46, 0x1e47, 0x1e48, 0x1e49,
900 0x1e4a, 0x1e4b, 0x1e4c, 0x1e4d, 0x1e4e, 0x1e4f, 0x1e50, 0x1e51, 0x1e52,
901 0x1e53, 0x1e54, 0x1e55, 0x1e56, 0x1e57, 0x1e58, 0x1e59, 0x1e5a, 0x1e5b,
902 0x1e5c, 0x1e5d, 0x1e5e, 0x1e5f,
903
904 0 };
Stefan Reinauer9a380ab2012-06-22 13:16:11 -0700905
906static const struct pci_driver pch_lpc __pci_driver = {
907 .ops = &device_ops,
908 .vendor = PCI_VENDOR_ID_INTEL,
909 .devices = pci_device_ids,
Stefan Reinauer8e073822012-04-04 00:07:22 +0200910};