blob: 9f70d1f8be9f61738571257c3789a48f2129677f [file] [log] [blame]
Angel Pons182dbde2020-04-02 23:49:05 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Patrick Georgie72a8a32012-11-06 11:05:09 +01002
3#include <console/console.h>
4#include <device/device.h>
5#include <device/pci.h>
6#include <device/pci_ids.h>
Kyösti Mälkkicbf95712020-01-05 08:05:45 +02007#include <option.h>
Patrick Georgie72a8a32012-11-06 11:05:09 +01008#include <pc80/mc146818rtc.h>
9#include <pc80/isa-dma.h>
10#include <pc80/i8259.h>
11#include <arch/io.h>
Kyösti Mälkkif1b58b72019-03-01 13:43:02 +020012#include <device/pci_ops.h>
Patrick Georgie72a8a32012-11-06 11:05:09 +010013#include <arch/ioapic.h>
Furquan Shaikh76cedd22020-05-02 10:24:23 -070014#include <acpi/acpi.h>
Patrick Georgie72a8a32012-11-06 11:05:09 +010015#include <cpu/x86/smm.h>
Furquan Shaikh76cedd22020-05-02 10:24:23 -070016#include <acpi/acpigen.h>
Kyösti Mälkki12b121c2019-08-18 16:33:39 +030017#include "chip.h"
Patrick Georgie72a8a32012-11-06 11:05:09 +010018#include "i82801ix.h"
Vladimir Serbinenko36fa5b82014-10-28 23:43:20 +010019#include <southbridge/intel/common/pciehp.h>
Angel Ponse1a616c2020-06-21 17:02:43 +020020#include <southbridge/intel/common/pmutil.h>
Arthur Heymanse798e6a2017-12-23 23:09:54 +010021#include <southbridge/intel/common/acpi_pirq_gen.h>
Tim Wawrzynczakf62c4942021-02-26 10:30:52 -070022#include <southbridge/intel/common/rcba_pirq.h>
Patrick Georgie72a8a32012-11-06 11:05:09 +010023
24#define NMI_OFF 0
25
Patrick Georgie72a8a32012-11-06 11:05:09 +010026typedef struct southbridge_intel_i82801ix_config config_t;
27
28static void i82801ix_enable_apic(struct device *dev)
29{
Patrick Georgie72a8a32012-11-06 11:05:09 +010030 /* Enable IOAPIC. Keep APIC Range Select at zero. */
31 RCBA8(0x31ff) = 0x03;
32 /* We have to read 0x31ff back if bit0 changed. */
Paul Menzeld0299e42013-10-21 09:28:19 +020033 RCBA8(0x31ff);
Patrick Georgie72a8a32012-11-06 11:05:09 +010034
35 /* Lock maximum redirection entries (MRE), R/WO register. */
Kyösti Mälkki04a40372021-06-06 08:04:28 +030036 ioapic_lock_max_vectors(VIO_APIC_VADDR);
Patrick Georgie72a8a32012-11-06 11:05:09 +010037
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -080038 setup_ioapic(VIO_APIC_VADDR, 2); /* ICH7 code uses id 2. */
Patrick Georgie72a8a32012-11-06 11:05:09 +010039}
40
41static void i82801ix_enable_serial_irqs(struct device *dev)
42{
43 /* Set packet length and toggle silent mode bit for one frame. */
44 pci_write_config8(dev, D31F0_SERIRQ_CNTL,
45 (1 << 7) | (1 << 6) | ((21 - 17) << 2) | (0 << 0));
46}
47
48/* PIRQ[n]_ROUT[3:0] - PIRQ Routing Control
49 * 0x00 - 0000 = Reserved
50 * 0x01 - 0001 = Reserved
51 * 0x02 - 0010 = Reserved
52 * 0x03 - 0011 = IRQ3
53 * 0x04 - 0100 = IRQ4
54 * 0x05 - 0101 = IRQ5
55 * 0x06 - 0110 = IRQ6
56 * 0x07 - 0111 = IRQ7
57 * 0x08 - 1000 = Reserved
58 * 0x09 - 1001 = IRQ9
59 * 0x0A - 1010 = IRQ10
60 * 0x0B - 1011 = IRQ11
61 * 0x0C - 1100 = IRQ12
62 * 0x0D - 1101 = Reserved
63 * 0x0E - 1110 = IRQ14
64 * 0x0F - 1111 = IRQ15
65 * PIRQ[n]_ROUT[7] - PIRQ Routing Control
66 * 0x80 - The PIRQ is not routed.
67 */
68
Elyes HAOUAS8aa50732018-05-13 13:34:58 +020069static void i82801ix_pirq_init(struct device *dev)
Patrick Georgie72a8a32012-11-06 11:05:09 +010070{
Elyes HAOUAS8aa50732018-05-13 13:34:58 +020071 struct device *irq_dev;
Patrick Georgie72a8a32012-11-06 11:05:09 +010072 /* Get the chip configuration */
73 config_t *config = dev->chip_info;
74
75 pci_write_config8(dev, D31F0_PIRQA_ROUT, config->pirqa_routing);
76 pci_write_config8(dev, D31F0_PIRQB_ROUT, config->pirqb_routing);
77 pci_write_config8(dev, D31F0_PIRQC_ROUT, config->pirqc_routing);
78 pci_write_config8(dev, D31F0_PIRQD_ROUT, config->pirqd_routing);
79
80 pci_write_config8(dev, D31F0_PIRQE_ROUT, config->pirqe_routing);
81 pci_write_config8(dev, D31F0_PIRQF_ROUT, config->pirqf_routing);
82 pci_write_config8(dev, D31F0_PIRQG_ROUT, config->pirqg_routing);
83 pci_write_config8(dev, D31F0_PIRQH_ROUT, config->pirqh_routing);
84
85 /* Eric Biederman once said we should let the OS do this.
86 * I am not so sure anymore he was right.
87 */
88
Elyes HAOUASba28e8d2016-08-31 19:22:16 +020089 for (irq_dev = all_devices; irq_dev; irq_dev = irq_dev->next) {
Angel Ponsbcc2c722020-08-10 13:44:09 +020090 u8 int_pin = 0, int_line = 0;
Patrick Georgie72a8a32012-11-06 11:05:09 +010091
92 if (!irq_dev->enabled || irq_dev->path.type != DEVICE_PATH_PCI)
93 continue;
94
95 int_pin = pci_read_config8(irq_dev, PCI_INTERRUPT_PIN);
96
97 switch (int_pin) {
98 case 1: /* INTA# */ int_line = config->pirqa_routing; break;
99 case 2: /* INTB# */ int_line = config->pirqb_routing; break;
100 case 3: /* INTC# */ int_line = config->pirqc_routing; break;
101 case 4: /* INTD# */ int_line = config->pirqd_routing; break;
102 }
103
104 if (!int_line)
105 continue;
106
107 pci_write_config8(irq_dev, PCI_INTERRUPT_LINE, int_line);
108 }
109}
110
Elyes HAOUAS8aa50732018-05-13 13:34:58 +0200111static void i82801ix_gpi_routing(struct device *dev)
Patrick Georgie72a8a32012-11-06 11:05:09 +0100112{
113 /* Get the chip configuration */
114 config_t *config = dev->chip_info;
115 u32 reg32 = 0;
116
117 /* An array would be much nicer here, or some
118 * other method of doing this.
119 */
120 reg32 |= (config->gpi0_routing & 0x03) << 0;
121 reg32 |= (config->gpi1_routing & 0x03) << 2;
122 reg32 |= (config->gpi2_routing & 0x03) << 4;
123 reg32 |= (config->gpi3_routing & 0x03) << 6;
124 reg32 |= (config->gpi4_routing & 0x03) << 8;
125 reg32 |= (config->gpi5_routing & 0x03) << 10;
126 reg32 |= (config->gpi6_routing & 0x03) << 12;
127 reg32 |= (config->gpi7_routing & 0x03) << 14;
128 reg32 |= (config->gpi8_routing & 0x03) << 16;
129 reg32 |= (config->gpi9_routing & 0x03) << 18;
130 reg32 |= (config->gpi10_routing & 0x03) << 20;
131 reg32 |= (config->gpi11_routing & 0x03) << 22;
132 reg32 |= (config->gpi12_routing & 0x03) << 24;
133 reg32 |= (config->gpi13_routing & 0x03) << 26;
134 reg32 |= (config->gpi14_routing & 0x03) << 28;
135 reg32 |= (config->gpi15_routing & 0x03) << 30;
136
137 pci_write_config32(dev, D31F0_GPIO_ROUT, reg32);
138}
139
Elyes HAOUAS8aa50732018-05-13 13:34:58 +0200140static void i82801ix_power_options(struct device *dev)
Patrick Georgie72a8a32012-11-06 11:05:09 +0100141{
142 u8 reg8;
143 u16 reg16, pmbase;
144 u32 reg32;
145 const char *state;
146 /* Get the chip configuration */
147 config_t *config = dev->chip_info;
148
Patrick Georgie72a8a32012-11-06 11:05:09 +0100149 /* BIOS must program... */
Angel Ponsbcc2c722020-08-10 13:44:09 +0200150 pci_or_config32(dev, 0xac, (1 << 30) | (3 << 8));
Patrick Georgie72a8a32012-11-06 11:05:09 +0100151
152 /* Which state do we want to goto after g3 (power restored)?
153 * 0 == S0 Full On
154 * 1 == S5 Soft Off
155 *
156 * If the option is not existent (Laptops), use MAINBOARD_POWER_ON.
157 */
Angel Pons88dcb312021-04-26 17:10:28 +0200158 const unsigned int pwr_on = get_uint_option("power_on_after_fail", MAINBOARD_POWER_ON);
Patrick Georgie72a8a32012-11-06 11:05:09 +0100159
160 reg8 = pci_read_config8(dev, D31F0_GEN_PMCON_3);
161 reg8 &= 0xfe;
162 switch (pwr_on) {
163 case MAINBOARD_POWER_OFF:
164 reg8 |= 1;
165 state = "off";
166 break;
167 case MAINBOARD_POWER_ON:
168 reg8 &= ~1;
169 state = "on";
170 break;
171 case MAINBOARD_POWER_KEEP:
172 reg8 &= ~1;
173 state = "state keep";
174 break;
175 default:
176 state = "undefined";
177 }
178
179 reg8 |= (3 << 4); /* avoid #S4 assertions */
Elyes HAOUASdc413712021-02-07 20:54:53 +0100180 reg8 &= ~(1 << 3); /* minimum assertion is 1 to 2 RTCCLK */
Patrick Georgie72a8a32012-11-06 11:05:09 +0100181
182 pci_write_config8(dev, D31F0_GEN_PMCON_3, reg8);
183 printk(BIOS_INFO, "Set power %s after power failure.\n", state);
184
185 /* Set up NMI on errors. */
186 reg8 = inb(0x61);
187 reg8 &= 0x0f; /* Higher Nibble must be 0 */
188 reg8 &= ~(1 << 3); /* IOCHK# NMI Enable */
189 // reg8 &= ~(1 << 2); /* PCI SERR# Enable */
190 reg8 |= (1 << 2); /* PCI SERR# Disable for now */
191 outb(reg8, 0x61);
192
193 reg8 = inb(0x74); /* Read from 0x74 as 0x70 is write only. */
Angel Pons88dcb312021-04-26 17:10:28 +0200194 const unsigned int nmi_option = get_uint_option("nmi", NMI_OFF);
Patrick Georgie72a8a32012-11-06 11:05:09 +0100195 if (nmi_option) {
196 printk(BIOS_INFO, "NMI sources enabled.\n");
197 reg8 &= ~(1 << 7); /* Set NMI. */
198 } else {
199 printk(BIOS_INFO, "NMI sources disabled.\n");
Elyes HAOUAS9c5d4632018-04-26 22:21:21 +0200200 reg8 |= (1 << 7); /* Can't mask NMI from PCI-E and NMI_NOW */
Patrick Georgie72a8a32012-11-06 11:05:09 +0100201 }
202 outb(reg8, 0x70);
203
204 /* Enable CPU_SLP# and Intel Speedstep, set SMI# rate down */
205 reg16 = pci_read_config16(dev, D31F0_GEN_PMCON_1);
206 reg16 &= ~(3 << 0); // SMI# rate 1 minute
207 reg16 |= (1 << 2); // CLKRUN_EN - Mobile/Ultra only
208 reg16 |= (1 << 3); // Speedstep Enable - Mobile/Ultra only
209 reg16 |= (1 << 5); // CPUSLP_EN Desktop only
210
211 if (config->c4onc3_enable)
212 reg16 |= (1 << 7);
213
214 // another laptop wants this?
215 // reg16 &= ~(1 << 10); // BIOS_PCI_EXP_EN - Desktop/Mobile only
216 reg16 |= (1 << 10); // BIOS_PCI_EXP_EN - Desktop/Mobile only
Kyösti Mälkki94464472020-06-13 13:45:42 +0300217 if (CONFIG(DEBUG_PERIODIC_SMI))
218 reg16 |= (3 << 0); // Periodic SMI every 8s
Patrick Georgie72a8a32012-11-06 11:05:09 +0100219 if (config->c5_enable)
220 reg16 |= (1 << 11); /* Enable C5, C6 and PMSYNC# */
221 pci_write_config16(dev, D31F0_GEN_PMCON_1, reg16);
222
223 /* Set exit timings for C5/C6. */
224 if (config->c5_enable) {
225 reg8 = pci_read_config8(dev, D31F0_C5_EXIT_TIMING);
226 reg8 &= ~((7 << 3) | (7 << 0));
227 if (config->c6_enable)
228 reg8 |= (5 << 3) | (3 << 0); /* 38-44us PMSYNC# to STPCLK#,
229 95-102us DPRSTP# to STP_CPU# */
230 else
231 reg8 |= (0 << 3) | (1 << 0); /* 16-17us PMSYNC# to STPCLK#,
232 34-40us DPRSTP# to STP_CPU# */
233 pci_write_config8(dev, D31F0_C5_EXIT_TIMING, reg8);
234 }
235
236 // Set the board's GPI routing.
237 i82801ix_gpi_routing(dev);
238
239 pmbase = pci_read_config16(dev, 0x40) & 0xfffe;
240
241 outl(config->gpe0_en, pmbase + 0x28);
242 outw(config->alt_gp_smi_en, pmbase + 0x38);
243
244 /* Set up power management block and determine sleep mode */
245 reg16 = inw(pmbase + 0x00); /* PM1_STS */
246 outw(reg16, pmbase + 0x00); /* Clear status bits. At least bit11 (power
247 button override) must be cleared or SCI
248 will be constantly fired and OSPM must
249 not know about it (ACPI spec says to
250 ignore the bit). */
Patrick Georgie72a8a32012-11-06 11:05:09 +0100251
252 /* Set duty cycle for hardware throttling (defaults to 0x0: 50%). */
253 reg32 = inl(pmbase + 0x10);
254 reg32 &= ~(7 << 5);
255 reg32 |= (config->throttle_duty & 7) << 5;
256 outl(reg32, pmbase + 0x10);
257}
258
Elyes HAOUAS8aa50732018-05-13 13:34:58 +0200259static void i82801ix_configure_cstates(struct device *dev)
Patrick Georgie72a8a32012-11-06 11:05:09 +0100260{
Angel Pons67406472020-06-08 11:13:42 +0200261 // Enable Popup & Popdown
262 pci_or_config8(dev, D31F0_CxSTATE_CNF, (1 << 4) | (1 << 3) | (1 << 2));
Patrick Georgie72a8a32012-11-06 11:05:09 +0100263
264 // Set Deeper Sleep configuration to recommended values
Angel Pons67406472020-06-08 11:13:42 +0200265 // Deeper Sleep to Stop CPU: 34-40us
266 // Deeper Sleep to Sleep: 15us
267 pci_update_config8(dev, D31F0_C4TIMING_CNT, ~0x0f, (2 << 2) | (2 << 0));
Patrick Georgie72a8a32012-11-06 11:05:09 +0100268
269 /* We could enable slow-C4 exit here, if someone needs it? */
270}
271
272static void i82801ix_rtc_init(struct device *dev)
273{
274 u8 reg8;
275 int rtc_failed;
276
277 reg8 = pci_read_config8(dev, D31F0_GEN_PMCON_3);
278 rtc_failed = reg8 & RTC_BATTERY_DEAD;
279 if (rtc_failed) {
280 reg8 &= ~RTC_BATTERY_DEAD;
281 pci_write_config8(dev, D31F0_GEN_PMCON_3, reg8);
282 }
283 printk(BIOS_DEBUG, "rtc_failed = 0x%x\n", rtc_failed);
284
Gabe Blackb3f08c62014-04-30 17:12:25 -0700285 cmos_init(rtc_failed);
Patrick Georgie72a8a32012-11-06 11:05:09 +0100286}
287
288static void enable_hpet(void)
289{
290 u32 reg32;
291
292 /* Move HPET to default address 0xfed00000 and enable it */
293 reg32 = RCBA32(RCBA_HPTC);
294 reg32 |= (1 << 7); // HPET Address Enable
295 reg32 &= ~(3 << 0);
296 RCBA32(RCBA_HPTC) = reg32;
297}
298
299static void enable_clock_gating(void)
300{
301 u32 reg32;
302
303 /* Enable DMI dynamic clock gating. */
304 RCBA32(RCBA_DMIC) |= 3;
305
306 /* Enable Clock Gating for most devices. */
307 reg32 = RCBA32(RCBA_CG);
308 reg32 |= (1 << 31); /* LPC dynamic clock gating */
309 /* USB UHCI dynamic clock gating: */
310 reg32 |= (1 << 29) | (1 << 28);
311 /* SATA dynamic clock gating [0-3]: */
312 reg32 |= (1 << 27) | (1 << 26) | (1 << 25) | (1 << 24);
313 reg32 |= (1 << 23); /* LAN static clock gating (if LAN disabled) */
314 reg32 |= (1 << 22); /* HD audio dynamic clock gating */
315 reg32 &= ~(1 << 21); /* No HD audio static clock gating */
316 reg32 &= ~(1 << 20); /* No USB EHCI static clock gating */
317 reg32 |= (1 << 19); /* USB EHCI dynamic clock gating */
318 /* More SATA dynamic clock gating [4-5]: */
319 reg32 |= (1 << 18) | (1 << 17);
320 reg32 |= (1 << 16); /* PCI dynamic clock gating */
321 /* PCIe, DMI dynamic clock gating: */
322 reg32 |= (1 << 4) | (1 << 3) | (1 << 2) | (1 << 1);
323 reg32 |= (1 << 0); /* PCIe root port static clock gating */
324 RCBA32(RCBA_CG) = reg32;
325
326 /* Enable SPI dynamic clock gating. */
327 RCBA32(0x38c0) |= 7;
328}
329
Kyösti Mälkki6feb4da2019-07-13 17:28:37 +0300330static void i82801ix_set_acpi_mode(struct device *dev)
Patrick Georgie72a8a32012-11-06 11:05:09 +0100331{
Kyösti Mälkkiad882c32020-06-02 05:05:30 +0300332 if (!acpi_is_wakeup_s3()) {
333 apm_control(APM_CNT_ACPI_DISABLE);
334 } else {
335 apm_control(APM_CNT_ACPI_ENABLE);
Patrick Georgie72a8a32012-11-06 11:05:09 +0100336 }
Patrick Georgie72a8a32012-11-06 11:05:09 +0100337}
Patrick Georgie72a8a32012-11-06 11:05:09 +0100338
339static void lpc_init(struct device *dev)
340{
Elyes HAOUASbfc255a2020-03-07 13:05:14 +0100341 printk(BIOS_DEBUG, "i82801ix: %s\n", __func__);
Patrick Georgie72a8a32012-11-06 11:05:09 +0100342
Patrick Georgie72a8a32012-11-06 11:05:09 +0100343 /* IO APIC initialization. */
344 i82801ix_enable_apic(dev);
345
346 i82801ix_enable_serial_irqs(dev);
347
348 /* Setup the PIRQ. */
349 i82801ix_pirq_init(dev);
350
351 /* Setup power options. */
352 i82801ix_power_options(dev);
353
354 /* Configure Cx state registers */
355 if (LPC_IS_MOBILE(dev))
356 i82801ix_configure_cstates(dev);
357
358 /* Initialize the real time clock. */
359 i82801ix_rtc_init(dev);
360
361 /* Initialize ISA DMA. */
362 isa_dma_init();
363
364 /* Initialize the High Precision Event Timers, if present. */
365 enable_hpet();
366
367 /* Initialize Clock Gating */
368 enable_clock_gating();
369
370 setup_i8259();
371
372 /* The OS should do this? */
373 /* Interrupt 9 should be level triggered (SCI) */
374 i8259_configure_irq_trigger(9, 1);
375
Kyösti Mälkki44da9e72019-10-09 12:32:16 +0300376 i82801ix_set_acpi_mode(dev);
Kyösti Mälkki6feb4da2019-07-13 17:28:37 +0300377
378 /* Don't allow evil boot loaders, kernels, or
379 * userspace applications to deceive us:
380 */
Kyösti Mälkki894f6f82022-01-29 14:05:58 +0200381 if (CONFIG(SMM_LEGACY_ASEG))
Kyösti Mälkki6feb4da2019-07-13 17:28:37 +0300382 aseg_smm_lock();
Patrick Georgie72a8a32012-11-06 11:05:09 +0100383}
384
Elyes HAOUAS8aa50732018-05-13 13:34:58 +0200385static void i82801ix_lpc_read_resources(struct device *dev)
Patrick Georgie72a8a32012-11-06 11:05:09 +0100386{
387 /*
388 * I/O Resources
389 *
390 * 0x0000 - 0x000f....ISA DMA
391 * 0x0010 - 0x001f....ISA DMA aliases
392 * 0x0020 ~ 0x003d....PIC
393 * 0x002e - 0x002f....Maybe Super I/O
394 * 0x0040 - 0x0043....Timer
395 * 0x004e - 0x004f....Maybe Super I/O
396 * 0x0050 - 0x0053....Timer aliases
397 * 0x0061.............NMI_SC
398 * 0x0070.............NMI_EN (readable in alternative access mode)
399 * 0x0070 - 0x0077....RTC
400 * 0x0080 - 0x008f....ISA DMA
401 * 0x0090 ~ 0x009f....ISA DMA aliases
402 * 0x0092.............Fast A20 and Init
403 * 0x00a0 ~ 0x00bd....PIC
404 * 0x00b2 - 0x00b3....APM
405 * 0x00c0 ~ 0x00de....ISA DMA
406 * 0x00c1 ~ 0x00df....ISA DMA aliases
407 * 0x00f0.............Coprocessor Error
Angel Ponsb21bffa2020-07-03 01:02:28 +0200408 * (0x0400-0x041f)....SMBus (CONFIG_FIXED_SMBUS_IO_BASE, during raminit)
Patrick Georgie72a8a32012-11-06 11:05:09 +0100409 * 0x04d0 - 0x04d1....PIC
410 * 0x0500 - 0x057f....PM (DEFAULT_PMBASE)
411 * 0x0580 - 0x05bf....SB GPIO (DEFAULT_GPIOBASE)
412 * 0x05c0 - 0x05ff....SB GPIO cont. (mobile only)
413 * 0x0cf8 - 0x0cff....PCI
414 * 0x0cf9.............Reset Control
415 */
416
417 struct resource *res;
418
419 /* Get the normal PCI resources of this device. */
420 pci_dev_read_resources(dev);
421
422 /* Add an extra subtractive resource for both memory and I/O. */
423 res = new_resource(dev, IOINDEX_SUBTRACTIVE(0, 0));
424 res->base = 0;
425 res->size = 0x1000;
426 res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
427 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
428
429 res = new_resource(dev, IOINDEX_SUBTRACTIVE(1, 0));
430 res->base = 0xff800000;
431 res->size = 0x00800000; /* 8 MB for flash */
432 res->flags = IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE |
433 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
434
435 res = new_resource(dev, 3); /* IOAPIC */
436 res->base = IO_APIC_ADDR;
437 res->size = 0x00001000;
438 res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
439}
440
Arthur Heymanse798e6a2017-12-23 23:09:54 +0100441static const char *lpc_acpi_name(const struct device *dev)
442{
443 return "LPCB";
444}
445
Furquan Shaikh7536a392020-04-24 21:59:21 -0700446static void southbridge_fill_ssdt(const struct device *device)
Vladimir Serbinenko36fa5b82014-10-28 23:43:20 +0100447{
Kyösti Mälkkic70eed12018-05-22 02:18:00 +0300448 struct device *dev = pcidev_on_root(0x1f, 0);
Vladimir Serbinenko36fa5b82014-10-28 23:43:20 +0100449 config_t *chip = dev->chip_info;
450
451 intel_acpi_pcie_hotplug_generator(chip->pcie_hotplug_map, 8);
Arthur Heymanse798e6a2017-12-23 23:09:54 +0100452 intel_acpi_gen_def_acpi_pirq(device);
Vladimir Serbinenko36fa5b82014-10-28 23:43:20 +0100453}
Vladimir Serbinenko33769a52014-08-30 22:39:20 +0200454
Patrick Georgie72a8a32012-11-06 11:05:09 +0100455static struct device_operations device_ops = {
456 .read_resources = i82801ix_lpc_read_resources,
457 .set_resources = pci_dev_set_resources,
458 .enable_resources = pci_dev_enable_resources,
Vladimir Serbinenko33769a52014-08-30 22:39:20 +0200459 .write_acpi_tables = acpi_write_hpet,
Nico Huber68680dd2020-03-31 17:34:52 +0200460 .acpi_fill_ssdt = southbridge_fill_ssdt,
Arthur Heymanse798e6a2017-12-23 23:09:54 +0100461 .acpi_name = lpc_acpi_name,
Patrick Georgie72a8a32012-11-06 11:05:09 +0100462 .init = lpc_init,
Nico Huber51b75ae2019-03-14 16:02:05 +0100463 .scan_bus = scan_static_bus,
Angel Pons1fc0edd2020-05-31 00:03:28 +0200464 .ops_pci = &pci_dev_ops_pci,
Patrick Georgie72a8a32012-11-06 11:05:09 +0100465};
466
467static const unsigned short pci_device_ids[] = {
Felix Singer43b7f412022-03-07 04:34:52 +0100468 PCI_DID_INTEL_82801IH_LPC, /* ICH9DH */
469 PCI_DID_INTEL_82801IO_LPC, /* ICH9DO */
470 PCI_DID_INTEL_82801IR_LPC, /* ICH9R */
471 PCI_DID_INTEL_82801IEM_LPC, /* ICH9M-E */
472 PCI_DID_INTEL_82801IB_LPC, /* ICH9 */
473 PCI_DID_INTEL_82801IBM_LPC, /* ICH9M */
Patrick Georgie72a8a32012-11-06 11:05:09 +0100474 0
475};
476
477static const struct pci_driver ich9_lpc __pci_driver = {
478 .ops = &device_ops,
Felix Singer43b7f412022-03-07 04:34:52 +0100479 .vendor = PCI_VID_INTEL,
Patrick Georgie72a8a32012-11-06 11:05:09 +0100480 .devices = pci_device_ids,
481};