blob: f70636dde6edbbebb8635cf79f583d8ac189bd3c [file] [log] [blame]
Angel Pons182dbde2020-04-02 23:49:05 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Arthur Heymans7b9c1392017-04-09 20:40:39 +02002
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>
Arthur Heymans7b9c1392017-04-09 20:40:39 +02008#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>
Arthur Heymans7b9c1392017-04-09 20:40:39 +020013#include <arch/ioapic.h>
Furquan Shaikh76cedd22020-05-02 10:24:23 -070014#include <acpi/acpi.h>
Arthur Heymans7b9c1392017-04-09 20:40:39 +020015#include <cpu/x86/smm.h>
Furquan Shaikh76cedd22020-05-02 10:24:23 -070016#include <acpi/acpigen.h>
Arthur Heymansad501492017-04-12 00:15:39 +020017#include <arch/smp/mpspec.h>
Kyösti Mälkki12b121c2019-08-18 16:33:39 +030018#include "chip.h"
Arthur Heymans349e0852017-04-09 20:48:37 +020019#include "i82801jx.h"
Arthur Heymans7b9c1392017-04-09 20:40:39 +020020#include <southbridge/intel/common/pciehp.h>
Angel Pons490473e2020-06-21 17:10:28 +020021#include <southbridge/intel/common/pmutil.h>
Arthur Heymansa8a9f342017-12-24 08:11:13 +010022#include <southbridge/intel/common/acpi_pirq_gen.h>
Arthur Heymans7b9c1392017-04-09 20:40:39 +020023
24#define NMI_OFF 0
25
Arthur Heymans349e0852017-04-09 20:48:37 +020026typedef struct southbridge_intel_i82801jx_config config_t;
Arthur Heymans7b9c1392017-04-09 20:40:39 +020027
Arthur Heymans349e0852017-04-09 20:48:37 +020028static void i82801jx_enable_apic(struct device *dev)
Arthur Heymans7b9c1392017-04-09 20:40:39 +020029{
30 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. */
37 RCBA8(0x31ff);
38
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
45 setup_ioapic(VIO_APIC_VADDR, 2); /* ICH7 code uses id 2. */
46}
47
Arthur Heymans349e0852017-04-09 20:48:37 +020048static void i82801jx_enable_serial_irqs(struct device *dev)
Arthur Heymans7b9c1392017-04-09 20:40:39 +020049{
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 HAOUAS1a8c1df2018-05-13 13:36:44 +020076static void i82801jx_pirq_init(struct device *dev)
Arthur Heymans7b9c1392017-04-09 20:40:39 +020077{
Elyes HAOUAS1a8c1df2018-05-13 13:36:44 +020078 struct device *irq_dev;
Arthur Heymans7b9c1392017-04-09 20:40:39 +020079
Arthur Heymans87af36a2017-04-12 10:53:30 +020080 /* Interrupt 11 is not used by legacy devices and so can always be used
81 * for PCI interrupts. Full legacy IRQ routing is complicated and hard
82 * to get right. Fortunately all modern OS use MSI and so it's not that
83 * big of an issue anyway. Still we have to provide a reasonable
84 * default. Using interrupt 11 for it everywhere is a working default.
85 * ACPI-aware OS can move it to any interrupt and others will just leave
86 * them at default.
87 */
88 const u8 pirq_routing = 11;
Arthur Heymans7b9c1392017-04-09 20:40:39 +020089
Arthur Heymans87af36a2017-04-12 10:53:30 +020090 pci_write_config8(dev, D31F0_PIRQA_ROUT, pirq_routing);
91 pci_write_config8(dev, D31F0_PIRQB_ROUT, pirq_routing);
92 pci_write_config8(dev, D31F0_PIRQC_ROUT, pirq_routing);
93 pci_write_config8(dev, D31F0_PIRQD_ROUT, pirq_routing);
94
95 pci_write_config8(dev, D31F0_PIRQE_ROUT, pirq_routing);
96 pci_write_config8(dev, D31F0_PIRQF_ROUT, pirq_routing);
97 pci_write_config8(dev, D31F0_PIRQG_ROUT, pirq_routing);
98 pci_write_config8(dev, D31F0_PIRQH_ROUT, pirq_routing);
Arthur Heymans7b9c1392017-04-09 20:40:39 +020099
100 /* Eric Biederman once said we should let the OS do this.
101 * I am not so sure anymore he was right.
102 */
103
104 for (irq_dev = all_devices; irq_dev; irq_dev = irq_dev->next) {
Arthur Heymans87af36a2017-04-12 10:53:30 +0200105 u8 int_pin = 0;
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200106
107 if (!irq_dev->enabled || irq_dev->path.type != DEVICE_PATH_PCI)
108 continue;
109
110 int_pin = pci_read_config8(irq_dev, PCI_INTERRUPT_PIN);
111
Arthur Heymans87af36a2017-04-12 10:53:30 +0200112 if (int_pin == 0)
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200113 continue;
114
Arthur Heymans87af36a2017-04-12 10:53:30 +0200115 pci_write_config8(irq_dev, PCI_INTERRUPT_LINE, pirq_routing);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200116 }
117}
118
Elyes HAOUAS1a8c1df2018-05-13 13:36:44 +0200119static void i82801jx_gpi_routing(struct device *dev)
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200120{
121 /* Get the chip configuration */
122 config_t *config = dev->chip_info;
123 u32 reg32 = 0;
124
125 /* An array would be much nicer here, or some
126 * other method of doing this.
127 */
128 reg32 |= (config->gpi0_routing & 0x03) << 0;
129 reg32 |= (config->gpi1_routing & 0x03) << 2;
130 reg32 |= (config->gpi2_routing & 0x03) << 4;
131 reg32 |= (config->gpi3_routing & 0x03) << 6;
132 reg32 |= (config->gpi4_routing & 0x03) << 8;
133 reg32 |= (config->gpi5_routing & 0x03) << 10;
134 reg32 |= (config->gpi6_routing & 0x03) << 12;
135 reg32 |= (config->gpi7_routing & 0x03) << 14;
136 reg32 |= (config->gpi8_routing & 0x03) << 16;
137 reg32 |= (config->gpi9_routing & 0x03) << 18;
138 reg32 |= (config->gpi10_routing & 0x03) << 20;
139 reg32 |= (config->gpi11_routing & 0x03) << 22;
140 reg32 |= (config->gpi12_routing & 0x03) << 24;
141 reg32 |= (config->gpi13_routing & 0x03) << 26;
142 reg32 |= (config->gpi14_routing & 0x03) << 28;
143 reg32 |= (config->gpi15_routing & 0x03) << 30;
144
145 pci_write_config32(dev, D31F0_GPIO_ROUT, reg32);
146}
147
Elyes HAOUAS1a8c1df2018-05-13 13:36:44 +0200148static void i82801jx_power_options(struct device *dev)
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200149{
150 u8 reg8;
151 u16 reg16, pmbase;
152 u32 reg32;
153 const char *state;
154 /* Get the chip configuration */
155 config_t *config = dev->chip_info;
156
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200157 /* BIOS must program... */
Angel Pons2048cb42020-06-08 02:09:33 +0200158 pci_or_config32(dev, 0xac, (1 << 30) | (3 << 8));
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200159
160 /* Which state do we want to goto after g3 (power restored)?
161 * 0 == S0 Full On
162 * 1 == S5 Soft Off
163 *
164 * If the option is not existent (Laptops), use MAINBOARD_POWER_ON.
165 */
Angel Pons62719a32021-04-19 13:15:28 +0200166 const int pwr_on = get_int_option("power_on_after_fail", MAINBOARD_POWER_ON);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200167
168 reg8 = pci_read_config8(dev, D31F0_GEN_PMCON_3);
169 reg8 &= 0xfe;
170 switch (pwr_on) {
171 case MAINBOARD_POWER_OFF:
172 reg8 |= 1;
173 state = "off";
174 break;
175 case MAINBOARD_POWER_ON:
176 reg8 &= ~1;
177 state = "on";
178 break;
179 case MAINBOARD_POWER_KEEP:
180 reg8 &= ~1;
181 state = "state keep";
182 break;
183 default:
184 state = "undefined";
185 }
186
187 reg8 |= (3 << 4); /* avoid #S4 assertions */
Elyes HAOUASdc413712021-02-07 20:54:53 +0100188 reg8 &= ~(1 << 3); /* minimum assertion is 1 to 2 RTCCLK */
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200189
190 pci_write_config8(dev, D31F0_GEN_PMCON_3, reg8);
191 printk(BIOS_INFO, "Set power %s after power failure.\n", state);
192
193 /* Set up NMI on errors. */
194 reg8 = inb(0x61);
195 reg8 &= 0x0f; /* Higher Nibble must be 0 */
196 reg8 &= ~(1 << 3); /* IOCHK# NMI Enable */
197 // reg8 &= ~(1 << 2); /* PCI SERR# Enable */
198 reg8 |= (1 << 2); /* PCI SERR# Disable for now */
199 outb(reg8, 0x61);
200
201 reg8 = inb(0x74); /* Read from 0x74 as 0x70 is write only. */
Angel Pons62719a32021-04-19 13:15:28 +0200202 const int nmi_option = get_int_option("nmi", NMI_OFF);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200203 if (nmi_option) {
204 printk(BIOS_INFO, "NMI sources enabled.\n");
205 reg8 &= ~(1 << 7); /* Set NMI. */
206 } else {
207 printk(BIOS_INFO, "NMI sources disabled.\n");
Elyes HAOUAS9c5d4632018-04-26 22:21:21 +0200208 reg8 |= (1 << 7); /* Can't mask NMI from PCI-E and NMI_NOW */
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200209 }
210 outb(reg8, 0x70);
211
212 /* Enable CPU_SLP# and Intel Speedstep, set SMI# rate down */
213 reg16 = pci_read_config16(dev, D31F0_GEN_PMCON_1);
214 reg16 &= ~(3 << 0); // SMI# rate 1 minute
215 reg16 |= (1 << 2); // CLKRUN_EN - Mobile/Ultra only
216 reg16 |= (1 << 3); // Speedstep Enable - Mobile/Ultra only
217 reg16 |= (1 << 5); // CPUSLP_EN Desktop only
218
219 if (config->c4onc3_enable)
220 reg16 |= (1 << 7);
221
222 // another laptop wants this?
223 // reg16 &= ~(1 << 10); // BIOS_PCI_EXP_EN - Desktop/Mobile only
224 reg16 |= (1 << 10); // BIOS_PCI_EXP_EN - Desktop/Mobile only
Kyösti Mälkki94464472020-06-13 13:45:42 +0300225 if (CONFIG(DEBUG_PERIODIC_SMI))
226 reg16 |= (3 << 0); // Periodic SMI every 8s
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200227 if (config->c5_enable)
228 reg16 |= (1 << 11); /* Enable C5, C6 and PMSYNC# */
229 pci_write_config16(dev, D31F0_GEN_PMCON_1, reg16);
230
231 /* Set exit timings for C5/C6. */
232 if (config->c5_enable) {
233 reg8 = pci_read_config8(dev, D31F0_C5_EXIT_TIMING);
234 reg8 &= ~((7 << 3) | (7 << 0));
235 if (config->c6_enable)
236 reg8 |= (5 << 3) | (3 << 0); /* 38-44us PMSYNC# to STPCLK#,
237 95-102us DPRSTP# to STP_CPU# */
238 else
239 reg8 |= (0 << 3) | (1 << 0); /* 16-17us PMSYNC# to STPCLK#,
240 34-40us DPRSTP# to STP_CPU# */
241 pci_write_config8(dev, D31F0_C5_EXIT_TIMING, reg8);
242 }
243
244 // Set the board's GPI routing.
Arthur Heymans349e0852017-04-09 20:48:37 +0200245 i82801jx_gpi_routing(dev);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200246
247 pmbase = pci_read_config16(dev, 0x40) & 0xfffe;
248
249 outl(config->gpe0_en, pmbase + 0x28);
250 outw(config->alt_gp_smi_en, pmbase + 0x38);
251
252 /* Set up power management block and determine sleep mode */
253 reg16 = inw(pmbase + 0x00); /* PM1_STS */
254 outw(reg16, pmbase + 0x00); /* Clear status bits. At least bit11 (power
255 button override) must be cleared or SCI
256 will be constantly fired and OSPM must
257 not know about it (ACPI spec says to
258 ignore the bit). */
259 reg32 = inl(pmbase + 0x04); // PM1_CNT
260 reg32 &= ~(7 << 10); // SLP_TYP
261 outl(reg32, pmbase + 0x04);
262
263 /* Set duty cycle for hardware throttling (defaults to 0x0: 50%). */
264 reg32 = inl(pmbase + 0x10);
265 reg32 &= ~(7 << 5);
266 reg32 |= (config->throttle_duty & 7) << 5;
267 outl(reg32, pmbase + 0x10);
268}
269
Arthur Heymans349e0852017-04-09 20:48:37 +0200270static void i82801jx_rtc_init(struct device *dev)
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200271{
272 u8 reg8;
273 int rtc_failed;
274
275 reg8 = pci_read_config8(dev, D31F0_GEN_PMCON_3);
276 rtc_failed = reg8 & RTC_BATTERY_DEAD;
277 if (rtc_failed) {
278 reg8 &= ~RTC_BATTERY_DEAD;
279 pci_write_config8(dev, D31F0_GEN_PMCON_3, reg8);
280 }
281 printk(BIOS_DEBUG, "rtc_failed = 0x%x\n", rtc_failed);
282
283 cmos_init(rtc_failed);
284}
285
286static void enable_hpet(void)
287{
288 u32 reg32;
289
290 /* Move HPET to default address 0xfed00000 and enable it */
291 reg32 = RCBA32(RCBA_HPTC);
292 reg32 |= (1 << 7); // HPET Address Enable
293 reg32 &= ~(3 << 0);
294 RCBA32(RCBA_HPTC) = reg32;
295}
296
297static void enable_clock_gating(void)
298{
299 u32 reg32;
300
301 /* Enable DMI dynamic clock gating. */
302 RCBA32(RCBA_DMIC) |= 3;
303
304 /* Enable Clock Gating for most devices. */
305 reg32 = RCBA32(RCBA_CG);
306 reg32 |= (1 << 31); /* LPC dynamic clock gating */
307 /* USB UHCI dynamic clock gating: */
308 reg32 |= (1 << 29) | (1 << 28);
309 /* SATA dynamic clock gating [0-3]: */
310 reg32 |= (1 << 27) | (1 << 26) | (1 << 25) | (1 << 24);
311 reg32 |= (1 << 23); /* LAN static clock gating (if LAN disabled) */
312 reg32 |= (1 << 22); /* HD audio dynamic clock gating */
313 reg32 &= ~(1 << 21); /* No HD audio static clock gating */
314 reg32 &= ~(1 << 20); /* No USB EHCI static clock gating */
315 reg32 |= (1 << 19); /* USB EHCI dynamic clock gating */
316 /* More SATA dynamic clock gating [4-5]: */
317 reg32 |= (1 << 18) | (1 << 17);
318 reg32 |= (1 << 16); /* PCI dynamic clock gating */
319 /* PCIe, DMI dynamic clock gating: */
320 reg32 |= (1 << 4) | (1 << 3) | (1 << 2) | (1 << 1);
321 reg32 |= (1 << 0); /* PCIe root port static clock gating */
322 RCBA32(RCBA_CG) = reg32;
323
324 /* Enable SPI dynamic clock gating. */
325 RCBA32(0x38c0) |= 7;
326}
327
Kyösti Mälkki83d6a8a2019-07-12 08:16:53 +0300328static void i82801jx_set_acpi_mode(struct device *dev)
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200329{
Kyösti Mälkkiad882c32020-06-02 05:05:30 +0300330 if (!acpi_is_wakeup_s3()) {
331 apm_control(APM_CNT_ACPI_DISABLE);
332 } else {
333 apm_control(APM_CNT_ACPI_ENABLE);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200334 }
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200335}
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200336
337static void lpc_init(struct device *dev)
338{
Elyes HAOUASbfc255a2020-03-07 13:05:14 +0100339 printk(BIOS_DEBUG, "i82801jx: %s\n", __func__);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200340
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200341 /* IO APIC initialization. */
Arthur Heymans349e0852017-04-09 20:48:37 +0200342 i82801jx_enable_apic(dev);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200343
Arthur Heymans349e0852017-04-09 20:48:37 +0200344 i82801jx_enable_serial_irqs(dev);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200345
346 /* Setup the PIRQ. */
Arthur Heymans349e0852017-04-09 20:48:37 +0200347 i82801jx_pirq_init(dev);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200348
349 /* Setup power options. */
Arthur Heymans349e0852017-04-09 20:48:37 +0200350 i82801jx_power_options(dev);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200351
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200352 /* Initialize the real time clock. */
Arthur Heymans349e0852017-04-09 20:48:37 +0200353 i82801jx_rtc_init(dev);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200354
355 /* Initialize ISA DMA. */
356 isa_dma_init();
357
358 /* Initialize the High Precision Event Timers, if present. */
359 enable_hpet();
360
361 /* Initialize Clock Gating */
362 enable_clock_gating();
363
364 setup_i8259();
365
366 /* The OS should do this? */
367 /* Interrupt 9 should be level triggered (SCI) */
368 i8259_configure_irq_trigger(9, 1);
369
Kyösti Mälkki44da9e72019-10-09 12:32:16 +0300370 i82801jx_set_acpi_mode(dev);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200371}
372
Arthur Heymansad501492017-04-12 00:15:39 +0200373unsigned long acpi_fill_madt(unsigned long current)
374{
375 /* Local APICs */
376 current = acpi_create_madt_lapics(current);
377
378 /* IOAPIC */
379 current += acpi_create_madt_ioapic((acpi_madt_ioapic_t *) current,
380 2, IO_APIC_ADDR, 0);
381
382 /* LAPIC_NMI */
383 current += acpi_create_madt_lapic_nmi((acpi_madt_lapic_nmi_t *)
384 current, 0,
385 MP_IRQ_POLARITY_HIGH |
386 MP_IRQ_TRIGGER_EDGE, 0x01);
387 current += acpi_create_madt_lapic_nmi((acpi_madt_lapic_nmi_t *)
388 current, 1, MP_IRQ_POLARITY_HIGH |
389 MP_IRQ_TRIGGER_EDGE, 0x01);
390
391 /* INT_SRC_OVR */
392 current += acpi_create_madt_irqoverride((acpi_madt_irqoverride_t *)
393 current, 0, 0, 2, MP_IRQ_POLARITY_HIGH | MP_IRQ_TRIGGER_EDGE);
394 current += acpi_create_madt_irqoverride((acpi_madt_irqoverride_t *)
395 current, 0, 9, 9, MP_IRQ_POLARITY_HIGH | MP_IRQ_TRIGGER_LEVEL);
396
Arthur Heymansad501492017-04-12 00:15:39 +0200397 return current;
398}
399
Elyes HAOUAS1a8c1df2018-05-13 13:36:44 +0200400static void i82801jx_lpc_read_resources(struct device *dev)
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200401{
Arthur Heymanse5dcaf12017-04-12 00:03:37 +0200402 int i, io_index = 0;
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200403 /*
404 * I/O Resources
405 *
406 * 0x0000 - 0x000f....ISA DMA
407 * 0x0010 - 0x001f....ISA DMA aliases
408 * 0x0020 ~ 0x003d....PIC
409 * 0x002e - 0x002f....Maybe Super I/O
410 * 0x0040 - 0x0043....Timer
411 * 0x004e - 0x004f....Maybe Super I/O
412 * 0x0050 - 0x0053....Timer aliases
413 * 0x0061.............NMI_SC
414 * 0x0070.............NMI_EN (readable in alternative access mode)
415 * 0x0070 - 0x0077....RTC
416 * 0x0080 - 0x008f....ISA DMA
417 * 0x0090 ~ 0x009f....ISA DMA aliases
418 * 0x0092.............Fast A20 and Init
419 * 0x00a0 ~ 0x00bd....PIC
420 * 0x00b2 - 0x00b3....APM
421 * 0x00c0 ~ 0x00de....ISA DMA
422 * 0x00c1 ~ 0x00df....ISA DMA aliases
423 * 0x00f0.............Coprocessor Error
Angel Ponsb21bffa2020-07-03 01:02:28 +0200424 * (0x0400-0x041f)....SMBus (CONFIG_FIXED_SMBUS_IO_BASE, during raminit)
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200425 * 0x04d0 - 0x04d1....PIC
426 * 0x0500 - 0x057f....PM (DEFAULT_PMBASE)
427 * 0x0580 - 0x05bf....SB GPIO (DEFAULT_GPIOBASE)
428 * 0x05c0 - 0x05ff....SB GPIO cont. (mobile only)
429 * 0x0cf8 - 0x0cff....PCI
430 * 0x0cf9.............Reset Control
431 */
432
433 struct resource *res;
434
435 /* Get the normal PCI resources of this device. */
436 pci_dev_read_resources(dev);
437
438 /* Add an extra subtractive resource for both memory and I/O. */
Arthur Heymanse5dcaf12017-04-12 00:03:37 +0200439 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200440 res->base = 0;
441 res->size = 0x1000;
442 res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
443 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
444
Arthur Heymanse5dcaf12017-04-12 00:03:37 +0200445 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
446 res->base = 0xff000000;
447 res->size = 0x01000000; /* 16 MB for flash */
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200448 res->flags = IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE |
449 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
450
451 res = new_resource(dev, 3); /* IOAPIC */
452 res->base = IO_APIC_ADDR;
453 res->size = 0x00001000;
454 res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
Arthur Heymanse5dcaf12017-04-12 00:03:37 +0200455
456 /* Set IO decode ranges if required.*/
457 for (i = 0; i < 4; i++) {
458 u32 gen_dec;
459 gen_dec = pci_read_config32(dev, 0x84 + 4 * i);
460
461 if ((gen_dec & 0xFFFC) > 0x1000) {
462 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
463 res->base = gen_dec & 0xFFFC;
464 res->size = (gen_dec >> 16) & 0xFC;
465 res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
466 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
467 }
468 }
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200469}
470
Arthur Heymansa8a9f342017-12-24 08:11:13 +0100471static const char *lpc_acpi_name(const struct device *dev)
472{
473 return "LPCB";
474}
475
Furquan Shaikh7536a392020-04-24 21:59:21 -0700476static void southbridge_fill_ssdt(const struct device *device)
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200477{
Kyösti Mälkkic70eed12018-05-22 02:18:00 +0300478 struct device *dev = pcidev_on_root(0x1f, 0);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200479 config_t *chip = dev->chip_info;
480
481 intel_acpi_pcie_hotplug_generator(chip->pcie_hotplug_map, 8);
Arthur Heymansa8a9f342017-12-24 08:11:13 +0100482 intel_acpi_gen_def_acpi_pirq(device);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200483}
484
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200485static struct device_operations device_ops = {
Arthur Heymans349e0852017-04-09 20:48:37 +0200486 .read_resources = i82801jx_lpc_read_resources,
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200487 .set_resources = pci_dev_set_resources,
488 .enable_resources = pci_dev_enable_resources,
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200489 .write_acpi_tables = acpi_write_hpet,
Nico Huber68680dd2020-03-31 17:34:52 +0200490 .acpi_fill_ssdt = southbridge_fill_ssdt,
Arthur Heymansa8a9f342017-12-24 08:11:13 +0100491 .acpi_name = lpc_acpi_name,
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200492 .init = lpc_init,
Nico Huber51b75ae2019-03-14 16:02:05 +0100493 .scan_bus = scan_static_bus,
Angel Pons1fc0edd2020-05-31 00:03:28 +0200494 .ops_pci = &pci_dev_ops_pci,
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200495};
496
497static const unsigned short pci_device_ids[] = {
Arthur Heymans349e0852017-04-09 20:48:37 +0200498 0x3a10, /* ICH10R Eng. Sample */
499 0x3a14, /* ICH10DO */
500 0x3a16, /* ICH10R */
501 0x3a18, /* ICH10 */
502 0x3a1a, /* ICH10D */
503 0x3a1e, /* ICH10 Eng. Sample */
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200504 0
505};
506
Arthur Heymans349e0852017-04-09 20:48:37 +0200507static const struct pci_driver ich10_lpc __pci_driver = {
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200508 .ops = &device_ops,
509 .vendor = PCI_VENDOR_ID_INTEL,
510 .devices = pci_device_ids,
511};