blob: eea20282cddafc367a32dd84128f5e68021b446c [file] [log] [blame]
Angel Pons4b429832020-04-02 23:48:50 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Stefan Reinauer278534d2008-10-29 04:51:07 +00002
Elyes HAOUAS3dff32c2020-03-30 17:16:51 +02003#include <cbmem.h>
Elyes HAOUAS5db98712019-04-21 18:50:34 +02004#include <cf9_reset.h>
Patrick Georgid0835952010-10-05 09:07:10 +00005#include <console/console.h>
Elyes HAOUAS3dff32c2020-03-30 17:16:51 +02006#include <device/pci_ops.h>
7#include <device/pci.h>
Kyösti Mälkkicbf95712020-01-05 08:05:45 +02008#include <option.h>
Elyes HAOUAS3dff32c2020-03-30 17:16:51 +02009#include <romstage_handoff.h>
Elyes HAOUAS51401c32019-05-15 21:09:30 +020010#include <types.h>
11
12#include "i945.h"
Stefan Reinauer278534d2008-10-29 04:51:07 +000013
Patrick Georgid0835952010-10-05 09:07:10 +000014int i945_silicon_revision(void)
Stefan Reinauer278534d2008-10-29 04:51:07 +000015{
Angel Pons3580d812020-06-11 14:13:33 +020016 return pci_read_config8(HOST_BRIDGE, PCI_CLASS_REVISION);
Stefan Reinauer278534d2008-10-29 04:51:07 +000017}
18
Stefan Reinauer71a3d962009-07-21 21:44:24 +000019static void i945m_detect_chipset(void)
Stefan Reinauer278534d2008-10-29 04:51:07 +000020{
21 u8 reg8;
22
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000023 printk(BIOS_INFO, "\n");
Angel Pons3580d812020-06-11 14:13:33 +020024 reg8 = (pci_read_config8(HOST_BRIDGE, 0xe7) & 0x70) >> 4;
Stefan Reinauer278534d2008-10-29 04:51:07 +000025 switch (reg8) {
26 case 1:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000027 printk(BIOS_INFO, "Mobile Intel(R) 82945GM/GME Express");
Stefan Reinauer278534d2008-10-29 04:51:07 +000028 break;
29 case 2:
Stefan Reinauer7981b942011-04-01 22:33:25 +020030 printk(BIOS_INFO, "Mobile Intel(R) 82945GMS/GU/GSE Express");
Stefan Reinauer278534d2008-10-29 04:51:07 +000031 break;
32 case 3:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000033 printk(BIOS_INFO, "Mobile Intel(R) 82945PM Express");
Stefan Reinauer278534d2008-10-29 04:51:07 +000034 break;
35 case 5:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000036 printk(BIOS_INFO, "Intel(R) 82945GT Express");
Stefan Reinauer278534d2008-10-29 04:51:07 +000037 break;
38 case 6:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000039 printk(BIOS_INFO, "Mobile Intel(R) 82943/82940GML Express");
Stefan Reinauer278534d2008-10-29 04:51:07 +000040 break;
Elyes HAOUAS3dff32c2020-03-30 17:16:51 +020041 default: /* Others reserved. */
42 printk(BIOS_INFO, "Unknown (%02x)", reg8);
Stefan Reinauer278534d2008-10-29 04:51:07 +000043 }
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000044 printk(BIOS_INFO, " Chipset\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +000045
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000046 printk(BIOS_DEBUG, "(G)MCH capable of up to FSB ");
Angel Pons3580d812020-06-11 14:13:33 +020047 reg8 = (pci_read_config8(HOST_BRIDGE, 0xe3) & 0xe0) >> 5;
Stefan Reinauer278534d2008-10-29 04:51:07 +000048 switch (reg8) {
49 case 2:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000050 printk(BIOS_DEBUG, "800 MHz"); /* According to 965 spec */
Stefan Reinauer278534d2008-10-29 04:51:07 +000051 break;
52 case 3:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000053 printk(BIOS_DEBUG, "667 MHz");
Stefan Reinauer278534d2008-10-29 04:51:07 +000054 break;
55 case 4:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000056 printk(BIOS_DEBUG, "533 MHz");
Stefan Reinauer278534d2008-10-29 04:51:07 +000057 break;
58 default:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000059 printk(BIOS_DEBUG, "N/A MHz (%02x)", reg8);
Stefan Reinauer278534d2008-10-29 04:51:07 +000060 }
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000061 printk(BIOS_DEBUG, "\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +000062
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000063 printk(BIOS_DEBUG, "(G)MCH capable of ");
Angel Pons3580d812020-06-11 14:13:33 +020064 reg8 = (pci_read_config8(HOST_BRIDGE, 0xe4) & 0x07);
Stefan Reinauer278534d2008-10-29 04:51:07 +000065 switch (reg8) {
66 case 2:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000067 printk(BIOS_DEBUG, "up to DDR2-667");
Stefan Reinauer278534d2008-10-29 04:51:07 +000068 break;
69 case 3:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000070 printk(BIOS_DEBUG, "up to DDR2-533");
Stefan Reinauer278534d2008-10-29 04:51:07 +000071 break;
72 case 4:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000073 printk(BIOS_DEBUG, "DDR2-400");
Stefan Reinauer278534d2008-10-29 04:51:07 +000074 break;
Elyes HAOUAS3dff32c2020-03-30 17:16:51 +020075 default: /* Others reserved. */
76 printk(BIOS_INFO, "unknown max. RAM clock (%02x).", reg8);
Stefan Reinauer278534d2008-10-29 04:51:07 +000077 }
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000078 printk(BIOS_DEBUG, "\n");
Elyes HAOUAS6372a0e2016-10-30 18:39:53 +010079
Julius Wernercd49cce2019-03-05 16:53:33 -080080 if (CONFIG(NORTHBRIDGE_INTEL_SUBTYPE_I945GC))
Elyes HAOUAS6372a0e2016-10-30 18:39:53 +010081 printk(BIOS_ERR, "coreboot is compiled for the wrong chipset.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +000082}
83
Stefan Reinauer71a3d962009-07-21 21:44:24 +000084static void i945_detect_chipset(void)
85{
86 u8 reg8;
87
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000088 printk(BIOS_INFO, "\nIntel(R) ");
Stefan Reinauer24b4df52010-01-17 13:47:35 +000089
Angel Pons3580d812020-06-11 14:13:33 +020090 reg8 = ((pci_read_config8(HOST_BRIDGE, 0xe7) >> 5) & 4)
91 | ((pci_read_config8(HOST_BRIDGE, 0xe4) >> 4) & 3);
Stefan Reinauer71a3d962009-07-21 21:44:24 +000092 switch (reg8) {
93 case 0:
94 case 1:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000095 printk(BIOS_INFO, "82945G");
Stefan Reinauer71a3d962009-07-21 21:44:24 +000096 break;
97 case 2:
Stefan Reinauer24b4df52010-01-17 13:47:35 +000098 case 3:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000099 printk(BIOS_INFO, "82945P");
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000100 break;
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000101 case 4:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000102 printk(BIOS_INFO, "82945GC");
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000103 break;
104 case 5:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000105 printk(BIOS_INFO, "82945GZ");
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000106 break;
107 case 6:
108 case 7:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000109 printk(BIOS_INFO, "82945PL");
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000110 break;
111 default:
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000112 break;
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000113 }
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000114 printk(BIOS_INFO, " Chipset\n");
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000115
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000116 printk(BIOS_DEBUG, "(G)MCH capable of ");
Angel Pons3580d812020-06-11 14:13:33 +0200117 reg8 = (pci_read_config8(HOST_BRIDGE, 0xe4) & 0x07);
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000118 switch (reg8) {
119 case 0:
Elyes HAOUAS5db94502016-10-30 18:30:21 +0100120 case 2:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000121 printk(BIOS_DEBUG, "up to DDR2-667");
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000122 break;
123 case 3:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000124 printk(BIOS_DEBUG, "up to DDR2-533");
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000125 break;
Elyes HAOUAS3dff32c2020-03-30 17:16:51 +0200126 default: /* Others reserved. */
127 printk(BIOS_INFO, "unknown max. RAM clock (%02x).", reg8);
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000128 }
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000129 printk(BIOS_DEBUG, "\n");
Elyes HAOUAS6372a0e2016-10-30 18:39:53 +0100130
Julius Wernercd49cce2019-03-05 16:53:33 -0800131 if (CONFIG(NORTHBRIDGE_INTEL_SUBTYPE_I945GM))
Elyes HAOUAS6372a0e2016-10-30 18:39:53 +0100132 printk(BIOS_ERR, "coreboot is compiled for the wrong chipset.\n");
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000133}
134
Stefan Reinauer278534d2008-10-29 04:51:07 +0000135static void i945_setup_bars(void)
136{
Arthur Heymans874a8f92016-05-19 16:06:09 +0200137 u8 reg8, gfxsize;
Stefan Reinauer278534d2008-10-29 04:51:07 +0000138
139 /* As of now, we don't have all the A0 workarounds implemented */
140 if (i945_silicon_revision() == 0)
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000141 printk(BIOS_INFO, "Warning: i945 silicon revision A0 might not work correctly.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000142
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000143 printk(BIOS_DEBUG, "Setting up static northbridge registers...");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000144 /* Set up all hardcoded northbridge BARs */
Angel Pons4299cb42021-01-20 12:32:22 +0100145 pci_write_config32(HOST_BRIDGE, EPBAR, CONFIG_FIXED_EPBAR_MMIO_BASE | 1);
146 pci_write_config32(HOST_BRIDGE, MCHBAR, CONFIG_FIXED_MCHBAR_MMIO_BASE | 1);
147 pci_write_config32(HOST_BRIDGE, DMIBAR, CONFIG_FIXED_DMIBAR_MMIO_BASE | 1);
Angel Pons3580d812020-06-11 14:13:33 +0200148 pci_write_config32(HOST_BRIDGE, X60BAR, DEFAULT_X60BAR | 1);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000149
Elyes HAOUAS2119d0b2020-02-16 10:01:33 +0100150 /* vram size from CMOS option */
Angel Pons88dcb312021-04-26 17:10:28 +0200151 gfxsize = get_uint_option("gfx_uma_size", 2); /* 2 for 8MB */
Arthur Heymans874a8f92016-05-19 16:06:09 +0200152 /* make sure no invalid setting is used */
153 if (gfxsize > 6)
154 gfxsize = 2;
Angel Pons3580d812020-06-11 14:13:33 +0200155 pci_write_config16(HOST_BRIDGE, GGC, ((gfxsize + 1) << 4));
Arthur Heymansd522db02018-08-06 15:50:54 +0200156 /* TSEG 2M, This amount can easily be covered by SMRR MTRR's,
157 which requires to have TSEG_BASE aligned to TSEG_SIZE. */
Angel Pons3580d812020-06-11 14:13:33 +0200158 pci_update_config8(HOST_BRIDGE, ESMRAMC, ~0x07, (1 << 1) | (1 << 0));
Arthur Heymanse07df9d2018-04-09 22:03:21 +0200159
Stefan Reinauer278534d2008-10-29 04:51:07 +0000160 /* Set C0000-FFFFF to access RAM on both reads and writes */
Angel Pons3580d812020-06-11 14:13:33 +0200161 pci_write_config8(HOST_BRIDGE, PAM0, 0x30);
162 pci_write_config8(HOST_BRIDGE, PAM1, 0x33);
163 pci_write_config8(HOST_BRIDGE, PAM2, 0x33);
164 pci_write_config8(HOST_BRIDGE, PAM3, 0x33);
165 pci_write_config8(HOST_BRIDGE, PAM4, 0x33);
166 pci_write_config8(HOST_BRIDGE, PAM5, 0x33);
167 pci_write_config8(HOST_BRIDGE, PAM6, 0x33);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000168
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000169 printk(BIOS_DEBUG, " done.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000170
171 /* Wait for MCH BAR to come up */
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000172 printk(BIOS_DEBUG, "Waiting for MCHBAR to come up...");
Angel Pons3580d812020-06-11 14:13:33 +0200173 if ((pci_read_config32(HOST_BRIDGE, 0xe4) & 0x20000) == 0x00) { /* Bit 49 of CAPID0 */
Stefan Reinauer278534d2008-10-29 04:51:07 +0000174 do {
175 reg8 = *(volatile u8 *)0xfed40000;
176 } while (!(reg8 & 0x80));
177 }
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000178 printk(BIOS_DEBUG, "ok\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000179}
180
181static void i945_setup_egress_port(void)
182{
183 u32 reg32;
184 u32 timeout;
185
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000186 printk(BIOS_DEBUG, "Setting up Egress Port RCRB\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000187
188 /* Egress Port Virtual Channel 0 Configuration */
189
190 /* map only TC0 to VC0 */
Angel Pons1d4044a2021-03-27 19:11:51 +0100191 reg32 = epbar_read32(EPVC0RCTL);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000192 reg32 &= 0xffffff01;
Angel Pons1d4044a2021-03-27 19:11:51 +0100193 epbar_write32(EPVC0RCTL, reg32);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000194
Angel Pons1d4044a2021-03-27 19:11:51 +0100195 reg32 = epbar_read32(EPPVCCAP1);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000196 reg32 &= ~(7 << 0);
197 reg32 |= 1;
Angel Pons1d4044a2021-03-27 19:11:51 +0100198 epbar_write32(EPPVCCAP1, reg32);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000199
200 /* Egress Port Virtual Channel 1 Configuration */
Angel Pons1d4044a2021-03-27 19:11:51 +0100201 reg32 = epbar_read32(0x2c);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000202 reg32 &= 0xffffff00;
Julius Wernercd49cce2019-03-05 16:53:33 -0800203 if (CONFIG(NORTHBRIDGE_INTEL_SUBTYPE_I945GC)) {
Angel Pons1d4044a2021-03-27 19:11:51 +0100204 if ((mchbar_read32(CLKCFG) & 7) == 0)
Elyes HAOUASf7acdf82016-10-31 18:55:04 +0100205 reg32 |= 0x1a; /* 1067MHz */
206 }
Angel Pons1d4044a2021-03-27 19:11:51 +0100207 if ((mchbar_read32(CLKCFG) & 7) == 1)
Stefan Reinauer278534d2008-10-29 04:51:07 +0000208 reg32 |= 0x0d; /* 533MHz */
Angel Pons1d4044a2021-03-27 19:11:51 +0100209 if ((mchbar_read32(CLKCFG) & 7) == 2)
Elyes HAOUASf7acdf82016-10-31 18:55:04 +0100210 reg32 |= 0x14; /* 800MHz */
Angel Pons1d4044a2021-03-27 19:11:51 +0100211 if ((mchbar_read32(CLKCFG) & 7) == 3)
Stefan Reinauer278534d2008-10-29 04:51:07 +0000212 reg32 |= 0x10; /* 667MHz */
Angel Pons1d4044a2021-03-27 19:11:51 +0100213 epbar_write32(0x2c, reg32);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000214
Angel Pons1d4044a2021-03-27 19:11:51 +0100215 epbar_write32(EPVC1MTS, 0x0a0a0a0a);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000216
Angel Pons1d4044a2021-03-27 19:11:51 +0100217 reg32 = epbar_read32(EPVC1RCAP);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000218 reg32 &= ~(0x7f << 16);
219 reg32 |= (0x0a << 16);
Angel Pons1d4044a2021-03-27 19:11:51 +0100220 epbar_write32(EPVC1RCAP, reg32);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000221
Julius Wernercd49cce2019-03-05 16:53:33 -0800222 if (CONFIG(NORTHBRIDGE_INTEL_SUBTYPE_I945GC)) {
Angel Pons1d4044a2021-03-27 19:11:51 +0100223 if ((mchbar_read32(CLKCFG) & 7) == 0) { /* 1067MHz */
224 epbar_write32(EPVC1IST + 0, 0x01380138);
225 epbar_write32(EPVC1IST + 4, 0x01380138);
Elyes HAOUASf7acdf82016-10-31 18:55:04 +0100226 }
227 }
228
Angel Pons1d4044a2021-03-27 19:11:51 +0100229 if ((mchbar_read32(CLKCFG) & 7) == 1) { /* 533MHz */
230 epbar_write32(EPVC1IST + 0, 0x009c009c);
231 epbar_write32(EPVC1IST + 4, 0x009c009c);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000232 }
233
Angel Pons1d4044a2021-03-27 19:11:51 +0100234 if ((mchbar_read32(CLKCFG) & 7) == 2) { /* 800MHz */
235 epbar_write32(EPVC1IST + 0, 0x00f000f0);
236 epbar_write32(EPVC1IST + 4, 0x00f000f0);
Elyes HAOUASf7acdf82016-10-31 18:55:04 +0100237 }
238
Angel Pons1d4044a2021-03-27 19:11:51 +0100239 if ((mchbar_read32(CLKCFG) & 7) == 3) { /* 667MHz */
240 epbar_write32(EPVC1IST + 0, 0x00c000c0);
241 epbar_write32(EPVC1IST + 4, 0x00c000c0);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000242 }
243
244 /* Is internal graphics enabled? */
Angel Pons3580d812020-06-11 14:13:33 +0200245 if (pci_read_config8(HOST_BRIDGE, DEVEN) & (DEVEN_D2F0 | DEVEN_D2F1))
Angel Pons1d4044a2021-03-27 19:11:51 +0100246 mchbar_setbits32(MMARB1, 1 << 17);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000247
248 /* Assign Virtual Channel ID 1 to VC1 */
Angel Pons1d4044a2021-03-27 19:11:51 +0100249 reg32 = epbar_read32(EPVC1RCTL);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000250 reg32 &= ~(7 << 24);
251 reg32 |= (1 << 24);
Angel Pons1d4044a2021-03-27 19:11:51 +0100252 epbar_write32(EPVC1RCTL, reg32);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000253
Angel Pons1d4044a2021-03-27 19:11:51 +0100254 reg32 = epbar_read32(EPVC1RCTL);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000255 reg32 &= 0xffffff01;
256 reg32 |= (1 << 7);
Angel Pons1d4044a2021-03-27 19:11:51 +0100257 epbar_write32(EPVC1RCTL, reg32);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000258
Angel Pons1d4044a2021-03-27 19:11:51 +0100259 epbar_write32(PORTARB + 0x00, 0x01000001);
260 epbar_write32(PORTARB + 0x04, 0x00040000);
261 epbar_write32(PORTARB + 0x08, 0x00001000);
262 epbar_write32(PORTARB + 0x0c, 0x00000040);
263 epbar_write32(PORTARB + 0x10, 0x01000001);
264 epbar_write32(PORTARB + 0x14, 0x00040000);
265 epbar_write32(PORTARB + 0x18, 0x00001000);
266 epbar_write32(PORTARB + 0x1c, 0x00000040);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000267
Angel Pons1d4044a2021-03-27 19:11:51 +0100268 epbar_setbits32(EPVC1RCTL, 1 << 16);
269 epbar_setbits32(EPVC1RCTL, 1 << 16);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000270
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000271 printk(BIOS_DEBUG, "Loading port arbitration table ...");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000272 /* Loop until bit 0 becomes 0 */
273 timeout = 0x7fffff;
Angel Pons1d4044a2021-03-27 19:11:51 +0100274 while ((epbar_read16(EPVC1RSTS) & (1 << 0)) && --timeout)
Arthur Heymans70a8e342017-03-09 11:30:23 +0100275 ;
Stefan Reinauer278534d2008-10-29 04:51:07 +0000276 if (!timeout)
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000277 printk(BIOS_DEBUG, "timeout!\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000278 else
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000279 printk(BIOS_DEBUG, "ok\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000280
281 /* Now enable VC1 */
Angel Pons1d4044a2021-03-27 19:11:51 +0100282 epbar_setbits32(EPVC1RCTL, 1 << 31);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000283
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000284 printk(BIOS_DEBUG, "Wait for VC1 negotiation ...");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000285 /* Wait for VC1 negotiation pending */
286 timeout = 0x7fff;
Angel Pons1d4044a2021-03-27 19:11:51 +0100287 while ((epbar_read16(EPVC1RSTS) & (1 << 1)) && --timeout)
Arthur Heymans70a8e342017-03-09 11:30:23 +0100288 ;
Stefan Reinauer278534d2008-10-29 04:51:07 +0000289 if (!timeout)
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000290 printk(BIOS_DEBUG, "timeout!\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000291 else
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000292 printk(BIOS_DEBUG, "ok\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000293}
294
295static void ich7_setup_dmi_rcrb(void)
296{
297 u16 reg16;
Stefan Reinauer30140a52009-03-11 16:20:39 +0000298 u32 reg32;
Stefan Reinauer278534d2008-10-29 04:51:07 +0000299
Stefan Reinauer278534d2008-10-29 04:51:07 +0000300 reg16 = RCBA16(LCTL);
301 reg16 &= ~(3 << 0);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000302 reg16 |= 3;
Stefan Reinauer278534d2008-10-29 04:51:07 +0000303 RCBA16(LCTL) = reg16;
304
305 RCBA32(V0CTL) = 0x80000001;
306 RCBA32(V1CAP) = 0x03128010;
Stefan Reinauer278534d2008-10-29 04:51:07 +0000307
Stefan Reinauer30140a52009-03-11 16:20:39 +0000308 pci_write_config16(PCI_DEV(0, 0x1c, 0), 0x42, 0x0141);
309 pci_write_config16(PCI_DEV(0, 0x1c, 4), 0x42, 0x0141);
310 pci_write_config16(PCI_DEV(0, 0x1c, 5), 0x42, 0x0141);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000311
Stefan Reinauer30140a52009-03-11 16:20:39 +0000312 pci_write_config32(PCI_DEV(0, 0x1c, 4), 0x54, 0x00480ce0);
313 pci_write_config32(PCI_DEV(0, 0x1c, 5), 0x54, 0x00500ce0);
314
315 reg32 = RCBA32(V1CTL);
Arthur Heymans70a8e342017-03-09 11:30:23 +0100316 reg32 &= ~((0x7f << 1) | (7 << 17) | (7 << 24));
Stefan Reinauer30140a52009-03-11 16:20:39 +0000317 reg32 |= (0x40 << 1) | (4 << 17) | (1 << 24) | (1 << 31);
318 RCBA32(V1CTL) = reg32;
319
Stefan Reinauer30140a52009-03-11 16:20:39 +0000320 RCBA32(LCAP) |= (3 << 10);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000321}
322
323static void i945_setup_dmi_rcrb(void)
324{
325 u32 reg32;
326 u32 timeout;
Stefan Reinauerbf264e92010-05-14 19:09:20 +0000327 int activate_aspm = 1; /* hardcode ASPM for now */
Stefan Reinauer30140a52009-03-11 16:20:39 +0000328
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000329 printk(BIOS_DEBUG, "Setting up DMI RCRB\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000330
331 /* Virtual Channel 0 Configuration */
Angel Pons1d4044a2021-03-27 19:11:51 +0100332 reg32 = dmibar_read32(DMIVC0RCTL0);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000333 reg32 &= 0xffffff01;
Angel Pons1d4044a2021-03-27 19:11:51 +0100334 dmibar_write32(DMIVC0RCTL0, reg32);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000335
Angel Pons1d4044a2021-03-27 19:11:51 +0100336 reg32 = dmibar_read32(DMIPVCCAP1);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000337 reg32 &= ~(7 << 0);
338 reg32 |= 1;
Angel Pons1d4044a2021-03-27 19:11:51 +0100339 dmibar_write32(DMIPVCCAP1, reg32);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000340
Angel Pons1d4044a2021-03-27 19:11:51 +0100341 reg32 = dmibar_read32(DMIVC1RCTL);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000342 reg32 &= ~(7 << 24);
343 reg32 |= (1 << 24); /* NOTE: This ID must match ICH7 side */
Angel Pons1d4044a2021-03-27 19:11:51 +0100344 dmibar_write32(DMIVC1RCTL, reg32);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000345
Angel Pons1d4044a2021-03-27 19:11:51 +0100346 reg32 = dmibar_read32(DMIVC1RCTL);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000347 reg32 &= 0xffffff01;
348 reg32 |= (1 << 7);
Angel Pons1d4044a2021-03-27 19:11:51 +0100349 dmibar_write32(DMIVC1RCTL, reg32);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000350
351 /* Now enable VC1 */
Angel Pons1d4044a2021-03-27 19:11:51 +0100352 dmibar_setbits32(DMIVC1RCTL, 1 << 31);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000353
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000354 printk(BIOS_DEBUG, "Wait for VC1 negotiation ...");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000355 /* Wait for VC1 negotiation pending */
356 timeout = 0x7ffff;
Angel Pons1d4044a2021-03-27 19:11:51 +0100357 while ((dmibar_read16(DMIVC1RSTS) & (1 << 1)) && --timeout)
Arthur Heymans70a8e342017-03-09 11:30:23 +0100358 ;
Stefan Reinauer278534d2008-10-29 04:51:07 +0000359 if (!timeout)
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000360 printk(BIOS_DEBUG, "timeout!\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000361 else
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000362 printk(BIOS_DEBUG, "done..\n");
Angel Pons81c9c272020-07-07 23:19:38 +0200363
Stefan Reinauer278534d2008-10-29 04:51:07 +0000364 /* Enable Active State Power Management (ASPM) L0 state */
365
Angel Pons1d4044a2021-03-27 19:11:51 +0100366 reg32 = dmibar_read32(DMILCAP);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000367 reg32 &= ~(7 << 12);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000368 reg32 |= (2 << 12);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000369
370 reg32 &= ~(7 << 15);
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000371
Stefan Reinauer30140a52009-03-11 16:20:39 +0000372 reg32 |= (2 << 15);
Angel Pons1d4044a2021-03-27 19:11:51 +0100373 dmibar_write32(DMILCAP, reg32);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000374
Angel Pons1d4044a2021-03-27 19:11:51 +0100375 reg32 = dmibar_read32(DMICC);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000376 reg32 &= 0x00ffffff;
Stefan Reinauer278534d2008-10-29 04:51:07 +0000377 reg32 &= ~(3 << 0);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000378 reg32 |= (1 << 0);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000379 reg32 &= ~(3 << 20);
380 reg32 |= (1 << 20);
381
Angel Pons1d4044a2021-03-27 19:11:51 +0100382 dmibar_write32(DMICC, reg32);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000383
Arthur Heymans70a8e342017-03-09 11:30:23 +0100384 if (activate_aspm)
Angel Pons1d4044a2021-03-27 19:11:51 +0100385 dmibar_setbits32(DMILCTL, 3 << 0);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000386
387 /* Last but not least, some additional steps */
Angel Pons1d4044a2021-03-27 19:11:51 +0100388 reg32 = mchbar_read32(FSBSNPCTL);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000389 reg32 &= ~(0xff << 2);
390 reg32 |= (0xaa << 2);
Angel Pons1d4044a2021-03-27 19:11:51 +0100391 mchbar_write32(FSBSNPCTL, reg32);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000392
Angel Pons1d4044a2021-03-27 19:11:51 +0100393 dmibar_write32(0x2c, 0x86000040);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000394
Angel Pons1d4044a2021-03-27 19:11:51 +0100395 reg32 = dmibar_read32(0x204);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000396 reg32 &= ~0x3ff;
397#if 1
Elyes HAOUAS3dff32c2020-03-30 17:16:51 +0200398 reg32 |= 0x13f; /* for x4 DMI only */
Stefan Reinauer278534d2008-10-29 04:51:07 +0000399#else
Elyes HAOUAS3dff32c2020-03-30 17:16:51 +0200400 reg32 |= 0x1e4; /* for x2 DMI only */
Stefan Reinauer278534d2008-10-29 04:51:07 +0000401#endif
Angel Pons1d4044a2021-03-27 19:11:51 +0100402 dmibar_write32(0x204, reg32);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000403
Angel Pons3580d812020-06-11 14:13:33 +0200404 if (pci_read_config8(HOST_BRIDGE, DEVEN) & (DEVEN_D2F0 | DEVEN_D2F1)) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000405 printk(BIOS_DEBUG, "Internal graphics: enabled\n");
Angel Pons1d4044a2021-03-27 19:11:51 +0100406 dmibar_setbits32(0x200, 1 << 21);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000407 } else {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000408 printk(BIOS_DEBUG, "Internal graphics: disabled\n");
Angel Pons1d4044a2021-03-27 19:11:51 +0100409 dmibar_clrbits32(0x200, 1 << 21);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000410 }
411
Angel Pons1d4044a2021-03-27 19:11:51 +0100412 reg32 = dmibar_read32(0x204);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000413 reg32 &= ~((1 << 11) | (1 << 10));
Angel Pons1d4044a2021-03-27 19:11:51 +0100414 dmibar_write32(0x204, reg32);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000415
Angel Pons1d4044a2021-03-27 19:11:51 +0100416 reg32 = dmibar_read32(0x204);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000417 reg32 &= ~(0xff << 12);
418 reg32 |= (0x0d << 12);
Angel Pons1d4044a2021-03-27 19:11:51 +0100419 dmibar_write32(0x204, reg32);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000420
Angel Pons1d4044a2021-03-27 19:11:51 +0100421 dmibar_setbits32(DMICTL1, 3 << 24);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000422
Angel Pons1d4044a2021-03-27 19:11:51 +0100423 reg32 = dmibar_read32(0x200);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000424 reg32 &= ~(0x3 << 26);
425 reg32 |= (0x02 << 26);
Angel Pons1d4044a2021-03-27 19:11:51 +0100426 dmibar_write32(0x200, reg32);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000427
Angel Pons1d4044a2021-03-27 19:11:51 +0100428 dmibar_clrbits32(DMIDRCCFG, 1 << 31);
429 dmibar_setbits32(DMICTL2, 1 << 31);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000430
431 if (i945_silicon_revision() >= 3) {
Angel Pons1d4044a2021-03-27 19:11:51 +0100432 reg32 = dmibar_read32(0xec0);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000433 reg32 &= 0x0fffffff;
434 reg32 |= (2 << 28);
Angel Pons1d4044a2021-03-27 19:11:51 +0100435 dmibar_write32(0xec0, reg32);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000436
Angel Pons1d4044a2021-03-27 19:11:51 +0100437 reg32 = dmibar_read32(0xed4);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000438 reg32 &= 0x0fffffff;
439 reg32 |= (2 << 28);
Angel Pons1d4044a2021-03-27 19:11:51 +0100440 dmibar_write32(0xed4, reg32);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000441
Angel Pons1d4044a2021-03-27 19:11:51 +0100442 reg32 = dmibar_read32(0xee8);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000443 reg32 &= 0x0fffffff;
444 reg32 |= (2 << 28);
Angel Pons1d4044a2021-03-27 19:11:51 +0100445 dmibar_write32(0xee8, reg32);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000446
Angel Pons1d4044a2021-03-27 19:11:51 +0100447 reg32 = dmibar_read32(0xefc);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000448 reg32 &= 0x0fffffff;
449 reg32 |= (2 << 28);
Angel Pons1d4044a2021-03-27 19:11:51 +0100450 dmibar_write32(0xefc, reg32);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000451 }
452
453 /* wait for bit toggle to 0 */
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000454 printk(BIOS_DEBUG, "Waiting for DMI hardware...");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000455 timeout = 0x7fffff;
Angel Pons1d4044a2021-03-27 19:11:51 +0100456 while ((dmibar_read8(0x32) & (1 << 1)) && --timeout)
Arthur Heymans70a8e342017-03-09 11:30:23 +0100457 ;
Stefan Reinauer278534d2008-10-29 04:51:07 +0000458 if (!timeout)
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000459 printk(BIOS_DEBUG, "timeout!\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000460 else
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000461 printk(BIOS_DEBUG, "ok\n");
Stefan Reinauer30140a52009-03-11 16:20:39 +0000462
Stefan Reinauerbf264e92010-05-14 19:09:20 +0000463 /* Clear Error Status Bits! */
Angel Pons1d4044a2021-03-27 19:11:51 +0100464 dmibar_write32(0x1c4, 0xffffffff);
465 dmibar_write32(0x1d0, 0xffffffff);
466 dmibar_write32(0x228, 0xffffffff);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000467
Stefan Reinauerbf264e92010-05-14 19:09:20 +0000468 /* Program Read-Only Write-Once Registers */
Angel Pons1d4044a2021-03-27 19:11:51 +0100469 dmibar_setbits32(0x308, 0);
470 dmibar_setbits32(0x314, 0);
471 dmibar_setbits32(0x324, 0);
472 dmibar_setbits32(0x328, 0);
473 dmibar_setbits32(0x334, 0);
474 dmibar_setbits32(0x338, 0);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000475
Angel Pons1d4044a2021-03-27 19:11:51 +0100476 if (i945_silicon_revision() == 1 && (mchbar_read8(DFT_STRAP1) & (1 << 5))) {
477 if ((mchbar_read32(0x214) & 0xf) != 0x3) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000478 printk(BIOS_INFO, "DMI link requires A1 stepping workaround. Rebooting.\n");
Angel Pons1d4044a2021-03-27 19:11:51 +0100479 reg32 = dmibar_read32(0x224);
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000480 reg32 &= ~(7 << 0);
481 reg32 |= (3 << 0);
Angel Pons1d4044a2021-03-27 19:11:51 +0100482 dmibar_write32(0x224, reg32);
Elyes HAOUAS5db98712019-04-21 18:50:34 +0200483 system_reset();
Stefan Reinauer278534d2008-10-29 04:51:07 +0000484 }
485 }
486}
487
488static void i945_setup_pci_express_x16(void)
489{
490 u32 timeout;
491 u32 reg32;
492 u16 reg16;
Elyes HAOUAS961658f2020-04-06 09:42:21 +0200493 const pci_devfn_t p2peg = PCI_DEV(0, 0x01, 0);
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000494
Kyösti Mälkki2647b6f2019-09-29 07:03:55 +0300495 u8 tmp_secondary = 0x0a;
Elyes HAOUAS961658f2020-04-06 09:42:21 +0200496 const pci_devfn_t peg_plugin = PCI_DEV(tmp_secondary, 0, 0);
Kyösti Mälkki2647b6f2019-09-29 07:03:55 +0300497
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000498 printk(BIOS_DEBUG, "Enabling PCI Express x16 Link\n");
Stefan Reinauer30140a52009-03-11 16:20:39 +0000499
Angel Pons3580d812020-06-11 14:13:33 +0200500 pci_or_config16(HOST_BRIDGE, DEVEN, DEVEN_D1F0);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000501
Angel Ponse3c68d22020-06-08 12:09:03 +0200502 pci_and_config32(p2peg, PEGCC, ~(1 << 8));
Stefan Reinauer30140a52009-03-11 16:20:39 +0000503
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000504 /* We have no success with querying the usual PCIe registers
505 * for link setup success on the i945. Hence we assign a temporary
506 * PCI bus 0x0a and check whether we find a device on 0:a.0
507 */
508
Kyösti Mälkkiad787e12019-09-30 04:14:19 +0300509 /* Force PCIRST# */
510 pci_s_assert_secondary_reset(p2peg);
511 pci_s_deassert_secondary_reset(p2peg);
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000512
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300513 reg16 = pci_read_config16(p2peg, SLOTSTS);
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000514 printk(BIOS_DEBUG, "SLOTSTS: %04x\n", reg16);
Arthur Heymans70a8e342017-03-09 11:30:23 +0100515 if (!(reg16 & 0x48))
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000516 goto disable_pciexpress_x16_link;
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000517 reg16 |= (1 << 4) | (1 << 0);
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300518 pci_write_config16(p2peg, SLOTSTS, reg16);
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000519
Kyösti Mälkkiad787e12019-09-30 04:14:19 +0300520 pci_s_bridge_set_secondary(p2peg, tmp_secondary);
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000521
Angel Ponse3c68d22020-06-08 12:09:03 +0200522 pci_and_config32(p2peg, 0x224, ~(1 << 8));
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000523
Angel Pons1d4044a2021-03-27 19:11:51 +0100524 mchbar_clrbits16(UPMC1, 1 << 5 | 1 << 0);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000525
Martin Roth128c1042016-11-18 09:29:03 -0700526 /* Initialize PEG_CAP */
Angel Ponse3c68d22020-06-08 12:09:03 +0200527 pci_or_config16(p2peg, PEG_CAP, 1 << 8);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000528
529 /* Setup SLOTCAP */
Elyes HAOUAS3dff32c2020-03-30 17:16:51 +0200530 /* TODO: These values are mainboard dependent and should be set from devicetree.cb.
Stefan Reinauer30140a52009-03-11 16:20:39 +0000531 */
532 /* NOTE: SLOTCAP becomes RO after the first write! */
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300533 reg32 = pci_read_config32(p2peg, SLOTCAP);
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000534 reg32 &= 0x0007ffff;
535
536 reg32 &= 0xfffe007f;
537
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300538 pci_write_config32(p2peg, SLOTCAP, reg32);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000539
540 /* Wait for training to succeed */
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000541 printk(BIOS_DEBUG, "PCIe link training ...");
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000542 timeout = 0x7ffff;
Angel Ponse3c68d22020-06-08 12:09:03 +0200543 while ((((pci_read_config32(p2peg, PEGSTS) >> 16) & 3) != 3) && --timeout)
Arthur Heymans70a8e342017-03-09 11:30:23 +0100544 ;
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000545
Kyösti Mälkki2647b6f2019-09-29 07:03:55 +0300546 reg32 = pci_read_config32(peg_plugin, PCI_VENDOR_ID);
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000547 if (reg32 != 0x00000000 && reg32 != 0xffffffff) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000548 printk(BIOS_DEBUG, " Detected PCIe device %04x:%04x\n",
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000549 reg32 & 0xffff, reg32 >> 16);
550 } else {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000551 printk(BIOS_DEBUG, " timeout!\n");
Stefan Reinauer30140a52009-03-11 16:20:39 +0000552
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000553 printk(BIOS_DEBUG, "Restrain PCIe port to x1\n");
Stefan Reinauer30140a52009-03-11 16:20:39 +0000554
Angel Ponse3c68d22020-06-08 12:09:03 +0200555 pci_update_config32(p2peg, PEGSTS, ~(0xf << 1), 1);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000556
Kyösti Mälkkiad787e12019-09-30 04:14:19 +0300557 /* Force PCIRST# */
558 pci_s_assert_secondary_reset(p2peg);
559 pci_s_deassert_secondary_reset(p2peg);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000560
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000561 printk(BIOS_DEBUG, "PCIe link training ...");
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000562 timeout = 0x7ffff;
Angel Ponse3c68d22020-06-08 12:09:03 +0200563 while ((((pci_read_config32(p2peg, PEGSTS) >> 16) & 3) != 3) && --timeout)
Arthur Heymans70a8e342017-03-09 11:30:23 +0100564 ;
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000565
Kyösti Mälkki2647b6f2019-09-29 07:03:55 +0300566 reg32 = pci_read_config32(peg_plugin, PCI_VENDOR_ID);
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000567 if (reg32 != 0x00000000 && reg32 != 0xffffffff) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000568 printk(BIOS_DEBUG, " Detected PCIe x1 device %04x:%04x\n",
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000569 reg32 & 0xffff, reg32 >> 16);
570 } else {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000571 printk(BIOS_DEBUG, " timeout!\n");
572 printk(BIOS_DEBUG, "Disabling PCIe x16 port completely.\n");
Stefan Reinauer30140a52009-03-11 16:20:39 +0000573 goto disable_pciexpress_x16_link;
Stefan Reinauer30140a52009-03-11 16:20:39 +0000574 }
Stefan Reinauer30140a52009-03-11 16:20:39 +0000575 }
576
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300577 reg16 = pci_read_config16(p2peg, 0xb2);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000578 reg16 >>= 4;
579 reg16 &= 0x3f;
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000580 /* reg16 == 1 -> x1; reg16 == 16 -> x16 */
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000581 printk(BIOS_DEBUG, "PCIe x%d link training succeeded.\n", reg16);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000582
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300583 reg32 = pci_read_config32(p2peg, PEGTC);
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000584 reg32 &= 0xfffffc00; /* clear [9:0] */
Arthur Heymans70a8e342017-03-09 11:30:23 +0100585 if (reg16 == 1)
Stefan Reinauer30140a52009-03-11 16:20:39 +0000586 reg32 |= 0x32b;
587 // TODO
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300588 /* pci_write_config32(p2peg, PEGTC, reg32); */
Arthur Heymans70a8e342017-03-09 11:30:23 +0100589 else if (reg16 == 16)
Stefan Reinauer30140a52009-03-11 16:20:39 +0000590 reg32 |= 0x0f4;
591 // TODO
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300592 /* pci_write_config32(p2peg, PEGTC, reg32); */
Stefan Reinauer30140a52009-03-11 16:20:39 +0000593
Kyösti Mälkki2647b6f2019-09-29 07:03:55 +0300594 reg32 = (pci_read_config32(peg_plugin, 0x8) >> 8);
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000595 printk(BIOS_DEBUG, "PCIe device class: %06x\n", reg32);
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000596 if (reg32 == 0x030000) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000597 printk(BIOS_DEBUG, "PCIe device is VGA. Disabling IGD.\n");
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000598 reg16 = (1 << 1);
Angel Pons3580d812020-06-11 14:13:33 +0200599 pci_write_config16(HOST_BRIDGE, GGC, reg16);
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000600
Angel Pons3580d812020-06-11 14:13:33 +0200601 pci_and_config32(HOST_BRIDGE, DEVEN, ~(DEVEN_D2F0 | DEVEN_D2F1));
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000602 }
603
Angel Ponse3c68d22020-06-08 12:09:03 +0200604 /* Enable GPEs: PMEGPE, HPGPE, GENGPE */
605 pci_or_config32(p2peg, PEG_LC, (1 << 2) | (1 << 1) | (1 << 0));
Stefan Reinauer30140a52009-03-11 16:20:39 +0000606
607 /* Virtual Channel Configuration: Only VC0 on PCIe x16 */
Angel Ponse3c68d22020-06-08 12:09:03 +0200608 pci_and_config32(p2peg, VC0RCTL, ~0x000000fe);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000609
610 /* Extended VC count */
Angel Ponse3c68d22020-06-08 12:09:03 +0200611 pci_and_config32(p2peg, PVCCAP1, ~(7 << 0));
Stefan Reinauer30140a52009-03-11 16:20:39 +0000612
613 /* Active State Power Management ASPM */
614
615 /* TODO */
616
617 /* Clear error bits */
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300618 pci_write_config16(p2peg, PCISTS1, 0xffff);
619 pci_write_config16(p2peg, SSTS1, 0xffff);
620 pci_write_config16(p2peg, DSTS, 0xffff);
621 pci_write_config32(p2peg, UESTS, 0xffffffff);
622 pci_write_config32(p2peg, CESTS, 0xffffffff);
623 pci_write_config32(p2peg, 0x1f0, 0xffffffff);
624 pci_write_config32(p2peg, 0x228, 0xffffffff);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000625
626 /* Program R/WO registers */
Angel Ponse3c68d22020-06-08 12:09:03 +0200627 pci_update_config32(p2peg, 0x308, ~0, 0);
628 pci_update_config32(p2peg, 0x314, ~0, 0);
629 pci_update_config32(p2peg, 0x324, ~0, 0);
630 pci_update_config32(p2peg, 0x328, ~0, 0);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000631
Stefan Reinauer30140a52009-03-11 16:20:39 +0000632 /* Additional PCIe graphics setup */
Angel Ponse3c68d22020-06-08 12:09:03 +0200633 pci_or_config32(p2peg, 0xf0, 3 << 26);
634 pci_or_config32(p2peg, 0xf0, 3 << 24);
635 pci_or_config32(p2peg, 0xf0, 1 << 5);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000636
Angel Ponse3c68d22020-06-08 12:09:03 +0200637 pci_update_config32(p2peg, 0x200, ~(3 << 26), 2 << 26);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000638
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300639 reg32 = pci_read_config32(p2peg, 0xe80);
Arthur Heymans70a8e342017-03-09 11:30:23 +0100640 if (i945_silicon_revision() >= 2)
Stefan Reinauer30140a52009-03-11 16:20:39 +0000641 reg32 |= (1 << 12);
Arthur Heymans70a8e342017-03-09 11:30:23 +0100642 else
Stefan Reinauer30140a52009-03-11 16:20:39 +0000643 reg32 &= ~(1 << 12);
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300644 pci_write_config32(p2peg, 0xe80, reg32);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000645
Angel Ponse3c68d22020-06-08 12:09:03 +0200646 pci_and_config32(p2peg, 0xeb4, ~(1 << 31));
Stefan Reinauer30140a52009-03-11 16:20:39 +0000647
Angel Ponse3c68d22020-06-08 12:09:03 +0200648 pci_or_config32(p2peg, 0xfc, 1 << 31);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000649
650 if (i945_silicon_revision() >= 3) {
651 static const u32 reglist[] = {
Elyes HAOUAS3dff32c2020-03-30 17:16:51 +0200652 0xec0, 0xed4, 0xee8, 0xefc, 0xf10, 0xf24, 0xf38, 0xf4c,
653 0xf60, 0xf74, 0xf88, 0xf9c, 0xfb0, 0xfc4, 0xfd8, 0xfec
Stefan Reinauer30140a52009-03-11 16:20:39 +0000654 };
655
656 int i;
Angel Ponse3c68d22020-06-08 12:09:03 +0200657 for (i = 0; i < ARRAY_SIZE(reglist); i++)
658 pci_update_config32(p2peg, reglist[i], ~(0xf << 28), 2 << 28);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000659 }
660
Arthur Heymans70a8e342017-03-09 11:30:23 +0100661 if (i945_silicon_revision() <= 2) {
Stefan Reinauer30140a52009-03-11 16:20:39 +0000662 /* Set voltage specific parameters */
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300663 reg32 = pci_read_config32(p2peg, 0xe80);
Stefan Reinauerbf264e92010-05-14 19:09:20 +0000664 reg32 &= (0xf << 4); /* Default case 1.05V */
Angel Pons1d4044a2021-03-27 19:11:51 +0100665 if ((mchbar_read32(DFT_STRAP1) & (1 << 20)) == 0) { /* 1.50V */
Stefan Reinauer30140a52009-03-11 16:20:39 +0000666 reg32 |= (7 << 4);
667 }
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300668 pci_write_config32(p2peg, 0xe80, reg32);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000669 }
670
671 return;
672
673disable_pciexpress_x16_link:
Stefan Reinauer278534d2008-10-29 04:51:07 +0000674 /* For now we just disable the x16 link */
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000675 printk(BIOS_DEBUG, "Disabling PCI Express x16 Link\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000676
Angel Pons1d4044a2021-03-27 19:11:51 +0100677 mchbar_setbits16(UPMC1, 1 << 5 | 1 << 0);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000678
Kyösti Mälkkiad787e12019-09-30 04:14:19 +0300679 /* Toggle PCIRST# */
680 pci_s_assert_secondary_reset(p2peg);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000681
Angel Ponse3c68d22020-06-08 12:09:03 +0200682 pci_or_config32(p2peg, 0x224, 1 << 8);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000683
Kyösti Mälkkiad787e12019-09-30 04:14:19 +0300684 pci_s_deassert_secondary_reset(p2peg);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000685
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000686 printk(BIOS_DEBUG, "Wait for link to enter detect state... ");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000687 timeout = 0x7fffff;
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300688 for (reg32 = pci_read_config32(p2peg, PEGSTS);
Arthur Heymans70a8e342017-03-09 11:30:23 +0100689 (reg32 & 0x000f0000) && --timeout;)
690 ;
Stefan Reinauer278534d2008-10-29 04:51:07 +0000691 if (!timeout)
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000692 printk(BIOS_DEBUG, "timeout!\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000693 else
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000694 printk(BIOS_DEBUG, "ok\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000695
696 /* Finally: Disable the PCI config header */
Angel Pons3580d812020-06-11 14:13:33 +0200697 pci_and_config16(HOST_BRIDGE, DEVEN, ~DEVEN_D1F0);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000698}
699
700static void i945_setup_root_complex_topology(void)
701{
702 u32 reg32;
Elyes HAOUAS961658f2020-04-06 09:42:21 +0200703 const pci_devfn_t p2peg = PCI_DEV(0, 0x01, 0);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000704
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000705 printk(BIOS_DEBUG, "Setting up Root Complex Topology\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000706 /* Egress Port Root Topology */
Stefan Reinauer30140a52009-03-11 16:20:39 +0000707
Angel Pons1d4044a2021-03-27 19:11:51 +0100708 reg32 = epbar_read32(EPESD);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000709 reg32 &= 0xff00ffff;
710 reg32 |= (1 << 16);
Angel Pons1d4044a2021-03-27 19:11:51 +0100711 epbar_write32(EPESD, reg32);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000712
Angel Pons1d4044a2021-03-27 19:11:51 +0100713 epbar_setbits32(EPLE1D, 1 << 16 | 1 << 0);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000714
Angel Pons1d4044a2021-03-27 19:11:51 +0100715 epbar_write32(EPLE1A, CONFIG_FIXED_DMIBAR_MMIO_BASE);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000716
Angel Pons1d4044a2021-03-27 19:11:51 +0100717 epbar_setbits32(EPLE2D, 1 << 16 | 1 << 0);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000718
719 /* DMI Port Root Topology */
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000720
Angel Pons1d4044a2021-03-27 19:11:51 +0100721 reg32 = dmibar_read32(DMILE1D);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000722 reg32 &= 0x00ffffff;
Stefan Reinauer30140a52009-03-11 16:20:39 +0000723
Stefan Reinauer278534d2008-10-29 04:51:07 +0000724 reg32 &= 0xff00ffff;
725 reg32 |= (2 << 16);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000726
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000727 reg32 |= (1 << 0);
Angel Pons1d4044a2021-03-27 19:11:51 +0100728 dmibar_write32(DMILE1D, reg32);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000729
Angel Pons1d4044a2021-03-27 19:11:51 +0100730 dmibar_write32(DMILE1A, CONFIG_FIXED_RCBA_MMIO_BASE);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000731
Angel Pons1d4044a2021-03-27 19:11:51 +0100732 dmibar_setbits32(DMILE2D, 1 << 16 | 1 << 0);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000733
Angel Pons1d4044a2021-03-27 19:11:51 +0100734 dmibar_write32(DMILE2A, CONFIG_FIXED_EPBAR_MMIO_BASE);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000735
736 /* PCI Express x16 Port Root Topology */
Angel Pons3580d812020-06-11 14:13:33 +0200737 if (pci_read_config8(HOST_BRIDGE, DEVEN) & DEVEN_D1F0) {
Angel Pons4299cb42021-01-20 12:32:22 +0100738 pci_write_config32(p2peg, LE1A, CONFIG_FIXED_EPBAR_MMIO_BASE);
Angel Ponse3c68d22020-06-08 12:09:03 +0200739 pci_or_config32(p2peg, LE1D, 1 << 0);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000740 }
741}
742
743static void ich7_setup_root_complex_topology(void)
744{
Elyes HAOUASb217baa2019-01-18 15:32:39 +0100745 /* Write the R/WO registers */
746
747 RCBA32(ESD) |= (2 << 16);
748
749 RCBA32(ULD) |= (1 << 24) | (1 << 16);
750
Angel Pons4299cb42021-01-20 12:32:22 +0100751 RCBA32(ULBA) = CONFIG_FIXED_DMIBAR_MMIO_BASE;
Elyes HAOUASb217baa2019-01-18 15:32:39 +0100752 /* Write ESD.CID to TCID */
753 RCBA32(RP1D) |= (2 << 16);
754 RCBA32(RP2D) |= (2 << 16);
755 RCBA32(RP3D) |= (2 << 16);
756 RCBA32(RP4D) |= (2 << 16);
757 RCBA32(HDD) |= (2 << 16);
758 RCBA32(RP5D) |= (2 << 16);
759 RCBA32(RP6D) |= (2 << 16);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000760}
761
762static void ich7_setup_pci_express(void)
763{
Elyes HAOUAS13746072019-12-08 11:34:24 +0100764 /* Enable PCIe Root Port Clock Gate */
Stefan Reinauer30140a52009-03-11 16:20:39 +0000765 RCBA32(CG) |= (1 << 0);
766
Stefan Reinauerbf264e92010-05-14 19:09:20 +0000767 /* Initialize slot power limit for root ports */
Stefan Reinauer278534d2008-10-29 04:51:07 +0000768 pci_write_config32(PCI_DEV(0, 0x1c, 0), 0x54, 0x00000060);
769
770 pci_write_config32(PCI_DEV(0, 0x1c, 0), 0xd8, 0x00110000);
771}
772
Patrick Georgid0835952010-10-05 09:07:10 +0000773void i945_early_initialization(void)
Stefan Reinauer278534d2008-10-29 04:51:07 +0000774{
775 /* Print some chipset specific information */
Angel Pons3580d812020-06-11 14:13:33 +0200776 switch (pci_read_config32(HOST_BRIDGE, 0)) {
Stefan Reinauerbf264e92010-05-14 19:09:20 +0000777 case 0x27708086: /* 82945G/GZ/GC/P/PL */
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000778 i945_detect_chipset();
779 break;
Stefan Reinauerbf264e92010-05-14 19:09:20 +0000780 case 0x27a08086: /* 945GME/GSE */
781 case 0x27ac8086: /* 945GM/PM/GMS/GU/GT, 943/940GML */
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000782 i945m_detect_chipset();
783 break;
784 }
Stefan Reinauer278534d2008-10-29 04:51:07 +0000785
786 /* Setup all BARs required for early PCIe and raminit */
787 i945_setup_bars();
788
789 /* Change port80 to LPC */
790 RCBA32(GCS) &= (~0x04);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000791
792 /* Just do it that way */
793 RCBA32(0x2010) |= (1 << 10);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000794}
795
Vladimir Serbinenko55601882014-10-15 20:17:51 +0200796static void i945_prepare_resume(int s3resume)
797{
798 int cbmem_was_initted;
799
800 cbmem_was_initted = !cbmem_recovery(s3resume);
801
Kyösti Mälkki81830252016-06-25 11:40:00 +0300802 romstage_handoff_init(cbmem_was_initted && s3resume);
Vladimir Serbinenko55601882014-10-15 20:17:51 +0200803}
804
805void i945_late_initialization(int s3resume)
Stefan Reinauer278534d2008-10-29 04:51:07 +0000806{
807 i945_setup_egress_port();
808
809 ich7_setup_root_complex_topology();
810
811 ich7_setup_pci_express();
812
813 ich7_setup_dmi_rcrb();
814
815 i945_setup_dmi_rcrb();
816
Julius Wernercd49cce2019-03-05 16:53:33 -0800817 if (CONFIG(NORTHBRIDGE_INTEL_SUBTYPE_I945GM))
Arthur Heymans2f6b52e2017-03-02 23:51:09 +0100818 i945_setup_pci_express_x16();
Stefan Reinauer278534d2008-10-29 04:51:07 +0000819
820 i945_setup_root_complex_topology();
Vladimir Serbinenko55601882014-10-15 20:17:51 +0200821
Kyösti Mälkki346d2012019-03-23 10:07:16 +0200822 if (CONFIG(DEBUG_RAM_SETUP))
823 sdram_dump_mchbar_registers();
Vladimir Serbinenko55601882014-10-15 20:17:51 +0200824
Angel Pons1d4044a2021-03-27 19:11:51 +0100825 mchbar_write16(SSKPD, 0xcafe);
Vladimir Serbinenko55601882014-10-15 20:17:51 +0200826
827 i945_prepare_resume(s3resume);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000828}