blob: d730b2e628ca328e3b691b3ffb79f11cb84911e6 [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 */
Angel Pons88dcb312021-04-26 17:10:28 +0200152 gfxsize = get_uint_option("gfx_uma_size", 2); /* 2 for 8MB */
Arthur Heymans874a8f92016-05-19 16:06:09 +0200153 /* make sure no invalid setting is used */
154 if (gfxsize > 6)
155 gfxsize = 2;
Angel Pons3580d812020-06-11 14:13:33 +0200156 pci_write_config16(HOST_BRIDGE, GGC, ((gfxsize + 1) << 4));
Arthur Heymansd522db02018-08-06 15:50:54 +0200157 /* TSEG 2M, This amount can easily be covered by SMRR MTRR's,
158 which requires to have TSEG_BASE aligned to TSEG_SIZE. */
Angel Pons3580d812020-06-11 14:13:33 +0200159 pci_update_config8(HOST_BRIDGE, ESMRAMC, ~0x07, (1 << 1) | (1 << 0));
Arthur Heymanse07df9d2018-04-09 22:03:21 +0200160
Stefan Reinauer278534d2008-10-29 04:51:07 +0000161 /* Set C0000-FFFFF to access RAM on both reads and writes */
Angel Pons3580d812020-06-11 14:13:33 +0200162 pci_write_config8(HOST_BRIDGE, PAM0, 0x30);
163 pci_write_config8(HOST_BRIDGE, PAM1, 0x33);
164 pci_write_config8(HOST_BRIDGE, PAM2, 0x33);
165 pci_write_config8(HOST_BRIDGE, PAM3, 0x33);
166 pci_write_config8(HOST_BRIDGE, PAM4, 0x33);
167 pci_write_config8(HOST_BRIDGE, PAM5, 0x33);
168 pci_write_config8(HOST_BRIDGE, PAM6, 0x33);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000169
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000170 printk(BIOS_DEBUG, " done.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000171
172 /* Wait for MCH BAR to come up */
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000173 printk(BIOS_DEBUG, "Waiting for MCHBAR to come up...");
Angel Pons3580d812020-06-11 14:13:33 +0200174 if ((pci_read_config32(HOST_BRIDGE, 0xe4) & 0x20000) == 0x00) { /* Bit 49 of CAPID0 */
Stefan Reinauer278534d2008-10-29 04:51:07 +0000175 do {
176 reg8 = *(volatile u8 *)0xfed40000;
177 } while (!(reg8 & 0x80));
178 }
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000179 printk(BIOS_DEBUG, "ok\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000180}
181
182static void i945_setup_egress_port(void)
183{
184 u32 reg32;
185 u32 timeout;
186
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000187 printk(BIOS_DEBUG, "Setting up Egress Port RCRB\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000188
189 /* Egress Port Virtual Channel 0 Configuration */
190
191 /* map only TC0 to VC0 */
Angel Pons1d4044a2021-03-27 19:11:51 +0100192 reg32 = epbar_read32(EPVC0RCTL);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000193 reg32 &= 0xffffff01;
Angel Pons1d4044a2021-03-27 19:11:51 +0100194 epbar_write32(EPVC0RCTL, reg32);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000195
Angel Pons1d4044a2021-03-27 19:11:51 +0100196 reg32 = epbar_read32(EPPVCCAP1);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000197 reg32 &= ~(7 << 0);
198 reg32 |= 1;
Angel Pons1d4044a2021-03-27 19:11:51 +0100199 epbar_write32(EPPVCCAP1, reg32);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000200
201 /* Egress Port Virtual Channel 1 Configuration */
Angel Pons1d4044a2021-03-27 19:11:51 +0100202 reg32 = epbar_read32(0x2c);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000203 reg32 &= 0xffffff00;
Julius Wernercd49cce2019-03-05 16:53:33 -0800204 if (CONFIG(NORTHBRIDGE_INTEL_SUBTYPE_I945GC)) {
Angel Pons1d4044a2021-03-27 19:11:51 +0100205 if ((mchbar_read32(CLKCFG) & 7) == 0)
Elyes HAOUASf7acdf82016-10-31 18:55:04 +0100206 reg32 |= 0x1a; /* 1067MHz */
207 }
Angel Pons1d4044a2021-03-27 19:11:51 +0100208 if ((mchbar_read32(CLKCFG) & 7) == 1)
Stefan Reinauer278534d2008-10-29 04:51:07 +0000209 reg32 |= 0x0d; /* 533MHz */
Angel Pons1d4044a2021-03-27 19:11:51 +0100210 if ((mchbar_read32(CLKCFG) & 7) == 2)
Elyes HAOUASf7acdf82016-10-31 18:55:04 +0100211 reg32 |= 0x14; /* 800MHz */
Angel Pons1d4044a2021-03-27 19:11:51 +0100212 if ((mchbar_read32(CLKCFG) & 7) == 3)
Stefan Reinauer278534d2008-10-29 04:51:07 +0000213 reg32 |= 0x10; /* 667MHz */
Angel Pons1d4044a2021-03-27 19:11:51 +0100214 epbar_write32(0x2c, reg32);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000215
Angel Pons1d4044a2021-03-27 19:11:51 +0100216 epbar_write32(EPVC1MTS, 0x0a0a0a0a);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000217
Angel Pons1d4044a2021-03-27 19:11:51 +0100218 reg32 = epbar_read32(EPVC1RCAP);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000219 reg32 &= ~(0x7f << 16);
220 reg32 |= (0x0a << 16);
Angel Pons1d4044a2021-03-27 19:11:51 +0100221 epbar_write32(EPVC1RCAP, reg32);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000222
Julius Wernercd49cce2019-03-05 16:53:33 -0800223 if (CONFIG(NORTHBRIDGE_INTEL_SUBTYPE_I945GC)) {
Angel Pons1d4044a2021-03-27 19:11:51 +0100224 if ((mchbar_read32(CLKCFG) & 7) == 0) { /* 1067MHz */
225 epbar_write32(EPVC1IST + 0, 0x01380138);
226 epbar_write32(EPVC1IST + 4, 0x01380138);
Elyes HAOUASf7acdf82016-10-31 18:55:04 +0100227 }
228 }
229
Angel Pons1d4044a2021-03-27 19:11:51 +0100230 if ((mchbar_read32(CLKCFG) & 7) == 1) { /* 533MHz */
231 epbar_write32(EPVC1IST + 0, 0x009c009c);
232 epbar_write32(EPVC1IST + 4, 0x009c009c);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000233 }
234
Angel Pons1d4044a2021-03-27 19:11:51 +0100235 if ((mchbar_read32(CLKCFG) & 7) == 2) { /* 800MHz */
236 epbar_write32(EPVC1IST + 0, 0x00f000f0);
237 epbar_write32(EPVC1IST + 4, 0x00f000f0);
Elyes HAOUASf7acdf82016-10-31 18:55:04 +0100238 }
239
Angel Pons1d4044a2021-03-27 19:11:51 +0100240 if ((mchbar_read32(CLKCFG) & 7) == 3) { /* 667MHz */
241 epbar_write32(EPVC1IST + 0, 0x00c000c0);
242 epbar_write32(EPVC1IST + 4, 0x00c000c0);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000243 }
244
245 /* Is internal graphics enabled? */
Angel Pons3580d812020-06-11 14:13:33 +0200246 if (pci_read_config8(HOST_BRIDGE, DEVEN) & (DEVEN_D2F0 | DEVEN_D2F1))
Angel Pons1d4044a2021-03-27 19:11:51 +0100247 mchbar_setbits32(MMARB1, 1 << 17);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000248
249 /* Assign Virtual Channel ID 1 to VC1 */
Angel Pons1d4044a2021-03-27 19:11:51 +0100250 reg32 = epbar_read32(EPVC1RCTL);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000251 reg32 &= ~(7 << 24);
252 reg32 |= (1 << 24);
Angel Pons1d4044a2021-03-27 19:11:51 +0100253 epbar_write32(EPVC1RCTL, reg32);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000254
Angel Pons1d4044a2021-03-27 19:11:51 +0100255 reg32 = epbar_read32(EPVC1RCTL);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000256 reg32 &= 0xffffff01;
257 reg32 |= (1 << 7);
Angel Pons1d4044a2021-03-27 19:11:51 +0100258 epbar_write32(EPVC1RCTL, reg32);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000259
Angel Pons1d4044a2021-03-27 19:11:51 +0100260 epbar_write32(PORTARB + 0x00, 0x01000001);
261 epbar_write32(PORTARB + 0x04, 0x00040000);
262 epbar_write32(PORTARB + 0x08, 0x00001000);
263 epbar_write32(PORTARB + 0x0c, 0x00000040);
264 epbar_write32(PORTARB + 0x10, 0x01000001);
265 epbar_write32(PORTARB + 0x14, 0x00040000);
266 epbar_write32(PORTARB + 0x18, 0x00001000);
267 epbar_write32(PORTARB + 0x1c, 0x00000040);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000268
Angel Pons1d4044a2021-03-27 19:11:51 +0100269 epbar_setbits32(EPVC1RCTL, 1 << 16);
270 epbar_setbits32(EPVC1RCTL, 1 << 16);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000271
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000272 printk(BIOS_DEBUG, "Loading port arbitration table ...");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000273 /* Loop until bit 0 becomes 0 */
274 timeout = 0x7fffff;
Angel Pons1d4044a2021-03-27 19:11:51 +0100275 while ((epbar_read16(EPVC1RSTS) & (1 << 0)) && --timeout)
Arthur Heymans70a8e342017-03-09 11:30:23 +0100276 ;
Stefan Reinauer278534d2008-10-29 04:51:07 +0000277 if (!timeout)
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000278 printk(BIOS_DEBUG, "timeout!\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000279 else
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000280 printk(BIOS_DEBUG, "ok\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000281
282 /* Now enable VC1 */
Angel Pons1d4044a2021-03-27 19:11:51 +0100283 epbar_setbits32(EPVC1RCTL, 1 << 31);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000284
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000285 printk(BIOS_DEBUG, "Wait for VC1 negotiation ...");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000286 /* Wait for VC1 negotiation pending */
287 timeout = 0x7fff;
Angel Pons1d4044a2021-03-27 19:11:51 +0100288 while ((epbar_read16(EPVC1RSTS) & (1 << 1)) && --timeout)
Arthur Heymans70a8e342017-03-09 11:30:23 +0100289 ;
Stefan Reinauer278534d2008-10-29 04:51:07 +0000290 if (!timeout)
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000291 printk(BIOS_DEBUG, "timeout!\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000292 else
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000293 printk(BIOS_DEBUG, "ok\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000294
295}
296
297static void ich7_setup_dmi_rcrb(void)
298{
299 u16 reg16;
Stefan Reinauer30140a52009-03-11 16:20:39 +0000300 u32 reg32;
Stefan Reinauer278534d2008-10-29 04:51:07 +0000301
Stefan Reinauer278534d2008-10-29 04:51:07 +0000302 reg16 = RCBA16(LCTL);
303 reg16 &= ~(3 << 0);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000304 reg16 |= 3;
Stefan Reinauer278534d2008-10-29 04:51:07 +0000305 RCBA16(LCTL) = reg16;
306
307 RCBA32(V0CTL) = 0x80000001;
308 RCBA32(V1CAP) = 0x03128010;
Stefan Reinauer278534d2008-10-29 04:51:07 +0000309
Stefan Reinauer30140a52009-03-11 16:20:39 +0000310 pci_write_config16(PCI_DEV(0, 0x1c, 0), 0x42, 0x0141);
311 pci_write_config16(PCI_DEV(0, 0x1c, 4), 0x42, 0x0141);
312 pci_write_config16(PCI_DEV(0, 0x1c, 5), 0x42, 0x0141);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000313
Stefan Reinauer30140a52009-03-11 16:20:39 +0000314 pci_write_config32(PCI_DEV(0, 0x1c, 4), 0x54, 0x00480ce0);
315 pci_write_config32(PCI_DEV(0, 0x1c, 5), 0x54, 0x00500ce0);
316
317 reg32 = RCBA32(V1CTL);
Arthur Heymans70a8e342017-03-09 11:30:23 +0100318 reg32 &= ~((0x7f << 1) | (7 << 17) | (7 << 24));
Stefan Reinauer30140a52009-03-11 16:20:39 +0000319 reg32 |= (0x40 << 1) | (4 << 17) | (1 << 24) | (1 << 31);
320 RCBA32(V1CTL) = reg32;
321
Stefan Reinauer30140a52009-03-11 16:20:39 +0000322 RCBA32(LCAP) |= (3 << 10);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000323}
324
325static void i945_setup_dmi_rcrb(void)
326{
327 u32 reg32;
328 u32 timeout;
Stefan Reinauerbf264e92010-05-14 19:09:20 +0000329 int activate_aspm = 1; /* hardcode ASPM for now */
Stefan Reinauer30140a52009-03-11 16:20:39 +0000330
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000331 printk(BIOS_DEBUG, "Setting up DMI RCRB\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000332
333 /* Virtual Channel 0 Configuration */
Angel Pons1d4044a2021-03-27 19:11:51 +0100334 reg32 = dmibar_read32(DMIVC0RCTL0);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000335 reg32 &= 0xffffff01;
Angel Pons1d4044a2021-03-27 19:11:51 +0100336 dmibar_write32(DMIVC0RCTL0, reg32);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000337
Angel Pons1d4044a2021-03-27 19:11:51 +0100338 reg32 = dmibar_read32(DMIPVCCAP1);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000339 reg32 &= ~(7 << 0);
340 reg32 |= 1;
Angel Pons1d4044a2021-03-27 19:11:51 +0100341 dmibar_write32(DMIPVCCAP1, reg32);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000342
Angel Pons1d4044a2021-03-27 19:11:51 +0100343 reg32 = dmibar_read32(DMIVC1RCTL);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000344 reg32 &= ~(7 << 24);
345 reg32 |= (1 << 24); /* NOTE: This ID must match ICH7 side */
Angel Pons1d4044a2021-03-27 19:11:51 +0100346 dmibar_write32(DMIVC1RCTL, reg32);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000347
Angel Pons1d4044a2021-03-27 19:11:51 +0100348 reg32 = dmibar_read32(DMIVC1RCTL);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000349 reg32 &= 0xffffff01;
350 reg32 |= (1 << 7);
Angel Pons1d4044a2021-03-27 19:11:51 +0100351 dmibar_write32(DMIVC1RCTL, reg32);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000352
353 /* Now enable VC1 */
Angel Pons1d4044a2021-03-27 19:11:51 +0100354 dmibar_setbits32(DMIVC1RCTL, 1 << 31);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000355
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000356 printk(BIOS_DEBUG, "Wait for VC1 negotiation ...");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000357 /* Wait for VC1 negotiation pending */
358 timeout = 0x7ffff;
Angel Pons1d4044a2021-03-27 19:11:51 +0100359 while ((dmibar_read16(DMIVC1RSTS) & (1 << 1)) && --timeout)
Arthur Heymans70a8e342017-03-09 11:30:23 +0100360 ;
Stefan Reinauer278534d2008-10-29 04:51:07 +0000361 if (!timeout)
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000362 printk(BIOS_DEBUG, "timeout!\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000363 else
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000364 printk(BIOS_DEBUG, "done..\n");
Angel Pons81c9c272020-07-07 23:19:38 +0200365
Stefan Reinauer278534d2008-10-29 04:51:07 +0000366 /* Enable Active State Power Management (ASPM) L0 state */
367
Angel Pons1d4044a2021-03-27 19:11:51 +0100368 reg32 = dmibar_read32(DMILCAP);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000369 reg32 &= ~(7 << 12);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000370 reg32 |= (2 << 12);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000371
372 reg32 &= ~(7 << 15);
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000373
Stefan Reinauer30140a52009-03-11 16:20:39 +0000374 reg32 |= (2 << 15);
Angel Pons1d4044a2021-03-27 19:11:51 +0100375 dmibar_write32(DMILCAP, reg32);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000376
Angel Pons1d4044a2021-03-27 19:11:51 +0100377 reg32 = dmibar_read32(DMICC);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000378 reg32 &= 0x00ffffff;
Stefan Reinauer278534d2008-10-29 04:51:07 +0000379 reg32 &= ~(3 << 0);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000380 reg32 |= (1 << 0);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000381 reg32 &= ~(3 << 20);
382 reg32 |= (1 << 20);
383
Angel Pons1d4044a2021-03-27 19:11:51 +0100384 dmibar_write32(DMICC, reg32);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000385
Arthur Heymans70a8e342017-03-09 11:30:23 +0100386 if (activate_aspm)
Angel Pons1d4044a2021-03-27 19:11:51 +0100387 dmibar_setbits32(DMILCTL, 3 << 0);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000388
389 /* Last but not least, some additional steps */
Angel Pons1d4044a2021-03-27 19:11:51 +0100390 reg32 = mchbar_read32(FSBSNPCTL);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000391 reg32 &= ~(0xff << 2);
392 reg32 |= (0xaa << 2);
Angel Pons1d4044a2021-03-27 19:11:51 +0100393 mchbar_write32(FSBSNPCTL, reg32);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000394
Angel Pons1d4044a2021-03-27 19:11:51 +0100395 dmibar_write32(0x2c, 0x86000040);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000396
Angel Pons1d4044a2021-03-27 19:11:51 +0100397 reg32 = dmibar_read32(0x204);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000398 reg32 &= ~0x3ff;
399#if 1
Elyes HAOUAS3dff32c2020-03-30 17:16:51 +0200400 reg32 |= 0x13f; /* for x4 DMI only */
Stefan Reinauer278534d2008-10-29 04:51:07 +0000401#else
Elyes HAOUAS3dff32c2020-03-30 17:16:51 +0200402 reg32 |= 0x1e4; /* for x2 DMI only */
Stefan Reinauer278534d2008-10-29 04:51:07 +0000403#endif
Angel Pons1d4044a2021-03-27 19:11:51 +0100404 dmibar_write32(0x204, reg32);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000405
Angel Pons3580d812020-06-11 14:13:33 +0200406 if (pci_read_config8(HOST_BRIDGE, DEVEN) & (DEVEN_D2F0 | DEVEN_D2F1)) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000407 printk(BIOS_DEBUG, "Internal graphics: enabled\n");
Angel Pons1d4044a2021-03-27 19:11:51 +0100408 dmibar_setbits32(0x200, 1 << 21);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000409 } else {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000410 printk(BIOS_DEBUG, "Internal graphics: disabled\n");
Angel Pons1d4044a2021-03-27 19:11:51 +0100411 dmibar_clrbits32(0x200, 1 << 21);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000412 }
413
Angel Pons1d4044a2021-03-27 19:11:51 +0100414 reg32 = dmibar_read32(0x204);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000415 reg32 &= ~((1 << 11) | (1 << 10));
Angel Pons1d4044a2021-03-27 19:11:51 +0100416 dmibar_write32(0x204, reg32);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000417
Angel Pons1d4044a2021-03-27 19:11:51 +0100418 reg32 = dmibar_read32(0x204);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000419 reg32 &= ~(0xff << 12);
420 reg32 |= (0x0d << 12);
Angel Pons1d4044a2021-03-27 19:11:51 +0100421 dmibar_write32(0x204, reg32);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000422
Angel Pons1d4044a2021-03-27 19:11:51 +0100423 dmibar_setbits32(DMICTL1, 3 << 24);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000424
Angel Pons1d4044a2021-03-27 19:11:51 +0100425 reg32 = dmibar_read32(0x200);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000426 reg32 &= ~(0x3 << 26);
427 reg32 |= (0x02 << 26);
Angel Pons1d4044a2021-03-27 19:11:51 +0100428 dmibar_write32(0x200, reg32);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000429
Angel Pons1d4044a2021-03-27 19:11:51 +0100430 dmibar_clrbits32(DMIDRCCFG, 1 << 31);
431 dmibar_setbits32(DMICTL2, 1 << 31);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000432
433 if (i945_silicon_revision() >= 3) {
Angel Pons1d4044a2021-03-27 19:11:51 +0100434 reg32 = dmibar_read32(0xec0);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000435 reg32 &= 0x0fffffff;
436 reg32 |= (2 << 28);
Angel Pons1d4044a2021-03-27 19:11:51 +0100437 dmibar_write32(0xec0, reg32);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000438
Angel Pons1d4044a2021-03-27 19:11:51 +0100439 reg32 = dmibar_read32(0xed4);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000440 reg32 &= 0x0fffffff;
441 reg32 |= (2 << 28);
Angel Pons1d4044a2021-03-27 19:11:51 +0100442 dmibar_write32(0xed4, reg32);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000443
Angel Pons1d4044a2021-03-27 19:11:51 +0100444 reg32 = dmibar_read32(0xee8);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000445 reg32 &= 0x0fffffff;
446 reg32 |= (2 << 28);
Angel Pons1d4044a2021-03-27 19:11:51 +0100447 dmibar_write32(0xee8, reg32);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000448
Angel Pons1d4044a2021-03-27 19:11:51 +0100449 reg32 = dmibar_read32(0xefc);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000450 reg32 &= 0x0fffffff;
451 reg32 |= (2 << 28);
Angel Pons1d4044a2021-03-27 19:11:51 +0100452 dmibar_write32(0xefc, reg32);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000453 }
454
455 /* wait for bit toggle to 0 */
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000456 printk(BIOS_DEBUG, "Waiting for DMI hardware...");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000457 timeout = 0x7fffff;
Angel Pons1d4044a2021-03-27 19:11:51 +0100458 while ((dmibar_read8(0x32) & (1 << 1)) && --timeout)
Arthur Heymans70a8e342017-03-09 11:30:23 +0100459 ;
Stefan Reinauer278534d2008-10-29 04:51:07 +0000460 if (!timeout)
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000461 printk(BIOS_DEBUG, "timeout!\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000462 else
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000463 printk(BIOS_DEBUG, "ok\n");
Stefan Reinauer30140a52009-03-11 16:20:39 +0000464
Stefan Reinauerbf264e92010-05-14 19:09:20 +0000465 /* Clear Error Status Bits! */
Angel Pons1d4044a2021-03-27 19:11:51 +0100466 dmibar_write32(0x1c4, 0xffffffff);
467 dmibar_write32(0x1d0, 0xffffffff);
468 dmibar_write32(0x228, 0xffffffff);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000469
Stefan Reinauerbf264e92010-05-14 19:09:20 +0000470 /* Program Read-Only Write-Once Registers */
Angel Pons1d4044a2021-03-27 19:11:51 +0100471 dmibar_setbits32(0x308, 0);
472 dmibar_setbits32(0x314, 0);
473 dmibar_setbits32(0x324, 0);
474 dmibar_setbits32(0x328, 0);
475 dmibar_setbits32(0x334, 0);
476 dmibar_setbits32(0x338, 0);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000477
Angel Pons1d4044a2021-03-27 19:11:51 +0100478 if (i945_silicon_revision() == 1 && (mchbar_read8(DFT_STRAP1) & (1 << 5))) {
479 if ((mchbar_read32(0x214) & 0xf) != 0x3) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000480 printk(BIOS_INFO, "DMI link requires A1 stepping workaround. Rebooting.\n");
Angel Pons1d4044a2021-03-27 19:11:51 +0100481 reg32 = dmibar_read32(0x224);
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000482 reg32 &= ~(7 << 0);
483 reg32 |= (3 << 0);
Angel Pons1d4044a2021-03-27 19:11:51 +0100484 dmibar_write32(0x224, reg32);
Elyes HAOUAS5db98712019-04-21 18:50:34 +0200485 system_reset();
Stefan Reinauer278534d2008-10-29 04:51:07 +0000486 }
487 }
488}
489
490static void i945_setup_pci_express_x16(void)
491{
492 u32 timeout;
493 u32 reg32;
494 u16 reg16;
Elyes HAOUAS961658f2020-04-06 09:42:21 +0200495 const pci_devfn_t p2peg = PCI_DEV(0, 0x01, 0);
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000496
Kyösti Mälkki2647b6f2019-09-29 07:03:55 +0300497 u8 tmp_secondary = 0x0a;
Elyes HAOUAS961658f2020-04-06 09:42:21 +0200498 const pci_devfn_t peg_plugin = PCI_DEV(tmp_secondary, 0, 0);
Kyösti Mälkki2647b6f2019-09-29 07:03:55 +0300499
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000500 printk(BIOS_DEBUG, "Enabling PCI Express x16 Link\n");
Stefan Reinauer30140a52009-03-11 16:20:39 +0000501
Angel Pons3580d812020-06-11 14:13:33 +0200502 pci_or_config16(HOST_BRIDGE, DEVEN, DEVEN_D1F0);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000503
Angel Ponse3c68d22020-06-08 12:09:03 +0200504 pci_and_config32(p2peg, PEGCC, ~(1 << 8));
Stefan Reinauer30140a52009-03-11 16:20:39 +0000505
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000506 /* We have no success with querying the usual PCIe registers
507 * for link setup success on the i945. Hence we assign a temporary
508 * PCI bus 0x0a and check whether we find a device on 0:a.0
509 */
510
Kyösti Mälkkiad787e12019-09-30 04:14:19 +0300511 /* Force PCIRST# */
512 pci_s_assert_secondary_reset(p2peg);
513 pci_s_deassert_secondary_reset(p2peg);
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000514
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300515 reg16 = pci_read_config16(p2peg, SLOTSTS);
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000516 printk(BIOS_DEBUG, "SLOTSTS: %04x\n", reg16);
Arthur Heymans70a8e342017-03-09 11:30:23 +0100517 if (!(reg16 & 0x48))
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000518 goto disable_pciexpress_x16_link;
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000519 reg16 |= (1 << 4) | (1 << 0);
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300520 pci_write_config16(p2peg, SLOTSTS, reg16);
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000521
Kyösti Mälkkiad787e12019-09-30 04:14:19 +0300522 pci_s_bridge_set_secondary(p2peg, tmp_secondary);
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000523
Angel Ponse3c68d22020-06-08 12:09:03 +0200524 pci_and_config32(p2peg, 0x224, ~(1 << 8));
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000525
Angel Pons1d4044a2021-03-27 19:11:51 +0100526 mchbar_clrbits16(UPMC1, 1 << 5 | 1 << 0);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000527
Martin Roth128c1042016-11-18 09:29:03 -0700528 /* Initialize PEG_CAP */
Angel Ponse3c68d22020-06-08 12:09:03 +0200529 pci_or_config16(p2peg, PEG_CAP, 1 << 8);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000530
531 /* Setup SLOTCAP */
Elyes HAOUAS3dff32c2020-03-30 17:16:51 +0200532 /* TODO: These values are mainboard dependent and should be set from devicetree.cb.
Stefan Reinauer30140a52009-03-11 16:20:39 +0000533 */
534 /* NOTE: SLOTCAP becomes RO after the first write! */
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300535 reg32 = pci_read_config32(p2peg, SLOTCAP);
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000536 reg32 &= 0x0007ffff;
537
538 reg32 &= 0xfffe007f;
539
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300540 pci_write_config32(p2peg, SLOTCAP, reg32);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000541
542 /* Wait for training to succeed */
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000543 printk(BIOS_DEBUG, "PCIe link training ...");
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000544 timeout = 0x7ffff;
Angel Ponse3c68d22020-06-08 12:09:03 +0200545 while ((((pci_read_config32(p2peg, PEGSTS) >> 16) & 3) != 3) && --timeout)
Arthur Heymans70a8e342017-03-09 11:30:23 +0100546 ;
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000547
Kyösti Mälkki2647b6f2019-09-29 07:03:55 +0300548 reg32 = pci_read_config32(peg_plugin, PCI_VENDOR_ID);
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000549 if (reg32 != 0x00000000 && reg32 != 0xffffffff) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000550 printk(BIOS_DEBUG, " Detected PCIe device %04x:%04x\n",
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000551 reg32 & 0xffff, reg32 >> 16);
552 } else {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000553 printk(BIOS_DEBUG, " timeout!\n");
Stefan Reinauer30140a52009-03-11 16:20:39 +0000554
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000555 printk(BIOS_DEBUG, "Restrain PCIe port to x1\n");
Stefan Reinauer30140a52009-03-11 16:20:39 +0000556
Angel Ponse3c68d22020-06-08 12:09:03 +0200557 pci_update_config32(p2peg, PEGSTS, ~(0xf << 1), 1);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000558
Kyösti Mälkkiad787e12019-09-30 04:14:19 +0300559 /* Force PCIRST# */
560 pci_s_assert_secondary_reset(p2peg);
561 pci_s_deassert_secondary_reset(p2peg);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000562
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000563 printk(BIOS_DEBUG, "PCIe link training ...");
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000564 timeout = 0x7ffff;
Angel Ponse3c68d22020-06-08 12:09:03 +0200565 while ((((pci_read_config32(p2peg, PEGSTS) >> 16) & 3) != 3) && --timeout)
Arthur Heymans70a8e342017-03-09 11:30:23 +0100566 ;
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000567
Kyösti Mälkki2647b6f2019-09-29 07:03:55 +0300568 reg32 = pci_read_config32(peg_plugin, PCI_VENDOR_ID);
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000569 if (reg32 != 0x00000000 && reg32 != 0xffffffff) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000570 printk(BIOS_DEBUG, " Detected PCIe x1 device %04x:%04x\n",
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000571 reg32 & 0xffff, reg32 >> 16);
572 } else {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000573 printk(BIOS_DEBUG, " timeout!\n");
574 printk(BIOS_DEBUG, "Disabling PCIe x16 port completely.\n");
Stefan Reinauer30140a52009-03-11 16:20:39 +0000575 goto disable_pciexpress_x16_link;
Stefan Reinauer30140a52009-03-11 16:20:39 +0000576 }
Stefan Reinauer30140a52009-03-11 16:20:39 +0000577 }
578
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300579 reg16 = pci_read_config16(p2peg, 0xb2);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000580 reg16 >>= 4;
581 reg16 &= 0x3f;
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000582 /* reg16 == 1 -> x1; reg16 == 16 -> x16 */
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000583 printk(BIOS_DEBUG, "PCIe x%d link training succeeded.\n", reg16);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000584
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300585 reg32 = pci_read_config32(p2peg, PEGTC);
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000586 reg32 &= 0xfffffc00; /* clear [9:0] */
Arthur Heymans70a8e342017-03-09 11:30:23 +0100587 if (reg16 == 1)
Stefan Reinauer30140a52009-03-11 16:20:39 +0000588 reg32 |= 0x32b;
589 // TODO
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300590 /* pci_write_config32(p2peg, PEGTC, reg32); */
Arthur Heymans70a8e342017-03-09 11:30:23 +0100591 else if (reg16 == 16)
Stefan Reinauer30140a52009-03-11 16:20:39 +0000592 reg32 |= 0x0f4;
593 // TODO
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300594 /* pci_write_config32(p2peg, PEGTC, reg32); */
Stefan Reinauer30140a52009-03-11 16:20:39 +0000595
Kyösti Mälkki2647b6f2019-09-29 07:03:55 +0300596 reg32 = (pci_read_config32(peg_plugin, 0x8) >> 8);
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000597 printk(BIOS_DEBUG, "PCIe device class: %06x\n", reg32);
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000598 if (reg32 == 0x030000) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000599 printk(BIOS_DEBUG, "PCIe device is VGA. Disabling IGD.\n");
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000600 reg16 = (1 << 1);
Angel Pons3580d812020-06-11 14:13:33 +0200601 pci_write_config16(HOST_BRIDGE, GGC, reg16);
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000602
Angel Pons3580d812020-06-11 14:13:33 +0200603 pci_and_config32(HOST_BRIDGE, DEVEN, ~(DEVEN_D2F0 | DEVEN_D2F1));
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000604 }
605
Angel Ponse3c68d22020-06-08 12:09:03 +0200606 /* Enable GPEs: PMEGPE, HPGPE, GENGPE */
607 pci_or_config32(p2peg, PEG_LC, (1 << 2) | (1 << 1) | (1 << 0));
Stefan Reinauer30140a52009-03-11 16:20:39 +0000608
609 /* Virtual Channel Configuration: Only VC0 on PCIe x16 */
Angel Ponse3c68d22020-06-08 12:09:03 +0200610 pci_and_config32(p2peg, VC0RCTL, ~0x000000fe);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000611
612 /* Extended VC count */
Angel Ponse3c68d22020-06-08 12:09:03 +0200613 pci_and_config32(p2peg, PVCCAP1, ~(7 << 0));
Stefan Reinauer30140a52009-03-11 16:20:39 +0000614
615 /* Active State Power Management ASPM */
616
617 /* TODO */
618
619 /* Clear error bits */
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300620 pci_write_config16(p2peg, PCISTS1, 0xffff);
621 pci_write_config16(p2peg, SSTS1, 0xffff);
622 pci_write_config16(p2peg, DSTS, 0xffff);
623 pci_write_config32(p2peg, UESTS, 0xffffffff);
624 pci_write_config32(p2peg, CESTS, 0xffffffff);
625 pci_write_config32(p2peg, 0x1f0, 0xffffffff);
626 pci_write_config32(p2peg, 0x228, 0xffffffff);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000627
628 /* Program R/WO registers */
Angel Ponse3c68d22020-06-08 12:09:03 +0200629 pci_update_config32(p2peg, 0x308, ~0, 0);
630 pci_update_config32(p2peg, 0x314, ~0, 0);
631 pci_update_config32(p2peg, 0x324, ~0, 0);
632 pci_update_config32(p2peg, 0x328, ~0, 0);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000633
Stefan Reinauer30140a52009-03-11 16:20:39 +0000634 /* Additional PCIe graphics setup */
Angel Ponse3c68d22020-06-08 12:09:03 +0200635 pci_or_config32(p2peg, 0xf0, 3 << 26);
636 pci_or_config32(p2peg, 0xf0, 3 << 24);
637 pci_or_config32(p2peg, 0xf0, 1 << 5);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000638
Angel Ponse3c68d22020-06-08 12:09:03 +0200639 pci_update_config32(p2peg, 0x200, ~(3 << 26), 2 << 26);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000640
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300641 reg32 = pci_read_config32(p2peg, 0xe80);
Arthur Heymans70a8e342017-03-09 11:30:23 +0100642 if (i945_silicon_revision() >= 2)
Stefan Reinauer30140a52009-03-11 16:20:39 +0000643 reg32 |= (1 << 12);
Arthur Heymans70a8e342017-03-09 11:30:23 +0100644 else
Stefan Reinauer30140a52009-03-11 16:20:39 +0000645 reg32 &= ~(1 << 12);
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300646 pci_write_config32(p2peg, 0xe80, reg32);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000647
Angel Ponse3c68d22020-06-08 12:09:03 +0200648 pci_and_config32(p2peg, 0xeb4, ~(1 << 31));
Stefan Reinauer30140a52009-03-11 16:20:39 +0000649
Angel Ponse3c68d22020-06-08 12:09:03 +0200650 pci_or_config32(p2peg, 0xfc, 1 << 31);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000651
652 if (i945_silicon_revision() >= 3) {
653 static const u32 reglist[] = {
Elyes HAOUAS3dff32c2020-03-30 17:16:51 +0200654 0xec0, 0xed4, 0xee8, 0xefc, 0xf10, 0xf24, 0xf38, 0xf4c,
655 0xf60, 0xf74, 0xf88, 0xf9c, 0xfb0, 0xfc4, 0xfd8, 0xfec
Stefan Reinauer30140a52009-03-11 16:20:39 +0000656 };
657
658 int i;
Angel Ponse3c68d22020-06-08 12:09:03 +0200659 for (i = 0; i < ARRAY_SIZE(reglist); i++)
660 pci_update_config32(p2peg, reglist[i], ~(0xf << 28), 2 << 28);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000661 }
662
Arthur Heymans70a8e342017-03-09 11:30:23 +0100663 if (i945_silicon_revision() <= 2) {
Stefan Reinauer30140a52009-03-11 16:20:39 +0000664 /* Set voltage specific parameters */
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300665 reg32 = pci_read_config32(p2peg, 0xe80);
Stefan Reinauerbf264e92010-05-14 19:09:20 +0000666 reg32 &= (0xf << 4); /* Default case 1.05V */
Angel Pons1d4044a2021-03-27 19:11:51 +0100667 if ((mchbar_read32(DFT_STRAP1) & (1 << 20)) == 0) { /* 1.50V */
Stefan Reinauer30140a52009-03-11 16:20:39 +0000668 reg32 |= (7 << 4);
669 }
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300670 pci_write_config32(p2peg, 0xe80, reg32);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000671 }
672
673 return;
674
675disable_pciexpress_x16_link:
Stefan Reinauer278534d2008-10-29 04:51:07 +0000676 /* For now we just disable the x16 link */
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000677 printk(BIOS_DEBUG, "Disabling PCI Express x16 Link\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000678
Angel Pons1d4044a2021-03-27 19:11:51 +0100679 mchbar_setbits16(UPMC1, 1 << 5 | 1 << 0);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000680
Kyösti Mälkkiad787e12019-09-30 04:14:19 +0300681 /* Toggle PCIRST# */
682 pci_s_assert_secondary_reset(p2peg);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000683
Angel Ponse3c68d22020-06-08 12:09:03 +0200684 pci_or_config32(p2peg, 0x224, 1 << 8);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000685
Kyösti Mälkkiad787e12019-09-30 04:14:19 +0300686 pci_s_deassert_secondary_reset(p2peg);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000687
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000688 printk(BIOS_DEBUG, "Wait for link to enter detect state... ");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000689 timeout = 0x7fffff;
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300690 for (reg32 = pci_read_config32(p2peg, PEGSTS);
Arthur Heymans70a8e342017-03-09 11:30:23 +0100691 (reg32 & 0x000f0000) && --timeout;)
692 ;
Stefan Reinauer278534d2008-10-29 04:51:07 +0000693 if (!timeout)
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000694 printk(BIOS_DEBUG, "timeout!\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000695 else
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000696 printk(BIOS_DEBUG, "ok\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000697
698 /* Finally: Disable the PCI config header */
Angel Pons3580d812020-06-11 14:13:33 +0200699 pci_and_config16(HOST_BRIDGE, DEVEN, ~DEVEN_D1F0);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000700}
701
702static void i945_setup_root_complex_topology(void)
703{
704 u32 reg32;
Elyes HAOUAS961658f2020-04-06 09:42:21 +0200705 const pci_devfn_t p2peg = PCI_DEV(0, 0x01, 0);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000706
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000707 printk(BIOS_DEBUG, "Setting up Root Complex Topology\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000708 /* Egress Port Root Topology */
Stefan Reinauer30140a52009-03-11 16:20:39 +0000709
Angel Pons1d4044a2021-03-27 19:11:51 +0100710 reg32 = epbar_read32(EPESD);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000711 reg32 &= 0xff00ffff;
712 reg32 |= (1 << 16);
Angel Pons1d4044a2021-03-27 19:11:51 +0100713 epbar_write32(EPESD, reg32);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000714
Angel Pons1d4044a2021-03-27 19:11:51 +0100715 epbar_setbits32(EPLE1D, 1 << 16 | 1 << 0);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000716
Angel Pons1d4044a2021-03-27 19:11:51 +0100717 epbar_write32(EPLE1A, CONFIG_FIXED_DMIBAR_MMIO_BASE);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000718
Angel Pons1d4044a2021-03-27 19:11:51 +0100719 epbar_setbits32(EPLE2D, 1 << 16 | 1 << 0);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000720
721 /* DMI Port Root Topology */
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000722
Angel Pons1d4044a2021-03-27 19:11:51 +0100723 reg32 = dmibar_read32(DMILE1D);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000724 reg32 &= 0x00ffffff;
Stefan Reinauer30140a52009-03-11 16:20:39 +0000725
Stefan Reinauer278534d2008-10-29 04:51:07 +0000726 reg32 &= 0xff00ffff;
727 reg32 |= (2 << 16);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000728
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000729 reg32 |= (1 << 0);
Angel Pons1d4044a2021-03-27 19:11:51 +0100730 dmibar_write32(DMILE1D, reg32);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000731
Angel Pons1d4044a2021-03-27 19:11:51 +0100732 dmibar_write32(DMILE1A, CONFIG_FIXED_RCBA_MMIO_BASE);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000733
Angel Pons1d4044a2021-03-27 19:11:51 +0100734 dmibar_setbits32(DMILE2D, 1 << 16 | 1 << 0);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000735
Angel Pons1d4044a2021-03-27 19:11:51 +0100736 dmibar_write32(DMILE2A, CONFIG_FIXED_EPBAR_MMIO_BASE);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000737
738 /* PCI Express x16 Port Root Topology */
Angel Pons3580d812020-06-11 14:13:33 +0200739 if (pci_read_config8(HOST_BRIDGE, DEVEN) & DEVEN_D1F0) {
Angel Pons4299cb42021-01-20 12:32:22 +0100740 pci_write_config32(p2peg, LE1A, CONFIG_FIXED_EPBAR_MMIO_BASE);
Angel Ponse3c68d22020-06-08 12:09:03 +0200741 pci_or_config32(p2peg, LE1D, 1 << 0);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000742 }
743}
744
745static void ich7_setup_root_complex_topology(void)
746{
Elyes HAOUASb217baa2019-01-18 15:32:39 +0100747 /* Write the R/WO registers */
748
749 RCBA32(ESD) |= (2 << 16);
750
751 RCBA32(ULD) |= (1 << 24) | (1 << 16);
752
Angel Pons4299cb42021-01-20 12:32:22 +0100753 RCBA32(ULBA) = CONFIG_FIXED_DMIBAR_MMIO_BASE;
Elyes HAOUASb217baa2019-01-18 15:32:39 +0100754 /* Write ESD.CID to TCID */
755 RCBA32(RP1D) |= (2 << 16);
756 RCBA32(RP2D) |= (2 << 16);
757 RCBA32(RP3D) |= (2 << 16);
758 RCBA32(RP4D) |= (2 << 16);
759 RCBA32(HDD) |= (2 << 16);
760 RCBA32(RP5D) |= (2 << 16);
761 RCBA32(RP6D) |= (2 << 16);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000762}
763
764static void ich7_setup_pci_express(void)
765{
Elyes HAOUAS13746072019-12-08 11:34:24 +0100766 /* Enable PCIe Root Port Clock Gate */
Stefan Reinauer30140a52009-03-11 16:20:39 +0000767 RCBA32(CG) |= (1 << 0);
768
Stefan Reinauerbf264e92010-05-14 19:09:20 +0000769 /* Initialize slot power limit for root ports */
Stefan Reinauer278534d2008-10-29 04:51:07 +0000770 pci_write_config32(PCI_DEV(0, 0x1c, 0), 0x54, 0x00000060);
771
772 pci_write_config32(PCI_DEV(0, 0x1c, 0), 0xd8, 0x00110000);
773}
774
Patrick Georgid0835952010-10-05 09:07:10 +0000775void i945_early_initialization(void)
Stefan Reinauer278534d2008-10-29 04:51:07 +0000776{
777 /* Print some chipset specific information */
Angel Pons3580d812020-06-11 14:13:33 +0200778 switch (pci_read_config32(HOST_BRIDGE, 0)) {
Stefan Reinauerbf264e92010-05-14 19:09:20 +0000779 case 0x27708086: /* 82945G/GZ/GC/P/PL */
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000780 i945_detect_chipset();
781 break;
Stefan Reinauerbf264e92010-05-14 19:09:20 +0000782 case 0x27a08086: /* 945GME/GSE */
783 case 0x27ac8086: /* 945GM/PM/GMS/GU/GT, 943/940GML */
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000784 i945m_detect_chipset();
785 break;
786 }
Stefan Reinauer278534d2008-10-29 04:51:07 +0000787
788 /* Setup all BARs required for early PCIe and raminit */
789 i945_setup_bars();
790
791 /* Change port80 to LPC */
792 RCBA32(GCS) &= (~0x04);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000793
794 /* Just do it that way */
795 RCBA32(0x2010) |= (1 << 10);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000796}
797
Vladimir Serbinenko55601882014-10-15 20:17:51 +0200798static void i945_prepare_resume(int s3resume)
799{
800 int cbmem_was_initted;
801
802 cbmem_was_initted = !cbmem_recovery(s3resume);
803
Kyösti Mälkki81830252016-06-25 11:40:00 +0300804 romstage_handoff_init(cbmem_was_initted && s3resume);
Vladimir Serbinenko55601882014-10-15 20:17:51 +0200805}
806
807void i945_late_initialization(int s3resume)
Stefan Reinauer278534d2008-10-29 04:51:07 +0000808{
809 i945_setup_egress_port();
810
811 ich7_setup_root_complex_topology();
812
813 ich7_setup_pci_express();
814
815 ich7_setup_dmi_rcrb();
816
817 i945_setup_dmi_rcrb();
818
Julius Wernercd49cce2019-03-05 16:53:33 -0800819 if (CONFIG(NORTHBRIDGE_INTEL_SUBTYPE_I945GM))
Arthur Heymans2f6b52e2017-03-02 23:51:09 +0100820 i945_setup_pci_express_x16();
Stefan Reinauer278534d2008-10-29 04:51:07 +0000821
822 i945_setup_root_complex_topology();
Vladimir Serbinenko55601882014-10-15 20:17:51 +0200823
Kyösti Mälkki346d2012019-03-23 10:07:16 +0200824 if (CONFIG(DEBUG_RAM_SETUP))
825 sdram_dump_mchbar_registers();
Vladimir Serbinenko55601882014-10-15 20:17:51 +0200826
Angel Pons1d4044a2021-03-27 19:11:51 +0100827 mchbar_write16(SSKPD, 0xcafe);
Vladimir Serbinenko55601882014-10-15 20:17:51 +0200828
829 i945_prepare_resume(s3resume);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000830}