blob: ae98fddc2a91aca659999fab7e3ffe62660da2b7 [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... */
163 reg32 = pci_read_config32(dev, 0xac);
164 pci_write_config32(dev, 0xac, reg32 | (1 << 30) | (3 << 8));
165
166 /* Which state do we want to goto after g3 (power restored)?
167 * 0 == S0 Full On
168 * 1 == S5 Soft Off
169 *
170 * If the option is not existent (Laptops), use MAINBOARD_POWER_ON.
171 */
172 pwr_on = MAINBOARD_POWER_ON;
173 get_option(&pwr_on, "power_on_after_fail");
174
175 reg8 = pci_read_config8(dev, D31F0_GEN_PMCON_3);
176 reg8 &= 0xfe;
177 switch (pwr_on) {
178 case MAINBOARD_POWER_OFF:
179 reg8 |= 1;
180 state = "off";
181 break;
182 case MAINBOARD_POWER_ON:
183 reg8 &= ~1;
184 state = "on";
185 break;
186 case MAINBOARD_POWER_KEEP:
187 reg8 &= ~1;
188 state = "state keep";
189 break;
190 default:
191 state = "undefined";
192 }
193
194 reg8 |= (3 << 4); /* avoid #S4 assertions */
195 reg8 &= ~(1 << 3); /* minimum asssertion is 1 to 2 RTCCLK */
196
197 pci_write_config8(dev, D31F0_GEN_PMCON_3, reg8);
198 printk(BIOS_INFO, "Set power %s after power failure.\n", state);
199
200 /* Set up NMI on errors. */
201 reg8 = inb(0x61);
202 reg8 &= 0x0f; /* Higher Nibble must be 0 */
203 reg8 &= ~(1 << 3); /* IOCHK# NMI Enable */
204 // reg8 &= ~(1 << 2); /* PCI SERR# Enable */
205 reg8 |= (1 << 2); /* PCI SERR# Disable for now */
206 outb(reg8, 0x61);
207
208 reg8 = inb(0x74); /* Read from 0x74 as 0x70 is write only. */
209 nmi_option = NMI_OFF;
210 get_option(&nmi_option, "nmi");
211 if (nmi_option) {
212 printk(BIOS_INFO, "NMI sources enabled.\n");
213 reg8 &= ~(1 << 7); /* Set NMI. */
214 } else {
215 printk(BIOS_INFO, "NMI sources disabled.\n");
Elyes HAOUAS9c5d4632018-04-26 22:21:21 +0200216 reg8 |= (1 << 7); /* Can't mask NMI from PCI-E and NMI_NOW */
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200217 }
218 outb(reg8, 0x70);
219
220 /* Enable CPU_SLP# and Intel Speedstep, set SMI# rate down */
221 reg16 = pci_read_config16(dev, D31F0_GEN_PMCON_1);
222 reg16 &= ~(3 << 0); // SMI# rate 1 minute
223 reg16 |= (1 << 2); // CLKRUN_EN - Mobile/Ultra only
224 reg16 |= (1 << 3); // Speedstep Enable - Mobile/Ultra only
225 reg16 |= (1 << 5); // CPUSLP_EN Desktop only
226
227 if (config->c4onc3_enable)
228 reg16 |= (1 << 7);
229
230 // another laptop wants this?
231 // reg16 &= ~(1 << 10); // BIOS_PCI_EXP_EN - Desktop/Mobile only
232 reg16 |= (1 << 10); // BIOS_PCI_EXP_EN - Desktop/Mobile only
233#if DEBUG_PERIODIC_SMIS
Arthur Heymans349e0852017-04-09 20:48:37 +0200234 /* Set DEBUG_PERIODIC_SMIS in i82801jx.h to debug using
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200235 * periodic SMIs.
236 */
237 reg16 |= (3 << 0); // Periodic SMI every 8s
238#endif
239 if (config->c5_enable)
240 reg16 |= (1 << 11); /* Enable C5, C6 and PMSYNC# */
241 pci_write_config16(dev, D31F0_GEN_PMCON_1, reg16);
242
243 /* Set exit timings for C5/C6. */
244 if (config->c5_enable) {
245 reg8 = pci_read_config8(dev, D31F0_C5_EXIT_TIMING);
246 reg8 &= ~((7 << 3) | (7 << 0));
247 if (config->c6_enable)
248 reg8 |= (5 << 3) | (3 << 0); /* 38-44us PMSYNC# to STPCLK#,
249 95-102us DPRSTP# to STP_CPU# */
250 else
251 reg8 |= (0 << 3) | (1 << 0); /* 16-17us PMSYNC# to STPCLK#,
252 34-40us DPRSTP# to STP_CPU# */
253 pci_write_config8(dev, D31F0_C5_EXIT_TIMING, reg8);
254 }
255
256 // Set the board's GPI routing.
Arthur Heymans349e0852017-04-09 20:48:37 +0200257 i82801jx_gpi_routing(dev);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200258
259 pmbase = pci_read_config16(dev, 0x40) & 0xfffe;
260
261 outl(config->gpe0_en, pmbase + 0x28);
262 outw(config->alt_gp_smi_en, pmbase + 0x38);
263
264 /* Set up power management block and determine sleep mode */
265 reg16 = inw(pmbase + 0x00); /* PM1_STS */
266 outw(reg16, pmbase + 0x00); /* Clear status bits. At least bit11 (power
267 button override) must be cleared or SCI
268 will be constantly fired and OSPM must
269 not know about it (ACPI spec says to
270 ignore the bit). */
271 reg32 = inl(pmbase + 0x04); // PM1_CNT
272 reg32 &= ~(7 << 10); // SLP_TYP
273 outl(reg32, pmbase + 0x04);
274
275 /* Set duty cycle for hardware throttling (defaults to 0x0: 50%). */
276 reg32 = inl(pmbase + 0x10);
277 reg32 &= ~(7 << 5);
278 reg32 |= (config->throttle_duty & 7) << 5;
279 outl(reg32, pmbase + 0x10);
280}
281
Elyes HAOUAS1a8c1df2018-05-13 13:36:44 +0200282static void i82801jx_configure_cstates(struct device *dev)
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200283{
284 u8 reg8;
285
286 reg8 = pci_read_config8(dev, D31F0_CxSTATE_CNF);
287 reg8 |= (1 << 4) | (1 << 3) | (1 << 2); // Enable Popup & Popdown
288 pci_write_config8(dev, D31F0_CxSTATE_CNF, reg8);
289
290 // Set Deeper Sleep configuration to recommended values
291 reg8 = pci_read_config8(dev, D31F0_C4TIMING_CNT);
292 reg8 &= 0xf0;
293 reg8 |= (2 << 2); // Deeper Sleep to Stop CPU: 34-40us
294 reg8 |= (2 << 0); // Deeper Sleep to Sleep: 15us
295 pci_write_config8(dev, D31F0_C4TIMING_CNT, reg8);
296
297 /* We could enable slow-C4 exit here, if someone needs it? */
298}
299
Arthur Heymans349e0852017-04-09 20:48:37 +0200300static void i82801jx_rtc_init(struct device *dev)
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200301{
302 u8 reg8;
303 int rtc_failed;
304
305 reg8 = pci_read_config8(dev, D31F0_GEN_PMCON_3);
306 rtc_failed = reg8 & RTC_BATTERY_DEAD;
307 if (rtc_failed) {
308 reg8 &= ~RTC_BATTERY_DEAD;
309 pci_write_config8(dev, D31F0_GEN_PMCON_3, reg8);
310 }
311 printk(BIOS_DEBUG, "rtc_failed = 0x%x\n", rtc_failed);
312
313 cmos_init(rtc_failed);
314}
315
316static void enable_hpet(void)
317{
318 u32 reg32;
319
320 /* Move HPET to default address 0xfed00000 and enable it */
321 reg32 = RCBA32(RCBA_HPTC);
322 reg32 |= (1 << 7); // HPET Address Enable
323 reg32 &= ~(3 << 0);
324 RCBA32(RCBA_HPTC) = reg32;
325}
326
327static void enable_clock_gating(void)
328{
329 u32 reg32;
330
331 /* Enable DMI dynamic clock gating. */
332 RCBA32(RCBA_DMIC) |= 3;
333
334 /* Enable Clock Gating for most devices. */
335 reg32 = RCBA32(RCBA_CG);
336 reg32 |= (1 << 31); /* LPC dynamic clock gating */
337 /* USB UHCI dynamic clock gating: */
338 reg32 |= (1 << 29) | (1 << 28);
339 /* SATA dynamic clock gating [0-3]: */
340 reg32 |= (1 << 27) | (1 << 26) | (1 << 25) | (1 << 24);
341 reg32 |= (1 << 23); /* LAN static clock gating (if LAN disabled) */
342 reg32 |= (1 << 22); /* HD audio dynamic clock gating */
343 reg32 &= ~(1 << 21); /* No HD audio static clock gating */
344 reg32 &= ~(1 << 20); /* No USB EHCI static clock gating */
345 reg32 |= (1 << 19); /* USB EHCI dynamic clock gating */
346 /* More SATA dynamic clock gating [4-5]: */
347 reg32 |= (1 << 18) | (1 << 17);
348 reg32 |= (1 << 16); /* PCI dynamic clock gating */
349 /* PCIe, DMI dynamic clock gating: */
350 reg32 |= (1 << 4) | (1 << 3) | (1 << 2) | (1 << 1);
351 reg32 |= (1 << 0); /* PCIe root port static clock gating */
352 RCBA32(RCBA_CG) = reg32;
353
354 /* Enable SPI dynamic clock gating. */
355 RCBA32(0x38c0) |= 7;
356}
357
Kyösti Mälkki83d6a8a2019-07-12 08:16:53 +0300358static void i82801jx_set_acpi_mode(struct device *dev)
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200359{
Kyösti Mälkki44da9e72019-10-09 12:32:16 +0300360 if (CONFIG(HAVE_SMI_HANDLER)) {
361 if (!acpi_is_wakeup_s3()) {
362 printk(BIOS_DEBUG, "Disabling ACPI via APMC:\n");
363 outb(APM_CNT_ACPI_DISABLE, APM_CNT); // Disable ACPI mode
364 printk(BIOS_DEBUG, "done.\n");
365 } else {
366 printk(BIOS_DEBUG, "S3 wakeup, enabling ACPI via APMC\n");
367 outb(APM_CNT_ACPI_ENABLE, APM_CNT);
368 }
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200369 }
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200370}
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200371
372static void lpc_init(struct device *dev)
373{
Elyes HAOUASbfc255a2020-03-07 13:05:14 +0100374 printk(BIOS_DEBUG, "i82801jx: %s\n", __func__);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200375
376 /* Set the value for PCI command register. */
377 pci_write_config16(dev, PCI_COMMAND, 0x000f);
378
379 /* IO APIC initialization. */
Arthur Heymans349e0852017-04-09 20:48:37 +0200380 i82801jx_enable_apic(dev);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200381
Arthur Heymans349e0852017-04-09 20:48:37 +0200382 i82801jx_enable_serial_irqs(dev);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200383
384 /* Setup the PIRQ. */
Arthur Heymans349e0852017-04-09 20:48:37 +0200385 i82801jx_pirq_init(dev);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200386
387 /* Setup power options. */
Arthur Heymans349e0852017-04-09 20:48:37 +0200388 i82801jx_power_options(dev);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200389
390 /* Configure Cx state registers */
391 if (LPC_IS_MOBILE(dev))
Arthur Heymans349e0852017-04-09 20:48:37 +0200392 i82801jx_configure_cstates(dev);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200393
394 /* Initialize the real time clock. */
Arthur Heymans349e0852017-04-09 20:48:37 +0200395 i82801jx_rtc_init(dev);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200396
397 /* Initialize ISA DMA. */
398 isa_dma_init();
399
400 /* Initialize the High Precision Event Timers, if present. */
401 enable_hpet();
402
403 /* Initialize Clock Gating */
404 enable_clock_gating();
405
406 setup_i8259();
407
408 /* The OS should do this? */
409 /* Interrupt 9 should be level triggered (SCI) */
410 i8259_configure_irq_trigger(9, 1);
411
Kyösti Mälkki44da9e72019-10-09 12:32:16 +0300412 i82801jx_set_acpi_mode(dev);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200413}
414
Arthur Heymansad501492017-04-12 00:15:39 +0200415unsigned long acpi_fill_madt(unsigned long current)
416{
417 /* Local APICs */
418 current = acpi_create_madt_lapics(current);
419
420 /* IOAPIC */
421 current += acpi_create_madt_ioapic((acpi_madt_ioapic_t *) current,
422 2, IO_APIC_ADDR, 0);
423
424 /* LAPIC_NMI */
425 current += acpi_create_madt_lapic_nmi((acpi_madt_lapic_nmi_t *)
426 current, 0,
427 MP_IRQ_POLARITY_HIGH |
428 MP_IRQ_TRIGGER_EDGE, 0x01);
429 current += acpi_create_madt_lapic_nmi((acpi_madt_lapic_nmi_t *)
430 current, 1, MP_IRQ_POLARITY_HIGH |
431 MP_IRQ_TRIGGER_EDGE, 0x01);
432
433 /* INT_SRC_OVR */
434 current += acpi_create_madt_irqoverride((acpi_madt_irqoverride_t *)
435 current, 0, 0, 2, MP_IRQ_POLARITY_HIGH | MP_IRQ_TRIGGER_EDGE);
436 current += acpi_create_madt_irqoverride((acpi_madt_irqoverride_t *)
437 current, 0, 9, 9, MP_IRQ_POLARITY_HIGH | MP_IRQ_TRIGGER_LEVEL);
438
439
440 return current;
441}
442
443void acpi_fill_fadt(acpi_fadt_t *fadt)
444{
Kyösti Mälkkic70eed12018-05-22 02:18:00 +0300445 struct device *dev = pcidev_on_root(0x1f, 0);
Arthur Heymansad501492017-04-12 00:15:39 +0200446 config_t *chip = dev->chip_info;
447 u16 pmbase = pci_read_config16(dev, 0x40) & 0xfffe;
448
449 fadt->pm1a_evt_blk = pmbase;
450 fadt->pm1b_evt_blk = 0x0;
451 fadt->pm1a_cnt_blk = pmbase + 0x4;
452 fadt->pm1b_cnt_blk = 0x0;
453 fadt->pm2_cnt_blk = pmbase + 0x50;
454 fadt->pm_tmr_blk = pmbase + 0x8;
455 fadt->gpe0_blk = pmbase + 0x20;
456 fadt->gpe1_blk = 0;
457
458 fadt->pm1_evt_len = 4;
459 fadt->pm1_cnt_len = 2;
460 fadt->pm2_cnt_len = 1;
461 fadt->pm_tmr_len = 4;
462 fadt->gpe0_blk_len = 16;
463 fadt->gpe1_blk_len = 0;
464 fadt->gpe1_base = 0;
465
466 fadt->reset_reg.space_id = 1;
467 fadt->reset_reg.bit_width = 8;
468 fadt->reset_reg.bit_offset = 0;
469 fadt->reset_reg.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
470 fadt->reset_reg.addrl = 0xcf9;
471 fadt->reset_reg.addrh = 0;
472 fadt->reset_value = 6;
473
474 fadt->x_pm1a_evt_blk.space_id = 1;
475 fadt->x_pm1a_evt_blk.bit_width = 32;
476 fadt->x_pm1a_evt_blk.bit_offset = 0;
477 fadt->x_pm1a_evt_blk.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
478 fadt->x_pm1a_evt_blk.addrl = pmbase;
479 fadt->x_pm1a_evt_blk.addrh = 0x0;
480
481 fadt->x_pm1b_evt_blk.space_id = 0;
482 fadt->x_pm1b_evt_blk.bit_width = 0;
483 fadt->x_pm1b_evt_blk.bit_offset = 0;
484 fadt->x_pm1b_evt_blk.access_size = 0;
485 fadt->x_pm1b_evt_blk.addrl = 0x0;
486 fadt->x_pm1b_evt_blk.addrh = 0x0;
487
488 fadt->x_pm1a_cnt_blk.space_id = 1;
489 fadt->x_pm1a_cnt_blk.bit_width = 16;
490 fadt->x_pm1a_cnt_blk.bit_offset = 0;
491 fadt->x_pm1a_cnt_blk.access_size = ACPI_ACCESS_SIZE_WORD_ACCESS;
492 fadt->x_pm1a_cnt_blk.addrl = pmbase + 0x4;
493 fadt->x_pm1a_cnt_blk.addrh = 0x0;
494
495 fadt->x_pm1b_cnt_blk.space_id = 0;
496 fadt->x_pm1b_cnt_blk.bit_width = 0;
497 fadt->x_pm1b_cnt_blk.bit_offset = 0;
498 fadt->x_pm1b_cnt_blk.access_size = 0;
499 fadt->x_pm1b_cnt_blk.addrl = 0x0;
500 fadt->x_pm1b_cnt_blk.addrh = 0x0;
501
502 fadt->x_pm2_cnt_blk.space_id = 1;
503 fadt->x_pm2_cnt_blk.bit_width = 8;
504 fadt->x_pm2_cnt_blk.bit_offset = 0;
505 fadt->x_pm2_cnt_blk.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
Arthur Heymans3556ac52018-12-03 00:29:08 +0100506 fadt->x_pm2_cnt_blk.addrl = pmbase + 0x50;
Arthur Heymansad501492017-04-12 00:15:39 +0200507 fadt->x_pm2_cnt_blk.addrh = 0x0;
508
509 fadt->x_pm_tmr_blk.space_id = 1;
510 fadt->x_pm_tmr_blk.bit_width = 32;
511 fadt->x_pm_tmr_blk.bit_offset = 0;
512 fadt->x_pm_tmr_blk.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
513 fadt->x_pm_tmr_blk.addrl = pmbase + 0x8;
514 fadt->x_pm_tmr_blk.addrh = 0x0;
515
516 fadt->x_gpe0_blk.space_id = 1;
517 fadt->x_gpe0_blk.bit_width = 128;
518 fadt->x_gpe0_blk.bit_offset = 0;
519 fadt->x_gpe0_blk.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
520 fadt->x_gpe0_blk.addrl = pmbase + 0x20;
521 fadt->x_gpe0_blk.addrh = 0x0;
522
523 fadt->x_gpe1_blk.space_id = 0;
524 fadt->x_gpe1_blk.bit_width = 0;
525 fadt->x_gpe1_blk.bit_offset = 0;
526 fadt->x_gpe1_blk.access_size = 0;
527 fadt->x_gpe1_blk.addrl = 0x0;
528 fadt->x_gpe1_blk.addrh = 0x0;
529 fadt->day_alrm = 0xd;
530 fadt->mon_alrm = 0x00;
531 fadt->century = 0x32;
532
Elyes HAOUAS0d4de2a2019-02-28 13:04:29 +0100533 fadt->reserved = 0;
Arthur Heymansad501492017-04-12 00:15:39 +0200534 fadt->sci_int = 0x9;
535 fadt->smi_cmd = APM_CNT;
536 fadt->acpi_enable = APM_CNT_ACPI_ENABLE;
537 fadt->acpi_disable = APM_CNT_ACPI_DISABLE;
538 fadt->s4bios_req = 0x0;
539 fadt->pstate_cnt = APM_CNT_PST_CONTROL;
540
541 fadt->cst_cnt = APM_CNT_CST_CONTROL;
542 fadt->p_lvl2_lat = 1;
543 fadt->p_lvl3_lat = chip->c3_latency;
544 fadt->flush_size = 0;
545 fadt->flush_stride = 0;
546 fadt->duty_offset = 1;
547 if (chip->p_cnt_throttling_supported)
548 fadt->duty_width = 3;
549 else
550 fadt->duty_width = 0;
551 fadt->iapc_boot_arch = 0x03;
552 fadt->flags = (ACPI_FADT_WBINVD | ACPI_FADT_C1_SUPPORTED
553 | ACPI_FADT_SLEEP_BUTTON | ACPI_FADT_S4_RTC_WAKE
554 | ACPI_FADT_PLATFORM_CLOCK | ACPI_FADT_RESET_REGISTER
555 | ACPI_FADT_C2_MP_SUPPORTED);
556 if (chip->docking_supported)
557 fadt->flags |= ACPI_FADT_DOCKING_SUPPORTED;
558}
559
Elyes HAOUAS1a8c1df2018-05-13 13:36:44 +0200560static void i82801jx_lpc_read_resources(struct device *dev)
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200561{
Arthur Heymanse5dcaf12017-04-12 00:03:37 +0200562 int i, io_index = 0;
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200563 /*
564 * I/O Resources
565 *
566 * 0x0000 - 0x000f....ISA DMA
567 * 0x0010 - 0x001f....ISA DMA aliases
568 * 0x0020 ~ 0x003d....PIC
569 * 0x002e - 0x002f....Maybe Super I/O
570 * 0x0040 - 0x0043....Timer
571 * 0x004e - 0x004f....Maybe Super I/O
572 * 0x0050 - 0x0053....Timer aliases
573 * 0x0061.............NMI_SC
574 * 0x0070.............NMI_EN (readable in alternative access mode)
575 * 0x0070 - 0x0077....RTC
576 * 0x0080 - 0x008f....ISA DMA
577 * 0x0090 ~ 0x009f....ISA DMA aliases
578 * 0x0092.............Fast A20 and Init
579 * 0x00a0 ~ 0x00bd....PIC
580 * 0x00b2 - 0x00b3....APM
581 * 0x00c0 ~ 0x00de....ISA DMA
582 * 0x00c1 ~ 0x00df....ISA DMA aliases
583 * 0x00f0.............Coprocessor Error
584 * (0x0400-0x041f)....SMBus (SMBUS_IO_BASE, during raminit)
585 * 0x04d0 - 0x04d1....PIC
586 * 0x0500 - 0x057f....PM (DEFAULT_PMBASE)
587 * 0x0580 - 0x05bf....SB GPIO (DEFAULT_GPIOBASE)
588 * 0x05c0 - 0x05ff....SB GPIO cont. (mobile only)
589 * 0x0cf8 - 0x0cff....PCI
590 * 0x0cf9.............Reset Control
591 */
592
593 struct resource *res;
594
595 /* Get the normal PCI resources of this device. */
596 pci_dev_read_resources(dev);
597
598 /* Add an extra subtractive resource for both memory and I/O. */
Arthur Heymanse5dcaf12017-04-12 00:03:37 +0200599 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200600 res->base = 0;
601 res->size = 0x1000;
602 res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
603 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
604
Arthur Heymanse5dcaf12017-04-12 00:03:37 +0200605 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
606 res->base = 0xff000000;
607 res->size = 0x01000000; /* 16 MB for flash */
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200608 res->flags = IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE |
609 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
610
611 res = new_resource(dev, 3); /* IOAPIC */
612 res->base = IO_APIC_ADDR;
613 res->size = 0x00001000;
614 res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
Arthur Heymanse5dcaf12017-04-12 00:03:37 +0200615
616 /* Set IO decode ranges if required.*/
617 for (i = 0; i < 4; i++) {
618 u32 gen_dec;
619 gen_dec = pci_read_config32(dev, 0x84 + 4 * i);
620
621 if ((gen_dec & 0xFFFC) > 0x1000) {
622 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
623 res->base = gen_dec & 0xFFFC;
624 res->size = (gen_dec >> 16) & 0xFC;
625 res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
626 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
627 }
628 }
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200629}
630
Furquan Shaikh338fd9a2020-04-24 22:57:05 -0700631static void southbridge_inject_dsdt(const struct device *dev)
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200632{
633 global_nvs_t *gnvs = cbmem_add (CBMEM_ID_ACPI_GNVS, sizeof(*gnvs));
634
635 if (gnvs) {
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200636 memset(gnvs, 0, sizeof(*gnvs));
637 acpi_create_gnvs(gnvs);
638
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200639 /* And tell SMI about it */
640 smm_setup_structures(gnvs, NULL, NULL);
641
642 /* Add it to SSDT. */
643 acpigen_write_scope("\\");
644 acpigen_write_name_dword("NVSA", (u32) gnvs);
645 acpigen_pop_len();
646 }
647}
648
Arthur Heymansa8a9f342017-12-24 08:11:13 +0100649static const char *lpc_acpi_name(const struct device *dev)
650{
651 return "LPCB";
652}
653
Furquan Shaikh7536a392020-04-24 21:59:21 -0700654static void southbridge_fill_ssdt(const struct device *device)
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200655{
Kyösti Mälkkic70eed12018-05-22 02:18:00 +0300656 struct device *dev = pcidev_on_root(0x1f, 0);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200657 config_t *chip = dev->chip_info;
658
659 intel_acpi_pcie_hotplug_generator(chip->pcie_hotplug_map, 8);
Arthur Heymansa8a9f342017-12-24 08:11:13 +0100660 intel_acpi_gen_def_acpi_pirq(device);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200661}
662
663static struct pci_operations pci_ops = {
Subrata Banik4a0f0712019-03-20 14:29:47 +0530664 .set_subsystem = pci_dev_set_subsystem,
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200665};
666
667static struct device_operations device_ops = {
Arthur Heymans349e0852017-04-09 20:48:37 +0200668 .read_resources = i82801jx_lpc_read_resources,
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200669 .set_resources = pci_dev_set_resources,
670 .enable_resources = pci_dev_enable_resources,
Nico Huber68680dd2020-03-31 17:34:52 +0200671 .acpi_inject_dsdt = southbridge_inject_dsdt,
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200672 .write_acpi_tables = acpi_write_hpet,
Nico Huber68680dd2020-03-31 17:34:52 +0200673 .acpi_fill_ssdt = southbridge_fill_ssdt,
Arthur Heymansa8a9f342017-12-24 08:11:13 +0100674 .acpi_name = lpc_acpi_name,
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200675 .init = lpc_init,
Nico Huber51b75ae2019-03-14 16:02:05 +0100676 .scan_bus = scan_static_bus,
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200677 .ops_pci = &pci_ops,
678};
679
680static const unsigned short pci_device_ids[] = {
Arthur Heymans349e0852017-04-09 20:48:37 +0200681 0x3a10, /* ICH10R Eng. Sample */
682 0x3a14, /* ICH10DO */
683 0x3a16, /* ICH10R */
684 0x3a18, /* ICH10 */
685 0x3a1a, /* ICH10D */
686 0x3a1e, /* ICH10 Eng. Sample */
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200687 0
688};
689
Arthur Heymans349e0852017-04-09 20:48:37 +0200690static const struct pci_driver ich10_lpc __pci_driver = {
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200691 .ops = &device_ops,
692 .vendor = PCI_VENDOR_ID_INTEL,
693 .devices = pci_device_ids,
694};