blob: 6ed3dce8b98c21338164d9574cf7e1bdf8e233e5 [file] [log] [blame]
Angel Pons182dbde2020-04-02 23:49:05 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Kyösti Mälkkie28bd4a2013-09-07 11:38:56 +03002
Kyösti Mälkki13f66502019-03-03 08:01:05 +02003#include <device/mmio.h>
Kyösti Mälkkif1b58b72019-03-01 13:43:02 +02004#include <device/pci_ops.h>
Nico Huber6760e0b2019-11-17 02:34:53 +01005#include <cf9_reset.h>
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07006#include <ip_checksum.h>
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07007#include <device/pci_def.h>
Kyösti Mälkkif555a582020-01-06 19:41:42 +02008#include <device/smbus_host.h>
Patrick Rudolph45d4b172019-03-24 12:27:31 +01009#include <southbridge/intel/common/gpio.h>
10#include <southbridge/intel/common/pmbase.h>
Patrick Rudolpha1e9eef2019-03-25 11:47:36 +010011#include <southbridge/intel/common/rcba.h>
Patrick Rudolph45d4b172019-03-24 12:27:31 +010012
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -070013/* For DMI bar. */
Elyes HAOUAS10b65dc2018-06-16 18:39:26 +020014#include <northbridge/intel/sandybridge/sandybridge.h>
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -070015
Elyes HAOUASbf0970e2019-03-21 11:10:03 +010016#include "pch.h"
Arthur Heymans6beaef92019-06-16 23:29:23 +020017#include "chip.h"
Elyes HAOUASbf0970e2019-03-21 11:10:03 +010018
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -070019#define SOUTHBRIDGE PCI_DEV(0, 0x1f, 0)
20
Angel Pons6cd6e712020-05-07 00:54:42 +020021static void wait_iobp(void)
Kyösti Mälkkie28bd4a2013-09-07 11:38:56 +030022{
Patrick Rudolpha1e9eef2019-03-25 11:47:36 +010023 while (RCBA8(IOBPS) & 1)
Felix Held2adab282017-07-29 16:48:10 +020024 ; // implement timeout?
Kyösti Mälkkie28bd4a2013-09-07 11:38:56 +030025}
Vladimir Serbinenko332f14b2014-09-05 16:29:41 +020026
Angel Pons6cd6e712020-05-07 00:54:42 +020027static u32 read_iobp(u32 address)
Vladimir Serbinenko332f14b2014-09-05 16:29:41 +020028{
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -070029 u32 ret;
Vladimir Serbinenko332f14b2014-09-05 16:29:41 +020030
Patrick Rudolpha1e9eef2019-03-25 11:47:36 +010031 RCBA32(IOBPIRI) = address;
32 RCBA16(IOBPS) = (RCBA16(IOBPS) & 0x1ff) | 0x600;
Felix Held2adab282017-07-29 16:48:10 +020033 wait_iobp();
Patrick Rudolpha1e9eef2019-03-25 11:47:36 +010034 ret = RCBA32(IOBPD);
Felix Held2adab282017-07-29 16:48:10 +020035 wait_iobp();
Elyes HAOUAS3c3f8362019-05-22 20:31:48 +020036 RCBA8(IOBPS); // call wait_iobp() instead here?
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -070037 return ret;
38}
Vladimir Serbinenko332f14b2014-09-05 16:29:41 +020039
Angel Pons6cd6e712020-05-07 00:54:42 +020040static void write_iobp(u32 address, u32 val)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -070041{
Felix Held2adab282017-07-29 16:48:10 +020042 /* this function was probably pch_iobp_update with the andvalue
43 * being 0. So either the IOBP read can be removed or this function
44 * and the pch_iobp_update function in ramstage could be merged */
45 read_iobp(address);
Patrick Rudolpha1e9eef2019-03-25 11:47:36 +010046 RCBA16(IOBPS) = (RCBA16(IOBPS) & 0x1ff) | 0x600;
Felix Held2adab282017-07-29 16:48:10 +020047 wait_iobp();
Vladimir Serbinenko332f14b2014-09-05 16:29:41 +020048
Patrick Rudolpha1e9eef2019-03-25 11:47:36 +010049 RCBA32(IOBPD) = val;
Felix Held2adab282017-07-29 16:48:10 +020050 wait_iobp();
Patrick Rudolpha1e9eef2019-03-25 11:47:36 +010051 RCBA16(IOBPS) = (RCBA16(IOBPS) & 0x1ff) | 0x600;
52
Elyes HAOUAS3c3f8362019-05-22 20:31:48 +020053 RCBA8(IOBPS); // call wait_iobp() instead here?
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -070054}
55
Patrick Rudolph6aca7e62019-03-26 18:22:36 +010056void early_pch_init_native_dmi_pre(void)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -070057{
Patrick Rudolphbf743502019-03-25 17:05:20 +010058 /* Link Capabilities Register */
Patrick Rudolph4f8b1082019-07-14 11:54:58 +020059 RCBA32(LCAP) = (RCBA32(LCAP) & ~0x3fc00) |
Patrick Rudolphbf743502019-03-25 17:05:20 +010060 (3 << 10) | // L0s and L1 entry supported
61 (2 << 12) | // L0s 128 ns to less than 256 ns
62 (2 << 15); // L1 2 us to less than 4 us
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -070063
Patrick Rudolphbf743502019-03-25 17:05:20 +010064 RCBA32(0x2340) = (RCBA32(0x2340) & ~0xff0000) | (0x3a << 16);
Patrick Rudolph4f8b1082019-07-14 11:54:58 +020065 RCBA8(DLCTL2) = (RCBA8(DLCTL2) & ~0xf) | 2;
Patrick Rudolph6aca7e62019-03-26 18:22:36 +010066}
Patrick Rudolphbf743502019-03-25 17:05:20 +010067
Patrick Rudolph6aca7e62019-03-26 18:22:36 +010068void early_pch_init_native_dmi_post(void)
69{
Patrick Rudolph4f8b1082019-07-14 11:54:58 +020070 RCBA32(CIR0); // !!! = 0x01200654
71 RCBA32(CIR0) = 0x01200654;
72 RCBA32(CIR0); // !!! = 0x01200654
73 RCBA32(CIR0) = 0x012a0654;
74 RCBA32(CIR0); // !!! = 0x012a0654
75 RCBA8(UPDCR); // !!! = 0x00
76 RCBA8(UPDCR) = 0x05;
Patrick Rudolphbf743502019-03-25 17:05:20 +010077
78 /*
79 * Virtual Channel resources must match settings in DMIBAR!
80 *
81 * Some of the following settings are taken from
82 * "Intel Core i5-600, i3-500 Desktop Processor Series and Intel
83 * Pentium Desktop Processor 6000 Series Vol. 2" datasheet and
84 * serialice traces.
85 */
86
87 /* Virtual Channel 0 Resource Control Register.
88 * Enable channel.
89 * Set Virtual Channel Identifier.
90 * Map TC0 and TC3 and TC4 to VC0.
91 */
92
Patrick Rudolph4f8b1082019-07-14 11:54:58 +020093 RCBA32(V0CTL) = (1 << 31) | (0 << 24) | (0x0c << 1) | 1;
Patrick Rudolphbf743502019-03-25 17:05:20 +010094
95 /* Virtual Channel 1 Resource Control Register.
96 * Enable channel.
97 * Set Virtual Channel Identifier.
98 * Map TC1 and TC5 to VC1.
99 */
Patrick Rudolph4f8b1082019-07-14 11:54:58 +0200100 RCBA32(V1CTL) = (1 << 31) | (1 << 24) | (0x11 << 1);
Patrick Rudolphbf743502019-03-25 17:05:20 +0100101 /* Read back register */
Patrick Rudolph4f8b1082019-07-14 11:54:58 +0200102 RCBA32(V1CTL);
Patrick Rudolphbf743502019-03-25 17:05:20 +0100103
104 /* Virtual Channel private Resource Control Register.
105 * Enable channel.
106 * Set Virtual Channel Identifier.
107 * Map TC2 and TC6 to VCp.
108 */
Patrick Rudolph4f8b1082019-07-14 11:54:58 +0200109 RCBA32(CIR31) = (1 << 31) | (2 << 24) | (0x22 << 1);
Patrick Rudolphbf743502019-03-25 17:05:20 +0100110 /* Read back register */
Patrick Rudolph4f8b1082019-07-14 11:54:58 +0200111 RCBA32(CIR31);
Patrick Rudolphbf743502019-03-25 17:05:20 +0100112
113 /* Virtual Channel ME Resource Control Register.
114 * Enable channel.
115 * Set Virtual Channel Identifier.
116 * Map TC7 to VCm.
117 */
Patrick Rudolph4f8b1082019-07-14 11:54:58 +0200118 RCBA32(CIR32) = (1 << 31) | (7 << 24) | (0x40 << 1);
Patrick Rudolphbf743502019-03-25 17:05:20 +0100119
120 /* Lock Virtual Channel Resource control register. */
Patrick Rudolph4f8b1082019-07-14 11:54:58 +0200121 RCBA32(CIR0) |= TCLOCKDN;
Patrick Rudolphbf743502019-03-25 17:05:20 +0100122 /* Read back register */
Patrick Rudolph4f8b1082019-07-14 11:54:58 +0200123 RCBA32(CIR0);
Patrick Rudolphbf743502019-03-25 17:05:20 +0100124
125 /* Wait for virtual channels negotiation pending */
Patrick Rudolph4f8b1082019-07-14 11:54:58 +0200126 while (RCBA16(V0STS) & VCNEGPND)
Patrick Rudolphbf743502019-03-25 17:05:20 +0100127 ;
Patrick Rudolph4f8b1082019-07-14 11:54:58 +0200128 while (RCBA16(V1STS) & VCNEGPND)
Patrick Rudolphbf743502019-03-25 17:05:20 +0100129 ;
130 while (RCBA16(0x2036) & VCNEGPND)
131 ;
132 while (RCBA16(0x2046) & VCNEGPND)
133 ;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700134}
135
Angel Pons6cd6e712020-05-07 00:54:42 +0200136void early_pch_init_native(void)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700137{
Angel Pons6cd6e712020-05-07 00:54:42 +0200138 pci_write_config8(SOUTHBRIDGE, 0xa6, pci_read_config8(SOUTHBRIDGE, 0xa6) | 2);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700139
Patrick Rudolph4f8b1082019-07-14 11:54:58 +0200140 RCBA32(CIR1) = 0x00109000;
141 RCBA32(REC); // !!! = 0x00000000
142 RCBA32(REC) = 0x40000000;
Patrick Rudolpha1e9eef2019-03-25 11:47:36 +0100143 RCBA32(0x100c) = 0x01110000;
144 RCBA8(0x2340) = 0x1b;
Patrick Rudolph4f8b1082019-07-14 11:54:58 +0200145 RCBA32(CIR6); // !!! = 0x0a080000
146 RCBA32(CIR6) = 0x0a280000;
Elyes HAOUAS3c3f8362019-05-22 20:31:48 +0200147 RCBA32(0x2310); // !!! = 0xc809605b
Patrick Rudolpha1e9eef2019-03-25 11:47:36 +0100148 RCBA32(0x2310) = 0xa809605b;
Patrick Rudolph4f8b1082019-07-14 11:54:58 +0200149 RCBA32(DMC2) = 0x00854c74;
150 RCBA8(RPC); // !!! = 0x00
Elyes HAOUAS3c3f8362019-05-22 20:31:48 +0200151 RCBA32(0x2310); // !!! = 0xa809605b
Patrick Rudolpha1e9eef2019-03-25 11:47:36 +0100152 RCBA32(0x2310) = 0xa809605b;
Elyes HAOUAS3c3f8362019-05-22 20:31:48 +0200153 RCBA32(0x2310); // !!! = 0xa809605b
Patrick Rudolpha1e9eef2019-03-25 11:47:36 +0100154 RCBA32(0x2310) = 0xa809605b;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700155
Felix Held2adab282017-07-29 16:48:10 +0200156 write_iobp(0xea007f62, 0x00590133);
157 write_iobp(0xec007f62, 0x00590133);
158 write_iobp(0xec007f64, 0x59555588);
159 write_iobp(0xea0040b9, 0x0001051c);
160 write_iobp(0xeb0040a1, 0x800084ff);
161 write_iobp(0xec0040a1, 0x800084ff);
162 write_iobp(0xea004001, 0x00008400);
163 write_iobp(0xeb004002, 0x40201758);
164 write_iobp(0xec004002, 0x40201758);
165 write_iobp(0xea004002, 0x00601758);
166 write_iobp(0xea0040a1, 0x810084ff);
167 write_iobp(0xeb0040b1, 0x0001c598);
168 write_iobp(0xec0040b1, 0x0001c598);
169 write_iobp(0xeb0040b6, 0x0001c598);
170 write_iobp(0xea0000a9, 0x80ff969f);
171 write_iobp(0xea0001a9, 0x80ff969f);
172 write_iobp(0xeb0040b2, 0x0001c396);
173 write_iobp(0xeb0040b3, 0x0001c396);
174 write_iobp(0xec0040b2, 0x0001c396);
175 write_iobp(0xea0001a9, 0x80ff94ff);
176 write_iobp(SATA_IOBP_SP0G3IR, 0x0088037f);
177 write_iobp(0xea0000a9, 0x80ff94ff);
178 write_iobp(SATA_IOBP_SP1G3IR, 0x0088037f);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700179
Felix Held2adab282017-07-29 16:48:10 +0200180 write_iobp(0xea007f05, 0x00010642);
181 write_iobp(0xea0040b7, 0x0001c91c);
182 write_iobp(0xea0040b8, 0x0001c91c);
183 write_iobp(0xeb0040a1, 0x820084ff);
184 write_iobp(0xec0040a1, 0x820084ff);
185 write_iobp(0xea007f0a, 0xc2480000);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700186
Felix Held2adab282017-07-29 16:48:10 +0200187 write_iobp(0xec00404d, 0x1ff177f);
188 write_iobp(0xec000084, 0x5a600000);
189 write_iobp(0xec000184, 0x5a600000);
190 write_iobp(0xec000284, 0x5a600000);
191 write_iobp(0xec000384, 0x5a600000);
192 write_iobp(0xec000094, 0x000f0501);
193 write_iobp(0xec000194, 0x000f0501);
194 write_iobp(0xec000294, 0x000f0501);
195 write_iobp(0xec000394, 0x000f0501);
196 write_iobp(0xec000096, 0x00000001);
197 write_iobp(0xec000196, 0x00000001);
198 write_iobp(0xec000296, 0x00000001);
199 write_iobp(0xec000396, 0x00000001);
200 write_iobp(0xec000001, 0x00008c08);
201 write_iobp(0xec000101, 0x00008c08);
202 write_iobp(0xec000201, 0x00008c08);
203 write_iobp(0xec000301, 0x00008c08);
204 write_iobp(0xec0040b5, 0x0001c518);
205 write_iobp(0xec000087, 0x06077597);
206 write_iobp(0xec000187, 0x06077597);
207 write_iobp(0xec000287, 0x06077597);
208 write_iobp(0xec000387, 0x06077597);
209 write_iobp(0xea000050, 0x00bb0157);
210 write_iobp(0xea000150, 0x00bb0157);
211 write_iobp(0xec007f60, 0x77777d77);
212 write_iobp(0xea00008d, 0x01320000);
213 write_iobp(0xea00018d, 0x01320000);
214 write_iobp(0xec0007b2, 0x04514b5e);
215 write_iobp(0xec00078c, 0x40000200);
216 write_iobp(0xec000780, 0x02000020);
Vladimir Serbinenko332f14b2014-09-05 16:29:41 +0200217}
Patrick Rudolph45d4b172019-03-24 12:27:31 +0100218
219static void pch_enable_bars(void)
220{
Angel Pons6e732d32021-01-28 13:56:18 +0100221 pci_write_config32(PCH_LPC_DEV, RCBA, CONFIG_FIXED_RCBA_MMIO_BASE | 1);
Patrick Rudolph45d4b172019-03-24 12:27:31 +0100222
223 pci_write_config32(PCH_LPC_DEV, PMBASE, DEFAULT_PMBASE | 1);
224
Angel Ponsf4711712020-11-04 00:38:28 +0100225 pci_write_config8(PCH_LPC_DEV, ACPI_CNTL, ACPI_EN);
Patrick Rudolph45d4b172019-03-24 12:27:31 +0100226
227 pci_write_config32(PCH_LPC_DEV, GPIO_BASE, DEFAULT_GPIOBASE | 1);
228
229 /* Enable GPIO functionality. */
230 pci_write_config8(PCH_LPC_DEV, GPIO_CNTL, 0x10);
231}
232
233static void pch_generic_setup(void)
234{
235 RCBA32(GCS) = RCBA32(GCS) | (1 << 5); /* No reset */
236 write_pmbase16(TCO1_CNT, 1 << 11); /* halt timer */
237}
238
Nico Huber6760e0b2019-11-17 02:34:53 +0100239static void pch_enable_gbe(void)
240{
241 uint8_t wanted_buc;
242
243 /* Don't do this in the bootblock, it might be RO. So one
244 couldn't change the setting later in an updated romstage. */
245 if (ENV_BOOTBLOCK)
246 return;
247
248 const struct device *const gbe = pcidev_on_root(0x19, 0);
249 if (gbe && gbe->enabled)
250 wanted_buc = RCBA8(BUC) & ~PCH_DISABLE_GBE;
251 else
252 wanted_buc = RCBA8(BUC) | PCH_DISABLE_GBE;
253
254 if (RCBA8(BUC) != wanted_buc) {
255 RCBA8(BUC) = wanted_buc;
256 /* Be double sure not to reset for naught. */
257 if (RCBA8(BUC) != wanted_buc)
258 return;
259 full_reset();
260 }
261}
262
Arthur Heymansd28d5072019-06-16 23:36:28 +0200263static void pch_enable_lpc_decode(void)
Arthur Heymans6beaef92019-06-16 23:29:23 +0200264{
Arthur Heymansd28d5072019-06-16 23:36:28 +0200265 /*
266 * Enable some common LPC IO ranges:
267 * - 0x2e/0x2f, 0x4e/0x4f often SuperIO
268 * - 0x60/0x64, 0x62/0x66 often KBC/EC
269 * - 0x3f0-0x3f5/0x3f7 FDD
270 * - 0x378-0x37f and 0x778-0x77f LPT
271 * - 0x2f8-0x2ff COMB
272 * - 0x3f8-0x3ff COMA
273 */
274 pci_write_config16(PCH_LPC_DEV, LPC_IO_DEC, 0x0010);
Angel Pons6cd6e712020-05-07 00:54:42 +0200275 pci_write_config16(PCH_LPC_DEV, LPC_EN, CNF2_LPC_EN | CNF1_LPC_EN | MC_LPC_EN
276 | KBC_LPC_EN | FDD_LPC_EN | LPT_LPC_EN | COMB_LPC_EN | COMA_LPC_EN);
Arthur Heymansd28d5072019-06-16 23:36:28 +0200277
Arthur Heymans6beaef92019-06-16 23:29:23 +0200278 const struct device *dev = pcidev_on_root(0x1f, 0);
279 const struct southbridge_intel_bd82x6x_config *config = NULL;
280
281 /* Set up generic decode ranges */
282 if (!dev)
283 return;
284 if (dev->chip_info)
285 config = dev->chip_info;
286 if (!config)
287 return;
288
289 pci_write_config32(PCH_LPC_DEV, LPC_GEN1_DEC, config->gen1_dec);
290 pci_write_config32(PCH_LPC_DEV, LPC_GEN2_DEC, config->gen2_dec);
291 pci_write_config32(PCH_LPC_DEV, LPC_GEN3_DEC, config->gen3_dec);
292 pci_write_config32(PCH_LPC_DEV, LPC_GEN4_DEC, config->gen4_dec);
293}
294
Arthur Heymans2b28a162019-11-12 17:21:08 +0100295__weak void mainboard_pch_lpc_setup(void)
296{
297}
298
Patrick Rudolph45d4b172019-03-24 12:27:31 +0100299void early_pch_init(void)
300{
Arthur Heymansd28d5072019-06-16 23:36:28 +0200301 pch_enable_lpc_decode();
302
Arthur Heymans2b28a162019-11-12 17:21:08 +0100303 mainboard_pch_lpc_setup();
Arthur Heymans6beaef92019-06-16 23:29:23 +0200304
Patrick Rudolph45d4b172019-03-24 12:27:31 +0100305 pch_enable_bars();
306
307 pch_generic_setup();
308
Nico Huber6760e0b2019-11-17 02:34:53 +0100309 pch_enable_gbe();
310
Patrick Rudolph45d4b172019-03-24 12:27:31 +0100311 setup_pch_gpios(&mainboard_gpio_map);
Kyösti Mälkkiffa520f2020-01-07 12:00:31 +0200312
313 if (ENV_ROMSTAGE)
314 enable_smbus();
Patrick Rudolph45d4b172019-03-24 12:27:31 +0100315}