blob: 1deca3eeba41edaead7ad194bb0d411ccb2bc80e [file] [log] [blame]
Stefan Reinauer278534d2008-10-29 04:51:07 +00001/*
2 * This file is part of the coreboot project.
3 *
Stefan Reinauerbf264e92010-05-14 19:09:20 +00004 * Copyright (C) 2007-2010 coresystems GmbH
Stefan Reinauer278534d2008-10-29 04:51:07 +00005 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
Stefan Reinauer278534d2008-10-29 04:51:07 +000014 */
15
Elyes HAOUAS5db98712019-04-21 18:50:34 +020016#include <cf9_reset.h>
Patrick Georgid0835952010-10-05 09:07:10 +000017#include <console/console.h>
18#include <arch/io.h>
Kyösti Mälkkiad787e12019-09-30 04:14:19 +030019#include <device/pci.h>
Kyösti Mälkkif1b58b72019-03-01 13:43:02 +020020#include <device/pci_ops.h>
Patrick Georgid0835952010-10-05 09:07:10 +000021#include <device/pci_def.h>
Vladimir Serbinenko55601882014-10-15 20:17:51 +020022#include <cbmem.h>
Kyösti Mälkki81830252016-06-25 11:40:00 +030023#include <romstage_handoff.h>
Kyösti Mälkkicbf95712020-01-05 08:05:45 +020024#include <option.h>
Elyes HAOUAS51401c32019-05-15 21:09:30 +020025#include <types.h>
26
27#include "i945.h"
Stefan Reinauer278534d2008-10-29 04:51:07 +000028
Patrick Georgid0835952010-10-05 09:07:10 +000029int i945_silicon_revision(void)
Stefan Reinauer278534d2008-10-29 04:51:07 +000030{
Stefan Reinauer779b3e32008-11-10 15:43:37 +000031 return pci_read_config8(PCI_DEV(0, 0x00, 0), PCI_CLASS_REVISION);
Stefan Reinauer278534d2008-10-29 04:51:07 +000032}
33
Stefan Reinauer71a3d962009-07-21 21:44:24 +000034static void i945m_detect_chipset(void)
Stefan Reinauer278534d2008-10-29 04:51:07 +000035{
36 u8 reg8;
37
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000038 printk(BIOS_INFO, "\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +000039 reg8 = (pci_read_config8(PCI_DEV(0, 0x00, 0), 0xe7) & 0x70) >> 4;
40 switch (reg8) {
41 case 1:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000042 printk(BIOS_INFO, "Mobile Intel(R) 82945GM/GME Express");
Stefan Reinauer278534d2008-10-29 04:51:07 +000043 break;
44 case 2:
Stefan Reinauer7981b942011-04-01 22:33:25 +020045 printk(BIOS_INFO, "Mobile Intel(R) 82945GMS/GU/GSE Express");
Stefan Reinauer278534d2008-10-29 04:51:07 +000046 break;
47 case 3:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000048 printk(BIOS_INFO, "Mobile Intel(R) 82945PM Express");
Stefan Reinauer278534d2008-10-29 04:51:07 +000049 break;
50 case 5:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000051 printk(BIOS_INFO, "Intel(R) 82945GT Express");
Stefan Reinauer278534d2008-10-29 04:51:07 +000052 break;
53 case 6:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000054 printk(BIOS_INFO, "Mobile Intel(R) 82943/82940GML Express");
Stefan Reinauer278534d2008-10-29 04:51:07 +000055 break;
56 default:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000057 printk(BIOS_INFO, "Unknown (%02x)", reg8); /* Others reserved. */
Stefan Reinauer278534d2008-10-29 04:51:07 +000058 }
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000059 printk(BIOS_INFO, " Chipset\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +000060
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000061 printk(BIOS_DEBUG, "(G)MCH capable of up to FSB ");
Stefan Reinauer278534d2008-10-29 04:51:07 +000062 reg8 = (pci_read_config8(PCI_DEV(0, 0x00, 0), 0xe3) & 0xe0) >> 5;
63 switch (reg8) {
64 case 2:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000065 printk(BIOS_DEBUG, "800 MHz"); /* According to 965 spec */
Stefan Reinauer278534d2008-10-29 04:51:07 +000066 break;
67 case 3:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000068 printk(BIOS_DEBUG, "667 MHz");
Stefan Reinauer278534d2008-10-29 04:51:07 +000069 break;
70 case 4:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000071 printk(BIOS_DEBUG, "533 MHz");
Stefan Reinauer278534d2008-10-29 04:51:07 +000072 break;
73 default:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000074 printk(BIOS_DEBUG, "N/A MHz (%02x)", reg8);
Stefan Reinauer278534d2008-10-29 04:51:07 +000075 }
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000076 printk(BIOS_DEBUG, "\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +000077
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000078 printk(BIOS_DEBUG, "(G)MCH capable of ");
Stefan Reinauer278534d2008-10-29 04:51:07 +000079 reg8 = (pci_read_config8(PCI_DEV(0, 0x00, 0), 0xe4) & 0x07);
80 switch (reg8) {
81 case 2:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000082 printk(BIOS_DEBUG, "up to DDR2-667");
Stefan Reinauer278534d2008-10-29 04:51:07 +000083 break;
84 case 3:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000085 printk(BIOS_DEBUG, "up to DDR2-533");
Stefan Reinauer278534d2008-10-29 04:51:07 +000086 break;
87 case 4:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000088 printk(BIOS_DEBUG, "DDR2-400");
Stefan Reinauer278534d2008-10-29 04:51:07 +000089 break;
90 default:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000091 printk(BIOS_INFO, "unknown max. RAM clock (%02x).", reg8); /* Others reserved. */
Stefan Reinauer278534d2008-10-29 04:51:07 +000092 }
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000093 printk(BIOS_DEBUG, "\n");
Elyes HAOUAS6372a0e2016-10-30 18:39:53 +010094
Julius Wernercd49cce2019-03-05 16:53:33 -080095 if (CONFIG(NORTHBRIDGE_INTEL_SUBTYPE_I945GC))
Elyes HAOUAS6372a0e2016-10-30 18:39:53 +010096 printk(BIOS_ERR, "coreboot is compiled for the wrong chipset.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +000097}
98
Stefan Reinauer71a3d962009-07-21 21:44:24 +000099static void i945_detect_chipset(void)
100{
101 u8 reg8;
102
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000103 printk(BIOS_INFO, "\nIntel(R) ");
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000104
105 reg8 = ((pci_read_config8(PCI_DEV(0, 0x00, 0), 0xe7) >> 5) & 4) | ((pci_read_config8(PCI_DEV(0, 0x00, 0), 0xe4) >> 4) & 3);
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000106 switch (reg8) {
107 case 0:
108 case 1:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000109 printk(BIOS_INFO, "82945G");
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000110 break;
111 case 2:
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000112 case 3:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000113 printk(BIOS_INFO, "82945P");
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000114 break;
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000115 case 4:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000116 printk(BIOS_INFO, "82945GC");
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000117 break;
118 case 5:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000119 printk(BIOS_INFO, "82945GZ");
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000120 break;
121 case 6:
122 case 7:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000123 printk(BIOS_INFO, "82945PL");
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000124 break;
125 default:
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000126 break;
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000127 }
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000128 printk(BIOS_INFO, " Chipset\n");
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000129
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000130 printk(BIOS_DEBUG, "(G)MCH capable of ");
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000131 reg8 = (pci_read_config8(PCI_DEV(0, 0x00, 0), 0xe4) & 0x07);
132 switch (reg8) {
133 case 0:
Elyes HAOUAS5db94502016-10-30 18:30:21 +0100134 case 2:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000135 printk(BIOS_DEBUG, "up to DDR2-667");
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000136 break;
137 case 3:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000138 printk(BIOS_DEBUG, "up to DDR2-533");
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000139 break;
140 default:
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000141 printk(BIOS_INFO, "unknown max. RAM clock (%02x).", reg8); /* Others reserved. */
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000142 }
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000143 printk(BIOS_DEBUG, "\n");
Elyes HAOUAS6372a0e2016-10-30 18:39:53 +0100144
Julius Wernercd49cce2019-03-05 16:53:33 -0800145 if (CONFIG(NORTHBRIDGE_INTEL_SUBTYPE_I945GM))
Elyes HAOUAS6372a0e2016-10-30 18:39:53 +0100146 printk(BIOS_ERR, "coreboot is compiled for the wrong chipset.\n");
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000147}
148
Stefan Reinauer278534d2008-10-29 04:51:07 +0000149static void i945_setup_bars(void)
150{
Arthur Heymans874a8f92016-05-19 16:06:09 +0200151 u8 reg8, gfxsize;
Stefan Reinauer278534d2008-10-29 04:51:07 +0000152
153 /* As of now, we don't have all the A0 workarounds implemented */
154 if (i945_silicon_revision() == 0)
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000155 printk(BIOS_INFO, "Warning: i945 silicon revision A0 might not work correctly.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000156
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000157 printk(BIOS_DEBUG, "Setting up static northbridge registers...");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000158 /* Set up all hardcoded northbridge BARs */
159 pci_write_config32(PCI_DEV(0, 0x00, 0), EPBAR, DEFAULT_EPBAR | 1);
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800160 pci_write_config32(PCI_DEV(0, 0x00, 0), MCHBAR, (uintptr_t)DEFAULT_MCHBAR | 1);
161 pci_write_config32(PCI_DEV(0, 0x00, 0), DMIBAR, (uintptr_t)DEFAULT_DMIBAR | 1);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000162 pci_write_config32(PCI_DEV(0, 0x00, 0), X60BAR, DEFAULT_X60BAR | 1);
163
Arthur Heymans874a8f92016-05-19 16:06:09 +0200164 /* vram size from cmos option */
165 if (get_option(&gfxsize, "gfx_uma_size") != CB_SUCCESS)
166 gfxsize = 2; /* 2 for 8MB */
167 /* make sure no invalid setting is used */
168 if (gfxsize > 6)
169 gfxsize = 2;
170 pci_write_config16(PCI_DEV(0, 0x00, 0), GGC, ((gfxsize + 1) << 4));
Arthur Heymansd522db02018-08-06 15:50:54 +0200171 /* TSEG 2M, This amount can easily be covered by SMRR MTRR's,
172 which requires to have TSEG_BASE aligned to TSEG_SIZE. */
Arthur Heymanse07df9d2018-04-09 22:03:21 +0200173 reg8 = pci_read_config8(PCI_DEV(0, 0, 0), ESMRAMC);
174 reg8 &= ~0x7;
Arthur Heymansd522db02018-08-06 15:50:54 +0200175 reg8 |= (1 << 1) | (1 << 0); /* 2M and TSEG_Enable */
Arthur Heymanse07df9d2018-04-09 22:03:21 +0200176 pci_write_config8(PCI_DEV(0, 0, 0), ESMRAMC, reg8);
177
Stefan Reinauer278534d2008-10-29 04:51:07 +0000178 /* Set C0000-FFFFF to access RAM on both reads and writes */
179 pci_write_config8(PCI_DEV(0, 0x00, 0), PAM0, 0x30);
180 pci_write_config8(PCI_DEV(0, 0x00, 0), PAM1, 0x33);
181 pci_write_config8(PCI_DEV(0, 0x00, 0), PAM2, 0x33);
182 pci_write_config8(PCI_DEV(0, 0x00, 0), PAM3, 0x33);
183 pci_write_config8(PCI_DEV(0, 0x00, 0), PAM4, 0x33);
184 pci_write_config8(PCI_DEV(0, 0x00, 0), PAM5, 0x33);
185 pci_write_config8(PCI_DEV(0, 0x00, 0), PAM6, 0x33);
186
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000187 printk(BIOS_DEBUG, " done.\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000188
189 /* Wait for MCH BAR to come up */
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000190 printk(BIOS_DEBUG, "Waiting for MCHBAR to come up...");
Elyes HAOUASa3ea1e42014-11-27 13:23:32 +0100191 if ((pci_read_config32(PCI_DEV(0, 0x00, 0), 0xe4) & 0x20000) == 0x00) { /* Bit 49 of CAPID0 */
Stefan Reinauer278534d2008-10-29 04:51:07 +0000192 do {
193 reg8 = *(volatile u8 *)0xfed40000;
194 } while (!(reg8 & 0x80));
195 }
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000196 printk(BIOS_DEBUG, "ok\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000197}
198
199static void i945_setup_egress_port(void)
200{
201 u32 reg32;
202 u32 timeout;
203
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000204 printk(BIOS_DEBUG, "Setting up Egress Port RCRB\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000205
206 /* Egress Port Virtual Channel 0 Configuration */
207
208 /* map only TC0 to VC0 */
209 reg32 = EPBAR32(EPVC0RCTL);
210 reg32 &= 0xffffff01;
211 EPBAR32(EPVC0RCTL) = reg32;
212
Stefan Reinauer278534d2008-10-29 04:51:07 +0000213 reg32 = EPBAR32(EPPVCCAP1);
214 reg32 &= ~(7 << 0);
215 reg32 |= 1;
216 EPBAR32(EPPVCCAP1) = reg32;
217
218 /* Egress Port Virtual Channel 1 Configuration */
219 reg32 = EPBAR32(0x2c);
220 reg32 &= 0xffffff00;
Julius Wernercd49cce2019-03-05 16:53:33 -0800221 if (CONFIG(NORTHBRIDGE_INTEL_SUBTYPE_I945GC)) {
Elyes HAOUASf7acdf82016-10-31 18:55:04 +0100222 if ((MCHBAR32(CLKCFG) & 7) == 0)
223 reg32 |= 0x1a; /* 1067MHz */
224 }
Stefan Reinauer278534d2008-10-29 04:51:07 +0000225 if ((MCHBAR32(CLKCFG) & 7) == 1)
226 reg32 |= 0x0d; /* 533MHz */
Elyes HAOUASf7acdf82016-10-31 18:55:04 +0100227 if ((MCHBAR32(CLKCFG) & 7) == 2)
228 reg32 |= 0x14; /* 800MHz */
Stefan Reinauer278534d2008-10-29 04:51:07 +0000229 if ((MCHBAR32(CLKCFG) & 7) == 3)
230 reg32 |= 0x10; /* 667MHz */
231 EPBAR32(0x2c) = reg32;
232
233 EPBAR32(EPVC1MTS) = 0x0a0a0a0a;
234
235 reg32 = EPBAR32(EPVC1RCAP);
236 reg32 &= ~(0x7f << 16);
237 reg32 |= (0x0a << 16);
238 EPBAR32(EPVC1RCAP) = reg32;
239
Julius Wernercd49cce2019-03-05 16:53:33 -0800240 if (CONFIG(NORTHBRIDGE_INTEL_SUBTYPE_I945GC)) {
Arthur Heymans70a8e342017-03-09 11:30:23 +0100241 if ((MCHBAR32(CLKCFG) & 7) == 0) { /* 1067MHz */
Elyes HAOUASf7acdf82016-10-31 18:55:04 +0100242 EPBAR32(EPVC1IST + 0) = 0x01380138;
243 EPBAR32(EPVC1IST + 4) = 0x01380138;
244 }
245 }
246
Stefan Reinauer278534d2008-10-29 04:51:07 +0000247 if ((MCHBAR32(CLKCFG) & 7) == 1) { /* 533MHz */
248 EPBAR32(EPVC1IST + 0) = 0x009c009c;
249 EPBAR32(EPVC1IST + 4) = 0x009c009c;
250 }
251
Elyes HAOUASf7acdf82016-10-31 18:55:04 +0100252 if ((MCHBAR32(CLKCFG) & 7) == 2) { /* 800MHz */
253 EPBAR32(EPVC1IST + 0) = 0x00f000f0;
254 EPBAR32(EPVC1IST + 4) = 0x00f000f0;
255 }
256
Stefan Reinauer278534d2008-10-29 04:51:07 +0000257 if ((MCHBAR32(CLKCFG) & 7) == 3) { /* 667MHz */
258 EPBAR32(EPVC1IST + 0) = 0x00c000c0;
259 EPBAR32(EPVC1IST + 4) = 0x00c000c0;
260 }
261
262 /* Is internal graphics enabled? */
Arthur Heymans70a8e342017-03-09 11:30:23 +0100263 if (pci_read_config8(PCI_DEV(0, 0x0, 0), DEVEN) & (DEVEN_D2F0 | DEVEN_D2F1))
Stefan Reinauer278534d2008-10-29 04:51:07 +0000264 MCHBAR32(MMARB1) |= (1 << 17);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000265
266 /* Assign Virtual Channel ID 1 to VC1 */
267 reg32 = EPBAR32(EPVC1RCTL);
268 reg32 &= ~(7 << 24);
269 reg32 |= (1 << 24);
270 EPBAR32(EPVC1RCTL) = reg32;
Stefan Reinauer30140a52009-03-11 16:20:39 +0000271
Stefan Reinauer278534d2008-10-29 04:51:07 +0000272 reg32 = EPBAR32(EPVC1RCTL);
273 reg32 &= 0xffffff01;
274 reg32 |= (1 << 7);
275 EPBAR32(EPVC1RCTL) = reg32;
Stefan Reinauer30140a52009-03-11 16:20:39 +0000276
Stefan Reinauer278534d2008-10-29 04:51:07 +0000277 EPBAR32(PORTARB + 0x00) = 0x01000001;
278 EPBAR32(PORTARB + 0x04) = 0x00040000;
279 EPBAR32(PORTARB + 0x08) = 0x00001000;
280 EPBAR32(PORTARB + 0x0c) = 0x00000040;
281 EPBAR32(PORTARB + 0x10) = 0x01000001;
282 EPBAR32(PORTARB + 0x14) = 0x00040000;
283 EPBAR32(PORTARB + 0x18) = 0x00001000;
284 EPBAR32(PORTARB + 0x1c) = 0x00000040;
Stefan Reinauer30140a52009-03-11 16:20:39 +0000285
Stefan Reinauer278534d2008-10-29 04:51:07 +0000286 EPBAR32(EPVC1RCTL) |= (1 << 16);
287 EPBAR32(EPVC1RCTL) |= (1 << 16);
288
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000289 printk(BIOS_DEBUG, "Loading port arbitration table ...");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000290 /* Loop until bit 0 becomes 0 */
291 timeout = 0x7fffff;
Arthur Heymans70a8e342017-03-09 11:30:23 +0100292 while ((EPBAR16(EPVC1RSTS) & 1) && --timeout)
293 ;
Stefan Reinauer278534d2008-10-29 04:51:07 +0000294 if (!timeout)
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000295 printk(BIOS_DEBUG, "timeout!\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000296 else
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000297 printk(BIOS_DEBUG, "ok\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000298
299 /* Now enable VC1 */
300 EPBAR32(EPVC1RCTL) |= (1 << 31);
301
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000302 printk(BIOS_DEBUG, "Wait for VC1 negotiation ...");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000303 /* Wait for VC1 negotiation pending */
304 timeout = 0x7fff;
Arthur Heymans70a8e342017-03-09 11:30:23 +0100305 while ((EPBAR16(EPVC1RSTS) & (1 << 1)) && --timeout)
306 ;
Stefan Reinauer278534d2008-10-29 04:51:07 +0000307 if (!timeout)
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000308 printk(BIOS_DEBUG, "timeout!\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000309 else
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000310 printk(BIOS_DEBUG, "ok\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000311
312}
313
314static void ich7_setup_dmi_rcrb(void)
315{
316 u16 reg16;
Stefan Reinauer30140a52009-03-11 16:20:39 +0000317 u32 reg32;
Stefan Reinauer278534d2008-10-29 04:51:07 +0000318
Stefan Reinauer278534d2008-10-29 04:51:07 +0000319 reg16 = RCBA16(LCTL);
320 reg16 &= ~(3 << 0);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000321 reg16 |= 3;
Stefan Reinauer278534d2008-10-29 04:51:07 +0000322 RCBA16(LCTL) = reg16;
323
324 RCBA32(V0CTL) = 0x80000001;
325 RCBA32(V1CAP) = 0x03128010;
Stefan Reinauer278534d2008-10-29 04:51:07 +0000326
Stefan Reinauer30140a52009-03-11 16:20:39 +0000327 pci_write_config16(PCI_DEV(0, 0x1c, 0), 0x42, 0x0141);
328 pci_write_config16(PCI_DEV(0, 0x1c, 4), 0x42, 0x0141);
329 pci_write_config16(PCI_DEV(0, 0x1c, 5), 0x42, 0x0141);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000330
Stefan Reinauer30140a52009-03-11 16:20:39 +0000331 pci_write_config32(PCI_DEV(0, 0x1c, 4), 0x54, 0x00480ce0);
332 pci_write_config32(PCI_DEV(0, 0x1c, 5), 0x54, 0x00500ce0);
333
334 reg32 = RCBA32(V1CTL);
Arthur Heymans70a8e342017-03-09 11:30:23 +0100335 reg32 &= ~((0x7f << 1) | (7 << 17) | (7 << 24));
Stefan Reinauer30140a52009-03-11 16:20:39 +0000336 reg32 |= (0x40 << 1) | (4 << 17) | (1 << 24) | (1 << 31);
337 RCBA32(V1CTL) = reg32;
338
Stefan Reinauer30140a52009-03-11 16:20:39 +0000339 RCBA32(LCAP) |= (3 << 10);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000340}
341
342static void i945_setup_dmi_rcrb(void)
343{
344 u32 reg32;
345 u32 timeout;
Stefan Reinauerbf264e92010-05-14 19:09:20 +0000346 int activate_aspm = 1; /* hardcode ASPM for now */
Stefan Reinauer30140a52009-03-11 16:20:39 +0000347
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000348 printk(BIOS_DEBUG, "Setting up DMI RCRB\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000349
350 /* Virtual Channel 0 Configuration */
351 reg32 = DMIBAR32(DMIVC0RCTL0);
352 reg32 &= 0xffffff01;
353 DMIBAR32(DMIVC0RCTL0) = reg32;
Stefan Reinauer30140a52009-03-11 16:20:39 +0000354
Stefan Reinauer278534d2008-10-29 04:51:07 +0000355 reg32 = DMIBAR32(DMIPVCCAP1);
356 reg32 &= ~(7 << 0);
357 reg32 |= 1;
358 DMIBAR32(DMIPVCCAP1) = reg32;
Stefan Reinauer30140a52009-03-11 16:20:39 +0000359
Stefan Reinauer278534d2008-10-29 04:51:07 +0000360 reg32 = DMIBAR32(DMIVC1RCTL);
361 reg32 &= ~(7 << 24);
362 reg32 |= (1 << 24); /* NOTE: This ID must match ICH7 side */
363 DMIBAR32(DMIVC1RCTL) = reg32;
Stefan Reinauer30140a52009-03-11 16:20:39 +0000364
Stefan Reinauer278534d2008-10-29 04:51:07 +0000365 reg32 = DMIBAR32(DMIVC1RCTL);
366 reg32 &= 0xffffff01;
367 reg32 |= (1 << 7);
368 DMIBAR32(DMIVC1RCTL) = reg32;
369
370 /* Now enable VC1 */
371 DMIBAR32(DMIVC1RCTL) |= (1 << 31);
372
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000373 printk(BIOS_DEBUG, "Wait for VC1 negotiation ...");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000374 /* Wait for VC1 negotiation pending */
375 timeout = 0x7ffff;
Arthur Heymans70a8e342017-03-09 11:30:23 +0100376 while ((DMIBAR16(DMIVC1RSTS) & (1 << 1)) && --timeout)
377 ;
Stefan Reinauer278534d2008-10-29 04:51:07 +0000378 if (!timeout)
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000379 printk(BIOS_DEBUG, "timeout!\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000380 else
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000381 printk(BIOS_DEBUG, "done..\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000382#if 1
383 /* Enable Active State Power Management (ASPM) L0 state */
384
385 reg32 = DMIBAR32(DMILCAP);
386 reg32 &= ~(7 << 12);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000387 reg32 |= (2 << 12);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000388
389 reg32 &= ~(7 << 15);
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000390
Stefan Reinauer30140a52009-03-11 16:20:39 +0000391 reg32 |= (2 << 15);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000392 DMIBAR32(DMILCAP) = reg32;
393
394 reg32 = DMIBAR32(DMICC);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000395 reg32 &= 0x00ffffff;
Stefan Reinauer278534d2008-10-29 04:51:07 +0000396 reg32 &= ~(3 << 0);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000397 reg32 |= (1 << 0);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000398 reg32 &= ~(3 << 20);
399 reg32 |= (1 << 20);
400
Stefan Reinauer278534d2008-10-29 04:51:07 +0000401 DMIBAR32(DMICC) = reg32;
402
Arthur Heymans70a8e342017-03-09 11:30:23 +0100403 if (activate_aspm)
Stefan Reinauer278534d2008-10-29 04:51:07 +0000404 DMIBAR32(DMILCTL) |= (3 << 0);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000405#endif
406
407 /* Last but not least, some additional steps */
408 reg32 = MCHBAR32(FSBSNPCTL);
409 reg32 &= ~(0xff << 2);
410 reg32 |= (0xaa << 2);
411 MCHBAR32(FSBSNPCTL) = reg32;
412
413 DMIBAR32(0x2c) = 0x86000040;
414
415 reg32 = DMIBAR32(0x204);
416 reg32 &= ~0x3ff;
417#if 1
418 reg32 |= 0x13f; /* for x4 DMI only */
419#else
420 reg32 |= 0x1e4; /* for x2 DMI only */
421#endif
422 DMIBAR32(0x204) = reg32;
423
Kyösti Mälkki3c3e34d2014-05-31 11:32:54 +0300424 if (pci_read_config8(PCI_DEV(0, 0x0, 0), DEVEN) & (DEVEN_D2F0 | DEVEN_D2F1)) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000425 printk(BIOS_DEBUG, "Internal graphics: enabled\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000426 DMIBAR32(0x200) |= (1 << 21);
427 } else {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000428 printk(BIOS_DEBUG, "Internal graphics: disabled\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000429 DMIBAR32(0x200) &= ~(1 << 21);
430 }
431
432 reg32 = DMIBAR32(0x204);
433 reg32 &= ~((1 << 11) | (1 << 10));
434 DMIBAR32(0x204) = reg32;
435
436 reg32 = DMIBAR32(0x204);
437 reg32 &= ~(0xff << 12);
438 reg32 |= (0x0d << 12);
439 DMIBAR32(0x204) = reg32;
440
441 DMIBAR32(DMICTL1) |= (3 << 24);
442
443 reg32 = DMIBAR32(0x200);
444 reg32 &= ~(0x3 << 26);
445 reg32 |= (0x02 << 26);
446 DMIBAR32(0x200) = reg32;
447
448 DMIBAR32(DMIDRCCFG) &= ~(1 << 31);
449 DMIBAR32(DMICTL2) |= (1 << 31);
450
451 if (i945_silicon_revision() >= 3) {
452 reg32 = DMIBAR32(0xec0);
453 reg32 &= 0x0fffffff;
454 reg32 |= (2 << 28);
455 DMIBAR32(0xec0) = reg32;
456
457 reg32 = DMIBAR32(0xed4);
458 reg32 &= 0x0fffffff;
459 reg32 |= (2 << 28);
460 DMIBAR32(0xed4) = reg32;
461
462 reg32 = DMIBAR32(0xee8);
463 reg32 &= 0x0fffffff;
464 reg32 |= (2 << 28);
465 DMIBAR32(0xee8) = reg32;
466
467 reg32 = DMIBAR32(0xefc);
468 reg32 &= 0x0fffffff;
469 reg32 |= (2 << 28);
470 DMIBAR32(0xefc) = reg32;
471 }
472
473 /* wait for bit toggle to 0 */
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000474 printk(BIOS_DEBUG, "Waiting for DMI hardware...");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000475 timeout = 0x7fffff;
Arthur Heymans70a8e342017-03-09 11:30:23 +0100476 while ((DMIBAR8(0x32) & (1 << 1)) && --timeout)
477 ;
Stefan Reinauer278534d2008-10-29 04:51:07 +0000478 if (!timeout)
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000479 printk(BIOS_DEBUG, "timeout!\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000480 else
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000481 printk(BIOS_DEBUG, "ok\n");
Stefan Reinauer30140a52009-03-11 16:20:39 +0000482
Stefan Reinauerbf264e92010-05-14 19:09:20 +0000483 /* Clear Error Status Bits! */
Stefan Reinauer278534d2008-10-29 04:51:07 +0000484 DMIBAR32(0x1c4) = 0xffffffff;
485 DMIBAR32(0x1d0) = 0xffffffff;
486 DMIBAR32(0x228) = 0xffffffff;
Stefan Reinauer30140a52009-03-11 16:20:39 +0000487
Stefan Reinauerbf264e92010-05-14 19:09:20 +0000488 /* Program Read-Only Write-Once Registers */
Stefan Reinauer278534d2008-10-29 04:51:07 +0000489 DMIBAR32(0x308) = DMIBAR32(0x308);
490 DMIBAR32(0x314) = DMIBAR32(0x314);
491 DMIBAR32(0x324) = DMIBAR32(0x324);
492 DMIBAR32(0x328) = DMIBAR32(0x328);
Elyes HAOUASd3fa7fa52019-01-24 11:47:27 +0100493 DMIBAR32(0x334) = DMIBAR32(0x334);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000494 DMIBAR32(0x338) = DMIBAR32(0x338);
495
Patrick Georgia341a772014-09-29 19:51:21 +0200496 if (i945_silicon_revision() == 1 && (MCHBAR8(DFT_STRAP1) & (1 << 5))) {
Stefan Reinauer30140a52009-03-11 16:20:39 +0000497 if ((MCHBAR32(0x214) & 0xf) != 0x3) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000498 printk(BIOS_INFO, "DMI link requires A1 stepping workaround. Rebooting.\n");
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000499 reg32 = DMIBAR32(0x224);
500 reg32 &= ~(7 << 0);
501 reg32 |= (3 << 0);
502 DMIBAR32(0x224) = reg32;
Elyes HAOUAS5db98712019-04-21 18:50:34 +0200503 system_reset();
Stefan Reinauer278534d2008-10-29 04:51:07 +0000504 }
505 }
506}
507
508static void i945_setup_pci_express_x16(void)
509{
510 u32 timeout;
511 u32 reg32;
512 u16 reg16;
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300513 pci_devfn_t p2peg = PCI_DEV(0, 0x01, 0);
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000514
Kyösti Mälkki2647b6f2019-09-29 07:03:55 +0300515 u8 tmp_secondary = 0x0a;
516 pci_devfn_t peg_plugin = PCI_DEV(tmp_secondary, 0, 0);
517
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000518 printk(BIOS_DEBUG, "Enabling PCI Express x16 Link\n");
Stefan Reinauer30140a52009-03-11 16:20:39 +0000519
520 reg16 = pci_read_config16(PCI_DEV(0, 0x00, 0), DEVEN);
521 reg16 |= DEVEN_D1F0;
522 pci_write_config16(PCI_DEV(0, 0x00, 0), DEVEN, reg16);
523
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300524 reg32 = pci_read_config32(p2peg, PEGCC);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000525 reg32 &= ~(1 << 8);
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300526 pci_write_config32(p2peg, PEGCC, reg32);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000527
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000528 /* We have no success with querying the usual PCIe registers
529 * for link setup success on the i945. Hence we assign a temporary
530 * PCI bus 0x0a and check whether we find a device on 0:a.0
531 */
532
Kyösti Mälkkiad787e12019-09-30 04:14:19 +0300533 /* Force PCIRST# */
534 pci_s_assert_secondary_reset(p2peg);
535 pci_s_deassert_secondary_reset(p2peg);
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000536
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300537 reg16 = pci_read_config16(p2peg, SLOTSTS);
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000538 printk(BIOS_DEBUG, "SLOTSTS: %04x\n", reg16);
Arthur Heymans70a8e342017-03-09 11:30:23 +0100539 if (!(reg16 & 0x48))
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000540 goto disable_pciexpress_x16_link;
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000541 reg16 |= (1 << 4) | (1 << 0);
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300542 pci_write_config16(p2peg, SLOTSTS, reg16);
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000543
Kyösti Mälkkiad787e12019-09-30 04:14:19 +0300544 pci_s_bridge_set_secondary(p2peg, tmp_secondary);
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000545
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300546 reg32 = pci_read_config32(p2peg, 0x224);
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000547 reg32 &= ~(1 << 8);
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300548 pci_write_config32(p2peg, 0x224, reg32);
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000549
Arthur Heymans70a8e342017-03-09 11:30:23 +0100550 MCHBAR16(UPMC1) &= ~((1 << 5) | (1 << 0));
Stefan Reinauer30140a52009-03-11 16:20:39 +0000551
Martin Roth128c1042016-11-18 09:29:03 -0700552 /* Initialize PEG_CAP */
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300553 reg16 = pci_read_config16(p2peg, PEG_CAP);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000554 reg16 |= (1 << 8);
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300555 pci_write_config16(p2peg, PEG_CAP, reg16);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000556
557 /* Setup SLOTCAP */
558 /* TODO: These values are mainboard dependent and should
Uwe Hermann607614d2010-11-18 20:12:13 +0000559 * be set from devicetree.cb.
Stefan Reinauer30140a52009-03-11 16:20:39 +0000560 */
561 /* NOTE: SLOTCAP becomes RO after the first write! */
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300562 reg32 = pci_read_config32(p2peg, SLOTCAP);
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000563 reg32 &= 0x0007ffff;
564
565 reg32 &= 0xfffe007f;
566
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300567 pci_write_config32(p2peg, SLOTCAP, reg32);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000568
569 /* Wait for training to succeed */
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000570 printk(BIOS_DEBUG, "PCIe link training ...");
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000571 timeout = 0x7ffff;
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300572 while ((((pci_read_config32(p2peg, PEGSTS) >> 16) & 3) != 3)
Arthur Heymans70a8e342017-03-09 11:30:23 +0100573 && --timeout)
574 ;
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000575
Kyösti Mälkki2647b6f2019-09-29 07:03:55 +0300576 reg32 = pci_read_config32(peg_plugin, PCI_VENDOR_ID);
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000577 if (reg32 != 0x00000000 && reg32 != 0xffffffff) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000578 printk(BIOS_DEBUG, " Detected PCIe device %04x:%04x\n",
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000579 reg32 & 0xffff, reg32 >> 16);
580 } else {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000581 printk(BIOS_DEBUG, " timeout!\n");
Stefan Reinauer30140a52009-03-11 16:20:39 +0000582
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000583 printk(BIOS_DEBUG, "Restrain PCIe port to x1\n");
Stefan Reinauer30140a52009-03-11 16:20:39 +0000584
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300585 reg32 = pci_read_config32(p2peg, PEGSTS);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000586 reg32 &= ~(0xf << 1);
Arthur Heymans70a8e342017-03-09 11:30:23 +0100587 reg32 |= 1;
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300588 pci_write_config32(p2peg, PEGSTS, reg32);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000589
Kyösti Mälkkiad787e12019-09-30 04:14:19 +0300590 /* Force PCIRST# */
591 pci_s_assert_secondary_reset(p2peg);
592 pci_s_deassert_secondary_reset(p2peg);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000593
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000594 printk(BIOS_DEBUG, "PCIe link training ...");
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000595 timeout = 0x7ffff;
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300596 while ((((pci_read_config32(p2peg, PEGSTS) >> 16) & 3) != 3)
Arthur Heymans70a8e342017-03-09 11:30:23 +0100597 && --timeout)
598 ;
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000599
Kyösti Mälkki2647b6f2019-09-29 07:03:55 +0300600 reg32 = pci_read_config32(peg_plugin, PCI_VENDOR_ID);
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000601 if (reg32 != 0x00000000 && reg32 != 0xffffffff) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000602 printk(BIOS_DEBUG, " Detected PCIe x1 device %04x:%04x\n",
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000603 reg32 & 0xffff, reg32 >> 16);
604 } else {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000605 printk(BIOS_DEBUG, " timeout!\n");
606 printk(BIOS_DEBUG, "Disabling PCIe x16 port completely.\n");
Stefan Reinauer30140a52009-03-11 16:20:39 +0000607 goto disable_pciexpress_x16_link;
Stefan Reinauer30140a52009-03-11 16:20:39 +0000608 }
Stefan Reinauer30140a52009-03-11 16:20:39 +0000609 }
610
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300611 reg16 = pci_read_config16(p2peg, 0xb2);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000612 reg16 >>= 4;
613 reg16 &= 0x3f;
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000614 /* reg16 == 1 -> x1; reg16 == 16 -> x16 */
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000615 printk(BIOS_DEBUG, "PCIe x%d link training succeeded.\n", reg16);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000616
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300617 reg32 = pci_read_config32(p2peg, PEGTC);
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000618 reg32 &= 0xfffffc00; /* clear [9:0] */
Arthur Heymans70a8e342017-03-09 11:30:23 +0100619 if (reg16 == 1)
Stefan Reinauer30140a52009-03-11 16:20:39 +0000620 reg32 |= 0x32b;
621 // TODO
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300622 /* pci_write_config32(p2peg, PEGTC, reg32); */
Arthur Heymans70a8e342017-03-09 11:30:23 +0100623 else if (reg16 == 16)
Stefan Reinauer30140a52009-03-11 16:20:39 +0000624 reg32 |= 0x0f4;
625 // TODO
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300626 /* pci_write_config32(p2peg, PEGTC, reg32); */
Stefan Reinauer30140a52009-03-11 16:20:39 +0000627
Kyösti Mälkki2647b6f2019-09-29 07:03:55 +0300628 reg32 = (pci_read_config32(peg_plugin, 0x8) >> 8);
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000629 printk(BIOS_DEBUG, "PCIe device class: %06x\n", reg32);
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000630 if (reg32 == 0x030000) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000631 printk(BIOS_DEBUG, "PCIe device is VGA. Disabling IGD.\n");
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000632 reg16 = (1 << 1);
Elyes HAOUASef20ecc2018-10-04 13:50:14 +0200633 pci_write_config16(PCI_DEV(0, 0x0, 0), GGC, reg16);
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000634
Kyösti Mälkki3c3e34d2014-05-31 11:32:54 +0300635 reg32 = pci_read_config32(PCI_DEV(0, 0x0, 0), DEVEN);
636 reg32 &= ~(DEVEN_D2F0 | DEVEN_D2F1);
637 pci_write_config32(PCI_DEV(0, 0x0, 0), DEVEN, reg32);
Stefan Reinaueraca6ec62009-10-26 17:12:21 +0000638 }
639
Stefan Reinauer30140a52009-03-11 16:20:39 +0000640 /* Enable GPEs */
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300641 reg32 = pci_read_config32(p2peg, PEG_LC);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000642 reg32 |= (1 << 2) | (1 << 1) | (1 << 0); /* PMEGPE, HPGPE, GENGPE */
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300643 pci_write_config32(p2peg, PEG_LC, reg32);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000644
645 /* Virtual Channel Configuration: Only VC0 on PCIe x16 */
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300646 reg32 = pci_read_config32(p2peg, VC0RCTL);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000647 reg32 &= 0xffffff01;
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300648 pci_write_config32(p2peg, VC0RCTL, reg32);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000649
650 /* Extended VC count */
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300651 reg32 = pci_read_config32(p2peg, PVCCAP1);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000652 reg32 &= ~(7 << 0);
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300653 pci_write_config32(p2peg, PVCCAP1, reg32);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000654
655 /* Active State Power Management ASPM */
656
657 /* TODO */
658
659 /* Clear error bits */
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300660 pci_write_config16(p2peg, PCISTS1, 0xffff);
661 pci_write_config16(p2peg, SSTS1, 0xffff);
662 pci_write_config16(p2peg, DSTS, 0xffff);
663 pci_write_config32(p2peg, UESTS, 0xffffffff);
664 pci_write_config32(p2peg, CESTS, 0xffffffff);
665 pci_write_config32(p2peg, 0x1f0, 0xffffffff);
666 pci_write_config32(p2peg, 0x228, 0xffffffff);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000667
668 /* Program R/WO registers */
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300669 reg32 = pci_read_config32(p2peg, 0x308);
670 pci_write_config32(p2peg, 0x308, reg32);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000671
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300672 reg32 = pci_read_config32(p2peg, 0x314);
673 pci_write_config32(p2peg, 0x314, reg32);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000674
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300675 reg32 = pci_read_config32(p2peg, 0x324);
676 pci_write_config32(p2peg, 0x324, reg32);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000677
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300678 reg32 = pci_read_config32(p2peg, 0x328);
679 pci_write_config32(p2peg, 0x328, reg32);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000680
Stefan Reinauer30140a52009-03-11 16:20:39 +0000681 /* Additional PCIe graphics setup */
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300682 reg32 = pci_read_config32(p2peg, 0xf0);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000683 reg32 |= (3 << 26);
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300684 pci_write_config32(p2peg, 0xf0, reg32);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000685
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300686 reg32 = pci_read_config32(p2peg, 0xf0);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000687 reg32 |= (3 << 24);
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300688 pci_write_config32(p2peg, 0xf0, reg32);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000689
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300690 reg32 = pci_read_config32(p2peg, 0xf0);
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000691 reg32 |= (1 << 5);
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300692 pci_write_config32(p2peg, 0xf0, reg32);
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000693
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300694 reg32 = pci_read_config32(p2peg, 0x200);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000695 reg32 &= ~(3 << 26);
696 reg32 |= (2 << 26);
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300697 pci_write_config32(p2peg, 0x200, reg32);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000698
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300699 reg32 = pci_read_config32(p2peg, 0xe80);
Arthur Heymans70a8e342017-03-09 11:30:23 +0100700 if (i945_silicon_revision() >= 2)
Stefan Reinauer30140a52009-03-11 16:20:39 +0000701 reg32 |= (1 << 12);
Arthur Heymans70a8e342017-03-09 11:30:23 +0100702 else
Stefan Reinauer30140a52009-03-11 16:20:39 +0000703 reg32 &= ~(1 << 12);
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300704 pci_write_config32(p2peg, 0xe80, reg32);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000705
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300706 reg32 = pci_read_config32(p2peg, 0xeb4);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000707 reg32 &= ~(1 << 31);
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300708 pci_write_config32(p2peg, 0xeb4, reg32);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000709
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300710 reg32 = pci_read_config32(p2peg, 0xfc);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000711 reg32 |= (1 << 31);
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300712 pci_write_config32(p2peg, 0xfc, reg32);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000713
714 if (i945_silicon_revision() >= 3) {
715 static const u32 reglist[] = {
716 0xec0, 0xed4, 0xee8, 0xefc, 0xf10, 0xf24,
717 0xf38, 0xf4c, 0xf60, 0xf74, 0xf88, 0xf9c,
718 0xfb0, 0xfc4, 0xfd8, 0xfec
719 };
720
721 int i;
Elyes HAOUAS0a15fe92016-09-17 19:12:27 +0200722 for (i = 0; i < ARRAY_SIZE(reglist); i++) {
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300723 reg32 = pci_read_config32(p2peg, reglist[i]);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000724 reg32 &= 0x0fffffff;
725 reg32 |= (2 << 28);
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300726 pci_write_config32(p2peg, reglist[i], reg32);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000727 }
728 }
729
Arthur Heymans70a8e342017-03-09 11:30:23 +0100730 if (i945_silicon_revision() <= 2) {
Stefan Reinauer30140a52009-03-11 16:20:39 +0000731 /* Set voltage specific parameters */
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300732 reg32 = pci_read_config32(p2peg, 0xe80);
Stefan Reinauerbf264e92010-05-14 19:09:20 +0000733 reg32 &= (0xf << 4); /* Default case 1.05V */
Patrick Georgi3cb86de2014-09-29 20:42:33 +0200734 if ((MCHBAR32(DFT_STRAP1) & (1 << 20)) == 0) { /* 1.50V */
Stefan Reinauer30140a52009-03-11 16:20:39 +0000735 reg32 |= (7 << 4);
736 }
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300737 pci_write_config32(p2peg, 0xe80, reg32);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000738 }
739
740 return;
741
742disable_pciexpress_x16_link:
Stefan Reinauer278534d2008-10-29 04:51:07 +0000743 /* For now we just disable the x16 link */
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000744 printk(BIOS_DEBUG, "Disabling PCI Express x16 Link\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000745
746 MCHBAR16(UPMC1) |= (1 << 5) | (1 << 0);
747
Kyösti Mälkkiad787e12019-09-30 04:14:19 +0300748 /* Toggle PCIRST# */
749 pci_s_assert_secondary_reset(p2peg);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000750
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300751 reg32 = pci_read_config32(p2peg, 0x224);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000752 reg32 |= (1 << 8);
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300753 pci_write_config32(p2peg, 0x224, reg32);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000754
Kyösti Mälkkiad787e12019-09-30 04:14:19 +0300755 pci_s_deassert_secondary_reset(p2peg);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000756
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000757 printk(BIOS_DEBUG, "Wait for link to enter detect state... ");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000758 timeout = 0x7fffff;
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300759 for (reg32 = pci_read_config32(p2peg, PEGSTS);
Arthur Heymans70a8e342017-03-09 11:30:23 +0100760 (reg32 & 0x000f0000) && --timeout;)
761 ;
Stefan Reinauer278534d2008-10-29 04:51:07 +0000762 if (!timeout)
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000763 printk(BIOS_DEBUG, "timeout!\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000764 else
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000765 printk(BIOS_DEBUG, "ok\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000766
767 /* Finally: Disable the PCI config header */
768 reg16 = pci_read_config16(PCI_DEV(0, 0x00, 0), DEVEN);
769 reg16 &= ~DEVEN_D1F0;
770 pci_write_config16(PCI_DEV(0, 0x00, 0), DEVEN, reg16);
771}
772
773static void i945_setup_root_complex_topology(void)
774{
775 u32 reg32;
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300776 pci_devfn_t p2peg = PCI_DEV(0, 0x01, 0);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000777
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000778 printk(BIOS_DEBUG, "Setting up Root Complex Topology\n");
Stefan Reinauer278534d2008-10-29 04:51:07 +0000779 /* Egress Port Root Topology */
Stefan Reinauer30140a52009-03-11 16:20:39 +0000780
Stefan Reinauer278534d2008-10-29 04:51:07 +0000781 reg32 = EPBAR32(EPESD);
782 reg32 &= 0xff00ffff;
783 reg32 |= (1 << 16);
784 EPBAR32(EPESD) = reg32;
Stefan Reinauer30140a52009-03-11 16:20:39 +0000785
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000786 EPBAR32(EPLE1D) |= (1 << 16) | (1 << 0);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000787
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800788 EPBAR32(EPLE1A) = (uintptr_t)DEFAULT_DMIBAR;
Stefan Reinauer30140a52009-03-11 16:20:39 +0000789
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000790 EPBAR32(EPLE2D) |= (1 << 16) | (1 << 0);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000791
792 /* DMI Port Root Topology */
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000793
Stefan Reinauer278534d2008-10-29 04:51:07 +0000794 reg32 = DMIBAR32(DMILE1D);
795 reg32 &= 0x00ffffff;
Stefan Reinauer30140a52009-03-11 16:20:39 +0000796
Stefan Reinauer278534d2008-10-29 04:51:07 +0000797 reg32 &= 0xff00ffff;
798 reg32 |= (2 << 16);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000799
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000800 reg32 |= (1 << 0);
801 DMIBAR32(DMILE1D) = reg32;
Stefan Reinauer30140a52009-03-11 16:20:39 +0000802
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800803 DMIBAR32(DMILE1A) = (uintptr_t)DEFAULT_RCBA;
Stefan Reinauer30140a52009-03-11 16:20:39 +0000804
Stefan Reinauer24b4df52010-01-17 13:47:35 +0000805 DMIBAR32(DMILE2D) |= (1 << 16) | (1 << 0);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000806
807 DMIBAR32(DMILE2A) = DEFAULT_EPBAR;
Stefan Reinauer278534d2008-10-29 04:51:07 +0000808
809 /* PCI Express x16 Port Root Topology */
810 if (pci_read_config8(PCI_DEV(0, 0x00, 0), DEVEN) & DEVEN_D1F0) {
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300811 pci_write_config32(p2peg, LE1A, DEFAULT_EPBAR);
812 reg32 = pci_read_config32(p2peg, LE1D);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000813 reg32 |= (1 << 0);
Kyösti Mälkki444d2af2019-09-29 07:03:31 +0300814 pci_write_config32(p2peg, LE1D, reg32);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000815 }
816}
817
818static void ich7_setup_root_complex_topology(void)
819{
Elyes HAOUASb217baa2019-01-18 15:32:39 +0100820 /* Write the R/WO registers */
821
822 RCBA32(ESD) |= (2 << 16);
823
824 RCBA32(ULD) |= (1 << 24) | (1 << 16);
825
826 RCBA32(ULBA) = (uintptr_t)DEFAULT_DMIBAR;
827 /* Write ESD.CID to TCID */
828 RCBA32(RP1D) |= (2 << 16);
829 RCBA32(RP2D) |= (2 << 16);
830 RCBA32(RP3D) |= (2 << 16);
831 RCBA32(RP4D) |= (2 << 16);
832 RCBA32(HDD) |= (2 << 16);
833 RCBA32(RP5D) |= (2 << 16);
834 RCBA32(RP6D) |= (2 << 16);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000835}
836
837static void ich7_setup_pci_express(void)
838{
Elyes HAOUAS13746072019-12-08 11:34:24 +0100839 /* Enable PCIe Root Port Clock Gate */
Stefan Reinauer30140a52009-03-11 16:20:39 +0000840 RCBA32(CG) |= (1 << 0);
841
Stefan Reinauerbf264e92010-05-14 19:09:20 +0000842 /* Initialize slot power limit for root ports */
Stefan Reinauer278534d2008-10-29 04:51:07 +0000843 pci_write_config32(PCI_DEV(0, 0x1c, 0), 0x54, 0x00000060);
Stefan Reinauerbf264e92010-05-14 19:09:20 +0000844#if 0
845 pci_write_config32(PCI_DEV(0, 0x1c, 4), 0x54, 0x00480ce0);
846 pci_write_config32(PCI_DEV(0, 0x1c, 5), 0x54, 0x00500ce0);
847#endif
Stefan Reinauer278534d2008-10-29 04:51:07 +0000848
849 pci_write_config32(PCI_DEV(0, 0x1c, 0), 0xd8, 0x00110000);
850}
851
Patrick Georgid0835952010-10-05 09:07:10 +0000852void i945_early_initialization(void)
Stefan Reinauer278534d2008-10-29 04:51:07 +0000853{
854 /* Print some chipset specific information */
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000855 switch (pci_read_config32(PCI_DEV(0, 0x00, 0), 0)) {
Stefan Reinauerbf264e92010-05-14 19:09:20 +0000856 case 0x27708086: /* 82945G/GZ/GC/P/PL */
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000857 i945_detect_chipset();
858 break;
Stefan Reinauerbf264e92010-05-14 19:09:20 +0000859 case 0x27a08086: /* 945GME/GSE */
860 case 0x27ac8086: /* 945GM/PM/GMS/GU/GT, 943/940GML */
Stefan Reinauer71a3d962009-07-21 21:44:24 +0000861 i945m_detect_chipset();
862 break;
863 }
Stefan Reinauer278534d2008-10-29 04:51:07 +0000864
865 /* Setup all BARs required for early PCIe and raminit */
866 i945_setup_bars();
867
868 /* Change port80 to LPC */
869 RCBA32(GCS) &= (~0x04);
Stefan Reinauer30140a52009-03-11 16:20:39 +0000870
871 /* Just do it that way */
872 RCBA32(0x2010) |= (1 << 10);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000873}
874
Vladimir Serbinenko55601882014-10-15 20:17:51 +0200875static void i945_prepare_resume(int s3resume)
876{
877 int cbmem_was_initted;
878
879 cbmem_was_initted = !cbmem_recovery(s3resume);
880
Kyösti Mälkki81830252016-06-25 11:40:00 +0300881 romstage_handoff_init(cbmem_was_initted && s3resume);
Vladimir Serbinenko55601882014-10-15 20:17:51 +0200882}
883
884void i945_late_initialization(int s3resume)
Stefan Reinauer278534d2008-10-29 04:51:07 +0000885{
886 i945_setup_egress_port();
887
888 ich7_setup_root_complex_topology();
889
890 ich7_setup_pci_express();
891
892 ich7_setup_dmi_rcrb();
893
894 i945_setup_dmi_rcrb();
895
Julius Wernercd49cce2019-03-05 16:53:33 -0800896 if (CONFIG(NORTHBRIDGE_INTEL_SUBTYPE_I945GM))
Arthur Heymans2f6b52e2017-03-02 23:51:09 +0100897 i945_setup_pci_express_x16();
Stefan Reinauer278534d2008-10-29 04:51:07 +0000898
899 i945_setup_root_complex_topology();
Vladimir Serbinenko55601882014-10-15 20:17:51 +0200900
Kyösti Mälkki346d2012019-03-23 10:07:16 +0200901 if (CONFIG(DEBUG_RAM_SETUP))
902 sdram_dump_mchbar_registers();
Vladimir Serbinenko55601882014-10-15 20:17:51 +0200903
904 MCHBAR16(SSKPD) = 0xCAFE;
905
906 i945_prepare_resume(s3resume);
Stefan Reinauer278534d2008-10-29 04:51:07 +0000907}