blob: 55b4746c28ae5a2a46bd2038ae04e04a045aeb96 [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{
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
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200158 /* BIOS must program... */
Angel Pons2048cb42020-06-08 02:09:33 +0200159 pci_or_config32(dev, 0xac, (1 << 30) | (3 << 8));
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200160
161 /* Which state do we want to goto after g3 (power restored)?
162 * 0 == S0 Full On
163 * 1 == S5 Soft Off
164 *
165 * If the option is not existent (Laptops), use MAINBOARD_POWER_ON.
166 */
Angel Pons62719a32021-04-19 13:15:28 +0200167 const int pwr_on = get_int_option("power_on_after_fail", MAINBOARD_POWER_ON);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200168
169 reg8 = pci_read_config8(dev, D31F0_GEN_PMCON_3);
170 reg8 &= 0xfe;
171 switch (pwr_on) {
172 case MAINBOARD_POWER_OFF:
173 reg8 |= 1;
174 state = "off";
175 break;
176 case MAINBOARD_POWER_ON:
177 reg8 &= ~1;
178 state = "on";
179 break;
180 case MAINBOARD_POWER_KEEP:
181 reg8 &= ~1;
182 state = "state keep";
183 break;
184 default:
185 state = "undefined";
186 }
187
188 reg8 |= (3 << 4); /* avoid #S4 assertions */
Elyes HAOUASdc413712021-02-07 20:54:53 +0100189 reg8 &= ~(1 << 3); /* minimum assertion is 1 to 2 RTCCLK */
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200190
191 pci_write_config8(dev, D31F0_GEN_PMCON_3, reg8);
192 printk(BIOS_INFO, "Set power %s after power failure.\n", state);
193
194 /* Set up NMI on errors. */
195 reg8 = inb(0x61);
196 reg8 &= 0x0f; /* Higher Nibble must be 0 */
197 reg8 &= ~(1 << 3); /* IOCHK# NMI Enable */
198 // reg8 &= ~(1 << 2); /* PCI SERR# Enable */
199 reg8 |= (1 << 2); /* PCI SERR# Disable for now */
200 outb(reg8, 0x61);
201
202 reg8 = inb(0x74); /* Read from 0x74 as 0x70 is write only. */
Angel Pons62719a32021-04-19 13:15:28 +0200203 const int nmi_option = get_int_option("nmi", NMI_OFF);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200204 if (nmi_option) {
205 printk(BIOS_INFO, "NMI sources enabled.\n");
206 reg8 &= ~(1 << 7); /* Set NMI. */
207 } else {
208 printk(BIOS_INFO, "NMI sources disabled.\n");
Elyes HAOUAS9c5d4632018-04-26 22:21:21 +0200209 reg8 |= (1 << 7); /* Can't mask NMI from PCI-E and NMI_NOW */
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200210 }
211 outb(reg8, 0x70);
212
213 /* Enable CPU_SLP# and Intel Speedstep, set SMI# rate down */
214 reg16 = pci_read_config16(dev, D31F0_GEN_PMCON_1);
215 reg16 &= ~(3 << 0); // SMI# rate 1 minute
216 reg16 |= (1 << 2); // CLKRUN_EN - Mobile/Ultra only
217 reg16 |= (1 << 3); // Speedstep Enable - Mobile/Ultra only
218 reg16 |= (1 << 5); // CPUSLP_EN Desktop only
219
220 if (config->c4onc3_enable)
221 reg16 |= (1 << 7);
222
223 // another laptop wants this?
224 // reg16 &= ~(1 << 10); // BIOS_PCI_EXP_EN - Desktop/Mobile only
225 reg16 |= (1 << 10); // BIOS_PCI_EXP_EN - Desktop/Mobile only
Kyösti Mälkki94464472020-06-13 13:45:42 +0300226 if (CONFIG(DEBUG_PERIODIC_SMI))
227 reg16 |= (3 << 0); // Periodic SMI every 8s
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200228 if (config->c5_enable)
229 reg16 |= (1 << 11); /* Enable C5, C6 and PMSYNC# */
230 pci_write_config16(dev, D31F0_GEN_PMCON_1, reg16);
231
232 /* Set exit timings for C5/C6. */
233 if (config->c5_enable) {
234 reg8 = pci_read_config8(dev, D31F0_C5_EXIT_TIMING);
235 reg8 &= ~((7 << 3) | (7 << 0));
236 if (config->c6_enable)
237 reg8 |= (5 << 3) | (3 << 0); /* 38-44us PMSYNC# to STPCLK#,
238 95-102us DPRSTP# to STP_CPU# */
239 else
240 reg8 |= (0 << 3) | (1 << 0); /* 16-17us PMSYNC# to STPCLK#,
241 34-40us DPRSTP# to STP_CPU# */
242 pci_write_config8(dev, D31F0_C5_EXIT_TIMING, reg8);
243 }
244
245 // Set the board's GPI routing.
Arthur Heymans349e0852017-04-09 20:48:37 +0200246 i82801jx_gpi_routing(dev);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200247
248 pmbase = pci_read_config16(dev, 0x40) & 0xfffe;
249
250 outl(config->gpe0_en, pmbase + 0x28);
251 outw(config->alt_gp_smi_en, pmbase + 0x38);
252
253 /* Set up power management block and determine sleep mode */
254 reg16 = inw(pmbase + 0x00); /* PM1_STS */
255 outw(reg16, pmbase + 0x00); /* Clear status bits. At least bit11 (power
256 button override) must be cleared or SCI
257 will be constantly fired and OSPM must
258 not know about it (ACPI spec says to
259 ignore the bit). */
260 reg32 = inl(pmbase + 0x04); // PM1_CNT
261 reg32 &= ~(7 << 10); // SLP_TYP
262 outl(reg32, pmbase + 0x04);
263
264 /* Set duty cycle for hardware throttling (defaults to 0x0: 50%). */
265 reg32 = inl(pmbase + 0x10);
266 reg32 &= ~(7 << 5);
267 reg32 |= (config->throttle_duty & 7) << 5;
268 outl(reg32, pmbase + 0x10);
269}
270
Arthur Heymans349e0852017-04-09 20:48:37 +0200271static void i82801jx_rtc_init(struct device *dev)
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200272{
273 u8 reg8;
274 int rtc_failed;
275
276 reg8 = pci_read_config8(dev, D31F0_GEN_PMCON_3);
277 rtc_failed = reg8 & RTC_BATTERY_DEAD;
278 if (rtc_failed) {
279 reg8 &= ~RTC_BATTERY_DEAD;
280 pci_write_config8(dev, D31F0_GEN_PMCON_3, reg8);
281 }
282 printk(BIOS_DEBUG, "rtc_failed = 0x%x\n", rtc_failed);
283
284 cmos_init(rtc_failed);
285}
286
287static void enable_hpet(void)
288{
289 u32 reg32;
290
291 /* Move HPET to default address 0xfed00000 and enable it */
292 reg32 = RCBA32(RCBA_HPTC);
293 reg32 |= (1 << 7); // HPET Address Enable
294 reg32 &= ~(3 << 0);
295 RCBA32(RCBA_HPTC) = reg32;
296}
297
298static void enable_clock_gating(void)
299{
300 u32 reg32;
301
302 /* Enable DMI dynamic clock gating. */
303 RCBA32(RCBA_DMIC) |= 3;
304
305 /* Enable Clock Gating for most devices. */
306 reg32 = RCBA32(RCBA_CG);
307 reg32 |= (1 << 31); /* LPC dynamic clock gating */
308 /* USB UHCI dynamic clock gating: */
309 reg32 |= (1 << 29) | (1 << 28);
310 /* SATA dynamic clock gating [0-3]: */
311 reg32 |= (1 << 27) | (1 << 26) | (1 << 25) | (1 << 24);
312 reg32 |= (1 << 23); /* LAN static clock gating (if LAN disabled) */
313 reg32 |= (1 << 22); /* HD audio dynamic clock gating */
314 reg32 &= ~(1 << 21); /* No HD audio static clock gating */
315 reg32 &= ~(1 << 20); /* No USB EHCI static clock gating */
316 reg32 |= (1 << 19); /* USB EHCI dynamic clock gating */
317 /* More SATA dynamic clock gating [4-5]: */
318 reg32 |= (1 << 18) | (1 << 17);
319 reg32 |= (1 << 16); /* PCI dynamic clock gating */
320 /* PCIe, DMI dynamic clock gating: */
321 reg32 |= (1 << 4) | (1 << 3) | (1 << 2) | (1 << 1);
322 reg32 |= (1 << 0); /* PCIe root port static clock gating */
323 RCBA32(RCBA_CG) = reg32;
324
325 /* Enable SPI dynamic clock gating. */
326 RCBA32(0x38c0) |= 7;
327}
328
Kyösti Mälkki83d6a8a2019-07-12 08:16:53 +0300329static void i82801jx_set_acpi_mode(struct device *dev)
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200330{
Kyösti Mälkkiad882c32020-06-02 05:05:30 +0300331 if (!acpi_is_wakeup_s3()) {
332 apm_control(APM_CNT_ACPI_DISABLE);
333 } else {
334 apm_control(APM_CNT_ACPI_ENABLE);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200335 }
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200336}
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200337
338static void lpc_init(struct device *dev)
339{
Elyes HAOUASbfc255a2020-03-07 13:05:14 +0100340 printk(BIOS_DEBUG, "i82801jx: %s\n", __func__);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200341
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200342 /* IO APIC initialization. */
Arthur Heymans349e0852017-04-09 20:48:37 +0200343 i82801jx_enable_apic(dev);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200344
Arthur Heymans349e0852017-04-09 20:48:37 +0200345 i82801jx_enable_serial_irqs(dev);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200346
347 /* Setup the PIRQ. */
Arthur Heymans349e0852017-04-09 20:48:37 +0200348 i82801jx_pirq_init(dev);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200349
350 /* Setup power options. */
Arthur Heymans349e0852017-04-09 20:48:37 +0200351 i82801jx_power_options(dev);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200352
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200353 /* Initialize the real time clock. */
Arthur Heymans349e0852017-04-09 20:48:37 +0200354 i82801jx_rtc_init(dev);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200355
356 /* Initialize ISA DMA. */
357 isa_dma_init();
358
359 /* Initialize the High Precision Event Timers, if present. */
360 enable_hpet();
361
362 /* Initialize Clock Gating */
363 enable_clock_gating();
364
365 setup_i8259();
366
367 /* The OS should do this? */
368 /* Interrupt 9 should be level triggered (SCI) */
369 i8259_configure_irq_trigger(9, 1);
370
Kyösti Mälkki44da9e72019-10-09 12:32:16 +0300371 i82801jx_set_acpi_mode(dev);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200372}
373
Arthur Heymansad501492017-04-12 00:15:39 +0200374unsigned long acpi_fill_madt(unsigned long current)
375{
376 /* Local APICs */
377 current = acpi_create_madt_lapics(current);
378
379 /* IOAPIC */
380 current += acpi_create_madt_ioapic((acpi_madt_ioapic_t *) current,
381 2, IO_APIC_ADDR, 0);
382
383 /* LAPIC_NMI */
384 current += acpi_create_madt_lapic_nmi((acpi_madt_lapic_nmi_t *)
385 current, 0,
386 MP_IRQ_POLARITY_HIGH |
387 MP_IRQ_TRIGGER_EDGE, 0x01);
388 current += acpi_create_madt_lapic_nmi((acpi_madt_lapic_nmi_t *)
389 current, 1, MP_IRQ_POLARITY_HIGH |
390 MP_IRQ_TRIGGER_EDGE, 0x01);
391
392 /* INT_SRC_OVR */
393 current += acpi_create_madt_irqoverride((acpi_madt_irqoverride_t *)
394 current, 0, 0, 2, MP_IRQ_POLARITY_HIGH | MP_IRQ_TRIGGER_EDGE);
395 current += acpi_create_madt_irqoverride((acpi_madt_irqoverride_t *)
396 current, 0, 9, 9, MP_IRQ_POLARITY_HIGH | MP_IRQ_TRIGGER_LEVEL);
397
Arthur Heymansad501492017-04-12 00:15:39 +0200398 return current;
399}
400
Elyes HAOUAS1a8c1df2018-05-13 13:36:44 +0200401static void i82801jx_lpc_read_resources(struct device *dev)
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200402{
Arthur Heymanse5dcaf12017-04-12 00:03:37 +0200403 int i, io_index = 0;
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200404 /*
405 * I/O Resources
406 *
407 * 0x0000 - 0x000f....ISA DMA
408 * 0x0010 - 0x001f....ISA DMA aliases
409 * 0x0020 ~ 0x003d....PIC
410 * 0x002e - 0x002f....Maybe Super I/O
411 * 0x0040 - 0x0043....Timer
412 * 0x004e - 0x004f....Maybe Super I/O
413 * 0x0050 - 0x0053....Timer aliases
414 * 0x0061.............NMI_SC
415 * 0x0070.............NMI_EN (readable in alternative access mode)
416 * 0x0070 - 0x0077....RTC
417 * 0x0080 - 0x008f....ISA DMA
418 * 0x0090 ~ 0x009f....ISA DMA aliases
419 * 0x0092.............Fast A20 and Init
420 * 0x00a0 ~ 0x00bd....PIC
421 * 0x00b2 - 0x00b3....APM
422 * 0x00c0 ~ 0x00de....ISA DMA
423 * 0x00c1 ~ 0x00df....ISA DMA aliases
424 * 0x00f0.............Coprocessor Error
Angel Ponsb21bffa2020-07-03 01:02:28 +0200425 * (0x0400-0x041f)....SMBus (CONFIG_FIXED_SMBUS_IO_BASE, during raminit)
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200426 * 0x04d0 - 0x04d1....PIC
427 * 0x0500 - 0x057f....PM (DEFAULT_PMBASE)
428 * 0x0580 - 0x05bf....SB GPIO (DEFAULT_GPIOBASE)
429 * 0x05c0 - 0x05ff....SB GPIO cont. (mobile only)
430 * 0x0cf8 - 0x0cff....PCI
431 * 0x0cf9.............Reset Control
432 */
433
434 struct resource *res;
435
436 /* Get the normal PCI resources of this device. */
437 pci_dev_read_resources(dev);
438
439 /* Add an extra subtractive resource for both memory and I/O. */
Arthur Heymanse5dcaf12017-04-12 00:03:37 +0200440 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200441 res->base = 0;
442 res->size = 0x1000;
443 res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
444 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
445
Arthur Heymanse5dcaf12017-04-12 00:03:37 +0200446 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
447 res->base = 0xff000000;
448 res->size = 0x01000000; /* 16 MB for flash */
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200449 res->flags = IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE |
450 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
451
452 res = new_resource(dev, 3); /* IOAPIC */
453 res->base = IO_APIC_ADDR;
454 res->size = 0x00001000;
455 res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
Arthur Heymanse5dcaf12017-04-12 00:03:37 +0200456
457 /* Set IO decode ranges if required.*/
458 for (i = 0; i < 4; i++) {
459 u32 gen_dec;
460 gen_dec = pci_read_config32(dev, 0x84 + 4 * i);
461
462 if ((gen_dec & 0xFFFC) > 0x1000) {
463 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
464 res->base = gen_dec & 0xFFFC;
465 res->size = (gen_dec >> 16) & 0xFC;
466 res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
467 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
468 }
469 }
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200470}
471
Arthur Heymansa8a9f342017-12-24 08:11:13 +0100472static const char *lpc_acpi_name(const struct device *dev)
473{
474 return "LPCB";
475}
476
Furquan Shaikh7536a392020-04-24 21:59:21 -0700477static void southbridge_fill_ssdt(const struct device *device)
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200478{
Kyösti Mälkkic70eed12018-05-22 02:18:00 +0300479 struct device *dev = pcidev_on_root(0x1f, 0);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200480 config_t *chip = dev->chip_info;
481
482 intel_acpi_pcie_hotplug_generator(chip->pcie_hotplug_map, 8);
Arthur Heymansa8a9f342017-12-24 08:11:13 +0100483 intel_acpi_gen_def_acpi_pirq(device);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200484}
485
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200486static struct device_operations device_ops = {
Arthur Heymans349e0852017-04-09 20:48:37 +0200487 .read_resources = i82801jx_lpc_read_resources,
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200488 .set_resources = pci_dev_set_resources,
489 .enable_resources = pci_dev_enable_resources,
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200490 .write_acpi_tables = acpi_write_hpet,
Nico Huber68680dd2020-03-31 17:34:52 +0200491 .acpi_fill_ssdt = southbridge_fill_ssdt,
Arthur Heymansa8a9f342017-12-24 08:11:13 +0100492 .acpi_name = lpc_acpi_name,
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200493 .init = lpc_init,
Nico Huber51b75ae2019-03-14 16:02:05 +0100494 .scan_bus = scan_static_bus,
Angel Pons1fc0edd2020-05-31 00:03:28 +0200495 .ops_pci = &pci_dev_ops_pci,
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200496};
497
498static const unsigned short pci_device_ids[] = {
Arthur Heymans349e0852017-04-09 20:48:37 +0200499 0x3a10, /* ICH10R Eng. Sample */
500 0x3a14, /* ICH10DO */
501 0x3a16, /* ICH10R */
502 0x3a18, /* ICH10 */
503 0x3a1a, /* ICH10D */
504 0x3a1e, /* ICH10 Eng. Sample */
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200505 0
506};
507
Arthur Heymans349e0852017-04-09 20:48:37 +0200508static const struct pci_driver ich10_lpc __pci_driver = {
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200509 .ops = &device_ops,
510 .vendor = PCI_VENDOR_ID_INTEL,
511 .devices = pci_device_ids,
512};