blob: 6a4d75cac2fbd79eef1e470b6450477be51ae8f3 [file] [log] [blame]
Aaron Durbin76c37002012-10-30 09:03:43 -05001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2008-2009 coresystems GmbH
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; version 2 of
9 * the License.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21#include <console/console.h>
22#include <device/device.h>
23#include <device/pci.h>
24#include <device/pciexp.h>
25#include <device/pci_ids.h>
26#include "pch.h"
27
Aaron Durbin1c4289d2013-06-21 14:06:11 -050028static void pcie_update_cfg8(device_t dev, int reg, u8 mask, u8 or);
29static void pcie_update_cfg(device_t dev, int reg, u32 mask, u32 or);
30
Aaron Durbinc0254e62013-06-20 01:20:30 -050031/* LynxPoint-LP has 6 root ports while non-LP has 8. */
32#define MAX_NUM_ROOT_PORTS 8
33#define H_NUM_ROOT_PORTS MAX_NUM_ROOT_PORTS
34#define LP_NUM_ROOT_PORTS (MAX_NUM_ROOT_PORTS - 2)
35
36struct root_port_config {
37 /* RPFN is a write-once register so keep a copy until it is written */
38 u32 orig_rpfn;
39 u32 new_rpfn;
40 u32 pin_ownership;
41 u32 strpfusecfg1;
42 u32 strpfusecfg2;
43 u32 strpfusecfg3;
Stefan Reinauerab365af2013-12-03 12:13:26 -080044 u32 b0d28f0_32c;
45 u32 b0d28f4_32c;
46 u32 b0d28f5_32c;
Aaron Durbinc0254e62013-06-20 01:20:30 -050047 int coalesce;
48 int gbe_port;
49 int num_ports;
50 device_t ports[MAX_NUM_ROOT_PORTS];
51};
52
53static struct root_port_config rpc;
54
55static inline int max_root_ports(void)
Aaron Durbin60f82082013-06-19 13:28:04 -050056{
Aaron Durbinc0254e62013-06-20 01:20:30 -050057 if (pch_is_lp())
58 return LP_NUM_ROOT_PORTS;
59 else
60 return H_NUM_ROOT_PORTS;
Aaron Durbin60f82082013-06-19 13:28:04 -050061}
62
Aaron Durbinc0254e62013-06-20 01:20:30 -050063static inline int root_port_is_first(device_t dev)
Aaron Durbin60f82082013-06-19 13:28:04 -050064{
Aaron Durbinc0254e62013-06-20 01:20:30 -050065 return PCI_FUNC(dev->path.pci.devfn) == 0;
66}
Aaron Durbin60f82082013-06-19 13:28:04 -050067
Aaron Durbinc0254e62013-06-20 01:20:30 -050068static inline int root_port_is_last(device_t dev)
69{
70 return PCI_FUNC(dev->path.pci.devfn) == (rpc.num_ports - 1);
71}
Aaron Durbin60f82082013-06-19 13:28:04 -050072
Aaron Durbinc0254e62013-06-20 01:20:30 -050073/* Root ports are numbered 1..N in the documentation. */
74static inline int root_port_number(device_t dev)
75{
76 return PCI_FUNC(dev->path.pci.devfn) + 1;
77}
Aaron Durbin60f82082013-06-19 13:28:04 -050078
Aaron Durbinc0254e62013-06-20 01:20:30 -050079static void root_port_config_update_gbe_port(void)
80{
81 /* Is the Gbe Port enabled? */
82 if (!((rpc.strpfusecfg1 >> 19) & 1))
83 return;
84
85 if (pch_is_lp()) {
86 switch ((rpc.strpfusecfg1 >> 16) & 0x7) {
87 case 0:
88 rpc.gbe_port = 3;
89 break;
90 case 1:
91 rpc.gbe_port = 4;
92 break;
93 case 2:
94 case 3:
95 case 4:
96 case 5:
97 /* Lanes 0-4 of Root Port 5. */
98 rpc.gbe_port = 5;
99 break;
100 default:
101 printk(BIOS_DEBUG, "Invalid GbE Port Selection.\n");
102 }
103 } else {
104 /* Non-LP has 1:1 mapping with root ports. */
105 rpc.gbe_port = ((rpc.strpfusecfg1 >> 16) & 0x7) + 1;
106 }
107}
108
109static void root_port_init_config(device_t dev)
110{
111 int rp;
112
113 if (root_port_is_first(dev)) {
114 rpc.orig_rpfn = RCBA32(RPFN);
115 rpc.new_rpfn = rpc.orig_rpfn;
116 rpc.num_ports = max_root_ports();
117 rpc.gbe_port = -1;
118
119 rpc.pin_ownership = pci_read_config32(dev, 0x410);
120 root_port_config_update_gbe_port();
121
122 if (dev->chip_info != NULL) {
123 struct southbridge_intel_lynxpoint_config *config;
124
125 config = dev->chip_info;
126 rpc.coalesce = config->pcie_port_coalesce;
127 }
128 }
129
130 rp = root_port_number(dev);
131 if (rp > rpc.num_ports) {
132 printk(BIOS_ERR, "Found Root Port %d, expecting %d\n",
133 rp, rpc.num_ports);
134 return;
135 }
136
137 /* Read the fuse configuration and pin ownership. */
138 switch (rp) {
139 case 1:
140 rpc.strpfusecfg1 = pci_read_config32(dev, 0xfc);
Stefan Reinauerab365af2013-12-03 12:13:26 -0800141 rpc.b0d28f0_32c = pci_read_config32(dev, 0x32c);
Aaron Durbinc0254e62013-06-20 01:20:30 -0500142 break;
143 case 5:
144 rpc.strpfusecfg2 = pci_read_config32(dev, 0xfc);
Stefan Reinauerab365af2013-12-03 12:13:26 -0800145 rpc.b0d28f4_32c = pci_read_config32(dev, 0x32c);
Aaron Durbinc0254e62013-06-20 01:20:30 -0500146 break;
147 case 6:
Stefan Reinauerab365af2013-12-03 12:13:26 -0800148 rpc.b0d28f5_32c = pci_read_config32(dev, 0x32c);
Aaron Durbinc0254e62013-06-20 01:20:30 -0500149 rpc.strpfusecfg3 = pci_read_config32(dev, 0xfc);
150 break;
151 default:
152 break;
153 }
154
155 /* Cache pci device. */
156 rpc.ports[rp - 1] = dev;
Aaron Durbin60f82082013-06-19 13:28:04 -0500157}
158
159/* Update devicetree with new Root Port function number assignment */
Aaron Durbinc0254e62013-06-20 01:20:30 -0500160static void pch_pcie_device_set_func(int index, int pci_func)
Aaron Durbin60f82082013-06-19 13:28:04 -0500161{
162 device_t dev;
Aaron Durbinc0254e62013-06-20 01:20:30 -0500163 unsigned new_devfn;
Aaron Durbin60f82082013-06-19 13:28:04 -0500164
Aaron Durbinc0254e62013-06-20 01:20:30 -0500165 dev = rpc.ports[index];
Aaron Durbin60f82082013-06-19 13:28:04 -0500166
Aaron Durbinc0254e62013-06-20 01:20:30 -0500167 /* Set the new PCI function field for this Root Port. */
168 rpc.new_rpfn &= ~RPFN_FNMASK(index);
169 rpc.new_rpfn |= RPFN_FNSET(index, pci_func);
Aaron Durbin60f82082013-06-19 13:28:04 -0500170
Aaron Durbinc0254e62013-06-20 01:20:30 -0500171 /* Determine the new devfn for this port */
172 new_devfn = PCI_DEVFN(PCH_PCIE_DEV_SLOT, pci_func);
Aaron Durbin60f82082013-06-19 13:28:04 -0500173
Aaron Durbinc0254e62013-06-20 01:20:30 -0500174 if (dev->path.pci.devfn != new_devfn) {
175 printk(BIOS_DEBUG,
176 "PCH: PCIe map %02x.%1x -> %02x.%1x\n",
177 PCI_SLOT(dev->path.pci.devfn),
178 PCI_FUNC(dev->path.pci.devfn),
179 PCI_SLOT(new_devfn), PCI_FUNC(new_devfn));
Aaron Durbin60f82082013-06-19 13:28:04 -0500180
Aaron Durbinc0254e62013-06-20 01:20:30 -0500181 dev->path.pci.devfn = new_devfn;
Aaron Durbin60f82082013-06-19 13:28:04 -0500182 }
183}
184
Aaron Durbin1c4289d2013-06-21 14:06:11 -0500185static void pcie_enable_clock_gating(void)
186{
187 int i;
188 int is_lp;
189 int enabled_ports;
190
191 is_lp = pch_is_lp();
192 enabled_ports = 0;
193
194 for (i = 0; i < rpc.num_ports; i++) {
195 device_t dev;
196 int rp;
197
198 dev = rpc.ports[i];
199 rp = root_port_number(dev);
200
201 if (!dev->enabled) {
202 /* Configure shared resource clock gating. */
203 if (rp == 1 || rp == 5 || (rp == 6 && is_lp))
204 pcie_update_cfg8(dev, 0xe1, 0xc3, 0x3c);
205
206 if (!is_lp) {
207 if (rp == 1 && !rpc.ports[1]->enabled &&
208 !rpc.ports[2]->enabled &&
209 !rpc.ports[3]->enabled) {
210 pcie_update_cfg8(dev, 0xe2, ~1, 1);
211 pcie_update_cfg8(dev, 0xe1, 0x7f, 0x80);
212 }
213 if (rp == 5 && !rpc.ports[5]->enabled &&
214 !rpc.ports[6]->enabled &&
215 !rpc.ports[7]->enabled) {
216 pcie_update_cfg8(dev, 0xe2, ~1, 1);
217 pcie_update_cfg8(dev, 0xe1, 0x7f, 0x80);
218 }
219 continue;
220 }
221
222 pcie_update_cfg8(dev, 0xe2, ~(3 << 4), (3 << 4));
223 pcie_update_cfg(dev, 0x420, ~(1 << 31), (1 << 31));
224
225 /* Per-Port CLKREQ# handling. */
226 if (is_lp && gpio_is_native(18 + rp - 1))
227 pcie_update_cfg(dev, 0x420, ~0, (3 << 29));
228
229 /* Enable static clock gating. */
230 if (rp == 1 && !rpc.ports[1]->enabled &&
231 !rpc.ports[2]->enabled && !rpc.ports[3]->enabled) {
232 pcie_update_cfg8(dev, 0xe2, ~1, 1);
233 pcie_update_cfg8(dev, 0xe1, 0x7f, 0x80);
234 } else if (rp == 5 || rp == 6) {
235 pcie_update_cfg8(dev, 0xe2, ~1, 1);
236 pcie_update_cfg8(dev, 0xe1, 0x7f, 0x80);
237 }
238 continue;
239 }
240
241 enabled_ports++;
242
243 /* Enable dynamic clock gating. */
244 pcie_update_cfg8(dev, 0xe1, 0xfc, 0x03);
245
246 if (is_lp) {
247 pcie_update_cfg8(dev, 0xe2, ~(1 << 6), (1 << 6));
248 pcie_update_cfg8(dev, 0xe8, ~(3 << 2), (2 << 2));
249 }
250
251 /* Update PECR1 register. */
252 pcie_update_cfg8(dev, 0xe8, ~0, 1);
253
254 pcie_update_cfg8(dev, 0x324, ~(1 << 5), (1 < 5));
255
256 /* Per-Port CLKREQ# handling. */
257 if (is_lp && gpio_is_native(18 + rp - 1))
258 pcie_update_cfg(dev, 0x420, ~0, (3 << 29));
259
260 /* Configure shared resource clock gating. */
261 if (rp == 1 || rp == 5 || (rp == 6 && is_lp))
262 pcie_update_cfg8(dev, 0xe1, 0xc3, 0x3c);
263 }
264
265 if (!enabled_ports && is_lp)
266 pcie_update_cfg8(rpc.ports[0], 0xe1, ~(1 << 6), (1 << 6));
267}
268
Aaron Durbinc0254e62013-06-20 01:20:30 -0500269static void root_port_commit_config(void)
Aaron Durbin60f82082013-06-19 13:28:04 -0500270{
Aaron Durbinc0254e62013-06-20 01:20:30 -0500271 int i;
Aaron Durbin60f82082013-06-19 13:28:04 -0500272
Aaron Durbinc0254e62013-06-20 01:20:30 -0500273 /* If the first root port is disabled the coalesce ports. */
274 if (!rpc.ports[0]->enabled)
275 rpc.coalesce = 1;
Aaron Durbin60f82082013-06-19 13:28:04 -0500276
Aaron Durbin1c4289d2013-06-21 14:06:11 -0500277 /* Perform clock gating configuration. */
278 pcie_enable_clock_gating();
279
Aaron Durbinc0254e62013-06-20 01:20:30 -0500280 for (i = 0; i < rpc.num_ports; i++) {
281 device_t dev;
282 u32 reg32;
Aaron Durbin60f82082013-06-19 13:28:04 -0500283
Aaron Durbinc0254e62013-06-20 01:20:30 -0500284 dev = rpc.ports[i];
Aaron Durbin60f82082013-06-19 13:28:04 -0500285
Aaron Durbinc0254e62013-06-20 01:20:30 -0500286 if (dev == NULL) {
287 printk(BIOS_ERR, "Root Port %d device is NULL?\n", i+1);
288 continue;
Aaron Durbin60f82082013-06-19 13:28:04 -0500289 }
290
Aaron Durbinc0254e62013-06-20 01:20:30 -0500291 if (dev->enabled)
292 continue;
293
294 printk(BIOS_DEBUG, "%s: Disabling device\n", dev_path(dev));
295
Aaron Durbin60f82082013-06-19 13:28:04 -0500296 /* Ensure memory, io, and bus master are all disabled */
297 reg32 = pci_read_config32(dev, PCI_COMMAND);
298 reg32 &= ~(PCI_COMMAND_MASTER |
299 PCI_COMMAND_MEMORY | PCI_COMMAND_IO);
300 pci_write_config32(dev, PCI_COMMAND, reg32);
301
Aaron Durbin60f82082013-06-19 13:28:04 -0500302 /* Disable this device if possible */
303 pch_disable_devfn(dev);
Aaron Durbin60f82082013-06-19 13:28:04 -0500304 }
305
Aaron Durbinc0254e62013-06-20 01:20:30 -0500306 if (rpc.coalesce) {
307 int current_func;
Aaron Durbin60f82082013-06-19 13:28:04 -0500308
Aaron Durbinc0254e62013-06-20 01:20:30 -0500309 /* For all Root Ports N enabled ports get assigned the lower
310 * PCI function number. The disabled ones get upper PCI
311 * function numbers. */
312 current_func = 0;
313 for (i = 0; i < rpc.num_ports; i++) {
314 if (!rpc.ports[i]->enabled)
315 continue;
316 pch_pcie_device_set_func(i, current_func);
317 current_func++;
318 }
319
320 /* Allocate the disabled devices' PCI function number. */
321 for (i = 0; i < rpc.num_ports; i++) {
322 if (rpc.ports[i]->enabled)
323 continue;
324 pch_pcie_device_set_func(i, current_func);
325 current_func++;
326 }
327 }
328
329 printk(BIOS_SPEW, "PCH: RPFN 0x%08x -> 0x%08x\n",
330 rpc.orig_rpfn, rpc.new_rpfn);
331 RCBA32(RPFN) = rpc.new_rpfn;
332}
333
334static void root_port_mark_disable(device_t dev)
335{
336 /* Mark device as disabled. */
337 dev->enabled = 0;
338 /* Mark device to be hidden. */
339 rpc.new_rpfn |= RPFN_HIDE(PCI_FUNC(dev->path.pci.devfn));
340}
341
342static void root_port_check_disable(device_t dev)
343{
344 int rp;
345 int is_lp;
346
347 /* Device already disabled. */
348 if (!dev->enabled) {
349 root_port_mark_disable(dev);
350 return;
351 }
352
353 rp = root_port_number(dev);
354
355 /* Is the GbE port mapped to this Root Port? */
356 if (rp == rpc.gbe_port) {
357 root_port_mark_disable(dev);
358 return;
359 }
360
361 is_lp = pch_is_lp();
362
363 /* Check Root Port Configuration. */
364 switch (rp) {
365 case 2:
366 /* Root Port 2 is disabled for all lane configurations
367 * but config 00b (4x1 links). */
368 if ((rpc.strpfusecfg1 >> 14) & 0x3) {
369 root_port_mark_disable(dev);
370 return;
371 }
372 break;
373 case 3:
374 /* Root Port 3 is disabled in config 11b (1x4 links). */
375 if (((rpc.strpfusecfg1 >> 14) & 0x3) == 0x3) {
376 root_port_mark_disable(dev);
377 return;
378 }
379 break;
380 case 4:
381 /* Root Port 4 is disabled in configs 11b (1x4 links)
382 * and 10b (2x2 links). */
383 if ((rpc.strpfusecfg1 >> 14) & 0x2) {
384 root_port_mark_disable(dev);
385 return;
386 }
387 break;
388 case 6:
389 if (is_lp)
390 break;
391 /* Root Port 6 is disabled for all lane configurations
392 * but config 00b (4x1 links). */
393 if ((rpc.strpfusecfg2 >> 14) & 0x3) {
394 root_port_mark_disable(dev);
395 return;
396 }
397 break;
398 case 7:
399 if (is_lp)
400 break;
401 /* Root Port 3 is disabled in config 11b (1x4 links). */
402 if (((rpc.strpfusecfg2 >> 14) & 0x3) == 0x3) {
403 root_port_mark_disable(dev);
404 return;
405 }
406 break;
407 case 8:
408 if (is_lp)
409 break;
410 /* Root Port 8 is disabled in configs 11b (1x4 links)
411 * and 10b (2x2 links). */
412 if ((rpc.strpfusecfg2 >> 14) & 0x2) {
413 root_port_mark_disable(dev);
414 return;
415 }
416 break;
417 }
418
419 /* Check Pin Ownership. */
420 if (is_lp) {
421 switch (rp) {
422 case 1:
423 /* Bit 0 is Root Port 1 ownership. */
424 if ((rpc.pin_ownership & 0x1) == 0) {
425 root_port_mark_disable(dev);
426 return;
427 }
428 break;
429 case 2:
430 /* Bit 2 is Root Port 2 ownership. */
431 if ((rpc.pin_ownership & 0x4) == 0) {
432 root_port_mark_disable(dev);
433 return;
434 }
435 break;
436 case 6:
437 /* Bits 7:4 are Root Port 6 pin-lane ownership. */
438 if ((rpc.pin_ownership & 0xf0) == 0) {
439 root_port_mark_disable(dev);
440 return;
441 }
442 break;
443 }
444 } else {
445 switch (rp) {
446 case 1:
447 /* Bits 4 and 0 are Root Port 1 ownership. */
448 if ((rpc.pin_ownership & 0x11) == 0) {
449 root_port_mark_disable(dev);
450 return;
451 }
452 break;
453 case 2:
454 /* Bits 5 and 2 are Root Port 2 ownership. */
455 if ((rpc.pin_ownership & 0x24) == 0) {
456 root_port_mark_disable(dev);
457 return;
458 }
459 break;
460 }
Aaron Durbin60f82082013-06-19 13:28:04 -0500461 }
462}
463
Stefan Reinauerab365af2013-12-03 12:13:26 -0800464static void pcie_update_cfg8(device_t dev, int reg, u8 mask, u8 or)
Aaron Durbin76c37002012-10-30 09:03:43 -0500465{
Aaron Durbin76c37002012-10-30 09:03:43 -0500466 u8 reg8;
467
Stefan Reinauerab365af2013-12-03 12:13:26 -0800468 reg8 = pci_read_config8(dev, reg);
469 reg8 &= mask;
470 reg8 |= or;
471 pci_write_config8(dev, reg, reg8);
Aaron Durbin76c37002012-10-30 09:03:43 -0500472}
473
Stefan Reinauerab365af2013-12-03 12:13:26 -0800474static void pcie_update_cfg(device_t dev, int reg, u32 mask, u32 or)
Aaron Durbin76c37002012-10-30 09:03:43 -0500475{
Aaron Durbin76c37002012-10-30 09:03:43 -0500476 u32 reg32;
477
Stefan Reinauerab365af2013-12-03 12:13:26 -0800478 reg32 = pci_read_config32(dev, reg);
479 reg32 &= mask;
480 reg32 |= or;
481 pci_write_config32(dev, reg, reg32);
482}
Aaron Durbin76c37002012-10-30 09:03:43 -0500483
Stefan Reinauerab365af2013-12-03 12:13:26 -0800484static void pcie_add_0x0202000_iobp(u32 reg)
485{
486 u32 reg32;
Aaron Durbin76c37002012-10-30 09:03:43 -0500487
Stefan Reinauerab365af2013-12-03 12:13:26 -0800488 reg32 = pch_iobp_read(reg);
489 reg32 += (0x2 << 16) | (0x2 << 8);
490 pch_iobp_write(reg, reg32);
491}
Aaron Durbin76c37002012-10-30 09:03:43 -0500492
Stefan Reinauerab365af2013-12-03 12:13:26 -0800493static void pch_pcie_early(struct device *dev)
494{
495 int rp;
496 int do_aspm;
497 int is_lp;
Duncan Laurie249a03b2013-08-09 09:06:41 -0700498 struct southbridge_intel_lynxpoint_config *config = dev->chip_info;
Aaron Durbin76c37002012-10-30 09:03:43 -0500499
Stefan Reinauerab365af2013-12-03 12:13:26 -0800500 rp = root_port_number(dev);
501 do_aspm = 0;
502 is_lp = pch_is_lp();
Aaron Durbin76c37002012-10-30 09:03:43 -0500503
Stefan Reinauerab365af2013-12-03 12:13:26 -0800504 if (is_lp) {
505 switch (rp) {
506 case 1:
507 case 2:
508 case 3:
509 case 4:
510 /* Bits 31:28 of b0d28f0 0x32c register correspnd to
511 * Root Ports 4:1. */
512 do_aspm = !!(rpc.b0d28f0_32c & (1 << (28 + rp - 1)));
513 break;
514 case 5:
515 /* Bit 28 of b0d28f4 0x32c register correspnd to
516 * Root Ports 4:1. */
517 do_aspm = !!(rpc.b0d28f4_32c & (1 << 28));
518 break;
519 case 6:
520 /* Bit 28 of b0d28f5 0x32c register correspnd to
521 * Root Ports 4:1. */
522 do_aspm = !!(rpc.b0d28f5_32c & (1 << 28));
523 break;
524 }
525 } else {
526 switch (rp) {
527 case 1:
528 case 2:
529 case 3:
530 case 4:
531 /* Bits 31:28 of b0d28f0 0x32c register correspnd to
532 * Root Ports 4:1. */
533 do_aspm = !!(rpc.b0d28f0_32c & (1 << (28 + rp - 1)));
534 break;
535 case 5:
536 case 6:
537 case 7:
538 case 8:
539 /* Bit 31:28 of b0d28f4 0x32c register correspnd to
540 * Root Ports 8:5. */
541 do_aspm = !!(rpc.b0d28f4_32c & (1 << (28 + rp - 5)));
542 break;
543 }
Aaron Durbin76c37002012-10-30 09:03:43 -0500544 }
Stefan Reinauerab365af2013-12-03 12:13:26 -0800545
Duncan Laurie249a03b2013-08-09 09:06:41 -0700546 /* Allow ASPM to be forced on in devicetree */
547 if (config && (config->pcie_port_force_aspm & (1 << (rp - 1))))
548 do_aspm = 1;
549
550 printk(BIOS_DEBUG, "PCIe Root Port %d ASPM is %sabled\n",
551 rp, do_aspm ? "en" : "dis");
552
Stefan Reinauerab365af2013-12-03 12:13:26 -0800553 if (do_aspm) {
554 /* Set ASPM bits in MPC2 register. */
555 pcie_update_cfg(dev, 0xd4, ~(0x3 << 2), (1 << 4) | (0x2 << 2));
556
557 /* Set unique clock exit latency in MPC register. */
558 pcie_update_cfg(dev, 0xd8, ~(0x7 << 18), (0x7 << 18));
559
560 /* Set L1 exit latency in LCAP register. */
561 pcie_update_cfg(dev, 0x4c, ~(0x7 << 15), (0x4 << 15));
562
563 if (is_lp) {
564 switch (rp) {
565 case 1:
566 pcie_add_0x0202000_iobp(0xe9002440);
567 break;
568 case 2:
569 pcie_add_0x0202000_iobp(0xe9002640);
570 break;
571 case 3:
572 pcie_add_0x0202000_iobp(0xe9000840);
573 break;
574 case 4:
575 pcie_add_0x0202000_iobp(0xe9000a40);
576 break;
577 case 5:
578 pcie_add_0x0202000_iobp(0xe9000c40);
579 pcie_add_0x0202000_iobp(0xe9000e40);
580 pcie_add_0x0202000_iobp(0xe9001040);
581 pcie_add_0x0202000_iobp(0xe9001240);
582 break;
583 case 6:
584 /* Update IOBP based on lane ownership. */
585 if (rpc.pin_ownership & (1 << 4))
586 pcie_add_0x0202000_iobp(0xea002040);
587 if (rpc.pin_ownership & (1 << 5))
588 pcie_add_0x0202000_iobp(0xea002240);
589 if (rpc.pin_ownership & (1 << 6))
590 pcie_add_0x0202000_iobp(0xea002440);
591 if (rpc.pin_ownership & (1 << 7))
592 pcie_add_0x0202000_iobp(0xea002640);
593 break;
594 }
595 } else {
596 switch (rp) {
597 case 1:
598 if ((rpc.pin_ownership & 0x3) == 1)
599 pcie_add_0x0202000_iobp(0xe9002e40);
600 else
601 pcie_add_0x0202000_iobp(0xea002040);
602 break;
603 case 2:
604 if ((rpc.pin_ownership & 0xc) == 0x4)
605 pcie_add_0x0202000_iobp(0xe9002c40);
606 else
607 pcie_add_0x0202000_iobp(0xea002240);
608 break;
609 case 3:
610 pcie_add_0x0202000_iobp(0xe9002a40);
611 break;
612 case 4:
613 pcie_add_0x0202000_iobp(0xe9002840);
614 break;
615 case 5:
616 pcie_add_0x0202000_iobp(0xe9002640);
617 break;
618 case 6:
619 pcie_add_0x0202000_iobp(0xe9002440);
620 break;
621 case 7:
622 pcie_add_0x0202000_iobp(0xe9002240);
623 break;
624 case 8:
625 pcie_add_0x0202000_iobp(0xe9002040);
626 break;
627 }
628 }
629
630 pcie_update_cfg(dev, 0x338, ~(1 << 26), 0);
631 }
632
633 /* Enable LTR in Root Port. */
634 pcie_update_cfg(dev, 0x64, ~(1 << 11), (1 << 11));
635 pcie_update_cfg(dev, 0x68, ~(1 << 10), (1 << 10));
636
637 pcie_update_cfg(dev, 0x318, ~(0xffff << 16), (0x1414 << 16));
638
639 /* Set L1 exit latency in LCAP register. */
640 if (!do_aspm && (pci_read_config8(dev, 0xf5) & 0x1))
641 pcie_update_cfg(dev, 0x4c, ~(0x7 << 15), (0x4 << 15));
642 else
643 pcie_update_cfg(dev, 0x4c, ~(0x7 << 15), (0x2 << 15));
644
645 pcie_update_cfg(dev, 0x314, 0x0, 0x743a361b);
646
647 /* Set Common Clock Exit Latency in MPC register. */
648 pcie_update_cfg(dev, 0xd8, ~(0x7 << 15), (0x3 << 15));
649
650 pcie_update_cfg(dev, 0x33c, ~0x00ffffff, 0x854c74);
651
652 /* Set undocumented bits in MPC2 register. */
653 pcie_update_cfg(dev, 0xd4, ~0, (1 << 12) | (1 << 6));
654
655 /* Set Invalid Recieve Range Check Enable in MPC register. */
656 pcie_update_cfg(dev, 0xd8, ~0, (1 << 25));
657
658 pcie_update_cfg8(dev, 0xf5, 0x3f, 0);
659
660 if (rp == 1 || rp == 5 || (is_lp && rp == 6))
661 pcie_update_cfg8(dev, 0xf7, ~0xc, 0);
662
663 /* Set EOI forwarding disable. */
664 pcie_update_cfg(dev, 0xd4, ~0, (1 << 1));
665
666 /* Set something involving advanced error reporting. */
667 pcie_update_cfg(dev, 0x100, ~((1 << 20) - 1), 0x10001);
668
669 if (is_lp)
670 pcie_update_cfg(dev, 0x100, ~0, (1 << 29));
671
672 /* Read and write back write-once capability registers. */
673 pcie_update_cfg(dev, 0x34, ~0, 0);
674 pcie_update_cfg(dev, 0x40, ~0, 0);
675 pcie_update_cfg(dev, 0x80, ~0, 0);
676 pcie_update_cfg(dev, 0x90, ~0, 0);
Aaron Durbin76c37002012-10-30 09:03:43 -0500677}
678
679static void pci_init(struct device *dev)
680{
681 u16 reg16;
682 u32 reg32;
683
684 printk(BIOS_DEBUG, "Initializing PCH PCIe bridge.\n");
685
Aaron Durbinc0254e62013-06-20 01:20:30 -0500686 /* Enable SERR */
687 reg32 = pci_read_config32(dev, PCI_COMMAND);
688 reg32 |= PCI_COMMAND_SERR;
689 pci_write_config32(dev, PCI_COMMAND, reg32);
690
Aaron Durbin76c37002012-10-30 09:03:43 -0500691 /* Enable Bus Master */
692 reg32 = pci_read_config32(dev, PCI_COMMAND);
693 reg32 |= PCI_COMMAND_MASTER;
694 pci_write_config32(dev, PCI_COMMAND, reg32);
695
696 /* Set Cache Line Size to 0x10 */
697 // This has no effect but the OS might expect it
698 pci_write_config8(dev, 0x0c, 0x10);
699
700 reg16 = pci_read_config16(dev, 0x3e);
701 reg16 &= ~(1 << 0); /* disable parity error response */
702 // reg16 &= ~(1 << 1); /* disable SERR */
703 reg16 |= (1 << 2); /* ISA enable */
704 pci_write_config16(dev, 0x3e, reg16);
705
706#ifdef EVEN_MORE_DEBUG
707 reg32 = pci_read_config32(dev, 0x20);
708 printk(BIOS_SPEW, " MBL = 0x%08x\n", reg32);
709 reg32 = pci_read_config32(dev, 0x24);
710 printk(BIOS_SPEW, " PMBL = 0x%08x\n", reg32);
711 reg32 = pci_read_config32(dev, 0x28);
712 printk(BIOS_SPEW, " PMBU32 = 0x%08x\n", reg32);
713 reg32 = pci_read_config32(dev, 0x2c);
714 printk(BIOS_SPEW, " PMLU32 = 0x%08x\n", reg32);
715#endif
716
717 /* Clear errors in status registers */
718 reg16 = pci_read_config16(dev, 0x06);
Aaron Durbin76c37002012-10-30 09:03:43 -0500719 pci_write_config16(dev, 0x06, reg16);
Aaron Durbin76c37002012-10-30 09:03:43 -0500720 reg16 = pci_read_config16(dev, 0x1e);
Aaron Durbin76c37002012-10-30 09:03:43 -0500721 pci_write_config16(dev, 0x1e, reg16);
Aaron Durbin76c37002012-10-30 09:03:43 -0500722}
723
724static void pch_pcie_enable(device_t dev)
725{
Aaron Durbinc0254e62013-06-20 01:20:30 -0500726 /* Add this device to the root port config structure. */
727 root_port_init_config(dev);
728
729 /* Check to see if this Root Port should be disabled. */
730 root_port_check_disable(dev);
731
Aaron Durbin76c37002012-10-30 09:03:43 -0500732 /* Power Management init before enumeration */
Aaron Durbinc0254e62013-06-20 01:20:30 -0500733 if (dev->enabled)
Stefan Reinauerab365af2013-12-03 12:13:26 -0800734 pch_pcie_early(dev);
Aaron Durbinc0254e62013-06-20 01:20:30 -0500735
736 /*
737 * When processing the last PCIe root port we can now
738 * update the Root Port Function Number and Hide register.
739 */
740 if (root_port_is_last(dev))
741 root_port_commit_config();
Aaron Durbin76c37002012-10-30 09:03:43 -0500742}
743
744static void pcie_set_subsystem(device_t dev, unsigned vendor, unsigned device)
745{
746 /* NOTE: This is not the default position! */
747 if (!vendor || !device) {
748 pci_write_config32(dev, 0x94,
749 pci_read_config32(dev, 0));
750 } else {
751 pci_write_config32(dev, 0x94,
752 ((device & 0xffff) << 16) | (vendor & 0xffff));
753 }
754}
755
756static struct pci_operations pci_ops = {
757 .set_subsystem = pcie_set_subsystem,
758};
759
760static struct device_operations device_ops = {
761 .read_resources = pci_bus_read_resources,
762 .set_resources = pci_dev_set_resources,
763 .enable_resources = pci_bus_enable_resources,
764 .init = pci_init,
765 .enable = pch_pcie_enable,
766 .scan_bus = pciexp_scan_bridge,
767 .ops_pci = &pci_ops,
768};
769
Duncan Laurie74c0d052012-12-17 11:31:40 -0800770static const unsigned short pci_device_ids[] = {
771 /* Lynxpoint Mobile */
772 0x8c10, 0x8c12, 0x8c14, 0x8c16, 0x8c18, 0x8c1a, 0x8c1c, 0x8c1e,
773 /* Lynxpoint Low Power */
774 0x9c10, 0x9c12, 0x9c14, 0x9c16, 0x9c18, 0x9c1a,
775 0
776};
Aaron Durbin76c37002012-10-30 09:03:43 -0500777
778static const struct pci_driver pch_pcie __pci_driver = {
779 .ops = &device_ops,
780 .vendor = PCI_VENDOR_ID_INTEL,
781 .devices = pci_device_ids,
782};