blob: fceeb3f80e90f9ba630fca2bc9e4c9c6b5e19c04 [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>
Kyösti Mälkki0c1dd9c2020-06-17 23:37:49 +030015#include <acpi/acpi_gnvs.h>
Arthur Heymans7b9c1392017-04-09 20:40:39 +020016#include <cpu/x86/smm.h>
Furquan Shaikh76cedd22020-05-02 10:24:23 -070017#include <acpi/acpigen.h>
Arthur Heymansad501492017-04-12 00:15:39 +020018#include <arch/smp/mpspec.h>
Arthur Heymans7b9c1392017-04-09 20:40:39 +020019#include <cbmem.h>
20#include <string.h>
Kyösti Mälkki12b121c2019-08-18 16:33:39 +030021#include "chip.h"
Arthur Heymans349e0852017-04-09 20:48:37 +020022#include "i82801jx.h"
Arthur Heymans7b9c1392017-04-09 20:40:39 +020023#include "nvs.h"
24#include <southbridge/intel/common/pciehp.h>
Angel Pons490473e2020-06-21 17:10:28 +020025#include <southbridge/intel/common/pmutil.h>
Arthur Heymansa8a9f342017-12-24 08:11:13 +010026#include <southbridge/intel/common/acpi_pirq_gen.h>
Arthur Heymans7b9c1392017-04-09 20:40:39 +020027
28#define NMI_OFF 0
29
Arthur Heymans349e0852017-04-09 20:48:37 +020030typedef struct southbridge_intel_i82801jx_config config_t;
Arthur Heymans7b9c1392017-04-09 20:40:39 +020031
Arthur Heymans349e0852017-04-09 20:48:37 +020032static void i82801jx_enable_apic(struct device *dev)
Arthur Heymans7b9c1392017-04-09 20:40:39 +020033{
34 u32 reg32;
35 volatile u32 *ioapic_index = (volatile u32 *)(IO_APIC_ADDR);
36 volatile u32 *ioapic_data = (volatile u32 *)(IO_APIC_ADDR + 0x10);
37
38 /* Enable IOAPIC. Keep APIC Range Select at zero. */
39 RCBA8(0x31ff) = 0x03;
40 /* We have to read 0x31ff back if bit0 changed. */
41 RCBA8(0x31ff);
42
43 /* Lock maximum redirection entries (MRE), R/WO register. */
44 *ioapic_index = 0x01;
45 reg32 = *ioapic_data;
46 *ioapic_index = 0x01;
47 *ioapic_data = reg32;
48
49 setup_ioapic(VIO_APIC_VADDR, 2); /* ICH7 code uses id 2. */
50}
51
Arthur Heymans349e0852017-04-09 20:48:37 +020052static void i82801jx_enable_serial_irqs(struct device *dev)
Arthur Heymans7b9c1392017-04-09 20:40:39 +020053{
54 /* Set packet length and toggle silent mode bit for one frame. */
55 pci_write_config8(dev, D31F0_SERIRQ_CNTL,
56 (1 << 7) | (1 << 6) | ((21 - 17) << 2) | (0 << 0));
57}
58
59/* PIRQ[n]_ROUT[3:0] - PIRQ Routing Control
60 * 0x00 - 0000 = Reserved
61 * 0x01 - 0001 = Reserved
62 * 0x02 - 0010 = Reserved
63 * 0x03 - 0011 = IRQ3
64 * 0x04 - 0100 = IRQ4
65 * 0x05 - 0101 = IRQ5
66 * 0x06 - 0110 = IRQ6
67 * 0x07 - 0111 = IRQ7
68 * 0x08 - 1000 = Reserved
69 * 0x09 - 1001 = IRQ9
70 * 0x0A - 1010 = IRQ10
71 * 0x0B - 1011 = IRQ11
72 * 0x0C - 1100 = IRQ12
73 * 0x0D - 1101 = Reserved
74 * 0x0E - 1110 = IRQ14
75 * 0x0F - 1111 = IRQ15
76 * PIRQ[n]_ROUT[7] - PIRQ Routing Control
77 * 0x80 - The PIRQ is not routed.
78 */
79
Elyes HAOUAS1a8c1df2018-05-13 13:36:44 +020080static void i82801jx_pirq_init(struct device *dev)
Arthur Heymans7b9c1392017-04-09 20:40:39 +020081{
Elyes HAOUAS1a8c1df2018-05-13 13:36:44 +020082 struct device *irq_dev;
Arthur Heymans7b9c1392017-04-09 20:40:39 +020083
Arthur Heymans87af36a2017-04-12 10:53:30 +020084 /* Interrupt 11 is not used by legacy devices and so can always be used
85 * for PCI interrupts. Full legacy IRQ routing is complicated and hard
86 * to get right. Fortunately all modern OS use MSI and so it's not that
87 * big of an issue anyway. Still we have to provide a reasonable
88 * default. Using interrupt 11 for it everywhere is a working default.
89 * ACPI-aware OS can move it to any interrupt and others will just leave
90 * them at default.
91 */
92 const u8 pirq_routing = 11;
Arthur Heymans7b9c1392017-04-09 20:40:39 +020093
Arthur Heymans87af36a2017-04-12 10:53:30 +020094 pci_write_config8(dev, D31F0_PIRQA_ROUT, pirq_routing);
95 pci_write_config8(dev, D31F0_PIRQB_ROUT, pirq_routing);
96 pci_write_config8(dev, D31F0_PIRQC_ROUT, pirq_routing);
97 pci_write_config8(dev, D31F0_PIRQD_ROUT, pirq_routing);
98
99 pci_write_config8(dev, D31F0_PIRQE_ROUT, pirq_routing);
100 pci_write_config8(dev, D31F0_PIRQF_ROUT, pirq_routing);
101 pci_write_config8(dev, D31F0_PIRQG_ROUT, pirq_routing);
102 pci_write_config8(dev, D31F0_PIRQH_ROUT, pirq_routing);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200103
104 /* Eric Biederman once said we should let the OS do this.
105 * I am not so sure anymore he was right.
106 */
107
108 for (irq_dev = all_devices; irq_dev; irq_dev = irq_dev->next) {
Arthur Heymans87af36a2017-04-12 10:53:30 +0200109 u8 int_pin = 0;
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200110
111 if (!irq_dev->enabled || irq_dev->path.type != DEVICE_PATH_PCI)
112 continue;
113
114 int_pin = pci_read_config8(irq_dev, PCI_INTERRUPT_PIN);
115
Arthur Heymans87af36a2017-04-12 10:53:30 +0200116 if (int_pin == 0)
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200117 continue;
118
Arthur Heymans87af36a2017-04-12 10:53:30 +0200119 pci_write_config8(irq_dev, PCI_INTERRUPT_LINE, pirq_routing);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200120 }
121}
122
Elyes HAOUAS1a8c1df2018-05-13 13:36:44 +0200123static void i82801jx_gpi_routing(struct device *dev)
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200124{
125 /* Get the chip configuration */
126 config_t *config = dev->chip_info;
127 u32 reg32 = 0;
128
129 /* An array would be much nicer here, or some
130 * other method of doing this.
131 */
132 reg32 |= (config->gpi0_routing & 0x03) << 0;
133 reg32 |= (config->gpi1_routing & 0x03) << 2;
134 reg32 |= (config->gpi2_routing & 0x03) << 4;
135 reg32 |= (config->gpi3_routing & 0x03) << 6;
136 reg32 |= (config->gpi4_routing & 0x03) << 8;
137 reg32 |= (config->gpi5_routing & 0x03) << 10;
138 reg32 |= (config->gpi6_routing & 0x03) << 12;
139 reg32 |= (config->gpi7_routing & 0x03) << 14;
140 reg32 |= (config->gpi8_routing & 0x03) << 16;
141 reg32 |= (config->gpi9_routing & 0x03) << 18;
142 reg32 |= (config->gpi10_routing & 0x03) << 20;
143 reg32 |= (config->gpi11_routing & 0x03) << 22;
144 reg32 |= (config->gpi12_routing & 0x03) << 24;
145 reg32 |= (config->gpi13_routing & 0x03) << 26;
146 reg32 |= (config->gpi14_routing & 0x03) << 28;
147 reg32 |= (config->gpi15_routing & 0x03) << 30;
148
149 pci_write_config32(dev, D31F0_GPIO_ROUT, reg32);
150}
151
Elyes HAOUAS1a8c1df2018-05-13 13:36:44 +0200152static void i82801jx_power_options(struct device *dev)
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200153{
154 u8 reg8;
155 u16 reg16, pmbase;
156 u32 reg32;
157 const char *state;
158 /* Get the chip configuration */
159 config_t *config = dev->chip_info;
160
Nico Huber9faae2b2018-11-14 00:00:35 +0100161 int pwr_on = CONFIG_MAINBOARD_POWER_FAILURE_STATE;
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200162 int nmi_option;
163
164 /* BIOS must program... */
Angel Pons2048cb42020-06-08 02:09:33 +0200165 pci_or_config32(dev, 0xac, (1 << 30) | (3 << 8));
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200166
167 /* Which state do we want to goto after g3 (power restored)?
168 * 0 == S0 Full On
169 * 1 == S5 Soft Off
170 *
171 * If the option is not existent (Laptops), use MAINBOARD_POWER_ON.
172 */
173 pwr_on = MAINBOARD_POWER_ON;
174 get_option(&pwr_on, "power_on_after_fail");
175
176 reg8 = pci_read_config8(dev, D31F0_GEN_PMCON_3);
177 reg8 &= 0xfe;
178 switch (pwr_on) {
179 case MAINBOARD_POWER_OFF:
180 reg8 |= 1;
181 state = "off";
182 break;
183 case MAINBOARD_POWER_ON:
184 reg8 &= ~1;
185 state = "on";
186 break;
187 case MAINBOARD_POWER_KEEP:
188 reg8 &= ~1;
189 state = "state keep";
190 break;
191 default:
192 state = "undefined";
193 }
194
195 reg8 |= (3 << 4); /* avoid #S4 assertions */
196 reg8 &= ~(1 << 3); /* minimum asssertion is 1 to 2 RTCCLK */
197
198 pci_write_config8(dev, D31F0_GEN_PMCON_3, reg8);
199 printk(BIOS_INFO, "Set power %s after power failure.\n", state);
200
201 /* Set up NMI on errors. */
202 reg8 = inb(0x61);
203 reg8 &= 0x0f; /* Higher Nibble must be 0 */
204 reg8 &= ~(1 << 3); /* IOCHK# NMI Enable */
205 // reg8 &= ~(1 << 2); /* PCI SERR# Enable */
206 reg8 |= (1 << 2); /* PCI SERR# Disable for now */
207 outb(reg8, 0x61);
208
209 reg8 = inb(0x74); /* Read from 0x74 as 0x70 is write only. */
210 nmi_option = NMI_OFF;
211 get_option(&nmi_option, "nmi");
212 if (nmi_option) {
213 printk(BIOS_INFO, "NMI sources enabled.\n");
214 reg8 &= ~(1 << 7); /* Set NMI. */
215 } else {
216 printk(BIOS_INFO, "NMI sources disabled.\n");
Elyes HAOUAS9c5d4632018-04-26 22:21:21 +0200217 reg8 |= (1 << 7); /* Can't mask NMI from PCI-E and NMI_NOW */
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200218 }
219 outb(reg8, 0x70);
220
221 /* Enable CPU_SLP# and Intel Speedstep, set SMI# rate down */
222 reg16 = pci_read_config16(dev, D31F0_GEN_PMCON_1);
223 reg16 &= ~(3 << 0); // SMI# rate 1 minute
224 reg16 |= (1 << 2); // CLKRUN_EN - Mobile/Ultra only
225 reg16 |= (1 << 3); // Speedstep Enable - Mobile/Ultra only
226 reg16 |= (1 << 5); // CPUSLP_EN Desktop only
227
228 if (config->c4onc3_enable)
229 reg16 |= (1 << 7);
230
231 // another laptop wants this?
232 // reg16 &= ~(1 << 10); // BIOS_PCI_EXP_EN - Desktop/Mobile only
233 reg16 |= (1 << 10); // BIOS_PCI_EXP_EN - Desktop/Mobile only
Kyösti Mälkki94464472020-06-13 13:45:42 +0300234 if (CONFIG(DEBUG_PERIODIC_SMI))
235 reg16 |= (3 << 0); // Periodic SMI every 8s
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200236 if (config->c5_enable)
237 reg16 |= (1 << 11); /* Enable C5, C6 and PMSYNC# */
238 pci_write_config16(dev, D31F0_GEN_PMCON_1, reg16);
239
240 /* Set exit timings for C5/C6. */
241 if (config->c5_enable) {
242 reg8 = pci_read_config8(dev, D31F0_C5_EXIT_TIMING);
243 reg8 &= ~((7 << 3) | (7 << 0));
244 if (config->c6_enable)
245 reg8 |= (5 << 3) | (3 << 0); /* 38-44us PMSYNC# to STPCLK#,
246 95-102us DPRSTP# to STP_CPU# */
247 else
248 reg8 |= (0 << 3) | (1 << 0); /* 16-17us PMSYNC# to STPCLK#,
249 34-40us DPRSTP# to STP_CPU# */
250 pci_write_config8(dev, D31F0_C5_EXIT_TIMING, reg8);
251 }
252
253 // Set the board's GPI routing.
Arthur Heymans349e0852017-04-09 20:48:37 +0200254 i82801jx_gpi_routing(dev);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200255
256 pmbase = pci_read_config16(dev, 0x40) & 0xfffe;
257
258 outl(config->gpe0_en, pmbase + 0x28);
259 outw(config->alt_gp_smi_en, pmbase + 0x38);
260
261 /* Set up power management block and determine sleep mode */
262 reg16 = inw(pmbase + 0x00); /* PM1_STS */
263 outw(reg16, pmbase + 0x00); /* Clear status bits. At least bit11 (power
264 button override) must be cleared or SCI
265 will be constantly fired and OSPM must
266 not know about it (ACPI spec says to
267 ignore the bit). */
268 reg32 = inl(pmbase + 0x04); // PM1_CNT
269 reg32 &= ~(7 << 10); // SLP_TYP
270 outl(reg32, pmbase + 0x04);
271
272 /* Set duty cycle for hardware throttling (defaults to 0x0: 50%). */
273 reg32 = inl(pmbase + 0x10);
274 reg32 &= ~(7 << 5);
275 reg32 |= (config->throttle_duty & 7) << 5;
276 outl(reg32, pmbase + 0x10);
277}
278
Elyes HAOUAS1a8c1df2018-05-13 13:36:44 +0200279static void i82801jx_configure_cstates(struct device *dev)
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200280{
Angel Pons2048cb42020-06-08 02:09:33 +0200281 // Enable Popup & Popdown
282 pci_or_config8(dev, D31F0_CxSTATE_CNF, (1 << 4) | (1 << 3) | (1 << 2));
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200283
284 // Set Deeper Sleep configuration to recommended values
Angel Pons2048cb42020-06-08 02:09:33 +0200285 // Deeper Sleep to Stop CPU: 34-40us
286 // Deeper Sleep to Sleep: 15us
287 pci_update_config8(dev, D31F0_C4TIMING_CNT, ~0x0f, (2 << 2) | (2 << 0));
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200288
289 /* We could enable slow-C4 exit here, if someone needs it? */
290}
291
Arthur Heymans349e0852017-04-09 20:48:37 +0200292static void i82801jx_rtc_init(struct device *dev)
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200293{
294 u8 reg8;
295 int rtc_failed;
296
297 reg8 = pci_read_config8(dev, D31F0_GEN_PMCON_3);
298 rtc_failed = reg8 & RTC_BATTERY_DEAD;
299 if (rtc_failed) {
300 reg8 &= ~RTC_BATTERY_DEAD;
301 pci_write_config8(dev, D31F0_GEN_PMCON_3, reg8);
302 }
303 printk(BIOS_DEBUG, "rtc_failed = 0x%x\n", rtc_failed);
304
305 cmos_init(rtc_failed);
306}
307
308static void enable_hpet(void)
309{
310 u32 reg32;
311
312 /* Move HPET to default address 0xfed00000 and enable it */
313 reg32 = RCBA32(RCBA_HPTC);
314 reg32 |= (1 << 7); // HPET Address Enable
315 reg32 &= ~(3 << 0);
316 RCBA32(RCBA_HPTC) = reg32;
317}
318
319static void enable_clock_gating(void)
320{
321 u32 reg32;
322
323 /* Enable DMI dynamic clock gating. */
324 RCBA32(RCBA_DMIC) |= 3;
325
326 /* Enable Clock Gating for most devices. */
327 reg32 = RCBA32(RCBA_CG);
328 reg32 |= (1 << 31); /* LPC dynamic clock gating */
329 /* USB UHCI dynamic clock gating: */
330 reg32 |= (1 << 29) | (1 << 28);
331 /* SATA dynamic clock gating [0-3]: */
332 reg32 |= (1 << 27) | (1 << 26) | (1 << 25) | (1 << 24);
333 reg32 |= (1 << 23); /* LAN static clock gating (if LAN disabled) */
334 reg32 |= (1 << 22); /* HD audio dynamic clock gating */
335 reg32 &= ~(1 << 21); /* No HD audio static clock gating */
336 reg32 &= ~(1 << 20); /* No USB EHCI static clock gating */
337 reg32 |= (1 << 19); /* USB EHCI dynamic clock gating */
338 /* More SATA dynamic clock gating [4-5]: */
339 reg32 |= (1 << 18) | (1 << 17);
340 reg32 |= (1 << 16); /* PCI dynamic clock gating */
341 /* PCIe, DMI dynamic clock gating: */
342 reg32 |= (1 << 4) | (1 << 3) | (1 << 2) | (1 << 1);
343 reg32 |= (1 << 0); /* PCIe root port static clock gating */
344 RCBA32(RCBA_CG) = reg32;
345
346 /* Enable SPI dynamic clock gating. */
347 RCBA32(0x38c0) |= 7;
348}
349
Kyösti Mälkki83d6a8a2019-07-12 08:16:53 +0300350static void i82801jx_set_acpi_mode(struct device *dev)
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200351{
Kyösti Mälkkiad882c32020-06-02 05:05:30 +0300352 if (!acpi_is_wakeup_s3()) {
353 apm_control(APM_CNT_ACPI_DISABLE);
354 } else {
355 apm_control(APM_CNT_ACPI_ENABLE);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200356 }
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200357}
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200358
359static void lpc_init(struct device *dev)
360{
Elyes HAOUASbfc255a2020-03-07 13:05:14 +0100361 printk(BIOS_DEBUG, "i82801jx: %s\n", __func__);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200362
363 /* Set the value for PCI command register. */
364 pci_write_config16(dev, PCI_COMMAND, 0x000f);
365
366 /* IO APIC initialization. */
Arthur Heymans349e0852017-04-09 20:48:37 +0200367 i82801jx_enable_apic(dev);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200368
Arthur Heymans349e0852017-04-09 20:48:37 +0200369 i82801jx_enable_serial_irqs(dev);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200370
371 /* Setup the PIRQ. */
Arthur Heymans349e0852017-04-09 20:48:37 +0200372 i82801jx_pirq_init(dev);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200373
374 /* Setup power options. */
Arthur Heymans349e0852017-04-09 20:48:37 +0200375 i82801jx_power_options(dev);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200376
377 /* Configure Cx state registers */
378 if (LPC_IS_MOBILE(dev))
Arthur Heymans349e0852017-04-09 20:48:37 +0200379 i82801jx_configure_cstates(dev);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200380
381 /* Initialize the real time clock. */
Arthur Heymans349e0852017-04-09 20:48:37 +0200382 i82801jx_rtc_init(dev);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200383
384 /* Initialize ISA DMA. */
385 isa_dma_init();
386
387 /* Initialize the High Precision Event Timers, if present. */
388 enable_hpet();
389
390 /* Initialize Clock Gating */
391 enable_clock_gating();
392
393 setup_i8259();
394
395 /* The OS should do this? */
396 /* Interrupt 9 should be level triggered (SCI) */
397 i8259_configure_irq_trigger(9, 1);
398
Kyösti Mälkki44da9e72019-10-09 12:32:16 +0300399 i82801jx_set_acpi_mode(dev);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200400}
401
Arthur Heymansad501492017-04-12 00:15:39 +0200402unsigned long acpi_fill_madt(unsigned long current)
403{
404 /* Local APICs */
405 current = acpi_create_madt_lapics(current);
406
407 /* IOAPIC */
408 current += acpi_create_madt_ioapic((acpi_madt_ioapic_t *) current,
409 2, IO_APIC_ADDR, 0);
410
411 /* LAPIC_NMI */
412 current += acpi_create_madt_lapic_nmi((acpi_madt_lapic_nmi_t *)
413 current, 0,
414 MP_IRQ_POLARITY_HIGH |
415 MP_IRQ_TRIGGER_EDGE, 0x01);
416 current += acpi_create_madt_lapic_nmi((acpi_madt_lapic_nmi_t *)
417 current, 1, MP_IRQ_POLARITY_HIGH |
418 MP_IRQ_TRIGGER_EDGE, 0x01);
419
420 /* INT_SRC_OVR */
421 current += acpi_create_madt_irqoverride((acpi_madt_irqoverride_t *)
422 current, 0, 0, 2, MP_IRQ_POLARITY_HIGH | MP_IRQ_TRIGGER_EDGE);
423 current += acpi_create_madt_irqoverride((acpi_madt_irqoverride_t *)
424 current, 0, 9, 9, MP_IRQ_POLARITY_HIGH | MP_IRQ_TRIGGER_LEVEL);
425
426
427 return current;
428}
429
Elyes HAOUAS1a8c1df2018-05-13 13:36:44 +0200430static void i82801jx_lpc_read_resources(struct device *dev)
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200431{
Arthur Heymanse5dcaf12017-04-12 00:03:37 +0200432 int i, io_index = 0;
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200433 /*
434 * I/O Resources
435 *
436 * 0x0000 - 0x000f....ISA DMA
437 * 0x0010 - 0x001f....ISA DMA aliases
438 * 0x0020 ~ 0x003d....PIC
439 * 0x002e - 0x002f....Maybe Super I/O
440 * 0x0040 - 0x0043....Timer
441 * 0x004e - 0x004f....Maybe Super I/O
442 * 0x0050 - 0x0053....Timer aliases
443 * 0x0061.............NMI_SC
444 * 0x0070.............NMI_EN (readable in alternative access mode)
445 * 0x0070 - 0x0077....RTC
446 * 0x0080 - 0x008f....ISA DMA
447 * 0x0090 ~ 0x009f....ISA DMA aliases
448 * 0x0092.............Fast A20 and Init
449 * 0x00a0 ~ 0x00bd....PIC
450 * 0x00b2 - 0x00b3....APM
451 * 0x00c0 ~ 0x00de....ISA DMA
452 * 0x00c1 ~ 0x00df....ISA DMA aliases
453 * 0x00f0.............Coprocessor Error
Angel Ponsb21bffa2020-07-03 01:02:28 +0200454 * (0x0400-0x041f)....SMBus (CONFIG_FIXED_SMBUS_IO_BASE, during raminit)
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200455 * 0x04d0 - 0x04d1....PIC
456 * 0x0500 - 0x057f....PM (DEFAULT_PMBASE)
457 * 0x0580 - 0x05bf....SB GPIO (DEFAULT_GPIOBASE)
458 * 0x05c0 - 0x05ff....SB GPIO cont. (mobile only)
459 * 0x0cf8 - 0x0cff....PCI
460 * 0x0cf9.............Reset Control
461 */
462
463 struct resource *res;
464
465 /* Get the normal PCI resources of this device. */
466 pci_dev_read_resources(dev);
467
468 /* Add an extra subtractive resource for both memory and I/O. */
Arthur Heymanse5dcaf12017-04-12 00:03:37 +0200469 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200470 res->base = 0;
471 res->size = 0x1000;
472 res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
473 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
474
Arthur Heymanse5dcaf12017-04-12 00:03:37 +0200475 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
476 res->base = 0xff000000;
477 res->size = 0x01000000; /* 16 MB for flash */
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200478 res->flags = IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE |
479 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
480
481 res = new_resource(dev, 3); /* IOAPIC */
482 res->base = IO_APIC_ADDR;
483 res->size = 0x00001000;
484 res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
Arthur Heymanse5dcaf12017-04-12 00:03:37 +0200485
486 /* Set IO decode ranges if required.*/
487 for (i = 0; i < 4; i++) {
488 u32 gen_dec;
489 gen_dec = pci_read_config32(dev, 0x84 + 4 * i);
490
491 if ((gen_dec & 0xFFFC) > 0x1000) {
492 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
493 res->base = gen_dec & 0xFFFC;
494 res->size = (gen_dec >> 16) & 0xFC;
495 res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
496 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
497 }
498 }
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200499}
500
Kyösti Mälkki0c1dd9c2020-06-17 23:37:49 +0300501void southbridge_inject_dsdt(const struct device *dev)
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200502{
Kyösti Mälkki0c1dd9c2020-06-17 23:37:49 +0300503 struct global_nvs *gnvs = cbmem_add(CBMEM_ID_ACPI_GNVS, sizeof(*gnvs));
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200504
505 if (gnvs) {
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200506 memset(gnvs, 0, sizeof(*gnvs));
507 acpi_create_gnvs(gnvs);
508
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200509 /* And tell SMI about it */
Kyösti Mälkkic3c55212020-06-17 10:34:26 +0300510 apm_control(APM_CNT_GNVS_UPDATE);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200511
512 /* Add it to SSDT. */
513 acpigen_write_scope("\\");
514 acpigen_write_name_dword("NVSA", (u32) gnvs);
515 acpigen_pop_len();
516 }
517}
518
Arthur Heymansa8a9f342017-12-24 08:11:13 +0100519static const char *lpc_acpi_name(const struct device *dev)
520{
521 return "LPCB";
522}
523
Furquan Shaikh7536a392020-04-24 21:59:21 -0700524static void southbridge_fill_ssdt(const struct device *device)
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200525{
Kyösti Mälkkic70eed12018-05-22 02:18:00 +0300526 struct device *dev = pcidev_on_root(0x1f, 0);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200527 config_t *chip = dev->chip_info;
528
529 intel_acpi_pcie_hotplug_generator(chip->pcie_hotplug_map, 8);
Arthur Heymansa8a9f342017-12-24 08:11:13 +0100530 intel_acpi_gen_def_acpi_pirq(device);
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200531}
532
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200533static struct device_operations device_ops = {
Arthur Heymans349e0852017-04-09 20:48:37 +0200534 .read_resources = i82801jx_lpc_read_resources,
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200535 .set_resources = pci_dev_set_resources,
536 .enable_resources = pci_dev_enable_resources,
Nico Huber68680dd2020-03-31 17:34:52 +0200537 .acpi_inject_dsdt = southbridge_inject_dsdt,
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200538 .write_acpi_tables = acpi_write_hpet,
Nico Huber68680dd2020-03-31 17:34:52 +0200539 .acpi_fill_ssdt = southbridge_fill_ssdt,
Arthur Heymansa8a9f342017-12-24 08:11:13 +0100540 .acpi_name = lpc_acpi_name,
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200541 .init = lpc_init,
Nico Huber51b75ae2019-03-14 16:02:05 +0100542 .scan_bus = scan_static_bus,
Angel Pons1fc0edd2020-05-31 00:03:28 +0200543 .ops_pci = &pci_dev_ops_pci,
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200544};
545
546static const unsigned short pci_device_ids[] = {
Arthur Heymans349e0852017-04-09 20:48:37 +0200547 0x3a10, /* ICH10R Eng. Sample */
548 0x3a14, /* ICH10DO */
549 0x3a16, /* ICH10R */
550 0x3a18, /* ICH10 */
551 0x3a1a, /* ICH10D */
552 0x3a1e, /* ICH10 Eng. Sample */
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200553 0
554};
555
Arthur Heymans349e0852017-04-09 20:48:37 +0200556static const struct pci_driver ich10_lpc __pci_driver = {
Arthur Heymans7b9c1392017-04-09 20:40:39 +0200557 .ops = &device_ops,
558 .vendor = PCI_VENDOR_ID_INTEL,
559 .devices = pci_device_ids,
560};