blob: 07cf5274a57cf3bafcb416afacf4fe7a8d362369 [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 <cbmem.h>
19#include <string.h>
Kyösti Mälkki12b121c2019-08-18 16:33:39 +030020#include "chip.h"
Arthur Heymans349e0852017-04-09 20:48:37 +020021#include "i82801jx.h"
Arthur Heymans7b9c1392017-04-09 20:40:39 +020022#include "nvs.h"
23#include <southbridge/intel/common/pciehp.h>
Arthur Heymansa8a9f342017-12-24 08:11:13 +010024#include <southbridge/intel/common/acpi_pirq_gen.h>
Arthur Heymans7b9c1392017-04-09 20:40:39 +020025
26#define NMI_OFF 0
27
Arthur Heymans349e0852017-04-09 20:48:37 +020028typedef struct southbridge_intel_i82801jx_config config_t;
Arthur Heymans7b9c1392017-04-09 20:40:39 +020029
Arthur Heymans349e0852017-04-09 20:48:37 +020030static void i82801jx_enable_apic(struct device *dev)
Arthur Heymans7b9c1392017-04-09 20:40:39 +020031{
32 u32 reg32;
33 volatile u32 *ioapic_index = (volatile u32 *)(IO_APIC_ADDR);
34 volatile u32 *ioapic_data = (volatile u32 *)(IO_APIC_ADDR + 0x10);
35
36 /* Enable IOAPIC. Keep APIC Range Select at zero. */
37 RCBA8(0x31ff) = 0x03;
38 /* We have to read 0x31ff back if bit0 changed. */
39 RCBA8(0x31ff);
40
41 /* Lock maximum redirection entries (MRE), R/WO register. */
42 *ioapic_index = 0x01;
43 reg32 = *ioapic_data;
44 *ioapic_index = 0x01;
45 *ioapic_data = reg32;
46
47 setup_ioapic(VIO_APIC_VADDR, 2); /* ICH7 code uses id 2. */
48}
49
Arthur Heymans349e0852017-04-09 20:48:37 +020050static void i82801jx_enable_serial_irqs(struct device *dev)
Arthur Heymans7b9c1392017-04-09 20:40:39 +020051{
52 /* Set packet length and toggle silent mode bit for one frame. */
53 pci_write_config8(dev, D31F0_SERIRQ_CNTL,
54 (1 << 7) | (1 << 6) | ((21 - 17) << 2) | (0 << 0));
55}
56
57/* PIRQ[n]_ROUT[3:0] - PIRQ Routing Control
58 * 0x00 - 0000 = Reserved
59 * 0x01 - 0001 = Reserved
60 * 0x02 - 0010 = Reserved
61 * 0x03 - 0011 = IRQ3
62 * 0x04 - 0100 = IRQ4
63 * 0x05 - 0101 = IRQ5
64 * 0x06 - 0110 = IRQ6
65 * 0x07 - 0111 = IRQ7
66 * 0x08 - 1000 = Reserved
67 * 0x09 - 1001 = IRQ9
68 * 0x0A - 1010 = IRQ10
69 * 0x0B - 1011 = IRQ11
70 * 0x0C - 1100 = IRQ12
71 * 0x0D - 1101 = Reserved
72 * 0x0E - 1110 = IRQ14
73 * 0x0F - 1111 = IRQ15
74 * PIRQ[n]_ROUT[7] - PIRQ Routing Control
75 * 0x80 - The PIRQ is not routed.
76 */
77
Elyes HAOUAS1a8c1df2018-05-13 13:36:44 +020078static void i82801jx_pirq_init(struct device *dev)
Arthur Heymans7b9c1392017-04-09 20:40:39 +020079{
Elyes HAOUAS1a8c1df2018-05-13 13:36:44 +020080 struct device *irq_dev;
Arthur Heymans7b9c1392017-04-09 20:40:39 +020081
Arthur Heymans87af36a2017-04-12 10:53:30 +020082 /* Interrupt 11 is not used by legacy devices and so can always be used
83 * for PCI interrupts. Full legacy IRQ routing is complicated and hard
84 * to get right. Fortunately all modern OS use MSI and so it's not that
85 * big of an issue anyway. Still we have to provide a reasonable
86 * default. Using interrupt 11 for it everywhere is a working default.
87 * ACPI-aware OS can move it to any interrupt and others will just leave
88 * them at default.
89 */
90 const u8 pirq_routing = 11;
Arthur Heymans7b9c1392017-04-09 20:40:39 +020091
Arthur Heymans87af36a2017-04-12 10:53:30 +020092 pci_write_config8(dev, D31F0_PIRQA_ROUT, pirq_routing);
93 pci_write_config8(dev, D31F0_PIRQB_ROUT, pirq_routing);
94 pci_write_config8(dev, D31F0_PIRQC_ROUT, pirq_routing);
95 pci_write_config8(dev, D31F0_PIRQD_ROUT, pirq_routing);
96
97 pci_write_config8(dev, D31F0_PIRQE_ROUT, pirq_routing);
98 pci_write_config8(dev, D31F0_PIRQF_ROUT, pirq_routing);
99 pci_write_config8(dev, D31F0_PIRQG_ROUT, pirq_routing);
100 pci_write_config8(dev, D31F0_PIRQH_ROUT, pirq_routing);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200101
102 /* Eric Biederman once said we should let the OS do this.
103 * I am not so sure anymore he was right.
104 */
105
106 for (irq_dev = all_devices; irq_dev; irq_dev = irq_dev->next) {
Arthur Heymans87af36a2017-04-12 10:53:30 +0200107 u8 int_pin = 0;
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200108
109 if (!irq_dev->enabled || irq_dev->path.type != DEVICE_PATH_PCI)
110 continue;
111
112 int_pin = pci_read_config8(irq_dev, PCI_INTERRUPT_PIN);
113
Arthur Heymans87af36a2017-04-12 10:53:30 +0200114 if (int_pin == 0)
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200115 continue;
116
Arthur Heymans87af36a2017-04-12 10:53:30 +0200117 pci_write_config8(irq_dev, PCI_INTERRUPT_LINE, pirq_routing);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200118 }
119}
120
Elyes HAOUAS1a8c1df2018-05-13 13:36:44 +0200121static void i82801jx_gpi_routing(struct device *dev)
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200122{
123 /* Get the chip configuration */
124 config_t *config = dev->chip_info;
125 u32 reg32 = 0;
126
127 /* An array would be much nicer here, or some
128 * other method of doing this.
129 */
130 reg32 |= (config->gpi0_routing & 0x03) << 0;
131 reg32 |= (config->gpi1_routing & 0x03) << 2;
132 reg32 |= (config->gpi2_routing & 0x03) << 4;
133 reg32 |= (config->gpi3_routing & 0x03) << 6;
134 reg32 |= (config->gpi4_routing & 0x03) << 8;
135 reg32 |= (config->gpi5_routing & 0x03) << 10;
136 reg32 |= (config->gpi6_routing & 0x03) << 12;
137 reg32 |= (config->gpi7_routing & 0x03) << 14;
138 reg32 |= (config->gpi8_routing & 0x03) << 16;
139 reg32 |= (config->gpi9_routing & 0x03) << 18;
140 reg32 |= (config->gpi10_routing & 0x03) << 20;
141 reg32 |= (config->gpi11_routing & 0x03) << 22;
142 reg32 |= (config->gpi12_routing & 0x03) << 24;
143 reg32 |= (config->gpi13_routing & 0x03) << 26;
144 reg32 |= (config->gpi14_routing & 0x03) << 28;
145 reg32 |= (config->gpi15_routing & 0x03) << 30;
146
147 pci_write_config32(dev, D31F0_GPIO_ROUT, reg32);
148}
149
Elyes HAOUAS1a8c1df2018-05-13 13:36:44 +0200150static void i82801jx_power_options(struct device *dev)
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200151{
152 u8 reg8;
153 u16 reg16, pmbase;
154 u32 reg32;
155 const char *state;
156 /* Get the chip configuration */
157 config_t *config = dev->chip_info;
158
Nico Huber9faae2b2018-11-14 00:00:35 +0100159 int pwr_on = CONFIG_MAINBOARD_POWER_FAILURE_STATE;
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200160 int nmi_option;
161
162 /* BIOS must program... */
Angel Pons2048cb42020-06-08 02:09:33 +0200163 pci_or_config32(dev, 0xac, (1 << 30) | (3 << 8));
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200164
165 /* Which state do we want to goto after g3 (power restored)?
166 * 0 == S0 Full On
167 * 1 == S5 Soft Off
168 *
169 * If the option is not existent (Laptops), use MAINBOARD_POWER_ON.
170 */
171 pwr_on = MAINBOARD_POWER_ON;
172 get_option(&pwr_on, "power_on_after_fail");
173
174 reg8 = pci_read_config8(dev, D31F0_GEN_PMCON_3);
175 reg8 &= 0xfe;
176 switch (pwr_on) {
177 case MAINBOARD_POWER_OFF:
178 reg8 |= 1;
179 state = "off";
180 break;
181 case MAINBOARD_POWER_ON:
182 reg8 &= ~1;
183 state = "on";
184 break;
185 case MAINBOARD_POWER_KEEP:
186 reg8 &= ~1;
187 state = "state keep";
188 break;
189 default:
190 state = "undefined";
191 }
192
193 reg8 |= (3 << 4); /* avoid #S4 assertions */
194 reg8 &= ~(1 << 3); /* minimum asssertion is 1 to 2 RTCCLK */
195
196 pci_write_config8(dev, D31F0_GEN_PMCON_3, reg8);
197 printk(BIOS_INFO, "Set power %s after power failure.\n", state);
198
199 /* Set up NMI on errors. */
200 reg8 = inb(0x61);
201 reg8 &= 0x0f; /* Higher Nibble must be 0 */
202 reg8 &= ~(1 << 3); /* IOCHK# NMI Enable */
203 // reg8 &= ~(1 << 2); /* PCI SERR# Enable */
204 reg8 |= (1 << 2); /* PCI SERR# Disable for now */
205 outb(reg8, 0x61);
206
207 reg8 = inb(0x74); /* Read from 0x74 as 0x70 is write only. */
208 nmi_option = NMI_OFF;
209 get_option(&nmi_option, "nmi");
210 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 */
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200216 }
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 Heymans7b9c1392017-04-09 20:40:39 +0200234 if (config->c5_enable)
235 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. */
239 if (config->c5_enable) {
240 reg8 = pci_read_config8(dev, D31F0_C5_EXIT_TIMING);
241 reg8 &= ~((7 << 3) | (7 << 0));
242 if (config->c6_enable)
243 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.
Arthur Heymans349e0852017-04-09 20:48:37 +0200252 i82801jx_gpi_routing(dev);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200253
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). */
266 reg32 = inl(pmbase + 0x04); // PM1_CNT
267 reg32 &= ~(7 << 10); // SLP_TYP
268 outl(reg32, pmbase + 0x04);
269
270 /* Set duty cycle for hardware throttling (defaults to 0x0: 50%). */
271 reg32 = inl(pmbase + 0x10);
272 reg32 &= ~(7 << 5);
273 reg32 |= (config->throttle_duty & 7) << 5;
274 outl(reg32, pmbase + 0x10);
275}
276
Elyes HAOUAS1a8c1df2018-05-13 13:36:44 +0200277static void i82801jx_configure_cstates(struct device *dev)
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200278{
Angel Pons2048cb42020-06-08 02:09:33 +0200279 // Enable Popup & Popdown
280 pci_or_config8(dev, D31F0_CxSTATE_CNF, (1 << 4) | (1 << 3) | (1 << 2));
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200281
282 // Set Deeper Sleep configuration to recommended values
Angel Pons2048cb42020-06-08 02:09:33 +0200283 // Deeper Sleep to Stop CPU: 34-40us
284 // Deeper Sleep to Sleep: 15us
285 pci_update_config8(dev, D31F0_C4TIMING_CNT, ~0x0f, (2 << 2) | (2 << 0));
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200286
287 /* We could enable slow-C4 exit here, if someone needs it? */
288}
289
Arthur Heymans349e0852017-04-09 20:48:37 +0200290static void i82801jx_rtc_init(struct device *dev)
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200291{
292 u8 reg8;
293 int rtc_failed;
294
295 reg8 = pci_read_config8(dev, D31F0_GEN_PMCON_3);
296 rtc_failed = reg8 & RTC_BATTERY_DEAD;
297 if (rtc_failed) {
298 reg8 &= ~RTC_BATTERY_DEAD;
299 pci_write_config8(dev, D31F0_GEN_PMCON_3, reg8);
300 }
301 printk(BIOS_DEBUG, "rtc_failed = 0x%x\n", rtc_failed);
302
303 cmos_init(rtc_failed);
304}
305
306static void enable_hpet(void)
307{
308 u32 reg32;
309
310 /* Move HPET to default address 0xfed00000 and enable it */
311 reg32 = RCBA32(RCBA_HPTC);
312 reg32 |= (1 << 7); // HPET Address Enable
313 reg32 &= ~(3 << 0);
314 RCBA32(RCBA_HPTC) = reg32;
315}
316
317static void enable_clock_gating(void)
318{
319 u32 reg32;
320
321 /* Enable DMI dynamic clock gating. */
322 RCBA32(RCBA_DMIC) |= 3;
323
324 /* Enable Clock Gating for most devices. */
325 reg32 = RCBA32(RCBA_CG);
326 reg32 |= (1 << 31); /* LPC dynamic clock gating */
327 /* USB UHCI dynamic clock gating: */
328 reg32 |= (1 << 29) | (1 << 28);
329 /* SATA dynamic clock gating [0-3]: */
330 reg32 |= (1 << 27) | (1 << 26) | (1 << 25) | (1 << 24);
331 reg32 |= (1 << 23); /* LAN static clock gating (if LAN disabled) */
332 reg32 |= (1 << 22); /* HD audio dynamic clock gating */
333 reg32 &= ~(1 << 21); /* No HD audio static clock gating */
334 reg32 &= ~(1 << 20); /* No USB EHCI static clock gating */
335 reg32 |= (1 << 19); /* USB EHCI dynamic clock gating */
336 /* More SATA dynamic clock gating [4-5]: */
337 reg32 |= (1 << 18) | (1 << 17);
338 reg32 |= (1 << 16); /* PCI dynamic clock gating */
339 /* PCIe, DMI dynamic clock gating: */
340 reg32 |= (1 << 4) | (1 << 3) | (1 << 2) | (1 << 1);
341 reg32 |= (1 << 0); /* PCIe root port static clock gating */
342 RCBA32(RCBA_CG) = reg32;
343
344 /* Enable SPI dynamic clock gating. */
345 RCBA32(0x38c0) |= 7;
346}
347
Kyösti Mälkki83d6a8a2019-07-12 08:16:53 +0300348static void i82801jx_set_acpi_mode(struct device *dev)
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200349{
Kyösti Mälkki44da9e72019-10-09 12:32:16 +0300350 if (CONFIG(HAVE_SMI_HANDLER)) {
351 if (!acpi_is_wakeup_s3()) {
352 printk(BIOS_DEBUG, "Disabling ACPI via APMC:\n");
353 outb(APM_CNT_ACPI_DISABLE, APM_CNT); // Disable ACPI mode
354 printk(BIOS_DEBUG, "done.\n");
355 } else {
356 printk(BIOS_DEBUG, "S3 wakeup, enabling ACPI via APMC\n");
357 outb(APM_CNT_ACPI_ENABLE, APM_CNT);
358 }
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200359 }
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200360}
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200361
362static void lpc_init(struct device *dev)
363{
Elyes HAOUASbfc255a2020-03-07 13:05:14 +0100364 printk(BIOS_DEBUG, "i82801jx: %s\n", __func__);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200365
366 /* Set the value for PCI command register. */
367 pci_write_config16(dev, PCI_COMMAND, 0x000f);
368
369 /* IO APIC initialization. */
Arthur Heymans349e0852017-04-09 20:48:37 +0200370 i82801jx_enable_apic(dev);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200371
Arthur Heymans349e0852017-04-09 20:48:37 +0200372 i82801jx_enable_serial_irqs(dev);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200373
374 /* Setup the PIRQ. */
Arthur Heymans349e0852017-04-09 20:48:37 +0200375 i82801jx_pirq_init(dev);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200376
377 /* Setup power options. */
Arthur Heymans349e0852017-04-09 20:48:37 +0200378 i82801jx_power_options(dev);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200379
380 /* Configure Cx state registers */
381 if (LPC_IS_MOBILE(dev))
Arthur Heymans349e0852017-04-09 20:48:37 +0200382 i82801jx_configure_cstates(dev);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200383
384 /* Initialize the real time clock. */
Arthur Heymans349e0852017-04-09 20:48:37 +0200385 i82801jx_rtc_init(dev);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200386
387 /* Initialize ISA DMA. */
388 isa_dma_init();
389
390 /* Initialize the High Precision Event Timers, if present. */
391 enable_hpet();
392
393 /* Initialize Clock Gating */
394 enable_clock_gating();
395
396 setup_i8259();
397
398 /* The OS should do this? */
399 /* Interrupt 9 should be level triggered (SCI) */
400 i8259_configure_irq_trigger(9, 1);
401
Kyösti Mälkki44da9e72019-10-09 12:32:16 +0300402 i82801jx_set_acpi_mode(dev);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200403}
404
Arthur Heymansad501492017-04-12 00:15:39 +0200405unsigned long acpi_fill_madt(unsigned long current)
406{
407 /* Local APICs */
408 current = acpi_create_madt_lapics(current);
409
410 /* IOAPIC */
411 current += acpi_create_madt_ioapic((acpi_madt_ioapic_t *) current,
412 2, IO_APIC_ADDR, 0);
413
414 /* LAPIC_NMI */
415 current += acpi_create_madt_lapic_nmi((acpi_madt_lapic_nmi_t *)
416 current, 0,
417 MP_IRQ_POLARITY_HIGH |
418 MP_IRQ_TRIGGER_EDGE, 0x01);
419 current += acpi_create_madt_lapic_nmi((acpi_madt_lapic_nmi_t *)
420 current, 1, MP_IRQ_POLARITY_HIGH |
421 MP_IRQ_TRIGGER_EDGE, 0x01);
422
423 /* INT_SRC_OVR */
424 current += acpi_create_madt_irqoverride((acpi_madt_irqoverride_t *)
425 current, 0, 0, 2, MP_IRQ_POLARITY_HIGH | MP_IRQ_TRIGGER_EDGE);
426 current += acpi_create_madt_irqoverride((acpi_madt_irqoverride_t *)
427 current, 0, 9, 9, MP_IRQ_POLARITY_HIGH | MP_IRQ_TRIGGER_LEVEL);
428
429
430 return current;
431}
432
433void acpi_fill_fadt(acpi_fadt_t *fadt)
434{
Kyösti Mälkkic70eed12018-05-22 02:18:00 +0300435 struct device *dev = pcidev_on_root(0x1f, 0);
Arthur Heymansad501492017-04-12 00:15:39 +0200436 config_t *chip = dev->chip_info;
437 u16 pmbase = pci_read_config16(dev, 0x40) & 0xfffe;
438
439 fadt->pm1a_evt_blk = pmbase;
440 fadt->pm1b_evt_blk = 0x0;
441 fadt->pm1a_cnt_blk = pmbase + 0x4;
442 fadt->pm1b_cnt_blk = 0x0;
443 fadt->pm2_cnt_blk = pmbase + 0x50;
444 fadt->pm_tmr_blk = pmbase + 0x8;
445 fadt->gpe0_blk = pmbase + 0x20;
446 fadt->gpe1_blk = 0;
447
448 fadt->pm1_evt_len = 4;
449 fadt->pm1_cnt_len = 2;
450 fadt->pm2_cnt_len = 1;
451 fadt->pm_tmr_len = 4;
452 fadt->gpe0_blk_len = 16;
453 fadt->gpe1_blk_len = 0;
454 fadt->gpe1_base = 0;
455
456 fadt->reset_reg.space_id = 1;
457 fadt->reset_reg.bit_width = 8;
458 fadt->reset_reg.bit_offset = 0;
459 fadt->reset_reg.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
460 fadt->reset_reg.addrl = 0xcf9;
461 fadt->reset_reg.addrh = 0;
462 fadt->reset_value = 6;
463
464 fadt->x_pm1a_evt_blk.space_id = 1;
465 fadt->x_pm1a_evt_blk.bit_width = 32;
466 fadt->x_pm1a_evt_blk.bit_offset = 0;
467 fadt->x_pm1a_evt_blk.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
468 fadt->x_pm1a_evt_blk.addrl = pmbase;
469 fadt->x_pm1a_evt_blk.addrh = 0x0;
470
471 fadt->x_pm1b_evt_blk.space_id = 0;
472 fadt->x_pm1b_evt_blk.bit_width = 0;
473 fadt->x_pm1b_evt_blk.bit_offset = 0;
474 fadt->x_pm1b_evt_blk.access_size = 0;
475 fadt->x_pm1b_evt_blk.addrl = 0x0;
476 fadt->x_pm1b_evt_blk.addrh = 0x0;
477
478 fadt->x_pm1a_cnt_blk.space_id = 1;
479 fadt->x_pm1a_cnt_blk.bit_width = 16;
480 fadt->x_pm1a_cnt_blk.bit_offset = 0;
481 fadt->x_pm1a_cnt_blk.access_size = ACPI_ACCESS_SIZE_WORD_ACCESS;
482 fadt->x_pm1a_cnt_blk.addrl = pmbase + 0x4;
483 fadt->x_pm1a_cnt_blk.addrh = 0x0;
484
485 fadt->x_pm1b_cnt_blk.space_id = 0;
486 fadt->x_pm1b_cnt_blk.bit_width = 0;
487 fadt->x_pm1b_cnt_blk.bit_offset = 0;
488 fadt->x_pm1b_cnt_blk.access_size = 0;
489 fadt->x_pm1b_cnt_blk.addrl = 0x0;
490 fadt->x_pm1b_cnt_blk.addrh = 0x0;
491
492 fadt->x_pm2_cnt_blk.space_id = 1;
493 fadt->x_pm2_cnt_blk.bit_width = 8;
494 fadt->x_pm2_cnt_blk.bit_offset = 0;
495 fadt->x_pm2_cnt_blk.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
Arthur Heymans3556ac52018-12-03 00:29:08 +0100496 fadt->x_pm2_cnt_blk.addrl = pmbase + 0x50;
Arthur Heymansad501492017-04-12 00:15:39 +0200497 fadt->x_pm2_cnt_blk.addrh = 0x0;
498
499 fadt->x_pm_tmr_blk.space_id = 1;
500 fadt->x_pm_tmr_blk.bit_width = 32;
501 fadt->x_pm_tmr_blk.bit_offset = 0;
502 fadt->x_pm_tmr_blk.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
503 fadt->x_pm_tmr_blk.addrl = pmbase + 0x8;
504 fadt->x_pm_tmr_blk.addrh = 0x0;
505
506 fadt->x_gpe0_blk.space_id = 1;
507 fadt->x_gpe0_blk.bit_width = 128;
508 fadt->x_gpe0_blk.bit_offset = 0;
509 fadt->x_gpe0_blk.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
510 fadt->x_gpe0_blk.addrl = pmbase + 0x20;
511 fadt->x_gpe0_blk.addrh = 0x0;
512
513 fadt->x_gpe1_blk.space_id = 0;
514 fadt->x_gpe1_blk.bit_width = 0;
515 fadt->x_gpe1_blk.bit_offset = 0;
516 fadt->x_gpe1_blk.access_size = 0;
517 fadt->x_gpe1_blk.addrl = 0x0;
518 fadt->x_gpe1_blk.addrh = 0x0;
519 fadt->day_alrm = 0xd;
520 fadt->mon_alrm = 0x00;
521 fadt->century = 0x32;
522
Arthur Heymansad501492017-04-12 00:15:39 +0200523 fadt->sci_int = 0x9;
Arthur Heymansad501492017-04-12 00:15:39 +0200524
Kyösti Mälkki0a9e72e2019-08-11 01:22:28 +0300525 if (permanent_smi_handler()) {
Kyösti Mälkkic328a682019-11-23 07:23:40 +0200526 fadt->smi_cmd = APM_CNT;
527 fadt->acpi_enable = APM_CNT_ACPI_ENABLE;
528 fadt->acpi_disable = APM_CNT_ACPI_DISABLE;
529 fadt->cst_cnt = APM_CNT_CST_CONTROL;
530 fadt->pstate_cnt = APM_CNT_PST_CONTROL;
531 }
532
Arthur Heymansad501492017-04-12 00:15:39 +0200533 fadt->p_lvl2_lat = 1;
534 fadt->p_lvl3_lat = chip->c3_latency;
535 fadt->flush_size = 0;
536 fadt->flush_stride = 0;
537 fadt->duty_offset = 1;
538 if (chip->p_cnt_throttling_supported)
539 fadt->duty_width = 3;
540 else
541 fadt->duty_width = 0;
542 fadt->iapc_boot_arch = 0x03;
543 fadt->flags = (ACPI_FADT_WBINVD | ACPI_FADT_C1_SUPPORTED
544 | ACPI_FADT_SLEEP_BUTTON | ACPI_FADT_S4_RTC_WAKE
545 | ACPI_FADT_PLATFORM_CLOCK | ACPI_FADT_RESET_REGISTER
546 | ACPI_FADT_C2_MP_SUPPORTED);
547 if (chip->docking_supported)
548 fadt->flags |= ACPI_FADT_DOCKING_SUPPORTED;
549}
550
Elyes HAOUAS1a8c1df2018-05-13 13:36:44 +0200551static void i82801jx_lpc_read_resources(struct device *dev)
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200552{
Arthur Heymanse5dcaf12017-04-12 00:03:37 +0200553 int i, io_index = 0;
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200554 /*
555 * I/O Resources
556 *
557 * 0x0000 - 0x000f....ISA DMA
558 * 0x0010 - 0x001f....ISA DMA aliases
559 * 0x0020 ~ 0x003d....PIC
560 * 0x002e - 0x002f....Maybe Super I/O
561 * 0x0040 - 0x0043....Timer
562 * 0x004e - 0x004f....Maybe Super I/O
563 * 0x0050 - 0x0053....Timer aliases
564 * 0x0061.............NMI_SC
565 * 0x0070.............NMI_EN (readable in alternative access mode)
566 * 0x0070 - 0x0077....RTC
567 * 0x0080 - 0x008f....ISA DMA
568 * 0x0090 ~ 0x009f....ISA DMA aliases
569 * 0x0092.............Fast A20 and Init
570 * 0x00a0 ~ 0x00bd....PIC
571 * 0x00b2 - 0x00b3....APM
572 * 0x00c0 ~ 0x00de....ISA DMA
573 * 0x00c1 ~ 0x00df....ISA DMA aliases
574 * 0x00f0.............Coprocessor Error
575 * (0x0400-0x041f)....SMBus (SMBUS_IO_BASE, during raminit)
576 * 0x04d0 - 0x04d1....PIC
577 * 0x0500 - 0x057f....PM (DEFAULT_PMBASE)
578 * 0x0580 - 0x05bf....SB GPIO (DEFAULT_GPIOBASE)
579 * 0x05c0 - 0x05ff....SB GPIO cont. (mobile only)
580 * 0x0cf8 - 0x0cff....PCI
581 * 0x0cf9.............Reset Control
582 */
583
584 struct resource *res;
585
586 /* Get the normal PCI resources of this device. */
587 pci_dev_read_resources(dev);
588
589 /* Add an extra subtractive resource for both memory and I/O. */
Arthur Heymanse5dcaf12017-04-12 00:03:37 +0200590 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200591 res->base = 0;
592 res->size = 0x1000;
593 res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
594 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
595
Arthur Heymanse5dcaf12017-04-12 00:03:37 +0200596 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
597 res->base = 0xff000000;
598 res->size = 0x01000000; /* 16 MB for flash */
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200599 res->flags = IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE |
600 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
601
602 res = new_resource(dev, 3); /* IOAPIC */
603 res->base = IO_APIC_ADDR;
604 res->size = 0x00001000;
605 res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
Arthur Heymanse5dcaf12017-04-12 00:03:37 +0200606
607 /* Set IO decode ranges if required.*/
608 for (i = 0; i < 4; i++) {
609 u32 gen_dec;
610 gen_dec = pci_read_config32(dev, 0x84 + 4 * i);
611
612 if ((gen_dec & 0xFFFC) > 0x1000) {
613 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
614 res->base = gen_dec & 0xFFFC;
615 res->size = (gen_dec >> 16) & 0xFC;
616 res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
617 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
618 }
619 }
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200620}
621
Furquan Shaikh338fd9a2020-04-24 22:57:05 -0700622static void southbridge_inject_dsdt(const struct device *dev)
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200623{
624 global_nvs_t *gnvs = cbmem_add (CBMEM_ID_ACPI_GNVS, sizeof(*gnvs));
625
626 if (gnvs) {
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200627 memset(gnvs, 0, sizeof(*gnvs));
628 acpi_create_gnvs(gnvs);
629
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200630 /* And tell SMI about it */
631 smm_setup_structures(gnvs, NULL, NULL);
632
633 /* Add it to SSDT. */
634 acpigen_write_scope("\\");
635 acpigen_write_name_dword("NVSA", (u32) gnvs);
636 acpigen_pop_len();
637 }
638}
639
Arthur Heymansa8a9f342017-12-24 08:11:13 +0100640static const char *lpc_acpi_name(const struct device *dev)
641{
642 return "LPCB";
643}
644
Furquan Shaikh7536a392020-04-24 21:59:21 -0700645static void southbridge_fill_ssdt(const struct device *device)
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200646{
Kyösti Mälkkic70eed12018-05-22 02:18:00 +0300647 struct device *dev = pcidev_on_root(0x1f, 0);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200648 config_t *chip = dev->chip_info;
649
650 intel_acpi_pcie_hotplug_generator(chip->pcie_hotplug_map, 8);
Arthur Heymansa8a9f342017-12-24 08:11:13 +0100651 intel_acpi_gen_def_acpi_pirq(device);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200652}
653
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200654static struct device_operations device_ops = {
Arthur Heymans349e0852017-04-09 20:48:37 +0200655 .read_resources = i82801jx_lpc_read_resources,
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200656 .set_resources = pci_dev_set_resources,
657 .enable_resources = pci_dev_enable_resources,
Nico Huber68680dd2020-03-31 17:34:52 +0200658 .acpi_inject_dsdt = southbridge_inject_dsdt,
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200659 .write_acpi_tables = acpi_write_hpet,
Nico Huber68680dd2020-03-31 17:34:52 +0200660 .acpi_fill_ssdt = southbridge_fill_ssdt,
Arthur Heymansa8a9f342017-12-24 08:11:13 +0100661 .acpi_name = lpc_acpi_name,
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200662 .init = lpc_init,
Nico Huber51b75ae2019-03-14 16:02:05 +0100663 .scan_bus = scan_static_bus,
Angel Pons1fc0edd2020-05-31 00:03:28 +0200664 .ops_pci = &pci_dev_ops_pci,
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200665};
666
667static const unsigned short pci_device_ids[] = {
Arthur Heymans349e0852017-04-09 20:48:37 +0200668 0x3a10, /* ICH10R Eng. Sample */
669 0x3a14, /* ICH10DO */
670 0x3a16, /* ICH10R */
671 0x3a18, /* ICH10 */
672 0x3a1a, /* ICH10D */
673 0x3a1e, /* ICH10 Eng. Sample */
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200674 0
675};
676
Arthur Heymans349e0852017-04-09 20:48:37 +0200677static const struct pci_driver ich10_lpc __pci_driver = {
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200678 .ops = &device_ops,
679 .vendor = PCI_VENDOR_ID_INTEL,
680 .devices = pci_device_ids,
681};