blob: 592c70f8b43caa38b04d08889c60f24ea6f8dd63 [file] [log] [blame]
Stefan Reinauer8e073822012-04-04 00:07:22 +02001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2008-2009 coresystems GmbH
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; version 2 of
9 * the License.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
Stefan Reinauer8e073822012-04-04 00:07:22 +020015 */
16
17#include <console/console.h>
18#include <device/device.h>
19#include <device/pci.h>
20#include <device/pci_ids.h>
Patrick Rudolphe56189c2018-04-18 10:11:59 +020021#include <device/pci_ops.h>
Patrick Rudolphef8c5592018-07-27 17:48:27 +020022#include <device/pci_def.h>
Stefan Reinauer8e073822012-04-04 00:07:22 +020023#include <pc80/mc146818rtc.h>
24#include <pc80/isa-dma.h>
25#include <pc80/i8259.h>
26#include <arch/io.h>
27#include <arch/ioapic.h>
28#include <arch/acpi.h>
Elyes HAOUASd2b9ec12018-10-27 09:41:02 +020029#include <arch/cpu.h>
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +020030#include <arch/acpigen.h>
31#include <drivers/intel/gma/i915.h>
Vladimir Serbinenko5b044ae2014-10-25 15:20:55 +020032#include <cpu/x86/smm.h>
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +020033#include <cbmem.h>
Vladimir Serbinenko7309c642014-10-05 11:07:33 +020034#include <string.h>
Kyösti Mälkki12b121c2019-08-18 16:33:39 +030035#include "chip.h"
Stefan Reinauer8e073822012-04-04 00:07:22 +020036#include "pch.h"
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +020037#include "nvs.h"
Vladimir Serbinenko36fa5b82014-10-28 23:43:20 +010038#include <southbridge/intel/common/pciehp.h>
Tobias Diedrich7f5efd92017-12-14 00:29:01 +010039#include <southbridge/intel/common/acpi_pirq_gen.h>
Arthur Heymansa0508172018-01-25 11:30:22 +010040#include <southbridge/intel/common/pmutil.h>
Patrick Rudolph6b931122018-11-01 17:48:37 +010041#include <southbridge/intel/common/rtc.h>
Stefan Reinauer8e073822012-04-04 00:07:22 +020042
43#define NMI_OFF 0
44
45#define ENABLE_ACPI_MODE_IN_COREBOOT 0
Stefan Reinauer8e073822012-04-04 00:07:22 +020046
47typedef struct southbridge_intel_bd82x6x_config config_t;
48
Paul Menzel9c50e6a2013-05-03 12:23:39 +020049/**
50 * Set miscellanous static southbridge features.
51 *
52 * @param dev PCI device with I/O APIC control registers
53 */
54static void pch_enable_ioapic(struct device *dev)
Stefan Reinauer8e073822012-04-04 00:07:22 +020055{
Stefan Reinauer8e073822012-04-04 00:07:22 +020056 u32 reg32;
Stefan Reinauer8e073822012-04-04 00:07:22 +020057
Nico Huberb2dae792015-10-26 12:34:02 +010058 /* Assign unique bus/dev/fn for I/O APIC */
59 pci_write_config16(dev, LPC_IBDF,
60 PCH_IOAPIC_PCI_BUS << 8 | PCH_IOAPIC_PCI_SLOT << 3);
61
Paul Menzel9c50e6a2013-05-03 12:23:39 +020062 /* Enable ACPI I/O range decode */
63 pci_write_config8(dev, ACPI_CNTL, ACPI_EN);
Stefan Reinauer8e073822012-04-04 00:07:22 +020064
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -080065 set_ioapic_id(VIO_APIC_VADDR, 0x02);
Stefan Reinauer8e073822012-04-04 00:07:22 +020066
67 /* affirm full set of redirection table entries ("write once") */
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -080068 reg32 = io_apic_read(VIO_APIC_VADDR, 0x01);
69 io_apic_write(VIO_APIC_VADDR, 0x01, reg32);
Stefan Reinauer8e073822012-04-04 00:07:22 +020070
Paul Menzel9c50e6a2013-05-03 12:23:39 +020071 /*
72 * Select Boot Configuration register (0x03) and
73 * use Processor System Bus (0x01) to deliver interrupts.
74 */
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -080075 io_apic_write(VIO_APIC_VADDR, 0x03, 0x01);
Stefan Reinauer8e073822012-04-04 00:07:22 +020076}
77
78static void pch_enable_serial_irqs(struct device *dev)
79{
80 /* Set packet length and toggle silent mode bit for one frame. */
81 pci_write_config8(dev, SERIRQ_CNTL,
82 (1 << 7) | (1 << 6) | ((21 - 17) << 2) | (0 << 0));
Julius Wernercd49cce2019-03-05 16:53:33 -080083#if !CONFIG(SERIRQ_CONTINUOUS_MODE)
Stefan Reinauer8e073822012-04-04 00:07:22 +020084 pci_write_config8(dev, SERIRQ_CNTL,
85 (1 << 7) | (0 << 6) | ((21 - 17) << 2) | (0 << 0));
86#endif
87}
88
89/* PIRQ[n]_ROUT[3:0] - PIRQ Routing Control
90 * 0x00 - 0000 = Reserved
91 * 0x01 - 0001 = Reserved
92 * 0x02 - 0010 = Reserved
93 * 0x03 - 0011 = IRQ3
94 * 0x04 - 0100 = IRQ4
95 * 0x05 - 0101 = IRQ5
96 * 0x06 - 0110 = IRQ6
97 * 0x07 - 0111 = IRQ7
98 * 0x08 - 1000 = Reserved
99 * 0x09 - 1001 = IRQ9
100 * 0x0A - 1010 = IRQ10
101 * 0x0B - 1011 = IRQ11
102 * 0x0C - 1100 = IRQ12
103 * 0x0D - 1101 = Reserved
104 * 0x0E - 1110 = IRQ14
105 * 0x0F - 1111 = IRQ15
106 * PIRQ[n]_ROUT[7] - PIRQ Routing Control
107 * 0x80 - The PIRQ is not routed.
108 */
109
Elyes HAOUAS4aec3402018-05-25 08:29:27 +0200110static void pch_pirq_init(struct device *dev)
Stefan Reinauer8e073822012-04-04 00:07:22 +0200111{
Elyes HAOUAS4aec3402018-05-25 08:29:27 +0200112 struct device *irq_dev;
Vladimir Serbinenko33b535f2014-10-19 10:13:14 +0200113 /* Interrupt 11 is not used by legacy devices and so can always be used for
114 PCI interrupts. Full legacy IRQ routing is complicated and hard to
115 get right. Fortunately all modern OS use MSI and so it's not that big of
116 an issue anyway. Still we have to provide a reasonable default. Using
117 interrupt 11 for it everywhere is a working default. ACPI-aware OS can
118 move it to any interrupt and others will just leave them at default.
Stefan Reinauer8e073822012-04-04 00:07:22 +0200119 */
Vladimir Serbinenko33b535f2014-10-19 10:13:14 +0200120 const u8 pirq_routing = 11;
121
122 pci_write_config8(dev, PIRQA_ROUT, pirq_routing);
123 pci_write_config8(dev, PIRQB_ROUT, pirq_routing);
124 pci_write_config8(dev, PIRQC_ROUT, pirq_routing);
125 pci_write_config8(dev, PIRQD_ROUT, pirq_routing);
126
127 pci_write_config8(dev, PIRQE_ROUT, pirq_routing);
128 pci_write_config8(dev, PIRQF_ROUT, pirq_routing);
129 pci_write_config8(dev, PIRQG_ROUT, pirq_routing);
130 pci_write_config8(dev, PIRQH_ROUT, pirq_routing);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200131
Elyes HAOUASba28e8d2016-08-31 19:22:16 +0200132 for (irq_dev = all_devices; irq_dev; irq_dev = irq_dev->next) {
Vladimir Serbinenko33b535f2014-10-19 10:13:14 +0200133 u8 int_pin=0;
Stefan Reinauer8e073822012-04-04 00:07:22 +0200134
135 if (!irq_dev->enabled || irq_dev->path.type != DEVICE_PATH_PCI)
136 continue;
137
138 int_pin = pci_read_config8(irq_dev, PCI_INTERRUPT_PIN);
139
Vladimir Serbinenko33b535f2014-10-19 10:13:14 +0200140 if (int_pin == 0)
Stefan Reinauer8e073822012-04-04 00:07:22 +0200141 continue;
142
Vladimir Serbinenko33b535f2014-10-19 10:13:14 +0200143 pci_write_config8(irq_dev, PCI_INTERRUPT_LINE, pirq_routing);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200144 }
145}
146
Elyes HAOUAS4aec3402018-05-25 08:29:27 +0200147static void pch_gpi_routing(struct device *dev)
Stefan Reinauer8e073822012-04-04 00:07:22 +0200148{
149 /* Get the chip configuration */
150 config_t *config = dev->chip_info;
151 u32 reg32 = 0;
152
153 /* An array would be much nicer here, or some
154 * other method of doing this.
155 */
156 reg32 |= (config->gpi0_routing & 0x03) << 0;
157 reg32 |= (config->gpi1_routing & 0x03) << 2;
158 reg32 |= (config->gpi2_routing & 0x03) << 4;
159 reg32 |= (config->gpi3_routing & 0x03) << 6;
160 reg32 |= (config->gpi4_routing & 0x03) << 8;
161 reg32 |= (config->gpi5_routing & 0x03) << 10;
162 reg32 |= (config->gpi6_routing & 0x03) << 12;
163 reg32 |= (config->gpi7_routing & 0x03) << 14;
164 reg32 |= (config->gpi8_routing & 0x03) << 16;
165 reg32 |= (config->gpi9_routing & 0x03) << 18;
166 reg32 |= (config->gpi10_routing & 0x03) << 20;
167 reg32 |= (config->gpi11_routing & 0x03) << 22;
168 reg32 |= (config->gpi12_routing & 0x03) << 24;
169 reg32 |= (config->gpi13_routing & 0x03) << 26;
170 reg32 |= (config->gpi14_routing & 0x03) << 28;
171 reg32 |= (config->gpi15_routing & 0x03) << 30;
172
Kyösti Mälkkib85a87b2014-12-29 11:32:27 +0200173 pci_write_config32(dev, GPIO_ROUT, reg32);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200174}
175
Elyes HAOUAS4aec3402018-05-25 08:29:27 +0200176static void pch_power_options(struct device *dev)
Stefan Reinauer8e073822012-04-04 00:07:22 +0200177{
178 u8 reg8;
179 u16 reg16, pmbase;
180 u32 reg32;
181 const char *state;
182 /* Get the chip configuration */
183 config_t *config = dev->chip_info;
184
Nico Huber9faae2b2018-11-14 00:00:35 +0100185 int pwr_on = CONFIG_MAINBOARD_POWER_FAILURE_STATE;
Stefan Reinauer8e073822012-04-04 00:07:22 +0200186 int nmi_option;
187
188 /* Which state do we want to goto after g3 (power restored)?
189 * 0 == S0 Full On
190 * 1 == S5 Soft Off
191 *
192 * If the option is not existent (Laptops), use Kconfig setting.
193 */
194 get_option(&pwr_on, "power_on_after_fail");
195
196 reg16 = pci_read_config16(dev, GEN_PMCON_3);
197 reg16 &= 0xfffe;
198 switch (pwr_on) {
199 case MAINBOARD_POWER_OFF:
200 reg16 |= 1;
201 state = "off";
202 break;
203 case MAINBOARD_POWER_ON:
204 reg16 &= ~1;
205 state = "on";
206 break;
207 case MAINBOARD_POWER_KEEP:
208 reg16 &= ~1;
209 state = "state keep";
210 break;
211 default:
212 state = "undefined";
213 }
214
215 reg16 &= ~(3 << 4); /* SLP_S4# Assertion Stretch 4s */
216 reg16 |= (1 << 3); /* SLP_S4# Assertion Stretch Enable */
217
218 reg16 &= ~(1 << 10);
219 reg16 |= (1 << 11); /* SLP_S3# Min Assertion Width 50ms */
220
221 reg16 |= (1 << 12); /* Disable SLP stretch after SUS well */
222
223 pci_write_config16(dev, GEN_PMCON_3, reg16);
224 printk(BIOS_INFO, "Set power %s after power failure.\n", state);
225
226 /* Set up NMI on errors. */
227 reg8 = inb(0x61);
228 reg8 &= 0x0f; /* Higher Nibble must be 0 */
229 reg8 &= ~(1 << 3); /* IOCHK# NMI Enable */
230 // reg8 &= ~(1 << 2); /* PCI SERR# Enable */
231 reg8 |= (1 << 2); /* PCI SERR# Disable for now */
232 outb(reg8, 0x61);
233
234 reg8 = inb(0x70);
235 nmi_option = NMI_OFF;
236 get_option(&nmi_option, "nmi");
237 if (nmi_option) {
238 printk(BIOS_INFO, "NMI sources enabled.\n");
239 reg8 &= ~(1 << 7); /* Set NMI. */
240 } else {
241 printk(BIOS_INFO, "NMI sources disabled.\n");
Elyes HAOUAS9c5d4632018-04-26 22:21:21 +0200242 reg8 |= (1 << 7); /* Can't mask NMI from PCI-E and NMI_NOW */
Stefan Reinauer8e073822012-04-04 00:07:22 +0200243 }
244 outb(reg8, 0x70);
245
246 /* Enable CPU_SLP# and Intel Speedstep, set SMI# rate down */
247 reg16 = pci_read_config16(dev, GEN_PMCON_1);
248 reg16 &= ~(3 << 0); // SMI# rate 1 minute
249 reg16 &= ~(1 << 10); // Disable BIOS_PCI_EXP_EN for native PME
250#if DEBUG_PERIODIC_SMIS
251 /* Set DEBUG_PERIODIC_SMIS in pch.h to debug using
252 * periodic SMIs.
253 */
254 reg16 |= (3 << 0); // Periodic SMI every 8s
255#endif
256 pci_write_config16(dev, GEN_PMCON_1, reg16);
257
258 // Set the board's GPI routing.
259 pch_gpi_routing(dev);
260
261 pmbase = pci_read_config16(dev, 0x40) & 0xfffe;
262
263 outl(config->gpe0_en, pmbase + GPE0_EN);
264 outw(config->alt_gp_smi_en, pmbase + ALT_GP_SMI_EN);
265
266 /* Set up power management block and determine sleep mode */
267 reg32 = inl(pmbase + 0x04); // PM1_CNT
268 reg32 &= ~(7 << 10); // SLP_TYP
269 reg32 |= (1 << 0); // SCI_EN
270 outl(reg32, pmbase + 0x04);
271
272 /* Clear magic status bits to prevent unexpected wake */
Patrick Rudolph4f8b1082019-07-14 11:54:58 +0200273 reg32 = RCBA32(PRSTS);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200274 reg32 |= (1 << 4)|(1 << 5)|(1 << 0);
Patrick Rudolph4f8b1082019-07-14 11:54:58 +0200275 RCBA32(PRSTS) = reg32;
Stefan Reinauer8e073822012-04-04 00:07:22 +0200276
277 reg32 = RCBA32(0x3f02);
278 reg32 &= ~0xf;
279 RCBA32(0x3f02) = reg32;
280}
281
Duncan Laurie3f6a4d72012-06-28 13:03:40 -0700282/* CougarPoint PCH Power Management init */
283static void cpt_pm_init(struct device *dev)
Stefan Reinauer8e073822012-04-04 00:07:22 +0200284{
Duncan Laurie3f6a4d72012-06-28 13:03:40 -0700285 printk(BIOS_DEBUG, "CougarPoint PM init\n");
Stefan Reinauer8e073822012-04-04 00:07:22 +0200286 pci_write_config8(dev, 0xa9, 0x47);
Patrick Rudolph4f8b1082019-07-14 11:54:58 +0200287 RCBA32_AND_OR(CIR30, ~0UL, (1 << 6)|(1 << 0));
288 RCBA32_AND_OR(CIR5, ~0UL, (1 << 0));
289 RCBA16_AND_OR(CIR3, ~0UL, (1 << 13)|(1 << 14));
290 RCBA16_AND_OR(CIR2, ~0UL, (1 << 14));
291 RCBA32(DMC) = 0xc0388400;
292 RCBA32_AND_OR(CIR6, ~0UL, (1 << 5)|(1 << 18));
293 RCBA32_AND_OR(CIR9, ~0UL, (1 << 15)|(1 << 1));
294 RCBA32_AND_OR(CIR7, ~0x1f, 0xf);
295 RCBA32(PM_CFG) = 0x050f0000;
296 RCBA32(CIR8) = 0x04000000;
297 RCBA32_AND_OR(CIR10, ~0UL, 0xfffff);
298 RCBA32_AND_OR(CIR11, ~0UL, (1 << 1));
299 RCBA32(CIR12) = 0x0001c000;
300 RCBA32(CIR14) = 0x00061100;
301 RCBA32(CIR15) = 0x7f8fdfff;
302 RCBA32(CIR13) = 0x000003fc;
303 RCBA32(CIR16) = 0x00001000;
304 RCBA32(CIR18) = 0x0001c000;
305 RCBA32(CIR17) = 0x00000800;
306 RCBA32(CIR23) = 0x00001000;
307 RCBA32(CIR19) = 0x00093900;
308 RCBA32(CIR20) = 0x24653002;
309 RCBA32(CIR21) = 0x062108fe;
310 RCBA32_AND_OR(CIR22, 0xf000f000, 0x00670060);
311 RCBA32(CIR24) = 0x01010000;
312 RCBA32(CIR25) = 0x01010404;
313 RCBA32(CIR27) = 0x01041041;
314 RCBA32_AND_OR(CIR28, ~0x0000ffff, 0x00001001);
315 RCBA32_AND_OR(CIR28, ~0UL, (1 << 24)); /* SATA 2/3 disabled */
316 RCBA32_AND_OR(CIR29, ~0UL, (1 << 0)); /* SATA 4/5 disabled */
317 RCBA32(CIR26) = 0x00000001;
Stefan Reinauer8e073822012-04-04 00:07:22 +0200318 RCBA32_AND_OR(0x2344, 0x00ffff00, 0xff00000c);
319 RCBA32_AND_OR(0x80c, ~(0xff << 20), 0x11 << 20);
Patrick Rudolph4f8b1082019-07-14 11:54:58 +0200320 RCBA32(PMSYNC_CFG) = 0;
Stefan Reinauer8e073822012-04-04 00:07:22 +0200321 RCBA32_AND_OR(0x21b0, ~0UL, 0xf);
322}
323
Duncan Laurie3f6a4d72012-06-28 13:03:40 -0700324/* PantherPoint PCH Power Management init */
325static void ppt_pm_init(struct device *dev)
326{
327 printk(BIOS_DEBUG, "PantherPoint PM init\n");
328 pci_write_config8(dev, 0xa9, 0x47);
Patrick Rudolph4f8b1082019-07-14 11:54:58 +0200329 RCBA32_AND_OR(CIR30, ~0UL, (1 << 0));
330 RCBA32_AND_OR(CIR5, ~0UL, (1 << 0));
331 RCBA16_AND_OR(CIR3, ~0UL, (1 << 13)|(1 << 14));
332 RCBA16_AND_OR(CIR2, ~0UL, (1 << 14));
333 RCBA32(DMC) = 0xc03b8400;
334 RCBA32_AND_OR(CIR6, ~0UL, (1 << 5)|(1 << 18));
335 RCBA32_AND_OR(CIR9, ~0UL, (1 << 15)|(1 << 1));
336 RCBA32_AND_OR(CIR7, ~0x1f, 0xf);
337 RCBA32(PM_CFG) = 0x054f0000;
338 RCBA32(CIR8) = 0x04000000;
339 RCBA32_AND_OR(CIR10, ~0UL, 0xfffff);
340 RCBA32_AND_OR(CIR11, ~0UL, (1 << 1)|(1 << 0));
341 RCBA32(CIR12) = 0x0001c000;
342 RCBA32(CIR14) = 0x00061100;
343 RCBA32(CIR15) = 0x7f8fdfff;
344 RCBA32(CIR13) = 0x000003fd;
345 RCBA32(CIR16) = 0x00001000;
346 RCBA32(CIR18) = 0x0001c000;
347 RCBA32(CIR17) = 0x00000800;
348 RCBA32(CIR23) = 0x00001000;
349 RCBA32(CIR19) = 0x00093900;
350 RCBA32(CIR20) = 0x24653002;
351 RCBA32(CIR21) = 0x067388fe;
352 RCBA32_AND_OR(CIR22, 0xf000f000, 0x00670060);
353 RCBA32(CIR24) = 0x01010000;
354 RCBA32(CIR25) = 0x01010404;
355 RCBA32(CIR27) = 0x01040000;
356 RCBA32_AND_OR(CIR28, ~0x0000ffff, 0x00001001);
357 RCBA32_AND_OR(CIR28, ~0UL, (1 << 24)); /* SATA 2/3 disabled */
358 RCBA32_AND_OR(CIR29, ~0UL, (1 << 0)); /* SATA 4/5 disabled */
359 RCBA32(CIR26) = 0x00000001;
Duncan Laurie3f6a4d72012-06-28 13:03:40 -0700360 RCBA32_AND_OR(0x2344, 0x00ffff00, 0xff00000c);
361 RCBA32_AND_OR(0x80c, ~(0xff << 20), 0x11 << 20);
362 RCBA32_AND_OR(0x33a4, ~0UL, (1 << 0));
Patrick Rudolph4f8b1082019-07-14 11:54:58 +0200363 RCBA32(PMSYNC_CFG) = 0;
Duncan Laurie3f6a4d72012-06-28 13:03:40 -0700364 RCBA32_AND_OR(0x21b0, ~0UL, 0xf);
365}
366
Nico Huberb2dae792015-10-26 12:34:02 +0100367static void enable_hpet(struct device *const dev)
Stefan Reinauer8e073822012-04-04 00:07:22 +0200368{
369 u32 reg32;
Nico Huberb2dae792015-10-26 12:34:02 +0100370 size_t i;
371
372 /* Assign unique bus/dev/fn for each HPET */
373 for (i = 0; i < 8; ++i)
374 pci_write_config16(dev, LPC_HnBDF(i),
375 PCH_HPET_PCI_BUS << 8 | PCH_HPET_PCI_SLOT << 3 | i);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200376
377 /* Move HPET to default address 0xfed00000 and enable it */
378 reg32 = RCBA32(HPTC);
379 reg32 |= (1 << 7); // HPET Address Enable
380 reg32 &= ~(3 << 0);
381 RCBA32(HPTC) = reg32;
382}
383
Elyes HAOUAS4aec3402018-05-25 08:29:27 +0200384static void enable_clock_gating(struct device *dev)
Stefan Reinauer8e073822012-04-04 00:07:22 +0200385{
386 u32 reg32;
387 u16 reg16;
388
Patrick Rudolph4f8b1082019-07-14 11:54:58 +0200389 RCBA32_AND_OR(DMIC, ~0UL, 0xf);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200390
391 reg16 = pci_read_config16(dev, GEN_PMCON_1);
392 reg16 |= (1 << 2) | (1 << 11);
393 pci_write_config16(dev, GEN_PMCON_1, reg16);
394
395 pch_iobp_update(0xEB007F07, ~0UL, (1 << 31));
396 pch_iobp_update(0xEB004000, ~0UL, (1 << 7));
397 pch_iobp_update(0xEC007F07, ~0UL, (1 << 31));
398 pch_iobp_update(0xEC004000, ~0UL, (1 << 7));
399
400 reg32 = RCBA32(CG);
401 reg32 |= (1 << 31);
402 reg32 |= (1 << 29) | (1 << 28);
403 reg32 |= (1 << 27) | (1 << 26) | (1 << 25) | (1 << 24);
404 reg32 |= (1 << 16);
405 reg32 |= (1 << 17);
406 reg32 |= (1 << 18);
407 reg32 |= (1 << 22);
408 reg32 |= (1 << 23);
409 reg32 &= ~(1 << 20);
410 reg32 |= (1 << 19);
411 reg32 |= (1 << 0);
412 reg32 |= (0xf << 1);
413 RCBA32(CG) = reg32;
414
415 RCBA32_OR(0x38c0, 0x7);
416 RCBA32_OR(0x36d4, 0x6680c004);
417 RCBA32_OR(0x3564, 0x3);
418}
419
Vladimir Serbinenkoa3e41c02015-05-28 16:04:17 +0200420static void pch_set_acpi_mode(void)
Stefan Reinauer8e073822012-04-04 00:07:22 +0200421{
Julius Werner5d1f9a02019-03-07 17:07:26 -0800422 if (!acpi_is_wakeup_s3() && CONFIG(HAVE_SMI_HANDLER)) {
Stefan Reinauer8e073822012-04-04 00:07:22 +0200423#if ENABLE_ACPI_MODE_IN_COREBOOT
Duncan Laurie95be1d62012-04-09 12:31:43 -0700424 printk(BIOS_DEBUG, "Enabling ACPI via APMC:\n");
Vladimir Serbinenkoa3e41c02015-05-28 16:04:17 +0200425 outb(APM_CNT_ACPI_ENABLE, APM_CNT); // Enable ACPI mode
Duncan Laurie95be1d62012-04-09 12:31:43 -0700426 printk(BIOS_DEBUG, "done.\n");
Stefan Reinauer8e073822012-04-04 00:07:22 +0200427#else
Duncan Laurie95be1d62012-04-09 12:31:43 -0700428 printk(BIOS_DEBUG, "Disabling ACPI via APMC:\n");
Vladimir Serbinenkoa3e41c02015-05-28 16:04:17 +0200429 outb(APM_CNT_ACPI_DISABLE, APM_CNT); // Disable ACPI mode
Duncan Laurie95be1d62012-04-09 12:31:43 -0700430 printk(BIOS_DEBUG, "done.\n");
Stefan Reinauer8e073822012-04-04 00:07:22 +0200431#endif
Duncan Laurie95be1d62012-04-09 12:31:43 -0700432 }
Stefan Reinauer8e073822012-04-04 00:07:22 +0200433}
Stefan Reinauer8e073822012-04-04 00:07:22 +0200434
435static void pch_disable_smm_only_flashing(struct device *dev)
436{
437 u8 reg8;
438
439 printk(BIOS_SPEW, "Enabling BIOS updates outside of SMM... ");
Elyes HAOUAS0c22d2f2018-12-01 12:19:52 +0100440 reg8 = pci_read_config8(dev, BIOS_CNTL);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200441 reg8 &= ~(1 << 5);
Elyes HAOUAS0c22d2f2018-12-01 12:19:52 +0100442 pci_write_config8(dev, BIOS_CNTL, reg8);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200443}
444
445static void pch_fixups(struct device *dev)
446{
447 u8 gen_pmcon_2;
448
449 /* Indicate DRAM init done for MRC S3 to know it can resume */
450 gen_pmcon_2 = pci_read_config8(dev, GEN_PMCON_2);
451 gen_pmcon_2 |= (1 << 7);
452 pci_write_config8(dev, GEN_PMCON_2, gen_pmcon_2);
453
454 /*
455 * Enable DMI ASPM in the PCH
456 */
Patrick Rudolph4f8b1082019-07-14 11:54:58 +0200457 RCBA32_AND_OR(DMC, ~(1 << 10), 0);
458 RCBA32_OR(LCAP, (1 << 11)|(1 << 10));
459 RCBA32_OR(LCTL, 0x3);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200460}
461
462static void pch_decode_init(struct device *dev)
463{
464 config_t *config = dev->chip_info;
465
466 printk(BIOS_DEBUG, "pch_decode_init\n");
467
468 pci_write_config32(dev, LPC_GEN1_DEC, config->gen1_dec);
469 pci_write_config32(dev, LPC_GEN2_DEC, config->gen2_dec);
470 pci_write_config32(dev, LPC_GEN3_DEC, config->gen3_dec);
471 pci_write_config32(dev, LPC_GEN4_DEC, config->gen4_dec);
472}
473
Nico Huber7b2f9f62015-10-01 19:00:51 +0200474static void pch_spi_init(const struct device *const dev)
475{
476 const config_t *const config = dev->chip_info;
477
478 printk(BIOS_DEBUG, "pch_spi_init\n");
479
480 if (config->spi_uvscc)
481 RCBA32(0x3800 + 0xc8) = config->spi_uvscc;
482 if (config->spi_lvscc)
483 RCBA32(0x3800 + 0xc4) = config->spi_lvscc;
484
485 if (config->spi_uvscc || config->spi_lvscc)
486 RCBA32_OR(0x3800 + 0xc4, 1 << 23); /* lock both UVSCC + LVSCC */
487}
488
Patrick Rudolphef8c5592018-07-27 17:48:27 +0200489static const struct {
490 u16 dev_id;
491 const char *dev_name;
492} pch_table[] = {
493 /* 6-series PCI ids from
494 * Intel® 6 Series Chipset and
495 * Intel® C200 Series Chipset
496 * Specification Update - NDA
497 * October 2013
498 * CDI / IBP#: 440377
499 */
500 {0x1C41, "SFF Sample"},
501 {0x1C42, "Desktop Sample"},
502 {0x1C43, "Mobile Sample"},
503 {0x1C44, "Z68"},
504 {0x1C46, "P67"},
505 {0x1C47, "UM67"},
506 {0x1C49, "HM65"},
507 {0x1C4A, "H67"},
508 {0x1C4B, "HM67"},
509 {0x1C4C, "Q65"},
510 {0x1C4D, "QS67"},
511 {0x1C4E, "Q67"},
512 {0x1C4F, "QM67"},
513 {0x1C50, "B65"},
514 {0x1C52, "C202"},
515 {0x1C54, "C204"},
516 {0x1C56, "C206"},
517 {0x1C5C, "H61"},
518 /* 7-series PCI ids from Intel document 472178 */
519 {0x1E41, "Desktop Sample"},
520 {0x1E42, "Mobile Sample"},
521 {0x1E43, "SFF Sample"},
522 {0x1E44, "Z77"},
523 {0x1E45, "H71"},
524 {0x1E46, "Z75"},
525 {0x1E47, "Q77"},
526 {0x1E48, "Q75"},
527 {0x1E49, "B75"},
528 {0x1E4A, "H77"},
529 {0x1E53, "C216"},
530 {0x1E55, "QM77"},
531 {0x1E56, "QS77"},
532 {0x1E58, "UM77"},
533 {0x1E57, "HM77"},
534 {0x1E59, "HM76"},
535 {0x1E5D, "HM75"},
536 {0x1E5E, "HM70"},
537 {0x1E5F, "NM70"},
538};
539
540static void report_pch_info(struct device *dev)
541{
542 const u16 dev_id = pci_read_config16(dev, PCI_DEVICE_ID);
543 int i;
544
545 const char *pch_type = "Unknown";
546 for (i = 0; i < ARRAY_SIZE(pch_table); i++) {
547 if (pch_table[i].dev_id == dev_id) {
548 pch_type = pch_table[i].dev_name;
549 break;
550 }
551 }
552 printk(BIOS_INFO, "PCH: detected %s, device id: 0x%x, rev id 0x%x\n",
553 pch_type, dev_id, pci_read_config8(dev, PCI_CLASS_REVISION));
554}
555
Stefan Reinauer8e073822012-04-04 00:07:22 +0200556static void lpc_init(struct device *dev)
557{
558 printk(BIOS_DEBUG, "pch: lpc_init\n");
559
Patrick Rudolphef8c5592018-07-27 17:48:27 +0200560 /* Print detected platform */
561 report_pch_info(dev);
562
Stefan Reinauer8e073822012-04-04 00:07:22 +0200563 /* Set the value for PCI command register. */
564 pci_write_config16(dev, PCI_COMMAND, 0x000f);
565
566 /* IO APIC initialization. */
Paul Menzel9c50e6a2013-05-03 12:23:39 +0200567 pch_enable_ioapic(dev);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200568
569 pch_enable_serial_irqs(dev);
570
571 /* Setup the PIRQ. */
572 pch_pirq_init(dev);
573
574 /* Setup power options. */
575 pch_power_options(dev);
576
577 /* Initialize power management */
Duncan Laurie3f6a4d72012-06-28 13:03:40 -0700578 switch (pch_silicon_type()) {
579 case PCH_TYPE_CPT: /* CougarPoint */
580 cpt_pm_init(dev);
581 break;
582 case PCH_TYPE_PPT: /* PantherPoint */
583 ppt_pm_init(dev);
584 break;
585 default:
586 printk(BIOS_ERR, "Unknown Chipset: 0x%04x\n", dev->device);
587 }
Stefan Reinauer8e073822012-04-04 00:07:22 +0200588
589 /* Set the state of the GPIO lines. */
590 //gpio_init(dev);
591
592 /* Initialize the real time clock. */
Patrick Rudolph6b931122018-11-01 17:48:37 +0100593 sb_rtc_init();
Stefan Reinauer8e073822012-04-04 00:07:22 +0200594
595 /* Initialize ISA DMA. */
596 isa_dma_init();
597
598 /* Initialize the High Precision Event Timers, if present. */
Nico Huberb2dae792015-10-26 12:34:02 +0100599 enable_hpet(dev);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200600
601 /* Initialize Clock Gating */
602 enable_clock_gating(dev);
603
604 setup_i8259();
605
606 /* The OS should do this? */
607 /* Interrupt 9 should be level triggered (SCI) */
608 i8259_configure_irq_trigger(9, 1);
609
610 pch_disable_smm_only_flashing(dev);
611
Vladimir Serbinenkoa3e41c02015-05-28 16:04:17 +0200612 pch_set_acpi_mode();
Stefan Reinauer8e073822012-04-04 00:07:22 +0200613
614 pch_fixups(dev);
Nico Huber7b2f9f62015-10-01 19:00:51 +0200615
616 pch_spi_init(dev);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200617}
618
Elyes HAOUAS4aec3402018-05-25 08:29:27 +0200619static void pch_lpc_read_resources(struct device *dev)
Stefan Reinauer8e073822012-04-04 00:07:22 +0200620{
621 struct resource *res;
Marc Jonesa0bec172012-07-13 14:14:34 -0600622 config_t *config = dev->chip_info;
623 u8 io_index = 0;
Stefan Reinauer8e073822012-04-04 00:07:22 +0200624
625 /* Get the normal PCI resources of this device. */
626 pci_dev_read_resources(dev);
627
628 /* Add an extra subtractive resource for both memory and I/O. */
Marc Jonesa0bec172012-07-13 14:14:34 -0600629 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
Stefan Reinauer8e073822012-04-04 00:07:22 +0200630 res->base = 0;
631 res->size = 0x1000;
632 res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
633 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
634
Marc Jonesa0bec172012-07-13 14:14:34 -0600635 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
Vladimir Serbinenko0650cd02014-02-05 15:03:50 +0100636 res->base = 0xff000000;
637 /* Some systems (e.g. X230) have 12 MiB flash.
638 SPI controller supports up to 2 x 16 MiB of flash but
639 address map limits this to 16MiB. */
640 res->size = 0x01000000; /* 16 MB for flash */
Stefan Reinauer8e073822012-04-04 00:07:22 +0200641 res->flags = IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE |
642 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
643
644 res = new_resource(dev, 3); /* IOAPIC */
645 res->base = IO_APIC_ADDR;
646 res->size = 0x00001000;
647 res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
Marc Jonesa0bec172012-07-13 14:14:34 -0600648
649 /* Set PCH IO decode ranges if required.*/
650 if ((config->gen1_dec & 0xFFFC) > 0x1000) {
651 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
652 res->base = config->gen1_dec & 0xFFFC;
653 res->size = (config->gen1_dec >> 16) & 0xFC;
654 res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
655 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
656 }
657
658 if ((config->gen2_dec & 0xFFFC) > 0x1000) {
659 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
660 res->base = config->gen2_dec & 0xFFFC;
661 res->size = (config->gen2_dec >> 16) & 0xFC;
662 res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
663 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
664 }
665
666 if ((config->gen3_dec & 0xFFFC) > 0x1000) {
667 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
668 res->base = config->gen3_dec & 0xFFFC;
669 res->size = (config->gen3_dec >> 16) & 0xFC;
670 res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
671 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
672 }
673
674 if ((config->gen4_dec & 0xFFFC) > 0x1000) {
675 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
676 res->base = config->gen4_dec & 0xFFFC;
677 res->size = (config->gen4_dec >> 16) & 0xFC;
678 res->flags = IORESOURCE_IO| IORESOURCE_SUBTRACTIVE |
679 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
680 }
Stefan Reinauer8e073822012-04-04 00:07:22 +0200681}
682
Elyes HAOUAS4aec3402018-05-25 08:29:27 +0200683static void pch_lpc_enable_resources(struct device *dev)
Stefan Reinauer8e073822012-04-04 00:07:22 +0200684{
685 pch_decode_init(dev);
686 return pci_dev_enable_resources(dev);
687}
688
Elyes HAOUAS4aec3402018-05-25 08:29:27 +0200689static void pch_lpc_enable(struct device *dev)
Stefan Reinauer8e073822012-04-04 00:07:22 +0200690{
691 /* Enable PCH Display Port */
692 RCBA16(DISPBDF) = 0x0010;
693 RCBA32_OR(FD2, PCH_ENABLE_DBDF);
694
695 pch_enable(dev);
696}
697
Elyes HAOUAS4aec3402018-05-25 08:29:27 +0200698static void southbridge_inject_dsdt(struct device *dev)
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +0200699{
Elyes HAOUAS035df002016-10-03 21:54:16 +0200700 global_nvs_t *gnvs = cbmem_add (CBMEM_ID_ACPI_GNVS, sizeof(*gnvs));
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +0200701
702 if (gnvs) {
Vladimir Serbinenkodd2bc3f2014-10-31 09:16:31 +0100703 const struct i915_gpu_controller_info *gfx = intel_gma_get_controller_info();
Elyes HAOUAS035df002016-10-03 21:54:16 +0200704 memset(gnvs, 0, sizeof(*gnvs));
Vladimir Serbinenko7309c642014-10-05 11:07:33 +0200705
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +0200706 acpi_create_gnvs(gnvs);
Vladimir Serbinenko06c788d2014-10-12 00:17:11 +0200707
708 gnvs->apic = 1;
709 gnvs->mpen = 1; /* Enable Multi Processing */
710 gnvs->pcnt = dev_count_cpu();
711
Nico Huber744d6bd2019-01-12 14:58:20 +0100712 if (gfx) {
713 gnvs->ndid = gfx->ndid;
714 memcpy(gnvs->did, gfx->did, sizeof(gnvs->did));
715 }
Vladimir Serbinenkodd2bc3f2014-10-31 09:16:31 +0100716
Julius Wernercd49cce2019-03-05 16:53:33 -0800717#if CONFIG(CHROMEOS)
Joel Kitching6fbd8742018-08-23 14:56:25 +0800718 chromeos_init_chromeos_acpi(&(gnvs->chromeos));
Vladimir Serbinenko06c788d2014-10-12 00:17:11 +0200719#endif
720
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +0200721 /* And tell SMI about it */
722 smm_setup_structures(gnvs, NULL, NULL);
723
Vladimir Serbinenko334fd8e2014-10-05 11:10:35 +0200724 /* Add it to DSDT. */
Vladimir Serbinenko226d7842014-11-04 21:09:23 +0100725 acpigen_write_scope("\\");
726 acpigen_write_name_dword("NVSA", (u32) gnvs);
727 acpigen_pop_len();
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +0200728 }
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +0200729}
730
Vladimir Serbinenko5b044ae2014-10-25 15:20:55 +0200731void acpi_fill_fadt(acpi_fadt_t *fadt)
732{
Kyösti Mälkkic70eed12018-05-22 02:18:00 +0300733 struct device *dev = pcidev_on_root(0x1f, 0);
Vladimir Serbinenko5b044ae2014-10-25 15:20:55 +0200734 config_t *chip = dev->chip_info;
735 u16 pmbase = pci_read_config16(dev, 0x40) & 0xfffe;
736 int c2_latency;
737
Elyes HAOUAS0d4de2a2019-02-28 13:04:29 +0100738 fadt->reserved = 0;
Vladimir Serbinenko5b044ae2014-10-25 15:20:55 +0200739
740 fadt->sci_int = 0x9;
741 fadt->smi_cmd = APM_CNT;
742 fadt->acpi_enable = APM_CNT_ACPI_ENABLE;
743 fadt->acpi_disable = APM_CNT_ACPI_DISABLE;
744 fadt->s4bios_req = 0x0;
745 fadt->pstate_cnt = 0;
746
747 fadt->pm1a_evt_blk = pmbase;
748 fadt->pm1b_evt_blk = 0x0;
749 fadt->pm1a_cnt_blk = pmbase + 0x4;
750 fadt->pm1b_cnt_blk = 0x0;
751 fadt->pm2_cnt_blk = pmbase + 0x50;
752 fadt->pm_tmr_blk = pmbase + 0x8;
753 fadt->gpe0_blk = pmbase + 0x20;
754 fadt->gpe1_blk = 0;
755
756 fadt->pm1_evt_len = 4;
757 fadt->pm1_cnt_len = 2;
758 fadt->pm2_cnt_len = 1;
759 fadt->pm_tmr_len = 4;
760 fadt->gpe0_blk_len = 16;
761 fadt->gpe1_blk_len = 0;
762 fadt->gpe1_base = 0;
763 fadt->cst_cnt = 0;
764 c2_latency = chip->c2_latency;
765 if (!c2_latency) {
766 c2_latency = 101; /* c2 unsupported */
767 }
768 fadt->p_lvl2_lat = c2_latency;
769 fadt->p_lvl3_lat = 87;
770 fadt->flush_size = 1024;
771 fadt->flush_stride = 16;
Patrick Rudolphb30a47b2019-07-15 18:04:23 +0200772 /* P_CNT not supported */
773 fadt->duty_offset = 0;
774 fadt->duty_width = 0;
775
Vladimir Serbinenko5b044ae2014-10-25 15:20:55 +0200776 fadt->day_alrm = 0xd;
777 fadt->mon_alrm = 0x00;
778 fadt->century = 0x00;
779 fadt->iapc_boot_arch = ACPI_FADT_LEGACY_DEVICES | ACPI_FADT_8042;
780
781 fadt->flags = ACPI_FADT_WBINVD |
782 ACPI_FADT_C1_SUPPORTED |
783 ACPI_FADT_SLEEP_BUTTON |
784 ACPI_FADT_RESET_REGISTER |
785 ACPI_FADT_SEALED_CASE |
786 ACPI_FADT_S4_RTC_WAKE |
787 ACPI_FADT_PLATFORM_CLOCK;
788 if (chip->docking_supported) {
789 fadt->flags |= ACPI_FADT_DOCKING_SUPPORTED;
790 }
791 if (c2_latency < 100) {
792 fadt->flags |= ACPI_FADT_C2_MP_SUPPORTED;
793 }
794
795 fadt->reset_reg.space_id = 1;
796 fadt->reset_reg.bit_width = 8;
797 fadt->reset_reg.bit_offset = 0;
798 fadt->reset_reg.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
799 fadt->reset_reg.addrl = 0xcf9;
800 fadt->reset_reg.addrh = 0;
801
802 fadt->reset_value = 6;
803
804 fadt->x_pm1a_evt_blk.space_id = 1;
805 fadt->x_pm1a_evt_blk.bit_width = 32;
806 fadt->x_pm1a_evt_blk.bit_offset = 0;
807 fadt->x_pm1a_evt_blk.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
808 fadt->x_pm1a_evt_blk.addrl = pmbase;
809 fadt->x_pm1a_evt_blk.addrh = 0x0;
810
811 fadt->x_pm1b_evt_blk.space_id = 1;
812 fadt->x_pm1b_evt_blk.bit_width = 0;
813 fadt->x_pm1b_evt_blk.bit_offset = 0;
814 fadt->x_pm1b_evt_blk.access_size = 0;
815 fadt->x_pm1b_evt_blk.addrl = 0x0;
816 fadt->x_pm1b_evt_blk.addrh = 0x0;
817
818 fadt->x_pm1a_cnt_blk.space_id = 1;
819 fadt->x_pm1a_cnt_blk.bit_width = 16;
820 fadt->x_pm1a_cnt_blk.bit_offset = 0;
821 fadt->x_pm1a_cnt_blk.access_size = ACPI_ACCESS_SIZE_WORD_ACCESS;
822 fadt->x_pm1a_cnt_blk.addrl = pmbase + 0x4;
823 fadt->x_pm1a_cnt_blk.addrh = 0x0;
824
825 fadt->x_pm1b_cnt_blk.space_id = 1;
826 fadt->x_pm1b_cnt_blk.bit_width = 0;
827 fadt->x_pm1b_cnt_blk.bit_offset = 0;
828 fadt->x_pm1b_cnt_blk.access_size = 0;
829 fadt->x_pm1b_cnt_blk.addrl = 0x0;
830 fadt->x_pm1b_cnt_blk.addrh = 0x0;
831
832 fadt->x_pm2_cnt_blk.space_id = 1;
833 fadt->x_pm2_cnt_blk.bit_width = 8;
834 fadt->x_pm2_cnt_blk.bit_offset = 0;
835 fadt->x_pm2_cnt_blk.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
836 fadt->x_pm2_cnt_blk.addrl = pmbase + 0x50;
837 fadt->x_pm2_cnt_blk.addrh = 0x0;
838
839 fadt->x_pm_tmr_blk.space_id = 1;
840 fadt->x_pm_tmr_blk.bit_width = 32;
841 fadt->x_pm_tmr_blk.bit_offset = 0;
842 fadt->x_pm_tmr_blk.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
843 fadt->x_pm_tmr_blk.addrl = pmbase + 0x8;
844 fadt->x_pm_tmr_blk.addrh = 0x0;
845
846 fadt->x_gpe0_blk.space_id = 1;
847 fadt->x_gpe0_blk.bit_width = 128;
848 fadt->x_gpe0_blk.bit_offset = 0;
849 fadt->x_gpe0_blk.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
850 fadt->x_gpe0_blk.addrl = pmbase + 0x20;
851 fadt->x_gpe0_blk.addrh = 0x0;
852
853 fadt->x_gpe1_blk.space_id = 1;
854 fadt->x_gpe1_blk.bit_width = 0;
855 fadt->x_gpe1_blk.bit_offset = 0;
856 fadt->x_gpe1_blk.access_size = 0;
857 fadt->x_gpe1_blk.addrl = 0x0;
858 fadt->x_gpe1_blk.addrh = 0x0;
859}
860
Aaron Durbinaa090cb2017-09-13 16:01:52 -0600861static const char *lpc_acpi_name(const struct device *dev)
Patrick Rudolph604f6982017-06-07 09:46:52 +0200862{
863 return "LPCB";
864}
865
Elyes HAOUAS4aec3402018-05-25 08:29:27 +0200866static void southbridge_fill_ssdt(struct device *device)
Vladimir Serbinenko36fa5b82014-10-28 23:43:20 +0100867{
Kyösti Mälkkic70eed12018-05-22 02:18:00 +0300868 struct device *dev = pcidev_on_root(0x1f, 0);
Vladimir Serbinenko36fa5b82014-10-28 23:43:20 +0100869 config_t *chip = dev->chip_info;
870
871 intel_acpi_pcie_hotplug_generator(chip->pcie_hotplug_map, 8);
Tobias Diedrich7f5efd92017-12-14 00:29:01 +0100872 intel_acpi_gen_def_acpi_pirq(dev);
Vladimir Serbinenko36fa5b82014-10-28 23:43:20 +0100873}
874
Vladimir Serbinenkob06a2492015-05-21 10:32:59 +0200875static void lpc_final(struct device *dev)
876{
Nico Huber8e50b6d2018-02-04 15:52:18 +0100877 u16 spi_opprefix = SPI_OPPREFIX;
878 u16 spi_optype = SPI_OPTYPE;
879 u32 spi_opmenu[2] = { SPI_OPMENU_LOWER, SPI_OPMENU_UPPER };
880
881 /* Configure SPI opcode menu; devicetree may override defaults. */
882 const config_t *const config = dev->chip_info;
883 if (config && config->spi.ops[0].op) {
884 unsigned int i;
885
886 spi_opprefix = 0;
887 spi_optype = 0;
888 spi_opmenu[0] = 0;
889 spi_opmenu[1] = 0;
890 for (i = 0; i < sizeof(spi_opprefix); ++i)
891 spi_opprefix |= config->spi.opprefixes[i] << i * 8;
892 for (i = 0; i < sizeof(spi_opmenu); ++i) {
893 spi_optype |=
894 config->spi.ops[i].is_write << 2 * i |
895 config->spi.ops[i].needs_address << (2 * i + 1);
896 spi_opmenu[i / 4] |=
897 config->spi.ops[i].op << (i % 4) * 8;
898 }
899 }
900 RCBA16(0x3894) = spi_opprefix;
901 RCBA16(0x3896) = spi_optype;
902 RCBA32(0x3898) = spi_opmenu[0];
903 RCBA32(0x389c) = spi_opmenu[1];
904
Bill XIEd533b162017-08-22 16:26:22 +0800905 /* Call SMM finalize() handlers before resume */
Julius Wernercd49cce2019-03-05 16:53:33 -0800906 if (CONFIG(HAVE_SMI_HANDLER)) {
907 if (CONFIG(INTEL_CHIPSET_LOCKDOWN) ||
Bill XIEd533b162017-08-22 16:26:22 +0800908 acpi_is_wakeup_s3()) {
909 outb(APM_CNT_FINALIZE, APM_CNT);
910 }
Vladimir Serbinenkob06a2492015-05-21 10:32:59 +0200911 }
912}
913
Stefan Reinauer8e073822012-04-04 00:07:22 +0200914static struct pci_operations pci_ops = {
Subrata Banik4a0f0712019-03-20 14:29:47 +0530915 .set_subsystem = pci_dev_set_subsystem,
Stefan Reinauer8e073822012-04-04 00:07:22 +0200916};
917
918static struct device_operations device_ops = {
919 .read_resources = pch_lpc_read_resources,
920 .set_resources = pci_dev_set_resources,
921 .enable_resources = pch_lpc_enable_resources,
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +0200922 .write_acpi_tables = acpi_write_hpet,
Vladimir Serbinenko334fd8e2014-10-05 11:10:35 +0200923 .acpi_inject_dsdt_generator = southbridge_inject_dsdt,
Vladimir Serbinenko36fa5b82014-10-28 23:43:20 +0100924 .acpi_fill_ssdt_generator = southbridge_fill_ssdt,
Patrick Rudolph604f6982017-06-07 09:46:52 +0200925 .acpi_name = lpc_acpi_name,
Stefan Reinauer8e073822012-04-04 00:07:22 +0200926 .init = lpc_init,
Vladimir Serbinenkob06a2492015-05-21 10:32:59 +0200927 .final = lpc_final,
Stefan Reinauer8e073822012-04-04 00:07:22 +0200928 .enable = pch_lpc_enable,
Kyösti Mälkkid0e212c2015-02-26 20:47:47 +0200929 .scan_bus = scan_lpc_bus,
Stefan Reinauer8e073822012-04-04 00:07:22 +0200930 .ops_pci = &pci_ops,
931};
932
933
Kimarie Hoote6f459c2012-07-14 08:26:08 -0600934/* IDs for LPC device of Intel 6 Series Chipset, Intel 7 Series Chipset, and
935 * Intel C200 Series Chipset
Stefan Reinauer8e073822012-04-04 00:07:22 +0200936 */
937
Vladimir Serbinenko42d55e02016-01-02 01:47:26 +0100938static const unsigned short pci_device_ids[] = {
939 0x1c40, 0x1c41, 0x1c42, 0x1c43, 0x1c44, 0x1c45, 0x1c46, 0x1c47, 0x1c48,
940 0x1c49, 0x1c4a, 0x1c4b, 0x1c4c, 0x1c4d, 0x1c4e, 0x1c4f, 0x1c50, 0x1c51,
941 0x1c52, 0x1c53, 0x1c54, 0x1c55, 0x1c56, 0x1c57, 0x1c58, 0x1c59, 0x1c5a,
942 0x1c5b, 0x1c5c, 0x1c5d, 0x1c5e, 0x1c5f,
943
944 0x1e41, 0x1e42, 0x1e43, 0x1e44, 0x1e45, 0x1e46, 0x1e47, 0x1e48, 0x1e49,
945 0x1e4a, 0x1e4b, 0x1e4c, 0x1e4d, 0x1e4e, 0x1e4f, 0x1e50, 0x1e51, 0x1e52,
946 0x1e53, 0x1e54, 0x1e55, 0x1e56, 0x1e57, 0x1e58, 0x1e59, 0x1e5a, 0x1e5b,
947 0x1e5c, 0x1e5d, 0x1e5e, 0x1e5f,
948
949 0 };
Stefan Reinauer9a380ab2012-06-22 13:16:11 -0700950
951static const struct pci_driver pch_lpc __pci_driver = {
952 .ops = &device_ops,
953 .vendor = PCI_VENDOR_ID_INTEL,
954 .devices = pci_device_ids,
Stefan Reinauer8e073822012-04-04 00:07:22 +0200955};