blob: e3881ffa133eda174887e8c666a0e632f800ebd8 [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>
Tim Wawrzynczakf62c4942021-02-26 10:30:52 -070023#include <southbridge/intel/common/rcba_pirq.h>
Arthur Heymans7b9c1392017-04-09 20:40:39 +020024
25#define NMI_OFF 0
26
Arthur Heymans349e0852017-04-09 20:48:37 +020027typedef struct southbridge_intel_i82801jx_config config_t;
Arthur Heymans7b9c1392017-04-09 20:40:39 +020028
Arthur Heymans349e0852017-04-09 20:48:37 +020029static void i82801jx_enable_apic(struct device *dev)
Arthur Heymans7b9c1392017-04-09 20:40:39 +020030{
Arthur Heymans7b9c1392017-04-09 20:40:39 +020031 /* Enable IOAPIC. Keep APIC Range Select at zero. */
32 RCBA8(0x31ff) = 0x03;
33 /* We have to read 0x31ff back if bit0 changed. */
34 RCBA8(0x31ff);
35
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);
Arthur Heymans7b9c1392017-04-09 20:40:39 +020038
39 setup_ioapic(VIO_APIC_VADDR, 2); /* ICH7 code uses id 2. */
40}
41
Arthur Heymans349e0852017-04-09 20:48:37 +020042static void i82801jx_enable_serial_irqs(struct device *dev)
Arthur Heymans7b9c1392017-04-09 20:40:39 +020043{
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 HAOUAS1a8c1df2018-05-13 13:36:44 +020070static void i82801jx_pirq_init(struct device *dev)
Arthur Heymans7b9c1392017-04-09 20:40:39 +020071{
Elyes HAOUAS1a8c1df2018-05-13 13:36:44 +020072 struct device *irq_dev;
Arthur Heymans7b9c1392017-04-09 20:40:39 +020073
Arthur Heymans87af36a2017-04-12 10:53:30 +020074 /* Interrupt 11 is not used by legacy devices and so can always be used
75 * for PCI interrupts. Full legacy IRQ routing is complicated and hard
76 * to get right. Fortunately all modern OS use MSI and so it's not that
77 * big of an issue anyway. Still we have to provide a reasonable
78 * default. Using interrupt 11 for it everywhere is a working default.
79 * ACPI-aware OS can move it to any interrupt and others will just leave
80 * them at default.
81 */
82 const u8 pirq_routing = 11;
Arthur Heymans7b9c1392017-04-09 20:40:39 +020083
Arthur Heymans87af36a2017-04-12 10:53:30 +020084 pci_write_config8(dev, D31F0_PIRQA_ROUT, pirq_routing);
85 pci_write_config8(dev, D31F0_PIRQB_ROUT, pirq_routing);
86 pci_write_config8(dev, D31F0_PIRQC_ROUT, pirq_routing);
87 pci_write_config8(dev, D31F0_PIRQD_ROUT, pirq_routing);
88
89 pci_write_config8(dev, D31F0_PIRQE_ROUT, pirq_routing);
90 pci_write_config8(dev, D31F0_PIRQF_ROUT, pirq_routing);
91 pci_write_config8(dev, D31F0_PIRQG_ROUT, pirq_routing);
92 pci_write_config8(dev, D31F0_PIRQH_ROUT, pirq_routing);
Arthur Heymans7b9c1392017-04-09 20:40:39 +020093
94 /* Eric Biederman once said we should let the OS do this.
95 * I am not so sure anymore he was right.
96 */
97
98 for (irq_dev = all_devices; irq_dev; irq_dev = irq_dev->next) {
Arthur Heymans87af36a2017-04-12 10:53:30 +020099 u8 int_pin = 0;
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200100
101 if (!irq_dev->enabled || irq_dev->path.type != DEVICE_PATH_PCI)
102 continue;
103
104 int_pin = pci_read_config8(irq_dev, PCI_INTERRUPT_PIN);
105
Arthur Heymans87af36a2017-04-12 10:53:30 +0200106 if (int_pin == 0)
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200107 continue;
108
Arthur Heymans87af36a2017-04-12 10:53:30 +0200109 pci_write_config8(irq_dev, PCI_INTERRUPT_LINE, pirq_routing);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200110 }
111}
112
Elyes HAOUAS1a8c1df2018-05-13 13:36:44 +0200113static void i82801jx_gpi_routing(struct device *dev)
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200114{
115 /* Get the chip configuration */
116 config_t *config = dev->chip_info;
117 u32 reg32 = 0;
118
119 /* An array would be much nicer here, or some
120 * other method of doing this.
121 */
122 reg32 |= (config->gpi0_routing & 0x03) << 0;
123 reg32 |= (config->gpi1_routing & 0x03) << 2;
124 reg32 |= (config->gpi2_routing & 0x03) << 4;
125 reg32 |= (config->gpi3_routing & 0x03) << 6;
126 reg32 |= (config->gpi4_routing & 0x03) << 8;
127 reg32 |= (config->gpi5_routing & 0x03) << 10;
128 reg32 |= (config->gpi6_routing & 0x03) << 12;
129 reg32 |= (config->gpi7_routing & 0x03) << 14;
130 reg32 |= (config->gpi8_routing & 0x03) << 16;
131 reg32 |= (config->gpi9_routing & 0x03) << 18;
132 reg32 |= (config->gpi10_routing & 0x03) << 20;
133 reg32 |= (config->gpi11_routing & 0x03) << 22;
134 reg32 |= (config->gpi12_routing & 0x03) << 24;
135 reg32 |= (config->gpi13_routing & 0x03) << 26;
136 reg32 |= (config->gpi14_routing & 0x03) << 28;
137 reg32 |= (config->gpi15_routing & 0x03) << 30;
138
139 pci_write_config32(dev, D31F0_GPIO_ROUT, reg32);
140}
141
Elyes HAOUAS1a8c1df2018-05-13 13:36:44 +0200142static void i82801jx_power_options(struct device *dev)
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200143{
144 u8 reg8;
145 u16 reg16, pmbase;
146 u32 reg32;
147 const char *state;
148 /* Get the chip configuration */
149 config_t *config = dev->chip_info;
150
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200151 /* BIOS must program... */
Angel Pons2048cb42020-06-08 02:09:33 +0200152 pci_or_config32(dev, 0xac, (1 << 30) | (3 << 8));
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200153
154 /* Which state do we want to goto after g3 (power restored)?
155 * 0 == S0 Full On
156 * 1 == S5 Soft Off
157 *
158 * If the option is not existent (Laptops), use MAINBOARD_POWER_ON.
159 */
Angel Pons88dcb312021-04-26 17:10:28 +0200160 const unsigned int pwr_on = get_uint_option("power_on_after_fail", MAINBOARD_POWER_ON);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200161
162 reg8 = pci_read_config8(dev, D31F0_GEN_PMCON_3);
163 reg8 &= 0xfe;
164 switch (pwr_on) {
165 case MAINBOARD_POWER_OFF:
166 reg8 |= 1;
167 state = "off";
168 break;
169 case MAINBOARD_POWER_ON:
170 reg8 &= ~1;
171 state = "on";
172 break;
173 case MAINBOARD_POWER_KEEP:
174 reg8 &= ~1;
175 state = "state keep";
176 break;
177 default:
178 state = "undefined";
179 }
180
181 reg8 |= (3 << 4); /* avoid #S4 assertions */
Elyes HAOUASdc413712021-02-07 20:54:53 +0100182 reg8 &= ~(1 << 3); /* minimum assertion is 1 to 2 RTCCLK */
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200183
184 pci_write_config8(dev, D31F0_GEN_PMCON_3, reg8);
185 printk(BIOS_INFO, "Set power %s after power failure.\n", state);
186
187 /* Set up NMI on errors. */
188 reg8 = inb(0x61);
189 reg8 &= 0x0f; /* Higher Nibble must be 0 */
190 reg8 &= ~(1 << 3); /* IOCHK# NMI Enable */
191 // reg8 &= ~(1 << 2); /* PCI SERR# Enable */
192 reg8 |= (1 << 2); /* PCI SERR# Disable for now */
193 outb(reg8, 0x61);
194
195 reg8 = inb(0x74); /* Read from 0x74 as 0x70 is write only. */
Angel Pons88dcb312021-04-26 17:10:28 +0200196 const unsigned int nmi_option = get_uint_option("nmi", NMI_OFF);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200197 if (nmi_option) {
198 printk(BIOS_INFO, "NMI sources enabled.\n");
199 reg8 &= ~(1 << 7); /* Set NMI. */
200 } else {
201 printk(BIOS_INFO, "NMI sources disabled.\n");
Elyes HAOUAS9c5d4632018-04-26 22:21:21 +0200202 reg8 |= (1 << 7); /* Can't mask NMI from PCI-E and NMI_NOW */
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200203 }
204 outb(reg8, 0x70);
205
206 /* Enable CPU_SLP# and Intel Speedstep, set SMI# rate down */
207 reg16 = pci_read_config16(dev, D31F0_GEN_PMCON_1);
208 reg16 &= ~(3 << 0); // SMI# rate 1 minute
209 reg16 |= (1 << 2); // CLKRUN_EN - Mobile/Ultra only
210 reg16 |= (1 << 3); // Speedstep Enable - Mobile/Ultra only
211 reg16 |= (1 << 5); // CPUSLP_EN Desktop only
212
213 if (config->c4onc3_enable)
214 reg16 |= (1 << 7);
215
216 // another laptop wants this?
217 // reg16 &= ~(1 << 10); // BIOS_PCI_EXP_EN - Desktop/Mobile only
218 reg16 |= (1 << 10); // BIOS_PCI_EXP_EN - Desktop/Mobile only
Kyösti Mälkki94464472020-06-13 13:45:42 +0300219 if (CONFIG(DEBUG_PERIODIC_SMI))
220 reg16 |= (3 << 0); // Periodic SMI every 8s
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200221 if (config->c5_enable)
222 reg16 |= (1 << 11); /* Enable C5, C6 and PMSYNC# */
223 pci_write_config16(dev, D31F0_GEN_PMCON_1, reg16);
224
225 /* Set exit timings for C5/C6. */
226 if (config->c5_enable) {
227 reg8 = pci_read_config8(dev, D31F0_C5_EXIT_TIMING);
228 reg8 &= ~((7 << 3) | (7 << 0));
229 if (config->c6_enable)
230 reg8 |= (5 << 3) | (3 << 0); /* 38-44us PMSYNC# to STPCLK#,
231 95-102us DPRSTP# to STP_CPU# */
232 else
233 reg8 |= (0 << 3) | (1 << 0); /* 16-17us PMSYNC# to STPCLK#,
234 34-40us DPRSTP# to STP_CPU# */
235 pci_write_config8(dev, D31F0_C5_EXIT_TIMING, reg8);
236 }
237
238 // Set the board's GPI routing.
Arthur Heymans349e0852017-04-09 20:48:37 +0200239 i82801jx_gpi_routing(dev);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200240
241 pmbase = pci_read_config16(dev, 0x40) & 0xfffe;
242
243 outl(config->gpe0_en, pmbase + 0x28);
244 outw(config->alt_gp_smi_en, pmbase + 0x38);
245
246 /* Set up power management block and determine sleep mode */
247 reg16 = inw(pmbase + 0x00); /* PM1_STS */
248 outw(reg16, pmbase + 0x00); /* Clear status bits. At least bit11 (power
249 button override) must be cleared or SCI
250 will be constantly fired and OSPM must
251 not know about it (ACPI spec says to
252 ignore the bit). */
253 reg32 = inl(pmbase + 0x04); // PM1_CNT
254 reg32 &= ~(7 << 10); // SLP_TYP
255 outl(reg32, pmbase + 0x04);
256
257 /* Set duty cycle for hardware throttling (defaults to 0x0: 50%). */
258 reg32 = inl(pmbase + 0x10);
259 reg32 &= ~(7 << 5);
260 reg32 |= (config->throttle_duty & 7) << 5;
261 outl(reg32, pmbase + 0x10);
262}
263
Arthur Heymans349e0852017-04-09 20:48:37 +0200264static void i82801jx_rtc_init(struct device *dev)
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200265{
266 u8 reg8;
267 int rtc_failed;
268
269 reg8 = pci_read_config8(dev, D31F0_GEN_PMCON_3);
270 rtc_failed = reg8 & RTC_BATTERY_DEAD;
271 if (rtc_failed) {
272 reg8 &= ~RTC_BATTERY_DEAD;
273 pci_write_config8(dev, D31F0_GEN_PMCON_3, reg8);
274 }
275 printk(BIOS_DEBUG, "rtc_failed = 0x%x\n", rtc_failed);
276
277 cmos_init(rtc_failed);
278}
279
280static void enable_hpet(void)
281{
282 u32 reg32;
283
284 /* Move HPET to default address 0xfed00000 and enable it */
285 reg32 = RCBA32(RCBA_HPTC);
286 reg32 |= (1 << 7); // HPET Address Enable
287 reg32 &= ~(3 << 0);
288 RCBA32(RCBA_HPTC) = reg32;
289}
290
291static void enable_clock_gating(void)
292{
293 u32 reg32;
294
295 /* Enable DMI dynamic clock gating. */
296 RCBA32(RCBA_DMIC) |= 3;
297
298 /* Enable Clock Gating for most devices. */
299 reg32 = RCBA32(RCBA_CG);
300 reg32 |= (1 << 31); /* LPC dynamic clock gating */
301 /* USB UHCI dynamic clock gating: */
302 reg32 |= (1 << 29) | (1 << 28);
303 /* SATA dynamic clock gating [0-3]: */
304 reg32 |= (1 << 27) | (1 << 26) | (1 << 25) | (1 << 24);
305 reg32 |= (1 << 23); /* LAN static clock gating (if LAN disabled) */
306 reg32 |= (1 << 22); /* HD audio dynamic clock gating */
307 reg32 &= ~(1 << 21); /* No HD audio static clock gating */
308 reg32 &= ~(1 << 20); /* No USB EHCI static clock gating */
309 reg32 |= (1 << 19); /* USB EHCI dynamic clock gating */
310 /* More SATA dynamic clock gating [4-5]: */
311 reg32 |= (1 << 18) | (1 << 17);
312 reg32 |= (1 << 16); /* PCI dynamic clock gating */
313 /* PCIe, DMI dynamic clock gating: */
314 reg32 |= (1 << 4) | (1 << 3) | (1 << 2) | (1 << 1);
315 reg32 |= (1 << 0); /* PCIe root port static clock gating */
316 RCBA32(RCBA_CG) = reg32;
317
318 /* Enable SPI dynamic clock gating. */
319 RCBA32(0x38c0) |= 7;
320}
321
Kyösti Mälkki83d6a8a2019-07-12 08:16:53 +0300322static void i82801jx_set_acpi_mode(struct device *dev)
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200323{
Kyösti Mälkkiad882c32020-06-02 05:05:30 +0300324 if (!acpi_is_wakeup_s3()) {
325 apm_control(APM_CNT_ACPI_DISABLE);
326 } else {
327 apm_control(APM_CNT_ACPI_ENABLE);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200328 }
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200329}
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200330
331static void lpc_init(struct device *dev)
332{
Elyes HAOUASbfc255a2020-03-07 13:05:14 +0100333 printk(BIOS_DEBUG, "i82801jx: %s\n", __func__);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200334
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200335 /* IO APIC initialization. */
Arthur Heymans349e0852017-04-09 20:48:37 +0200336 i82801jx_enable_apic(dev);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200337
Arthur Heymans349e0852017-04-09 20:48:37 +0200338 i82801jx_enable_serial_irqs(dev);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200339
340 /* Setup the PIRQ. */
Arthur Heymans349e0852017-04-09 20:48:37 +0200341 i82801jx_pirq_init(dev);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200342
343 /* Setup power options. */
Arthur Heymans349e0852017-04-09 20:48:37 +0200344 i82801jx_power_options(dev);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200345
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200346 /* Initialize the real time clock. */
Arthur Heymans349e0852017-04-09 20:48:37 +0200347 i82801jx_rtc_init(dev);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200348
349 /* Initialize ISA DMA. */
350 isa_dma_init();
351
352 /* Initialize the High Precision Event Timers, if present. */
353 enable_hpet();
354
355 /* Initialize Clock Gating */
356 enable_clock_gating();
357
358 setup_i8259();
359
360 /* The OS should do this? */
361 /* Interrupt 9 should be level triggered (SCI) */
362 i8259_configure_irq_trigger(9, 1);
363
Kyösti Mälkki44da9e72019-10-09 12:32:16 +0300364 i82801jx_set_acpi_mode(dev);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200365}
366
Arthur Heymansad501492017-04-12 00:15:39 +0200367unsigned long acpi_fill_madt(unsigned long current)
368{
369 /* Local APICs */
370 current = acpi_create_madt_lapics(current);
371
372 /* IOAPIC */
373 current += acpi_create_madt_ioapic((acpi_madt_ioapic_t *) current,
374 2, IO_APIC_ADDR, 0);
375
376 /* LAPIC_NMI */
377 current += acpi_create_madt_lapic_nmi((acpi_madt_lapic_nmi_t *)
378 current, 0,
379 MP_IRQ_POLARITY_HIGH |
380 MP_IRQ_TRIGGER_EDGE, 0x01);
381 current += acpi_create_madt_lapic_nmi((acpi_madt_lapic_nmi_t *)
382 current, 1, MP_IRQ_POLARITY_HIGH |
383 MP_IRQ_TRIGGER_EDGE, 0x01);
384
385 /* INT_SRC_OVR */
386 current += acpi_create_madt_irqoverride((acpi_madt_irqoverride_t *)
387 current, 0, 0, 2, MP_IRQ_POLARITY_HIGH | MP_IRQ_TRIGGER_EDGE);
388 current += acpi_create_madt_irqoverride((acpi_madt_irqoverride_t *)
389 current, 0, 9, 9, MP_IRQ_POLARITY_HIGH | MP_IRQ_TRIGGER_LEVEL);
390
Arthur Heymansad501492017-04-12 00:15:39 +0200391 return current;
392}
393
Elyes HAOUAS1a8c1df2018-05-13 13:36:44 +0200394static void i82801jx_lpc_read_resources(struct device *dev)
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200395{
Arthur Heymanse5dcaf12017-04-12 00:03:37 +0200396 int i, io_index = 0;
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200397 /*
398 * I/O Resources
399 *
400 * 0x0000 - 0x000f....ISA DMA
401 * 0x0010 - 0x001f....ISA DMA aliases
402 * 0x0020 ~ 0x003d....PIC
403 * 0x002e - 0x002f....Maybe Super I/O
404 * 0x0040 - 0x0043....Timer
405 * 0x004e - 0x004f....Maybe Super I/O
406 * 0x0050 - 0x0053....Timer aliases
407 * 0x0061.............NMI_SC
408 * 0x0070.............NMI_EN (readable in alternative access mode)
409 * 0x0070 - 0x0077....RTC
410 * 0x0080 - 0x008f....ISA DMA
411 * 0x0090 ~ 0x009f....ISA DMA aliases
412 * 0x0092.............Fast A20 and Init
413 * 0x00a0 ~ 0x00bd....PIC
414 * 0x00b2 - 0x00b3....APM
415 * 0x00c0 ~ 0x00de....ISA DMA
416 * 0x00c1 ~ 0x00df....ISA DMA aliases
417 * 0x00f0.............Coprocessor Error
Angel Ponsb21bffa2020-07-03 01:02:28 +0200418 * (0x0400-0x041f)....SMBus (CONFIG_FIXED_SMBUS_IO_BASE, during raminit)
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200419 * 0x04d0 - 0x04d1....PIC
420 * 0x0500 - 0x057f....PM (DEFAULT_PMBASE)
421 * 0x0580 - 0x05bf....SB GPIO (DEFAULT_GPIOBASE)
422 * 0x05c0 - 0x05ff....SB GPIO cont. (mobile only)
423 * 0x0cf8 - 0x0cff....PCI
424 * 0x0cf9.............Reset Control
425 */
426
427 struct resource *res;
428
429 /* Get the normal PCI resources of this device. */
430 pci_dev_read_resources(dev);
431
432 /* Add an extra subtractive resource for both memory and I/O. */
Arthur Heymanse5dcaf12017-04-12 00:03:37 +0200433 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200434 res->base = 0;
435 res->size = 0x1000;
436 res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
437 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
438
Arthur Heymanse5dcaf12017-04-12 00:03:37 +0200439 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
440 res->base = 0xff000000;
441 res->size = 0x01000000; /* 16 MB for flash */
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200442 res->flags = IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE |
443 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
444
445 res = new_resource(dev, 3); /* IOAPIC */
446 res->base = IO_APIC_ADDR;
447 res->size = 0x00001000;
448 res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
Arthur Heymanse5dcaf12017-04-12 00:03:37 +0200449
450 /* Set IO decode ranges if required.*/
451 for (i = 0; i < 4; i++) {
452 u32 gen_dec;
453 gen_dec = pci_read_config32(dev, 0x84 + 4 * i);
454
455 if ((gen_dec & 0xFFFC) > 0x1000) {
456 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
457 res->base = gen_dec & 0xFFFC;
458 res->size = (gen_dec >> 16) & 0xFC;
459 res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
460 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
461 }
462 }
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200463}
464
Arthur Heymansa8a9f342017-12-24 08:11:13 +0100465static const char *lpc_acpi_name(const struct device *dev)
466{
467 return "LPCB";
468}
469
Furquan Shaikh7536a392020-04-24 21:59:21 -0700470static void southbridge_fill_ssdt(const struct device *device)
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200471{
Kyösti Mälkkic70eed12018-05-22 02:18:00 +0300472 struct device *dev = pcidev_on_root(0x1f, 0);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200473 config_t *chip = dev->chip_info;
474
475 intel_acpi_pcie_hotplug_generator(chip->pcie_hotplug_map, 8);
Arthur Heymansa8a9f342017-12-24 08:11:13 +0100476 intel_acpi_gen_def_acpi_pirq(device);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200477}
478
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200479static struct device_operations device_ops = {
Arthur Heymans349e0852017-04-09 20:48:37 +0200480 .read_resources = i82801jx_lpc_read_resources,
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200481 .set_resources = pci_dev_set_resources,
482 .enable_resources = pci_dev_enable_resources,
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200483 .write_acpi_tables = acpi_write_hpet,
Nico Huber68680dd2020-03-31 17:34:52 +0200484 .acpi_fill_ssdt = southbridge_fill_ssdt,
Arthur Heymansa8a9f342017-12-24 08:11:13 +0100485 .acpi_name = lpc_acpi_name,
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200486 .init = lpc_init,
Nico Huber51b75ae2019-03-14 16:02:05 +0100487 .scan_bus = scan_static_bus,
Angel Pons1fc0edd2020-05-31 00:03:28 +0200488 .ops_pci = &pci_dev_ops_pci,
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200489};
490
491static const unsigned short pci_device_ids[] = {
Arthur Heymans349e0852017-04-09 20:48:37 +0200492 0x3a10, /* ICH10R Eng. Sample */
493 0x3a14, /* ICH10DO */
494 0x3a16, /* ICH10R */
495 0x3a18, /* ICH10 */
496 0x3a1a, /* ICH10D */
497 0x3a1e, /* ICH10 Eng. Sample */
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200498 0
499};
500
Arthur Heymans349e0852017-04-09 20:48:37 +0200501static const struct pci_driver ich10_lpc __pci_driver = {
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200502 .ops = &device_ops,
Felix Singer43b7f412022-03-07 04:34:52 +0100503 .vendor = PCI_VID_INTEL,
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200504 .devices = pci_device_ids,
505};