blob: d897130e42224fd8890b7f7ccaed3eb9d6c91708 [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
Arthur Heymans98c92572022-11-07 11:39:58 +01003#include <cpu/intel/speedstep.h>
Patrick Georgie72a8a32012-11-06 11:05:09 +01004#include <console/console.h>
5#include <device/device.h>
6#include <device/pci.h>
7#include <device/pci_ids.h>
Kyösti Mälkkicbf95712020-01-05 08:05:45 +02008#include <option.h>
Patrick Georgie72a8a32012-11-06 11:05:09 +01009#include <pc80/mc146818rtc.h>
10#include <pc80/isa-dma.h>
11#include <pc80/i8259.h>
12#include <arch/io.h>
Kyösti Mälkkif1b58b72019-03-01 13:43:02 +020013#include <device/pci_ops.h>
Patrick Georgie72a8a32012-11-06 11:05:09 +010014#include <arch/ioapic.h>
Furquan Shaikh76cedd22020-05-02 10:24:23 -070015#include <acpi/acpi.h>
Patrick Georgie72a8a32012-11-06 11:05:09 +010016#include <cpu/x86/smm.h>
Furquan Shaikh76cedd22020-05-02 10:24:23 -070017#include <acpi/acpigen.h>
Kyösti Mälkki12b121c2019-08-18 16:33:39 +030018#include "chip.h"
Patrick Georgie72a8a32012-11-06 11:05:09 +010019#include "i82801ix.h"
Vladimir Serbinenko36fa5b82014-10-28 23:43:20 +010020#include <southbridge/intel/common/pciehp.h>
Angel Ponse1a616c2020-06-21 17:02:43 +020021#include <southbridge/intel/common/pmutil.h>
Arthur Heymanse798e6a2017-12-23 23:09:54 +010022#include <southbridge/intel/common/acpi_pirq_gen.h>
Tim Wawrzynczakf62c4942021-02-26 10:30:52 -070023#include <southbridge/intel/common/rcba_pirq.h>
Patrick Georgie72a8a32012-11-06 11:05:09 +010024
25#define NMI_OFF 0
26
Patrick Georgie72a8a32012-11-06 11:05:09 +010027typedef struct southbridge_intel_i82801ix_config config_t;
28
29static void i82801ix_enable_apic(struct device *dev)
30{
Patrick Georgie72a8a32012-11-06 11:05:09 +010031 /* Enable IOAPIC. Keep APIC Range Select at zero. */
32 RCBA8(0x31ff) = 0x03;
33 /* We have to read 0x31ff back if bit0 changed. */
Paul Menzeld0299e42013-10-21 09:28:19 +020034 RCBA8(0x31ff);
Patrick Georgie72a8a32012-11-06 11:05:09 +010035
36 /* Lock maximum redirection entries (MRE), R/WO register. */
Kyösti Mälkki04a40372021-06-06 08:04:28 +030037 ioapic_lock_max_vectors(VIO_APIC_VADDR);
Patrick Georgie72a8a32012-11-06 11:05:09 +010038
Kyösti Mälkkid1653572021-06-08 11:31:19 +030039 register_new_ioapic_gsi0(VIO_APIC_VADDR);
Patrick Georgie72a8a32012-11-06 11:05:09 +010040}
41
42static void i82801ix_enable_serial_irqs(struct device *dev)
43{
44 /* Set packet length and toggle silent mode bit for one frame. */
45 pci_write_config8(dev, D31F0_SERIRQ_CNTL,
46 (1 << 7) | (1 << 6) | ((21 - 17) << 2) | (0 << 0));
47}
48
49/* PIRQ[n]_ROUT[3:0] - PIRQ Routing Control
50 * 0x00 - 0000 = Reserved
51 * 0x01 - 0001 = Reserved
52 * 0x02 - 0010 = Reserved
53 * 0x03 - 0011 = IRQ3
54 * 0x04 - 0100 = IRQ4
55 * 0x05 - 0101 = IRQ5
56 * 0x06 - 0110 = IRQ6
57 * 0x07 - 0111 = IRQ7
58 * 0x08 - 1000 = Reserved
59 * 0x09 - 1001 = IRQ9
60 * 0x0A - 1010 = IRQ10
61 * 0x0B - 1011 = IRQ11
62 * 0x0C - 1100 = IRQ12
63 * 0x0D - 1101 = Reserved
64 * 0x0E - 1110 = IRQ14
65 * 0x0F - 1111 = IRQ15
66 * PIRQ[n]_ROUT[7] - PIRQ Routing Control
67 * 0x80 - The PIRQ is not routed.
68 */
69
Elyes HAOUAS8aa50732018-05-13 13:34:58 +020070static void i82801ix_pirq_init(struct device *dev)
Patrick Georgie72a8a32012-11-06 11:05:09 +010071{
Elyes HAOUAS8aa50732018-05-13 13:34:58 +020072 struct device *irq_dev;
Patrick Georgie72a8a32012-11-06 11:05:09 +010073 /* Get the chip configuration */
74 config_t *config = dev->chip_info;
75
76 pci_write_config8(dev, D31F0_PIRQA_ROUT, config->pirqa_routing);
77 pci_write_config8(dev, D31F0_PIRQB_ROUT, config->pirqb_routing);
78 pci_write_config8(dev, D31F0_PIRQC_ROUT, config->pirqc_routing);
79 pci_write_config8(dev, D31F0_PIRQD_ROUT, config->pirqd_routing);
80
81 pci_write_config8(dev, D31F0_PIRQE_ROUT, config->pirqe_routing);
82 pci_write_config8(dev, D31F0_PIRQF_ROUT, config->pirqf_routing);
83 pci_write_config8(dev, D31F0_PIRQG_ROUT, config->pirqg_routing);
84 pci_write_config8(dev, D31F0_PIRQH_ROUT, config->pirqh_routing);
85
86 /* Eric Biederman once said we should let the OS do this.
87 * I am not so sure anymore he was right.
88 */
89
Elyes HAOUASba28e8d2016-08-31 19:22:16 +020090 for (irq_dev = all_devices; irq_dev; irq_dev = irq_dev->next) {
Angel Ponsbcc2c722020-08-10 13:44:09 +020091 u8 int_pin = 0, int_line = 0;
Patrick Georgie72a8a32012-11-06 11:05:09 +010092
Fabio Aiutod835da92022-09-30 11:25:28 +020093 if (!is_enabled_pci(irq_dev))
Patrick Georgie72a8a32012-11-06 11:05:09 +010094 continue;
95
96 int_pin = pci_read_config8(irq_dev, PCI_INTERRUPT_PIN);
97
98 switch (int_pin) {
99 case 1: /* INTA# */ int_line = config->pirqa_routing; break;
100 case 2: /* INTB# */ int_line = config->pirqb_routing; break;
101 case 3: /* INTC# */ int_line = config->pirqc_routing; break;
102 case 4: /* INTD# */ int_line = config->pirqd_routing; break;
103 }
104
105 if (!int_line)
106 continue;
107
108 pci_write_config8(irq_dev, PCI_INTERRUPT_LINE, int_line);
109 }
110}
111
Elyes HAOUAS8aa50732018-05-13 13:34:58 +0200112static void i82801ix_gpi_routing(struct device *dev)
Patrick Georgie72a8a32012-11-06 11:05:09 +0100113{
114 /* Get the chip configuration */
115 config_t *config = dev->chip_info;
116 u32 reg32 = 0;
117
118 /* An array would be much nicer here, or some
119 * other method of doing this.
120 */
121 reg32 |= (config->gpi0_routing & 0x03) << 0;
122 reg32 |= (config->gpi1_routing & 0x03) << 2;
123 reg32 |= (config->gpi2_routing & 0x03) << 4;
124 reg32 |= (config->gpi3_routing & 0x03) << 6;
125 reg32 |= (config->gpi4_routing & 0x03) << 8;
126 reg32 |= (config->gpi5_routing & 0x03) << 10;
127 reg32 |= (config->gpi6_routing & 0x03) << 12;
128 reg32 |= (config->gpi7_routing & 0x03) << 14;
129 reg32 |= (config->gpi8_routing & 0x03) << 16;
130 reg32 |= (config->gpi9_routing & 0x03) << 18;
131 reg32 |= (config->gpi10_routing & 0x03) << 20;
132 reg32 |= (config->gpi11_routing & 0x03) << 22;
133 reg32 |= (config->gpi12_routing & 0x03) << 24;
134 reg32 |= (config->gpi13_routing & 0x03) << 26;
135 reg32 |= (config->gpi14_routing & 0x03) << 28;
136 reg32 |= (config->gpi15_routing & 0x03) << 30;
137
138 pci_write_config32(dev, D31F0_GPIO_ROUT, reg32);
139}
140
Arthur Heymans98c92572022-11-07 11:39:58 +0100141bool southbridge_support_c5(void)
142{
143 struct device *lpc_dev = __pci_0_1f_0;
144 struct southbridge_intel_i82801ix_config *config = lpc_dev->chip_info;
145 return config->c5_enable == 1;
146}
147
148bool southbridge_support_c6(void)
149{
150 struct device *lpc_dev = __pci_0_1f_0;
151 struct southbridge_intel_i82801ix_config *config = lpc_dev->chip_info;
152 return config->c6_enable == 1;
153}
154
Elyes HAOUAS8aa50732018-05-13 13:34:58 +0200155static void i82801ix_power_options(struct device *dev)
Patrick Georgie72a8a32012-11-06 11:05:09 +0100156{
157 u8 reg8;
158 u16 reg16, pmbase;
159 u32 reg32;
160 const char *state;
161 /* Get the chip configuration */
162 config_t *config = dev->chip_info;
163
Patrick Georgie72a8a32012-11-06 11:05:09 +0100164 /* BIOS must program... */
Angel Ponsbcc2c722020-08-10 13:44:09 +0200165 pci_or_config32(dev, 0xac, (1 << 30) | (3 << 8));
Patrick Georgie72a8a32012-11-06 11:05:09 +0100166
167 /* Which state do we want to goto after g3 (power restored)?
168 * 0 == S0 Full On
169 * 1 == S5 Soft Off
170 *
171 * If the option is not existent (Laptops), use MAINBOARD_POWER_ON.
172 */
Angel Pons88dcb312021-04-26 17:10:28 +0200173 const unsigned int pwr_on = get_uint_option("power_on_after_fail", MAINBOARD_POWER_ON);
Patrick Georgie72a8a32012-11-06 11:05:09 +0100174
175 reg8 = pci_read_config8(dev, D31F0_GEN_PMCON_3);
176 reg8 &= 0xfe;
177 switch (pwr_on) {
178 case MAINBOARD_POWER_OFF:
179 reg8 |= 1;
180 state = "off";
181 break;
182 case MAINBOARD_POWER_ON:
183 reg8 &= ~1;
184 state = "on";
185 break;
186 case MAINBOARD_POWER_KEEP:
187 reg8 &= ~1;
188 state = "state keep";
189 break;
190 default:
191 state = "undefined";
192 }
193
194 reg8 |= (3 << 4); /* avoid #S4 assertions */
Elyes HAOUASdc413712021-02-07 20:54:53 +0100195 reg8 &= ~(1 << 3); /* minimum assertion is 1 to 2 RTCCLK */
Patrick Georgie72a8a32012-11-06 11:05:09 +0100196
197 pci_write_config8(dev, D31F0_GEN_PMCON_3, reg8);
198 printk(BIOS_INFO, "Set power %s after power failure.\n", state);
199
200 /* Set up NMI on errors. */
201 reg8 = inb(0x61);
202 reg8 &= 0x0f; /* Higher Nibble must be 0 */
203 reg8 &= ~(1 << 3); /* IOCHK# NMI Enable */
204 // reg8 &= ~(1 << 2); /* PCI SERR# Enable */
205 reg8 |= (1 << 2); /* PCI SERR# Disable for now */
206 outb(reg8, 0x61);
207
208 reg8 = inb(0x74); /* Read from 0x74 as 0x70 is write only. */
Angel Pons88dcb312021-04-26 17:10:28 +0200209 const unsigned int nmi_option = get_uint_option("nmi", NMI_OFF);
Patrick Georgie72a8a32012-11-06 11:05:09 +0100210 if (nmi_option) {
211 printk(BIOS_INFO, "NMI sources enabled.\n");
212 reg8 &= ~(1 << 7); /* Set NMI. */
213 } else {
214 printk(BIOS_INFO, "NMI sources disabled.\n");
Elyes HAOUAS9c5d4632018-04-26 22:21:21 +0200215 reg8 |= (1 << 7); /* Can't mask NMI from PCI-E and NMI_NOW */
Patrick Georgie72a8a32012-11-06 11:05:09 +0100216 }
217 outb(reg8, 0x70);
218
219 /* Enable CPU_SLP# and Intel Speedstep, set SMI# rate down */
220 reg16 = pci_read_config16(dev, D31F0_GEN_PMCON_1);
221 reg16 &= ~(3 << 0); // SMI# rate 1 minute
222 reg16 |= (1 << 2); // CLKRUN_EN - Mobile/Ultra only
223 reg16 |= (1 << 3); // Speedstep Enable - Mobile/Ultra only
224 reg16 |= (1 << 5); // CPUSLP_EN Desktop only
225
226 if (config->c4onc3_enable)
227 reg16 |= (1 << 7);
228
229 // another laptop wants this?
230 // reg16 &= ~(1 << 10); // BIOS_PCI_EXP_EN - Desktop/Mobile only
231 reg16 |= (1 << 10); // BIOS_PCI_EXP_EN - Desktop/Mobile only
Kyösti Mälkki94464472020-06-13 13:45:42 +0300232 if (CONFIG(DEBUG_PERIODIC_SMI))
233 reg16 |= (3 << 0); // Periodic SMI every 8s
Arthur Heymans98c92572022-11-07 11:39:58 +0100234 if (southbridge_support_c5())
Patrick Georgie72a8a32012-11-06 11:05:09 +0100235 reg16 |= (1 << 11); /* Enable C5, C6 and PMSYNC# */
236 pci_write_config16(dev, D31F0_GEN_PMCON_1, reg16);
237
238 /* Set exit timings for C5/C6. */
Arthur Heymans98c92572022-11-07 11:39:58 +0100239 if (southbridge_support_c5()) {
Patrick Georgie72a8a32012-11-06 11:05:09 +0100240 reg8 = pci_read_config8(dev, D31F0_C5_EXIT_TIMING);
241 reg8 &= ~((7 << 3) | (7 << 0));
Arthur Heymans98c92572022-11-07 11:39:58 +0100242 if (southbridge_support_c6())
Patrick Georgie72a8a32012-11-06 11:05:09 +0100243 reg8 |= (5 << 3) | (3 << 0); /* 38-44us PMSYNC# to STPCLK#,
244 95-102us DPRSTP# to STP_CPU# */
245 else
246 reg8 |= (0 << 3) | (1 << 0); /* 16-17us PMSYNC# to STPCLK#,
247 34-40us DPRSTP# to STP_CPU# */
248 pci_write_config8(dev, D31F0_C5_EXIT_TIMING, reg8);
249 }
250
251 // Set the board's GPI routing.
252 i82801ix_gpi_routing(dev);
253
254 pmbase = pci_read_config16(dev, 0x40) & 0xfffe;
255
256 outl(config->gpe0_en, pmbase + 0x28);
257 outw(config->alt_gp_smi_en, pmbase + 0x38);
258
259 /* Set up power management block and determine sleep mode */
260 reg16 = inw(pmbase + 0x00); /* PM1_STS */
261 outw(reg16, pmbase + 0x00); /* Clear status bits. At least bit11 (power
262 button override) must be cleared or SCI
263 will be constantly fired and OSPM must
264 not know about it (ACPI spec says to
265 ignore the bit). */
Patrick Georgie72a8a32012-11-06 11:05:09 +0100266
267 /* Set duty cycle for hardware throttling (defaults to 0x0: 50%). */
268 reg32 = inl(pmbase + 0x10);
269 reg32 &= ~(7 << 5);
270 reg32 |= (config->throttle_duty & 7) << 5;
271 outl(reg32, pmbase + 0x10);
272}
273
Elyes HAOUAS8aa50732018-05-13 13:34:58 +0200274static void i82801ix_configure_cstates(struct device *dev)
Patrick Georgie72a8a32012-11-06 11:05:09 +0100275{
Angel Pons67406472020-06-08 11:13:42 +0200276 // Enable Popup & Popdown
277 pci_or_config8(dev, D31F0_CxSTATE_CNF, (1 << 4) | (1 << 3) | (1 << 2));
Patrick Georgie72a8a32012-11-06 11:05:09 +0100278
279 // Set Deeper Sleep configuration to recommended values
Angel Pons67406472020-06-08 11:13:42 +0200280 // Deeper Sleep to Stop CPU: 34-40us
281 // Deeper Sleep to Sleep: 15us
282 pci_update_config8(dev, D31F0_C4TIMING_CNT, ~0x0f, (2 << 2) | (2 << 0));
Patrick Georgie72a8a32012-11-06 11:05:09 +0100283
284 /* We could enable slow-C4 exit here, if someone needs it? */
285}
286
287static void i82801ix_rtc_init(struct device *dev)
288{
289 u8 reg8;
290 int rtc_failed;
291
292 reg8 = pci_read_config8(dev, D31F0_GEN_PMCON_3);
293 rtc_failed = reg8 & RTC_BATTERY_DEAD;
294 if (rtc_failed) {
295 reg8 &= ~RTC_BATTERY_DEAD;
296 pci_write_config8(dev, D31F0_GEN_PMCON_3, reg8);
297 }
298 printk(BIOS_DEBUG, "rtc_failed = 0x%x\n", rtc_failed);
299
Gabe Blackb3f08c62014-04-30 17:12:25 -0700300 cmos_init(rtc_failed);
Patrick Georgie72a8a32012-11-06 11:05:09 +0100301}
302
303static void enable_hpet(void)
304{
305 u32 reg32;
306
307 /* Move HPET to default address 0xfed00000 and enable it */
308 reg32 = RCBA32(RCBA_HPTC);
309 reg32 |= (1 << 7); // HPET Address Enable
310 reg32 &= ~(3 << 0);
311 RCBA32(RCBA_HPTC) = reg32;
312}
313
314static void enable_clock_gating(void)
315{
316 u32 reg32;
317
318 /* Enable DMI dynamic clock gating. */
319 RCBA32(RCBA_DMIC) |= 3;
320
321 /* Enable Clock Gating for most devices. */
322 reg32 = RCBA32(RCBA_CG);
323 reg32 |= (1 << 31); /* LPC dynamic clock gating */
324 /* USB UHCI dynamic clock gating: */
325 reg32 |= (1 << 29) | (1 << 28);
326 /* SATA dynamic clock gating [0-3]: */
327 reg32 |= (1 << 27) | (1 << 26) | (1 << 25) | (1 << 24);
328 reg32 |= (1 << 23); /* LAN static clock gating (if LAN disabled) */
329 reg32 |= (1 << 22); /* HD audio dynamic clock gating */
330 reg32 &= ~(1 << 21); /* No HD audio static clock gating */
331 reg32 &= ~(1 << 20); /* No USB EHCI static clock gating */
332 reg32 |= (1 << 19); /* USB EHCI dynamic clock gating */
333 /* More SATA dynamic clock gating [4-5]: */
334 reg32 |= (1 << 18) | (1 << 17);
335 reg32 |= (1 << 16); /* PCI dynamic clock gating */
336 /* PCIe, DMI dynamic clock gating: */
337 reg32 |= (1 << 4) | (1 << 3) | (1 << 2) | (1 << 1);
338 reg32 |= (1 << 0); /* PCIe root port static clock gating */
339 RCBA32(RCBA_CG) = reg32;
340
341 /* Enable SPI dynamic clock gating. */
342 RCBA32(0x38c0) |= 7;
343}
344
Kyösti Mälkki6feb4da2019-07-13 17:28:37 +0300345static void i82801ix_set_acpi_mode(struct device *dev)
Patrick Georgie72a8a32012-11-06 11:05:09 +0100346{
Kyösti Mälkkiad882c32020-06-02 05:05:30 +0300347 if (!acpi_is_wakeup_s3()) {
348 apm_control(APM_CNT_ACPI_DISABLE);
349 } else {
350 apm_control(APM_CNT_ACPI_ENABLE);
Patrick Georgie72a8a32012-11-06 11:05:09 +0100351 }
Patrick Georgie72a8a32012-11-06 11:05:09 +0100352}
Patrick Georgie72a8a32012-11-06 11:05:09 +0100353
354static void lpc_init(struct device *dev)
355{
Elyes HAOUASbfc255a2020-03-07 13:05:14 +0100356 printk(BIOS_DEBUG, "i82801ix: %s\n", __func__);
Patrick Georgie72a8a32012-11-06 11:05:09 +0100357
Patrick Georgie72a8a32012-11-06 11:05:09 +0100358 /* IO APIC initialization. */
359 i82801ix_enable_apic(dev);
360
361 i82801ix_enable_serial_irqs(dev);
362
363 /* Setup the PIRQ. */
364 i82801ix_pirq_init(dev);
365
366 /* Setup power options. */
367 i82801ix_power_options(dev);
368
369 /* Configure Cx state registers */
370 if (LPC_IS_MOBILE(dev))
371 i82801ix_configure_cstates(dev);
372
373 /* Initialize the real time clock. */
374 i82801ix_rtc_init(dev);
375
376 /* Initialize ISA DMA. */
377 isa_dma_init();
378
379 /* Initialize the High Precision Event Timers, if present. */
380 enable_hpet();
381
382 /* Initialize Clock Gating */
383 enable_clock_gating();
384
385 setup_i8259();
386
387 /* The OS should do this? */
388 /* Interrupt 9 should be level triggered (SCI) */
389 i8259_configure_irq_trigger(9, 1);
390
Kyösti Mälkki44da9e72019-10-09 12:32:16 +0300391 i82801ix_set_acpi_mode(dev);
Patrick Georgie72a8a32012-11-06 11:05:09 +0100392}
393
Elyes HAOUAS8aa50732018-05-13 13:34:58 +0200394static void i82801ix_lpc_read_resources(struct device *dev)
Patrick Georgie72a8a32012-11-06 11:05:09 +0100395{
396 /*
397 * I/O Resources
398 *
399 * 0x0000 - 0x000f....ISA DMA
400 * 0x0010 - 0x001f....ISA DMA aliases
401 * 0x0020 ~ 0x003d....PIC
402 * 0x002e - 0x002f....Maybe Super I/O
403 * 0x0040 - 0x0043....Timer
404 * 0x004e - 0x004f....Maybe Super I/O
405 * 0x0050 - 0x0053....Timer aliases
406 * 0x0061.............NMI_SC
407 * 0x0070.............NMI_EN (readable in alternative access mode)
408 * 0x0070 - 0x0077....RTC
409 * 0x0080 - 0x008f....ISA DMA
410 * 0x0090 ~ 0x009f....ISA DMA aliases
411 * 0x0092.............Fast A20 and Init
412 * 0x00a0 ~ 0x00bd....PIC
413 * 0x00b2 - 0x00b3....APM
414 * 0x00c0 ~ 0x00de....ISA DMA
415 * 0x00c1 ~ 0x00df....ISA DMA aliases
416 * 0x00f0.............Coprocessor Error
Angel Ponsb21bffa2020-07-03 01:02:28 +0200417 * (0x0400-0x041f)....SMBus (CONFIG_FIXED_SMBUS_IO_BASE, during raminit)
Patrick Georgie72a8a32012-11-06 11:05:09 +0100418 * 0x04d0 - 0x04d1....PIC
419 * 0x0500 - 0x057f....PM (DEFAULT_PMBASE)
420 * 0x0580 - 0x05bf....SB GPIO (DEFAULT_GPIOBASE)
421 * 0x05c0 - 0x05ff....SB GPIO cont. (mobile only)
422 * 0x0cf8 - 0x0cff....PCI
423 * 0x0cf9.............Reset Control
424 */
425
426 struct resource *res;
427
428 /* Get the normal PCI resources of this device. */
429 pci_dev_read_resources(dev);
430
431 /* Add an extra subtractive resource for both memory and I/O. */
432 res = new_resource(dev, IOINDEX_SUBTRACTIVE(0, 0));
433 res->base = 0;
434 res->size = 0x1000;
435 res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
436 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
437
438 res = new_resource(dev, IOINDEX_SUBTRACTIVE(1, 0));
439 res->base = 0xff800000;
440 res->size = 0x00800000; /* 8 MB for flash */
441 res->flags = IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE |
442 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
443
444 res = new_resource(dev, 3); /* IOAPIC */
445 res->base = IO_APIC_ADDR;
446 res->size = 0x00001000;
447 res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
448}
449
Arthur Heymanse798e6a2017-12-23 23:09:54 +0100450static const char *lpc_acpi_name(const struct device *dev)
451{
452 return "LPCB";
453}
454
Furquan Shaikh7536a392020-04-24 21:59:21 -0700455static void southbridge_fill_ssdt(const struct device *device)
Vladimir Serbinenko36fa5b82014-10-28 23:43:20 +0100456{
Kyösti Mälkkic70eed12018-05-22 02:18:00 +0300457 struct device *dev = pcidev_on_root(0x1f, 0);
Vladimir Serbinenko36fa5b82014-10-28 23:43:20 +0100458 config_t *chip = dev->chip_info;
459
460 intel_acpi_pcie_hotplug_generator(chip->pcie_hotplug_map, 8);
Arthur Heymanse798e6a2017-12-23 23:09:54 +0100461 intel_acpi_gen_def_acpi_pirq(device);
Vladimir Serbinenko36fa5b82014-10-28 23:43:20 +0100462}
Vladimir Serbinenko33769a52014-08-30 22:39:20 +0200463
Patrick Georgie72a8a32012-11-06 11:05:09 +0100464static struct device_operations device_ops = {
465 .read_resources = i82801ix_lpc_read_resources,
466 .set_resources = pci_dev_set_resources,
467 .enable_resources = pci_dev_enable_resources,
Vladimir Serbinenko33769a52014-08-30 22:39:20 +0200468 .write_acpi_tables = acpi_write_hpet,
Nico Huber68680dd2020-03-31 17:34:52 +0200469 .acpi_fill_ssdt = southbridge_fill_ssdt,
Arthur Heymanse798e6a2017-12-23 23:09:54 +0100470 .acpi_name = lpc_acpi_name,
Patrick Georgie72a8a32012-11-06 11:05:09 +0100471 .init = lpc_init,
Nico Huber51b75ae2019-03-14 16:02:05 +0100472 .scan_bus = scan_static_bus,
Angel Pons1fc0edd2020-05-31 00:03:28 +0200473 .ops_pci = &pci_dev_ops_pci,
Patrick Georgie72a8a32012-11-06 11:05:09 +0100474};
475
476static const unsigned short pci_device_ids[] = {
Felix Singer43b7f412022-03-07 04:34:52 +0100477 PCI_DID_INTEL_82801IH_LPC, /* ICH9DH */
478 PCI_DID_INTEL_82801IO_LPC, /* ICH9DO */
479 PCI_DID_INTEL_82801IR_LPC, /* ICH9R */
480 PCI_DID_INTEL_82801IEM_LPC, /* ICH9M-E */
481 PCI_DID_INTEL_82801IB_LPC, /* ICH9 */
482 PCI_DID_INTEL_82801IBM_LPC, /* ICH9M */
Patrick Georgie72a8a32012-11-06 11:05:09 +0100483 0
484};
485
486static const struct pci_driver ich9_lpc __pci_driver = {
487 .ops = &device_ops,
Felix Singer43b7f412022-03-07 04:34:52 +0100488 .vendor = PCI_VID_INTEL,
Patrick Georgie72a8a32012-11-06 11:05:09 +0100489 .devices = pci_device_ids,
490};