blob: 11b765adc6baac0d5c6676fae8144c91ef9b17dc [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.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
Paul Menzela46a7122013-02-23 18:37:27 +010018 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Stefan Reinauer8e073822012-04-04 00:07:22 +020019 */
20
21#include <console/console.h>
22#include <device/device.h>
23#include <device/pci.h>
24#include <device/pci_ids.h>
25#include <pc80/mc146818rtc.h>
26#include <pc80/isa-dma.h>
27#include <pc80/i8259.h>
28#include <arch/io.h>
29#include <arch/ioapic.h>
30#include <arch/acpi.h>
31#include <cpu/cpu.h>
Duncan Laurie800e9502012-06-23 17:06:47 -070032#include <elog.h>
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +020033#include <arch/acpigen.h>
34#include <drivers/intel/gma/i915.h>
Vladimir Serbinenko5b044ae2014-10-25 15:20:55 +020035#include <cpu/x86/smm.h>
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +020036#include <cbmem.h>
Vladimir Serbinenko7309c642014-10-05 11:07:33 +020037#include <string.h>
Vladimir Serbinenko5b044ae2014-10-25 15:20:55 +020038#include <cpu/x86/smm.h>
Stefan Reinauer8e073822012-04-04 00:07:22 +020039#include "pch.h"
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +020040#include "nvs.h"
Vladimir Serbinenko36fa5b82014-10-28 23:43:20 +010041#include <southbridge/intel/common/pciehp.h>
Stefan Reinauer8e073822012-04-04 00:07:22 +020042
43#define NMI_OFF 0
44
45#define ENABLE_ACPI_MODE_IN_COREBOOT 0
46#define TEST_SMM_FLASH_LOCKDOWN 0
47
48typedef struct southbridge_intel_bd82x6x_config config_t;
49
Paul Menzel9c50e6a2013-05-03 12:23:39 +020050/**
51 * Set miscellanous static southbridge features.
52 *
53 * @param dev PCI device with I/O APIC control registers
54 */
55static void pch_enable_ioapic(struct device *dev)
Stefan Reinauer8e073822012-04-04 00:07:22 +020056{
Stefan Reinauer8e073822012-04-04 00:07:22 +020057 u32 reg32;
Stefan Reinauer8e073822012-04-04 00:07:22 +020058
Paul Menzel9c50e6a2013-05-03 12:23:39 +020059 /* Enable ACPI I/O range decode */
60 pci_write_config8(dev, ACPI_CNTL, ACPI_EN);
Stefan Reinauer8e073822012-04-04 00:07:22 +020061
Paul Menzel9c50e6a2013-05-03 12:23:39 +020062 set_ioapic_id(IO_APIC_ADDR, 0x02);
Stefan Reinauer8e073822012-04-04 00:07:22 +020063
64 /* affirm full set of redirection table entries ("write once") */
Paul Menzel9c50e6a2013-05-03 12:23:39 +020065 reg32 = io_apic_read(IO_APIC_ADDR, 0x01);
66 io_apic_write(IO_APIC_ADDR, 0x01, reg32);
Stefan Reinauer8e073822012-04-04 00:07:22 +020067
Paul Menzel9c50e6a2013-05-03 12:23:39 +020068 /*
69 * Select Boot Configuration register (0x03) and
70 * use Processor System Bus (0x01) to deliver interrupts.
71 */
72 io_apic_write(IO_APIC_ADDR, 0x03, 0x01);
Stefan Reinauer8e073822012-04-04 00:07:22 +020073}
74
75static void pch_enable_serial_irqs(struct device *dev)
76{
77 /* Set packet length and toggle silent mode bit for one frame. */
78 pci_write_config8(dev, SERIRQ_CNTL,
79 (1 << 7) | (1 << 6) | ((21 - 17) << 2) | (0 << 0));
80#if !CONFIG_SERIRQ_CONTINUOUS_MODE
81 pci_write_config8(dev, SERIRQ_CNTL,
82 (1 << 7) | (0 << 6) | ((21 - 17) << 2) | (0 << 0));
83#endif
84}
85
86/* PIRQ[n]_ROUT[3:0] - PIRQ Routing Control
87 * 0x00 - 0000 = Reserved
88 * 0x01 - 0001 = Reserved
89 * 0x02 - 0010 = Reserved
90 * 0x03 - 0011 = IRQ3
91 * 0x04 - 0100 = IRQ4
92 * 0x05 - 0101 = IRQ5
93 * 0x06 - 0110 = IRQ6
94 * 0x07 - 0111 = IRQ7
95 * 0x08 - 1000 = Reserved
96 * 0x09 - 1001 = IRQ9
97 * 0x0A - 1010 = IRQ10
98 * 0x0B - 1011 = IRQ11
99 * 0x0C - 1100 = IRQ12
100 * 0x0D - 1101 = Reserved
101 * 0x0E - 1110 = IRQ14
102 * 0x0F - 1111 = IRQ15
103 * PIRQ[n]_ROUT[7] - PIRQ Routing Control
104 * 0x80 - The PIRQ is not routed.
105 */
106
107static void pch_pirq_init(device_t dev)
108{
109 device_t irq_dev;
Vladimir Serbinenko33b535f2014-10-19 10:13:14 +0200110 /* Interrupt 11 is not used by legacy devices and so can always be used for
111 PCI interrupts. Full legacy IRQ routing is complicated and hard to
112 get right. Fortunately all modern OS use MSI and so it's not that big of
113 an issue anyway. Still we have to provide a reasonable default. Using
114 interrupt 11 for it everywhere is a working default. ACPI-aware OS can
115 move it to any interrupt and others will just leave them at default.
Stefan Reinauer8e073822012-04-04 00:07:22 +0200116 */
Vladimir Serbinenko33b535f2014-10-19 10:13:14 +0200117 const u8 pirq_routing = 11;
118
119 pci_write_config8(dev, PIRQA_ROUT, pirq_routing);
120 pci_write_config8(dev, PIRQB_ROUT, pirq_routing);
121 pci_write_config8(dev, PIRQC_ROUT, pirq_routing);
122 pci_write_config8(dev, PIRQD_ROUT, pirq_routing);
123
124 pci_write_config8(dev, PIRQE_ROUT, pirq_routing);
125 pci_write_config8(dev, PIRQF_ROUT, pirq_routing);
126 pci_write_config8(dev, PIRQG_ROUT, pirq_routing);
127 pci_write_config8(dev, PIRQH_ROUT, pirq_routing);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200128
129 for(irq_dev = all_devices; irq_dev; irq_dev = irq_dev->next) {
Vladimir Serbinenko33b535f2014-10-19 10:13:14 +0200130 u8 int_pin=0;
Stefan Reinauer8e073822012-04-04 00:07:22 +0200131
132 if (!irq_dev->enabled || irq_dev->path.type != DEVICE_PATH_PCI)
133 continue;
134
135 int_pin = pci_read_config8(irq_dev, PCI_INTERRUPT_PIN);
136
Vladimir Serbinenko33b535f2014-10-19 10:13:14 +0200137 if (int_pin == 0)
Stefan Reinauer8e073822012-04-04 00:07:22 +0200138 continue;
139
Vladimir Serbinenko33b535f2014-10-19 10:13:14 +0200140 pci_write_config8(irq_dev, PCI_INTERRUPT_LINE, pirq_routing);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200141 }
142}
143
144static void pch_gpi_routing(device_t dev)
145{
146 /* Get the chip configuration */
147 config_t *config = dev->chip_info;
148 u32 reg32 = 0;
149
150 /* An array would be much nicer here, or some
151 * other method of doing this.
152 */
153 reg32 |= (config->gpi0_routing & 0x03) << 0;
154 reg32 |= (config->gpi1_routing & 0x03) << 2;
155 reg32 |= (config->gpi2_routing & 0x03) << 4;
156 reg32 |= (config->gpi3_routing & 0x03) << 6;
157 reg32 |= (config->gpi4_routing & 0x03) << 8;
158 reg32 |= (config->gpi5_routing & 0x03) << 10;
159 reg32 |= (config->gpi6_routing & 0x03) << 12;
160 reg32 |= (config->gpi7_routing & 0x03) << 14;
161 reg32 |= (config->gpi8_routing & 0x03) << 16;
162 reg32 |= (config->gpi9_routing & 0x03) << 18;
163 reg32 |= (config->gpi10_routing & 0x03) << 20;
164 reg32 |= (config->gpi11_routing & 0x03) << 22;
165 reg32 |= (config->gpi12_routing & 0x03) << 24;
166 reg32 |= (config->gpi13_routing & 0x03) << 26;
167 reg32 |= (config->gpi14_routing & 0x03) << 28;
168 reg32 |= (config->gpi15_routing & 0x03) << 30;
169
170 pci_write_config32(dev, 0xb8, reg32);
171}
172
173static void pch_power_options(device_t dev)
174{
175 u8 reg8;
176 u16 reg16, pmbase;
177 u32 reg32;
178 const char *state;
179 /* Get the chip configuration */
180 config_t *config = dev->chip_info;
181
182 int pwr_on=CONFIG_MAINBOARD_POWER_ON_AFTER_POWER_FAIL;
183 int nmi_option;
184
185 /* Which state do we want to goto after g3 (power restored)?
186 * 0 == S0 Full On
187 * 1 == S5 Soft Off
188 *
189 * If the option is not existent (Laptops), use Kconfig setting.
190 */
191 get_option(&pwr_on, "power_on_after_fail");
192
193 reg16 = pci_read_config16(dev, GEN_PMCON_3);
194 reg16 &= 0xfffe;
195 switch (pwr_on) {
196 case MAINBOARD_POWER_OFF:
197 reg16 |= 1;
198 state = "off";
199 break;
200 case MAINBOARD_POWER_ON:
201 reg16 &= ~1;
202 state = "on";
203 break;
204 case MAINBOARD_POWER_KEEP:
205 reg16 &= ~1;
206 state = "state keep";
207 break;
208 default:
209 state = "undefined";
210 }
211
212 reg16 &= ~(3 << 4); /* SLP_S4# Assertion Stretch 4s */
213 reg16 |= (1 << 3); /* SLP_S4# Assertion Stretch Enable */
214
215 reg16 &= ~(1 << 10);
216 reg16 |= (1 << 11); /* SLP_S3# Min Assertion Width 50ms */
217
218 reg16 |= (1 << 12); /* Disable SLP stretch after SUS well */
219
220 pci_write_config16(dev, GEN_PMCON_3, reg16);
221 printk(BIOS_INFO, "Set power %s after power failure.\n", state);
222
223 /* Set up NMI on errors. */
224 reg8 = inb(0x61);
225 reg8 &= 0x0f; /* Higher Nibble must be 0 */
226 reg8 &= ~(1 << 3); /* IOCHK# NMI Enable */
227 // reg8 &= ~(1 << 2); /* PCI SERR# Enable */
228 reg8 |= (1 << 2); /* PCI SERR# Disable for now */
229 outb(reg8, 0x61);
230
231 reg8 = inb(0x70);
232 nmi_option = NMI_OFF;
233 get_option(&nmi_option, "nmi");
234 if (nmi_option) {
235 printk(BIOS_INFO, "NMI sources enabled.\n");
236 reg8 &= ~(1 << 7); /* Set NMI. */
237 } else {
238 printk(BIOS_INFO, "NMI sources disabled.\n");
239 reg8 |= ( 1 << 7); /* Can't mask NMI from PCI-E and NMI_NOW */
240 }
241 outb(reg8, 0x70);
242
243 /* Enable CPU_SLP# and Intel Speedstep, set SMI# rate down */
244 reg16 = pci_read_config16(dev, GEN_PMCON_1);
245 reg16 &= ~(3 << 0); // SMI# rate 1 minute
246 reg16 &= ~(1 << 10); // Disable BIOS_PCI_EXP_EN for native PME
247#if DEBUG_PERIODIC_SMIS
248 /* Set DEBUG_PERIODIC_SMIS in pch.h to debug using
249 * periodic SMIs.
250 */
251 reg16 |= (3 << 0); // Periodic SMI every 8s
252#endif
253 pci_write_config16(dev, GEN_PMCON_1, reg16);
254
255 // Set the board's GPI routing.
256 pch_gpi_routing(dev);
257
258 pmbase = pci_read_config16(dev, 0x40) & 0xfffe;
259
260 outl(config->gpe0_en, pmbase + GPE0_EN);
261 outw(config->alt_gp_smi_en, pmbase + ALT_GP_SMI_EN);
262
263 /* Set up power management block and determine sleep mode */
264 reg32 = inl(pmbase + 0x04); // PM1_CNT
265 reg32 &= ~(7 << 10); // SLP_TYP
266 reg32 |= (1 << 0); // SCI_EN
267 outl(reg32, pmbase + 0x04);
268
269 /* Clear magic status bits to prevent unexpected wake */
270 reg32 = RCBA32(0x3310);
271 reg32 |= (1 << 4)|(1 << 5)|(1 << 0);
272 RCBA32(0x3310) = reg32;
273
274 reg32 = RCBA32(0x3f02);
275 reg32 &= ~0xf;
276 RCBA32(0x3f02) = reg32;
277}
278
279static void pch_rtc_init(struct device *dev)
280{
281 u8 reg8;
282 int rtc_failed;
283
284 reg8 = pci_read_config8(dev, GEN_PMCON_3);
285 rtc_failed = reg8 & RTC_BATTERY_DEAD;
286 if (rtc_failed) {
287 reg8 &= ~RTC_BATTERY_DEAD;
288 pci_write_config8(dev, GEN_PMCON_3, reg8);
Duncan Laurie800e9502012-06-23 17:06:47 -0700289#if CONFIG_ELOG
290 elog_add_event(ELOG_TYPE_RTC_RESET);
291#endif
Stefan Reinauer8e073822012-04-04 00:07:22 +0200292 }
293 printk(BIOS_DEBUG, "rtc_failed = 0x%x\n", rtc_failed);
294
Gabe Blackb3f08c62014-04-30 17:12:25 -0700295 cmos_init(rtc_failed);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200296}
297
Duncan Laurie3f6a4d72012-06-28 13:03:40 -0700298/* CougarPoint PCH Power Management init */
299static void cpt_pm_init(struct device *dev)
Stefan Reinauer8e073822012-04-04 00:07:22 +0200300{
Duncan Laurie3f6a4d72012-06-28 13:03:40 -0700301 printk(BIOS_DEBUG, "CougarPoint PM init\n");
Stefan Reinauer8e073822012-04-04 00:07:22 +0200302 pci_write_config8(dev, 0xa9, 0x47);
303 RCBA32_AND_OR(0x2238, ~0UL, (1 << 6)|(1 << 0));
304 RCBA32_AND_OR(0x228c, ~0UL, (1 << 0));
305 RCBA16_AND_OR(0x1100, ~0UL, (1 << 13)|(1 << 14));
306 RCBA16_AND_OR(0x0900, ~0UL, (1 << 14));
307 RCBA32(0x2304) = 0xc0388400;
308 RCBA32_AND_OR(0x2314, ~0UL, (1 << 5)|(1 << 18));
309 RCBA32_AND_OR(0x2320, ~0UL, (1 << 15)|(1 << 1));
310 RCBA32_AND_OR(0x3314, ~0x1f, 0xf);
311 RCBA32(0x3318) = 0x050f0000;
312 RCBA32(0x3324) = 0x04000000;
313 RCBA32_AND_OR(0x3340, ~0UL, 0xfffff);
314 RCBA32_AND_OR(0x3344, ~0UL, (1 << 1));
315 RCBA32(0x3360) = 0x0001c000;
316 RCBA32(0x3368) = 0x00061100;
317 RCBA32(0x3378) = 0x7f8fdfff;
318 RCBA32(0x337c) = 0x000003fc;
319 RCBA32(0x3388) = 0x00001000;
320 RCBA32(0x3390) = 0x0001c000;
321 RCBA32(0x33a0) = 0x00000800;
322 RCBA32(0x33b0) = 0x00001000;
323 RCBA32(0x33c0) = 0x00093900;
324 RCBA32(0x33cc) = 0x24653002;
325 RCBA32(0x33d0) = 0x062108fe;
326 RCBA32_AND_OR(0x33d4, 0xf000f000, 0x00670060);
327 RCBA32(0x3a28) = 0x01010000;
328 RCBA32(0x3a2c) = 0x01010404;
329 RCBA32(0x3a80) = 0x01041041;
330 RCBA32_AND_OR(0x3a84, ~0x0000ffff, 0x00001001);
331 RCBA32_AND_OR(0x3a84, ~0UL, (1 << 24)); /* SATA 2/3 disabled */
332 RCBA32_AND_OR(0x3a88, ~0UL, (1 << 0)); /* SATA 4/5 disabled */
333 RCBA32(0x3a6c) = 0x00000001;
334 RCBA32_AND_OR(0x2344, 0x00ffff00, 0xff00000c);
335 RCBA32_AND_OR(0x80c, ~(0xff << 20), 0x11 << 20);
336 RCBA32(0x33c8) = 0;
337 RCBA32_AND_OR(0x21b0, ~0UL, 0xf);
338}
339
Duncan Laurie3f6a4d72012-06-28 13:03:40 -0700340/* PantherPoint PCH Power Management init */
341static void ppt_pm_init(struct device *dev)
342{
343 printk(BIOS_DEBUG, "PantherPoint PM init\n");
344 pci_write_config8(dev, 0xa9, 0x47);
345 RCBA32_AND_OR(0x2238, ~0UL, (1 << 0));
346 RCBA32_AND_OR(0x228c, ~0UL, (1 << 0));
347 RCBA16_AND_OR(0x1100, ~0UL, (1 << 13)|(1 << 14));
348 RCBA16_AND_OR(0x0900, ~0UL, (1 << 14));
349 RCBA32(0x2304) = 0xc03b8400;
350 RCBA32_AND_OR(0x2314, ~0UL, (1 << 5)|(1 << 18));
351 RCBA32_AND_OR(0x2320, ~0UL, (1 << 15)|(1 << 1));
352 RCBA32_AND_OR(0x3314, ~0x1f, 0xf);
353 RCBA32(0x3318) = 0x054f0000;
354 RCBA32(0x3324) = 0x04000000;
355 RCBA32_AND_OR(0x3340, ~0UL, 0xfffff);
356 RCBA32_AND_OR(0x3344, ~0UL, (1 << 1)|(1 << 0));
357 RCBA32(0x3360) = 0x0001c000;
358 RCBA32(0x3368) = 0x00061100;
359 RCBA32(0x3378) = 0x7f8fdfff;
360 RCBA32(0x337c) = 0x000003fd;
361 RCBA32(0x3388) = 0x00001000;
362 RCBA32(0x3390) = 0x0001c000;
363 RCBA32(0x33a0) = 0x00000800;
364 RCBA32(0x33b0) = 0x00001000;
365 RCBA32(0x33c0) = 0x00093900;
366 RCBA32(0x33cc) = 0x24653002;
367 RCBA32(0x33d0) = 0x067388fe;
368 RCBA32_AND_OR(0x33d4, 0xf000f000, 0x00670060);
369 RCBA32(0x3a28) = 0x01010000;
370 RCBA32(0x3a2c) = 0x01010404;
371 RCBA32(0x3a80) = 0x01040000;
372 RCBA32_AND_OR(0x3a84, ~0x0000ffff, 0x00001001);
373 RCBA32_AND_OR(0x3a84, ~0UL, (1 << 24)); /* SATA 2/3 disabled */
374 RCBA32_AND_OR(0x3a88, ~0UL, (1 << 0)); /* SATA 4/5 disabled */
375 RCBA32(0x3a6c) = 0x00000001;
376 RCBA32_AND_OR(0x2344, 0x00ffff00, 0xff00000c);
377 RCBA32_AND_OR(0x80c, ~(0xff << 20), 0x11 << 20);
378 RCBA32_AND_OR(0x33a4, ~0UL, (1 << 0));
379 RCBA32(0x33c8) = 0;
380 RCBA32_AND_OR(0x21b0, ~0UL, 0xf);
381}
382
Stefan Reinauer8e073822012-04-04 00:07:22 +0200383static void enable_hpet(void)
384{
385 u32 reg32;
386
387 /* Move HPET to default address 0xfed00000 and enable it */
388 reg32 = RCBA32(HPTC);
389 reg32 |= (1 << 7); // HPET Address Enable
390 reg32 &= ~(3 << 0);
391 RCBA32(HPTC) = reg32;
392}
393
394static void enable_clock_gating(device_t dev)
395{
396 u32 reg32;
397 u16 reg16;
398
399 RCBA32_AND_OR(0x2234, ~0UL, 0xf);
400
401 reg16 = pci_read_config16(dev, GEN_PMCON_1);
402 reg16 |= (1 << 2) | (1 << 11);
403 pci_write_config16(dev, GEN_PMCON_1, reg16);
404
405 pch_iobp_update(0xEB007F07, ~0UL, (1 << 31));
406 pch_iobp_update(0xEB004000, ~0UL, (1 << 7));
407 pch_iobp_update(0xEC007F07, ~0UL, (1 << 31));
408 pch_iobp_update(0xEC004000, ~0UL, (1 << 7));
409
410 reg32 = RCBA32(CG);
411 reg32 |= (1 << 31);
412 reg32 |= (1 << 29) | (1 << 28);
413 reg32 |= (1 << 27) | (1 << 26) | (1 << 25) | (1 << 24);
414 reg32 |= (1 << 16);
415 reg32 |= (1 << 17);
416 reg32 |= (1 << 18);
417 reg32 |= (1 << 22);
418 reg32 |= (1 << 23);
419 reg32 &= ~(1 << 20);
420 reg32 |= (1 << 19);
421 reg32 |= (1 << 0);
422 reg32 |= (0xf << 1);
423 RCBA32(CG) = reg32;
424
425 RCBA32_OR(0x38c0, 0x7);
426 RCBA32_OR(0x36d4, 0x6680c004);
427 RCBA32_OR(0x3564, 0x3);
428}
429
430#if CONFIG_HAVE_SMI_HANDLER
431static void pch_lock_smm(struct device *dev)
432{
433#if TEST_SMM_FLASH_LOCKDOWN
434 u8 reg8;
435#endif
436
Kyösti Mälkkic3ed8862014-06-19 19:50:51 +0300437 if (!acpi_is_wakeup_s3()) {
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");
440 outb(0xe1, 0xb2); // Enable ACPI mode
441 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");
444 outb(0x1e, 0xb2); // Disable ACPI mode
445 printk(BIOS_DEBUG, "done.\n");
Stefan Reinauer8e073822012-04-04 00:07:22 +0200446#endif
Duncan Laurie95be1d62012-04-09 12:31:43 -0700447 }
448
Stefan Reinauer8e073822012-04-04 00:07:22 +0200449 /* Don't allow evil boot loaders, kernels, or
450 * userspace applications to deceive us:
451 */
452 smm_lock();
453
454#if TEST_SMM_FLASH_LOCKDOWN
455 /* Now try this: */
456 printk(BIOS_DEBUG, "Locking BIOS to RO... ");
457 reg8 = pci_read_config8(dev, 0xdc); /* BIOS_CNTL */
458 printk(BIOS_DEBUG, " BLE: %s; BWE: %s\n", (reg8&2)?"on":"off",
459 (reg8&1)?"rw":"ro");
460 reg8 &= ~(1 << 0); /* clear BIOSWE */
461 pci_write_config8(dev, 0xdc, reg8);
462 reg8 |= (1 << 1); /* set BLE */
463 pci_write_config8(dev, 0xdc, reg8);
464 printk(BIOS_DEBUG, "ok.\n");
465 reg8 = pci_read_config8(dev, 0xdc); /* BIOS_CNTL */
466 printk(BIOS_DEBUG, " BLE: %s; BWE: %s\n", (reg8&2)?"on":"off",
467 (reg8&1)?"rw":"ro");
468
469 printk(BIOS_DEBUG, "Writing:\n");
470 *(volatile u8 *)0xfff00000 = 0x00;
471 printk(BIOS_DEBUG, "Testing:\n");
472 reg8 |= (1 << 0); /* set BIOSWE */
473 pci_write_config8(dev, 0xdc, reg8);
474
475 reg8 = pci_read_config8(dev, 0xdc); /* BIOS_CNTL */
476 printk(BIOS_DEBUG, " BLE: %s; BWE: %s\n", (reg8&2)?"on":"off",
477 (reg8&1)?"rw":"ro");
478 printk(BIOS_DEBUG, "Done.\n");
479#endif
480}
481#endif
482
483static void pch_disable_smm_only_flashing(struct device *dev)
484{
485 u8 reg8;
486
487 printk(BIOS_SPEW, "Enabling BIOS updates outside of SMM... ");
488 reg8 = pci_read_config8(dev, 0xdc); /* BIOS_CNTL */
489 reg8 &= ~(1 << 5);
490 pci_write_config8(dev, 0xdc, reg8);
491}
492
493static void pch_fixups(struct device *dev)
494{
495 u8 gen_pmcon_2;
496
497 /* Indicate DRAM init done for MRC S3 to know it can resume */
498 gen_pmcon_2 = pci_read_config8(dev, GEN_PMCON_2);
499 gen_pmcon_2 |= (1 << 7);
500 pci_write_config8(dev, GEN_PMCON_2, gen_pmcon_2);
501
502 /*
503 * Enable DMI ASPM in the PCH
504 */
505 RCBA32_AND_OR(0x2304, ~(1 << 10), 0);
506 RCBA32_OR(0x21a4, (1 << 11)|(1 << 10));
507 RCBA32_OR(0x21a8, 0x3);
508}
509
510static void pch_decode_init(struct device *dev)
511{
512 config_t *config = dev->chip_info;
513
514 printk(BIOS_DEBUG, "pch_decode_init\n");
515
516 pci_write_config32(dev, LPC_GEN1_DEC, config->gen1_dec);
517 pci_write_config32(dev, LPC_GEN2_DEC, config->gen2_dec);
518 pci_write_config32(dev, LPC_GEN3_DEC, config->gen3_dec);
519 pci_write_config32(dev, LPC_GEN4_DEC, config->gen4_dec);
520}
521
522static void lpc_init(struct device *dev)
523{
524 printk(BIOS_DEBUG, "pch: lpc_init\n");
525
526 /* Set the value for PCI command register. */
527 pci_write_config16(dev, PCI_COMMAND, 0x000f);
528
529 /* IO APIC initialization. */
Paul Menzel9c50e6a2013-05-03 12:23:39 +0200530 pch_enable_ioapic(dev);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200531
532 pch_enable_serial_irqs(dev);
533
534 /* Setup the PIRQ. */
535 pch_pirq_init(dev);
536
537 /* Setup power options. */
538 pch_power_options(dev);
539
540 /* Initialize power management */
Duncan Laurie3f6a4d72012-06-28 13:03:40 -0700541 switch (pch_silicon_type()) {
542 case PCH_TYPE_CPT: /* CougarPoint */
543 cpt_pm_init(dev);
544 break;
545 case PCH_TYPE_PPT: /* PantherPoint */
546 ppt_pm_init(dev);
547 break;
548 default:
549 printk(BIOS_ERR, "Unknown Chipset: 0x%04x\n", dev->device);
550 }
Stefan Reinauer8e073822012-04-04 00:07:22 +0200551
552 /* Set the state of the GPIO lines. */
553 //gpio_init(dev);
554
555 /* Initialize the real time clock. */
556 pch_rtc_init(dev);
557
558 /* Initialize ISA DMA. */
559 isa_dma_init();
560
561 /* Initialize the High Precision Event Timers, if present. */
562 enable_hpet();
563
564 /* Initialize Clock Gating */
565 enable_clock_gating(dev);
566
567 setup_i8259();
568
569 /* The OS should do this? */
570 /* Interrupt 9 should be level triggered (SCI) */
571 i8259_configure_irq_trigger(9, 1);
572
573 pch_disable_smm_only_flashing(dev);
574
575#if CONFIG_HAVE_SMI_HANDLER
576 pch_lock_smm(dev);
577#endif
578
579 pch_fixups(dev);
580}
581
582static void pch_lpc_read_resources(device_t dev)
583{
584 struct resource *res;
Marc Jonesa0bec172012-07-13 14:14:34 -0600585 config_t *config = dev->chip_info;
586 u8 io_index = 0;
Stefan Reinauer8e073822012-04-04 00:07:22 +0200587
588 /* Get the normal PCI resources of this device. */
589 pci_dev_read_resources(dev);
590
591 /* Add an extra subtractive resource for both memory and I/O. */
Marc Jonesa0bec172012-07-13 14:14:34 -0600592 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
Stefan Reinauer8e073822012-04-04 00:07:22 +0200593 res->base = 0;
594 res->size = 0x1000;
595 res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
596 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
597
Marc Jonesa0bec172012-07-13 14:14:34 -0600598 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
Vladimir Serbinenko0650cd02014-02-05 15:03:50 +0100599 res->base = 0xff000000;
600 /* Some systems (e.g. X230) have 12 MiB flash.
601 SPI controller supports up to 2 x 16 MiB of flash but
602 address map limits this to 16MiB. */
603 res->size = 0x01000000; /* 16 MB for flash */
Stefan Reinauer8e073822012-04-04 00:07:22 +0200604 res->flags = IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE |
605 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
606
607 res = new_resource(dev, 3); /* IOAPIC */
608 res->base = IO_APIC_ADDR;
609 res->size = 0x00001000;
610 res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
Marc Jonesa0bec172012-07-13 14:14:34 -0600611
612 /* Set PCH IO decode ranges if required.*/
613 if ((config->gen1_dec & 0xFFFC) > 0x1000) {
614 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
615 res->base = config->gen1_dec & 0xFFFC;
616 res->size = (config->gen1_dec >> 16) & 0xFC;
617 res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
618 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
619 }
620
621 if ((config->gen2_dec & 0xFFFC) > 0x1000) {
622 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
623 res->base = config->gen2_dec & 0xFFFC;
624 res->size = (config->gen2_dec >> 16) & 0xFC;
625 res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
626 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
627 }
628
629 if ((config->gen3_dec & 0xFFFC) > 0x1000) {
630 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
631 res->base = config->gen3_dec & 0xFFFC;
632 res->size = (config->gen3_dec >> 16) & 0xFC;
633 res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
634 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
635 }
636
637 if ((config->gen4_dec & 0xFFFC) > 0x1000) {
638 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
639 res->base = config->gen4_dec & 0xFFFC;
640 res->size = (config->gen4_dec >> 16) & 0xFC;
641 res->flags = IORESOURCE_IO| IORESOURCE_SUBTRACTIVE |
642 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
643 }
Stefan Reinauer8e073822012-04-04 00:07:22 +0200644}
645
646static void pch_lpc_enable_resources(device_t dev)
647{
648 pch_decode_init(dev);
649 return pci_dev_enable_resources(dev);
650}
651
652static void pch_lpc_enable(device_t dev)
653{
654 /* Enable PCH Display Port */
655 RCBA16(DISPBDF) = 0x0010;
656 RCBA32_OR(FD2, PCH_ENABLE_DBDF);
657
658 pch_enable(dev);
659}
660
661static void set_subsystem(device_t dev, unsigned vendor, unsigned device)
662{
663 if (!vendor || !device) {
664 pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
665 pci_read_config32(dev, PCI_VENDOR_ID));
666 } else {
667 pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
668 ((device & 0xffff) << 16) | (vendor & 0xffff));
669 }
670}
671
Vladimir Serbinenko334fd8e2014-10-05 11:10:35 +0200672static void southbridge_inject_dsdt(void)
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +0200673{
674 global_nvs_t *gnvs = cbmem_add (CBMEM_ID_ACPI_GNVS, sizeof (*gnvs));
675 void *opregion;
676
677 /* Calling northbridge code as gnvs contains opregion address. */
678 opregion = igd_make_opregion();
679
680 if (gnvs) {
Vladimir Serbinenko7309c642014-10-05 11:07:33 +0200681 memset(gnvs, 0, sizeof (*gnvs));
682
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +0200683 acpi_create_gnvs(gnvs);
Vladimir Serbinenko06c788d2014-10-12 00:17:11 +0200684
685 gnvs->apic = 1;
686 gnvs->mpen = 1; /* Enable Multi Processing */
687 gnvs->pcnt = dev_count_cpu();
688
689#if CONFIG_CHROMEOS
690 chromeos_init_vboot(&(gnvs->chromeos));
691#endif
692
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +0200693 /* IGD OpRegion Base Address */
694 gnvs->aslb = (u32)opregion;
695 /* And tell SMI about it */
696 smm_setup_structures(gnvs, NULL, NULL);
697
Vladimir Serbinenko334fd8e2014-10-05 11:10:35 +0200698 /* Add it to DSDT. */
Vladimir Serbinenko226d7842014-11-04 21:09:23 +0100699 acpigen_write_scope("\\");
700 acpigen_write_name_dword("NVSA", (u32) gnvs);
701 acpigen_pop_len();
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +0200702 }
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +0200703}
704
Vladimir Serbinenko5b044ae2014-10-25 15:20:55 +0200705void acpi_fill_fadt(acpi_fadt_t *fadt)
706{
707 device_t dev = dev_find_slot(0, PCI_DEVFN(0x1f,0));
708 config_t *chip = dev->chip_info;
709 u16 pmbase = pci_read_config16(dev, 0x40) & 0xfffe;
710 int c2_latency;
711
712 fadt->model = 1;
713
714 fadt->sci_int = 0x9;
715 fadt->smi_cmd = APM_CNT;
716 fadt->acpi_enable = APM_CNT_ACPI_ENABLE;
717 fadt->acpi_disable = APM_CNT_ACPI_DISABLE;
718 fadt->s4bios_req = 0x0;
719 fadt->pstate_cnt = 0;
720
721 fadt->pm1a_evt_blk = pmbase;
722 fadt->pm1b_evt_blk = 0x0;
723 fadt->pm1a_cnt_blk = pmbase + 0x4;
724 fadt->pm1b_cnt_blk = 0x0;
725 fadt->pm2_cnt_blk = pmbase + 0x50;
726 fadt->pm_tmr_blk = pmbase + 0x8;
727 fadt->gpe0_blk = pmbase + 0x20;
728 fadt->gpe1_blk = 0;
729
730 fadt->pm1_evt_len = 4;
731 fadt->pm1_cnt_len = 2;
732 fadt->pm2_cnt_len = 1;
733 fadt->pm_tmr_len = 4;
734 fadt->gpe0_blk_len = 16;
735 fadt->gpe1_blk_len = 0;
736 fadt->gpe1_base = 0;
737 fadt->cst_cnt = 0;
738 c2_latency = chip->c2_latency;
739 if (!c2_latency) {
740 c2_latency = 101; /* c2 unsupported */
741 }
742 fadt->p_lvl2_lat = c2_latency;
743 fadt->p_lvl3_lat = 87;
744 fadt->flush_size = 1024;
745 fadt->flush_stride = 16;
746 fadt->duty_offset = 1;
747 if (chip->p_cnt_throttling_supported) {
748 fadt->duty_width = 3;
749 } else {
750 fadt->duty_width = 0;
751 }
752 fadt->day_alrm = 0xd;
753 fadt->mon_alrm = 0x00;
754 fadt->century = 0x00;
755 fadt->iapc_boot_arch = ACPI_FADT_LEGACY_DEVICES | ACPI_FADT_8042;
756
757 fadt->flags = ACPI_FADT_WBINVD |
758 ACPI_FADT_C1_SUPPORTED |
759 ACPI_FADT_SLEEP_BUTTON |
760 ACPI_FADT_RESET_REGISTER |
761 ACPI_FADT_SEALED_CASE |
762 ACPI_FADT_S4_RTC_WAKE |
763 ACPI_FADT_PLATFORM_CLOCK;
764 if (chip->docking_supported) {
765 fadt->flags |= ACPI_FADT_DOCKING_SUPPORTED;
766 }
767 if (c2_latency < 100) {
768 fadt->flags |= ACPI_FADT_C2_MP_SUPPORTED;
769 }
770
771 fadt->reset_reg.space_id = 1;
772 fadt->reset_reg.bit_width = 8;
773 fadt->reset_reg.bit_offset = 0;
774 fadt->reset_reg.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
775 fadt->reset_reg.addrl = 0xcf9;
776 fadt->reset_reg.addrh = 0;
777
778 fadt->reset_value = 6;
779
780 fadt->x_pm1a_evt_blk.space_id = 1;
781 fadt->x_pm1a_evt_blk.bit_width = 32;
782 fadt->x_pm1a_evt_blk.bit_offset = 0;
783 fadt->x_pm1a_evt_blk.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
784 fadt->x_pm1a_evt_blk.addrl = pmbase;
785 fadt->x_pm1a_evt_blk.addrh = 0x0;
786
787 fadt->x_pm1b_evt_blk.space_id = 1;
788 fadt->x_pm1b_evt_blk.bit_width = 0;
789 fadt->x_pm1b_evt_blk.bit_offset = 0;
790 fadt->x_pm1b_evt_blk.access_size = 0;
791 fadt->x_pm1b_evt_blk.addrl = 0x0;
792 fadt->x_pm1b_evt_blk.addrh = 0x0;
793
794 fadt->x_pm1a_cnt_blk.space_id = 1;
795 fadt->x_pm1a_cnt_blk.bit_width = 16;
796 fadt->x_pm1a_cnt_blk.bit_offset = 0;
797 fadt->x_pm1a_cnt_blk.access_size = ACPI_ACCESS_SIZE_WORD_ACCESS;
798 fadt->x_pm1a_cnt_blk.addrl = pmbase + 0x4;
799 fadt->x_pm1a_cnt_blk.addrh = 0x0;
800
801 fadt->x_pm1b_cnt_blk.space_id = 1;
802 fadt->x_pm1b_cnt_blk.bit_width = 0;
803 fadt->x_pm1b_cnt_blk.bit_offset = 0;
804 fadt->x_pm1b_cnt_blk.access_size = 0;
805 fadt->x_pm1b_cnt_blk.addrl = 0x0;
806 fadt->x_pm1b_cnt_blk.addrh = 0x0;
807
808 fadt->x_pm2_cnt_blk.space_id = 1;
809 fadt->x_pm2_cnt_blk.bit_width = 8;
810 fadt->x_pm2_cnt_blk.bit_offset = 0;
811 fadt->x_pm2_cnt_blk.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
812 fadt->x_pm2_cnt_blk.addrl = pmbase + 0x50;
813 fadt->x_pm2_cnt_blk.addrh = 0x0;
814
815 fadt->x_pm_tmr_blk.space_id = 1;
816 fadt->x_pm_tmr_blk.bit_width = 32;
817 fadt->x_pm_tmr_blk.bit_offset = 0;
818 fadt->x_pm_tmr_blk.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
819 fadt->x_pm_tmr_blk.addrl = pmbase + 0x8;
820 fadt->x_pm_tmr_blk.addrh = 0x0;
821
822 fadt->x_gpe0_blk.space_id = 1;
823 fadt->x_gpe0_blk.bit_width = 128;
824 fadt->x_gpe0_blk.bit_offset = 0;
825 fadt->x_gpe0_blk.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
826 fadt->x_gpe0_blk.addrl = pmbase + 0x20;
827 fadt->x_gpe0_blk.addrh = 0x0;
828
829 fadt->x_gpe1_blk.space_id = 1;
830 fadt->x_gpe1_blk.bit_width = 0;
831 fadt->x_gpe1_blk.bit_offset = 0;
832 fadt->x_gpe1_blk.access_size = 0;
833 fadt->x_gpe1_blk.addrl = 0x0;
834 fadt->x_gpe1_blk.addrh = 0x0;
835}
836
Vladimir Serbinenko36fa5b82014-10-28 23:43:20 +0100837static void southbridge_fill_ssdt(void)
838{
839 device_t dev = dev_find_slot(0, PCI_DEVFN(0x1f,0));
840 config_t *chip = dev->chip_info;
841
842 intel_acpi_pcie_hotplug_generator(chip->pcie_hotplug_map, 8);
843}
844
Stefan Reinauer8e073822012-04-04 00:07:22 +0200845static struct pci_operations pci_ops = {
846 .set_subsystem = set_subsystem,
847};
848
849static struct device_operations device_ops = {
850 .read_resources = pch_lpc_read_resources,
851 .set_resources = pci_dev_set_resources,
852 .enable_resources = pch_lpc_enable_resources,
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +0200853 .write_acpi_tables = acpi_write_hpet,
Vladimir Serbinenko334fd8e2014-10-05 11:10:35 +0200854 .acpi_inject_dsdt_generator = southbridge_inject_dsdt,
Vladimir Serbinenko36fa5b82014-10-28 23:43:20 +0100855 .acpi_fill_ssdt_generator = southbridge_fill_ssdt,
Stefan Reinauer8e073822012-04-04 00:07:22 +0200856 .init = lpc_init,
857 .enable = pch_lpc_enable,
858 .scan_bus = scan_static_bus,
859 .ops_pci = &pci_ops,
860};
861
862
Kimarie Hoote6f459c2012-07-14 08:26:08 -0600863/* IDs for LPC device of Intel 6 Series Chipset, Intel 7 Series Chipset, and
864 * Intel C200 Series Chipset
Stefan Reinauer8e073822012-04-04 00:07:22 +0200865 */
866
Stefan Reinauer9a380ab2012-06-22 13:16:11 -0700867static const unsigned short pci_device_ids[] = { 0x1c46, 0x1c47, 0x1c49, 0x1c4a,
868 0x1c4b, 0x1c4c, 0x1c4d, 0x1c4e,
869 0x1c4f, 0x1c50, 0x1c52, 0x1c54,
Kimarie Hoote6f459c2012-07-14 08:26:08 -0600870 0x1e55, 0x1c56, 0x1e57, 0x1c5c,
871 0x1e5d, 0x1e5e, 0x1e5f,
Stefan Reinauer9a380ab2012-06-22 13:16:11 -0700872 0 };
873
874static const struct pci_driver pch_lpc __pci_driver = {
875 .ops = &device_ops,
876 .vendor = PCI_VENDOR_ID_INTEL,
877 .devices = pci_device_ids,
Stefan Reinauer8e073822012-04-04 00:07:22 +0200878};