blob: 8433bb2dd548828de08eae606813c8355d18949a [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)
Patrick Rudolph873178b2023-10-02 07:06:45 +020020#define PCI_DEVICE_ID_INTEL_UM77 0x1e58
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -070021
Angel Pons6cd6e712020-05-07 00:54:42 +020022static void wait_iobp(void)
Kyösti Mälkkie28bd4a2013-09-07 11:38:56 +030023{
Patrick Rudolpha1e9eef2019-03-25 11:47:36 +010024 while (RCBA8(IOBPS) & 1)
Felix Held2adab282017-07-29 16:48:10 +020025 ; // implement timeout?
Kyösti Mälkkie28bd4a2013-09-07 11:38:56 +030026}
Vladimir Serbinenko332f14b2014-09-05 16:29:41 +020027
Angel Pons6cd6e712020-05-07 00:54:42 +020028static u32 read_iobp(u32 address)
Vladimir Serbinenko332f14b2014-09-05 16:29:41 +020029{
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -070030 u32 ret;
Vladimir Serbinenko332f14b2014-09-05 16:29:41 +020031
Patrick Rudolpha1e9eef2019-03-25 11:47:36 +010032 RCBA32(IOBPIRI) = address;
33 RCBA16(IOBPS) = (RCBA16(IOBPS) & 0x1ff) | 0x600;
Felix Held2adab282017-07-29 16:48:10 +020034 wait_iobp();
Patrick Rudolpha1e9eef2019-03-25 11:47:36 +010035 ret = RCBA32(IOBPD);
Felix Held2adab282017-07-29 16:48:10 +020036 wait_iobp();
Elyes HAOUAS3c3f8362019-05-22 20:31:48 +020037 RCBA8(IOBPS); // call wait_iobp() instead here?
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -070038 return ret;
39}
Vladimir Serbinenko332f14b2014-09-05 16:29:41 +020040
Angel Pons6cd6e712020-05-07 00:54:42 +020041static void write_iobp(u32 address, u32 val)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -070042{
Felix Held2adab282017-07-29 16:48:10 +020043 /* this function was probably pch_iobp_update with the andvalue
44 * being 0. So either the IOBP read can be removed or this function
45 * and the pch_iobp_update function in ramstage could be merged */
46 read_iobp(address);
Patrick Rudolpha1e9eef2019-03-25 11:47:36 +010047 RCBA16(IOBPS) = (RCBA16(IOBPS) & 0x1ff) | 0x600;
Felix Held2adab282017-07-29 16:48:10 +020048 wait_iobp();
Vladimir Serbinenko332f14b2014-09-05 16:29:41 +020049
Patrick Rudolpha1e9eef2019-03-25 11:47:36 +010050 RCBA32(IOBPD) = val;
Felix Held2adab282017-07-29 16:48:10 +020051 wait_iobp();
Patrick Rudolpha1e9eef2019-03-25 11:47:36 +010052 RCBA16(IOBPS) = (RCBA16(IOBPS) & 0x1ff) | 0x600;
53
Elyes HAOUAS3c3f8362019-05-22 20:31:48 +020054 RCBA8(IOBPS); // call wait_iobp() instead here?
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -070055}
56
Patrick Rudolph6aca7e62019-03-26 18:22:36 +010057void early_pch_init_native_dmi_pre(void)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -070058{
Patrick Rudolphbf743502019-03-25 17:05:20 +010059 /* Link Capabilities Register */
Patrick Rudolph4f8b1082019-07-14 11:54:58 +020060 RCBA32(LCAP) = (RCBA32(LCAP) & ~0x3fc00) |
Patrick Rudolphbf743502019-03-25 17:05:20 +010061 (3 << 10) | // L0s and L1 entry supported
62 (2 << 12) | // L0s 128 ns to less than 256 ns
63 (2 << 15); // L1 2 us to less than 4 us
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -070064
Patrick Rudolphbf743502019-03-25 17:05:20 +010065 RCBA32(0x2340) = (RCBA32(0x2340) & ~0xff0000) | (0x3a << 16);
Patrick Rudolph4f8b1082019-07-14 11:54:58 +020066 RCBA8(DLCTL2) = (RCBA8(DLCTL2) & ~0xf) | 2;
Patrick Rudolph6aca7e62019-03-26 18:22:36 +010067}
Patrick Rudolphbf743502019-03-25 17:05:20 +010068
Patrick Rudolph6aca7e62019-03-26 18:22:36 +010069void early_pch_init_native_dmi_post(void)
70{
Patrick Rudolph4f8b1082019-07-14 11:54:58 +020071 RCBA32(CIR0); // !!! = 0x01200654
72 RCBA32(CIR0) = 0x01200654;
73 RCBA32(CIR0); // !!! = 0x01200654
74 RCBA32(CIR0) = 0x012a0654;
75 RCBA32(CIR0); // !!! = 0x012a0654
76 RCBA8(UPDCR); // !!! = 0x00
77 RCBA8(UPDCR) = 0x05;
Patrick Rudolphbf743502019-03-25 17:05:20 +010078
79 /*
80 * Virtual Channel resources must match settings in DMIBAR!
81 *
82 * Some of the following settings are taken from
83 * "Intel Core i5-600, i3-500 Desktop Processor Series and Intel
84 * Pentium Desktop Processor 6000 Series Vol. 2" datasheet and
85 * serialice traces.
86 */
87
88 /* Virtual Channel 0 Resource Control Register.
89 * Enable channel.
90 * Set Virtual Channel Identifier.
91 * Map TC0 and TC3 and TC4 to VC0.
92 */
93
Patrick Rudolph4f8b1082019-07-14 11:54:58 +020094 RCBA32(V0CTL) = (1 << 31) | (0 << 24) | (0x0c << 1) | 1;
Patrick Rudolphbf743502019-03-25 17:05:20 +010095
96 /* Virtual Channel 1 Resource Control Register.
97 * Enable channel.
98 * Set Virtual Channel Identifier.
99 * Map TC1 and TC5 to VC1.
100 */
Patrick Rudolph4f8b1082019-07-14 11:54:58 +0200101 RCBA32(V1CTL) = (1 << 31) | (1 << 24) | (0x11 << 1);
Patrick Rudolphbf743502019-03-25 17:05:20 +0100102 /* Read back register */
Patrick Rudolph4f8b1082019-07-14 11:54:58 +0200103 RCBA32(V1CTL);
Patrick Rudolphbf743502019-03-25 17:05:20 +0100104
105 /* Virtual Channel private Resource Control Register.
106 * Enable channel.
107 * Set Virtual Channel Identifier.
108 * Map TC2 and TC6 to VCp.
109 */
Patrick Rudolph4f8b1082019-07-14 11:54:58 +0200110 RCBA32(CIR31) = (1 << 31) | (2 << 24) | (0x22 << 1);
Patrick Rudolphbf743502019-03-25 17:05:20 +0100111 /* Read back register */
Patrick Rudolph4f8b1082019-07-14 11:54:58 +0200112 RCBA32(CIR31);
Patrick Rudolphbf743502019-03-25 17:05:20 +0100113
114 /* Virtual Channel ME Resource Control Register.
115 * Enable channel.
116 * Set Virtual Channel Identifier.
117 * Map TC7 to VCm.
118 */
Patrick Rudolph4f8b1082019-07-14 11:54:58 +0200119 RCBA32(CIR32) = (1 << 31) | (7 << 24) | (0x40 << 1);
Patrick Rudolphbf743502019-03-25 17:05:20 +0100120
121 /* Lock Virtual Channel Resource control register. */
Patrick Rudolph4f8b1082019-07-14 11:54:58 +0200122 RCBA32(CIR0) |= TCLOCKDN;
Patrick Rudolphbf743502019-03-25 17:05:20 +0100123 /* Read back register */
Patrick Rudolph4f8b1082019-07-14 11:54:58 +0200124 RCBA32(CIR0);
Patrick Rudolphbf743502019-03-25 17:05:20 +0100125
126 /* Wait for virtual channels negotiation pending */
Patrick Rudolph4f8b1082019-07-14 11:54:58 +0200127 while (RCBA16(V0STS) & VCNEGPND)
Patrick Rudolphbf743502019-03-25 17:05:20 +0100128 ;
Patrick Rudolph4f8b1082019-07-14 11:54:58 +0200129 while (RCBA16(V1STS) & VCNEGPND)
Patrick Rudolphbf743502019-03-25 17:05:20 +0100130 ;
131 while (RCBA16(0x2036) & VCNEGPND)
132 ;
133 while (RCBA16(0x2046) & VCNEGPND)
134 ;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700135}
136
Angel Pons6cd6e712020-05-07 00:54:42 +0200137void early_pch_init_native(void)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700138{
Patrick Rudolph873178b2023-10-02 07:06:45 +0200139 const u16 dev_id = pci_read_config16(PCH_LPC_DEV, PCI_DEVICE_ID);
140 u8 pcie_ports = (dev_id == PCI_DEVICE_ID_INTEL_UM77) ? 4 : 8;
141
Angel Pons6cd6e712020-05-07 00:54:42 +0200142 pci_write_config8(SOUTHBRIDGE, 0xa6, pci_read_config8(SOUTHBRIDGE, 0xa6) | 2);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700143
Patrick Rudolph873178b2023-10-02 07:06:45 +0200144 /* Clear this bit early for PCIe device detection */
145 for (uint8_t i = 0; i < pcie_ports; i++)
146 pci_update_config32(PCH_PCIE_DEV(i), 0x338, ~(1 << 26), 0);
147
Patrick Rudolph4f8b1082019-07-14 11:54:58 +0200148 RCBA32(CIR1) = 0x00109000;
149 RCBA32(REC); // !!! = 0x00000000
150 RCBA32(REC) = 0x40000000;
Patrick Rudolpha1e9eef2019-03-25 11:47:36 +0100151 RCBA32(0x100c) = 0x01110000;
152 RCBA8(0x2340) = 0x1b;
Patrick Rudolph4f8b1082019-07-14 11:54:58 +0200153 RCBA32(CIR6); // !!! = 0x0a080000
154 RCBA32(CIR6) = 0x0a280000;
Elyes HAOUAS3c3f8362019-05-22 20:31:48 +0200155 RCBA32(0x2310); // !!! = 0xc809605b
Patrick Rudolpha1e9eef2019-03-25 11:47:36 +0100156 RCBA32(0x2310) = 0xa809605b;
Patrick Rudolph4f8b1082019-07-14 11:54:58 +0200157 RCBA32(DMC2) = 0x00854c74;
158 RCBA8(RPC); // !!! = 0x00
Elyes HAOUAS3c3f8362019-05-22 20:31:48 +0200159 RCBA32(0x2310); // !!! = 0xa809605b
Patrick Rudolpha1e9eef2019-03-25 11:47:36 +0100160 RCBA32(0x2310) = 0xa809605b;
Elyes HAOUAS3c3f8362019-05-22 20:31:48 +0200161 RCBA32(0x2310); // !!! = 0xa809605b
Patrick Rudolpha1e9eef2019-03-25 11:47:36 +0100162 RCBA32(0x2310) = 0xa809605b;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700163
Felix Held2adab282017-07-29 16:48:10 +0200164 write_iobp(0xea007f62, 0x00590133);
165 write_iobp(0xec007f62, 0x00590133);
166 write_iobp(0xec007f64, 0x59555588);
167 write_iobp(0xea0040b9, 0x0001051c);
168 write_iobp(0xeb0040a1, 0x800084ff);
169 write_iobp(0xec0040a1, 0x800084ff);
170 write_iobp(0xea004001, 0x00008400);
171 write_iobp(0xeb004002, 0x40201758);
172 write_iobp(0xec004002, 0x40201758);
173 write_iobp(0xea004002, 0x00601758);
174 write_iobp(0xea0040a1, 0x810084ff);
175 write_iobp(0xeb0040b1, 0x0001c598);
176 write_iobp(0xec0040b1, 0x0001c598);
177 write_iobp(0xeb0040b6, 0x0001c598);
178 write_iobp(0xea0000a9, 0x80ff969f);
179 write_iobp(0xea0001a9, 0x80ff969f);
180 write_iobp(0xeb0040b2, 0x0001c396);
181 write_iobp(0xeb0040b3, 0x0001c396);
182 write_iobp(0xec0040b2, 0x0001c396);
183 write_iobp(0xea0001a9, 0x80ff94ff);
184 write_iobp(SATA_IOBP_SP0G3IR, 0x0088037f);
185 write_iobp(0xea0000a9, 0x80ff94ff);
186 write_iobp(SATA_IOBP_SP1G3IR, 0x0088037f);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700187
Felix Held2adab282017-07-29 16:48:10 +0200188 write_iobp(0xea007f05, 0x00010642);
189 write_iobp(0xea0040b7, 0x0001c91c);
190 write_iobp(0xea0040b8, 0x0001c91c);
191 write_iobp(0xeb0040a1, 0x820084ff);
192 write_iobp(0xec0040a1, 0x820084ff);
193 write_iobp(0xea007f0a, 0xc2480000);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700194
Felix Held2adab282017-07-29 16:48:10 +0200195 write_iobp(0xec00404d, 0x1ff177f);
196 write_iobp(0xec000084, 0x5a600000);
197 write_iobp(0xec000184, 0x5a600000);
198 write_iobp(0xec000284, 0x5a600000);
199 write_iobp(0xec000384, 0x5a600000);
200 write_iobp(0xec000094, 0x000f0501);
201 write_iobp(0xec000194, 0x000f0501);
202 write_iobp(0xec000294, 0x000f0501);
203 write_iobp(0xec000394, 0x000f0501);
204 write_iobp(0xec000096, 0x00000001);
205 write_iobp(0xec000196, 0x00000001);
206 write_iobp(0xec000296, 0x00000001);
207 write_iobp(0xec000396, 0x00000001);
208 write_iobp(0xec000001, 0x00008c08);
209 write_iobp(0xec000101, 0x00008c08);
210 write_iobp(0xec000201, 0x00008c08);
211 write_iobp(0xec000301, 0x00008c08);
212 write_iobp(0xec0040b5, 0x0001c518);
213 write_iobp(0xec000087, 0x06077597);
214 write_iobp(0xec000187, 0x06077597);
215 write_iobp(0xec000287, 0x06077597);
216 write_iobp(0xec000387, 0x06077597);
217 write_iobp(0xea000050, 0x00bb0157);
218 write_iobp(0xea000150, 0x00bb0157);
219 write_iobp(0xec007f60, 0x77777d77);
220 write_iobp(0xea00008d, 0x01320000);
221 write_iobp(0xea00018d, 0x01320000);
222 write_iobp(0xec0007b2, 0x04514b5e);
223 write_iobp(0xec00078c, 0x40000200);
224 write_iobp(0xec000780, 0x02000020);
Vladimir Serbinenko332f14b2014-09-05 16:29:41 +0200225}
Patrick Rudolph45d4b172019-03-24 12:27:31 +0100226
227static void pch_enable_bars(void)
228{
Angel Pons6e732d32021-01-28 13:56:18 +0100229 pci_write_config32(PCH_LPC_DEV, RCBA, CONFIG_FIXED_RCBA_MMIO_BASE | 1);
Patrick Rudolph45d4b172019-03-24 12:27:31 +0100230
231 pci_write_config32(PCH_LPC_DEV, PMBASE, DEFAULT_PMBASE | 1);
232
Angel Ponsf4711712020-11-04 00:38:28 +0100233 pci_write_config8(PCH_LPC_DEV, ACPI_CNTL, ACPI_EN);
Patrick Rudolph45d4b172019-03-24 12:27:31 +0100234
235 pci_write_config32(PCH_LPC_DEV, GPIO_BASE, DEFAULT_GPIOBASE | 1);
236
237 /* Enable GPIO functionality. */
238 pci_write_config8(PCH_LPC_DEV, GPIO_CNTL, 0x10);
239}
240
241static void pch_generic_setup(void)
242{
243 RCBA32(GCS) = RCBA32(GCS) | (1 << 5); /* No reset */
244 write_pmbase16(TCO1_CNT, 1 << 11); /* halt timer */
245}
246
Nico Huber6760e0b2019-11-17 02:34:53 +0100247static void pch_enable_gbe(void)
248{
249 uint8_t wanted_buc;
250
251 /* Don't do this in the bootblock, it might be RO. So one
252 couldn't change the setting later in an updated romstage. */
253 if (ENV_BOOTBLOCK)
254 return;
255
256 const struct device *const gbe = pcidev_on_root(0x19, 0);
257 if (gbe && gbe->enabled)
258 wanted_buc = RCBA8(BUC) & ~PCH_DISABLE_GBE;
259 else
260 wanted_buc = RCBA8(BUC) | PCH_DISABLE_GBE;
261
262 if (RCBA8(BUC) != wanted_buc) {
263 RCBA8(BUC) = wanted_buc;
264 /* Be double sure not to reset for naught. */
265 if (RCBA8(BUC) != wanted_buc)
266 return;
267 full_reset();
268 }
269}
270
Arthur Heymansd28d5072019-06-16 23:36:28 +0200271static void pch_enable_lpc_decode(void)
Arthur Heymans6beaef92019-06-16 23:29:23 +0200272{
Arthur Heymansd28d5072019-06-16 23:36:28 +0200273 /*
274 * Enable some common LPC IO ranges:
275 * - 0x2e/0x2f, 0x4e/0x4f often SuperIO
276 * - 0x60/0x64, 0x62/0x66 often KBC/EC
277 * - 0x3f0-0x3f5/0x3f7 FDD
278 * - 0x378-0x37f and 0x778-0x77f LPT
279 * - 0x2f8-0x2ff COMB
280 * - 0x3f8-0x3ff COMA
281 */
282 pci_write_config16(PCH_LPC_DEV, LPC_IO_DEC, 0x0010);
Angel Pons6cd6e712020-05-07 00:54:42 +0200283 pci_write_config16(PCH_LPC_DEV, LPC_EN, CNF2_LPC_EN | CNF1_LPC_EN | MC_LPC_EN
284 | KBC_LPC_EN | FDD_LPC_EN | LPT_LPC_EN | COMB_LPC_EN | COMA_LPC_EN);
Arthur Heymansd28d5072019-06-16 23:36:28 +0200285
Arthur Heymans6beaef92019-06-16 23:29:23 +0200286 const struct device *dev = pcidev_on_root(0x1f, 0);
287 const struct southbridge_intel_bd82x6x_config *config = NULL;
288
289 /* Set up generic decode ranges */
290 if (!dev)
291 return;
292 if (dev->chip_info)
293 config = dev->chip_info;
294 if (!config)
295 return;
296
297 pci_write_config32(PCH_LPC_DEV, LPC_GEN1_DEC, config->gen1_dec);
298 pci_write_config32(PCH_LPC_DEV, LPC_GEN2_DEC, config->gen2_dec);
299 pci_write_config32(PCH_LPC_DEV, LPC_GEN3_DEC, config->gen3_dec);
300 pci_write_config32(PCH_LPC_DEV, LPC_GEN4_DEC, config->gen4_dec);
301}
302
Arthur Heymans2b28a162019-11-12 17:21:08 +0100303__weak void mainboard_pch_lpc_setup(void)
304{
305}
306
Patrick Rudolph45d4b172019-03-24 12:27:31 +0100307void early_pch_init(void)
308{
Arthur Heymansd28d5072019-06-16 23:36:28 +0200309 pch_enable_lpc_decode();
310
Arthur Heymans2b28a162019-11-12 17:21:08 +0100311 mainboard_pch_lpc_setup();
Arthur Heymans6beaef92019-06-16 23:29:23 +0200312
Patrick Rudolph45d4b172019-03-24 12:27:31 +0100313 pch_enable_bars();
314
315 pch_generic_setup();
316
Nico Huber6760e0b2019-11-17 02:34:53 +0100317 pch_enable_gbe();
318
Patrick Rudolph45d4b172019-03-24 12:27:31 +0100319 setup_pch_gpios(&mainboard_gpio_map);
Kyösti Mälkkiffa520f2020-01-07 12:00:31 +0200320
Husni Faizf571ce52022-09-05 15:28:53 +0530321 if (ENV_RAMINIT || (CONFIG(CONSOLE_I2C_SMBUS) && ENV_INITIAL_STAGE))
Kyösti Mälkkiffa520f2020-01-07 12:00:31 +0200322 enable_smbus();
Patrick Rudolph45d4b172019-03-24 12:27:31 +0100323}