blob: c4cde920ed46ad82942cca5b7eaa41fdf7ce2481 [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 Durbinc0254e62013-06-20 01:20:30 -050028/* LynxPoint-LP has 6 root ports while non-LP has 8. */
29#define MAX_NUM_ROOT_PORTS 8
30#define H_NUM_ROOT_PORTS MAX_NUM_ROOT_PORTS
31#define LP_NUM_ROOT_PORTS (MAX_NUM_ROOT_PORTS - 2)
32
33struct root_port_config {
34 /* RPFN is a write-once register so keep a copy until it is written */
35 u32 orig_rpfn;
36 u32 new_rpfn;
37 u32 pin_ownership;
38 u32 strpfusecfg1;
39 u32 strpfusecfg2;
40 u32 strpfusecfg3;
Stefan Reinauerab365af2013-12-03 12:13:26 -080041 u32 b0d28f0_32c;
42 u32 b0d28f4_32c;
43 u32 b0d28f5_32c;
Aaron Durbinc0254e62013-06-20 01:20:30 -050044 int coalesce;
45 int gbe_port;
46 int num_ports;
47 device_t ports[MAX_NUM_ROOT_PORTS];
48};
49
50static struct root_port_config rpc;
51
52static inline int max_root_ports(void)
Aaron Durbin60f82082013-06-19 13:28:04 -050053{
Aaron Durbinc0254e62013-06-20 01:20:30 -050054 if (pch_is_lp())
55 return LP_NUM_ROOT_PORTS;
56 else
57 return H_NUM_ROOT_PORTS;
Aaron Durbin60f82082013-06-19 13:28:04 -050058}
59
Aaron Durbinc0254e62013-06-20 01:20:30 -050060static inline int root_port_is_first(device_t dev)
Aaron Durbin60f82082013-06-19 13:28:04 -050061{
Aaron Durbinc0254e62013-06-20 01:20:30 -050062 return PCI_FUNC(dev->path.pci.devfn) == 0;
63}
Aaron Durbin60f82082013-06-19 13:28:04 -050064
Aaron Durbinc0254e62013-06-20 01:20:30 -050065static inline int root_port_is_last(device_t dev)
66{
67 return PCI_FUNC(dev->path.pci.devfn) == (rpc.num_ports - 1);
68}
Aaron Durbin60f82082013-06-19 13:28:04 -050069
Aaron Durbinc0254e62013-06-20 01:20:30 -050070/* Root ports are numbered 1..N in the documentation. */
71static inline int root_port_number(device_t dev)
72{
73 return PCI_FUNC(dev->path.pci.devfn) + 1;
74}
Aaron Durbin60f82082013-06-19 13:28:04 -050075
Aaron Durbinc0254e62013-06-20 01:20:30 -050076static void root_port_config_update_gbe_port(void)
77{
78 /* Is the Gbe Port enabled? */
79 if (!((rpc.strpfusecfg1 >> 19) & 1))
80 return;
81
82 if (pch_is_lp()) {
83 switch ((rpc.strpfusecfg1 >> 16) & 0x7) {
84 case 0:
85 rpc.gbe_port = 3;
86 break;
87 case 1:
88 rpc.gbe_port = 4;
89 break;
90 case 2:
91 case 3:
92 case 4:
93 case 5:
94 /* Lanes 0-4 of Root Port 5. */
95 rpc.gbe_port = 5;
96 break;
97 default:
98 printk(BIOS_DEBUG, "Invalid GbE Port Selection.\n");
99 }
100 } else {
101 /* Non-LP has 1:1 mapping with root ports. */
102 rpc.gbe_port = ((rpc.strpfusecfg1 >> 16) & 0x7) + 1;
103 }
104}
105
106static void root_port_init_config(device_t dev)
107{
108 int rp;
109
110 if (root_port_is_first(dev)) {
111 rpc.orig_rpfn = RCBA32(RPFN);
112 rpc.new_rpfn = rpc.orig_rpfn;
113 rpc.num_ports = max_root_ports();
114 rpc.gbe_port = -1;
115
116 rpc.pin_ownership = pci_read_config32(dev, 0x410);
117 root_port_config_update_gbe_port();
118
119 if (dev->chip_info != NULL) {
120 struct southbridge_intel_lynxpoint_config *config;
121
122 config = dev->chip_info;
123 rpc.coalesce = config->pcie_port_coalesce;
124 }
125 }
126
127 rp = root_port_number(dev);
128 if (rp > rpc.num_ports) {
129 printk(BIOS_ERR, "Found Root Port %d, expecting %d\n",
130 rp, rpc.num_ports);
131 return;
132 }
133
134 /* Read the fuse configuration and pin ownership. */
135 switch (rp) {
136 case 1:
137 rpc.strpfusecfg1 = pci_read_config32(dev, 0xfc);
Stefan Reinauerab365af2013-12-03 12:13:26 -0800138 rpc.b0d28f0_32c = pci_read_config32(dev, 0x32c);
Aaron Durbinc0254e62013-06-20 01:20:30 -0500139 break;
140 case 5:
141 rpc.strpfusecfg2 = pci_read_config32(dev, 0xfc);
Stefan Reinauerab365af2013-12-03 12:13:26 -0800142 rpc.b0d28f4_32c = pci_read_config32(dev, 0x32c);
Aaron Durbinc0254e62013-06-20 01:20:30 -0500143 break;
144 case 6:
Stefan Reinauerab365af2013-12-03 12:13:26 -0800145 rpc.b0d28f5_32c = pci_read_config32(dev, 0x32c);
Aaron Durbinc0254e62013-06-20 01:20:30 -0500146 rpc.strpfusecfg3 = pci_read_config32(dev, 0xfc);
147 break;
148 default:
149 break;
150 }
151
152 /* Cache pci device. */
153 rpc.ports[rp - 1] = dev;
Aaron Durbin60f82082013-06-19 13:28:04 -0500154}
155
156/* Update devicetree with new Root Port function number assignment */
Aaron Durbinc0254e62013-06-20 01:20:30 -0500157static void pch_pcie_device_set_func(int index, int pci_func)
Aaron Durbin60f82082013-06-19 13:28:04 -0500158{
159 device_t dev;
Aaron Durbinc0254e62013-06-20 01:20:30 -0500160 unsigned new_devfn;
Aaron Durbin60f82082013-06-19 13:28:04 -0500161
Aaron Durbinc0254e62013-06-20 01:20:30 -0500162 dev = rpc.ports[index];
Aaron Durbin60f82082013-06-19 13:28:04 -0500163
Aaron Durbinc0254e62013-06-20 01:20:30 -0500164 /* Set the new PCI function field for this Root Port. */
165 rpc.new_rpfn &= ~RPFN_FNMASK(index);
166 rpc.new_rpfn |= RPFN_FNSET(index, pci_func);
Aaron Durbin60f82082013-06-19 13:28:04 -0500167
Aaron Durbinc0254e62013-06-20 01:20:30 -0500168 /* Determine the new devfn for this port */
169 new_devfn = PCI_DEVFN(PCH_PCIE_DEV_SLOT, pci_func);
Aaron Durbin60f82082013-06-19 13:28:04 -0500170
Aaron Durbinc0254e62013-06-20 01:20:30 -0500171 if (dev->path.pci.devfn != new_devfn) {
172 printk(BIOS_DEBUG,
173 "PCH: PCIe map %02x.%1x -> %02x.%1x\n",
174 PCI_SLOT(dev->path.pci.devfn),
175 PCI_FUNC(dev->path.pci.devfn),
176 PCI_SLOT(new_devfn), PCI_FUNC(new_devfn));
Aaron Durbin60f82082013-06-19 13:28:04 -0500177
Aaron Durbinc0254e62013-06-20 01:20:30 -0500178 dev->path.pci.devfn = new_devfn;
Aaron Durbin60f82082013-06-19 13:28:04 -0500179 }
180}
181
Aaron Durbinc0254e62013-06-20 01:20:30 -0500182static void root_port_commit_config(void)
Aaron Durbin60f82082013-06-19 13:28:04 -0500183{
Aaron Durbinc0254e62013-06-20 01:20:30 -0500184 int i;
Aaron Durbin60f82082013-06-19 13:28:04 -0500185
Aaron Durbinc0254e62013-06-20 01:20:30 -0500186 /* If the first root port is disabled the coalesce ports. */
187 if (!rpc.ports[0]->enabled)
188 rpc.coalesce = 1;
Aaron Durbin60f82082013-06-19 13:28:04 -0500189
Aaron Durbinc0254e62013-06-20 01:20:30 -0500190 for (i = 0; i < rpc.num_ports; i++) {
191 device_t dev;
192 u32 reg32;
Aaron Durbin60f82082013-06-19 13:28:04 -0500193
Aaron Durbinc0254e62013-06-20 01:20:30 -0500194 dev = rpc.ports[i];
Aaron Durbin60f82082013-06-19 13:28:04 -0500195
Aaron Durbinc0254e62013-06-20 01:20:30 -0500196 if (dev == NULL) {
197 printk(BIOS_ERR, "Root Port %d device is NULL?\n", i+1);
198 continue;
Aaron Durbin60f82082013-06-19 13:28:04 -0500199 }
200
Aaron Durbinc0254e62013-06-20 01:20:30 -0500201 if (dev->enabled)
202 continue;
203
204 printk(BIOS_DEBUG, "%s: Disabling device\n", dev_path(dev));
205
Aaron Durbin60f82082013-06-19 13:28:04 -0500206 /* Ensure memory, io, and bus master are all disabled */
207 reg32 = pci_read_config32(dev, PCI_COMMAND);
208 reg32 &= ~(PCI_COMMAND_MASTER |
209 PCI_COMMAND_MEMORY | PCI_COMMAND_IO);
210 pci_write_config32(dev, PCI_COMMAND, reg32);
211
Aaron Durbin60f82082013-06-19 13:28:04 -0500212 /* Disable this device if possible */
213 pch_disable_devfn(dev);
Aaron Durbin60f82082013-06-19 13:28:04 -0500214 }
215
Aaron Durbinc0254e62013-06-20 01:20:30 -0500216 if (rpc.coalesce) {
217 int current_func;
Aaron Durbin60f82082013-06-19 13:28:04 -0500218
Aaron Durbinc0254e62013-06-20 01:20:30 -0500219 /* For all Root Ports N enabled ports get assigned the lower
220 * PCI function number. The disabled ones get upper PCI
221 * function numbers. */
222 current_func = 0;
223 for (i = 0; i < rpc.num_ports; i++) {
224 if (!rpc.ports[i]->enabled)
225 continue;
226 pch_pcie_device_set_func(i, current_func);
227 current_func++;
228 }
229
230 /* Allocate the disabled devices' PCI function number. */
231 for (i = 0; i < rpc.num_ports; i++) {
232 if (rpc.ports[i]->enabled)
233 continue;
234 pch_pcie_device_set_func(i, current_func);
235 current_func++;
236 }
237 }
238
239 printk(BIOS_SPEW, "PCH: RPFN 0x%08x -> 0x%08x\n",
240 rpc.orig_rpfn, rpc.new_rpfn);
241 RCBA32(RPFN) = rpc.new_rpfn;
242}
243
244static void root_port_mark_disable(device_t dev)
245{
246 /* Mark device as disabled. */
247 dev->enabled = 0;
248 /* Mark device to be hidden. */
249 rpc.new_rpfn |= RPFN_HIDE(PCI_FUNC(dev->path.pci.devfn));
250}
251
252static void root_port_check_disable(device_t dev)
253{
254 int rp;
255 int is_lp;
256
257 /* Device already disabled. */
258 if (!dev->enabled) {
259 root_port_mark_disable(dev);
260 return;
261 }
262
263 rp = root_port_number(dev);
264
265 /* Is the GbE port mapped to this Root Port? */
266 if (rp == rpc.gbe_port) {
267 root_port_mark_disable(dev);
268 return;
269 }
270
271 is_lp = pch_is_lp();
272
273 /* Check Root Port Configuration. */
274 switch (rp) {
275 case 2:
276 /* Root Port 2 is disabled for all lane configurations
277 * but config 00b (4x1 links). */
278 if ((rpc.strpfusecfg1 >> 14) & 0x3) {
279 root_port_mark_disable(dev);
280 return;
281 }
282 break;
283 case 3:
284 /* Root Port 3 is disabled in config 11b (1x4 links). */
285 if (((rpc.strpfusecfg1 >> 14) & 0x3) == 0x3) {
286 root_port_mark_disable(dev);
287 return;
288 }
289 break;
290 case 4:
291 /* Root Port 4 is disabled in configs 11b (1x4 links)
292 * and 10b (2x2 links). */
293 if ((rpc.strpfusecfg1 >> 14) & 0x2) {
294 root_port_mark_disable(dev);
295 return;
296 }
297 break;
298 case 6:
299 if (is_lp)
300 break;
301 /* Root Port 6 is disabled for all lane configurations
302 * but config 00b (4x1 links). */
303 if ((rpc.strpfusecfg2 >> 14) & 0x3) {
304 root_port_mark_disable(dev);
305 return;
306 }
307 break;
308 case 7:
309 if (is_lp)
310 break;
311 /* Root Port 3 is disabled in config 11b (1x4 links). */
312 if (((rpc.strpfusecfg2 >> 14) & 0x3) == 0x3) {
313 root_port_mark_disable(dev);
314 return;
315 }
316 break;
317 case 8:
318 if (is_lp)
319 break;
320 /* Root Port 8 is disabled in configs 11b (1x4 links)
321 * and 10b (2x2 links). */
322 if ((rpc.strpfusecfg2 >> 14) & 0x2) {
323 root_port_mark_disable(dev);
324 return;
325 }
326 break;
327 }
328
329 /* Check Pin Ownership. */
330 if (is_lp) {
331 switch (rp) {
332 case 1:
333 /* Bit 0 is Root Port 1 ownership. */
334 if ((rpc.pin_ownership & 0x1) == 0) {
335 root_port_mark_disable(dev);
336 return;
337 }
338 break;
339 case 2:
340 /* Bit 2 is Root Port 2 ownership. */
341 if ((rpc.pin_ownership & 0x4) == 0) {
342 root_port_mark_disable(dev);
343 return;
344 }
345 break;
346 case 6:
347 /* Bits 7:4 are Root Port 6 pin-lane ownership. */
348 if ((rpc.pin_ownership & 0xf0) == 0) {
349 root_port_mark_disable(dev);
350 return;
351 }
352 break;
353 }
354 } else {
355 switch (rp) {
356 case 1:
357 /* Bits 4 and 0 are Root Port 1 ownership. */
358 if ((rpc.pin_ownership & 0x11) == 0) {
359 root_port_mark_disable(dev);
360 return;
361 }
362 break;
363 case 2:
364 /* Bits 5 and 2 are Root Port 2 ownership. */
365 if ((rpc.pin_ownership & 0x24) == 0) {
366 root_port_mark_disable(dev);
367 return;
368 }
369 break;
370 }
Aaron Durbin60f82082013-06-19 13:28:04 -0500371 }
372}
373
Stefan Reinauerab365af2013-12-03 12:13:26 -0800374static void pcie_update_cfg8(device_t dev, int reg, u8 mask, u8 or)
Aaron Durbin76c37002012-10-30 09:03:43 -0500375{
Aaron Durbin76c37002012-10-30 09:03:43 -0500376 u8 reg8;
377
Stefan Reinauerab365af2013-12-03 12:13:26 -0800378 reg8 = pci_read_config8(dev, reg);
379 reg8 &= mask;
380 reg8 |= or;
381 pci_write_config8(dev, reg, reg8);
Aaron Durbin76c37002012-10-30 09:03:43 -0500382}
383
Stefan Reinauerab365af2013-12-03 12:13:26 -0800384static void pcie_update_cfg(device_t dev, int reg, u32 mask, u32 or)
Aaron Durbin76c37002012-10-30 09:03:43 -0500385{
Aaron Durbin76c37002012-10-30 09:03:43 -0500386 u32 reg32;
387
Stefan Reinauerab365af2013-12-03 12:13:26 -0800388 reg32 = pci_read_config32(dev, reg);
389 reg32 &= mask;
390 reg32 |= or;
391 pci_write_config32(dev, reg, reg32);
392}
Aaron Durbin76c37002012-10-30 09:03:43 -0500393
Stefan Reinauerab365af2013-12-03 12:13:26 -0800394static void pcie_add_0x0202000_iobp(u32 reg)
395{
396 u32 reg32;
Aaron Durbin76c37002012-10-30 09:03:43 -0500397
Stefan Reinauerab365af2013-12-03 12:13:26 -0800398 reg32 = pch_iobp_read(reg);
399 reg32 += (0x2 << 16) | (0x2 << 8);
400 pch_iobp_write(reg, reg32);
401}
Aaron Durbin76c37002012-10-30 09:03:43 -0500402
Stefan Reinauerab365af2013-12-03 12:13:26 -0800403static void pch_pcie_early(struct device *dev)
404{
405 int rp;
406 int do_aspm;
407 int is_lp;
Aaron Durbin76c37002012-10-30 09:03:43 -0500408
Stefan Reinauerab365af2013-12-03 12:13:26 -0800409 rp = root_port_number(dev);
410 do_aspm = 0;
411 is_lp = pch_is_lp();
Aaron Durbin76c37002012-10-30 09:03:43 -0500412
Stefan Reinauerab365af2013-12-03 12:13:26 -0800413 if (is_lp) {
414 switch (rp) {
415 case 1:
416 case 2:
417 case 3:
418 case 4:
419 /* Bits 31:28 of b0d28f0 0x32c register correspnd to
420 * Root Ports 4:1. */
421 do_aspm = !!(rpc.b0d28f0_32c & (1 << (28 + rp - 1)));
422 break;
423 case 5:
424 /* Bit 28 of b0d28f4 0x32c register correspnd to
425 * Root Ports 4:1. */
426 do_aspm = !!(rpc.b0d28f4_32c & (1 << 28));
427 break;
428 case 6:
429 /* Bit 28 of b0d28f5 0x32c register correspnd to
430 * Root Ports 4:1. */
431 do_aspm = !!(rpc.b0d28f5_32c & (1 << 28));
432 break;
433 }
434 } else {
435 switch (rp) {
436 case 1:
437 case 2:
438 case 3:
439 case 4:
440 /* Bits 31:28 of b0d28f0 0x32c register correspnd to
441 * Root Ports 4:1. */
442 do_aspm = !!(rpc.b0d28f0_32c & (1 << (28 + rp - 1)));
443 break;
444 case 5:
445 case 6:
446 case 7:
447 case 8:
448 /* Bit 31:28 of b0d28f4 0x32c register correspnd to
449 * Root Ports 8:5. */
450 do_aspm = !!(rpc.b0d28f4_32c & (1 << (28 + rp - 5)));
451 break;
452 }
Aaron Durbin76c37002012-10-30 09:03:43 -0500453 }
Stefan Reinauerab365af2013-12-03 12:13:26 -0800454
455 if (do_aspm) {
456 /* Set ASPM bits in MPC2 register. */
457 pcie_update_cfg(dev, 0xd4, ~(0x3 << 2), (1 << 4) | (0x2 << 2));
458
459 /* Set unique clock exit latency in MPC register. */
460 pcie_update_cfg(dev, 0xd8, ~(0x7 << 18), (0x7 << 18));
461
462 /* Set L1 exit latency in LCAP register. */
463 pcie_update_cfg(dev, 0x4c, ~(0x7 << 15), (0x4 << 15));
464
465 if (is_lp) {
466 switch (rp) {
467 case 1:
468 pcie_add_0x0202000_iobp(0xe9002440);
469 break;
470 case 2:
471 pcie_add_0x0202000_iobp(0xe9002640);
472 break;
473 case 3:
474 pcie_add_0x0202000_iobp(0xe9000840);
475 break;
476 case 4:
477 pcie_add_0x0202000_iobp(0xe9000a40);
478 break;
479 case 5:
480 pcie_add_0x0202000_iobp(0xe9000c40);
481 pcie_add_0x0202000_iobp(0xe9000e40);
482 pcie_add_0x0202000_iobp(0xe9001040);
483 pcie_add_0x0202000_iobp(0xe9001240);
484 break;
485 case 6:
486 /* Update IOBP based on lane ownership. */
487 if (rpc.pin_ownership & (1 << 4))
488 pcie_add_0x0202000_iobp(0xea002040);
489 if (rpc.pin_ownership & (1 << 5))
490 pcie_add_0x0202000_iobp(0xea002240);
491 if (rpc.pin_ownership & (1 << 6))
492 pcie_add_0x0202000_iobp(0xea002440);
493 if (rpc.pin_ownership & (1 << 7))
494 pcie_add_0x0202000_iobp(0xea002640);
495 break;
496 }
497 } else {
498 switch (rp) {
499 case 1:
500 if ((rpc.pin_ownership & 0x3) == 1)
501 pcie_add_0x0202000_iobp(0xe9002e40);
502 else
503 pcie_add_0x0202000_iobp(0xea002040);
504 break;
505 case 2:
506 if ((rpc.pin_ownership & 0xc) == 0x4)
507 pcie_add_0x0202000_iobp(0xe9002c40);
508 else
509 pcie_add_0x0202000_iobp(0xea002240);
510 break;
511 case 3:
512 pcie_add_0x0202000_iobp(0xe9002a40);
513 break;
514 case 4:
515 pcie_add_0x0202000_iobp(0xe9002840);
516 break;
517 case 5:
518 pcie_add_0x0202000_iobp(0xe9002640);
519 break;
520 case 6:
521 pcie_add_0x0202000_iobp(0xe9002440);
522 break;
523 case 7:
524 pcie_add_0x0202000_iobp(0xe9002240);
525 break;
526 case 8:
527 pcie_add_0x0202000_iobp(0xe9002040);
528 break;
529 }
530 }
531
532 pcie_update_cfg(dev, 0x338, ~(1 << 26), 0);
533 }
534
535 /* Enable LTR in Root Port. */
536 pcie_update_cfg(dev, 0x64, ~(1 << 11), (1 << 11));
537 pcie_update_cfg(dev, 0x68, ~(1 << 10), (1 << 10));
538
539 pcie_update_cfg(dev, 0x318, ~(0xffff << 16), (0x1414 << 16));
540
541 /* Set L1 exit latency in LCAP register. */
542 if (!do_aspm && (pci_read_config8(dev, 0xf5) & 0x1))
543 pcie_update_cfg(dev, 0x4c, ~(0x7 << 15), (0x4 << 15));
544 else
545 pcie_update_cfg(dev, 0x4c, ~(0x7 << 15), (0x2 << 15));
546
547 pcie_update_cfg(dev, 0x314, 0x0, 0x743a361b);
548
549 /* Set Common Clock Exit Latency in MPC register. */
550 pcie_update_cfg(dev, 0xd8, ~(0x7 << 15), (0x3 << 15));
551
552 pcie_update_cfg(dev, 0x33c, ~0x00ffffff, 0x854c74);
553
554 /* Set undocumented bits in MPC2 register. */
555 pcie_update_cfg(dev, 0xd4, ~0, (1 << 12) | (1 << 6));
556
557 /* Set Invalid Recieve Range Check Enable in MPC register. */
558 pcie_update_cfg(dev, 0xd8, ~0, (1 << 25));
559
560 pcie_update_cfg8(dev, 0xf5, 0x3f, 0);
561
562 if (rp == 1 || rp == 5 || (is_lp && rp == 6))
563 pcie_update_cfg8(dev, 0xf7, ~0xc, 0);
564
565 /* Set EOI forwarding disable. */
566 pcie_update_cfg(dev, 0xd4, ~0, (1 << 1));
567
568 /* Set something involving advanced error reporting. */
569 pcie_update_cfg(dev, 0x100, ~((1 << 20) - 1), 0x10001);
570
571 if (is_lp)
572 pcie_update_cfg(dev, 0x100, ~0, (1 << 29));
573
574 /* Read and write back write-once capability registers. */
575 pcie_update_cfg(dev, 0x34, ~0, 0);
576 pcie_update_cfg(dev, 0x40, ~0, 0);
577 pcie_update_cfg(dev, 0x80, ~0, 0);
578 pcie_update_cfg(dev, 0x90, ~0, 0);
Aaron Durbin76c37002012-10-30 09:03:43 -0500579}
580
581static void pci_init(struct device *dev)
582{
583 u16 reg16;
584 u32 reg32;
585
586 printk(BIOS_DEBUG, "Initializing PCH PCIe bridge.\n");
587
Aaron Durbinc0254e62013-06-20 01:20:30 -0500588 /* Enable SERR */
589 reg32 = pci_read_config32(dev, PCI_COMMAND);
590 reg32 |= PCI_COMMAND_SERR;
591 pci_write_config32(dev, PCI_COMMAND, reg32);
592
Aaron Durbin76c37002012-10-30 09:03:43 -0500593 /* Enable Bus Master */
594 reg32 = pci_read_config32(dev, PCI_COMMAND);
595 reg32 |= PCI_COMMAND_MASTER;
596 pci_write_config32(dev, PCI_COMMAND, reg32);
597
598 /* Set Cache Line Size to 0x10 */
599 // This has no effect but the OS might expect it
600 pci_write_config8(dev, 0x0c, 0x10);
601
602 reg16 = pci_read_config16(dev, 0x3e);
603 reg16 &= ~(1 << 0); /* disable parity error response */
604 // reg16 &= ~(1 << 1); /* disable SERR */
605 reg16 |= (1 << 2); /* ISA enable */
606 pci_write_config16(dev, 0x3e, reg16);
607
608#ifdef EVEN_MORE_DEBUG
609 reg32 = pci_read_config32(dev, 0x20);
610 printk(BIOS_SPEW, " MBL = 0x%08x\n", reg32);
611 reg32 = pci_read_config32(dev, 0x24);
612 printk(BIOS_SPEW, " PMBL = 0x%08x\n", reg32);
613 reg32 = pci_read_config32(dev, 0x28);
614 printk(BIOS_SPEW, " PMBU32 = 0x%08x\n", reg32);
615 reg32 = pci_read_config32(dev, 0x2c);
616 printk(BIOS_SPEW, " PMLU32 = 0x%08x\n", reg32);
617#endif
618
619 /* Clear errors in status registers */
620 reg16 = pci_read_config16(dev, 0x06);
Aaron Durbin76c37002012-10-30 09:03:43 -0500621 pci_write_config16(dev, 0x06, reg16);
Aaron Durbin76c37002012-10-30 09:03:43 -0500622 reg16 = pci_read_config16(dev, 0x1e);
Aaron Durbin76c37002012-10-30 09:03:43 -0500623 pci_write_config16(dev, 0x1e, reg16);
Aaron Durbin76c37002012-10-30 09:03:43 -0500624}
625
626static void pch_pcie_enable(device_t dev)
627{
Aaron Durbinc0254e62013-06-20 01:20:30 -0500628 /* Add this device to the root port config structure. */
629 root_port_init_config(dev);
630
631 /* Check to see if this Root Port should be disabled. */
632 root_port_check_disable(dev);
633
Aaron Durbin76c37002012-10-30 09:03:43 -0500634 /* Power Management init before enumeration */
Aaron Durbinc0254e62013-06-20 01:20:30 -0500635 if (dev->enabled)
Stefan Reinauerab365af2013-12-03 12:13:26 -0800636 pch_pcie_early(dev);
Aaron Durbinc0254e62013-06-20 01:20:30 -0500637
638 /*
639 * When processing the last PCIe root port we can now
640 * update the Root Port Function Number and Hide register.
641 */
642 if (root_port_is_last(dev))
643 root_port_commit_config();
Aaron Durbin76c37002012-10-30 09:03:43 -0500644}
645
646static void pcie_set_subsystem(device_t dev, unsigned vendor, unsigned device)
647{
648 /* NOTE: This is not the default position! */
649 if (!vendor || !device) {
650 pci_write_config32(dev, 0x94,
651 pci_read_config32(dev, 0));
652 } else {
653 pci_write_config32(dev, 0x94,
654 ((device & 0xffff) << 16) | (vendor & 0xffff));
655 }
656}
657
658static struct pci_operations pci_ops = {
659 .set_subsystem = pcie_set_subsystem,
660};
661
662static struct device_operations device_ops = {
663 .read_resources = pci_bus_read_resources,
664 .set_resources = pci_dev_set_resources,
665 .enable_resources = pci_bus_enable_resources,
666 .init = pci_init,
667 .enable = pch_pcie_enable,
668 .scan_bus = pciexp_scan_bridge,
669 .ops_pci = &pci_ops,
670};
671
Duncan Laurie74c0d052012-12-17 11:31:40 -0800672static const unsigned short pci_device_ids[] = {
673 /* Lynxpoint Mobile */
674 0x8c10, 0x8c12, 0x8c14, 0x8c16, 0x8c18, 0x8c1a, 0x8c1c, 0x8c1e,
675 /* Lynxpoint Low Power */
676 0x9c10, 0x9c12, 0x9c14, 0x9c16, 0x9c18, 0x9c1a,
677 0
678};
Aaron Durbin76c37002012-10-30 09:03:43 -0500679
680static const struct pci_driver pch_pcie __pci_driver = {
681 .ops = &device_ops,
682 .vendor = PCI_VENDOR_ID_INTEL,
683 .devices = pci_device_ids,
684};