blob: a2798342695515bc0e9a76f4b0613157d4415cf7 [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>
Arthur Heymans7b9c1392017-04-09 20:40:39 +020018#include <string.h>
Kyösti Mälkki12b121c2019-08-18 16:33:39 +030019#include "chip.h"
Arthur Heymans349e0852017-04-09 20:48:37 +020020#include "i82801jx.h"
Arthur Heymans7b9c1392017-04-09 20:40:39 +020021#include <southbridge/intel/common/pciehp.h>
Angel Pons490473e2020-06-21 17:10:28 +020022#include <southbridge/intel/common/pmutil.h>
Arthur Heymansa8a9f342017-12-24 08:11:13 +010023#include <southbridge/intel/common/acpi_pirq_gen.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{
31 u32 reg32;
32 volatile u32 *ioapic_index = (volatile u32 *)(IO_APIC_ADDR);
33 volatile u32 *ioapic_data = (volatile u32 *)(IO_APIC_ADDR + 0x10);
34
35 /* Enable IOAPIC. Keep APIC Range Select at zero. */
36 RCBA8(0x31ff) = 0x03;
37 /* We have to read 0x31ff back if bit0 changed. */
38 RCBA8(0x31ff);
39
40 /* Lock maximum redirection entries (MRE), R/WO register. */
41 *ioapic_index = 0x01;
42 reg32 = *ioapic_data;
43 *ioapic_index = 0x01;
44 *ioapic_data = reg32;
45
46 setup_ioapic(VIO_APIC_VADDR, 2); /* ICH7 code uses id 2. */
47}
48
Arthur Heymans349e0852017-04-09 20:48:37 +020049static void i82801jx_enable_serial_irqs(struct device *dev)
Arthur Heymans7b9c1392017-04-09 20:40:39 +020050{
51 /* Set packet length and toggle silent mode bit for one frame. */
52 pci_write_config8(dev, D31F0_SERIRQ_CNTL,
53 (1 << 7) | (1 << 6) | ((21 - 17) << 2) | (0 << 0));
54}
55
56/* PIRQ[n]_ROUT[3:0] - PIRQ Routing Control
57 * 0x00 - 0000 = Reserved
58 * 0x01 - 0001 = Reserved
59 * 0x02 - 0010 = Reserved
60 * 0x03 - 0011 = IRQ3
61 * 0x04 - 0100 = IRQ4
62 * 0x05 - 0101 = IRQ5
63 * 0x06 - 0110 = IRQ6
64 * 0x07 - 0111 = IRQ7
65 * 0x08 - 1000 = Reserved
66 * 0x09 - 1001 = IRQ9
67 * 0x0A - 1010 = IRQ10
68 * 0x0B - 1011 = IRQ11
69 * 0x0C - 1100 = IRQ12
70 * 0x0D - 1101 = Reserved
71 * 0x0E - 1110 = IRQ14
72 * 0x0F - 1111 = IRQ15
73 * PIRQ[n]_ROUT[7] - PIRQ Routing Control
74 * 0x80 - The PIRQ is not routed.
75 */
76
Elyes HAOUAS1a8c1df2018-05-13 13:36:44 +020077static void i82801jx_pirq_init(struct device *dev)
Arthur Heymans7b9c1392017-04-09 20:40:39 +020078{
Elyes HAOUAS1a8c1df2018-05-13 13:36:44 +020079 struct device *irq_dev;
Arthur Heymans7b9c1392017-04-09 20:40:39 +020080
Arthur Heymans87af36a2017-04-12 10:53:30 +020081 /* Interrupt 11 is not used by legacy devices and so can always be used
82 * for PCI interrupts. Full legacy IRQ routing is complicated and hard
83 * to get right. Fortunately all modern OS use MSI and so it's not that
84 * big of an issue anyway. Still we have to provide a reasonable
85 * default. Using interrupt 11 for it everywhere is a working default.
86 * ACPI-aware OS can move it to any interrupt and others will just leave
87 * them at default.
88 */
89 const u8 pirq_routing = 11;
Arthur Heymans7b9c1392017-04-09 20:40:39 +020090
Arthur Heymans87af36a2017-04-12 10:53:30 +020091 pci_write_config8(dev, D31F0_PIRQA_ROUT, pirq_routing);
92 pci_write_config8(dev, D31F0_PIRQB_ROUT, pirq_routing);
93 pci_write_config8(dev, D31F0_PIRQC_ROUT, pirq_routing);
94 pci_write_config8(dev, D31F0_PIRQD_ROUT, pirq_routing);
95
96 pci_write_config8(dev, D31F0_PIRQE_ROUT, pirq_routing);
97 pci_write_config8(dev, D31F0_PIRQF_ROUT, pirq_routing);
98 pci_write_config8(dev, D31F0_PIRQG_ROUT, pirq_routing);
99 pci_write_config8(dev, D31F0_PIRQH_ROUT, pirq_routing);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200100
101 /* Eric Biederman once said we should let the OS do this.
102 * I am not so sure anymore he was right.
103 */
104
105 for (irq_dev = all_devices; irq_dev; irq_dev = irq_dev->next) {
Arthur Heymans87af36a2017-04-12 10:53:30 +0200106 u8 int_pin = 0;
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200107
108 if (!irq_dev->enabled || irq_dev->path.type != DEVICE_PATH_PCI)
109 continue;
110
111 int_pin = pci_read_config8(irq_dev, PCI_INTERRUPT_PIN);
112
Arthur Heymans87af36a2017-04-12 10:53:30 +0200113 if (int_pin == 0)
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200114 continue;
115
Arthur Heymans87af36a2017-04-12 10:53:30 +0200116 pci_write_config8(irq_dev, PCI_INTERRUPT_LINE, pirq_routing);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200117 }
118}
119
Elyes HAOUAS1a8c1df2018-05-13 13:36:44 +0200120static void i82801jx_gpi_routing(struct device *dev)
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200121{
122 /* Get the chip configuration */
123 config_t *config = dev->chip_info;
124 u32 reg32 = 0;
125
126 /* An array would be much nicer here, or some
127 * other method of doing this.
128 */
129 reg32 |= (config->gpi0_routing & 0x03) << 0;
130 reg32 |= (config->gpi1_routing & 0x03) << 2;
131 reg32 |= (config->gpi2_routing & 0x03) << 4;
132 reg32 |= (config->gpi3_routing & 0x03) << 6;
133 reg32 |= (config->gpi4_routing & 0x03) << 8;
134 reg32 |= (config->gpi5_routing & 0x03) << 10;
135 reg32 |= (config->gpi6_routing & 0x03) << 12;
136 reg32 |= (config->gpi7_routing & 0x03) << 14;
137 reg32 |= (config->gpi8_routing & 0x03) << 16;
138 reg32 |= (config->gpi9_routing & 0x03) << 18;
139 reg32 |= (config->gpi10_routing & 0x03) << 20;
140 reg32 |= (config->gpi11_routing & 0x03) << 22;
141 reg32 |= (config->gpi12_routing & 0x03) << 24;
142 reg32 |= (config->gpi13_routing & 0x03) << 26;
143 reg32 |= (config->gpi14_routing & 0x03) << 28;
144 reg32 |= (config->gpi15_routing & 0x03) << 30;
145
146 pci_write_config32(dev, D31F0_GPIO_ROUT, reg32);
147}
148
Elyes HAOUAS1a8c1df2018-05-13 13:36:44 +0200149static void i82801jx_power_options(struct device *dev)
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200150{
151 u8 reg8;
152 u16 reg16, pmbase;
153 u32 reg32;
154 const char *state;
155 /* Get the chip configuration */
156 config_t *config = dev->chip_info;
157
Nico Huber9faae2b2018-11-14 00:00:35 +0100158 int pwr_on = CONFIG_MAINBOARD_POWER_FAILURE_STATE;
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200159 int nmi_option;
160
161 /* BIOS must program... */
Angel Pons2048cb42020-06-08 02:09:33 +0200162 pci_or_config32(dev, 0xac, (1 << 30) | (3 << 8));
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200163
164 /* Which state do we want to goto after g3 (power restored)?
165 * 0 == S0 Full On
166 * 1 == S5 Soft Off
167 *
168 * If the option is not existent (Laptops), use MAINBOARD_POWER_ON.
169 */
170 pwr_on = MAINBOARD_POWER_ON;
171 get_option(&pwr_on, "power_on_after_fail");
172
173 reg8 = pci_read_config8(dev, D31F0_GEN_PMCON_3);
174 reg8 &= 0xfe;
175 switch (pwr_on) {
176 case MAINBOARD_POWER_OFF:
177 reg8 |= 1;
178 state = "off";
179 break;
180 case MAINBOARD_POWER_ON:
181 reg8 &= ~1;
182 state = "on";
183 break;
184 case MAINBOARD_POWER_KEEP:
185 reg8 &= ~1;
186 state = "state keep";
187 break;
188 default:
189 state = "undefined";
190 }
191
192 reg8 |= (3 << 4); /* avoid #S4 assertions */
Elyes HAOUASdc413712021-02-07 20:54:53 +0100193 reg8 &= ~(1 << 3); /* minimum assertion is 1 to 2 RTCCLK */
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200194
195 pci_write_config8(dev, D31F0_GEN_PMCON_3, reg8);
196 printk(BIOS_INFO, "Set power %s after power failure.\n", state);
197
198 /* Set up NMI on errors. */
199 reg8 = inb(0x61);
200 reg8 &= 0x0f; /* Higher Nibble must be 0 */
201 reg8 &= ~(1 << 3); /* IOCHK# NMI Enable */
202 // reg8 &= ~(1 << 2); /* PCI SERR# Enable */
203 reg8 |= (1 << 2); /* PCI SERR# Disable for now */
204 outb(reg8, 0x61);
205
206 reg8 = inb(0x74); /* Read from 0x74 as 0x70 is write only. */
207 nmi_option = NMI_OFF;
208 get_option(&nmi_option, "nmi");
209 if (nmi_option) {
210 printk(BIOS_INFO, "NMI sources enabled.\n");
211 reg8 &= ~(1 << 7); /* Set NMI. */
212 } else {
213 printk(BIOS_INFO, "NMI sources disabled.\n");
Elyes HAOUAS9c5d4632018-04-26 22:21:21 +0200214 reg8 |= (1 << 7); /* Can't mask NMI from PCI-E and NMI_NOW */
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200215 }
216 outb(reg8, 0x70);
217
218 /* Enable CPU_SLP# and Intel Speedstep, set SMI# rate down */
219 reg16 = pci_read_config16(dev, D31F0_GEN_PMCON_1);
220 reg16 &= ~(3 << 0); // SMI# rate 1 minute
221 reg16 |= (1 << 2); // CLKRUN_EN - Mobile/Ultra only
222 reg16 |= (1 << 3); // Speedstep Enable - Mobile/Ultra only
223 reg16 |= (1 << 5); // CPUSLP_EN Desktop only
224
225 if (config->c4onc3_enable)
226 reg16 |= (1 << 7);
227
228 // another laptop wants this?
229 // reg16 &= ~(1 << 10); // BIOS_PCI_EXP_EN - Desktop/Mobile only
230 reg16 |= (1 << 10); // BIOS_PCI_EXP_EN - Desktop/Mobile only
Kyösti Mälkki94464472020-06-13 13:45:42 +0300231 if (CONFIG(DEBUG_PERIODIC_SMI))
232 reg16 |= (3 << 0); // Periodic SMI every 8s
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200233 if (config->c5_enable)
234 reg16 |= (1 << 11); /* Enable C5, C6 and PMSYNC# */
235 pci_write_config16(dev, D31F0_GEN_PMCON_1, reg16);
236
237 /* Set exit timings for C5/C6. */
238 if (config->c5_enable) {
239 reg8 = pci_read_config8(dev, D31F0_C5_EXIT_TIMING);
240 reg8 &= ~((7 << 3) | (7 << 0));
241 if (config->c6_enable)
242 reg8 |= (5 << 3) | (3 << 0); /* 38-44us PMSYNC# to STPCLK#,
243 95-102us DPRSTP# to STP_CPU# */
244 else
245 reg8 |= (0 << 3) | (1 << 0); /* 16-17us PMSYNC# to STPCLK#,
246 34-40us DPRSTP# to STP_CPU# */
247 pci_write_config8(dev, D31F0_C5_EXIT_TIMING, reg8);
248 }
249
250 // Set the board's GPI routing.
Arthur Heymans349e0852017-04-09 20:48:37 +0200251 i82801jx_gpi_routing(dev);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200252
253 pmbase = pci_read_config16(dev, 0x40) & 0xfffe;
254
255 outl(config->gpe0_en, pmbase + 0x28);
256 outw(config->alt_gp_smi_en, pmbase + 0x38);
257
258 /* Set up power management block and determine sleep mode */
259 reg16 = inw(pmbase + 0x00); /* PM1_STS */
260 outw(reg16, pmbase + 0x00); /* Clear status bits. At least bit11 (power
261 button override) must be cleared or SCI
262 will be constantly fired and OSPM must
263 not know about it (ACPI spec says to
264 ignore the bit). */
265 reg32 = inl(pmbase + 0x04); // PM1_CNT
266 reg32 &= ~(7 << 10); // SLP_TYP
267 outl(reg32, pmbase + 0x04);
268
269 /* Set duty cycle for hardware throttling (defaults to 0x0: 50%). */
270 reg32 = inl(pmbase + 0x10);
271 reg32 &= ~(7 << 5);
272 reg32 |= (config->throttle_duty & 7) << 5;
273 outl(reg32, pmbase + 0x10);
274}
275
Arthur Heymans349e0852017-04-09 20:48:37 +0200276static void i82801jx_rtc_init(struct device *dev)
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200277{
278 u8 reg8;
279 int rtc_failed;
280
281 reg8 = pci_read_config8(dev, D31F0_GEN_PMCON_3);
282 rtc_failed = reg8 & RTC_BATTERY_DEAD;
283 if (rtc_failed) {
284 reg8 &= ~RTC_BATTERY_DEAD;
285 pci_write_config8(dev, D31F0_GEN_PMCON_3, reg8);
286 }
287 printk(BIOS_DEBUG, "rtc_failed = 0x%x\n", rtc_failed);
288
289 cmos_init(rtc_failed);
290}
291
292static void enable_hpet(void)
293{
294 u32 reg32;
295
296 /* Move HPET to default address 0xfed00000 and enable it */
297 reg32 = RCBA32(RCBA_HPTC);
298 reg32 |= (1 << 7); // HPET Address Enable
299 reg32 &= ~(3 << 0);
300 RCBA32(RCBA_HPTC) = reg32;
301}
302
303static void enable_clock_gating(void)
304{
305 u32 reg32;
306
307 /* Enable DMI dynamic clock gating. */
308 RCBA32(RCBA_DMIC) |= 3;
309
310 /* Enable Clock Gating for most devices. */
311 reg32 = RCBA32(RCBA_CG);
312 reg32 |= (1 << 31); /* LPC dynamic clock gating */
313 /* USB UHCI dynamic clock gating: */
314 reg32 |= (1 << 29) | (1 << 28);
315 /* SATA dynamic clock gating [0-3]: */
316 reg32 |= (1 << 27) | (1 << 26) | (1 << 25) | (1 << 24);
317 reg32 |= (1 << 23); /* LAN static clock gating (if LAN disabled) */
318 reg32 |= (1 << 22); /* HD audio dynamic clock gating */
319 reg32 &= ~(1 << 21); /* No HD audio static clock gating */
320 reg32 &= ~(1 << 20); /* No USB EHCI static clock gating */
321 reg32 |= (1 << 19); /* USB EHCI dynamic clock gating */
322 /* More SATA dynamic clock gating [4-5]: */
323 reg32 |= (1 << 18) | (1 << 17);
324 reg32 |= (1 << 16); /* PCI dynamic clock gating */
325 /* PCIe, DMI dynamic clock gating: */
326 reg32 |= (1 << 4) | (1 << 3) | (1 << 2) | (1 << 1);
327 reg32 |= (1 << 0); /* PCIe root port static clock gating */
328 RCBA32(RCBA_CG) = reg32;
329
330 /* Enable SPI dynamic clock gating. */
331 RCBA32(0x38c0) |= 7;
332}
333
Kyösti Mälkki83d6a8a2019-07-12 08:16:53 +0300334static void i82801jx_set_acpi_mode(struct device *dev)
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200335{
Kyösti Mälkkiad882c32020-06-02 05:05:30 +0300336 if (!acpi_is_wakeup_s3()) {
337 apm_control(APM_CNT_ACPI_DISABLE);
338 } else {
339 apm_control(APM_CNT_ACPI_ENABLE);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200340 }
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200341}
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200342
343static void lpc_init(struct device *dev)
344{
Elyes HAOUASbfc255a2020-03-07 13:05:14 +0100345 printk(BIOS_DEBUG, "i82801jx: %s\n", __func__);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200346
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200347 /* IO APIC initialization. */
Arthur Heymans349e0852017-04-09 20:48:37 +0200348 i82801jx_enable_apic(dev);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200349
Arthur Heymans349e0852017-04-09 20:48:37 +0200350 i82801jx_enable_serial_irqs(dev);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200351
352 /* Setup the PIRQ. */
Arthur Heymans349e0852017-04-09 20:48:37 +0200353 i82801jx_pirq_init(dev);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200354
355 /* Setup power options. */
Arthur Heymans349e0852017-04-09 20:48:37 +0200356 i82801jx_power_options(dev);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200357
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200358 /* Initialize the real time clock. */
Arthur Heymans349e0852017-04-09 20:48:37 +0200359 i82801jx_rtc_init(dev);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200360
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 i82801jx_set_acpi_mode(dev);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200377}
378
Arthur Heymansad501492017-04-12 00:15:39 +0200379unsigned long acpi_fill_madt(unsigned long current)
380{
381 /* Local APICs */
382 current = acpi_create_madt_lapics(current);
383
384 /* IOAPIC */
385 current += acpi_create_madt_ioapic((acpi_madt_ioapic_t *) current,
386 2, IO_APIC_ADDR, 0);
387
388 /* LAPIC_NMI */
389 current += acpi_create_madt_lapic_nmi((acpi_madt_lapic_nmi_t *)
390 current, 0,
391 MP_IRQ_POLARITY_HIGH |
392 MP_IRQ_TRIGGER_EDGE, 0x01);
393 current += acpi_create_madt_lapic_nmi((acpi_madt_lapic_nmi_t *)
394 current, 1, MP_IRQ_POLARITY_HIGH |
395 MP_IRQ_TRIGGER_EDGE, 0x01);
396
397 /* INT_SRC_OVR */
398 current += acpi_create_madt_irqoverride((acpi_madt_irqoverride_t *)
399 current, 0, 0, 2, MP_IRQ_POLARITY_HIGH | MP_IRQ_TRIGGER_EDGE);
400 current += acpi_create_madt_irqoverride((acpi_madt_irqoverride_t *)
401 current, 0, 9, 9, MP_IRQ_POLARITY_HIGH | MP_IRQ_TRIGGER_LEVEL);
402
Arthur Heymansad501492017-04-12 00:15:39 +0200403 return current;
404}
405
Elyes HAOUAS1a8c1df2018-05-13 13:36:44 +0200406static void i82801jx_lpc_read_resources(struct device *dev)
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200407{
Arthur Heymanse5dcaf12017-04-12 00:03:37 +0200408 int i, io_index = 0;
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200409 /*
410 * I/O Resources
411 *
412 * 0x0000 - 0x000f....ISA DMA
413 * 0x0010 - 0x001f....ISA DMA aliases
414 * 0x0020 ~ 0x003d....PIC
415 * 0x002e - 0x002f....Maybe Super I/O
416 * 0x0040 - 0x0043....Timer
417 * 0x004e - 0x004f....Maybe Super I/O
418 * 0x0050 - 0x0053....Timer aliases
419 * 0x0061.............NMI_SC
420 * 0x0070.............NMI_EN (readable in alternative access mode)
421 * 0x0070 - 0x0077....RTC
422 * 0x0080 - 0x008f....ISA DMA
423 * 0x0090 ~ 0x009f....ISA DMA aliases
424 * 0x0092.............Fast A20 and Init
425 * 0x00a0 ~ 0x00bd....PIC
426 * 0x00b2 - 0x00b3....APM
427 * 0x00c0 ~ 0x00de....ISA DMA
428 * 0x00c1 ~ 0x00df....ISA DMA aliases
429 * 0x00f0.............Coprocessor Error
Angel Ponsb21bffa2020-07-03 01:02:28 +0200430 * (0x0400-0x041f)....SMBus (CONFIG_FIXED_SMBUS_IO_BASE, during raminit)
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200431 * 0x04d0 - 0x04d1....PIC
432 * 0x0500 - 0x057f....PM (DEFAULT_PMBASE)
433 * 0x0580 - 0x05bf....SB GPIO (DEFAULT_GPIOBASE)
434 * 0x05c0 - 0x05ff....SB GPIO cont. (mobile only)
435 * 0x0cf8 - 0x0cff....PCI
436 * 0x0cf9.............Reset Control
437 */
438
439 struct resource *res;
440
441 /* Get the normal PCI resources of this device. */
442 pci_dev_read_resources(dev);
443
444 /* Add an extra subtractive resource for both memory and I/O. */
Arthur Heymanse5dcaf12017-04-12 00:03:37 +0200445 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200446 res->base = 0;
447 res->size = 0x1000;
448 res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
449 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
450
Arthur Heymanse5dcaf12017-04-12 00:03:37 +0200451 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
452 res->base = 0xff000000;
453 res->size = 0x01000000; /* 16 MB for flash */
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200454 res->flags = IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE |
455 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
456
457 res = new_resource(dev, 3); /* IOAPIC */
458 res->base = IO_APIC_ADDR;
459 res->size = 0x00001000;
460 res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
Arthur Heymanse5dcaf12017-04-12 00:03:37 +0200461
462 /* Set IO decode ranges if required.*/
463 for (i = 0; i < 4; i++) {
464 u32 gen_dec;
465 gen_dec = pci_read_config32(dev, 0x84 + 4 * i);
466
467 if ((gen_dec & 0xFFFC) > 0x1000) {
468 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
469 res->base = gen_dec & 0xFFFC;
470 res->size = (gen_dec >> 16) & 0xFC;
471 res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
472 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
473 }
474 }
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200475}
476
Arthur Heymansa8a9f342017-12-24 08:11:13 +0100477static const char *lpc_acpi_name(const struct device *dev)
478{
479 return "LPCB";
480}
481
Furquan Shaikh7536a392020-04-24 21:59:21 -0700482static void southbridge_fill_ssdt(const struct device *device)
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200483{
Kyösti Mälkkic70eed12018-05-22 02:18:00 +0300484 struct device *dev = pcidev_on_root(0x1f, 0);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200485 config_t *chip = dev->chip_info;
486
487 intel_acpi_pcie_hotplug_generator(chip->pcie_hotplug_map, 8);
Arthur Heymansa8a9f342017-12-24 08:11:13 +0100488 intel_acpi_gen_def_acpi_pirq(device);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200489}
490
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200491static struct device_operations device_ops = {
Arthur Heymans349e0852017-04-09 20:48:37 +0200492 .read_resources = i82801jx_lpc_read_resources,
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200493 .set_resources = pci_dev_set_resources,
494 .enable_resources = pci_dev_enable_resources,
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200495 .write_acpi_tables = acpi_write_hpet,
Nico Huber68680dd2020-03-31 17:34:52 +0200496 .acpi_fill_ssdt = southbridge_fill_ssdt,
Arthur Heymansa8a9f342017-12-24 08:11:13 +0100497 .acpi_name = lpc_acpi_name,
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200498 .init = lpc_init,
Nico Huber51b75ae2019-03-14 16:02:05 +0100499 .scan_bus = scan_static_bus,
Angel Pons1fc0edd2020-05-31 00:03:28 +0200500 .ops_pci = &pci_dev_ops_pci,
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200501};
502
503static const unsigned short pci_device_ids[] = {
Arthur Heymans349e0852017-04-09 20:48:37 +0200504 0x3a10, /* ICH10R Eng. Sample */
505 0x3a14, /* ICH10DO */
506 0x3a16, /* ICH10R */
507 0x3a18, /* ICH10 */
508 0x3a1a, /* ICH10D */
509 0x3a1e, /* ICH10 Eng. Sample */
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200510 0
511};
512
Arthur Heymans349e0852017-04-09 20:48:37 +0200513static const struct pci_driver ich10_lpc __pci_driver = {
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200514 .ops = &device_ops,
515 .vendor = PCI_VENDOR_ID_INTEL,
516 .devices = pci_device_ids,
517};