blob: 88ec8515820150dae917ee332e525d5a4499f58d [file] [log] [blame]
Vladimir Serbinenko888d5592013-11-13 17:53:38 +01001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2008-2009 coresystems GmbH
5 * Copyright (C) 2013 Vladimir Serbinenko
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; version 2 of
10 * the License.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
Vladimir Serbinenko888d5592013-11-13 17:53:38 +010016 */
17
18#include <console/console.h>
19#include <device/device.h>
20#include <device/pci.h>
21#include <device/pci_ids.h>
22#include <pc80/mc146818rtc.h>
23#include <pc80/isa-dma.h>
24#include <pc80/i8259.h>
25#include <arch/io.h>
26#include <arch/ioapic.h>
27#include <arch/acpi.h>
28#include <cpu/cpu.h>
29#include <elog.h>
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +020030#include <arch/acpigen.h>
31#include <drivers/intel/gma/i915.h>
32#include <cbmem.h>
Vladimir Serbinenko7309c642014-10-05 11:07:33 +020033#include <string.h>
Vladimir Serbinenko67bfbfd2014-10-25 15:49:23 +020034#include <cpu/x86/smm.h>
Vladimir Serbinenko888d5592013-11-13 17:53:38 +010035#include "pch.h"
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +020036#include "nvs.h"
Vladimir Serbinenko36fa5b82014-10-28 23:43:20 +010037#include <southbridge/intel/common/pciehp.h>
Vladimir Serbinenko888d5592013-11-13 17:53:38 +010038
39#define NMI_OFF 0
40
41#define ENABLE_ACPI_MODE_IN_COREBOOT 0
Vladimir Serbinenko888d5592013-11-13 17:53:38 +010042
Vladimir Serbinenko46957052013-11-26 01:16:20 +010043typedef struct southbridge_intel_ibexpeak_config config_t;
Vladimir Serbinenko888d5592013-11-13 17:53:38 +010044
45/**
46 * Set miscellanous static southbridge features.
47 *
48 * @param dev PCI device with I/O APIC control registers
49 */
50static void pch_enable_ioapic(struct device *dev)
51{
52 u32 reg32;
53
54 /* Enable ACPI I/O range decode */
55 pci_write_config8(dev, ACPI_CNTL, ACPI_EN);
56
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -080057 set_ioapic_id(VIO_APIC_VADDR, 0x01);
Vladimir Serbinenko888d5592013-11-13 17:53:38 +010058 /* affirm full set of redirection table entries ("write once") */
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -080059 reg32 = io_apic_read(VIO_APIC_VADDR, 0x01);
60 io_apic_write(VIO_APIC_VADDR, 0x01, reg32);
Vladimir Serbinenko888d5592013-11-13 17:53:38 +010061
62 /*
63 * Select Boot Configuration register (0x03) and
64 * use Processor System Bus (0x01) to deliver interrupts.
65 */
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -080066 io_apic_write(VIO_APIC_VADDR, 0x03, 0x01);
Vladimir Serbinenko888d5592013-11-13 17:53:38 +010067}
68
69static void pch_enable_serial_irqs(struct device *dev)
70{
71 /* Set packet length and toggle silent mode bit for one frame. */
72 pci_write_config8(dev, SERIRQ_CNTL,
73 (1 << 7) | (1 << 6) | ((21 - 17) << 2) | (0 << 0));
74#if !CONFIG_SERIRQ_CONTINUOUS_MODE
75 pci_write_config8(dev, SERIRQ_CNTL,
76 (1 << 7) | (0 << 6) | ((21 - 17) << 2) | (0 << 0));
77#endif
78}
79
80/* PIRQ[n]_ROUT[3:0] - PIRQ Routing Control
81 * 0x00 - 0000 = Reserved
82 * 0x01 - 0001 = Reserved
83 * 0x02 - 0010 = Reserved
84 * 0x03 - 0011 = IRQ3
85 * 0x04 - 0100 = IRQ4
86 * 0x05 - 0101 = IRQ5
87 * 0x06 - 0110 = IRQ6
88 * 0x07 - 0111 = IRQ7
89 * 0x08 - 1000 = Reserved
90 * 0x09 - 1001 = IRQ9
91 * 0x0A - 1010 = IRQ10
92 * 0x0B - 1011 = IRQ11
93 * 0x0C - 1100 = IRQ12
94 * 0x0D - 1101 = Reserved
95 * 0x0E - 1110 = IRQ14
96 * 0x0F - 1111 = IRQ15
97 * PIRQ[n]_ROUT[7] - PIRQ Routing Control
98 * 0x80 - The PIRQ is not routed.
99 */
100
101static void pch_pirq_init(device_t dev)
102{
103 device_t irq_dev;
Vladimir Serbinenko33b535f2014-10-19 10:13:14 +0200104 /* Interrupt 11 is not used by legacy devices and so can always be used for
105 PCI interrupts. Full legacy IRQ routing is complicated and hard to
106 get right. Fortunately all modern OS use MSI and so it's not that big of
107 an issue anyway. Still we have to provide a reasonable default. Using
108 interrupt 11 for it everywhere is a working default. ACPI-aware OS can
109 move it to any interrupt and others will just leave them at default.
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100110 */
Vladimir Serbinenko33b535f2014-10-19 10:13:14 +0200111 const u8 pirq_routing = 11;
112
113 pci_write_config8(dev, PIRQA_ROUT, pirq_routing);
114 pci_write_config8(dev, PIRQB_ROUT, pirq_routing);
115 pci_write_config8(dev, PIRQC_ROUT, pirq_routing);
116 pci_write_config8(dev, PIRQD_ROUT, pirq_routing);
117
118 pci_write_config8(dev, PIRQE_ROUT, pirq_routing);
119 pci_write_config8(dev, PIRQF_ROUT, pirq_routing);
120 pci_write_config8(dev, PIRQG_ROUT, pirq_routing);
121 pci_write_config8(dev, PIRQH_ROUT, pirq_routing);
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100122
123 for(irq_dev = all_devices; irq_dev; irq_dev = irq_dev->next) {
Vladimir Serbinenko33b535f2014-10-19 10:13:14 +0200124 u8 int_pin=0;
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100125
126 if (!irq_dev->enabled || irq_dev->path.type != DEVICE_PATH_PCI)
127 continue;
128
129 int_pin = pci_read_config8(irq_dev, PCI_INTERRUPT_PIN);
130
Vladimir Serbinenko33b535f2014-10-19 10:13:14 +0200131 if (int_pin == 0)
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100132 continue;
133
Vladimir Serbinenko33b535f2014-10-19 10:13:14 +0200134 pci_write_config8(irq_dev, PCI_INTERRUPT_LINE, pirq_routing);
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100135 }
136}
137
138static void pch_gpi_routing(device_t dev)
139{
140 /* Get the chip configuration */
141 config_t *config = dev->chip_info;
142 u32 reg32 = 0;
143
144 /* An array would be much nicer here, or some
145 * other method of doing this.
146 */
147 reg32 |= (config->gpi0_routing & 0x03) << 0;
148 reg32 |= (config->gpi1_routing & 0x03) << 2;
149 reg32 |= (config->gpi2_routing & 0x03) << 4;
150 reg32 |= (config->gpi3_routing & 0x03) << 6;
151 reg32 |= (config->gpi4_routing & 0x03) << 8;
152 reg32 |= (config->gpi5_routing & 0x03) << 10;
153 reg32 |= (config->gpi6_routing & 0x03) << 12;
154 reg32 |= (config->gpi7_routing & 0x03) << 14;
155 reg32 |= (config->gpi8_routing & 0x03) << 16;
156 reg32 |= (config->gpi9_routing & 0x03) << 18;
157 reg32 |= (config->gpi10_routing & 0x03) << 20;
158 reg32 |= (config->gpi11_routing & 0x03) << 22;
159 reg32 |= (config->gpi12_routing & 0x03) << 24;
160 reg32 |= (config->gpi13_routing & 0x03) << 26;
161 reg32 |= (config->gpi14_routing & 0x03) << 28;
162 reg32 |= (config->gpi15_routing & 0x03) << 30;
163
Kyösti Mälkkib85a87b2014-12-29 11:32:27 +0200164 pci_write_config32(dev, GPIO_ROUT, reg32);
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100165}
166
167static void pch_power_options(device_t dev)
168{
169 u8 reg8;
170 u16 reg16, pmbase;
171 u32 reg32;
172 const char *state;
173 /* Get the chip configuration */
174 config_t *config = dev->chip_info;
175
176 int pwr_on=CONFIG_MAINBOARD_POWER_ON_AFTER_POWER_FAIL;
177 int nmi_option;
178
179 /* Which state do we want to goto after g3 (power restored)?
180 * 0 == S0 Full On
181 * 1 == S5 Soft Off
182 *
183 * If the option is not existent (Laptops), use Kconfig setting.
184 */
185 get_option(&pwr_on, "power_on_after_fail");
186
187 reg16 = pci_read_config16(dev, GEN_PMCON_3);
188 reg16 &= 0xfffe;
189 switch (pwr_on) {
190 case MAINBOARD_POWER_OFF:
191 reg16 |= 1;
192 state = "off";
193 break;
194 case MAINBOARD_POWER_ON:
195 reg16 &= ~1;
196 state = "on";
197 break;
198 case MAINBOARD_POWER_KEEP:
199 reg16 &= ~1;
200 state = "state keep";
201 break;
202 default:
203 state = "undefined";
204 }
205
206 reg16 &= ~(3 << 4); /* SLP_S4# Assertion Stretch 4s */
207 reg16 |= (1 << 3); /* SLP_S4# Assertion Stretch Enable */
208
209 reg16 &= ~(1 << 10);
210 reg16 |= (1 << 11); /* SLP_S3# Min Assertion Width 50ms */
211
212 reg16 |= (1 << 12); /* Disable SLP stretch after SUS well */
213
214 pci_write_config16(dev, GEN_PMCON_3, reg16);
215 printk(BIOS_INFO, "Set power %s after power failure.\n", state);
216
217 /* Set up NMI on errors. */
218 reg8 = inb(0x61);
219 reg8 &= 0x0f; /* Higher Nibble must be 0 */
220 reg8 &= ~(1 << 3); /* IOCHK# NMI Enable */
221 // reg8 &= ~(1 << 2); /* PCI SERR# Enable */
222 reg8 |= (1 << 2); /* PCI SERR# Disable for now */
223 outb(reg8, 0x61);
224
225 reg8 = inb(0x70);
226 nmi_option = NMI_OFF;
227 get_option(&nmi_option, "nmi");
228 if (nmi_option) {
229 printk(BIOS_INFO, "NMI sources enabled.\n");
230 reg8 &= ~(1 << 7); /* Set NMI. */
231 } else {
232 printk(BIOS_INFO, "NMI sources disabled.\n");
233 reg8 |= ( 1 << 7); /* Can't mask NMI from PCI-E and NMI_NOW */
234 }
235 outb(reg8, 0x70);
236
237 /* Enable CPU_SLP# and Intel Speedstep, set SMI# rate down */
238 reg16 = pci_read_config16(dev, GEN_PMCON_1);
239 reg16 &= ~(3 << 0); // SMI# rate 1 minute
240 reg16 &= ~(1 << 10); // Disable BIOS_PCI_EXP_EN for native PME
241#if DEBUG_PERIODIC_SMIS
242 /* Set DEBUG_PERIODIC_SMIS in pch.h to debug using
243 * periodic SMIs.
244 */
245 reg16 |= (3 << 0); // Periodic SMI every 8s
246#endif
247 pci_write_config16(dev, GEN_PMCON_1, reg16);
248
249 // Set the board's GPI routing.
250 pch_gpi_routing(dev);
251
252 pmbase = pci_read_config16(dev, 0x40) & 0xfffe;
253
254 outl(config->gpe0_en, pmbase + GPE0_EN);
255 outw(config->alt_gp_smi_en, pmbase + ALT_GP_SMI_EN);
256
257 /* Set up power management block and determine sleep mode */
258 reg32 = inl(pmbase + 0x04); // PM1_CNT
259 reg32 &= ~(7 << 10); // SLP_TYP
260 reg32 |= (1 << 0); // SCI_EN
261 outl(reg32, pmbase + 0x04);
262
263 /* Clear magic status bits to prevent unexpected wake */
264 reg32 = RCBA32(0x3310);
265 reg32 |= (1 << 4)|(1 << 5)|(1 << 0);
266 RCBA32(0x3310) = reg32;
267
268 reg32 = RCBA32(0x3f02);
269 reg32 &= ~0xf;
270 RCBA32(0x3f02) = reg32;
271}
272
273static void pch_rtc_init(struct device *dev)
274{
275 u8 reg8;
276 int rtc_failed;
277
278 reg8 = pci_read_config8(dev, GEN_PMCON_3);
279 rtc_failed = reg8 & RTC_BATTERY_DEAD;
280 if (rtc_failed) {
281 reg8 &= ~RTC_BATTERY_DEAD;
282 pci_write_config8(dev, GEN_PMCON_3, reg8);
283#if CONFIG_ELOG
284 elog_add_event(ELOG_TYPE_RTC_RESET);
285#endif
286 }
287 printk(BIOS_DEBUG, "rtc_failed = 0x%x\n", rtc_failed);
288
Gabe Blackb3f08c62014-04-30 17:12:25 -0700289 cmos_init(rtc_failed);
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100290}
291
292static void mobile5_pm_init(struct device *dev)
293{
294 int i;
295
296 printk(BIOS_DEBUG, "Mobile 5 PM init\n");
297 pci_write_config8(dev, 0xa9, 0x47);
298
299 RCBA32 (0x1d44) = 0x00000000;
300 (void) RCBA32 (0x1d44);
301 RCBA32 (0x1d48) = 0x00030000;
302 (void) RCBA32 (0x1d48);
303 RCBA32 (0x1e80) = 0x000c0801;
304 (void) RCBA32 (0x1e80);
305 RCBA32 (0x1e84) = 0x000200f0;
306 (void) RCBA32 (0x1e84);
307
308 const u32 rcba2010[] =
309 {
310 /* 2010: */ 0x00188200, 0x14000016, 0xbc4abcb5, 0x00000000,
311 /* 2020: */ 0xf0c9605b, 0x13683040, 0x04c8f16e, 0x09e90170
312 };
313 for (i = 0; i < sizeof (rcba2010) / sizeof (rcba2010[0]); i++)
314 {
315 RCBA32 (0x2010 + 4 * i) = rcba2010[i];
316 RCBA32 (0x2010 + 4 * i);
317 }
318
319 RCBA32 (0x2100) = 0x00000000;
320 (void) RCBA32 (0x2100);
321 RCBA32 (0x2104) = 0x00000757;
322 (void) RCBA32 (0x2104);
323 RCBA32 (0x2108) = 0x00170001;
324 (void) RCBA32 (0x2108);
325
326 RCBA32 (0x211c) = 0x00000000;
327 (void) RCBA32 (0x211c);
328 RCBA32 (0x2120) = 0x00010000;
329 (void) RCBA32 (0x2120);
330
331 RCBA32 (0x21fc) = 0x00000000;
332 (void) RCBA32 (0x21fc);
333 RCBA32 (0x2200) = 0x20000044;
334 (void) RCBA32 (0x2200);
335 RCBA32 (0x2204) = 0x00000001;
336 (void) RCBA32 (0x2204);
337 RCBA32 (0x2208) = 0x00003457;
338 (void) RCBA32 (0x2208);
339
340 const u32 rcba2210[] =
341 {
342 /* 2210 */ 0x00000000, 0x00000001, 0xa0fff210, 0x0000df00,
343 /* 2220 */ 0x00e30880, 0x00000070, 0x00004000, 0x00000000,
344 /* 2230 */ 0x00e30880, 0x00000070, 0x00004000, 0x00000000,
345 /* 2240 */ 0x00002301, 0x36000000, 0x00010107, 0x00160000,
346 /* 2250 */ 0x00001b01, 0x36000000, 0x00010107, 0x00160000,
347 /* 2260 */ 0x00000601, 0x16000000, 0x00010107, 0x00160000,
348 /* 2270 */ 0x00001c01, 0x16000000, 0x00010107, 0x00160000
349 };
350
351 for (i = 0; i < sizeof (rcba2210) / sizeof (rcba2210[0]); i++)
352 {
353 RCBA32 (0x2210 + 4 * i) = rcba2210[i];
354 RCBA32 (0x2210 + 4 * i);
355 }
356
357 const u32 rcba2300[] =
358 {
359 /* 2300: */ 0x00000000, 0x40000000, 0x4646827b, 0x6e803131,
360 /* 2310: */ 0x32c77887, 0x00077733, 0x00007447, 0x00000040,
361 /* 2320: */ 0xcccc0cfc, 0x0fbb0fff
362 };
363
364 for (i = 0; i < sizeof (rcba2300) / sizeof (rcba2300[0]); i++)
365 {
366 RCBA32 (0x2300 + 4 * i) = rcba2300[i];
367 RCBA32 (0x2300 + 4 * i);
368 }
369
370 RCBA32 (0x37fc) = 0x00000000;
371 (void) RCBA32 (0x37fc);
372 RCBA32 (0x3dfc) = 0x00000000;
373 (void) RCBA32 (0x3dfc);
374 RCBA32 (0x3e7c) = 0xffffffff;
375 (void) RCBA32 (0x3e7c);
376 RCBA32 (0x3efc) = 0x00000000;
377 (void) RCBA32 (0x3efc);
378 RCBA32 (0x3f00) = 0x0000010b;
379 (void) RCBA32 (0x3f00);
380}
381
382static void enable_hpet(void)
383{
384 u32 reg32;
385
386 /* Move HPET to default address 0xfed00000 and enable it */
387 reg32 = RCBA32(HPTC);
388 reg32 |= (1 << 7); // HPET Address Enable
389 reg32 &= ~(3 << 0);
390 RCBA32(HPTC) = reg32;
391
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800392 write32((u32 *)0xfed00010, read32((u32 *)0xfed00010) | 1);
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100393}
394
395static void enable_clock_gating(device_t dev)
396{
397 u32 reg32;
398 u16 reg16;
399
400 RCBA32_AND_OR(0x2234, ~0UL, 0xf);
401
402 reg16 = pci_read_config16(dev, GEN_PMCON_1);
403 reg16 |= (1 << 2) | (1 << 11);
404 pci_write_config16(dev, GEN_PMCON_1, reg16);
405
406 pch_iobp_update(0xEB007F07, ~0UL, (1 << 31));
407 pch_iobp_update(0xEB004000, ~0UL, (1 << 7));
408 pch_iobp_update(0xEC007F07, ~0UL, (1 << 31));
409 pch_iobp_update(0xEC004000, ~0UL, (1 << 7));
410
411 reg32 = RCBA32(CG);
412 reg32 |= (1 << 31);
413 reg32 |= (1 << 29) | (1 << 28);
414 reg32 |= (1 << 27) | (1 << 26) | (1 << 25) | (1 << 24);
415 reg32 |= (1 << 16);
416 reg32 |= (1 << 17);
417 reg32 |= (1 << 18);
418 reg32 |= (1 << 22);
419 reg32 |= (1 << 23);
420 reg32 &= ~(1 << 20);
421 reg32 |= (1 << 19);
422 reg32 |= (1 << 0);
423 reg32 |= (0xf << 1);
424 RCBA32(CG) = reg32;
425
426 RCBA32_OR(0x38c0, 0x7);
427 RCBA32_OR(0x36d4, 0x6680c004);
428 RCBA32_OR(0x3564, 0x3);
429}
430
Vladimir Serbinenko456f4952015-05-28 20:42:32 +0200431static void pch_set_acpi_mode(void)
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100432{
Vladimir Serbinenko456f4952015-05-28 20:42:32 +0200433 if (!acpi_is_wakeup_s3() && CONFIG_HAVE_SMI_HANDLER) {
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100434#if ENABLE_ACPI_MODE_IN_COREBOOT
435 printk(BIOS_DEBUG, "Enabling ACPI via APMC:\n");
Vladimir Serbinenko456f4952015-05-28 20:42:32 +0200436 outb(APM_CNT_ACPI_ENABLE, APM_CNT); // Enable ACPI mode
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100437 printk(BIOS_DEBUG, "done.\n");
438#else
439 printk(BIOS_DEBUG, "Disabling ACPI via APMC:\n");
Vladimir Serbinenko456f4952015-05-28 20:42:32 +0200440 outb(APM_CNT_ACPI_DISABLE, APM_CNT); // Disable ACPI mode
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100441 printk(BIOS_DEBUG, "done.\n");
442#endif
443 }
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100444}
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100445
446static void pch_disable_smm_only_flashing(struct device *dev)
447{
448 u8 reg8;
449
450 printk(BIOS_SPEW, "Enabling BIOS updates outside of SMM... ");
451 reg8 = pci_read_config8(dev, 0xdc); /* BIOS_CNTL */
452 reg8 &= ~(1 << 5);
453 pci_write_config8(dev, 0xdc, reg8);
454}
455
456static void pch_fixups(struct device *dev)
457{
458 /*
459 * Enable DMI ASPM in the PCH
460 */
461 RCBA32_AND_OR(0x2304, ~(1 << 10), 0);
462 RCBA32_OR(0x21a4, (1 << 11)|(1 << 10));
463 RCBA32_OR(0x21a8, 0x3);
464}
465
466static void pch_decode_init(struct device *dev)
467{
468 config_t *config = dev->chip_info;
469
470 printk(BIOS_DEBUG, "pch_decode_init\n");
471
472 pci_write_config32(dev, LPC_GEN1_DEC, config->gen1_dec);
473 pci_write_config32(dev, LPC_GEN2_DEC, config->gen2_dec);
474 pci_write_config32(dev, LPC_GEN3_DEC, config->gen3_dec);
475 pci_write_config32(dev, LPC_GEN4_DEC, config->gen4_dec);
476}
477
478static void lpc_init(struct device *dev)
479{
480 printk(BIOS_DEBUG, "pch: lpc_init\n");
481
482 /* Set the value for PCI command register. */
483 pci_write_config16(dev, PCI_COMMAND, 0x000f);
484
485 /* IO APIC initialization. */
486 pch_enable_ioapic(dev);
487
488 pch_enable_serial_irqs(dev);
489
490 /* Setup the PIRQ. */
491 pch_pirq_init(dev);
492
493 /* Setup power options. */
494 pch_power_options(dev);
495
496 /* Initialize power management */
497 switch (pch_silicon_type()) {
498 case PCH_TYPE_MOBILE5:
499 mobile5_pm_init (dev);
500 break;
501 default:
502 printk(BIOS_ERR, "Unknown Chipset: 0x%04x\n", dev->device);
503 }
504
505 /* Set the state of the GPIO lines. */
506 //gpio_init(dev);
507
508 /* Initialize the real time clock. */
509 pch_rtc_init(dev);
510
511 /* Initialize ISA DMA. */
512 isa_dma_init();
513
514 /* Initialize the High Precision Event Timers, if present. */
515 enable_hpet();
516
517 /* Initialize Clock Gating */
518 enable_clock_gating(dev);
519
520 setup_i8259();
521
522 /* The OS should do this? */
523 /* Interrupt 9 should be level triggered (SCI) */
524 i8259_configure_irq_trigger(9, 1);
525
526 pch_disable_smm_only_flashing(dev);
527
Vladimir Serbinenko456f4952015-05-28 20:42:32 +0200528 pch_set_acpi_mode();
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100529
530 pch_fixups(dev);
531}
532
533static void pch_lpc_read_resources(device_t dev)
534{
535 struct resource *res;
536 config_t *config = dev->chip_info;
537 u8 io_index = 0;
538
539 /* Get the normal PCI resources of this device. */
540 pci_dev_read_resources(dev);
541
542 /* Add an extra subtractive resource for both memory and I/O. */
543 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
544 res->base = 0;
545 res->size = 0x1000;
546 res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
547 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
548
549 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
550 res->base = 0xff800000;
551 res->size = 0x00800000; /* 8 MB for flash */
552 res->flags = IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE |
553 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
554
555 res = new_resource(dev, 3); /* IOAPIC */
556 res->base = IO_APIC_ADDR;
557 res->size = 0x00001000;
558 res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
559
560 /* Set PCH IO decode ranges if required.*/
561 if ((config->gen1_dec & 0xFFFC) > 0x1000) {
562 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
563 res->base = config->gen1_dec & 0xFFFC;
564 res->size = (config->gen1_dec >> 16) & 0xFC;
565 res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
566 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
567 }
568
569 if ((config->gen2_dec & 0xFFFC) > 0x1000) {
570 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
571 res->base = config->gen2_dec & 0xFFFC;
572 res->size = (config->gen2_dec >> 16) & 0xFC;
573 res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
574 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
575 }
576
577 if ((config->gen3_dec & 0xFFFC) > 0x1000) {
578 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
579 res->base = config->gen3_dec & 0xFFFC;
580 res->size = (config->gen3_dec >> 16) & 0xFC;
581 res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
582 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
583 }
584
585 if ((config->gen4_dec & 0xFFFC) > 0x1000) {
586 res = new_resource(dev, IOINDEX_SUBTRACTIVE(io_index++, 0));
587 res->base = config->gen4_dec & 0xFFFC;
588 res->size = (config->gen4_dec >> 16) & 0xFC;
589 res->flags = IORESOURCE_IO| IORESOURCE_SUBTRACTIVE |
590 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
591 }
592}
593
594static void pch_lpc_enable_resources(device_t dev)
595{
596 pch_decode_init(dev);
597 return pci_dev_enable_resources(dev);
598}
599
600static void pch_lpc_enable(device_t dev)
601{
602 /* Enable PCH Display Port */
603 RCBA16(DISPBDF) = 0x0010;
604 RCBA32_OR(FD2, PCH_ENABLE_DBDF);
605
606 pch_enable(dev);
607}
608
609static void set_subsystem(device_t dev, unsigned vendor, unsigned device)
610{
611 if (!vendor || !device) {
612 pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
613 pci_read_config32(dev, PCI_VENDOR_ID));
614 } else {
615 pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
616 ((device & 0xffff) << 16) | (vendor & 0xffff));
617 }
618}
619
Alexander Couzensa90dad12015-04-12 21:49:46 +0200620static void southbridge_inject_dsdt(device_t dev)
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +0200621{
622 global_nvs_t *gnvs = cbmem_add (CBMEM_ID_ACPI_GNVS, sizeof (*gnvs));
623 void *opregion;
624
625 /* Calling northbridge code as gnvs contains opregion address. */
626 opregion = igd_make_opregion();
627
628 if (gnvs) {
Vladimir Serbinenkodd2bc3f2014-10-31 09:16:31 +0100629 const struct i915_gpu_controller_info *gfx = intel_gma_get_controller_info();
Vladimir Serbinenko7309c642014-10-05 11:07:33 +0200630 memset(gnvs, 0, sizeof (*gnvs));
631
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +0200632 acpi_create_gnvs(gnvs);
Vladimir Serbinenko9d45d692014-10-20 19:16:44 +0200633
634 gnvs->apic = 1;
635 gnvs->mpen = 1; /* Enable Multi Processing */
636 gnvs->pcnt = dev_count_cpu();
Vladimir Serbinenkodd2bc3f2014-10-31 09:16:31 +0100637 gnvs->ndid = gfx->ndid;
638 memcpy(gnvs->did, gfx->did, sizeof(gnvs->did));
Vladimir Serbinenko9d45d692014-10-20 19:16:44 +0200639
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +0200640 /* IGD OpRegion Base Address */
641 gnvs->aslb = (u32)opregion;
642 /* And tell SMI about it */
643 smm_setup_structures(gnvs, NULL, NULL);
644
645 /* Add it to SSDT. */
Vladimir Serbinenko226d7842014-11-04 21:09:23 +0100646 acpigen_write_scope("\\");
647 acpigen_write_name_dword("NVSA", (u32) gnvs);
648 acpigen_pop_len();
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +0200649 }
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +0200650}
651
Vladimir Serbinenko67bfbfd2014-10-25 15:49:23 +0200652void acpi_fill_fadt(acpi_fadt_t *fadt)
653{
654 device_t dev = dev_find_slot(0, PCI_DEVFN(0x1f,0));
655 config_t *chip = dev->chip_info;
656 u16 pmbase = pci_read_config16(dev, 0x40) & 0xfffe;
657 int c2_latency;
658
659 fadt->model = 1;
660
661 fadt->sci_int = 0x9;
662 fadt->smi_cmd = APM_CNT;
663 fadt->acpi_enable = APM_CNT_ACPI_ENABLE;
664 fadt->acpi_disable = APM_CNT_ACPI_DISABLE;
665 fadt->s4bios_req = 0x0;
666 fadt->pstate_cnt = 0;
667
668 fadt->pm1a_evt_blk = pmbase;
669 fadt->pm1b_evt_blk = 0x0;
670 fadt->pm1a_cnt_blk = pmbase + 0x4;
671 fadt->pm1b_cnt_blk = 0x0;
672 fadt->pm2_cnt_blk = pmbase + 0x50;
673 fadt->pm_tmr_blk = pmbase + 0x8;
674 fadt->gpe0_blk = pmbase + 0x20;
675 fadt->gpe1_blk = 0;
676
677 fadt->pm1_evt_len = 4;
678 fadt->pm1_cnt_len = 2;
679 fadt->pm2_cnt_len = 1;
680 fadt->pm_tmr_len = 4;
681 fadt->gpe0_blk_len = 16;
682 fadt->gpe1_blk_len = 0;
683 fadt->gpe1_base = 0;
684 fadt->cst_cnt = 0;
685 c2_latency = chip->c2_latency;
686 if (!c2_latency) {
687 c2_latency = 101; /* c2 unsupported */
688 }
689 fadt->p_lvl2_lat = c2_latency;
690 fadt->p_lvl3_lat = 87;
691 fadt->flush_size = 1024;
692 fadt->flush_stride = 16;
693 fadt->duty_offset = 1;
694 if (chip->p_cnt_throttling_supported) {
695 fadt->duty_width = 3;
696 } else {
697 fadt->duty_width = 0;
698 }
699 fadt->day_alrm = 0xd;
700 fadt->mon_alrm = 0x00;
701 fadt->century = 0x32;
702 fadt->iapc_boot_arch = ACPI_FADT_LEGACY_DEVICES | ACPI_FADT_8042;
703
704 fadt->flags = ACPI_FADT_WBINVD |
705 ACPI_FADT_C1_SUPPORTED |
706 ACPI_FADT_SLEEP_BUTTON |
707 ACPI_FADT_RESET_REGISTER |
708 ACPI_FADT_S4_RTC_WAKE |
709 ACPI_FADT_PLATFORM_CLOCK;
710 if (chip->docking_supported) {
711 fadt->flags |= ACPI_FADT_DOCKING_SUPPORTED;
712 }
713 if (c2_latency < 100) {
714 fadt->flags |= ACPI_FADT_C2_MP_SUPPORTED;
715 }
716
717 fadt->reset_reg.space_id = 1;
718 fadt->reset_reg.bit_width = 8;
719 fadt->reset_reg.bit_offset = 0;
720 fadt->reset_reg.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
721 fadt->reset_reg.addrl = 0xcf9;
722 fadt->reset_reg.addrh = 0;
723
724 fadt->reset_value = 6;
725
726 fadt->x_pm1a_evt_blk.space_id = 1;
727 fadt->x_pm1a_evt_blk.bit_width = 32;
728 fadt->x_pm1a_evt_blk.bit_offset = 0;
729 fadt->x_pm1a_evt_blk.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
730 fadt->x_pm1a_evt_blk.addrl = pmbase;
731 fadt->x_pm1a_evt_blk.addrh = 0x0;
732
733 fadt->x_pm1b_evt_blk.space_id = 1;
734 fadt->x_pm1b_evt_blk.bit_width = 0;
735 fadt->x_pm1b_evt_blk.bit_offset = 0;
736 fadt->x_pm1b_evt_blk.access_size = 0;
737 fadt->x_pm1b_evt_blk.addrl = 0x0;
738 fadt->x_pm1b_evt_blk.addrh = 0x0;
739
740 fadt->x_pm1a_cnt_blk.space_id = 1;
741 fadt->x_pm1a_cnt_blk.bit_width = 16;
742 fadt->x_pm1a_cnt_blk.bit_offset = 0;
743 fadt->x_pm1a_cnt_blk.access_size = ACPI_ACCESS_SIZE_WORD_ACCESS;
744 fadt->x_pm1a_cnt_blk.addrl = pmbase + 0x4;
745 fadt->x_pm1a_cnt_blk.addrh = 0x0;
746
747 fadt->x_pm1b_cnt_blk.space_id = 1;
748 fadt->x_pm1b_cnt_blk.bit_width = 0;
749 fadt->x_pm1b_cnt_blk.bit_offset = 0;
750 fadt->x_pm1b_cnt_blk.access_size = 0;
751 fadt->x_pm1b_cnt_blk.addrl = 0x0;
752 fadt->x_pm1b_cnt_blk.addrh = 0x0;
753
754 fadt->x_pm2_cnt_blk.space_id = 1;
755 fadt->x_pm2_cnt_blk.bit_width = 8;
756 fadt->x_pm2_cnt_blk.bit_offset = 0;
757 fadt->x_pm2_cnt_blk.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
758 fadt->x_pm2_cnt_blk.addrl = pmbase + 0x50;
759 fadt->x_pm2_cnt_blk.addrh = 0x0;
760
761 fadt->x_pm_tmr_blk.space_id = 1;
762 fadt->x_pm_tmr_blk.bit_width = 32;
763 fadt->x_pm_tmr_blk.bit_offset = 0;
764 fadt->x_pm_tmr_blk.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
765 fadt->x_pm_tmr_blk.addrl = pmbase + 0x8;
766 fadt->x_pm_tmr_blk.addrh = 0x0;
767
768 fadt->x_gpe0_blk.space_id = 1;
769 fadt->x_gpe0_blk.bit_width = 128;
770 fadt->x_gpe0_blk.bit_offset = 0;
771 fadt->x_gpe0_blk.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
772 fadt->x_gpe0_blk.addrl = pmbase + 0x20;
773 fadt->x_gpe0_blk.addrh = 0x0;
774
775 fadt->x_gpe1_blk.space_id = 1;
776 fadt->x_gpe1_blk.bit_width = 0;
777 fadt->x_gpe1_blk.bit_offset = 0;
778 fadt->x_gpe1_blk.access_size = 0;
779 fadt->x_gpe1_blk.addrl = 0x0;
780 fadt->x_gpe1_blk.addrh = 0x0;
781}
782
Alexander Couzens5eea4582015-04-12 22:18:55 +0200783static void southbridge_fill_ssdt(device_t device)
Vladimir Serbinenko36fa5b82014-10-28 23:43:20 +0100784{
785 device_t dev = dev_find_slot(0, PCI_DEVFN(0x1f,0));
786 config_t *chip = dev->chip_info;
787
788 intel_acpi_pcie_hotplug_generator(chip->pcie_hotplug_map, 8);
789}
790
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100791static struct pci_operations pci_ops = {
792 .set_subsystem = set_subsystem,
793};
794
795static struct device_operations device_ops = {
796 .read_resources = pch_lpc_read_resources,
797 .set_resources = pci_dev_set_resources,
798 .enable_resources = pch_lpc_enable_resources,
Vladimir Serbinenko334fd8e2014-10-05 11:10:35 +0200799 .acpi_inject_dsdt_generator = southbridge_inject_dsdt,
Vladimir Serbinenko36fa5b82014-10-28 23:43:20 +0100800 .acpi_fill_ssdt_generator = southbridge_fill_ssdt,
Vladimir Serbinenko35c0f432014-09-02 22:25:36 +0200801 .write_acpi_tables = acpi_write_hpet,
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100802 .init = lpc_init,
803 .enable = pch_lpc_enable,
Kyösti Mälkkid0e212c2015-02-26 20:47:47 +0200804 .scan_bus = scan_lpc_bus,
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100805 .ops_pci = &pci_ops,
806};
807
808
Vladimir Serbinenkob7d87882014-02-19 22:01:35 +0100809static const unsigned short pci_device_ids[] = { 0x3b07, 0x3b09, 0 };
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100810
811static const struct pci_driver pch_lpc __pci_driver = {
812 .ops = &device_ops,
813 .vendor = PCI_VENDOR_ID_INTEL,
814 .devices = pci_device_ids,
815};