blob: df749b9485bc71eaae6782967c2ca96dbb8a65e0 [file] [log] [blame]
Patrick Georgi021b7032012-11-06 11:05:38 +01001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2012 secunet Security Networks AG
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.
Patrick Georgi021b7032012-11-06 11:05:38 +010015 */
16
Elyes HAOUASec16e932016-10-07 18:22:44 +020017/* __PRE_RAM__ means: use "unsigned" for device, not a struct. */
Patrick Georgi021b7032012-11-06 11:05:38 +010018
19#include <stdint.h>
20#include <string.h>
21#include <arch/io.h>
Patrick Georgi021b7032012-11-06 11:05:38 +010022#include <cpu/x86/lapic.h>
23#include <cpu/x86/msr.h>
24#include <cpu/x86/tsc.h>
Kyösti Mälkki15fa9922016-06-17 10:00:28 +030025#include <cpu/intel/romstage.h>
Kyösti Mälkki12d681b2014-06-14 18:51:34 +030026#include <arch/acpi.h>
Patrick Georgi021b7032012-11-06 11:05:38 +010027#include <cbmem.h>
28#include <lib.h>
29#include <pc80/mc146818rtc.h>
30#include <console/console.h>
31#include <southbridge/intel/i82801ix/i82801ix.h>
32#include <northbridge/intel/gm45/gm45.h>
Antonello Dettori6321d7c2016-03-07 01:59:48 +000033#include <superio/smsc/lpc47n227/lpc47n227.h>
Patrick Georgi021b7032012-11-06 11:05:38 +010034
35#define LPC_DEV PCI_DEV(0, 0x1f, 0)
36#define SERIAL_DEV PNP_DEV(0x2e, LPC47N227_SP1)
37
38static void default_southbridge_gpio_setup(void)
39{
40 /* Enable GPIOs [31:0]. */
41 outl(0x197e7dfe, DEFAULT_GPIOBASE + 0x00);
42 /* Set input/output mode [31:0] (0 == out, 1 == in). */
43 outl(0xe0ea43fe, DEFAULT_GPIOBASE + 0x04);
44 /* Set gpio levels [31:0]. orig: 0x01140800 (~SATA0, ~SATA1, GSM, BT,
45 WLAN, ~ANTMUX, ~GPIO12,
46 ~SUSPWR, SMBALERT) */
47 outl(0x00000800, DEFAULT_GPIOBASE + 0x0c);
48
49 /* Disable blink [31:0]. */
50 outl(0x00000000, DEFAULT_GPIOBASE + 0x18);
51 /* Set input inversion [31:0]. */
52 outl(0x00000182, DEFAULT_GPIOBASE + 0x2c);
53
54 /* Enable GPIOs [60:32]. */
55 outl(0x130300fe, DEFAULT_GPIOBASE + 0x30);
56 /* Set input/output mode [60:32] (0 == out, 1 == in). */
57 outl(0x0e55ffb0, DEFAULT_GPIOBASE + 0x34);
58 /* Set gpio levels [60:32]. orig: 0x10020046 (LNKALERT, ~ATAIO,
59 DMITERM, TXT, ~CLKSATA,
60 GPS, AUDIO) */
61 outl(0x10020042, DEFAULT_GPIOBASE + 0x38);
62}
63
64static void early_lpc_setup(void)
65{
66 /* Set up SuperIO LPC forwards */
67
68 /* Configure serial IRQs.*/
69 pci_write_config8(LPC_DEV, D31F0_SERIRQ_CNTL, 0xd0);
70 /* Map COMa on 0x3f8, COMb on 0x2f8. */
71 pci_write_config16(LPC_DEV, D31F0_LPC_IODEC, 0x0010);
72 /* Enable COMa, COMb, Kbd, SuperIO at 0x2e, MCs at 0x4e and 0x62/66. */
73 pci_write_config16(LPC_DEV, D31F0_LPC_EN, 0x3c03);
74}
75
76static void default_superio_gpio_setup(void)
77{
78 /* Original settings:
79 idx 30 31 32 33 34 35 36 37 38 39
80 val 60 00 00 40 00 ff 00 e0 00 80
81 def 00 00 00 00 00 00 00 00 00 80
82
83 Values:
84 GP1 GP2 GP3 GP4
85 fd 17 88 14
86 */
87 const device_t sio = PNP_DEV(0x2e, 0);
88
89 /* Enter super-io's configuration state. */
90 pnp_enter_conf_state(sio);
91
92 /* Set lpc47n227's runtime register block's base address. */
93 pnp_write_config(sio, 0x30, 0x600 >> 4);
94
95 /* Set GP23 to alternate function. */
96 pnp_write_config(sio, 0x33, 0x40);
97
98 /* Set GP30 - GP37 to output mode: COM control */
99 pnp_write_config(sio, 0x35, 0xff);
100
101 /* Set GP45 - GP47 to output mode. */
102 pnp_write_config(sio, 0x37, 0xe0);
103
104 /* Set nIO_PME to open drain. */
105 pnp_write_config(sio, 0x39, 0x80);
106
107 /* Exit configuration state. */
108 pnp_exit_conf_state(sio);
109
110
111 /* Enable decoding of 0x600-0x60f through lpc. */
112 pci_write_config32(LPC_DEV, D31F0_GEN1_DEC, 0x000c0601);
113
114 /* Set GPIO output values: */
115 outb(0x88, 0x600 + 0xb + 3); /* GP30 - GP37 */
116 outb(0x10, 0x600 + 0xb + 4); /* GP40 - GP47 */
117}
118
Kyösti Mälkki15fa9922016-06-17 10:00:28 +0300119void mainboard_romstage_entry(unsigned long bist)
Patrick Georgi021b7032012-11-06 11:05:38 +0100120{
121 sysinfo_t sysinfo;
122 int s3resume = 0;
Kyösti Mälkki886a5432013-10-13 20:41:57 +0300123 int cbmem_initted;
Patrick Georgi021b7032012-11-06 11:05:38 +0100124 u16 reg16;
125
126 /* basic northbridge setup, including MMCONF BAR */
127 gm45_early_init();
128
129 if (bist == 0)
130 enable_lapic();
131
132 /* First, run everything needed for console output. */
133 i82801ix_early_init();
134 early_lpc_setup();
135 default_superio_gpio_setup();
136 lpc47n227_enable_serial(SERIAL_DEV, CONFIG_TTYS0_BASE);
137 console_init();
138 printk(BIOS_DEBUG, "running main(bist = %lu)\n", bist);
139
140 reg16 = pci_read_config16(LPC_DEV, D31F0_GEN_PMCON_3);
141 pci_write_config16(LPC_DEV, D31F0_GEN_PMCON_3, reg16);
142 if ((MCHBAR16(SSKPD_MCHBAR) == 0xCAFE) && !(reg16 & (1 << 9))) {
143 printk(BIOS_DEBUG, "soft reset detected, rebooting properly\n");
144 gm45_early_reset();
145 }
146
147 default_southbridge_gpio_setup();
148
149 /* ASPM related setting, set early by original BIOS. */
150 DMIBAR16(0x204) &= ~(3 << 10);
151
152 /* Check for S3 resume. */
153 const u32 pm1_cnt = inl(DEFAULT_PMBASE + 0x04);
154 if (((pm1_cnt >> 10) & 7) == 5) {
Kyösti Mälkki12d681b2014-06-14 18:51:34 +0300155 if (acpi_s3_resume_allowed()) {
156 printk(BIOS_DEBUG, "Resume from S3 detected.\n");
157 s3resume = 1;
158 /* Clear SLP_TYPE. This will break stage2 but
159 * we care for that when we get there.
160 */
161 outl(pm1_cnt & ~(7 << 10), DEFAULT_PMBASE + 0x04);
162 } else {
163 printk(BIOS_DEBUG, "Resume from S3 detected, but disabled.\n");
164 }
Patrick Georgi021b7032012-11-06 11:05:38 +0100165 }
166
167 /* RAM initialization */
168 enter_raminit_or_reset();
Vladimir Serbinenko56ae8a02014-08-16 10:59:02 +0200169 memset(&sysinfo, 0, sizeof(sysinfo));
Patrick Georgi021b7032012-11-06 11:05:38 +0100170 get_gmch_info(&sysinfo);
Vladimir Serbinenkoc4d89482014-06-05 09:14:48 +0200171 sysinfo.spd_map[0] = 0x50;
172 sysinfo.spd_map[1] = 0;
173 sysinfo.spd_map[2] = 0x52;
174 sysinfo.spd_map[3] = 0;
Vladimir Serbinenko56ae8a02014-08-16 10:59:02 +0200175 sysinfo.enable_igd = 1;
176 sysinfo.enable_peg = 0;
Patrick Georgi021b7032012-11-06 11:05:38 +0100177 raminit(&sysinfo, s3resume);
178
Vladimir Serbinenko020dc0e2014-08-12 22:50:40 +0200179 init_pm(&sysinfo, 1);
Patrick Georgi021b7032012-11-06 11:05:38 +0100180
181 i82801ix_dmi_setup();
182 gm45_late_init(sysinfo.stepping);
183 i82801ix_dmi_poll_vc1();
184
185 MCHBAR16(SSKPD_MCHBAR) = 0xCAFE;
186
187 init_iommu();
188
Nico Huber8a44b0b2015-11-12 20:16:18 +0100189 cbmem_initted = !cbmem_recovery(s3resume);
Patrick Georgi021b7032012-11-06 11:05:38 +0100190#if CONFIG_HAVE_ACPI_RESUME
Patrick Georgi021b7032012-11-06 11:05:38 +0100191 /* If there is no high memory area, we didn't boot before, so
192 * this is not a resume. In that case we just create the cbmem toc.
193 */
Kyösti Mälkki886a5432013-10-13 20:41:57 +0300194 if (s3resume && cbmem_initted) {
Kyösti Mälkkic7204df2016-06-17 22:52:16 +0300195 acpi_prepare_for_resume();
Patrick Georgi021b7032012-11-06 11:05:38 +0100196
197 /* Magic for S3 resume */
198 pci_write_config32(PCI_DEV(0, 0, 0), D0F0_SKPD, SKPAD_ACPI_S3_MAGIC);
Vladimir Serbinenkod25273e2014-08-13 23:06:07 +0200199 } else {
200 /* Magic for S3 resume */
201 pci_write_config32(PCI_DEV(0, 0, 0), D0F0_SKPD, SKPAD_NORMAL_BOOT_MAGIC);
Patrick Georgi021b7032012-11-06 11:05:38 +0100202 }
203#endif
204 printk(BIOS_SPEW, "exit main()\n");
205}