blob: 3c559462eec9f8fd6024acf333a1d71c93a9e46f [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;
110 /* Get the chip configuration */
111 config_t *config = dev->chip_info;
112
113 pci_write_config8(dev, PIRQA_ROUT, config->pirqa_routing);
114 pci_write_config8(dev, PIRQB_ROUT, config->pirqb_routing);
115 pci_write_config8(dev, PIRQC_ROUT, config->pirqc_routing);
116 pci_write_config8(dev, PIRQD_ROUT, config->pirqd_routing);
117
118 pci_write_config8(dev, PIRQE_ROUT, config->pirqe_routing);
119 pci_write_config8(dev, PIRQF_ROUT, config->pirqf_routing);
120 pci_write_config8(dev, PIRQG_ROUT, config->pirqg_routing);
121 pci_write_config8(dev, PIRQH_ROUT, config->pirqh_routing);
122
123 /* Eric Biederman once said we should let the OS do this.
124 * I am not so sure anymore he was right.
125 */
126
127 for(irq_dev = all_devices; irq_dev; irq_dev = irq_dev->next) {
128 u8 int_pin=0, int_line=0;
129
130 if (!irq_dev->enabled || irq_dev->path.type != DEVICE_PATH_PCI)
131 continue;
132
133 int_pin = pci_read_config8(irq_dev, PCI_INTERRUPT_PIN);
134
135 switch (int_pin) {
136 case 1: /* INTA# */ int_line = config->pirqa_routing; break;
137 case 2: /* INTB# */ int_line = config->pirqb_routing; break;
138 case 3: /* INTC# */ int_line = config->pirqc_routing; break;
139 case 4: /* INTD# */ int_line = config->pirqd_routing; break;
140 }
141
142 if (!int_line)
143 continue;
144
145 pci_write_config8(irq_dev, PCI_INTERRUPT_LINE, int_line);
146 }
147}
148
149static void pch_gpi_routing(device_t dev)
150{
151 /* Get the chip configuration */
152 config_t *config = dev->chip_info;
153 u32 reg32 = 0;
154
155 /* An array would be much nicer here, or some
156 * other method of doing this.
157 */
158 reg32 |= (config->gpi0_routing & 0x03) << 0;
159 reg32 |= (config->gpi1_routing & 0x03) << 2;
160 reg32 |= (config->gpi2_routing & 0x03) << 4;
161 reg32 |= (config->gpi3_routing & 0x03) << 6;
162 reg32 |= (config->gpi4_routing & 0x03) << 8;
163 reg32 |= (config->gpi5_routing & 0x03) << 10;
164 reg32 |= (config->gpi6_routing & 0x03) << 12;
165 reg32 |= (config->gpi7_routing & 0x03) << 14;
166 reg32 |= (config->gpi8_routing & 0x03) << 16;
167 reg32 |= (config->gpi9_routing & 0x03) << 18;
168 reg32 |= (config->gpi10_routing & 0x03) << 20;
169 reg32 |= (config->gpi11_routing & 0x03) << 22;
170 reg32 |= (config->gpi12_routing & 0x03) << 24;
171 reg32 |= (config->gpi13_routing & 0x03) << 26;
172 reg32 |= (config->gpi14_routing & 0x03) << 28;
173 reg32 |= (config->gpi15_routing & 0x03) << 30;
174
175 pci_write_config32(dev, 0xb8, reg32);
176}
177
178static void pch_power_options(device_t dev)
179{
180 u8 reg8;
181 u16 reg16, pmbase;
182 u32 reg32;
183 const char *state;
184 /* Get the chip configuration */
185 config_t *config = dev->chip_info;
186
187 int pwr_on=CONFIG_MAINBOARD_POWER_ON_AFTER_POWER_FAIL;
188 int nmi_option;
189
190 /* Which state do we want to goto after g3 (power restored)?
191 * 0 == S0 Full On
192 * 1 == S5 Soft Off
193 *
194 * If the option is not existent (Laptops), use Kconfig setting.
195 */
196 get_option(&pwr_on, "power_on_after_fail");
197
198 reg16 = pci_read_config16(dev, GEN_PMCON_3);
199 reg16 &= 0xfffe;
200 switch (pwr_on) {
201 case MAINBOARD_POWER_OFF:
202 reg16 |= 1;
203 state = "off";
204 break;
205 case MAINBOARD_POWER_ON:
206 reg16 &= ~1;
207 state = "on";
208 break;
209 case MAINBOARD_POWER_KEEP:
210 reg16 &= ~1;
211 state = "state keep";
212 break;
213 default:
214 state = "undefined";
215 }
216
217 reg16 &= ~(3 << 4); /* SLP_S4# Assertion Stretch 4s */
218 reg16 |= (1 << 3); /* SLP_S4# Assertion Stretch Enable */
219
220 reg16 &= ~(1 << 10);
221 reg16 |= (1 << 11); /* SLP_S3# Min Assertion Width 50ms */
222
223 reg16 |= (1 << 12); /* Disable SLP stretch after SUS well */
224
225 pci_write_config16(dev, GEN_PMCON_3, reg16);
226 printk(BIOS_INFO, "Set power %s after power failure.\n", state);
227
228 /* Set up NMI on errors. */
229 reg8 = inb(0x61);
230 reg8 &= 0x0f; /* Higher Nibble must be 0 */
231 reg8 &= ~(1 << 3); /* IOCHK# NMI Enable */
232 // reg8 &= ~(1 << 2); /* PCI SERR# Enable */
233 reg8 |= (1 << 2); /* PCI SERR# Disable for now */
234 outb(reg8, 0x61);
235
236 reg8 = inb(0x70);
237 nmi_option = NMI_OFF;
238 get_option(&nmi_option, "nmi");
239 if (nmi_option) {
240 printk(BIOS_INFO, "NMI sources enabled.\n");
241 reg8 &= ~(1 << 7); /* Set NMI. */
242 } else {
243 printk(BIOS_INFO, "NMI sources disabled.\n");
244 reg8 |= ( 1 << 7); /* Can't mask NMI from PCI-E and NMI_NOW */
245 }
246 outb(reg8, 0x70);
247
248 /* Enable CPU_SLP# and Intel Speedstep, set SMI# rate down */
249 reg16 = pci_read_config16(dev, GEN_PMCON_1);
250 reg16 &= ~(3 << 0); // SMI# rate 1 minute
251 reg16 &= ~(1 << 10); // Disable BIOS_PCI_EXP_EN for native PME
252#if DEBUG_PERIODIC_SMIS
253 /* Set DEBUG_PERIODIC_SMIS in pch.h to debug using
254 * periodic SMIs.
255 */
256 reg16 |= (3 << 0); // Periodic SMI every 8s
257#endif
258 pci_write_config16(dev, GEN_PMCON_1, reg16);
259
260 // Set the board's GPI routing.
261 pch_gpi_routing(dev);
262
263 pmbase = pci_read_config16(dev, 0x40) & 0xfffe;
264
265 outl(config->gpe0_en, pmbase + GPE0_EN);
266 outw(config->alt_gp_smi_en, pmbase + ALT_GP_SMI_EN);
267
268 /* Set up power management block and determine sleep mode */
269 reg32 = inl(pmbase + 0x04); // PM1_CNT
270 reg32 &= ~(7 << 10); // SLP_TYP
271 reg32 |= (1 << 0); // SCI_EN
272 outl(reg32, pmbase + 0x04);
273
274 /* Clear magic status bits to prevent unexpected wake */
275 reg32 = RCBA32(0x3310);
276 reg32 |= (1 << 4)|(1 << 5)|(1 << 0);
277 RCBA32(0x3310) = reg32;
278
279 reg32 = RCBA32(0x3f02);
280 reg32 &= ~0xf;
281 RCBA32(0x3f02) = reg32;
282}
283
284static void pch_rtc_init(struct device *dev)
285{
286 u8 reg8;
287 int rtc_failed;
288
289 reg8 = pci_read_config8(dev, GEN_PMCON_3);
290 rtc_failed = reg8 & RTC_BATTERY_DEAD;
291 if (rtc_failed) {
292 reg8 &= ~RTC_BATTERY_DEAD;
293 pci_write_config8(dev, GEN_PMCON_3, reg8);
Duncan Laurie800e9502012-06-23 17:06:47 -0700294#if CONFIG_ELOG
295 elog_add_event(ELOG_TYPE_RTC_RESET);
296#endif
Stefan Reinauer8e073822012-04-04 00:07:22 +0200297 }
298 printk(BIOS_DEBUG, "rtc_failed = 0x%x\n", rtc_failed);
299
Gabe Blackb3f08c62014-04-30 17:12:25 -0700300 cmos_init(rtc_failed);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200301}
302
Duncan Laurie3f6a4d72012-06-28 13:03:40 -0700303/* CougarPoint PCH Power Management init */
304static void cpt_pm_init(struct device *dev)
Stefan Reinauer8e073822012-04-04 00:07:22 +0200305{
Duncan Laurie3f6a4d72012-06-28 13:03:40 -0700306 printk(BIOS_DEBUG, "CougarPoint PM init\n");
Stefan Reinauer8e073822012-04-04 00:07:22 +0200307 pci_write_config8(dev, 0xa9, 0x47);
308 RCBA32_AND_OR(0x2238, ~0UL, (1 << 6)|(1 << 0));
309 RCBA32_AND_OR(0x228c, ~0UL, (1 << 0));
310 RCBA16_AND_OR(0x1100, ~0UL, (1 << 13)|(1 << 14));
311 RCBA16_AND_OR(0x0900, ~0UL, (1 << 14));
312 RCBA32(0x2304) = 0xc0388400;
313 RCBA32_AND_OR(0x2314, ~0UL, (1 << 5)|(1 << 18));
314 RCBA32_AND_OR(0x2320, ~0UL, (1 << 15)|(1 << 1));
315 RCBA32_AND_OR(0x3314, ~0x1f, 0xf);
316 RCBA32(0x3318) = 0x050f0000;
317 RCBA32(0x3324) = 0x04000000;
318 RCBA32_AND_OR(0x3340, ~0UL, 0xfffff);
319 RCBA32_AND_OR(0x3344, ~0UL, (1 << 1));
320 RCBA32(0x3360) = 0x0001c000;
321 RCBA32(0x3368) = 0x00061100;
322 RCBA32(0x3378) = 0x7f8fdfff;
323 RCBA32(0x337c) = 0x000003fc;
324 RCBA32(0x3388) = 0x00001000;
325 RCBA32(0x3390) = 0x0001c000;
326 RCBA32(0x33a0) = 0x00000800;
327 RCBA32(0x33b0) = 0x00001000;
328 RCBA32(0x33c0) = 0x00093900;
329 RCBA32(0x33cc) = 0x24653002;
330 RCBA32(0x33d0) = 0x062108fe;
331 RCBA32_AND_OR(0x33d4, 0xf000f000, 0x00670060);
332 RCBA32(0x3a28) = 0x01010000;
333 RCBA32(0x3a2c) = 0x01010404;
334 RCBA32(0x3a80) = 0x01041041;
335 RCBA32_AND_OR(0x3a84, ~0x0000ffff, 0x00001001);
336 RCBA32_AND_OR(0x3a84, ~0UL, (1 << 24)); /* SATA 2/3 disabled */
337 RCBA32_AND_OR(0x3a88, ~0UL, (1 << 0)); /* SATA 4/5 disabled */
338 RCBA32(0x3a6c) = 0x00000001;
339 RCBA32_AND_OR(0x2344, 0x00ffff00, 0xff00000c);
340 RCBA32_AND_OR(0x80c, ~(0xff << 20), 0x11 << 20);
341 RCBA32(0x33c8) = 0;
342 RCBA32_AND_OR(0x21b0, ~0UL, 0xf);
343}
344
Duncan Laurie3f6a4d72012-06-28 13:03:40 -0700345/* PantherPoint PCH Power Management init */
346static void ppt_pm_init(struct device *dev)
347{
348 printk(BIOS_DEBUG, "PantherPoint PM init\n");
349 pci_write_config8(dev, 0xa9, 0x47);
350 RCBA32_AND_OR(0x2238, ~0UL, (1 << 0));
351 RCBA32_AND_OR(0x228c, ~0UL, (1 << 0));
352 RCBA16_AND_OR(0x1100, ~0UL, (1 << 13)|(1 << 14));
353 RCBA16_AND_OR(0x0900, ~0UL, (1 << 14));
354 RCBA32(0x2304) = 0xc03b8400;
355 RCBA32_AND_OR(0x2314, ~0UL, (1 << 5)|(1 << 18));
356 RCBA32_AND_OR(0x2320, ~0UL, (1 << 15)|(1 << 1));
357 RCBA32_AND_OR(0x3314, ~0x1f, 0xf);
358 RCBA32(0x3318) = 0x054f0000;
359 RCBA32(0x3324) = 0x04000000;
360 RCBA32_AND_OR(0x3340, ~0UL, 0xfffff);
361 RCBA32_AND_OR(0x3344, ~0UL, (1 << 1)|(1 << 0));
362 RCBA32(0x3360) = 0x0001c000;
363 RCBA32(0x3368) = 0x00061100;
364 RCBA32(0x3378) = 0x7f8fdfff;
365 RCBA32(0x337c) = 0x000003fd;
366 RCBA32(0x3388) = 0x00001000;
367 RCBA32(0x3390) = 0x0001c000;
368 RCBA32(0x33a0) = 0x00000800;
369 RCBA32(0x33b0) = 0x00001000;
370 RCBA32(0x33c0) = 0x00093900;
371 RCBA32(0x33cc) = 0x24653002;
372 RCBA32(0x33d0) = 0x067388fe;
373 RCBA32_AND_OR(0x33d4, 0xf000f000, 0x00670060);
374 RCBA32(0x3a28) = 0x01010000;
375 RCBA32(0x3a2c) = 0x01010404;
376 RCBA32(0x3a80) = 0x01040000;
377 RCBA32_AND_OR(0x3a84, ~0x0000ffff, 0x00001001);
378 RCBA32_AND_OR(0x3a84, ~0UL, (1 << 24)); /* SATA 2/3 disabled */
379 RCBA32_AND_OR(0x3a88, ~0UL, (1 << 0)); /* SATA 4/5 disabled */
380 RCBA32(0x3a6c) = 0x00000001;
381 RCBA32_AND_OR(0x2344, 0x00ffff00, 0xff00000c);
382 RCBA32_AND_OR(0x80c, ~(0xff << 20), 0x11 << 20);
383 RCBA32_AND_OR(0x33a4, ~0UL, (1 << 0));
384 RCBA32(0x33c8) = 0;
385 RCBA32_AND_OR(0x21b0, ~0UL, 0xf);
386}
387
Stefan Reinauer8e073822012-04-04 00:07:22 +0200388static void enable_hpet(void)
389{
390 u32 reg32;
391
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
399static void enable_clock_gating(device_t dev)
400{
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
435#if CONFIG_HAVE_SMI_HANDLER
436static void pch_lock_smm(struct device *dev)
437{
438#if TEST_SMM_FLASH_LOCKDOWN
439 u8 reg8;
440#endif
441
Kyösti Mälkkic3ed8862014-06-19 19:50:51 +0300442 if (!acpi_is_wakeup_s3()) {
Stefan Reinauer8e073822012-04-04 00:07:22 +0200443#if ENABLE_ACPI_MODE_IN_COREBOOT
Duncan Laurie95be1d62012-04-09 12:31:43 -0700444 printk(BIOS_DEBUG, "Enabling ACPI via APMC:\n");
445 outb(0xe1, 0xb2); // Enable ACPI mode
446 printk(BIOS_DEBUG, "done.\n");
Stefan Reinauer8e073822012-04-04 00:07:22 +0200447#else
Duncan Laurie95be1d62012-04-09 12:31:43 -0700448 printk(BIOS_DEBUG, "Disabling ACPI via APMC:\n");
449 outb(0x1e, 0xb2); // Disable ACPI mode
450 printk(BIOS_DEBUG, "done.\n");
Stefan Reinauer8e073822012-04-04 00:07:22 +0200451#endif
Duncan Laurie95be1d62012-04-09 12:31:43 -0700452 }
453
Stefan Reinauer8e073822012-04-04 00:07:22 +0200454 /* Don't allow evil boot loaders, kernels, or
455 * userspace applications to deceive us:
456 */
457 smm_lock();
458
459#if TEST_SMM_FLASH_LOCKDOWN
460 /* Now try this: */
461 printk(BIOS_DEBUG, "Locking BIOS to RO... ");
462 reg8 = pci_read_config8(dev, 0xdc); /* BIOS_CNTL */
463 printk(BIOS_DEBUG, " BLE: %s; BWE: %s\n", (reg8&2)?"on":"off",
464 (reg8&1)?"rw":"ro");
465 reg8 &= ~(1 << 0); /* clear BIOSWE */
466 pci_write_config8(dev, 0xdc, reg8);
467 reg8 |= (1 << 1); /* set BLE */
468 pci_write_config8(dev, 0xdc, reg8);
469 printk(BIOS_DEBUG, "ok.\n");
470 reg8 = pci_read_config8(dev, 0xdc); /* BIOS_CNTL */
471 printk(BIOS_DEBUG, " BLE: %s; BWE: %s\n", (reg8&2)?"on":"off",
472 (reg8&1)?"rw":"ro");
473
474 printk(BIOS_DEBUG, "Writing:\n");
475 *(volatile u8 *)0xfff00000 = 0x00;
476 printk(BIOS_DEBUG, "Testing:\n");
477 reg8 |= (1 << 0); /* set BIOSWE */
478 pci_write_config8(dev, 0xdc, reg8);
479
480 reg8 = pci_read_config8(dev, 0xdc); /* BIOS_CNTL */
481 printk(BIOS_DEBUG, " BLE: %s; BWE: %s\n", (reg8&2)?"on":"off",
482 (reg8&1)?"rw":"ro");
483 printk(BIOS_DEBUG, "Done.\n");
484#endif
485}
486#endif
487
488static void pch_disable_smm_only_flashing(struct device *dev)
489{
490 u8 reg8;
491
492 printk(BIOS_SPEW, "Enabling BIOS updates outside of SMM... ");
493 reg8 = pci_read_config8(dev, 0xdc); /* BIOS_CNTL */
494 reg8 &= ~(1 << 5);
495 pci_write_config8(dev, 0xdc, reg8);
496}
497
498static void pch_fixups(struct device *dev)
499{
500 u8 gen_pmcon_2;
501
502 /* Indicate DRAM init done for MRC S3 to know it can resume */
503 gen_pmcon_2 = pci_read_config8(dev, GEN_PMCON_2);
504 gen_pmcon_2 |= (1 << 7);
505 pci_write_config8(dev, GEN_PMCON_2, gen_pmcon_2);
506
507 /*
508 * Enable DMI ASPM in the PCH
509 */
510 RCBA32_AND_OR(0x2304, ~(1 << 10), 0);
511 RCBA32_OR(0x21a4, (1 << 11)|(1 << 10));
512 RCBA32_OR(0x21a8, 0x3);
513}
514
515static void pch_decode_init(struct device *dev)
516{
517 config_t *config = dev->chip_info;
518
519 printk(BIOS_DEBUG, "pch_decode_init\n");
520
521 pci_write_config32(dev, LPC_GEN1_DEC, config->gen1_dec);
522 pci_write_config32(dev, LPC_GEN2_DEC, config->gen2_dec);
523 pci_write_config32(dev, LPC_GEN3_DEC, config->gen3_dec);
524 pci_write_config32(dev, LPC_GEN4_DEC, config->gen4_dec);
525}
526
527static void lpc_init(struct device *dev)
528{
529 printk(BIOS_DEBUG, "pch: lpc_init\n");
530
531 /* Set the value for PCI command register. */
532 pci_write_config16(dev, PCI_COMMAND, 0x000f);
533
534 /* IO APIC initialization. */
Paul Menzel9c50e6a2013-05-03 12:23:39 +0200535 pch_enable_ioapic(dev);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200536
537 pch_enable_serial_irqs(dev);
538
539 /* Setup the PIRQ. */
540 pch_pirq_init(dev);
541
542 /* Setup power options. */
543 pch_power_options(dev);
544
545 /* Initialize power management */
Duncan Laurie3f6a4d72012-06-28 13:03:40 -0700546 switch (pch_silicon_type()) {
547 case PCH_TYPE_CPT: /* CougarPoint */
548 cpt_pm_init(dev);
549 break;
550 case PCH_TYPE_PPT: /* PantherPoint */
551 ppt_pm_init(dev);
552 break;
553 default:
554 printk(BIOS_ERR, "Unknown Chipset: 0x%04x\n", dev->device);
555 }
Stefan Reinauer8e073822012-04-04 00:07:22 +0200556
557 /* Set the state of the GPIO lines. */
558 //gpio_init(dev);
559
560 /* Initialize the real time clock. */
561 pch_rtc_init(dev);
562
563 /* Initialize ISA DMA. */
564 isa_dma_init();
565
566 /* Initialize the High Precision Event Timers, if present. */
567 enable_hpet();
568
569 /* Initialize Clock Gating */
570 enable_clock_gating(dev);
571
572 setup_i8259();
573
574 /* The OS should do this? */
575 /* Interrupt 9 should be level triggered (SCI) */
576 i8259_configure_irq_trigger(9, 1);
577
578 pch_disable_smm_only_flashing(dev);
579
580#if CONFIG_HAVE_SMI_HANDLER
581 pch_lock_smm(dev);
582#endif
583
584 pch_fixups(dev);
585}
586
587static void pch_lpc_read_resources(device_t dev)
588{
589 struct resource *res;
Marc Jonesa0bec172012-07-13 14:14:34 -0600590 config_t *config = dev->chip_info;
591 u8 io_index = 0;
Stefan Reinauer8e073822012-04-04 00:07:22 +0200592
593 /* Get the normal PCI resources of this device. */
594 pci_dev_read_resources(dev);
595
596 /* Add an extra subtractive resource for both memory and I/O. */
Marc Jonesa0bec172012-07-13 14:14:34 -0600597 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
Stefan Reinauer8e073822012-04-04 00:07:22 +0200598 res->base = 0;
599 res->size = 0x1000;
600 res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
601 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
602
Marc Jonesa0bec172012-07-13 14:14:34 -0600603 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
Vladimir Serbinenko0650cd02014-02-05 15:03:50 +0100604 res->base = 0xff000000;
605 /* Some systems (e.g. X230) have 12 MiB flash.
606 SPI controller supports up to 2 x 16 MiB of flash but
607 address map limits this to 16MiB. */
608 res->size = 0x01000000; /* 16 MB for flash */
Stefan Reinauer8e073822012-04-04 00:07:22 +0200609 res->flags = IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE |
610 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
611
612 res = new_resource(dev, 3); /* IOAPIC */
613 res->base = IO_APIC_ADDR;
614 res->size = 0x00001000;
615 res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
Marc Jonesa0bec172012-07-13 14:14:34 -0600616
617 /* Set PCH IO decode ranges if required.*/
618 if ((config->gen1_dec & 0xFFFC) > 0x1000) {
619 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
620 res->base = config->gen1_dec & 0xFFFC;
621 res->size = (config->gen1_dec >> 16) & 0xFC;
622 res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
623 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
624 }
625
626 if ((config->gen2_dec & 0xFFFC) > 0x1000) {
627 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
628 res->base = config->gen2_dec & 0xFFFC;
629 res->size = (config->gen2_dec >> 16) & 0xFC;
630 res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
631 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
632 }
633
634 if ((config->gen3_dec & 0xFFFC) > 0x1000) {
635 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
636 res->base = config->gen3_dec & 0xFFFC;
637 res->size = (config->gen3_dec >> 16) & 0xFC;
638 res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
639 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
640 }
641
642 if ((config->gen4_dec & 0xFFFC) > 0x1000) {
643 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
644 res->base = config->gen4_dec & 0xFFFC;
645 res->size = (config->gen4_dec >> 16) & 0xFC;
646 res->flags = IORESOURCE_IO| IORESOURCE_SUBTRACTIVE |
647 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
648 }
Stefan Reinauer8e073822012-04-04 00:07:22 +0200649}
650
651static void pch_lpc_enable_resources(device_t dev)
652{
653 pch_decode_init(dev);
654 return pci_dev_enable_resources(dev);
655}
656
657static void pch_lpc_enable(device_t dev)
658{
659 /* Enable PCH Display Port */
660 RCBA16(DISPBDF) = 0x0010;
661 RCBA32_OR(FD2, PCH_ENABLE_DBDF);
662
663 pch_enable(dev);
664}
665
666static void set_subsystem(device_t dev, unsigned vendor, unsigned device)
667{
668 if (!vendor || !device) {
669 pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
670 pci_read_config32(dev, PCI_VENDOR_ID));
671 } else {
672 pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
673 ((device & 0xffff) << 16) | (vendor & 0xffff));
674 }
675}
676
Vladimir Serbinenko334fd8e2014-10-05 11:10:35 +0200677static void southbridge_inject_dsdt(void)
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +0200678{
679 global_nvs_t *gnvs = cbmem_add (CBMEM_ID_ACPI_GNVS, sizeof (*gnvs));
680 void *opregion;
681
682 /* Calling northbridge code as gnvs contains opregion address. */
683 opregion = igd_make_opregion();
684
685 if (gnvs) {
Vladimir Serbinenko7309c642014-10-05 11:07:33 +0200686 memset(gnvs, 0, sizeof (*gnvs));
687
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +0200688 acpi_create_gnvs(gnvs);
Vladimir Serbinenko06c788d2014-10-12 00:17:11 +0200689
690 gnvs->apic = 1;
691 gnvs->mpen = 1; /* Enable Multi Processing */
692 gnvs->pcnt = dev_count_cpu();
693
694#if CONFIG_CHROMEOS
695 chromeos_init_vboot(&(gnvs->chromeos));
696#endif
697
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +0200698 /* IGD OpRegion Base Address */
699 gnvs->aslb = (u32)opregion;
700 /* And tell SMI about it */
701 smm_setup_structures(gnvs, NULL, NULL);
702
Vladimir Serbinenko334fd8e2014-10-05 11:10:35 +0200703 /* Add it to DSDT. */
Vladimir Serbinenko226d7842014-11-04 21:09:23 +0100704 acpigen_write_scope("\\");
705 acpigen_write_name_dword("NVSA", (u32) gnvs);
706 acpigen_pop_len();
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +0200707 }
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +0200708}
709
Vladimir Serbinenko5b044ae2014-10-25 15:20:55 +0200710void acpi_fill_fadt(acpi_fadt_t *fadt)
711{
712 device_t dev = dev_find_slot(0, PCI_DEVFN(0x1f,0));
713 config_t *chip = dev->chip_info;
714 u16 pmbase = pci_read_config16(dev, 0x40) & 0xfffe;
715 int c2_latency;
716
717 fadt->model = 1;
718
719 fadt->sci_int = 0x9;
720 fadt->smi_cmd = APM_CNT;
721 fadt->acpi_enable = APM_CNT_ACPI_ENABLE;
722 fadt->acpi_disable = APM_CNT_ACPI_DISABLE;
723 fadt->s4bios_req = 0x0;
724 fadt->pstate_cnt = 0;
725
726 fadt->pm1a_evt_blk = pmbase;
727 fadt->pm1b_evt_blk = 0x0;
728 fadt->pm1a_cnt_blk = pmbase + 0x4;
729 fadt->pm1b_cnt_blk = 0x0;
730 fadt->pm2_cnt_blk = pmbase + 0x50;
731 fadt->pm_tmr_blk = pmbase + 0x8;
732 fadt->gpe0_blk = pmbase + 0x20;
733 fadt->gpe1_blk = 0;
734
735 fadt->pm1_evt_len = 4;
736 fadt->pm1_cnt_len = 2;
737 fadt->pm2_cnt_len = 1;
738 fadt->pm_tmr_len = 4;
739 fadt->gpe0_blk_len = 16;
740 fadt->gpe1_blk_len = 0;
741 fadt->gpe1_base = 0;
742 fadt->cst_cnt = 0;
743 c2_latency = chip->c2_latency;
744 if (!c2_latency) {
745 c2_latency = 101; /* c2 unsupported */
746 }
747 fadt->p_lvl2_lat = c2_latency;
748 fadt->p_lvl3_lat = 87;
749 fadt->flush_size = 1024;
750 fadt->flush_stride = 16;
751 fadt->duty_offset = 1;
752 if (chip->p_cnt_throttling_supported) {
753 fadt->duty_width = 3;
754 } else {
755 fadt->duty_width = 0;
756 }
757 fadt->day_alrm = 0xd;
758 fadt->mon_alrm = 0x00;
759 fadt->century = 0x00;
760 fadt->iapc_boot_arch = ACPI_FADT_LEGACY_DEVICES | ACPI_FADT_8042;
761
762 fadt->flags = ACPI_FADT_WBINVD |
763 ACPI_FADT_C1_SUPPORTED |
764 ACPI_FADT_SLEEP_BUTTON |
765 ACPI_FADT_RESET_REGISTER |
766 ACPI_FADT_SEALED_CASE |
767 ACPI_FADT_S4_RTC_WAKE |
768 ACPI_FADT_PLATFORM_CLOCK;
769 if (chip->docking_supported) {
770 fadt->flags |= ACPI_FADT_DOCKING_SUPPORTED;
771 }
772 if (c2_latency < 100) {
773 fadt->flags |= ACPI_FADT_C2_MP_SUPPORTED;
774 }
775
776 fadt->reset_reg.space_id = 1;
777 fadt->reset_reg.bit_width = 8;
778 fadt->reset_reg.bit_offset = 0;
779 fadt->reset_reg.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
780 fadt->reset_reg.addrl = 0xcf9;
781 fadt->reset_reg.addrh = 0;
782
783 fadt->reset_value = 6;
784
785 fadt->x_pm1a_evt_blk.space_id = 1;
786 fadt->x_pm1a_evt_blk.bit_width = 32;
787 fadt->x_pm1a_evt_blk.bit_offset = 0;
788 fadt->x_pm1a_evt_blk.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
789 fadt->x_pm1a_evt_blk.addrl = pmbase;
790 fadt->x_pm1a_evt_blk.addrh = 0x0;
791
792 fadt->x_pm1b_evt_blk.space_id = 1;
793 fadt->x_pm1b_evt_blk.bit_width = 0;
794 fadt->x_pm1b_evt_blk.bit_offset = 0;
795 fadt->x_pm1b_evt_blk.access_size = 0;
796 fadt->x_pm1b_evt_blk.addrl = 0x0;
797 fadt->x_pm1b_evt_blk.addrh = 0x0;
798
799 fadt->x_pm1a_cnt_blk.space_id = 1;
800 fadt->x_pm1a_cnt_blk.bit_width = 16;
801 fadt->x_pm1a_cnt_blk.bit_offset = 0;
802 fadt->x_pm1a_cnt_blk.access_size = ACPI_ACCESS_SIZE_WORD_ACCESS;
803 fadt->x_pm1a_cnt_blk.addrl = pmbase + 0x4;
804 fadt->x_pm1a_cnt_blk.addrh = 0x0;
805
806 fadt->x_pm1b_cnt_blk.space_id = 1;
807 fadt->x_pm1b_cnt_blk.bit_width = 0;
808 fadt->x_pm1b_cnt_blk.bit_offset = 0;
809 fadt->x_pm1b_cnt_blk.access_size = 0;
810 fadt->x_pm1b_cnt_blk.addrl = 0x0;
811 fadt->x_pm1b_cnt_blk.addrh = 0x0;
812
813 fadt->x_pm2_cnt_blk.space_id = 1;
814 fadt->x_pm2_cnt_blk.bit_width = 8;
815 fadt->x_pm2_cnt_blk.bit_offset = 0;
816 fadt->x_pm2_cnt_blk.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
817 fadt->x_pm2_cnt_blk.addrl = pmbase + 0x50;
818 fadt->x_pm2_cnt_blk.addrh = 0x0;
819
820 fadt->x_pm_tmr_blk.space_id = 1;
821 fadt->x_pm_tmr_blk.bit_width = 32;
822 fadt->x_pm_tmr_blk.bit_offset = 0;
823 fadt->x_pm_tmr_blk.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
824 fadt->x_pm_tmr_blk.addrl = pmbase + 0x8;
825 fadt->x_pm_tmr_blk.addrh = 0x0;
826
827 fadt->x_gpe0_blk.space_id = 1;
828 fadt->x_gpe0_blk.bit_width = 128;
829 fadt->x_gpe0_blk.bit_offset = 0;
830 fadt->x_gpe0_blk.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
831 fadt->x_gpe0_blk.addrl = pmbase + 0x20;
832 fadt->x_gpe0_blk.addrh = 0x0;
833
834 fadt->x_gpe1_blk.space_id = 1;
835 fadt->x_gpe1_blk.bit_width = 0;
836 fadt->x_gpe1_blk.bit_offset = 0;
837 fadt->x_gpe1_blk.access_size = 0;
838 fadt->x_gpe1_blk.addrl = 0x0;
839 fadt->x_gpe1_blk.addrh = 0x0;
840}
841
Vladimir Serbinenko36fa5b82014-10-28 23:43:20 +0100842static void southbridge_fill_ssdt(void)
843{
844 device_t dev = dev_find_slot(0, PCI_DEVFN(0x1f,0));
845 config_t *chip = dev->chip_info;
846
847 intel_acpi_pcie_hotplug_generator(chip->pcie_hotplug_map, 8);
848}
849
Stefan Reinauer8e073822012-04-04 00:07:22 +0200850static struct pci_operations pci_ops = {
851 .set_subsystem = set_subsystem,
852};
853
854static struct device_operations device_ops = {
855 .read_resources = pch_lpc_read_resources,
856 .set_resources = pci_dev_set_resources,
857 .enable_resources = pch_lpc_enable_resources,
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +0200858 .write_acpi_tables = acpi_write_hpet,
Vladimir Serbinenko334fd8e2014-10-05 11:10:35 +0200859 .acpi_inject_dsdt_generator = southbridge_inject_dsdt,
Vladimir Serbinenko36fa5b82014-10-28 23:43:20 +0100860 .acpi_fill_ssdt_generator = southbridge_fill_ssdt,
Stefan Reinauer8e073822012-04-04 00:07:22 +0200861 .init = lpc_init,
862 .enable = pch_lpc_enable,
863 .scan_bus = scan_static_bus,
864 .ops_pci = &pci_ops,
865};
866
867
Kimarie Hoote6f459c2012-07-14 08:26:08 -0600868/* IDs for LPC device of Intel 6 Series Chipset, Intel 7 Series Chipset, and
869 * Intel C200 Series Chipset
Stefan Reinauer8e073822012-04-04 00:07:22 +0200870 */
871
Stefan Reinauer9a380ab2012-06-22 13:16:11 -0700872static const unsigned short pci_device_ids[] = { 0x1c46, 0x1c47, 0x1c49, 0x1c4a,
873 0x1c4b, 0x1c4c, 0x1c4d, 0x1c4e,
874 0x1c4f, 0x1c50, 0x1c52, 0x1c54,
Kimarie Hoote6f459c2012-07-14 08:26:08 -0600875 0x1e55, 0x1c56, 0x1e57, 0x1c5c,
876 0x1e5d, 0x1e5e, 0x1e5f,
Stefan Reinauer9a380ab2012-06-22 13:16:11 -0700877 0 };
878
879static const struct pci_driver pch_lpc __pci_driver = {
880 .ops = &device_ops,
881 .vendor = PCI_VENDOR_ID_INTEL,
882 .devices = pci_device_ids,
Stefan Reinauer8e073822012-04-04 00:07:22 +0200883};