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