blob: 41d66e2f2a5f2dc6bea73d064292eda08b3d8ebf [file] [log] [blame]
Duncan Lauriec88c54c2014-04-30 16:36:13 -07001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2008-2009 coresystems GmbH
5 * Copyright (C) 2014 Google Inc.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 2 of 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.
Duncan Lauriec88c54c2014-04-30 16:36:13 -070015 */
16
17#include <console/console.h>
18#include <device/device.h>
19#include <device/pci.h>
20#include <device/pciexp.h>
21#include <device/pci_def.h>
22#include <device/pci_ids.h>
Julius Werner4ee4bd52014-10-20 13:46:39 -070023#include <soc/gpio.h>
24#include <soc/lpc.h>
25#include <soc/iobp.h>
26#include <soc/pch.h>
27#include <soc/pci_devs.h>
28#include <soc/rcba.h>
29#include <soc/intel/broadwell/chip.h>
30#include <soc/cpu.h>
Wenkai Du83067612014-12-05 14:00:26 -080031#include <delay.h>
Duncan Lauriec88c54c2014-04-30 16:36:13 -070032
33static void pcie_update_cfg8(device_t dev, int reg, u8 mask, u8 or);
34static void pcie_update_cfg(device_t dev, int reg, u32 mask, u32 or);
35
36/* Low Power variant has 6 root ports. */
37#define NUM_ROOT_PORTS 6
38
39struct root_port_config {
40 /* RPFN is a write-once register so keep a copy until it is written */
41 u32 orig_rpfn;
42 u32 new_rpfn;
43 u32 pin_ownership;
44 u32 strpfusecfg1;
45 u32 strpfusecfg2;
46 u32 strpfusecfg3;
47 u32 b0d28f0_32c;
48 u32 b0d28f4_32c;
49 u32 b0d28f5_32c;
50 int coalesce;
51 int gbe_port;
52 int num_ports;
53 device_t ports[NUM_ROOT_PORTS];
54};
55
56static struct root_port_config rpc;
57
58static inline int root_port_is_first(device_t dev)
59{
60 return PCI_FUNC(dev->path.pci.devfn) == 0;
61}
62
63static inline int root_port_is_last(device_t dev)
64{
65 return PCI_FUNC(dev->path.pci.devfn) == (rpc.num_ports - 1);
66}
67
68/* Root ports are numbered 1..N in the documentation. */
69static inline int root_port_number(device_t dev)
70{
71 return PCI_FUNC(dev->path.pci.devfn) + 1;
72}
73
74static void root_port_config_update_gbe_port(void)
75{
76 /* Is the Gbe Port enabled? */
77 if (!((rpc.strpfusecfg1 >> 19) & 1))
78 return;
79
80 switch ((rpc.strpfusecfg1 >> 16) & 0x7) {
81 case 0:
82 rpc.gbe_port = 3;
83 break;
84 case 1:
85 rpc.gbe_port = 4;
86 break;
87 case 2:
88 case 3:
89 case 4:
90 case 5:
91 /* Lanes 0-4 of Root Port 5. */
92 rpc.gbe_port = 5;
93 break;
94 default:
95 printk(BIOS_DEBUG, "Invalid GbE Port Selection.\n");
96 }
97}
98
Kenji Chen87d4a202014-09-24 01:18:26 +080099static void pcie_iosf_port_grant_count(device_t dev)
100{
101 u8 update_val;
102 u32 rpcd = (pci_read_config32(dev, 0xfc) > 14) & 0x3;
103
104 switch (rpcd) {
105 case 1:
106 case 3:
107 update_val = 0x02;
108 break;
109 case 2:
110 update_val = 0x22;
111 break;
112 default:
113 update_val = 0x00;
114 break;
115 }
116
117 RCBA32(0x103C) = (RCBA32(0x103C) & (~0xff)) | update_val;
118}
119
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700120static void root_port_init_config(device_t dev)
121{
122 int rp;
Martin Roth2b2ff7f2015-12-18 10:46:59 -0700123 u32 data = 0;
Kenji Chene383feb2014-09-26 03:14:57 +0800124 u8 resp, id;
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700125
126 if (root_port_is_first(dev)) {
127 rpc.orig_rpfn = RCBA32(RPFN);
128 rpc.new_rpfn = rpc.orig_rpfn;
129 rpc.num_ports = NUM_ROOT_PORTS;
130 rpc.gbe_port = -1;
Kenji Chen87d4a202014-09-24 01:18:26 +0800131 /* RP0 f5[3:0] = 0101b*/
132 pcie_update_cfg8(dev, 0xf5, ~0xa, 0x5);
133
134 pcie_iosf_port_grant_count(dev);
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700135
136 rpc.pin_ownership = pci_read_config32(dev, 0x410);
137 root_port_config_update_gbe_port();
138
Kane Chen642e5982014-09-09 15:53:09 -0700139 pcie_update_cfg8(dev, 0xe2, ~(3 << 4), (3 << 4));
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700140 if (dev->chip_info != NULL) {
141 config_t *config = dev->chip_info;
142 rpc.coalesce = config->pcie_port_coalesce;
143 }
144 }
145
146 rp = root_port_number(dev);
147 if (rp > rpc.num_ports) {
148 printk(BIOS_ERR, "Found Root Port %d, expecting %d\n",
149 rp, rpc.num_ports);
150 return;
151 }
152
153 /* Read the fuse configuration and pin ownership. */
154 switch (rp) {
155 case 1:
156 rpc.strpfusecfg1 = pci_read_config32(dev, 0xfc);
157 rpc.b0d28f0_32c = pci_read_config32(dev, 0x32c);
158 break;
159 case 5:
160 rpc.strpfusecfg2 = pci_read_config32(dev, 0xfc);
161 rpc.b0d28f4_32c = pci_read_config32(dev, 0x32c);
162 break;
163 case 6:
164 rpc.b0d28f5_32c = pci_read_config32(dev, 0x32c);
165 rpc.strpfusecfg3 = pci_read_config32(dev, 0xfc);
166 break;
167 default:
168 break;
169 }
170
Kane Chen46134722014-08-28 17:05:06 -0700171 pcie_update_cfg(dev, 0x418, 0, 0x02000430);
Kenji Chene383feb2014-09-26 03:14:57 +0800172
Kenji Chene383feb2014-09-26 03:14:57 +0800173 if (root_port_is_first(dev)) {
Kenji Chene8f36642014-10-04 02:59:06 +0800174 /*
175 * set RP0 PCICFG E2h[5:4] = 11b and E1h[6] = 1
176 * before configuring ASPM
177 */
Kenji Chene383feb2014-09-26 03:14:57 +0800178 id = 0xe0 + (u8)(RCBA32(RPFN) & 0x07);
179 pch_iobp_exec(0xE00000E0, IOBP_PCICFG_READ, id, &data, &resp);
Kenji Chene8f36642014-10-04 02:59:06 +0800180 data |= ((0x30 << 16) | (0x40 << 8));
Kenji Chene383feb2014-09-26 03:14:57 +0800181 pch_iobp_exec(0xE00000E0, IOBP_PCICFG_WRITE, id, &data, &resp);
182 }
183
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700184 /* Cache pci device. */
185 rpc.ports[rp - 1] = dev;
186}
187
188/* Update devicetree with new Root Port function number assignment */
189static void pch_pcie_device_set_func(int index, int pci_func)
190{
191 device_t dev;
192 unsigned new_devfn;
193
194 dev = rpc.ports[index];
195
196 /* Set the new PCI function field for this Root Port. */
197 rpc.new_rpfn &= ~RPFN_FNMASK(index);
198 rpc.new_rpfn |= RPFN_FNSET(index, pci_func);
199
200 /* Determine the new devfn for this port */
201 new_devfn = PCI_DEVFN(PCH_DEV_SLOT_PCIE, pci_func);
202
203 if (dev->path.pci.devfn != new_devfn) {
204 printk(BIOS_DEBUG,
205 "PCH: PCIe map %02x.%1x -> %02x.%1x\n",
206 PCI_SLOT(dev->path.pci.devfn),
207 PCI_FUNC(dev->path.pci.devfn),
208 PCI_SLOT(new_devfn), PCI_FUNC(new_devfn));
209
210 dev->path.pci.devfn = new_devfn;
211 }
212}
213
214static void pcie_enable_clock_gating(void)
215{
216 int i;
217 int enabled_ports = 0;
Kane Chen4fef5a22014-08-27 15:21:32 -0700218 int is_broadwell = !!(cpu_family_model() == BROADWELL_FAMILY_ULT);
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700219
220 for (i = 0; i < rpc.num_ports; i++) {
221 device_t dev;
222 int rp;
223
224 dev = rpc.ports[i];
225 rp = root_port_number(dev);
226
227 if (!dev->enabled) {
228 /* Configure shared resource clock gating. */
229 if (rp == 1 || rp == 5 || rp == 6)
230 pcie_update_cfg8(dev, 0xe1, 0xc3, 0x3c);
231
232 pcie_update_cfg8(dev, 0xe2, ~(3 << 4), (3 << 4));
233 pcie_update_cfg(dev, 0x420, ~(1 << 31), (1 << 31));
234
235 /* Per-Port CLKREQ# handling. */
236 if (gpio_is_native(18 + rp - 1))
237 pcie_update_cfg(dev, 0x420, ~0, (3 << 29));
238
239 /* Enable static clock gating. */
240 if (rp == 1 && !rpc.ports[1]->enabled &&
241 !rpc.ports[2]->enabled && !rpc.ports[3]->enabled) {
242 pcie_update_cfg8(dev, 0xe2, ~1, 1);
243 pcie_update_cfg8(dev, 0xe1, 0x7f, 0x80);
244 } else if (rp == 5 || rp == 6) {
245 pcie_update_cfg8(dev, 0xe2, ~1, 1);
246 pcie_update_cfg8(dev, 0xe1, 0x7f, 0x80);
247 }
248 continue;
249 }
250
251 enabled_ports++;
252
253 /* Enable dynamic clock gating. */
254 pcie_update_cfg8(dev, 0xe1, 0xfc, 0x03);
255 pcie_update_cfg8(dev, 0xe2, ~(1 << 6), (1 << 6));
256 pcie_update_cfg8(dev, 0xe8, ~(3 << 2), (2 << 2));
257
258 /* Update PECR1 register. */
Kane Chen4fef5a22014-08-27 15:21:32 -0700259 pcie_update_cfg8(dev, 0xe8, ~0, 3);
260 if (is_broadwell) {
261 pcie_update_cfg(dev, 0x324, ~((1 << 5) | (1 << 14)),
262 ((1 << 5) | (1 << 14)));
263 } else {
264 pcie_update_cfg(dev, 0x324, ~(1 << 5), (1 << 5));
265 }
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700266 /* Per-Port CLKREQ# handling. */
267 if (gpio_is_native(18 + rp - 1))
Kenji Chene8f36642014-10-04 02:59:06 +0800268 /*
269 * In addition to D28Fx PCICFG 420h[30:29] = 11b,
270 * set 420h[17] = 0b and 420[0] = 1b for L1 SubState.
271 */
272 pcie_update_cfg(dev, 0x420, ~0x20000, (3 << 29) | 1);
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700273
274 /* Configure shared resource clock gating. */
275 if (rp == 1 || rp == 5 || rp == 6)
276 pcie_update_cfg8(dev, 0xe1, 0xc3, 0x3c);
Duncan Laurie446fb8e2014-08-08 09:59:43 -0700277
278 /* CLKREQ# VR Idle Enable */
279 RCBA32_OR(0x2b1c, (1 << (16 + i)));
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700280 }
281
282 if (!enabled_ports)
283 pcie_update_cfg8(rpc.ports[0], 0xe1, ~(1 << 6), (1 << 6));
284}
285
286static void root_port_commit_config(void)
287{
288 int i;
289
290 /* If the first root port is disabled the coalesce ports. */
291 if (!rpc.ports[0]->enabled)
292 rpc.coalesce = 1;
293
294 /* Perform clock gating configuration. */
295 pcie_enable_clock_gating();
296
297 for (i = 0; i < rpc.num_ports; i++) {
298 device_t dev;
299 u32 reg32;
Wenkai Du83067612014-12-05 14:00:26 -0800300 int n = 0;
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700301
302 dev = rpc.ports[i];
303
304 if (dev == NULL) {
305 printk(BIOS_ERR, "Root Port %d device is NULL?\n", i+1);
306 continue;
307 }
308
309 if (dev->enabled)
310 continue;
311
312 printk(BIOS_DEBUG, "%s: Disabling device\n", dev_path(dev));
313
Wenkai Du83067612014-12-05 14:00:26 -0800314 /* 8.2 Configuration of PCI Express Root Ports */
315 pcie_update_cfg(dev, 0x338, ~(1 << 26), 1 << 26);
316
317 do {
318 reg32 = pci_read_config32(dev, 0x328);
319 n++;
Duncan Lauriecad2b7b2015-01-14 17:30:20 -0800320 if (((reg32 & 0xff000000) == 0x01000000) || (n > 50))
Wenkai Du83067612014-12-05 14:00:26 -0800321 break;
322 udelay(100);
323 } while (1);
324
Duncan Lauriecad2b7b2015-01-14 17:30:20 -0800325 if (n > 50)
Wenkai Du83067612014-12-05 14:00:26 -0800326 printk(BIOS_DEBUG, "%s: Timeout waiting for 328h\n",
327 dev_path(dev));
328
329 pcie_update_cfg(dev, 0x408, ~(1 << 27), 1 << 27);
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700330
331 /* Disable this device if possible */
332 pch_disable_devfn(dev);
333 }
334
335 if (rpc.coalesce) {
336 int current_func;
337
338 /* For all Root Ports N enabled ports get assigned the lower
339 * PCI function number. The disabled ones get upper PCI
340 * function numbers. */
341 current_func = 0;
342 for (i = 0; i < rpc.num_ports; i++) {
343 if (!rpc.ports[i]->enabled)
344 continue;
345 pch_pcie_device_set_func(i, current_func);
346 current_func++;
347 }
348
349 /* Allocate the disabled devices' PCI function number. */
350 for (i = 0; i < rpc.num_ports; i++) {
351 if (rpc.ports[i]->enabled)
352 continue;
353 pch_pcie_device_set_func(i, current_func);
354 current_func++;
355 }
356 }
357
358 printk(BIOS_SPEW, "PCH: RPFN 0x%08x -> 0x%08x\n",
359 rpc.orig_rpfn, rpc.new_rpfn);
360 RCBA32(RPFN) = rpc.new_rpfn;
361}
362
363static void root_port_mark_disable(device_t dev)
364{
365 /* Mark device as disabled. */
366 dev->enabled = 0;
367 /* Mark device to be hidden. */
368 rpc.new_rpfn |= RPFN_HIDE(PCI_FUNC(dev->path.pci.devfn));
369}
370
371static void root_port_check_disable(device_t dev)
372{
373 int rp;
374
375 /* Device already disabled. */
376 if (!dev->enabled) {
377 root_port_mark_disable(dev);
378 return;
379 }
380
381 rp = root_port_number(dev);
382
383 /* Is the GbE port mapped to this Root Port? */
384 if (rp == rpc.gbe_port) {
385 root_port_mark_disable(dev);
386 return;
387 }
388
389 /* Check Root Port Configuration. */
390 switch (rp) {
391 case 2:
392 /* Root Port 2 is disabled for all lane configurations
393 * but config 00b (4x1 links). */
394 if ((rpc.strpfusecfg1 >> 14) & 0x3) {
395 root_port_mark_disable(dev);
396 return;
397 }
398 break;
399 case 3:
400 /* Root Port 3 is disabled in config 11b (1x4 links). */
401 if (((rpc.strpfusecfg1 >> 14) & 0x3) == 0x3) {
402 root_port_mark_disable(dev);
403 return;
404 }
405 break;
406 case 4:
407 /* Root Port 4 is disabled in configs 11b (1x4 links)
408 * and 10b (2x2 links). */
409 if ((rpc.strpfusecfg1 >> 14) & 0x2) {
410 root_port_mark_disable(dev);
411 return;
412 }
413 break;
414 }
415
416 /* Check Pin Ownership. */
417 switch (rp) {
418 case 1:
419 /* Bit 0 is Root Port 1 ownership. */
420 if ((rpc.pin_ownership & 0x1) == 0) {
421 root_port_mark_disable(dev);
422 return;
423 }
424 break;
425 case 2:
426 /* Bit 2 is Root Port 2 ownership. */
427 if ((rpc.pin_ownership & 0x4) == 0) {
428 root_port_mark_disable(dev);
429 return;
430 }
431 break;
432 case 6:
433 /* Bits 7:4 are Root Port 6 pin-lane ownership. */
434 if ((rpc.pin_ownership & 0xf0) == 0) {
435 root_port_mark_disable(dev);
436 return;
437 }
438 break;
439 }
440}
441
442static void pcie_update_cfg8(device_t dev, int reg, u8 mask, u8 or)
443{
444 u8 reg8;
445
446 reg8 = pci_read_config8(dev, reg);
447 reg8 &= mask;
448 reg8 |= or;
449 pci_write_config8(dev, reg, reg8);
450}
451
452static void pcie_update_cfg(device_t dev, int reg, u32 mask, u32 or)
453{
454 u32 reg32;
455
456 reg32 = pci_read_config32(dev, reg);
457 reg32 &= mask;
458 reg32 |= or;
459 pci_write_config32(dev, reg, reg32);
460}
461
462static void pcie_add_0x0202000_iobp(u32 reg)
463{
464 u32 reg32;
465
466 reg32 = pch_iobp_read(reg);
467 reg32 += (0x2 << 16) | (0x2 << 8);
468 pch_iobp_write(reg, reg32);
469}
470
471static void pch_pcie_early(struct device *dev)
472{
473 config_t *config = dev->chip_info;
474 int do_aspm = 0;
475 int rp = root_port_number(dev);
476
477 switch (rp) {
478 case 1:
479 case 2:
480 case 3:
481 case 4:
482 /*
Martin Rothde7ed6f2014-12-07 14:58:18 -0700483 * Bits 31:28 of b0d28f0 0x32c register correspond to
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700484 * Root Ports 4:1.
485 */
486 do_aspm = !!(rpc.b0d28f0_32c & (1 << (28 + rp - 1)));
487 break;
488 case 5:
489 /*
Martin Rothde7ed6f2014-12-07 14:58:18 -0700490 * Bit 28 of b0d28f4 0x32c register correspond to
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700491 * Root Ports 4:1.
492 */
493 do_aspm = !!(rpc.b0d28f4_32c & (1 << 28));
494 break;
495 case 6:
496 /*
Martin Rothde7ed6f2014-12-07 14:58:18 -0700497 * Bit 28 of b0d28f5 0x32c register correspond to
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700498 * Root Ports 4:1.
499 */
500 do_aspm = !!(rpc.b0d28f5_32c & (1 << 28));
501 break;
502 }
503
504 /* Allow ASPM to be forced on in devicetree */
505 if (config && (config->pcie_port_force_aspm & (1 << (rp - 1))))
506 do_aspm = 1;
507
508 printk(BIOS_DEBUG, "PCIe Root Port %d ASPM is %sabled\n",
509 rp, do_aspm ? "en" : "dis");
510
511 if (do_aspm) {
512 /* Set ASPM bits in MPC2 register. */
513 pcie_update_cfg(dev, 0xd4, ~(0x3 << 2), (1 << 4) | (0x2 << 2));
514
515 /* Set unique clock exit latency in MPC register. */
516 pcie_update_cfg(dev, 0xd8, ~(0x7 << 18), (0x7 << 18));
517
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700518 switch (rp) {
519 case 1:
520 pcie_add_0x0202000_iobp(0xe9002440);
521 break;
522 case 2:
523 pcie_add_0x0202000_iobp(0xe9002640);
524 break;
525 case 3:
526 pcie_add_0x0202000_iobp(0xe9000840);
527 break;
528 case 4:
529 pcie_add_0x0202000_iobp(0xe9000a40);
530 break;
531 case 5:
532 pcie_add_0x0202000_iobp(0xe9000c40);
533 pcie_add_0x0202000_iobp(0xe9000e40);
534 pcie_add_0x0202000_iobp(0xe9001040);
535 pcie_add_0x0202000_iobp(0xe9001240);
536 break;
537 case 6:
538 /* Update IOBP based on lane ownership. */
539 if (rpc.pin_ownership & (1 << 4))
540 pcie_add_0x0202000_iobp(0xea002040);
541 if (rpc.pin_ownership & (1 << 5))
542 pcie_add_0x0202000_iobp(0xea002240);
543 if (rpc.pin_ownership & (1 << 6))
544 pcie_add_0x0202000_iobp(0xea002440);
545 if (rpc.pin_ownership & (1 << 7))
546 pcie_add_0x0202000_iobp(0xea002640);
547 break;
548 }
549
550 pcie_update_cfg(dev, 0x338, ~(1 << 26), 0);
551 }
552
Kenji Chenc373f502014-09-26 02:48:16 +0800553 /* Enable LTR in Root Port. Disable OBFF. */
554 pcie_update_cfg(dev, 0x64, ~(1 << 11) & ~(3 << 18), (1 << 11));
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700555 pcie_update_cfg(dev, 0x68, ~(1 << 10), (1 << 10));
556
557 pcie_update_cfg(dev, 0x318, ~(0xffff << 16), (0x1414 << 16));
558
559 /* Set L1 exit latency in LCAP register. */
560 if (!do_aspm && (pci_read_config8(dev, 0xf5) & 0x1))
561 pcie_update_cfg(dev, 0x4c, ~(0x7 << 15), (0x4 << 15));
562 else
563 pcie_update_cfg(dev, 0x4c, ~(0x7 << 15), (0x2 << 15));
564
565 pcie_update_cfg(dev, 0x314, 0x0, 0x743a361b);
566
567 /* Set Common Clock Exit Latency in MPC register. */
568 pcie_update_cfg(dev, 0xd8, ~(0x7 << 15), (0x3 << 15));
569
Duncan Laurieb14c0672015-02-02 21:00:33 -0800570 pcie_update_cfg(dev, 0x33c, ~0x00ffffff, 0x854d74);
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700571
Martin Rothde7ed6f2014-12-07 14:58:18 -0700572 /* Set Invalid Receive Range Check Enable in MPC register. */
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700573 pcie_update_cfg(dev, 0xd8, ~0, (1 << 25));
574
Kane Chen4fef5a22014-08-27 15:21:32 -0700575 pcie_update_cfg8(dev, 0xf5, 0x0f, 0);
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700576
Kenji Chen94fea492014-09-30 14:17:35 +0800577 /* Set AER Extended Cap ID to 01h and Next Cap Pointer to 200h. */
Kenji Chen8ef55ee2014-09-25 21:34:42 +0800578 pcie_update_cfg(dev, 0x100, ~(1 << 29) & ~0xfffff, (1 << 29) | 0x10001);
579
Kenji Chen94fea492014-09-30 14:17:35 +0800580 /* Set L1 Sub-State Cap ID to 1Eh and Next Cap Pointer to None. */
581 pcie_update_cfg(dev, 0x200, ~0xffff, 0x001e);
582
Kenji Chenc373f502014-09-26 02:48:16 +0800583 pcie_update_cfg(dev, 0x320, ~(3 << 20) & ~(7 << 6),
584 (1 << 20) | (3 << 6));
585 /* Enable Relaxed Order from Root Port. */
586 pcie_update_cfg(dev, 0x320, ~(3 << 23), (3 << 23));
587
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700588 if (rp == 1 || rp == 5 || rp == 6)
589 pcie_update_cfg8(dev, 0xf7, ~0xc, 0);
590
591 /* Set EOI forwarding disable. */
592 pcie_update_cfg(dev, 0xd4, ~0, (1 << 1));
593
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700594 /* Read and write back write-once capability registers. */
595 pcie_update_cfg(dev, 0x34, ~0, 0);
596 pcie_update_cfg(dev, 0x40, ~0, 0);
597 pcie_update_cfg(dev, 0x80, ~0, 0);
598 pcie_update_cfg(dev, 0x90, ~0, 0);
599}
600
601static void pch_pcie_init(struct device *dev)
602{
603 u16 reg16;
604 u32 reg32;
605
606 printk(BIOS_DEBUG, "Initializing PCH PCIe bridge.\n");
607
608 /* Enable SERR */
609 reg32 = pci_read_config32(dev, PCI_COMMAND);
610 reg32 |= PCI_COMMAND_SERR;
611 pci_write_config32(dev, PCI_COMMAND, reg32);
612
613 /* Enable Bus Master */
614 reg32 = pci_read_config32(dev, PCI_COMMAND);
615 reg32 |= PCI_COMMAND_MASTER;
616 pci_write_config32(dev, PCI_COMMAND, reg32);
617
618 /* Set Cache Line Size to 0x10 */
619 pci_write_config8(dev, 0x0c, 0x10);
620
621 reg16 = pci_read_config16(dev, 0x3e);
622 reg16 &= ~(1 << 0); /* disable parity error response */
623 reg16 |= (1 << 2); /* ISA enable */
624 pci_write_config16(dev, 0x3e, reg16);
625
626#ifdef EVEN_MORE_DEBUG
627 reg32 = pci_read_config32(dev, 0x20);
628 printk(BIOS_SPEW, " MBL = 0x%08x\n", reg32);
629 reg32 = pci_read_config32(dev, 0x24);
630 printk(BIOS_SPEW, " PMBL = 0x%08x\n", reg32);
631 reg32 = pci_read_config32(dev, 0x28);
632 printk(BIOS_SPEW, " PMBU32 = 0x%08x\n", reg32);
633 reg32 = pci_read_config32(dev, 0x2c);
634 printk(BIOS_SPEW, " PMLU32 = 0x%08x\n", reg32);
635#endif
636
637 /* Clear errors in status registers */
638 reg16 = pci_read_config16(dev, 0x06);
639 pci_write_config16(dev, 0x06, reg16);
640 reg16 = pci_read_config16(dev, 0x1e);
641 pci_write_config16(dev, 0x1e, reg16);
642}
643
644static void pch_pcie_enable(device_t dev)
645{
646 /* Add this device to the root port config structure. */
647 root_port_init_config(dev);
648
649 /* Check to see if this Root Port should be disabled. */
650 root_port_check_disable(dev);
651
652 /* Power Management init before enumeration */
653 if (dev->enabled)
654 pch_pcie_early(dev);
655
656 /*
657 * When processing the last PCIe root port we can now
658 * update the Root Port Function Number and Hide register.
659 */
660 if (root_port_is_last(dev))
661 root_port_commit_config();
662}
663
664static void pcie_set_subsystem(device_t dev, unsigned vendor, unsigned device)
665{
666 /* NOTE: This is not the default position! */
667 if (!vendor || !device)
668 pci_write_config32(dev, 0x94, pci_read_config32(dev, 0));
669 else
670 pci_write_config32(dev, 0x94, (device << 16) | vendor);
671}
672
Kenji Chenb71d9b82014-10-10 03:08:15 +0800673static void pcie_set_L1_ss_max_latency(device_t dev, unsigned int off)
674{
675 /* Set max snoop and non-snoop latency for Broadwell */
676 pci_mmio_write_config32(dev, off, 0x10031003);
677}
678
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700679static struct pci_operations pcie_ops = {
680 .set_subsystem = pcie_set_subsystem,
Kenji Chenb71d9b82014-10-10 03:08:15 +0800681 .set_L1_ss_latency = pcie_set_L1_ss_max_latency,
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700682};
683
684static struct device_operations device_ops = {
685 .read_resources = pci_bus_read_resources,
686 .set_resources = pci_dev_set_resources,
687 .enable_resources = pci_bus_enable_resources,
688 .init = pch_pcie_init,
689 .enable = pch_pcie_enable,
690 .scan_bus = pciexp_scan_bridge,
691 .ops_pci = &pcie_ops,
692};
693
694static const unsigned short pcie_device_ids[] = {
695 /* Lynxpoint-LP */
696 0x9c10, 0x9c12, 0x9c14, 0x9c16, 0x9c18, 0x9c1a,
697 /* WildcatPoint */
698 0x9c90, 0x9c92, 0x9c94, 0x9c96, 0x9c98, 0x9c9a, 0x2448,
699 0
700};
701
702static const struct pci_driver pch_pcie __pci_driver = {
703 .ops = &device_ops,
704 .vendor = PCI_VENDOR_ID_INTEL,
705 .devices = pcie_device_ids,
706};