blob: 866ede9a504660f1ec68f2c07419fb41b3b18861 [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 u32 reg32;
31 volatile u32 *ioapic_index = (volatile u32 *)(IO_APIC_ADDR);
32 volatile u32 *ioapic_data = (volatile u32 *)(IO_APIC_ADDR + 0x10);
33
34 /* Enable IOAPIC. Keep APIC Range Select at zero. */
35 RCBA8(0x31ff) = 0x03;
36 /* We have to read 0x31ff back if bit0 changed. */
Paul Menzeld0299e42013-10-21 09:28:19 +020037 RCBA8(0x31ff);
Patrick Georgie72a8a32012-11-06 11:05:09 +010038
39 /* Lock maximum redirection entries (MRE), R/WO register. */
40 *ioapic_index = 0x01;
41 reg32 = *ioapic_data;
42 *ioapic_index = 0x01;
43 *ioapic_data = reg32;
44
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -080045 setup_ioapic(VIO_APIC_VADDR, 2); /* ICH7 code uses id 2. */
Patrick Georgie72a8a32012-11-06 11:05:09 +010046}
47
48static void i82801ix_enable_serial_irqs(struct device *dev)
49{
50 /* Set packet length and toggle silent mode bit for one frame. */
51 pci_write_config8(dev, D31F0_SERIRQ_CNTL,
52 (1 << 7) | (1 << 6) | ((21 - 17) << 2) | (0 << 0));
53}
54
55/* PIRQ[n]_ROUT[3:0] - PIRQ Routing Control
56 * 0x00 - 0000 = Reserved
57 * 0x01 - 0001 = Reserved
58 * 0x02 - 0010 = Reserved
59 * 0x03 - 0011 = IRQ3
60 * 0x04 - 0100 = IRQ4
61 * 0x05 - 0101 = IRQ5
62 * 0x06 - 0110 = IRQ6
63 * 0x07 - 0111 = IRQ7
64 * 0x08 - 1000 = Reserved
65 * 0x09 - 1001 = IRQ9
66 * 0x0A - 1010 = IRQ10
67 * 0x0B - 1011 = IRQ11
68 * 0x0C - 1100 = IRQ12
69 * 0x0D - 1101 = Reserved
70 * 0x0E - 1110 = IRQ14
71 * 0x0F - 1111 = IRQ15
72 * PIRQ[n]_ROUT[7] - PIRQ Routing Control
73 * 0x80 - The PIRQ is not routed.
74 */
75
Elyes HAOUAS8aa50732018-05-13 13:34:58 +020076static void i82801ix_pirq_init(struct device *dev)
Patrick Georgie72a8a32012-11-06 11:05:09 +010077{
Elyes HAOUAS8aa50732018-05-13 13:34:58 +020078 struct device *irq_dev;
Patrick Georgie72a8a32012-11-06 11:05:09 +010079 /* Get the chip configuration */
80 config_t *config = dev->chip_info;
81
82 pci_write_config8(dev, D31F0_PIRQA_ROUT, config->pirqa_routing);
83 pci_write_config8(dev, D31F0_PIRQB_ROUT, config->pirqb_routing);
84 pci_write_config8(dev, D31F0_PIRQC_ROUT, config->pirqc_routing);
85 pci_write_config8(dev, D31F0_PIRQD_ROUT, config->pirqd_routing);
86
87 pci_write_config8(dev, D31F0_PIRQE_ROUT, config->pirqe_routing);
88 pci_write_config8(dev, D31F0_PIRQF_ROUT, config->pirqf_routing);
89 pci_write_config8(dev, D31F0_PIRQG_ROUT, config->pirqg_routing);
90 pci_write_config8(dev, D31F0_PIRQH_ROUT, config->pirqh_routing);
91
92 /* Eric Biederman once said we should let the OS do this.
93 * I am not so sure anymore he was right.
94 */
95
Elyes HAOUASba28e8d2016-08-31 19:22:16 +020096 for (irq_dev = all_devices; irq_dev; irq_dev = irq_dev->next) {
Angel Ponsbcc2c722020-08-10 13:44:09 +020097 u8 int_pin = 0, int_line = 0;
Patrick Georgie72a8a32012-11-06 11:05:09 +010098
99 if (!irq_dev->enabled || irq_dev->path.type != DEVICE_PATH_PCI)
100 continue;
101
102 int_pin = pci_read_config8(irq_dev, PCI_INTERRUPT_PIN);
103
104 switch (int_pin) {
105 case 1: /* INTA# */ int_line = config->pirqa_routing; break;
106 case 2: /* INTB# */ int_line = config->pirqb_routing; break;
107 case 3: /* INTC# */ int_line = config->pirqc_routing; break;
108 case 4: /* INTD# */ int_line = config->pirqd_routing; break;
109 }
110
111 if (!int_line)
112 continue;
113
114 pci_write_config8(irq_dev, PCI_INTERRUPT_LINE, int_line);
115 }
116}
117
Elyes HAOUAS8aa50732018-05-13 13:34:58 +0200118static void i82801ix_gpi_routing(struct device *dev)
Patrick Georgie72a8a32012-11-06 11:05:09 +0100119{
120 /* Get the chip configuration */
121 config_t *config = dev->chip_info;
122 u32 reg32 = 0;
123
124 /* An array would be much nicer here, or some
125 * other method of doing this.
126 */
127 reg32 |= (config->gpi0_routing & 0x03) << 0;
128 reg32 |= (config->gpi1_routing & 0x03) << 2;
129 reg32 |= (config->gpi2_routing & 0x03) << 4;
130 reg32 |= (config->gpi3_routing & 0x03) << 6;
131 reg32 |= (config->gpi4_routing & 0x03) << 8;
132 reg32 |= (config->gpi5_routing & 0x03) << 10;
133 reg32 |= (config->gpi6_routing & 0x03) << 12;
134 reg32 |= (config->gpi7_routing & 0x03) << 14;
135 reg32 |= (config->gpi8_routing & 0x03) << 16;
136 reg32 |= (config->gpi9_routing & 0x03) << 18;
137 reg32 |= (config->gpi10_routing & 0x03) << 20;
138 reg32 |= (config->gpi11_routing & 0x03) << 22;
139 reg32 |= (config->gpi12_routing & 0x03) << 24;
140 reg32 |= (config->gpi13_routing & 0x03) << 26;
141 reg32 |= (config->gpi14_routing & 0x03) << 28;
142 reg32 |= (config->gpi15_routing & 0x03) << 30;
143
144 pci_write_config32(dev, D31F0_GPIO_ROUT, reg32);
145}
146
Elyes HAOUAS8aa50732018-05-13 13:34:58 +0200147static void i82801ix_power_options(struct device *dev)
Patrick Georgie72a8a32012-11-06 11:05:09 +0100148{
149 u8 reg8;
150 u16 reg16, pmbase;
151 u32 reg32;
152 const char *state;
153 /* Get the chip configuration */
154 config_t *config = dev->chip_info;
155
Patrick Georgie72a8a32012-11-06 11:05:09 +0100156 /* BIOS must program... */
Angel Ponsbcc2c722020-08-10 13:44:09 +0200157 pci_or_config32(dev, 0xac, (1 << 30) | (3 << 8));
Patrick Georgie72a8a32012-11-06 11:05:09 +0100158
159 /* Which state do we want to goto after g3 (power restored)?
160 * 0 == S0 Full On
161 * 1 == S5 Soft Off
162 *
163 * If the option is not existent (Laptops), use MAINBOARD_POWER_ON.
164 */
Angel Pons88dcb312021-04-26 17:10:28 +0200165 const unsigned int pwr_on = get_uint_option("power_on_after_fail", MAINBOARD_POWER_ON);
Patrick Georgie72a8a32012-11-06 11:05:09 +0100166
167 reg8 = pci_read_config8(dev, D31F0_GEN_PMCON_3);
168 reg8 &= 0xfe;
169 switch (pwr_on) {
170 case MAINBOARD_POWER_OFF:
171 reg8 |= 1;
172 state = "off";
173 break;
174 case MAINBOARD_POWER_ON:
175 reg8 &= ~1;
176 state = "on";
177 break;
178 case MAINBOARD_POWER_KEEP:
179 reg8 &= ~1;
180 state = "state keep";
181 break;
182 default:
183 state = "undefined";
184 }
185
186 reg8 |= (3 << 4); /* avoid #S4 assertions */
Elyes HAOUASdc413712021-02-07 20:54:53 +0100187 reg8 &= ~(1 << 3); /* minimum assertion is 1 to 2 RTCCLK */
Patrick Georgie72a8a32012-11-06 11:05:09 +0100188
189 pci_write_config8(dev, D31F0_GEN_PMCON_3, reg8);
190 printk(BIOS_INFO, "Set power %s after power failure.\n", state);
191
192 /* Set up NMI on errors. */
193 reg8 = inb(0x61);
194 reg8 &= 0x0f; /* Higher Nibble must be 0 */
195 reg8 &= ~(1 << 3); /* IOCHK# NMI Enable */
196 // reg8 &= ~(1 << 2); /* PCI SERR# Enable */
197 reg8 |= (1 << 2); /* PCI SERR# Disable for now */
198 outb(reg8, 0x61);
199
200 reg8 = inb(0x74); /* Read from 0x74 as 0x70 is write only. */
Angel Pons88dcb312021-04-26 17:10:28 +0200201 const unsigned int nmi_option = get_uint_option("nmi", NMI_OFF);
Patrick Georgie72a8a32012-11-06 11:05:09 +0100202 if (nmi_option) {
203 printk(BIOS_INFO, "NMI sources enabled.\n");
204 reg8 &= ~(1 << 7); /* Set NMI. */
205 } else {
206 printk(BIOS_INFO, "NMI sources disabled.\n");
Elyes HAOUAS9c5d4632018-04-26 22:21:21 +0200207 reg8 |= (1 << 7); /* Can't mask NMI from PCI-E and NMI_NOW */
Patrick Georgie72a8a32012-11-06 11:05:09 +0100208 }
209 outb(reg8, 0x70);
210
211 /* Enable CPU_SLP# and Intel Speedstep, set SMI# rate down */
212 reg16 = pci_read_config16(dev, D31F0_GEN_PMCON_1);
213 reg16 &= ~(3 << 0); // SMI# rate 1 minute
214 reg16 |= (1 << 2); // CLKRUN_EN - Mobile/Ultra only
215 reg16 |= (1 << 3); // Speedstep Enable - Mobile/Ultra only
216 reg16 |= (1 << 5); // CPUSLP_EN Desktop only
217
218 if (config->c4onc3_enable)
219 reg16 |= (1 << 7);
220
221 // another laptop wants this?
222 // reg16 &= ~(1 << 10); // BIOS_PCI_EXP_EN - Desktop/Mobile only
223 reg16 |= (1 << 10); // BIOS_PCI_EXP_EN - Desktop/Mobile only
Kyösti Mälkki94464472020-06-13 13:45:42 +0300224 if (CONFIG(DEBUG_PERIODIC_SMI))
225 reg16 |= (3 << 0); // Periodic SMI every 8s
Patrick Georgie72a8a32012-11-06 11:05:09 +0100226 if (config->c5_enable)
227 reg16 |= (1 << 11); /* Enable C5, C6 and PMSYNC# */
228 pci_write_config16(dev, D31F0_GEN_PMCON_1, reg16);
229
230 /* Set exit timings for C5/C6. */
231 if (config->c5_enable) {
232 reg8 = pci_read_config8(dev, D31F0_C5_EXIT_TIMING);
233 reg8 &= ~((7 << 3) | (7 << 0));
234 if (config->c6_enable)
235 reg8 |= (5 << 3) | (3 << 0); /* 38-44us PMSYNC# to STPCLK#,
236 95-102us DPRSTP# to STP_CPU# */
237 else
238 reg8 |= (0 << 3) | (1 << 0); /* 16-17us PMSYNC# to STPCLK#,
239 34-40us DPRSTP# to STP_CPU# */
240 pci_write_config8(dev, D31F0_C5_EXIT_TIMING, reg8);
241 }
242
243 // Set the board's GPI routing.
244 i82801ix_gpi_routing(dev);
245
246 pmbase = pci_read_config16(dev, 0x40) & 0xfffe;
247
248 outl(config->gpe0_en, pmbase + 0x28);
249 outw(config->alt_gp_smi_en, pmbase + 0x38);
250
251 /* Set up power management block and determine sleep mode */
252 reg16 = inw(pmbase + 0x00); /* PM1_STS */
253 outw(reg16, pmbase + 0x00); /* Clear status bits. At least bit11 (power
254 button override) must be cleared or SCI
255 will be constantly fired and OSPM must
256 not know about it (ACPI spec says to
257 ignore the bit). */
Patrick Georgie72a8a32012-11-06 11:05:09 +0100258
259 /* Set duty cycle for hardware throttling (defaults to 0x0: 50%). */
260 reg32 = inl(pmbase + 0x10);
261 reg32 &= ~(7 << 5);
262 reg32 |= (config->throttle_duty & 7) << 5;
263 outl(reg32, pmbase + 0x10);
264}
265
Elyes HAOUAS8aa50732018-05-13 13:34:58 +0200266static void i82801ix_configure_cstates(struct device *dev)
Patrick Georgie72a8a32012-11-06 11:05:09 +0100267{
Angel Pons67406472020-06-08 11:13:42 +0200268 // Enable Popup & Popdown
269 pci_or_config8(dev, D31F0_CxSTATE_CNF, (1 << 4) | (1 << 3) | (1 << 2));
Patrick Georgie72a8a32012-11-06 11:05:09 +0100270
271 // Set Deeper Sleep configuration to recommended values
Angel Pons67406472020-06-08 11:13:42 +0200272 // Deeper Sleep to Stop CPU: 34-40us
273 // Deeper Sleep to Sleep: 15us
274 pci_update_config8(dev, D31F0_C4TIMING_CNT, ~0x0f, (2 << 2) | (2 << 0));
Patrick Georgie72a8a32012-11-06 11:05:09 +0100275
276 /* We could enable slow-C4 exit here, if someone needs it? */
277}
278
279static void i82801ix_rtc_init(struct device *dev)
280{
281 u8 reg8;
282 int rtc_failed;
283
284 reg8 = pci_read_config8(dev, D31F0_GEN_PMCON_3);
285 rtc_failed = reg8 & RTC_BATTERY_DEAD;
286 if (rtc_failed) {
287 reg8 &= ~RTC_BATTERY_DEAD;
288 pci_write_config8(dev, D31F0_GEN_PMCON_3, reg8);
289 }
290 printk(BIOS_DEBUG, "rtc_failed = 0x%x\n", rtc_failed);
291
Gabe Blackb3f08c62014-04-30 17:12:25 -0700292 cmos_init(rtc_failed);
Patrick Georgie72a8a32012-11-06 11:05:09 +0100293}
294
295static void enable_hpet(void)
296{
297 u32 reg32;
298
299 /* Move HPET to default address 0xfed00000 and enable it */
300 reg32 = RCBA32(RCBA_HPTC);
301 reg32 |= (1 << 7); // HPET Address Enable
302 reg32 &= ~(3 << 0);
303 RCBA32(RCBA_HPTC) = reg32;
304}
305
306static void enable_clock_gating(void)
307{
308 u32 reg32;
309
310 /* Enable DMI dynamic clock gating. */
311 RCBA32(RCBA_DMIC) |= 3;
312
313 /* Enable Clock Gating for most devices. */
314 reg32 = RCBA32(RCBA_CG);
315 reg32 |= (1 << 31); /* LPC dynamic clock gating */
316 /* USB UHCI dynamic clock gating: */
317 reg32 |= (1 << 29) | (1 << 28);
318 /* SATA dynamic clock gating [0-3]: */
319 reg32 |= (1 << 27) | (1 << 26) | (1 << 25) | (1 << 24);
320 reg32 |= (1 << 23); /* LAN static clock gating (if LAN disabled) */
321 reg32 |= (1 << 22); /* HD audio dynamic clock gating */
322 reg32 &= ~(1 << 21); /* No HD audio static clock gating */
323 reg32 &= ~(1 << 20); /* No USB EHCI static clock gating */
324 reg32 |= (1 << 19); /* USB EHCI dynamic clock gating */
325 /* More SATA dynamic clock gating [4-5]: */
326 reg32 |= (1 << 18) | (1 << 17);
327 reg32 |= (1 << 16); /* PCI dynamic clock gating */
328 /* PCIe, DMI dynamic clock gating: */
329 reg32 |= (1 << 4) | (1 << 3) | (1 << 2) | (1 << 1);
330 reg32 |= (1 << 0); /* PCIe root port static clock gating */
331 RCBA32(RCBA_CG) = reg32;
332
333 /* Enable SPI dynamic clock gating. */
334 RCBA32(0x38c0) |= 7;
335}
336
Kyösti Mälkki6feb4da2019-07-13 17:28:37 +0300337static void i82801ix_set_acpi_mode(struct device *dev)
Patrick Georgie72a8a32012-11-06 11:05:09 +0100338{
Kyösti Mälkkiad882c32020-06-02 05:05:30 +0300339 if (!acpi_is_wakeup_s3()) {
340 apm_control(APM_CNT_ACPI_DISABLE);
341 } else {
342 apm_control(APM_CNT_ACPI_ENABLE);
Patrick Georgie72a8a32012-11-06 11:05:09 +0100343 }
Patrick Georgie72a8a32012-11-06 11:05:09 +0100344}
Patrick Georgie72a8a32012-11-06 11:05:09 +0100345
346static void lpc_init(struct device *dev)
347{
Elyes HAOUASbfc255a2020-03-07 13:05:14 +0100348 printk(BIOS_DEBUG, "i82801ix: %s\n", __func__);
Patrick Georgie72a8a32012-11-06 11:05:09 +0100349
Patrick Georgie72a8a32012-11-06 11:05:09 +0100350 /* IO APIC initialization. */
351 i82801ix_enable_apic(dev);
352
353 i82801ix_enable_serial_irqs(dev);
354
355 /* Setup the PIRQ. */
356 i82801ix_pirq_init(dev);
357
358 /* Setup power options. */
359 i82801ix_power_options(dev);
360
361 /* Configure Cx state registers */
362 if (LPC_IS_MOBILE(dev))
363 i82801ix_configure_cstates(dev);
364
365 /* Initialize the real time clock. */
366 i82801ix_rtc_init(dev);
367
368 /* Initialize ISA DMA. */
369 isa_dma_init();
370
371 /* Initialize the High Precision Event Timers, if present. */
372 enable_hpet();
373
374 /* Initialize Clock Gating */
375 enable_clock_gating();
376
377 setup_i8259();
378
379 /* The OS should do this? */
380 /* Interrupt 9 should be level triggered (SCI) */
381 i8259_configure_irq_trigger(9, 1);
382
Kyösti Mälkki44da9e72019-10-09 12:32:16 +0300383 i82801ix_set_acpi_mode(dev);
Kyösti Mälkki6feb4da2019-07-13 17:28:37 +0300384
385 /* Don't allow evil boot loaders, kernels, or
386 * userspace applications to deceive us:
387 */
Kyösti Mälkkicd0b67b2019-10-09 07:52:40 +0300388 if (CONFIG(HAVE_SMI_HANDLER) && !CONFIG(PARALLEL_MP))
Kyösti Mälkki6feb4da2019-07-13 17:28:37 +0300389 aseg_smm_lock();
Patrick Georgie72a8a32012-11-06 11:05:09 +0100390}
391
Elyes HAOUAS8aa50732018-05-13 13:34:58 +0200392static void i82801ix_lpc_read_resources(struct device *dev)
Patrick Georgie72a8a32012-11-06 11:05:09 +0100393{
394 /*
395 * I/O Resources
396 *
397 * 0x0000 - 0x000f....ISA DMA
398 * 0x0010 - 0x001f....ISA DMA aliases
399 * 0x0020 ~ 0x003d....PIC
400 * 0x002e - 0x002f....Maybe Super I/O
401 * 0x0040 - 0x0043....Timer
402 * 0x004e - 0x004f....Maybe Super I/O
403 * 0x0050 - 0x0053....Timer aliases
404 * 0x0061.............NMI_SC
405 * 0x0070.............NMI_EN (readable in alternative access mode)
406 * 0x0070 - 0x0077....RTC
407 * 0x0080 - 0x008f....ISA DMA
408 * 0x0090 ~ 0x009f....ISA DMA aliases
409 * 0x0092.............Fast A20 and Init
410 * 0x00a0 ~ 0x00bd....PIC
411 * 0x00b2 - 0x00b3....APM
412 * 0x00c0 ~ 0x00de....ISA DMA
413 * 0x00c1 ~ 0x00df....ISA DMA aliases
414 * 0x00f0.............Coprocessor Error
Angel Ponsb21bffa2020-07-03 01:02:28 +0200415 * (0x0400-0x041f)....SMBus (CONFIG_FIXED_SMBUS_IO_BASE, during raminit)
Patrick Georgie72a8a32012-11-06 11:05:09 +0100416 * 0x04d0 - 0x04d1....PIC
417 * 0x0500 - 0x057f....PM (DEFAULT_PMBASE)
418 * 0x0580 - 0x05bf....SB GPIO (DEFAULT_GPIOBASE)
419 * 0x05c0 - 0x05ff....SB GPIO cont. (mobile only)
420 * 0x0cf8 - 0x0cff....PCI
421 * 0x0cf9.............Reset Control
422 */
423
424 struct resource *res;
425
426 /* Get the normal PCI resources of this device. */
427 pci_dev_read_resources(dev);
428
429 /* Add an extra subtractive resource for both memory and I/O. */
430 res = new_resource(dev, IOINDEX_SUBTRACTIVE(0, 0));
431 res->base = 0;
432 res->size = 0x1000;
433 res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
434 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
435
436 res = new_resource(dev, IOINDEX_SUBTRACTIVE(1, 0));
437 res->base = 0xff800000;
438 res->size = 0x00800000; /* 8 MB for flash */
439 res->flags = IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE |
440 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
441
442 res = new_resource(dev, 3); /* IOAPIC */
443 res->base = IO_APIC_ADDR;
444 res->size = 0x00001000;
445 res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
446}
447
Arthur Heymanse798e6a2017-12-23 23:09:54 +0100448static const char *lpc_acpi_name(const struct device *dev)
449{
450 return "LPCB";
451}
452
Furquan Shaikh7536a392020-04-24 21:59:21 -0700453static void southbridge_fill_ssdt(const struct device *device)
Vladimir Serbinenko36fa5b82014-10-28 23:43:20 +0100454{
Kyösti Mälkkic70eed12018-05-22 02:18:00 +0300455 struct device *dev = pcidev_on_root(0x1f, 0);
Vladimir Serbinenko36fa5b82014-10-28 23:43:20 +0100456 config_t *chip = dev->chip_info;
457
458 intel_acpi_pcie_hotplug_generator(chip->pcie_hotplug_map, 8);
Arthur Heymanse798e6a2017-12-23 23:09:54 +0100459 intel_acpi_gen_def_acpi_pirq(device);
Vladimir Serbinenko36fa5b82014-10-28 23:43:20 +0100460}
Vladimir Serbinenko33769a52014-08-30 22:39:20 +0200461
Patrick Georgie72a8a32012-11-06 11:05:09 +0100462static struct device_operations device_ops = {
463 .read_resources = i82801ix_lpc_read_resources,
464 .set_resources = pci_dev_set_resources,
465 .enable_resources = pci_dev_enable_resources,
Vladimir Serbinenko33769a52014-08-30 22:39:20 +0200466 .write_acpi_tables = acpi_write_hpet,
Nico Huber68680dd2020-03-31 17:34:52 +0200467 .acpi_fill_ssdt = southbridge_fill_ssdt,
Arthur Heymanse798e6a2017-12-23 23:09:54 +0100468 .acpi_name = lpc_acpi_name,
Patrick Georgie72a8a32012-11-06 11:05:09 +0100469 .init = lpc_init,
Nico Huber51b75ae2019-03-14 16:02:05 +0100470 .scan_bus = scan_static_bus,
Angel Pons1fc0edd2020-05-31 00:03:28 +0200471 .ops_pci = &pci_dev_ops_pci,
Patrick Georgie72a8a32012-11-06 11:05:09 +0100472};
473
474static const unsigned short pci_device_ids[] = {
Felix Singer7f8b0cd82019-11-10 11:04:08 +0100475 PCI_DEVICE_ID_INTEL_82801IH_LPC, /* ICH9DH */
476 PCI_DEVICE_ID_INTEL_82801IO_LPC, /* ICH9DO */
477 PCI_DEVICE_ID_INTEL_82801IR_LPC, /* ICH9R */
478 PCI_DEVICE_ID_INTEL_82801IEM_LPC, /* ICH9M-E */
479 PCI_DEVICE_ID_INTEL_82801IB_LPC, /* ICH9 */
480 PCI_DEVICE_ID_INTEL_82801IBM_LPC, /* ICH9M */
Patrick Georgie72a8a32012-11-06 11:05:09 +0100481 0
482};
483
484static const struct pci_driver ich9_lpc __pci_driver = {
485 .ops = &device_ops,
486 .vendor = PCI_VENDOR_ID_INTEL,
487 .devices = pci_device_ids,
488};