blob: 271b5b06cc679944c828a3e90bbb94e4b93f4459 [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>
29#include <cpu/cpu.h>
Duncan Laurie800e9502012-06-23 17:06:47 -070030#include <elog.h>
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +020031#include <arch/acpigen.h>
32#include <drivers/intel/gma/i915.h>
Vladimir Serbinenko5b044ae2014-10-25 15:20:55 +020033#include <cpu/x86/smm.h>
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +020034#include <cbmem.h>
Vladimir Serbinenko7309c642014-10-05 11:07:33 +020035#include <string.h>
Vladimir Serbinenko5b044ae2014-10-25 15:20:55 +020036#include <cpu/x86/smm.h>
Stefan Reinauer8e073822012-04-04 00:07:22 +020037#include "pch.h"
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +020038#include "nvs.h"
Vladimir Serbinenko36fa5b82014-10-28 23:43:20 +010039#include <southbridge/intel/common/pciehp.h>
Tobias Diedrich7f5efd92017-12-14 00:29:01 +010040#include <southbridge/intel/common/acpi_pirq_gen.h>
Arthur Heymansa0508172018-01-25 11:30:22 +010041#include <southbridge/intel/common/pmutil.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));
Martin Roth7a1a3ad2017-06-24 21:29:38 -060083#if !IS_ENABLED(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
185 int pwr_on=CONFIG_MAINBOARD_POWER_ON_AFTER_POWER_FAIL;
186 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 */
273 reg32 = RCBA32(0x3310);
274 reg32 |= (1 << 4)|(1 << 5)|(1 << 0);
275 RCBA32(0x3310) = reg32;
276
277 reg32 = RCBA32(0x3f02);
278 reg32 &= ~0xf;
279 RCBA32(0x3f02) = reg32;
280}
281
282static void pch_rtc_init(struct device *dev)
283{
Aaron Durbin976200382017-09-15 15:19:32 -0600284 int rtc_failed = rtc_failure();
Stefan Reinauer8e073822012-04-04 00:07:22 +0200285
Stefan Reinauer8e073822012-04-04 00:07:22 +0200286 if (rtc_failed) {
Aaron Durbin976200382017-09-15 15:19:32 -0600287 if (IS_ENABLED(CONFIG_ELOG))
288 elog_add_event(ELOG_TYPE_RTC_RESET);
289 pci_update_config8(dev, GEN_PMCON_3, ~RTC_BATTERY_DEAD, 0);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200290 }
Aaron Durbin976200382017-09-15 15:19:32 -0600291
Stefan Reinauer8e073822012-04-04 00:07:22 +0200292 printk(BIOS_DEBUG, "rtc_failed = 0x%x\n", rtc_failed);
293
Gabe Blackb3f08c62014-04-30 17:12:25 -0700294 cmos_init(rtc_failed);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200295}
296
Duncan Laurie3f6a4d72012-06-28 13:03:40 -0700297/* CougarPoint PCH Power Management init */
298static void cpt_pm_init(struct device *dev)
Stefan Reinauer8e073822012-04-04 00:07:22 +0200299{
Duncan Laurie3f6a4d72012-06-28 13:03:40 -0700300 printk(BIOS_DEBUG, "CougarPoint PM init\n");
Stefan Reinauer8e073822012-04-04 00:07:22 +0200301 pci_write_config8(dev, 0xa9, 0x47);
302 RCBA32_AND_OR(0x2238, ~0UL, (1 << 6)|(1 << 0));
303 RCBA32_AND_OR(0x228c, ~0UL, (1 << 0));
304 RCBA16_AND_OR(0x1100, ~0UL, (1 << 13)|(1 << 14));
305 RCBA16_AND_OR(0x0900, ~0UL, (1 << 14));
306 RCBA32(0x2304) = 0xc0388400;
307 RCBA32_AND_OR(0x2314, ~0UL, (1 << 5)|(1 << 18));
308 RCBA32_AND_OR(0x2320, ~0UL, (1 << 15)|(1 << 1));
309 RCBA32_AND_OR(0x3314, ~0x1f, 0xf);
310 RCBA32(0x3318) = 0x050f0000;
311 RCBA32(0x3324) = 0x04000000;
312 RCBA32_AND_OR(0x3340, ~0UL, 0xfffff);
313 RCBA32_AND_OR(0x3344, ~0UL, (1 << 1));
314 RCBA32(0x3360) = 0x0001c000;
315 RCBA32(0x3368) = 0x00061100;
316 RCBA32(0x3378) = 0x7f8fdfff;
317 RCBA32(0x337c) = 0x000003fc;
318 RCBA32(0x3388) = 0x00001000;
319 RCBA32(0x3390) = 0x0001c000;
320 RCBA32(0x33a0) = 0x00000800;
321 RCBA32(0x33b0) = 0x00001000;
322 RCBA32(0x33c0) = 0x00093900;
323 RCBA32(0x33cc) = 0x24653002;
324 RCBA32(0x33d0) = 0x062108fe;
325 RCBA32_AND_OR(0x33d4, 0xf000f000, 0x00670060);
326 RCBA32(0x3a28) = 0x01010000;
327 RCBA32(0x3a2c) = 0x01010404;
328 RCBA32(0x3a80) = 0x01041041;
329 RCBA32_AND_OR(0x3a84, ~0x0000ffff, 0x00001001);
330 RCBA32_AND_OR(0x3a84, ~0UL, (1 << 24)); /* SATA 2/3 disabled */
331 RCBA32_AND_OR(0x3a88, ~0UL, (1 << 0)); /* SATA 4/5 disabled */
332 RCBA32(0x3a6c) = 0x00000001;
333 RCBA32_AND_OR(0x2344, 0x00ffff00, 0xff00000c);
334 RCBA32_AND_OR(0x80c, ~(0xff << 20), 0x11 << 20);
335 RCBA32(0x33c8) = 0;
336 RCBA32_AND_OR(0x21b0, ~0UL, 0xf);
337}
338
Duncan Laurie3f6a4d72012-06-28 13:03:40 -0700339/* PantherPoint PCH Power Management init */
340static void ppt_pm_init(struct device *dev)
341{
342 printk(BIOS_DEBUG, "PantherPoint PM init\n");
343 pci_write_config8(dev, 0xa9, 0x47);
344 RCBA32_AND_OR(0x2238, ~0UL, (1 << 0));
345 RCBA32_AND_OR(0x228c, ~0UL, (1 << 0));
346 RCBA16_AND_OR(0x1100, ~0UL, (1 << 13)|(1 << 14));
347 RCBA16_AND_OR(0x0900, ~0UL, (1 << 14));
348 RCBA32(0x2304) = 0xc03b8400;
349 RCBA32_AND_OR(0x2314, ~0UL, (1 << 5)|(1 << 18));
350 RCBA32_AND_OR(0x2320, ~0UL, (1 << 15)|(1 << 1));
351 RCBA32_AND_OR(0x3314, ~0x1f, 0xf);
352 RCBA32(0x3318) = 0x054f0000;
353 RCBA32(0x3324) = 0x04000000;
354 RCBA32_AND_OR(0x3340, ~0UL, 0xfffff);
355 RCBA32_AND_OR(0x3344, ~0UL, (1 << 1)|(1 << 0));
356 RCBA32(0x3360) = 0x0001c000;
357 RCBA32(0x3368) = 0x00061100;
358 RCBA32(0x3378) = 0x7f8fdfff;
359 RCBA32(0x337c) = 0x000003fd;
360 RCBA32(0x3388) = 0x00001000;
361 RCBA32(0x3390) = 0x0001c000;
362 RCBA32(0x33a0) = 0x00000800;
363 RCBA32(0x33b0) = 0x00001000;
364 RCBA32(0x33c0) = 0x00093900;
365 RCBA32(0x33cc) = 0x24653002;
366 RCBA32(0x33d0) = 0x067388fe;
367 RCBA32_AND_OR(0x33d4, 0xf000f000, 0x00670060);
368 RCBA32(0x3a28) = 0x01010000;
369 RCBA32(0x3a2c) = 0x01010404;
370 RCBA32(0x3a80) = 0x01040000;
371 RCBA32_AND_OR(0x3a84, ~0x0000ffff, 0x00001001);
372 RCBA32_AND_OR(0x3a84, ~0UL, (1 << 24)); /* SATA 2/3 disabled */
373 RCBA32_AND_OR(0x3a88, ~0UL, (1 << 0)); /* SATA 4/5 disabled */
374 RCBA32(0x3a6c) = 0x00000001;
375 RCBA32_AND_OR(0x2344, 0x00ffff00, 0xff00000c);
376 RCBA32_AND_OR(0x80c, ~(0xff << 20), 0x11 << 20);
377 RCBA32_AND_OR(0x33a4, ~0UL, (1 << 0));
378 RCBA32(0x33c8) = 0;
379 RCBA32_AND_OR(0x21b0, ~0UL, 0xf);
380}
381
Nico Huberb2dae792015-10-26 12:34:02 +0100382static void enable_hpet(struct device *const dev)
Stefan Reinauer8e073822012-04-04 00:07:22 +0200383{
384 u32 reg32;
Nico Huberb2dae792015-10-26 12:34:02 +0100385 size_t i;
386
387 /* Assign unique bus/dev/fn for each HPET */
388 for (i = 0; i < 8; ++i)
389 pci_write_config16(dev, LPC_HnBDF(i),
390 PCH_HPET_PCI_BUS << 8 | PCH_HPET_PCI_SLOT << 3 | i);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200391
392 /* Move HPET to default address 0xfed00000 and enable it */
393 reg32 = RCBA32(HPTC);
394 reg32 |= (1 << 7); // HPET Address Enable
395 reg32 &= ~(3 << 0);
396 RCBA32(HPTC) = reg32;
397}
398
Elyes HAOUAS4aec3402018-05-25 08:29:27 +0200399static void enable_clock_gating(struct device *dev)
Stefan Reinauer8e073822012-04-04 00:07:22 +0200400{
401 u32 reg32;
402 u16 reg16;
403
404 RCBA32_AND_OR(0x2234, ~0UL, 0xf);
405
406 reg16 = pci_read_config16(dev, GEN_PMCON_1);
407 reg16 |= (1 << 2) | (1 << 11);
408 pci_write_config16(dev, GEN_PMCON_1, reg16);
409
410 pch_iobp_update(0xEB007F07, ~0UL, (1 << 31));
411 pch_iobp_update(0xEB004000, ~0UL, (1 << 7));
412 pch_iobp_update(0xEC007F07, ~0UL, (1 << 31));
413 pch_iobp_update(0xEC004000, ~0UL, (1 << 7));
414
415 reg32 = RCBA32(CG);
416 reg32 |= (1 << 31);
417 reg32 |= (1 << 29) | (1 << 28);
418 reg32 |= (1 << 27) | (1 << 26) | (1 << 25) | (1 << 24);
419 reg32 |= (1 << 16);
420 reg32 |= (1 << 17);
421 reg32 |= (1 << 18);
422 reg32 |= (1 << 22);
423 reg32 |= (1 << 23);
424 reg32 &= ~(1 << 20);
425 reg32 |= (1 << 19);
426 reg32 |= (1 << 0);
427 reg32 |= (0xf << 1);
428 RCBA32(CG) = reg32;
429
430 RCBA32_OR(0x38c0, 0x7);
431 RCBA32_OR(0x36d4, 0x6680c004);
432 RCBA32_OR(0x3564, 0x3);
433}
434
Vladimir Serbinenkoa3e41c02015-05-28 16:04:17 +0200435static void pch_set_acpi_mode(void)
Stefan Reinauer8e073822012-04-04 00:07:22 +0200436{
Vladimir Serbinenkoa3e41c02015-05-28 16:04:17 +0200437 if (!acpi_is_wakeup_s3() && CONFIG_HAVE_SMI_HANDLER) {
Stefan Reinauer8e073822012-04-04 00:07:22 +0200438#if ENABLE_ACPI_MODE_IN_COREBOOT
Duncan Laurie95be1d62012-04-09 12:31:43 -0700439 printk(BIOS_DEBUG, "Enabling ACPI via APMC:\n");
Vladimir Serbinenkoa3e41c02015-05-28 16:04:17 +0200440 outb(APM_CNT_ACPI_ENABLE, APM_CNT); // Enable ACPI mode
Duncan Laurie95be1d62012-04-09 12:31:43 -0700441 printk(BIOS_DEBUG, "done.\n");
Stefan Reinauer8e073822012-04-04 00:07:22 +0200442#else
Duncan Laurie95be1d62012-04-09 12:31:43 -0700443 printk(BIOS_DEBUG, "Disabling ACPI via APMC:\n");
Vladimir Serbinenkoa3e41c02015-05-28 16:04:17 +0200444 outb(APM_CNT_ACPI_DISABLE, APM_CNT); // Disable ACPI mode
Duncan Laurie95be1d62012-04-09 12:31:43 -0700445 printk(BIOS_DEBUG, "done.\n");
Stefan Reinauer8e073822012-04-04 00:07:22 +0200446#endif
Duncan Laurie95be1d62012-04-09 12:31:43 -0700447 }
Stefan Reinauer8e073822012-04-04 00:07:22 +0200448}
Stefan Reinauer8e073822012-04-04 00:07:22 +0200449
450static void pch_disable_smm_only_flashing(struct device *dev)
451{
452 u8 reg8;
453
454 printk(BIOS_SPEW, "Enabling BIOS updates outside of SMM... ");
455 reg8 = pci_read_config8(dev, 0xdc); /* BIOS_CNTL */
456 reg8 &= ~(1 << 5);
457 pci_write_config8(dev, 0xdc, reg8);
458}
459
460static void pch_fixups(struct device *dev)
461{
462 u8 gen_pmcon_2;
463
464 /* Indicate DRAM init done for MRC S3 to know it can resume */
465 gen_pmcon_2 = pci_read_config8(dev, GEN_PMCON_2);
466 gen_pmcon_2 |= (1 << 7);
467 pci_write_config8(dev, GEN_PMCON_2, gen_pmcon_2);
468
469 /*
470 * Enable DMI ASPM in the PCH
471 */
472 RCBA32_AND_OR(0x2304, ~(1 << 10), 0);
473 RCBA32_OR(0x21a4, (1 << 11)|(1 << 10));
474 RCBA32_OR(0x21a8, 0x3);
475}
476
477static void pch_decode_init(struct device *dev)
478{
479 config_t *config = dev->chip_info;
480
481 printk(BIOS_DEBUG, "pch_decode_init\n");
482
483 pci_write_config32(dev, LPC_GEN1_DEC, config->gen1_dec);
484 pci_write_config32(dev, LPC_GEN2_DEC, config->gen2_dec);
485 pci_write_config32(dev, LPC_GEN3_DEC, config->gen3_dec);
486 pci_write_config32(dev, LPC_GEN4_DEC, config->gen4_dec);
487}
488
Nico Huber7b2f9f62015-10-01 19:00:51 +0200489static void pch_spi_init(const struct device *const dev)
490{
491 const config_t *const config = dev->chip_info;
492
493 printk(BIOS_DEBUG, "pch_spi_init\n");
494
495 if (config->spi_uvscc)
496 RCBA32(0x3800 + 0xc8) = config->spi_uvscc;
497 if (config->spi_lvscc)
498 RCBA32(0x3800 + 0xc4) = config->spi_lvscc;
499
500 if (config->spi_uvscc || config->spi_lvscc)
501 RCBA32_OR(0x3800 + 0xc4, 1 << 23); /* lock both UVSCC + LVSCC */
502}
503
Patrick Rudolphef8c5592018-07-27 17:48:27 +0200504static const struct {
505 u16 dev_id;
506 const char *dev_name;
507} pch_table[] = {
508 /* 6-series PCI ids from
509 * Intel® 6 Series Chipset and
510 * Intel® C200 Series Chipset
511 * Specification Update - NDA
512 * October 2013
513 * CDI / IBP#: 440377
514 */
515 {0x1C41, "SFF Sample"},
516 {0x1C42, "Desktop Sample"},
517 {0x1C43, "Mobile Sample"},
518 {0x1C44, "Z68"},
519 {0x1C46, "P67"},
520 {0x1C47, "UM67"},
521 {0x1C49, "HM65"},
522 {0x1C4A, "H67"},
523 {0x1C4B, "HM67"},
524 {0x1C4C, "Q65"},
525 {0x1C4D, "QS67"},
526 {0x1C4E, "Q67"},
527 {0x1C4F, "QM67"},
528 {0x1C50, "B65"},
529 {0x1C52, "C202"},
530 {0x1C54, "C204"},
531 {0x1C56, "C206"},
532 {0x1C5C, "H61"},
533 /* 7-series PCI ids from Intel document 472178 */
534 {0x1E41, "Desktop Sample"},
535 {0x1E42, "Mobile Sample"},
536 {0x1E43, "SFF Sample"},
537 {0x1E44, "Z77"},
538 {0x1E45, "H71"},
539 {0x1E46, "Z75"},
540 {0x1E47, "Q77"},
541 {0x1E48, "Q75"},
542 {0x1E49, "B75"},
543 {0x1E4A, "H77"},
544 {0x1E53, "C216"},
545 {0x1E55, "QM77"},
546 {0x1E56, "QS77"},
547 {0x1E58, "UM77"},
548 {0x1E57, "HM77"},
549 {0x1E59, "HM76"},
550 {0x1E5D, "HM75"},
551 {0x1E5E, "HM70"},
552 {0x1E5F, "NM70"},
553};
554
555static void report_pch_info(struct device *dev)
556{
557 const u16 dev_id = pci_read_config16(dev, PCI_DEVICE_ID);
558 int i;
559
560 const char *pch_type = "Unknown";
561 for (i = 0; i < ARRAY_SIZE(pch_table); i++) {
562 if (pch_table[i].dev_id == dev_id) {
563 pch_type = pch_table[i].dev_name;
564 break;
565 }
566 }
567 printk(BIOS_INFO, "PCH: detected %s, device id: 0x%x, rev id 0x%x\n",
568 pch_type, dev_id, pci_read_config8(dev, PCI_CLASS_REVISION));
569}
570
Stefan Reinauer8e073822012-04-04 00:07:22 +0200571static void lpc_init(struct device *dev)
572{
573 printk(BIOS_DEBUG, "pch: lpc_init\n");
574
Patrick Rudolphef8c5592018-07-27 17:48:27 +0200575 /* Print detected platform */
576 report_pch_info(dev);
577
Stefan Reinauer8e073822012-04-04 00:07:22 +0200578 /* Set the value for PCI command register. */
579 pci_write_config16(dev, PCI_COMMAND, 0x000f);
580
581 /* IO APIC initialization. */
Paul Menzel9c50e6a2013-05-03 12:23:39 +0200582 pch_enable_ioapic(dev);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200583
584 pch_enable_serial_irqs(dev);
585
586 /* Setup the PIRQ. */
587 pch_pirq_init(dev);
588
589 /* Setup power options. */
590 pch_power_options(dev);
591
592 /* Initialize power management */
Duncan Laurie3f6a4d72012-06-28 13:03:40 -0700593 switch (pch_silicon_type()) {
594 case PCH_TYPE_CPT: /* CougarPoint */
595 cpt_pm_init(dev);
596 break;
597 case PCH_TYPE_PPT: /* PantherPoint */
598 ppt_pm_init(dev);
599 break;
600 default:
601 printk(BIOS_ERR, "Unknown Chipset: 0x%04x\n", dev->device);
602 }
Stefan Reinauer8e073822012-04-04 00:07:22 +0200603
604 /* Set the state of the GPIO lines. */
605 //gpio_init(dev);
606
607 /* Initialize the real time clock. */
608 pch_rtc_init(dev);
609
610 /* Initialize ISA DMA. */
611 isa_dma_init();
612
613 /* Initialize the High Precision Event Timers, if present. */
Nico Huberb2dae792015-10-26 12:34:02 +0100614 enable_hpet(dev);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200615
616 /* Initialize Clock Gating */
617 enable_clock_gating(dev);
618
619 setup_i8259();
620
621 /* The OS should do this? */
622 /* Interrupt 9 should be level triggered (SCI) */
623 i8259_configure_irq_trigger(9, 1);
624
625 pch_disable_smm_only_flashing(dev);
626
Vladimir Serbinenkoa3e41c02015-05-28 16:04:17 +0200627 pch_set_acpi_mode();
Stefan Reinauer8e073822012-04-04 00:07:22 +0200628
629 pch_fixups(dev);
Nico Huber7b2f9f62015-10-01 19:00:51 +0200630
631 pch_spi_init(dev);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200632}
633
Elyes HAOUAS4aec3402018-05-25 08:29:27 +0200634static void pch_lpc_read_resources(struct device *dev)
Stefan Reinauer8e073822012-04-04 00:07:22 +0200635{
636 struct resource *res;
Marc Jonesa0bec172012-07-13 14:14:34 -0600637 config_t *config = dev->chip_info;
638 u8 io_index = 0;
Stefan Reinauer8e073822012-04-04 00:07:22 +0200639
640 /* Get the normal PCI resources of this device. */
641 pci_dev_read_resources(dev);
642
643 /* Add an extra subtractive resource for both memory and I/O. */
Marc Jonesa0bec172012-07-13 14:14:34 -0600644 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
Stefan Reinauer8e073822012-04-04 00:07:22 +0200645 res->base = 0;
646 res->size = 0x1000;
647 res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
648 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
649
Marc Jonesa0bec172012-07-13 14:14:34 -0600650 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
Vladimir Serbinenko0650cd02014-02-05 15:03:50 +0100651 res->base = 0xff000000;
652 /* Some systems (e.g. X230) have 12 MiB flash.
653 SPI controller supports up to 2 x 16 MiB of flash but
654 address map limits this to 16MiB. */
655 res->size = 0x01000000; /* 16 MB for flash */
Stefan Reinauer8e073822012-04-04 00:07:22 +0200656 res->flags = IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE |
657 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
658
659 res = new_resource(dev, 3); /* IOAPIC */
660 res->base = IO_APIC_ADDR;
661 res->size = 0x00001000;
662 res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
Marc Jonesa0bec172012-07-13 14:14:34 -0600663
664 /* Set PCH IO decode ranges if required.*/
665 if ((config->gen1_dec & 0xFFFC) > 0x1000) {
666 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
667 res->base = config->gen1_dec & 0xFFFC;
668 res->size = (config->gen1_dec >> 16) & 0xFC;
669 res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
670 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
671 }
672
673 if ((config->gen2_dec & 0xFFFC) > 0x1000) {
674 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
675 res->base = config->gen2_dec & 0xFFFC;
676 res->size = (config->gen2_dec >> 16) & 0xFC;
677 res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
678 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
679 }
680
681 if ((config->gen3_dec & 0xFFFC) > 0x1000) {
682 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
683 res->base = config->gen3_dec & 0xFFFC;
684 res->size = (config->gen3_dec >> 16) & 0xFC;
685 res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
686 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
687 }
688
689 if ((config->gen4_dec & 0xFFFC) > 0x1000) {
690 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
691 res->base = config->gen4_dec & 0xFFFC;
692 res->size = (config->gen4_dec >> 16) & 0xFC;
693 res->flags = IORESOURCE_IO| IORESOURCE_SUBTRACTIVE |
694 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
695 }
Stefan Reinauer8e073822012-04-04 00:07:22 +0200696}
697
Elyes HAOUAS4aec3402018-05-25 08:29:27 +0200698static void pch_lpc_enable_resources(struct device *dev)
Stefan Reinauer8e073822012-04-04 00:07:22 +0200699{
700 pch_decode_init(dev);
701 return pci_dev_enable_resources(dev);
702}
703
Elyes HAOUAS4aec3402018-05-25 08:29:27 +0200704static void pch_lpc_enable(struct device *dev)
Stefan Reinauer8e073822012-04-04 00:07:22 +0200705{
706 /* Enable PCH Display Port */
707 RCBA16(DISPBDF) = 0x0010;
708 RCBA32_OR(FD2, PCH_ENABLE_DBDF);
709
710 pch_enable(dev);
711}
712
Elyes HAOUAS4aec3402018-05-25 08:29:27 +0200713static void set_subsystem(struct device *dev, unsigned vendor, unsigned device)
Stefan Reinauer8e073822012-04-04 00:07:22 +0200714{
715 if (!vendor || !device) {
716 pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
717 pci_read_config32(dev, PCI_VENDOR_ID));
718 } else {
719 pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
720 ((device & 0xffff) << 16) | (vendor & 0xffff));
721 }
722}
723
Elyes HAOUAS4aec3402018-05-25 08:29:27 +0200724static void southbridge_inject_dsdt(struct device *dev)
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +0200725{
Elyes HAOUAS035df002016-10-03 21:54:16 +0200726 global_nvs_t *gnvs = cbmem_add (CBMEM_ID_ACPI_GNVS, sizeof(*gnvs));
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +0200727
728 if (gnvs) {
Vladimir Serbinenkodd2bc3f2014-10-31 09:16:31 +0100729 const struct i915_gpu_controller_info *gfx = intel_gma_get_controller_info();
Elyes HAOUAS035df002016-10-03 21:54:16 +0200730 memset(gnvs, 0, sizeof(*gnvs));
Vladimir Serbinenko7309c642014-10-05 11:07:33 +0200731
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +0200732 acpi_create_gnvs(gnvs);
Vladimir Serbinenko06c788d2014-10-12 00:17:11 +0200733
734 gnvs->apic = 1;
735 gnvs->mpen = 1; /* Enable Multi Processing */
736 gnvs->pcnt = dev_count_cpu();
737
Vladimir Serbinenkodd2bc3f2014-10-31 09:16:31 +0100738 gnvs->ndid = gfx->ndid;
739 memcpy(gnvs->did, gfx->did, sizeof(gnvs->did));
740
Martin Roth7a1a3ad2017-06-24 21:29:38 -0600741#if IS_ENABLED(CONFIG_CHROMEOS)
Joel Kitching6fbd8742018-08-23 14:56:25 +0800742 chromeos_init_chromeos_acpi(&(gnvs->chromeos));
Vladimir Serbinenko06c788d2014-10-12 00:17:11 +0200743#endif
744
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +0200745 /* And tell SMI about it */
746 smm_setup_structures(gnvs, NULL, NULL);
747
Vladimir Serbinenko334fd8e2014-10-05 11:10:35 +0200748 /* Add it to DSDT. */
Vladimir Serbinenko226d7842014-11-04 21:09:23 +0100749 acpigen_write_scope("\\");
750 acpigen_write_name_dword("NVSA", (u32) gnvs);
751 acpigen_pop_len();
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +0200752 }
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +0200753}
754
Vladimir Serbinenko5b044ae2014-10-25 15:20:55 +0200755void acpi_fill_fadt(acpi_fadt_t *fadt)
756{
Elyes HAOUAS4aec3402018-05-25 08:29:27 +0200757 struct device *dev = dev_find_slot(0, PCI_DEVFN(0x1f, 0));
Vladimir Serbinenko5b044ae2014-10-25 15:20:55 +0200758 config_t *chip = dev->chip_info;
759 u16 pmbase = pci_read_config16(dev, 0x40) & 0xfffe;
760 int c2_latency;
761
762 fadt->model = 1;
763
764 fadt->sci_int = 0x9;
765 fadt->smi_cmd = APM_CNT;
766 fadt->acpi_enable = APM_CNT_ACPI_ENABLE;
767 fadt->acpi_disable = APM_CNT_ACPI_DISABLE;
768 fadt->s4bios_req = 0x0;
769 fadt->pstate_cnt = 0;
770
771 fadt->pm1a_evt_blk = pmbase;
772 fadt->pm1b_evt_blk = 0x0;
773 fadt->pm1a_cnt_blk = pmbase + 0x4;
774 fadt->pm1b_cnt_blk = 0x0;
775 fadt->pm2_cnt_blk = pmbase + 0x50;
776 fadt->pm_tmr_blk = pmbase + 0x8;
777 fadt->gpe0_blk = pmbase + 0x20;
778 fadt->gpe1_blk = 0;
779
780 fadt->pm1_evt_len = 4;
781 fadt->pm1_cnt_len = 2;
782 fadt->pm2_cnt_len = 1;
783 fadt->pm_tmr_len = 4;
784 fadt->gpe0_blk_len = 16;
785 fadt->gpe1_blk_len = 0;
786 fadt->gpe1_base = 0;
787 fadt->cst_cnt = 0;
788 c2_latency = chip->c2_latency;
789 if (!c2_latency) {
790 c2_latency = 101; /* c2 unsupported */
791 }
792 fadt->p_lvl2_lat = c2_latency;
793 fadt->p_lvl3_lat = 87;
794 fadt->flush_size = 1024;
795 fadt->flush_stride = 16;
796 fadt->duty_offset = 1;
797 if (chip->p_cnt_throttling_supported) {
798 fadt->duty_width = 3;
799 } else {
800 fadt->duty_width = 0;
801 }
802 fadt->day_alrm = 0xd;
803 fadt->mon_alrm = 0x00;
804 fadt->century = 0x00;
805 fadt->iapc_boot_arch = ACPI_FADT_LEGACY_DEVICES | ACPI_FADT_8042;
806
807 fadt->flags = ACPI_FADT_WBINVD |
808 ACPI_FADT_C1_SUPPORTED |
809 ACPI_FADT_SLEEP_BUTTON |
810 ACPI_FADT_RESET_REGISTER |
811 ACPI_FADT_SEALED_CASE |
812 ACPI_FADT_S4_RTC_WAKE |
813 ACPI_FADT_PLATFORM_CLOCK;
814 if (chip->docking_supported) {
815 fadt->flags |= ACPI_FADT_DOCKING_SUPPORTED;
816 }
817 if (c2_latency < 100) {
818 fadt->flags |= ACPI_FADT_C2_MP_SUPPORTED;
819 }
820
821 fadt->reset_reg.space_id = 1;
822 fadt->reset_reg.bit_width = 8;
823 fadt->reset_reg.bit_offset = 0;
824 fadt->reset_reg.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
825 fadt->reset_reg.addrl = 0xcf9;
826 fadt->reset_reg.addrh = 0;
827
828 fadt->reset_value = 6;
829
830 fadt->x_pm1a_evt_blk.space_id = 1;
831 fadt->x_pm1a_evt_blk.bit_width = 32;
832 fadt->x_pm1a_evt_blk.bit_offset = 0;
833 fadt->x_pm1a_evt_blk.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
834 fadt->x_pm1a_evt_blk.addrl = pmbase;
835 fadt->x_pm1a_evt_blk.addrh = 0x0;
836
837 fadt->x_pm1b_evt_blk.space_id = 1;
838 fadt->x_pm1b_evt_blk.bit_width = 0;
839 fadt->x_pm1b_evt_blk.bit_offset = 0;
840 fadt->x_pm1b_evt_blk.access_size = 0;
841 fadt->x_pm1b_evt_blk.addrl = 0x0;
842 fadt->x_pm1b_evt_blk.addrh = 0x0;
843
844 fadt->x_pm1a_cnt_blk.space_id = 1;
845 fadt->x_pm1a_cnt_blk.bit_width = 16;
846 fadt->x_pm1a_cnt_blk.bit_offset = 0;
847 fadt->x_pm1a_cnt_blk.access_size = ACPI_ACCESS_SIZE_WORD_ACCESS;
848 fadt->x_pm1a_cnt_blk.addrl = pmbase + 0x4;
849 fadt->x_pm1a_cnt_blk.addrh = 0x0;
850
851 fadt->x_pm1b_cnt_blk.space_id = 1;
852 fadt->x_pm1b_cnt_blk.bit_width = 0;
853 fadt->x_pm1b_cnt_blk.bit_offset = 0;
854 fadt->x_pm1b_cnt_blk.access_size = 0;
855 fadt->x_pm1b_cnt_blk.addrl = 0x0;
856 fadt->x_pm1b_cnt_blk.addrh = 0x0;
857
858 fadt->x_pm2_cnt_blk.space_id = 1;
859 fadt->x_pm2_cnt_blk.bit_width = 8;
860 fadt->x_pm2_cnt_blk.bit_offset = 0;
861 fadt->x_pm2_cnt_blk.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
862 fadt->x_pm2_cnt_blk.addrl = pmbase + 0x50;
863 fadt->x_pm2_cnt_blk.addrh = 0x0;
864
865 fadt->x_pm_tmr_blk.space_id = 1;
866 fadt->x_pm_tmr_blk.bit_width = 32;
867 fadt->x_pm_tmr_blk.bit_offset = 0;
868 fadt->x_pm_tmr_blk.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
869 fadt->x_pm_tmr_blk.addrl = pmbase + 0x8;
870 fadt->x_pm_tmr_blk.addrh = 0x0;
871
872 fadt->x_gpe0_blk.space_id = 1;
873 fadt->x_gpe0_blk.bit_width = 128;
874 fadt->x_gpe0_blk.bit_offset = 0;
875 fadt->x_gpe0_blk.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
876 fadt->x_gpe0_blk.addrl = pmbase + 0x20;
877 fadt->x_gpe0_blk.addrh = 0x0;
878
879 fadt->x_gpe1_blk.space_id = 1;
880 fadt->x_gpe1_blk.bit_width = 0;
881 fadt->x_gpe1_blk.bit_offset = 0;
882 fadt->x_gpe1_blk.access_size = 0;
883 fadt->x_gpe1_blk.addrl = 0x0;
884 fadt->x_gpe1_blk.addrh = 0x0;
885}
886
Aaron Durbinaa090cb2017-09-13 16:01:52 -0600887static const char *lpc_acpi_name(const struct device *dev)
Patrick Rudolph604f6982017-06-07 09:46:52 +0200888{
889 return "LPCB";
890}
891
Elyes HAOUAS4aec3402018-05-25 08:29:27 +0200892static void southbridge_fill_ssdt(struct device *device)
Vladimir Serbinenko36fa5b82014-10-28 23:43:20 +0100893{
Elyes HAOUAS4aec3402018-05-25 08:29:27 +0200894 struct device *dev = dev_find_slot(0, PCI_DEVFN(0x1f, 0));
Vladimir Serbinenko36fa5b82014-10-28 23:43:20 +0100895 config_t *chip = dev->chip_info;
896
897 intel_acpi_pcie_hotplug_generator(chip->pcie_hotplug_map, 8);
Tobias Diedrich7f5efd92017-12-14 00:29:01 +0100898 intel_acpi_gen_def_acpi_pirq(dev);
Vladimir Serbinenko36fa5b82014-10-28 23:43:20 +0100899}
900
Vladimir Serbinenkob06a2492015-05-21 10:32:59 +0200901static void lpc_final(struct device *dev)
902{
Nico Huber8e50b6d2018-02-04 15:52:18 +0100903 u16 spi_opprefix = SPI_OPPREFIX;
904 u16 spi_optype = SPI_OPTYPE;
905 u32 spi_opmenu[2] = { SPI_OPMENU_LOWER, SPI_OPMENU_UPPER };
906
907 /* Configure SPI opcode menu; devicetree may override defaults. */
908 const config_t *const config = dev->chip_info;
909 if (config && config->spi.ops[0].op) {
910 unsigned int i;
911
912 spi_opprefix = 0;
913 spi_optype = 0;
914 spi_opmenu[0] = 0;
915 spi_opmenu[1] = 0;
916 for (i = 0; i < sizeof(spi_opprefix); ++i)
917 spi_opprefix |= config->spi.opprefixes[i] << i * 8;
918 for (i = 0; i < sizeof(spi_opmenu); ++i) {
919 spi_optype |=
920 config->spi.ops[i].is_write << 2 * i |
921 config->spi.ops[i].needs_address << (2 * i + 1);
922 spi_opmenu[i / 4] |=
923 config->spi.ops[i].op << (i % 4) * 8;
924 }
925 }
926 RCBA16(0x3894) = spi_opprefix;
927 RCBA16(0x3896) = spi_optype;
928 RCBA32(0x3898) = spi_opmenu[0];
929 RCBA32(0x389c) = spi_opmenu[1];
930
Bill XIEd533b162017-08-22 16:26:22 +0800931 /* Call SMM finalize() handlers before resume */
932 if (IS_ENABLED(CONFIG_HAVE_SMI_HANDLER)) {
933 if (IS_ENABLED(CONFIG_INTEL_CHIPSET_LOCKDOWN) ||
934 acpi_is_wakeup_s3()) {
935 outb(APM_CNT_FINALIZE, APM_CNT);
936 }
Vladimir Serbinenkob06a2492015-05-21 10:32:59 +0200937 }
938}
939
Stefan Reinauer8e073822012-04-04 00:07:22 +0200940static struct pci_operations pci_ops = {
941 .set_subsystem = set_subsystem,
942};
943
944static struct device_operations device_ops = {
945 .read_resources = pch_lpc_read_resources,
946 .set_resources = pci_dev_set_resources,
947 .enable_resources = pch_lpc_enable_resources,
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +0200948 .write_acpi_tables = acpi_write_hpet,
Vladimir Serbinenko334fd8e2014-10-05 11:10:35 +0200949 .acpi_inject_dsdt_generator = southbridge_inject_dsdt,
Vladimir Serbinenko36fa5b82014-10-28 23:43:20 +0100950 .acpi_fill_ssdt_generator = southbridge_fill_ssdt,
Patrick Rudolph604f6982017-06-07 09:46:52 +0200951 .acpi_name = lpc_acpi_name,
Stefan Reinauer8e073822012-04-04 00:07:22 +0200952 .init = lpc_init,
Vladimir Serbinenkob06a2492015-05-21 10:32:59 +0200953 .final = lpc_final,
Stefan Reinauer8e073822012-04-04 00:07:22 +0200954 .enable = pch_lpc_enable,
Kyösti Mälkkid0e212c2015-02-26 20:47:47 +0200955 .scan_bus = scan_lpc_bus,
Stefan Reinauer8e073822012-04-04 00:07:22 +0200956 .ops_pci = &pci_ops,
957};
958
959
Kimarie Hoote6f459c2012-07-14 08:26:08 -0600960/* IDs for LPC device of Intel 6 Series Chipset, Intel 7 Series Chipset, and
961 * Intel C200 Series Chipset
Stefan Reinauer8e073822012-04-04 00:07:22 +0200962 */
963
Vladimir Serbinenko42d55e02016-01-02 01:47:26 +0100964static const unsigned short pci_device_ids[] = {
965 0x1c40, 0x1c41, 0x1c42, 0x1c43, 0x1c44, 0x1c45, 0x1c46, 0x1c47, 0x1c48,
966 0x1c49, 0x1c4a, 0x1c4b, 0x1c4c, 0x1c4d, 0x1c4e, 0x1c4f, 0x1c50, 0x1c51,
967 0x1c52, 0x1c53, 0x1c54, 0x1c55, 0x1c56, 0x1c57, 0x1c58, 0x1c59, 0x1c5a,
968 0x1c5b, 0x1c5c, 0x1c5d, 0x1c5e, 0x1c5f,
969
970 0x1e41, 0x1e42, 0x1e43, 0x1e44, 0x1e45, 0x1e46, 0x1e47, 0x1e48, 0x1e49,
971 0x1e4a, 0x1e4b, 0x1e4c, 0x1e4d, 0x1e4e, 0x1e4f, 0x1e50, 0x1e51, 0x1e52,
972 0x1e53, 0x1e54, 0x1e55, 0x1e56, 0x1e57, 0x1e58, 0x1e59, 0x1e5a, 0x1e5b,
973 0x1e5c, 0x1e5d, 0x1e5e, 0x1e5f,
974
975 0 };
Stefan Reinauer9a380ab2012-06-22 13:16:11 -0700976
977static const struct pci_driver pch_lpc __pci_driver = {
978 .ops = &device_ops,
979 .vendor = PCI_VENDOR_ID_INTEL,
980 .devices = pci_device_ids,
Stefan Reinauer8e073822012-04-04 00:07:22 +0200981};