blob: b91afda187a79d4d10d30113e06e4dd6d9fdfc3f [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>
Patrick Georgid0835952010-10-05 09:07:10 +00006#include <device/pci_def.h>
Elyes HAOUAS3dff32c2020-03-30 17:16:51 +02007#include <device/pci_ops.h>
8#include <device/pci.h>
Kyösti Mälkkicbf95712020-01-05 08:05:45 +02009#include <option.h>
Elyes HAOUAS3dff32c2020-03-30 17:16:51 +020010#include <romstage_handoff.h>
Elyes HAOUAS51401c32019-05-15 21:09:30 +020011#include <types.h>
12
13#include "i945.h"
Stefan Reinauer278534d2008-10-29 04:51:07 +000014
Patrick Georgid0835952010-10-05 09:07:10 +000015int i945_silicon_revision(void)
Stefan Reinauer278534d2008-10-29 04:51:07 +000016{
Angel Pons3580d812020-06-11 14:13:33 +020017 return pci_read_config8(HOST_BRIDGE, PCI_CLASS_REVISION);
Stefan Reinauer278534d2008-10-29 04:51:07 +000018}
19
Stefan Reinauer71a3d962009-07-21 21:44:24 +000020static void i945m_detect_chipset(void)
Stefan Reinauer278534d2008-10-29 04:51:07 +000021{
22 u8 reg8;
23
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000024 printk(BIOS_INFO, "\n");
Angel Pons3580d812020-06-11 14:13:33 +020025 reg8 = (pci_read_config8(HOST_BRIDGE, 0xe7) & 0x70) >> 4;
Stefan Reinauer278534d2008-10-29 04:51:07 +000026 switch (reg8) {
27 case 1:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000028 printk(BIOS_INFO, "Mobile Intel(R) 82945GM/GME Express");
Stefan Reinauer278534d2008-10-29 04:51:07 +000029 break;
30 case 2:
Stefan Reinauer7981b942011-04-01 22:33:25 +020031 printk(BIOS_INFO, "Mobile Intel(R) 82945GMS/GU/GSE Express");
Stefan Reinauer278534d2008-10-29 04:51:07 +000032 break;
33 case 3:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000034 printk(BIOS_INFO, "Mobile Intel(R) 82945PM Express");
Stefan Reinauer278534d2008-10-29 04:51:07 +000035 break;
36 case 5:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000037 printk(BIOS_INFO, "Intel(R) 82945GT Express");
Stefan Reinauer278534d2008-10-29 04:51:07 +000038 break;
39 case 6:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000040 printk(BIOS_INFO, "Mobile Intel(R) 82943/82940GML Express");
Stefan Reinauer278534d2008-10-29 04:51:07 +000041 break;
Elyes HAOUAS3dff32c2020-03-30 17:16:51 +020042 default: /* Others reserved. */
43 printk(BIOS_INFO, "Unknown (%02x)", reg8);
Stefan Reinauer278534d2008-10-29 04:51:07 +000044 }
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000045 printk(BIOS_INFO, " Chipset\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +000046
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000047 printk(BIOS_DEBUG, "(G)MCH capable of up to FSB ");
Angel Pons3580d812020-06-11 14:13:33 +020048 reg8 = (pci_read_config8(HOST_BRIDGE, 0xe3) & 0xe0) >> 5;
Stefan Reinauer278534d2008-10-29 04:51:07 +000049 switch (reg8) {
50 case 2:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000051 printk(BIOS_DEBUG, "800 MHz"); /* According to 965 spec */
Stefan Reinauer278534d2008-10-29 04:51:07 +000052 break;
53 case 3:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000054 printk(BIOS_DEBUG, "667 MHz");
Stefan Reinauer278534d2008-10-29 04:51:07 +000055 break;
56 case 4:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000057 printk(BIOS_DEBUG, "533 MHz");
Stefan Reinauer278534d2008-10-29 04:51:07 +000058 break;
59 default:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000060 printk(BIOS_DEBUG, "N/A MHz (%02x)", reg8);
Stefan Reinauer278534d2008-10-29 04:51:07 +000061 }
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000062 printk(BIOS_DEBUG, "\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +000063
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000064 printk(BIOS_DEBUG, "(G)MCH capable of ");
Angel Pons3580d812020-06-11 14:13:33 +020065 reg8 = (pci_read_config8(HOST_BRIDGE, 0xe4) & 0x07);
Stefan Reinauer278534d2008-10-29 04:51:07 +000066 switch (reg8) {
67 case 2:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000068 printk(BIOS_DEBUG, "up to DDR2-667");
Stefan Reinauer278534d2008-10-29 04:51:07 +000069 break;
70 case 3:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000071 printk(BIOS_DEBUG, "up to DDR2-533");
Stefan Reinauer278534d2008-10-29 04:51:07 +000072 break;
73 case 4:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000074 printk(BIOS_DEBUG, "DDR2-400");
Stefan Reinauer278534d2008-10-29 04:51:07 +000075 break;
Elyes HAOUAS3dff32c2020-03-30 17:16:51 +020076 default: /* Others reserved. */
77 printk(BIOS_INFO, "unknown max. RAM clock (%02x).", reg8);
Stefan Reinauer278534d2008-10-29 04:51:07 +000078 }
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000079 printk(BIOS_DEBUG, "\n");
Elyes HAOUAS6372a0e2016-10-30 18:39:53 +010080
Julius Wernercd49cce2019-03-05 16:53:33 -080081 if (CONFIG(NORTHBRIDGE_INTEL_SUBTYPE_I945GC))
Elyes HAOUAS6372a0e2016-10-30 18:39:53 +010082 printk(BIOS_ERR, "coreboot is compiled for the wrong chipset.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +000083}
84
Stefan Reinauer71a3d962009-07-21 21:44:24 +000085static void i945_detect_chipset(void)
86{
87 u8 reg8;
88
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000089 printk(BIOS_INFO, "\nIntel(R) ");
Stefan Reinauer24b4df52010-01-17 13:47:35 +000090
Angel Pons3580d812020-06-11 14:13:33 +020091 reg8 = ((pci_read_config8(HOST_BRIDGE, 0xe7) >> 5) & 4)
92 | ((pci_read_config8(HOST_BRIDGE, 0xe4) >> 4) & 3);
Stefan Reinauer71a3d962009-07-21 21:44:24 +000093 switch (reg8) {
94 case 0:
95 case 1:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000096 printk(BIOS_INFO, "82945G");
Stefan Reinauer71a3d962009-07-21 21:44:24 +000097 break;
98 case 2:
Stefan Reinauer24b4df52010-01-17 13:47:35 +000099 case 3:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000100 printk(BIOS_INFO, "82945P");
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000101 break;
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000102 case 4:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000103 printk(BIOS_INFO, "82945GC");
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000104 break;
105 case 5:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000106 printk(BIOS_INFO, "82945GZ");
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000107 break;
108 case 6:
109 case 7:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000110 printk(BIOS_INFO, "82945PL");
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000111 break;
112 default:
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000113 break;
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000114 }
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000115 printk(BIOS_INFO, " Chipset\n");
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000116
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000117 printk(BIOS_DEBUG, "(G)MCH capable of ");
Angel Pons3580d812020-06-11 14:13:33 +0200118 reg8 = (pci_read_config8(HOST_BRIDGE, 0xe4) & 0x07);
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000119 switch (reg8) {
120 case 0:
Elyes HAOUAS5db94502016-10-30 18:30:21 +0100121 case 2:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000122 printk(BIOS_DEBUG, "up to DDR2-667");
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000123 break;
124 case 3:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000125 printk(BIOS_DEBUG, "up to DDR2-533");
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000126 break;
Elyes HAOUAS3dff32c2020-03-30 17:16:51 +0200127 default: /* Others reserved. */
128 printk(BIOS_INFO, "unknown max. RAM clock (%02x).", reg8);
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000129 }
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000130 printk(BIOS_DEBUG, "\n");
Elyes HAOUAS6372a0e2016-10-30 18:39:53 +0100131
Julius Wernercd49cce2019-03-05 16:53:33 -0800132 if (CONFIG(NORTHBRIDGE_INTEL_SUBTYPE_I945GM))
Elyes HAOUAS6372a0e2016-10-30 18:39:53 +0100133 printk(BIOS_ERR, "coreboot is compiled for the wrong chipset.\n");
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000134}
135
Stefan Reinauer278534d2008-10-29 04:51:07 +0000136static void i945_setup_bars(void)
137{
Arthur Heymans874a8f92016-05-19 16:06:09 +0200138 u8 reg8, gfxsize;
Stefan Reinauer278534d2008-10-29 04:51:07 +0000139
140 /* As of now, we don't have all the A0 workarounds implemented */
141 if (i945_silicon_revision() == 0)
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000142 printk(BIOS_INFO, "Warning: i945 silicon revision A0 might not work correctly.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000143
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000144 printk(BIOS_DEBUG, "Setting up static northbridge registers...");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000145 /* Set up all hardcoded northbridge BARs */
Angel Pons4299cb42021-01-20 12:32:22 +0100146 pci_write_config32(HOST_BRIDGE, EPBAR, CONFIG_FIXED_EPBAR_MMIO_BASE | 1);
147 pci_write_config32(HOST_BRIDGE, MCHBAR, CONFIG_FIXED_MCHBAR_MMIO_BASE | 1);
148 pci_write_config32(HOST_BRIDGE, DMIBAR, CONFIG_FIXED_DMIBAR_MMIO_BASE | 1);
Angel Pons3580d812020-06-11 14:13:33 +0200149 pci_write_config32(HOST_BRIDGE, X60BAR, DEFAULT_X60BAR | 1);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000150
Elyes HAOUAS2119d0b2020-02-16 10:01:33 +0100151 /* vram size from CMOS option */
Arthur Heymans874a8f92016-05-19 16:06:09 +0200152 if (get_option(&gfxsize, "gfx_uma_size") != CB_SUCCESS)
153 gfxsize = 2; /* 2 for 8MB */
154 /* make sure no invalid setting is used */
155 if (gfxsize > 6)
156 gfxsize = 2;
Angel Pons3580d812020-06-11 14:13:33 +0200157 pci_write_config16(HOST_BRIDGE, GGC, ((gfxsize + 1) << 4));
Arthur Heymansd522db02018-08-06 15:50:54 +0200158 /* TSEG 2M, This amount can easily be covered by SMRR MTRR's,
159 which requires to have TSEG_BASE aligned to TSEG_SIZE. */
Angel Pons3580d812020-06-11 14:13:33 +0200160 pci_update_config8(HOST_BRIDGE, ESMRAMC, ~0x07, (1 << 1) | (1 << 0));
Arthur Heymanse07df9d2018-04-09 22:03:21 +0200161
Stefan Reinauer278534d2008-10-29 04:51:07 +0000162 /* Set C0000-FFFFF to access RAM on both reads and writes */
Angel Pons3580d812020-06-11 14:13:33 +0200163 pci_write_config8(HOST_BRIDGE, PAM0, 0x30);
164 pci_write_config8(HOST_BRIDGE, PAM1, 0x33);
165 pci_write_config8(HOST_BRIDGE, PAM2, 0x33);
166 pci_write_config8(HOST_BRIDGE, PAM3, 0x33);
167 pci_write_config8(HOST_BRIDGE, PAM4, 0x33);
168 pci_write_config8(HOST_BRIDGE, PAM5, 0x33);
169 pci_write_config8(HOST_BRIDGE, PAM6, 0x33);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000170
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000171 printk(BIOS_DEBUG, " done.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000172
173 /* Wait for MCH BAR to come up */
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000174 printk(BIOS_DEBUG, "Waiting for MCHBAR to come up...");
Angel Pons3580d812020-06-11 14:13:33 +0200175 if ((pci_read_config32(HOST_BRIDGE, 0xe4) & 0x20000) == 0x00) { /* Bit 49 of CAPID0 */
Stefan Reinauer278534d2008-10-29 04:51:07 +0000176 do {
177 reg8 = *(volatile u8 *)0xfed40000;
178 } while (!(reg8 & 0x80));
179 }
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000180 printk(BIOS_DEBUG, "ok\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000181}
182
183static void i945_setup_egress_port(void)
184{
185 u32 reg32;
186 u32 timeout;
187
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000188 printk(BIOS_DEBUG, "Setting up Egress Port RCRB\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000189
190 /* Egress Port Virtual Channel 0 Configuration */
191
192 /* map only TC0 to VC0 */
193 reg32 = EPBAR32(EPVC0RCTL);
194 reg32 &= 0xffffff01;
195 EPBAR32(EPVC0RCTL) = reg32;
196
Stefan Reinauer278534d2008-10-29 04:51:07 +0000197 reg32 = EPBAR32(EPPVCCAP1);
198 reg32 &= ~(7 << 0);
199 reg32 |= 1;
200 EPBAR32(EPPVCCAP1) = reg32;
201
202 /* Egress Port Virtual Channel 1 Configuration */
203 reg32 = EPBAR32(0x2c);
204 reg32 &= 0xffffff00;
Julius Wernercd49cce2019-03-05 16:53:33 -0800205 if (CONFIG(NORTHBRIDGE_INTEL_SUBTYPE_I945GC)) {
Elyes HAOUASf7acdf82016-10-31 18:55:04 +0100206 if ((MCHBAR32(CLKCFG) & 7) == 0)
207 reg32 |= 0x1a; /* 1067MHz */
208 }
Stefan Reinauer278534d2008-10-29 04:51:07 +0000209 if ((MCHBAR32(CLKCFG) & 7) == 1)
210 reg32 |= 0x0d; /* 533MHz */
Elyes HAOUASf7acdf82016-10-31 18:55:04 +0100211 if ((MCHBAR32(CLKCFG) & 7) == 2)
212 reg32 |= 0x14; /* 800MHz */
Stefan Reinauer278534d2008-10-29 04:51:07 +0000213 if ((MCHBAR32(CLKCFG) & 7) == 3)
214 reg32 |= 0x10; /* 667MHz */
215 EPBAR32(0x2c) = reg32;
216
217 EPBAR32(EPVC1MTS) = 0x0a0a0a0a;
218
219 reg32 = EPBAR32(EPVC1RCAP);
220 reg32 &= ~(0x7f << 16);
221 reg32 |= (0x0a << 16);
222 EPBAR32(EPVC1RCAP) = reg32;
223
Julius Wernercd49cce2019-03-05 16:53:33 -0800224 if (CONFIG(NORTHBRIDGE_INTEL_SUBTYPE_I945GC)) {
Arthur Heymans70a8e342017-03-09 11:30:23 +0100225 if ((MCHBAR32(CLKCFG) & 7) == 0) { /* 1067MHz */
Elyes HAOUASf7acdf82016-10-31 18:55:04 +0100226 EPBAR32(EPVC1IST + 0) = 0x01380138;
227 EPBAR32(EPVC1IST + 4) = 0x01380138;
228 }
229 }
230
Stefan Reinauer278534d2008-10-29 04:51:07 +0000231 if ((MCHBAR32(CLKCFG) & 7) == 1) { /* 533MHz */
232 EPBAR32(EPVC1IST + 0) = 0x009c009c;
233 EPBAR32(EPVC1IST + 4) = 0x009c009c;
234 }
235
Elyes HAOUASf7acdf82016-10-31 18:55:04 +0100236 if ((MCHBAR32(CLKCFG) & 7) == 2) { /* 800MHz */
237 EPBAR32(EPVC1IST + 0) = 0x00f000f0;
238 EPBAR32(EPVC1IST + 4) = 0x00f000f0;
239 }
240
Stefan Reinauer278534d2008-10-29 04:51:07 +0000241 if ((MCHBAR32(CLKCFG) & 7) == 3) { /* 667MHz */
242 EPBAR32(EPVC1IST + 0) = 0x00c000c0;
243 EPBAR32(EPVC1IST + 4) = 0x00c000c0;
244 }
245
246 /* Is internal graphics enabled? */
Angel Pons3580d812020-06-11 14:13:33 +0200247 if (pci_read_config8(HOST_BRIDGE, DEVEN) & (DEVEN_D2F0 | DEVEN_D2F1))
Stefan Reinauer278534d2008-10-29 04:51:07 +0000248 MCHBAR32(MMARB1) |= (1 << 17);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000249
250 /* Assign Virtual Channel ID 1 to VC1 */
251 reg32 = EPBAR32(EPVC1RCTL);
252 reg32 &= ~(7 << 24);
253 reg32 |= (1 << 24);
254 EPBAR32(EPVC1RCTL) = reg32;
Stefan Reinauer30140a52009-03-11 16:20:39 +0000255
Stefan Reinauer278534d2008-10-29 04:51:07 +0000256 reg32 = EPBAR32(EPVC1RCTL);
257 reg32 &= 0xffffff01;
258 reg32 |= (1 << 7);
259 EPBAR32(EPVC1RCTL) = reg32;
Stefan Reinauer30140a52009-03-11 16:20:39 +0000260
Stefan Reinauer278534d2008-10-29 04:51:07 +0000261 EPBAR32(PORTARB + 0x00) = 0x01000001;
262 EPBAR32(PORTARB + 0x04) = 0x00040000;
263 EPBAR32(PORTARB + 0x08) = 0x00001000;
264 EPBAR32(PORTARB + 0x0c) = 0x00000040;
265 EPBAR32(PORTARB + 0x10) = 0x01000001;
266 EPBAR32(PORTARB + 0x14) = 0x00040000;
267 EPBAR32(PORTARB + 0x18) = 0x00001000;
268 EPBAR32(PORTARB + 0x1c) = 0x00000040;
Stefan Reinauer30140a52009-03-11 16:20:39 +0000269
Stefan Reinauer278534d2008-10-29 04:51:07 +0000270 EPBAR32(EPVC1RCTL) |= (1 << 16);
271 EPBAR32(EPVC1RCTL) |= (1 << 16);
272
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000273 printk(BIOS_DEBUG, "Loading port arbitration table ...");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000274 /* Loop until bit 0 becomes 0 */
275 timeout = 0x7fffff;
Arthur Heymans70a8e342017-03-09 11:30:23 +0100276 while ((EPBAR16(EPVC1RSTS) & 1) && --timeout)
277 ;
Stefan Reinauer278534d2008-10-29 04:51:07 +0000278 if (!timeout)
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000279 printk(BIOS_DEBUG, "timeout!\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000280 else
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000281 printk(BIOS_DEBUG, "ok\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000282
283 /* Now enable VC1 */
284 EPBAR32(EPVC1RCTL) |= (1 << 31);
285
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000286 printk(BIOS_DEBUG, "Wait for VC1 negotiation ...");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000287 /* Wait for VC1 negotiation pending */
288 timeout = 0x7fff;
Arthur Heymans70a8e342017-03-09 11:30:23 +0100289 while ((EPBAR16(EPVC1RSTS) & (1 << 1)) && --timeout)
290 ;
Stefan Reinauer278534d2008-10-29 04:51:07 +0000291 if (!timeout)
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000292 printk(BIOS_DEBUG, "timeout!\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000293 else
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000294 printk(BIOS_DEBUG, "ok\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000295
296}
297
298static void ich7_setup_dmi_rcrb(void)
299{
300 u16 reg16;
Stefan Reinauer30140a52009-03-11 16:20:39 +0000301 u32 reg32;
Stefan Reinauer278534d2008-10-29 04:51:07 +0000302
Stefan Reinauer278534d2008-10-29 04:51:07 +0000303 reg16 = RCBA16(LCTL);
304 reg16 &= ~(3 << 0);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000305 reg16 |= 3;
Stefan Reinauer278534d2008-10-29 04:51:07 +0000306 RCBA16(LCTL) = reg16;
307
308 RCBA32(V0CTL) = 0x80000001;
309 RCBA32(V1CAP) = 0x03128010;
Stefan Reinauer278534d2008-10-29 04:51:07 +0000310
Stefan Reinauer30140a52009-03-11 16:20:39 +0000311 pci_write_config16(PCI_DEV(0, 0x1c, 0), 0x42, 0x0141);
312 pci_write_config16(PCI_DEV(0, 0x1c, 4), 0x42, 0x0141);
313 pci_write_config16(PCI_DEV(0, 0x1c, 5), 0x42, 0x0141);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000314
Stefan Reinauer30140a52009-03-11 16:20:39 +0000315 pci_write_config32(PCI_DEV(0, 0x1c, 4), 0x54, 0x00480ce0);
316 pci_write_config32(PCI_DEV(0, 0x1c, 5), 0x54, 0x00500ce0);
317
318 reg32 = RCBA32(V1CTL);
Arthur Heymans70a8e342017-03-09 11:30:23 +0100319 reg32 &= ~((0x7f << 1) | (7 << 17) | (7 << 24));
Stefan Reinauer30140a52009-03-11 16:20:39 +0000320 reg32 |= (0x40 << 1) | (4 << 17) | (1 << 24) | (1 << 31);
321 RCBA32(V1CTL) = reg32;
322
Stefan Reinauer30140a52009-03-11 16:20:39 +0000323 RCBA32(LCAP) |= (3 << 10);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000324}
325
326static void i945_setup_dmi_rcrb(void)
327{
328 u32 reg32;
329 u32 timeout;
Stefan Reinauerbf264e92010-05-14 19:09:20 +0000330 int activate_aspm = 1; /* hardcode ASPM for now */
Stefan Reinauer30140a52009-03-11 16:20:39 +0000331
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000332 printk(BIOS_DEBUG, "Setting up DMI RCRB\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000333
334 /* Virtual Channel 0 Configuration */
335 reg32 = DMIBAR32(DMIVC0RCTL0);
336 reg32 &= 0xffffff01;
337 DMIBAR32(DMIVC0RCTL0) = reg32;
Stefan Reinauer30140a52009-03-11 16:20:39 +0000338
Stefan Reinauer278534d2008-10-29 04:51:07 +0000339 reg32 = DMIBAR32(DMIPVCCAP1);
340 reg32 &= ~(7 << 0);
341 reg32 |= 1;
342 DMIBAR32(DMIPVCCAP1) = reg32;
Stefan Reinauer30140a52009-03-11 16:20:39 +0000343
Stefan Reinauer278534d2008-10-29 04:51:07 +0000344 reg32 = DMIBAR32(DMIVC1RCTL);
345 reg32 &= ~(7 << 24);
346 reg32 |= (1 << 24); /* NOTE: This ID must match ICH7 side */
347 DMIBAR32(DMIVC1RCTL) = reg32;
Stefan Reinauer30140a52009-03-11 16:20:39 +0000348
Stefan Reinauer278534d2008-10-29 04:51:07 +0000349 reg32 = DMIBAR32(DMIVC1RCTL);
350 reg32 &= 0xffffff01;
351 reg32 |= (1 << 7);
352 DMIBAR32(DMIVC1RCTL) = reg32;
353
354 /* Now enable VC1 */
355 DMIBAR32(DMIVC1RCTL) |= (1 << 31);
356
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000357 printk(BIOS_DEBUG, "Wait for VC1 negotiation ...");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000358 /* Wait for VC1 negotiation pending */
359 timeout = 0x7ffff;
Arthur Heymans70a8e342017-03-09 11:30:23 +0100360 while ((DMIBAR16(DMIVC1RSTS) & (1 << 1)) && --timeout)
361 ;
Stefan Reinauer278534d2008-10-29 04:51:07 +0000362 if (!timeout)
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000363 printk(BIOS_DEBUG, "timeout!\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000364 else
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000365 printk(BIOS_DEBUG, "done..\n");
Angel Pons81c9c272020-07-07 23:19:38 +0200366
Stefan Reinauer278534d2008-10-29 04:51:07 +0000367 /* Enable Active State Power Management (ASPM) L0 state */
368
369 reg32 = DMIBAR32(DMILCAP);
370 reg32 &= ~(7 << 12);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000371 reg32 |= (2 << 12);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000372
373 reg32 &= ~(7 << 15);
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000374
Stefan Reinauer30140a52009-03-11 16:20:39 +0000375 reg32 |= (2 << 15);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000376 DMIBAR32(DMILCAP) = reg32;
377
378 reg32 = DMIBAR32(DMICC);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000379 reg32 &= 0x00ffffff;
Stefan Reinauer278534d2008-10-29 04:51:07 +0000380 reg32 &= ~(3 << 0);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000381 reg32 |= (1 << 0);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000382 reg32 &= ~(3 << 20);
383 reg32 |= (1 << 20);
384
Stefan Reinauer278534d2008-10-29 04:51:07 +0000385 DMIBAR32(DMICC) = reg32;
386
Arthur Heymans70a8e342017-03-09 11:30:23 +0100387 if (activate_aspm)
Stefan Reinauer278534d2008-10-29 04:51:07 +0000388 DMIBAR32(DMILCTL) |= (3 << 0);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000389
390 /* Last but not least, some additional steps */
391 reg32 = MCHBAR32(FSBSNPCTL);
392 reg32 &= ~(0xff << 2);
393 reg32 |= (0xaa << 2);
394 MCHBAR32(FSBSNPCTL) = reg32;
395
396 DMIBAR32(0x2c) = 0x86000040;
397
398 reg32 = DMIBAR32(0x204);
399 reg32 &= ~0x3ff;
400#if 1
Elyes HAOUAS3dff32c2020-03-30 17:16:51 +0200401 reg32 |= 0x13f; /* for x4 DMI only */
Stefan Reinauer278534d2008-10-29 04:51:07 +0000402#else
Elyes HAOUAS3dff32c2020-03-30 17:16:51 +0200403 reg32 |= 0x1e4; /* for x2 DMI only */
Stefan Reinauer278534d2008-10-29 04:51:07 +0000404#endif
405 DMIBAR32(0x204) = reg32;
406
Angel Pons3580d812020-06-11 14:13:33 +0200407 if (pci_read_config8(HOST_BRIDGE, DEVEN) & (DEVEN_D2F0 | DEVEN_D2F1)) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000408 printk(BIOS_DEBUG, "Internal graphics: enabled\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000409 DMIBAR32(0x200) |= (1 << 21);
410 } else {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000411 printk(BIOS_DEBUG, "Internal graphics: disabled\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000412 DMIBAR32(0x200) &= ~(1 << 21);
413 }
414
415 reg32 = DMIBAR32(0x204);
416 reg32 &= ~((1 << 11) | (1 << 10));
417 DMIBAR32(0x204) = reg32;
418
419 reg32 = DMIBAR32(0x204);
420 reg32 &= ~(0xff << 12);
421 reg32 |= (0x0d << 12);
422 DMIBAR32(0x204) = reg32;
423
424 DMIBAR32(DMICTL1) |= (3 << 24);
425
426 reg32 = DMIBAR32(0x200);
427 reg32 &= ~(0x3 << 26);
428 reg32 |= (0x02 << 26);
429 DMIBAR32(0x200) = reg32;
430
431 DMIBAR32(DMIDRCCFG) &= ~(1 << 31);
432 DMIBAR32(DMICTL2) |= (1 << 31);
433
434 if (i945_silicon_revision() >= 3) {
435 reg32 = DMIBAR32(0xec0);
436 reg32 &= 0x0fffffff;
437 reg32 |= (2 << 28);
438 DMIBAR32(0xec0) = reg32;
439
440 reg32 = DMIBAR32(0xed4);
441 reg32 &= 0x0fffffff;
442 reg32 |= (2 << 28);
443 DMIBAR32(0xed4) = reg32;
444
445 reg32 = DMIBAR32(0xee8);
446 reg32 &= 0x0fffffff;
447 reg32 |= (2 << 28);
448 DMIBAR32(0xee8) = reg32;
449
450 reg32 = DMIBAR32(0xefc);
451 reg32 &= 0x0fffffff;
452 reg32 |= (2 << 28);
453 DMIBAR32(0xefc) = reg32;
454 }
455
456 /* wait for bit toggle to 0 */
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000457 printk(BIOS_DEBUG, "Waiting for DMI hardware...");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000458 timeout = 0x7fffff;
Arthur Heymans70a8e342017-03-09 11:30:23 +0100459 while ((DMIBAR8(0x32) & (1 << 1)) && --timeout)
460 ;
Stefan Reinauer278534d2008-10-29 04:51:07 +0000461 if (!timeout)
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000462 printk(BIOS_DEBUG, "timeout!\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000463 else
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000464 printk(BIOS_DEBUG, "ok\n");
Stefan Reinauer30140a52009-03-11 16:20:39 +0000465
Stefan Reinauerbf264e92010-05-14 19:09:20 +0000466 /* Clear Error Status Bits! */
Stefan Reinauer278534d2008-10-29 04:51:07 +0000467 DMIBAR32(0x1c4) = 0xffffffff;
468 DMIBAR32(0x1d0) = 0xffffffff;
469 DMIBAR32(0x228) = 0xffffffff;
Stefan Reinauer30140a52009-03-11 16:20:39 +0000470
Stefan Reinauerbf264e92010-05-14 19:09:20 +0000471 /* Program Read-Only Write-Once Registers */
Stefan Reinauer278534d2008-10-29 04:51:07 +0000472 DMIBAR32(0x308) = DMIBAR32(0x308);
473 DMIBAR32(0x314) = DMIBAR32(0x314);
474 DMIBAR32(0x324) = DMIBAR32(0x324);
475 DMIBAR32(0x328) = DMIBAR32(0x328);
Elyes HAOUASd3fa7fa52019-01-24 11:47:27 +0100476 DMIBAR32(0x334) = DMIBAR32(0x334);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000477 DMIBAR32(0x338) = DMIBAR32(0x338);
478
Patrick Georgia341a772014-09-29 19:51:21 +0200479 if (i945_silicon_revision() == 1 && (MCHBAR8(DFT_STRAP1) & (1 << 5))) {
Stefan Reinauer30140a52009-03-11 16:20:39 +0000480 if ((MCHBAR32(0x214) & 0xf) != 0x3) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000481 printk(BIOS_INFO, "DMI link requires A1 stepping workaround. Rebooting.\n");
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000482 reg32 = DMIBAR32(0x224);
483 reg32 &= ~(7 << 0);
484 reg32 |= (3 << 0);
485 DMIBAR32(0x224) = reg32;
Elyes HAOUAS5db98712019-04-21 18:50:34 +0200486 system_reset();
Stefan Reinauer278534d2008-10-29 04:51:07 +0000487 }
488 }
489}
490
491static void i945_setup_pci_express_x16(void)
492{
493 u32 timeout;
494 u32 reg32;
495 u16 reg16;
Elyes HAOUAS961658f2020-04-06 09:42:21 +0200496 const pci_devfn_t p2peg = PCI_DEV(0, 0x01, 0);
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000497
Kyösti Mälkki2647b6f2019-09-29 07:03:55 +0300498 u8 tmp_secondary = 0x0a;
Elyes HAOUAS961658f2020-04-06 09:42:21 +0200499 const pci_devfn_t peg_plugin = PCI_DEV(tmp_secondary, 0, 0);
Kyösti Mälkki2647b6f2019-09-29 07:03:55 +0300500
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000501 printk(BIOS_DEBUG, "Enabling PCI Express x16 Link\n");
Stefan Reinauer30140a52009-03-11 16:20:39 +0000502
Angel Pons3580d812020-06-11 14:13:33 +0200503 pci_or_config16(HOST_BRIDGE, DEVEN, DEVEN_D1F0);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000504
Angel Ponse3c68d22020-06-08 12:09:03 +0200505 pci_and_config32(p2peg, PEGCC, ~(1 << 8));
Stefan Reinauer30140a52009-03-11 16:20:39 +0000506
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000507 /* We have no success with querying the usual PCIe registers
508 * for link setup success on the i945. Hence we assign a temporary
509 * PCI bus 0x0a and check whether we find a device on 0:a.0
510 */
511
Kyösti Mälkkiad787e12019-09-30 04:14:19 +0300512 /* Force PCIRST# */
513 pci_s_assert_secondary_reset(p2peg);
514 pci_s_deassert_secondary_reset(p2peg);
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000515
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300516 reg16 = pci_read_config16(p2peg, SLOTSTS);
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000517 printk(BIOS_DEBUG, "SLOTSTS: %04x\n", reg16);
Arthur Heymans70a8e342017-03-09 11:30:23 +0100518 if (!(reg16 & 0x48))
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000519 goto disable_pciexpress_x16_link;
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000520 reg16 |= (1 << 4) | (1 << 0);
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300521 pci_write_config16(p2peg, SLOTSTS, reg16);
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000522
Kyösti Mälkkiad787e12019-09-30 04:14:19 +0300523 pci_s_bridge_set_secondary(p2peg, tmp_secondary);
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000524
Angel Ponse3c68d22020-06-08 12:09:03 +0200525 pci_and_config32(p2peg, 0x224, ~(1 << 8));
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000526
Arthur Heymans70a8e342017-03-09 11:30:23 +0100527 MCHBAR16(UPMC1) &= ~((1 << 5) | (1 << 0));
Stefan Reinauer30140a52009-03-11 16:20:39 +0000528
Martin Roth128c1042016-11-18 09:29:03 -0700529 /* Initialize PEG_CAP */
Angel Ponse3c68d22020-06-08 12:09:03 +0200530 pci_or_config16(p2peg, PEG_CAP, 1 << 8);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000531
532 /* Setup SLOTCAP */
Elyes HAOUAS3dff32c2020-03-30 17:16:51 +0200533 /* TODO: These values are mainboard dependent and should be set from devicetree.cb.
Stefan Reinauer30140a52009-03-11 16:20:39 +0000534 */
535 /* NOTE: SLOTCAP becomes RO after the first write! */
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300536 reg32 = pci_read_config32(p2peg, SLOTCAP);
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000537 reg32 &= 0x0007ffff;
538
539 reg32 &= 0xfffe007f;
540
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300541 pci_write_config32(p2peg, SLOTCAP, reg32);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000542
543 /* Wait for training to succeed */
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000544 printk(BIOS_DEBUG, "PCIe link training ...");
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000545 timeout = 0x7ffff;
Angel Ponse3c68d22020-06-08 12:09:03 +0200546 while ((((pci_read_config32(p2peg, PEGSTS) >> 16) & 3) != 3) && --timeout)
Arthur Heymans70a8e342017-03-09 11:30:23 +0100547 ;
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000548
Kyösti Mälkki2647b6f2019-09-29 07:03:55 +0300549 reg32 = pci_read_config32(peg_plugin, PCI_VENDOR_ID);
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000550 if (reg32 != 0x00000000 && reg32 != 0xffffffff) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000551 printk(BIOS_DEBUG, " Detected PCIe device %04x:%04x\n",
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000552 reg32 & 0xffff, reg32 >> 16);
553 } else {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000554 printk(BIOS_DEBUG, " timeout!\n");
Stefan Reinauer30140a52009-03-11 16:20:39 +0000555
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000556 printk(BIOS_DEBUG, "Restrain PCIe port to x1\n");
Stefan Reinauer30140a52009-03-11 16:20:39 +0000557
Angel Ponse3c68d22020-06-08 12:09:03 +0200558 pci_update_config32(p2peg, PEGSTS, ~(0xf << 1), 1);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000559
Kyösti Mälkkiad787e12019-09-30 04:14:19 +0300560 /* Force PCIRST# */
561 pci_s_assert_secondary_reset(p2peg);
562 pci_s_deassert_secondary_reset(p2peg);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000563
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000564 printk(BIOS_DEBUG, "PCIe link training ...");
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000565 timeout = 0x7ffff;
Angel Ponse3c68d22020-06-08 12:09:03 +0200566 while ((((pci_read_config32(p2peg, PEGSTS) >> 16) & 3) != 3) && --timeout)
Arthur Heymans70a8e342017-03-09 11:30:23 +0100567 ;
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000568
Kyösti Mälkki2647b6f2019-09-29 07:03:55 +0300569 reg32 = pci_read_config32(peg_plugin, PCI_VENDOR_ID);
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000570 if (reg32 != 0x00000000 && reg32 != 0xffffffff) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000571 printk(BIOS_DEBUG, " Detected PCIe x1 device %04x:%04x\n",
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000572 reg32 & 0xffff, reg32 >> 16);
573 } else {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000574 printk(BIOS_DEBUG, " timeout!\n");
575 printk(BIOS_DEBUG, "Disabling PCIe x16 port completely.\n");
Stefan Reinauer30140a52009-03-11 16:20:39 +0000576 goto disable_pciexpress_x16_link;
Stefan Reinauer30140a52009-03-11 16:20:39 +0000577 }
Stefan Reinauer30140a52009-03-11 16:20:39 +0000578 }
579
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300580 reg16 = pci_read_config16(p2peg, 0xb2);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000581 reg16 >>= 4;
582 reg16 &= 0x3f;
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000583 /* reg16 == 1 -> x1; reg16 == 16 -> x16 */
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000584 printk(BIOS_DEBUG, "PCIe x%d link training succeeded.\n", reg16);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000585
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300586 reg32 = pci_read_config32(p2peg, PEGTC);
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000587 reg32 &= 0xfffffc00; /* clear [9:0] */
Arthur Heymans70a8e342017-03-09 11:30:23 +0100588 if (reg16 == 1)
Stefan Reinauer30140a52009-03-11 16:20:39 +0000589 reg32 |= 0x32b;
590 // TODO
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300591 /* pci_write_config32(p2peg, PEGTC, reg32); */
Arthur Heymans70a8e342017-03-09 11:30:23 +0100592 else if (reg16 == 16)
Stefan Reinauer30140a52009-03-11 16:20:39 +0000593 reg32 |= 0x0f4;
594 // TODO
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300595 /* pci_write_config32(p2peg, PEGTC, reg32); */
Stefan Reinauer30140a52009-03-11 16:20:39 +0000596
Kyösti Mälkki2647b6f2019-09-29 07:03:55 +0300597 reg32 = (pci_read_config32(peg_plugin, 0x8) >> 8);
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000598 printk(BIOS_DEBUG, "PCIe device class: %06x\n", reg32);
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000599 if (reg32 == 0x030000) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000600 printk(BIOS_DEBUG, "PCIe device is VGA. Disabling IGD.\n");
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000601 reg16 = (1 << 1);
Angel Pons3580d812020-06-11 14:13:33 +0200602 pci_write_config16(HOST_BRIDGE, GGC, reg16);
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000603
Angel Pons3580d812020-06-11 14:13:33 +0200604 pci_and_config32(HOST_BRIDGE, DEVEN, ~(DEVEN_D2F0 | DEVEN_D2F1));
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000605 }
606
Angel Ponse3c68d22020-06-08 12:09:03 +0200607 /* Enable GPEs: PMEGPE, HPGPE, GENGPE */
608 pci_or_config32(p2peg, PEG_LC, (1 << 2) | (1 << 1) | (1 << 0));
Stefan Reinauer30140a52009-03-11 16:20:39 +0000609
610 /* Virtual Channel Configuration: Only VC0 on PCIe x16 */
Angel Ponse3c68d22020-06-08 12:09:03 +0200611 pci_and_config32(p2peg, VC0RCTL, ~0x000000fe);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000612
613 /* Extended VC count */
Angel Ponse3c68d22020-06-08 12:09:03 +0200614 pci_and_config32(p2peg, PVCCAP1, ~(7 << 0));
Stefan Reinauer30140a52009-03-11 16:20:39 +0000615
616 /* Active State Power Management ASPM */
617
618 /* TODO */
619
620 /* Clear error bits */
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300621 pci_write_config16(p2peg, PCISTS1, 0xffff);
622 pci_write_config16(p2peg, SSTS1, 0xffff);
623 pci_write_config16(p2peg, DSTS, 0xffff);
624 pci_write_config32(p2peg, UESTS, 0xffffffff);
625 pci_write_config32(p2peg, CESTS, 0xffffffff);
626 pci_write_config32(p2peg, 0x1f0, 0xffffffff);
627 pci_write_config32(p2peg, 0x228, 0xffffffff);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000628
629 /* Program R/WO registers */
Angel Ponse3c68d22020-06-08 12:09:03 +0200630 pci_update_config32(p2peg, 0x308, ~0, 0);
631 pci_update_config32(p2peg, 0x314, ~0, 0);
632 pci_update_config32(p2peg, 0x324, ~0, 0);
633 pci_update_config32(p2peg, 0x328, ~0, 0);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000634
Stefan Reinauer30140a52009-03-11 16:20:39 +0000635 /* Additional PCIe graphics setup */
Angel Ponse3c68d22020-06-08 12:09:03 +0200636 pci_or_config32(p2peg, 0xf0, 3 << 26);
637 pci_or_config32(p2peg, 0xf0, 3 << 24);
638 pci_or_config32(p2peg, 0xf0, 1 << 5);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000639
Angel Ponse3c68d22020-06-08 12:09:03 +0200640 pci_update_config32(p2peg, 0x200, ~(3 << 26), 2 << 26);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000641
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300642 reg32 = pci_read_config32(p2peg, 0xe80);
Arthur Heymans70a8e342017-03-09 11:30:23 +0100643 if (i945_silicon_revision() >= 2)
Stefan Reinauer30140a52009-03-11 16:20:39 +0000644 reg32 |= (1 << 12);
Arthur Heymans70a8e342017-03-09 11:30:23 +0100645 else
Stefan Reinauer30140a52009-03-11 16:20:39 +0000646 reg32 &= ~(1 << 12);
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300647 pci_write_config32(p2peg, 0xe80, reg32);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000648
Angel Ponse3c68d22020-06-08 12:09:03 +0200649 pci_and_config32(p2peg, 0xeb4, ~(1 << 31));
Stefan Reinauer30140a52009-03-11 16:20:39 +0000650
Angel Ponse3c68d22020-06-08 12:09:03 +0200651 pci_or_config32(p2peg, 0xfc, 1 << 31);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000652
653 if (i945_silicon_revision() >= 3) {
654 static const u32 reglist[] = {
Elyes HAOUAS3dff32c2020-03-30 17:16:51 +0200655 0xec0, 0xed4, 0xee8, 0xefc, 0xf10, 0xf24, 0xf38, 0xf4c,
656 0xf60, 0xf74, 0xf88, 0xf9c, 0xfb0, 0xfc4, 0xfd8, 0xfec
Stefan Reinauer30140a52009-03-11 16:20:39 +0000657 };
658
659 int i;
Angel Ponse3c68d22020-06-08 12:09:03 +0200660 for (i = 0; i < ARRAY_SIZE(reglist); i++)
661 pci_update_config32(p2peg, reglist[i], ~(0xf << 28), 2 << 28);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000662 }
663
Arthur Heymans70a8e342017-03-09 11:30:23 +0100664 if (i945_silicon_revision() <= 2) {
Stefan Reinauer30140a52009-03-11 16:20:39 +0000665 /* Set voltage specific parameters */
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300666 reg32 = pci_read_config32(p2peg, 0xe80);
Stefan Reinauerbf264e92010-05-14 19:09:20 +0000667 reg32 &= (0xf << 4); /* Default case 1.05V */
Patrick Georgi3cb86de2014-09-29 20:42:33 +0200668 if ((MCHBAR32(DFT_STRAP1) & (1 << 20)) == 0) { /* 1.50V */
Stefan Reinauer30140a52009-03-11 16:20:39 +0000669 reg32 |= (7 << 4);
670 }
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300671 pci_write_config32(p2peg, 0xe80, reg32);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000672 }
673
674 return;
675
676disable_pciexpress_x16_link:
Stefan Reinauer278534d2008-10-29 04:51:07 +0000677 /* For now we just disable the x16 link */
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000678 printk(BIOS_DEBUG, "Disabling PCI Express x16 Link\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000679
680 MCHBAR16(UPMC1) |= (1 << 5) | (1 << 0);
681
Kyösti Mälkkiad787e12019-09-30 04:14:19 +0300682 /* Toggle PCIRST# */
683 pci_s_assert_secondary_reset(p2peg);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000684
Angel Ponse3c68d22020-06-08 12:09:03 +0200685 pci_or_config32(p2peg, 0x224, 1 << 8);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000686
Kyösti Mälkkiad787e12019-09-30 04:14:19 +0300687 pci_s_deassert_secondary_reset(p2peg);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000688
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000689 printk(BIOS_DEBUG, "Wait for link to enter detect state... ");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000690 timeout = 0x7fffff;
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300691 for (reg32 = pci_read_config32(p2peg, PEGSTS);
Arthur Heymans70a8e342017-03-09 11:30:23 +0100692 (reg32 & 0x000f0000) && --timeout;)
693 ;
Stefan Reinauer278534d2008-10-29 04:51:07 +0000694 if (!timeout)
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000695 printk(BIOS_DEBUG, "timeout!\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000696 else
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000697 printk(BIOS_DEBUG, "ok\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000698
699 /* Finally: Disable the PCI config header */
Angel Pons3580d812020-06-11 14:13:33 +0200700 pci_and_config16(HOST_BRIDGE, DEVEN, ~DEVEN_D1F0);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000701}
702
703static void i945_setup_root_complex_topology(void)
704{
705 u32 reg32;
Elyes HAOUAS961658f2020-04-06 09:42:21 +0200706 const pci_devfn_t p2peg = PCI_DEV(0, 0x01, 0);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000707
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000708 printk(BIOS_DEBUG, "Setting up Root Complex Topology\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000709 /* Egress Port Root Topology */
Stefan Reinauer30140a52009-03-11 16:20:39 +0000710
Stefan Reinauer278534d2008-10-29 04:51:07 +0000711 reg32 = EPBAR32(EPESD);
712 reg32 &= 0xff00ffff;
713 reg32 |= (1 << 16);
714 EPBAR32(EPESD) = reg32;
Stefan Reinauer30140a52009-03-11 16:20:39 +0000715
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000716 EPBAR32(EPLE1D) |= (1 << 16) | (1 << 0);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000717
Angel Pons4299cb42021-01-20 12:32:22 +0100718 EPBAR32(EPLE1A) = CONFIG_FIXED_DMIBAR_MMIO_BASE;
Stefan Reinauer30140a52009-03-11 16:20:39 +0000719
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000720 EPBAR32(EPLE2D) |= (1 << 16) | (1 << 0);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000721
722 /* DMI Port Root Topology */
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000723
Stefan Reinauer278534d2008-10-29 04:51:07 +0000724 reg32 = DMIBAR32(DMILE1D);
725 reg32 &= 0x00ffffff;
Stefan Reinauer30140a52009-03-11 16:20:39 +0000726
Stefan Reinauer278534d2008-10-29 04:51:07 +0000727 reg32 &= 0xff00ffff;
728 reg32 |= (2 << 16);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000729
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000730 reg32 |= (1 << 0);
731 DMIBAR32(DMILE1D) = reg32;
Stefan Reinauer30140a52009-03-11 16:20:39 +0000732
Angel Pons6e732d32021-01-28 13:56:18 +0100733 DMIBAR32(DMILE1A) = CONFIG_FIXED_RCBA_MMIO_BASE;
Stefan Reinauer30140a52009-03-11 16:20:39 +0000734
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000735 DMIBAR32(DMILE2D) |= (1 << 16) | (1 << 0);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000736
Angel Pons4299cb42021-01-20 12:32:22 +0100737 DMIBAR32(DMILE2A) = CONFIG_FIXED_EPBAR_MMIO_BASE;
Stefan Reinauer278534d2008-10-29 04:51:07 +0000738
739 /* PCI Express x16 Port Root Topology */
Angel Pons3580d812020-06-11 14:13:33 +0200740 if (pci_read_config8(HOST_BRIDGE, DEVEN) & DEVEN_D1F0) {
Angel Pons4299cb42021-01-20 12:32:22 +0100741 pci_write_config32(p2peg, LE1A, CONFIG_FIXED_EPBAR_MMIO_BASE);
Angel Ponse3c68d22020-06-08 12:09:03 +0200742 pci_or_config32(p2peg, LE1D, 1 << 0);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000743 }
744}
745
746static void ich7_setup_root_complex_topology(void)
747{
Elyes HAOUASb217baa2019-01-18 15:32:39 +0100748 /* Write the R/WO registers */
749
750 RCBA32(ESD) |= (2 << 16);
751
752 RCBA32(ULD) |= (1 << 24) | (1 << 16);
753
Angel Pons4299cb42021-01-20 12:32:22 +0100754 RCBA32(ULBA) = CONFIG_FIXED_DMIBAR_MMIO_BASE;
Elyes HAOUASb217baa2019-01-18 15:32:39 +0100755 /* Write ESD.CID to TCID */
756 RCBA32(RP1D) |= (2 << 16);
757 RCBA32(RP2D) |= (2 << 16);
758 RCBA32(RP3D) |= (2 << 16);
759 RCBA32(RP4D) |= (2 << 16);
760 RCBA32(HDD) |= (2 << 16);
761 RCBA32(RP5D) |= (2 << 16);
762 RCBA32(RP6D) |= (2 << 16);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000763}
764
765static void ich7_setup_pci_express(void)
766{
Elyes HAOUAS13746072019-12-08 11:34:24 +0100767 /* Enable PCIe Root Port Clock Gate */
Stefan Reinauer30140a52009-03-11 16:20:39 +0000768 RCBA32(CG) |= (1 << 0);
769
Stefan Reinauerbf264e92010-05-14 19:09:20 +0000770 /* Initialize slot power limit for root ports */
Stefan Reinauer278534d2008-10-29 04:51:07 +0000771 pci_write_config32(PCI_DEV(0, 0x1c, 0), 0x54, 0x00000060);
772
773 pci_write_config32(PCI_DEV(0, 0x1c, 0), 0xd8, 0x00110000);
774}
775
Patrick Georgid0835952010-10-05 09:07:10 +0000776void i945_early_initialization(void)
Stefan Reinauer278534d2008-10-29 04:51:07 +0000777{
778 /* Print some chipset specific information */
Angel Pons3580d812020-06-11 14:13:33 +0200779 switch (pci_read_config32(HOST_BRIDGE, 0)) {
Stefan Reinauerbf264e92010-05-14 19:09:20 +0000780 case 0x27708086: /* 82945G/GZ/GC/P/PL */
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000781 i945_detect_chipset();
782 break;
Stefan Reinauerbf264e92010-05-14 19:09:20 +0000783 case 0x27a08086: /* 945GME/GSE */
784 case 0x27ac8086: /* 945GM/PM/GMS/GU/GT, 943/940GML */
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000785 i945m_detect_chipset();
786 break;
787 }
Stefan Reinauer278534d2008-10-29 04:51:07 +0000788
789 /* Setup all BARs required for early PCIe and raminit */
790 i945_setup_bars();
791
792 /* Change port80 to LPC */
793 RCBA32(GCS) &= (~0x04);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000794
795 /* Just do it that way */
796 RCBA32(0x2010) |= (1 << 10);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000797}
798
Vladimir Serbinenko55601882014-10-15 20:17:51 +0200799static void i945_prepare_resume(int s3resume)
800{
801 int cbmem_was_initted;
802
803 cbmem_was_initted = !cbmem_recovery(s3resume);
804
Kyösti Mälkki81830252016-06-25 11:40:00 +0300805 romstage_handoff_init(cbmem_was_initted && s3resume);
Vladimir Serbinenko55601882014-10-15 20:17:51 +0200806}
807
808void i945_late_initialization(int s3resume)
Stefan Reinauer278534d2008-10-29 04:51:07 +0000809{
810 i945_setup_egress_port();
811
812 ich7_setup_root_complex_topology();
813
814 ich7_setup_pci_express();
815
816 ich7_setup_dmi_rcrb();
817
818 i945_setup_dmi_rcrb();
819
Julius Wernercd49cce2019-03-05 16:53:33 -0800820 if (CONFIG(NORTHBRIDGE_INTEL_SUBTYPE_I945GM))
Arthur Heymans2f6b52e2017-03-02 23:51:09 +0100821 i945_setup_pci_express_x16();
Stefan Reinauer278534d2008-10-29 04:51:07 +0000822
823 i945_setup_root_complex_topology();
Vladimir Serbinenko55601882014-10-15 20:17:51 +0200824
Kyösti Mälkki346d2012019-03-23 10:07:16 +0200825 if (CONFIG(DEBUG_RAM_SETUP))
826 sdram_dump_mchbar_registers();
Vladimir Serbinenko55601882014-10-15 20:17:51 +0200827
828 MCHBAR16(SSKPD) = 0xCAFE;
829
830 i945_prepare_resume(s3resume);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000831}