blob: a1c7c2a289c23a5647e960180dcbe86751cf14c9 [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>
35#include <cbmem.h>
Vladimir Serbinenko7309c642014-10-05 11:07:33 +020036#include <string.h>
Stefan Reinauer8e073822012-04-04 00:07:22 +020037#include "pch.h"
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +020038#include "nvs.h"
Stefan Reinauer8e073822012-04-04 00:07:22 +020039
40#define NMI_OFF 0
41
42#define ENABLE_ACPI_MODE_IN_COREBOOT 0
43#define TEST_SMM_FLASH_LOCKDOWN 0
44
45typedef struct southbridge_intel_bd82x6x_config config_t;
46
Paul Menzel9c50e6a2013-05-03 12:23:39 +020047/**
48 * Set miscellanous static southbridge features.
49 *
50 * @param dev PCI device with I/O APIC control registers
51 */
52static void pch_enable_ioapic(struct device *dev)
Stefan Reinauer8e073822012-04-04 00:07:22 +020053{
Stefan Reinauer8e073822012-04-04 00:07:22 +020054 u32 reg32;
Stefan Reinauer8e073822012-04-04 00:07:22 +020055
Paul Menzel9c50e6a2013-05-03 12:23:39 +020056 /* Enable ACPI I/O range decode */
57 pci_write_config8(dev, ACPI_CNTL, ACPI_EN);
Stefan Reinauer8e073822012-04-04 00:07:22 +020058
Paul Menzel9c50e6a2013-05-03 12:23:39 +020059 set_ioapic_id(IO_APIC_ADDR, 0x02);
Stefan Reinauer8e073822012-04-04 00:07:22 +020060
61 /* affirm full set of redirection table entries ("write once") */
Paul Menzel9c50e6a2013-05-03 12:23:39 +020062 reg32 = io_apic_read(IO_APIC_ADDR, 0x01);
63 io_apic_write(IO_APIC_ADDR, 0x01, reg32);
Stefan Reinauer8e073822012-04-04 00:07:22 +020064
Paul Menzel9c50e6a2013-05-03 12:23:39 +020065 /*
66 * Select Boot Configuration register (0x03) and
67 * use Processor System Bus (0x01) to deliver interrupts.
68 */
69 io_apic_write(IO_APIC_ADDR, 0x03, 0x01);
Stefan Reinauer8e073822012-04-04 00:07:22 +020070}
71
72static void pch_enable_serial_irqs(struct device *dev)
73{
74 /* Set packet length and toggle silent mode bit for one frame. */
75 pci_write_config8(dev, SERIRQ_CNTL,
76 (1 << 7) | (1 << 6) | ((21 - 17) << 2) | (0 << 0));
77#if !CONFIG_SERIRQ_CONTINUOUS_MODE
78 pci_write_config8(dev, SERIRQ_CNTL,
79 (1 << 7) | (0 << 6) | ((21 - 17) << 2) | (0 << 0));
80#endif
81}
82
83/* PIRQ[n]_ROUT[3:0] - PIRQ Routing Control
84 * 0x00 - 0000 = Reserved
85 * 0x01 - 0001 = Reserved
86 * 0x02 - 0010 = Reserved
87 * 0x03 - 0011 = IRQ3
88 * 0x04 - 0100 = IRQ4
89 * 0x05 - 0101 = IRQ5
90 * 0x06 - 0110 = IRQ6
91 * 0x07 - 0111 = IRQ7
92 * 0x08 - 1000 = Reserved
93 * 0x09 - 1001 = IRQ9
94 * 0x0A - 1010 = IRQ10
95 * 0x0B - 1011 = IRQ11
96 * 0x0C - 1100 = IRQ12
97 * 0x0D - 1101 = Reserved
98 * 0x0E - 1110 = IRQ14
99 * 0x0F - 1111 = IRQ15
100 * PIRQ[n]_ROUT[7] - PIRQ Routing Control
101 * 0x80 - The PIRQ is not routed.
102 */
103
104static void pch_pirq_init(device_t dev)
105{
106 device_t irq_dev;
107 /* Get the chip configuration */
108 config_t *config = dev->chip_info;
109
110 pci_write_config8(dev, PIRQA_ROUT, config->pirqa_routing);
111 pci_write_config8(dev, PIRQB_ROUT, config->pirqb_routing);
112 pci_write_config8(dev, PIRQC_ROUT, config->pirqc_routing);
113 pci_write_config8(dev, PIRQD_ROUT, config->pirqd_routing);
114
115 pci_write_config8(dev, PIRQE_ROUT, config->pirqe_routing);
116 pci_write_config8(dev, PIRQF_ROUT, config->pirqf_routing);
117 pci_write_config8(dev, PIRQG_ROUT, config->pirqg_routing);
118 pci_write_config8(dev, PIRQH_ROUT, config->pirqh_routing);
119
120 /* Eric Biederman once said we should let the OS do this.
121 * I am not so sure anymore he was right.
122 */
123
124 for(irq_dev = all_devices; irq_dev; irq_dev = irq_dev->next) {
125 u8 int_pin=0, int_line=0;
126
127 if (!irq_dev->enabled || irq_dev->path.type != DEVICE_PATH_PCI)
128 continue;
129
130 int_pin = pci_read_config8(irq_dev, PCI_INTERRUPT_PIN);
131
132 switch (int_pin) {
133 case 1: /* INTA# */ int_line = config->pirqa_routing; break;
134 case 2: /* INTB# */ int_line = config->pirqb_routing; break;
135 case 3: /* INTC# */ int_line = config->pirqc_routing; break;
136 case 4: /* INTD# */ int_line = config->pirqd_routing; break;
137 }
138
139 if (!int_line)
140 continue;
141
142 pci_write_config8(irq_dev, PCI_INTERRUPT_LINE, int_line);
143 }
144}
145
146static void pch_gpi_routing(device_t dev)
147{
148 /* Get the chip configuration */
149 config_t *config = dev->chip_info;
150 u32 reg32 = 0;
151
152 /* An array would be much nicer here, or some
153 * other method of doing this.
154 */
155 reg32 |= (config->gpi0_routing & 0x03) << 0;
156 reg32 |= (config->gpi1_routing & 0x03) << 2;
157 reg32 |= (config->gpi2_routing & 0x03) << 4;
158 reg32 |= (config->gpi3_routing & 0x03) << 6;
159 reg32 |= (config->gpi4_routing & 0x03) << 8;
160 reg32 |= (config->gpi5_routing & 0x03) << 10;
161 reg32 |= (config->gpi6_routing & 0x03) << 12;
162 reg32 |= (config->gpi7_routing & 0x03) << 14;
163 reg32 |= (config->gpi8_routing & 0x03) << 16;
164 reg32 |= (config->gpi9_routing & 0x03) << 18;
165 reg32 |= (config->gpi10_routing & 0x03) << 20;
166 reg32 |= (config->gpi11_routing & 0x03) << 22;
167 reg32 |= (config->gpi12_routing & 0x03) << 24;
168 reg32 |= (config->gpi13_routing & 0x03) << 26;
169 reg32 |= (config->gpi14_routing & 0x03) << 28;
170 reg32 |= (config->gpi15_routing & 0x03) << 30;
171
172 pci_write_config32(dev, 0xb8, reg32);
173}
174
175static void pch_power_options(device_t dev)
176{
177 u8 reg8;
178 u16 reg16, pmbase;
179 u32 reg32;
180 const char *state;
181 /* Get the chip configuration */
182 config_t *config = dev->chip_info;
183
184 int pwr_on=CONFIG_MAINBOARD_POWER_ON_AFTER_POWER_FAIL;
185 int nmi_option;
186
187 /* Which state do we want to goto after g3 (power restored)?
188 * 0 == S0 Full On
189 * 1 == S5 Soft Off
190 *
191 * If the option is not existent (Laptops), use Kconfig setting.
192 */
193 get_option(&pwr_on, "power_on_after_fail");
194
195 reg16 = pci_read_config16(dev, GEN_PMCON_3);
196 reg16 &= 0xfffe;
197 switch (pwr_on) {
198 case MAINBOARD_POWER_OFF:
199 reg16 |= 1;
200 state = "off";
201 break;
202 case MAINBOARD_POWER_ON:
203 reg16 &= ~1;
204 state = "on";
205 break;
206 case MAINBOARD_POWER_KEEP:
207 reg16 &= ~1;
208 state = "state keep";
209 break;
210 default:
211 state = "undefined";
212 }
213
214 reg16 &= ~(3 << 4); /* SLP_S4# Assertion Stretch 4s */
215 reg16 |= (1 << 3); /* SLP_S4# Assertion Stretch Enable */
216
217 reg16 &= ~(1 << 10);
218 reg16 |= (1 << 11); /* SLP_S3# Min Assertion Width 50ms */
219
220 reg16 |= (1 << 12); /* Disable SLP stretch after SUS well */
221
222 pci_write_config16(dev, GEN_PMCON_3, reg16);
223 printk(BIOS_INFO, "Set power %s after power failure.\n", state);
224
225 /* Set up NMI on errors. */
226 reg8 = inb(0x61);
227 reg8 &= 0x0f; /* Higher Nibble must be 0 */
228 reg8 &= ~(1 << 3); /* IOCHK# NMI Enable */
229 // reg8 &= ~(1 << 2); /* PCI SERR# Enable */
230 reg8 |= (1 << 2); /* PCI SERR# Disable for now */
231 outb(reg8, 0x61);
232
233 reg8 = inb(0x70);
234 nmi_option = NMI_OFF;
235 get_option(&nmi_option, "nmi");
236 if (nmi_option) {
237 printk(BIOS_INFO, "NMI sources enabled.\n");
238 reg8 &= ~(1 << 7); /* Set NMI. */
239 } else {
240 printk(BIOS_INFO, "NMI sources disabled.\n");
241 reg8 |= ( 1 << 7); /* Can't mask NMI from PCI-E and NMI_NOW */
242 }
243 outb(reg8, 0x70);
244
245 /* Enable CPU_SLP# and Intel Speedstep, set SMI# rate down */
246 reg16 = pci_read_config16(dev, GEN_PMCON_1);
247 reg16 &= ~(3 << 0); // SMI# rate 1 minute
248 reg16 &= ~(1 << 10); // Disable BIOS_PCI_EXP_EN for native PME
249#if DEBUG_PERIODIC_SMIS
250 /* Set DEBUG_PERIODIC_SMIS in pch.h to debug using
251 * periodic SMIs.
252 */
253 reg16 |= (3 << 0); // Periodic SMI every 8s
254#endif
255 pci_write_config16(dev, GEN_PMCON_1, reg16);
256
257 // Set the board's GPI routing.
258 pch_gpi_routing(dev);
259
260 pmbase = pci_read_config16(dev, 0x40) & 0xfffe;
261
262 outl(config->gpe0_en, pmbase + GPE0_EN);
263 outw(config->alt_gp_smi_en, pmbase + ALT_GP_SMI_EN);
264
265 /* Set up power management block and determine sleep mode */
266 reg32 = inl(pmbase + 0x04); // PM1_CNT
267 reg32 &= ~(7 << 10); // SLP_TYP
268 reg32 |= (1 << 0); // SCI_EN
269 outl(reg32, pmbase + 0x04);
270
271 /* Clear magic status bits to prevent unexpected wake */
272 reg32 = RCBA32(0x3310);
273 reg32 |= (1 << 4)|(1 << 5)|(1 << 0);
274 RCBA32(0x3310) = reg32;
275
276 reg32 = RCBA32(0x3f02);
277 reg32 &= ~0xf;
278 RCBA32(0x3f02) = reg32;
279}
280
281static void pch_rtc_init(struct device *dev)
282{
283 u8 reg8;
284 int rtc_failed;
285
286 reg8 = pci_read_config8(dev, GEN_PMCON_3);
287 rtc_failed = reg8 & RTC_BATTERY_DEAD;
288 if (rtc_failed) {
289 reg8 &= ~RTC_BATTERY_DEAD;
290 pci_write_config8(dev, GEN_PMCON_3, reg8);
Duncan Laurie800e9502012-06-23 17:06:47 -0700291#if CONFIG_ELOG
292 elog_add_event(ELOG_TYPE_RTC_RESET);
293#endif
Stefan Reinauer8e073822012-04-04 00:07:22 +0200294 }
295 printk(BIOS_DEBUG, "rtc_failed = 0x%x\n", rtc_failed);
296
297 rtc_init(rtc_failed);
298}
299
Duncan Laurie3f6a4d72012-06-28 13:03:40 -0700300/* CougarPoint PCH Power Management init */
301static void cpt_pm_init(struct device *dev)
Stefan Reinauer8e073822012-04-04 00:07:22 +0200302{
Duncan Laurie3f6a4d72012-06-28 13:03:40 -0700303 printk(BIOS_DEBUG, "CougarPoint PM init\n");
Stefan Reinauer8e073822012-04-04 00:07:22 +0200304 pci_write_config8(dev, 0xa9, 0x47);
305 RCBA32_AND_OR(0x2238, ~0UL, (1 << 6)|(1 << 0));
306 RCBA32_AND_OR(0x228c, ~0UL, (1 << 0));
307 RCBA16_AND_OR(0x1100, ~0UL, (1 << 13)|(1 << 14));
308 RCBA16_AND_OR(0x0900, ~0UL, (1 << 14));
309 RCBA32(0x2304) = 0xc0388400;
310 RCBA32_AND_OR(0x2314, ~0UL, (1 << 5)|(1 << 18));
311 RCBA32_AND_OR(0x2320, ~0UL, (1 << 15)|(1 << 1));
312 RCBA32_AND_OR(0x3314, ~0x1f, 0xf);
313 RCBA32(0x3318) = 0x050f0000;
314 RCBA32(0x3324) = 0x04000000;
315 RCBA32_AND_OR(0x3340, ~0UL, 0xfffff);
316 RCBA32_AND_OR(0x3344, ~0UL, (1 << 1));
317 RCBA32(0x3360) = 0x0001c000;
318 RCBA32(0x3368) = 0x00061100;
319 RCBA32(0x3378) = 0x7f8fdfff;
320 RCBA32(0x337c) = 0x000003fc;
321 RCBA32(0x3388) = 0x00001000;
322 RCBA32(0x3390) = 0x0001c000;
323 RCBA32(0x33a0) = 0x00000800;
324 RCBA32(0x33b0) = 0x00001000;
325 RCBA32(0x33c0) = 0x00093900;
326 RCBA32(0x33cc) = 0x24653002;
327 RCBA32(0x33d0) = 0x062108fe;
328 RCBA32_AND_OR(0x33d4, 0xf000f000, 0x00670060);
329 RCBA32(0x3a28) = 0x01010000;
330 RCBA32(0x3a2c) = 0x01010404;
331 RCBA32(0x3a80) = 0x01041041;
332 RCBA32_AND_OR(0x3a84, ~0x0000ffff, 0x00001001);
333 RCBA32_AND_OR(0x3a84, ~0UL, (1 << 24)); /* SATA 2/3 disabled */
334 RCBA32_AND_OR(0x3a88, ~0UL, (1 << 0)); /* SATA 4/5 disabled */
335 RCBA32(0x3a6c) = 0x00000001;
336 RCBA32_AND_OR(0x2344, 0x00ffff00, 0xff00000c);
337 RCBA32_AND_OR(0x80c, ~(0xff << 20), 0x11 << 20);
338 RCBA32(0x33c8) = 0;
339 RCBA32_AND_OR(0x21b0, ~0UL, 0xf);
340}
341
Duncan Laurie3f6a4d72012-06-28 13:03:40 -0700342/* PantherPoint PCH Power Management init */
343static void ppt_pm_init(struct device *dev)
344{
345 printk(BIOS_DEBUG, "PantherPoint PM init\n");
346 pci_write_config8(dev, 0xa9, 0x47);
347 RCBA32_AND_OR(0x2238, ~0UL, (1 << 0));
348 RCBA32_AND_OR(0x228c, ~0UL, (1 << 0));
349 RCBA16_AND_OR(0x1100, ~0UL, (1 << 13)|(1 << 14));
350 RCBA16_AND_OR(0x0900, ~0UL, (1 << 14));
351 RCBA32(0x2304) = 0xc03b8400;
352 RCBA32_AND_OR(0x2314, ~0UL, (1 << 5)|(1 << 18));
353 RCBA32_AND_OR(0x2320, ~0UL, (1 << 15)|(1 << 1));
354 RCBA32_AND_OR(0x3314, ~0x1f, 0xf);
355 RCBA32(0x3318) = 0x054f0000;
356 RCBA32(0x3324) = 0x04000000;
357 RCBA32_AND_OR(0x3340, ~0UL, 0xfffff);
358 RCBA32_AND_OR(0x3344, ~0UL, (1 << 1)|(1 << 0));
359 RCBA32(0x3360) = 0x0001c000;
360 RCBA32(0x3368) = 0x00061100;
361 RCBA32(0x3378) = 0x7f8fdfff;
362 RCBA32(0x337c) = 0x000003fd;
363 RCBA32(0x3388) = 0x00001000;
364 RCBA32(0x3390) = 0x0001c000;
365 RCBA32(0x33a0) = 0x00000800;
366 RCBA32(0x33b0) = 0x00001000;
367 RCBA32(0x33c0) = 0x00093900;
368 RCBA32(0x33cc) = 0x24653002;
369 RCBA32(0x33d0) = 0x067388fe;
370 RCBA32_AND_OR(0x33d4, 0xf000f000, 0x00670060);
371 RCBA32(0x3a28) = 0x01010000;
372 RCBA32(0x3a2c) = 0x01010404;
373 RCBA32(0x3a80) = 0x01040000;
374 RCBA32_AND_OR(0x3a84, ~0x0000ffff, 0x00001001);
375 RCBA32_AND_OR(0x3a84, ~0UL, (1 << 24)); /* SATA 2/3 disabled */
376 RCBA32_AND_OR(0x3a88, ~0UL, (1 << 0)); /* SATA 4/5 disabled */
377 RCBA32(0x3a6c) = 0x00000001;
378 RCBA32_AND_OR(0x2344, 0x00ffff00, 0xff00000c);
379 RCBA32_AND_OR(0x80c, ~(0xff << 20), 0x11 << 20);
380 RCBA32_AND_OR(0x33a4, ~0UL, (1 << 0));
381 RCBA32(0x33c8) = 0;
382 RCBA32_AND_OR(0x21b0, ~0UL, 0xf);
383}
384
Stefan Reinauer8e073822012-04-04 00:07:22 +0200385static void enable_hpet(void)
386{
387 u32 reg32;
388
389 /* Move HPET to default address 0xfed00000 and enable it */
390 reg32 = RCBA32(HPTC);
391 reg32 |= (1 << 7); // HPET Address Enable
392 reg32 &= ~(3 << 0);
393 RCBA32(HPTC) = reg32;
394}
395
396static void enable_clock_gating(device_t dev)
397{
398 u32 reg32;
399 u16 reg16;
400
401 RCBA32_AND_OR(0x2234, ~0UL, 0xf);
402
403 reg16 = pci_read_config16(dev, GEN_PMCON_1);
404 reg16 |= (1 << 2) | (1 << 11);
405 pci_write_config16(dev, GEN_PMCON_1, reg16);
406
407 pch_iobp_update(0xEB007F07, ~0UL, (1 << 31));
408 pch_iobp_update(0xEB004000, ~0UL, (1 << 7));
409 pch_iobp_update(0xEC007F07, ~0UL, (1 << 31));
410 pch_iobp_update(0xEC004000, ~0UL, (1 << 7));
411
412 reg32 = RCBA32(CG);
413 reg32 |= (1 << 31);
414 reg32 |= (1 << 29) | (1 << 28);
415 reg32 |= (1 << 27) | (1 << 26) | (1 << 25) | (1 << 24);
416 reg32 |= (1 << 16);
417 reg32 |= (1 << 17);
418 reg32 |= (1 << 18);
419 reg32 |= (1 << 22);
420 reg32 |= (1 << 23);
421 reg32 &= ~(1 << 20);
422 reg32 |= (1 << 19);
423 reg32 |= (1 << 0);
424 reg32 |= (0xf << 1);
425 RCBA32(CG) = reg32;
426
427 RCBA32_OR(0x38c0, 0x7);
428 RCBA32_OR(0x36d4, 0x6680c004);
429 RCBA32_OR(0x3564, 0x3);
430}
431
432#if CONFIG_HAVE_SMI_HANDLER
433static void pch_lock_smm(struct device *dev)
434{
435#if TEST_SMM_FLASH_LOCKDOWN
436 u8 reg8;
437#endif
438
Kyösti Mälkkic3ed8862014-06-19 19:50:51 +0300439 if (!acpi_is_wakeup_s3()) {
Stefan Reinauer8e073822012-04-04 00:07:22 +0200440#if ENABLE_ACPI_MODE_IN_COREBOOT
Duncan Laurie95be1d62012-04-09 12:31:43 -0700441 printk(BIOS_DEBUG, "Enabling ACPI via APMC:\n");
442 outb(0xe1, 0xb2); // Enable ACPI mode
443 printk(BIOS_DEBUG, "done.\n");
Stefan Reinauer8e073822012-04-04 00:07:22 +0200444#else
Duncan Laurie95be1d62012-04-09 12:31:43 -0700445 printk(BIOS_DEBUG, "Disabling ACPI via APMC:\n");
446 outb(0x1e, 0xb2); // Disable ACPI mode
447 printk(BIOS_DEBUG, "done.\n");
Stefan Reinauer8e073822012-04-04 00:07:22 +0200448#endif
Duncan Laurie95be1d62012-04-09 12:31:43 -0700449 }
450
Stefan Reinauer8e073822012-04-04 00:07:22 +0200451 /* Don't allow evil boot loaders, kernels, or
452 * userspace applications to deceive us:
453 */
454 smm_lock();
455
456#if TEST_SMM_FLASH_LOCKDOWN
457 /* Now try this: */
458 printk(BIOS_DEBUG, "Locking BIOS to RO... ");
459 reg8 = pci_read_config8(dev, 0xdc); /* BIOS_CNTL */
460 printk(BIOS_DEBUG, " BLE: %s; BWE: %s\n", (reg8&2)?"on":"off",
461 (reg8&1)?"rw":"ro");
462 reg8 &= ~(1 << 0); /* clear BIOSWE */
463 pci_write_config8(dev, 0xdc, reg8);
464 reg8 |= (1 << 1); /* set BLE */
465 pci_write_config8(dev, 0xdc, reg8);
466 printk(BIOS_DEBUG, "ok.\n");
467 reg8 = pci_read_config8(dev, 0xdc); /* BIOS_CNTL */
468 printk(BIOS_DEBUG, " BLE: %s; BWE: %s\n", (reg8&2)?"on":"off",
469 (reg8&1)?"rw":"ro");
470
471 printk(BIOS_DEBUG, "Writing:\n");
472 *(volatile u8 *)0xfff00000 = 0x00;
473 printk(BIOS_DEBUG, "Testing:\n");
474 reg8 |= (1 << 0); /* set BIOSWE */
475 pci_write_config8(dev, 0xdc, reg8);
476
477 reg8 = pci_read_config8(dev, 0xdc); /* BIOS_CNTL */
478 printk(BIOS_DEBUG, " BLE: %s; BWE: %s\n", (reg8&2)?"on":"off",
479 (reg8&1)?"rw":"ro");
480 printk(BIOS_DEBUG, "Done.\n");
481#endif
482}
483#endif
484
485static void pch_disable_smm_only_flashing(struct device *dev)
486{
487 u8 reg8;
488
489 printk(BIOS_SPEW, "Enabling BIOS updates outside of SMM... ");
490 reg8 = pci_read_config8(dev, 0xdc); /* BIOS_CNTL */
491 reg8 &= ~(1 << 5);
492 pci_write_config8(dev, 0xdc, reg8);
493}
494
495static void pch_fixups(struct device *dev)
496{
497 u8 gen_pmcon_2;
498
499 /* Indicate DRAM init done for MRC S3 to know it can resume */
500 gen_pmcon_2 = pci_read_config8(dev, GEN_PMCON_2);
501 gen_pmcon_2 |= (1 << 7);
502 pci_write_config8(dev, GEN_PMCON_2, gen_pmcon_2);
503
504 /*
505 * Enable DMI ASPM in the PCH
506 */
507 RCBA32_AND_OR(0x2304, ~(1 << 10), 0);
508 RCBA32_OR(0x21a4, (1 << 11)|(1 << 10));
509 RCBA32_OR(0x21a8, 0x3);
510}
511
512static void pch_decode_init(struct device *dev)
513{
514 config_t *config = dev->chip_info;
515
516 printk(BIOS_DEBUG, "pch_decode_init\n");
517
518 pci_write_config32(dev, LPC_GEN1_DEC, config->gen1_dec);
519 pci_write_config32(dev, LPC_GEN2_DEC, config->gen2_dec);
520 pci_write_config32(dev, LPC_GEN3_DEC, config->gen3_dec);
521 pci_write_config32(dev, LPC_GEN4_DEC, config->gen4_dec);
522}
523
524static void lpc_init(struct device *dev)
525{
526 printk(BIOS_DEBUG, "pch: lpc_init\n");
527
528 /* Set the value for PCI command register. */
529 pci_write_config16(dev, PCI_COMMAND, 0x000f);
530
531 /* IO APIC initialization. */
Paul Menzel9c50e6a2013-05-03 12:23:39 +0200532 pch_enable_ioapic(dev);
Stefan Reinauer8e073822012-04-04 00:07:22 +0200533
534 pch_enable_serial_irqs(dev);
535
536 /* Setup the PIRQ. */
537 pch_pirq_init(dev);
538
539 /* Setup power options. */
540 pch_power_options(dev);
541
542 /* Initialize power management */
Duncan Laurie3f6a4d72012-06-28 13:03:40 -0700543 switch (pch_silicon_type()) {
544 case PCH_TYPE_CPT: /* CougarPoint */
545 cpt_pm_init(dev);
546 break;
547 case PCH_TYPE_PPT: /* PantherPoint */
548 ppt_pm_init(dev);
549 break;
550 default:
551 printk(BIOS_ERR, "Unknown Chipset: 0x%04x\n", dev->device);
552 }
Stefan Reinauer8e073822012-04-04 00:07:22 +0200553
554 /* Set the state of the GPIO lines. */
555 //gpio_init(dev);
556
557 /* Initialize the real time clock. */
558 pch_rtc_init(dev);
559
560 /* Initialize ISA DMA. */
561 isa_dma_init();
562
563 /* Initialize the High Precision Event Timers, if present. */
564 enable_hpet();
565
566 /* Initialize Clock Gating */
567 enable_clock_gating(dev);
568
569 setup_i8259();
570
571 /* The OS should do this? */
572 /* Interrupt 9 should be level triggered (SCI) */
573 i8259_configure_irq_trigger(9, 1);
574
575 pch_disable_smm_only_flashing(dev);
576
577#if CONFIG_HAVE_SMI_HANDLER
578 pch_lock_smm(dev);
579#endif
580
581 pch_fixups(dev);
582}
583
584static void pch_lpc_read_resources(device_t dev)
585{
586 struct resource *res;
Marc Jonesa0bec172012-07-13 14:14:34 -0600587 config_t *config = dev->chip_info;
588 u8 io_index = 0;
Stefan Reinauer8e073822012-04-04 00:07:22 +0200589
590 /* Get the normal PCI resources of this device. */
591 pci_dev_read_resources(dev);
592
593 /* Add an extra subtractive resource for both memory and I/O. */
Marc Jonesa0bec172012-07-13 14:14:34 -0600594 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
Stefan Reinauer8e073822012-04-04 00:07:22 +0200595 res->base = 0;
596 res->size = 0x1000;
597 res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
598 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
599
Marc Jonesa0bec172012-07-13 14:14:34 -0600600 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
Vladimir Serbinenko0650cd02014-02-05 15:03:50 +0100601 res->base = 0xff000000;
602 /* Some systems (e.g. X230) have 12 MiB flash.
603 SPI controller supports up to 2 x 16 MiB of flash but
604 address map limits this to 16MiB. */
605 res->size = 0x01000000; /* 16 MB for flash */
Stefan Reinauer8e073822012-04-04 00:07:22 +0200606 res->flags = IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE |
607 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
608
609 res = new_resource(dev, 3); /* IOAPIC */
610 res->base = IO_APIC_ADDR;
611 res->size = 0x00001000;
612 res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
Marc Jonesa0bec172012-07-13 14:14:34 -0600613
614 /* Set PCH IO decode ranges if required.*/
615 if ((config->gen1_dec & 0xFFFC) > 0x1000) {
616 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
617 res->base = config->gen1_dec & 0xFFFC;
618 res->size = (config->gen1_dec >> 16) & 0xFC;
619 res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
620 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
621 }
622
623 if ((config->gen2_dec & 0xFFFC) > 0x1000) {
624 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
625 res->base = config->gen2_dec & 0xFFFC;
626 res->size = (config->gen2_dec >> 16) & 0xFC;
627 res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
628 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
629 }
630
631 if ((config->gen3_dec & 0xFFFC) > 0x1000) {
632 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
633 res->base = config->gen3_dec & 0xFFFC;
634 res->size = (config->gen3_dec >> 16) & 0xFC;
635 res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
636 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
637 }
638
639 if ((config->gen4_dec & 0xFFFC) > 0x1000) {
640 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
641 res->base = config->gen4_dec & 0xFFFC;
642 res->size = (config->gen4_dec >> 16) & 0xFC;
643 res->flags = IORESOURCE_IO| IORESOURCE_SUBTRACTIVE |
644 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
645 }
Stefan Reinauer8e073822012-04-04 00:07:22 +0200646}
647
648static void pch_lpc_enable_resources(device_t dev)
649{
650 pch_decode_init(dev);
651 return pci_dev_enable_resources(dev);
652}
653
654static void pch_lpc_enable(device_t dev)
655{
656 /* Enable PCH Display Port */
657 RCBA16(DISPBDF) = 0x0010;
658 RCBA32_OR(FD2, PCH_ENABLE_DBDF);
659
660 pch_enable(dev);
661}
662
663static void set_subsystem(device_t dev, unsigned vendor, unsigned device)
664{
665 if (!vendor || !device) {
666 pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
667 pci_read_config32(dev, PCI_VENDOR_ID));
668 } else {
669 pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
670 ((device & 0xffff) << 16) | (vendor & 0xffff));
671 }
672}
673
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +0200674static unsigned long southbridge_fill_ssdt(unsigned long current, const char *oem_table_id)
675{
676 global_nvs_t *gnvs = cbmem_add (CBMEM_ID_ACPI_GNVS, sizeof (*gnvs));
677 void *opregion;
678
679 /* Calling northbridge code as gnvs contains opregion address. */
680 opregion = igd_make_opregion();
681
682 if (gnvs) {
683 int scopelen;
Vladimir Serbinenko7309c642014-10-05 11:07:33 +0200684
685 memset(gnvs, 0, sizeof (*gnvs));
686
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +0200687 acpi_create_gnvs(gnvs);
688 /* IGD OpRegion Base Address */
689 gnvs->aslb = (u32)opregion;
690 /* And tell SMI about it */
691 smm_setup_structures(gnvs, NULL, NULL);
692
693 /* Add it to SSDT. */
694 scopelen = acpigen_write_scope("\\");
695 scopelen += acpigen_write_name_dword("NVSA", (u32) gnvs);
696 acpigen_patch_len(scopelen - 1);
697 }
698
699 return (unsigned long) (acpigen_get_current());
700}
701
Stefan Reinauer8e073822012-04-04 00:07:22 +0200702static struct pci_operations pci_ops = {
703 .set_subsystem = set_subsystem,
704};
705
706static struct device_operations device_ops = {
707 .read_resources = pch_lpc_read_resources,
708 .set_resources = pci_dev_set_resources,
709 .enable_resources = pch_lpc_enable_resources,
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +0200710 .write_acpi_tables = acpi_write_hpet,
711 .acpi_fill_ssdt_generator = southbridge_fill_ssdt,
Stefan Reinauer8e073822012-04-04 00:07:22 +0200712 .init = lpc_init,
713 .enable = pch_lpc_enable,
714 .scan_bus = scan_static_bus,
715 .ops_pci = &pci_ops,
716};
717
718
Kimarie Hoote6f459c2012-07-14 08:26:08 -0600719/* IDs for LPC device of Intel 6 Series Chipset, Intel 7 Series Chipset, and
720 * Intel C200 Series Chipset
Stefan Reinauer8e073822012-04-04 00:07:22 +0200721 */
722
Stefan Reinauer9a380ab2012-06-22 13:16:11 -0700723static const unsigned short pci_device_ids[] = { 0x1c46, 0x1c47, 0x1c49, 0x1c4a,
724 0x1c4b, 0x1c4c, 0x1c4d, 0x1c4e,
725 0x1c4f, 0x1c50, 0x1c52, 0x1c54,
Kimarie Hoote6f459c2012-07-14 08:26:08 -0600726 0x1e55, 0x1c56, 0x1e57, 0x1c5c,
727 0x1e5d, 0x1e5e, 0x1e5f,
Stefan Reinauer9a380ab2012-06-22 13:16:11 -0700728 0 };
729
730static const struct pci_driver pch_lpc __pci_driver = {
731 .ops = &device_ops,
732 .vendor = PCI_VENDOR_ID_INTEL,
733 .devices = pci_device_ids,
Stefan Reinauer8e073822012-04-04 00:07:22 +0200734};