blob: bb237be21f2fc5ab2c815d073f5eb5c75830b857 [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.
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_def.h>
26#include <device/pci_ids.h>
Julius Werner4ee4bd52014-10-20 13:46:39 -070027#include <soc/gpio.h>
28#include <soc/lpc.h>
29#include <soc/iobp.h>
30#include <soc/pch.h>
31#include <soc/pci_devs.h>
32#include <soc/rcba.h>
33#include <soc/intel/broadwell/chip.h>
34#include <soc/cpu.h>
Duncan Lauriec88c54c2014-04-30 16:36:13 -070035
36static void pcie_update_cfg8(device_t dev, int reg, u8 mask, u8 or);
37static void pcie_update_cfg(device_t dev, int reg, u32 mask, u32 or);
38
39/* Low Power variant has 6 root ports. */
40#define NUM_ROOT_PORTS 6
41
42struct root_port_config {
43 /* RPFN is a write-once register so keep a copy until it is written */
44 u32 orig_rpfn;
45 u32 new_rpfn;
46 u32 pin_ownership;
47 u32 strpfusecfg1;
48 u32 strpfusecfg2;
49 u32 strpfusecfg3;
50 u32 b0d28f0_32c;
51 u32 b0d28f4_32c;
52 u32 b0d28f5_32c;
53 int coalesce;
54 int gbe_port;
55 int num_ports;
56 device_t ports[NUM_ROOT_PORTS];
57};
58
59static struct root_port_config rpc;
60
61static inline int root_port_is_first(device_t dev)
62{
63 return PCI_FUNC(dev->path.pci.devfn) == 0;
64}
65
66static inline int root_port_is_last(device_t dev)
67{
68 return PCI_FUNC(dev->path.pci.devfn) == (rpc.num_ports - 1);
69}
70
71/* Root ports are numbered 1..N in the documentation. */
72static inline int root_port_number(device_t dev)
73{
74 return PCI_FUNC(dev->path.pci.devfn) + 1;
75}
76
77static void root_port_config_update_gbe_port(void)
78{
79 /* Is the Gbe Port enabled? */
80 if (!((rpc.strpfusecfg1 >> 19) & 1))
81 return;
82
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}
101
Kenji Chen87d4a202014-09-24 01:18:26 +0800102static void pcie_iosf_port_grant_count(device_t dev)
103{
104 u8 update_val;
105 u32 rpcd = (pci_read_config32(dev, 0xfc) > 14) & 0x3;
106
107 switch (rpcd) {
108 case 1:
109 case 3:
110 update_val = 0x02;
111 break;
112 case 2:
113 update_val = 0x22;
114 break;
115 default:
116 update_val = 0x00;
117 break;
118 }
119
120 RCBA32(0x103C) = (RCBA32(0x103C) & (~0xff)) | update_val;
121}
122
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700123static void root_port_init_config(device_t dev)
124{
125 int rp;
Kenji Chene383feb2014-09-26 03:14:57 +0800126 u32 data;
127 u8 resp, id;
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700128
129 if (root_port_is_first(dev)) {
130 rpc.orig_rpfn = RCBA32(RPFN);
131 rpc.new_rpfn = rpc.orig_rpfn;
132 rpc.num_ports = NUM_ROOT_PORTS;
133 rpc.gbe_port = -1;
Kenji Chen87d4a202014-09-24 01:18:26 +0800134 /* RP0 f5[3:0] = 0101b*/
135 pcie_update_cfg8(dev, 0xf5, ~0xa, 0x5);
136
137 pcie_iosf_port_grant_count(dev);
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700138
139 rpc.pin_ownership = pci_read_config32(dev, 0x410);
140 root_port_config_update_gbe_port();
141
Kane Chen642e5982014-09-09 15:53:09 -0700142 pcie_update_cfg8(dev, 0xe2, ~(3 << 4), (3 << 4));
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700143 if (dev->chip_info != NULL) {
144 config_t *config = dev->chip_info;
145 rpc.coalesce = config->pcie_port_coalesce;
146 }
147 }
148
149 rp = root_port_number(dev);
150 if (rp > rpc.num_ports) {
151 printk(BIOS_ERR, "Found Root Port %d, expecting %d\n",
152 rp, rpc.num_ports);
153 return;
154 }
155
156 /* Read the fuse configuration and pin ownership. */
157 switch (rp) {
158 case 1:
159 rpc.strpfusecfg1 = pci_read_config32(dev, 0xfc);
160 rpc.b0d28f0_32c = pci_read_config32(dev, 0x32c);
161 break;
162 case 5:
163 rpc.strpfusecfg2 = pci_read_config32(dev, 0xfc);
164 rpc.b0d28f4_32c = pci_read_config32(dev, 0x32c);
165 break;
166 case 6:
167 rpc.b0d28f5_32c = pci_read_config32(dev, 0x32c);
168 rpc.strpfusecfg3 = pci_read_config32(dev, 0xfc);
169 break;
170 default:
171 break;
172 }
173
Kane Chen46134722014-08-28 17:05:06 -0700174 pcie_update_cfg(dev, 0x418, 0, 0x02000430);
Kenji Chene383feb2014-09-26 03:14:57 +0800175
Kenji Chene383feb2014-09-26 03:14:57 +0800176 if (root_port_is_first(dev)) {
Kenji Chene8f36642014-10-04 02:59:06 +0800177 /*
178 * set RP0 PCICFG E2h[5:4] = 11b and E1h[6] = 1
179 * before configuring ASPM
180 */
Kenji Chene383feb2014-09-26 03:14:57 +0800181 id = 0xe0 + (u8)(RCBA32(RPFN) & 0x07);
182 pch_iobp_exec(0xE00000E0, IOBP_PCICFG_READ, id, &data, &resp);
Kenji Chene8f36642014-10-04 02:59:06 +0800183 data |= ((0x30 << 16) | (0x40 << 8));
Kenji Chene383feb2014-09-26 03:14:57 +0800184 pch_iobp_exec(0xE00000E0, IOBP_PCICFG_WRITE, id, &data, &resp);
185 }
186
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700187 /* Cache pci device. */
188 rpc.ports[rp - 1] = dev;
189}
190
191/* Update devicetree with new Root Port function number assignment */
192static void pch_pcie_device_set_func(int index, int pci_func)
193{
194 device_t dev;
195 unsigned new_devfn;
196
197 dev = rpc.ports[index];
198
199 /* Set the new PCI function field for this Root Port. */
200 rpc.new_rpfn &= ~RPFN_FNMASK(index);
201 rpc.new_rpfn |= RPFN_FNSET(index, pci_func);
202
203 /* Determine the new devfn for this port */
204 new_devfn = PCI_DEVFN(PCH_DEV_SLOT_PCIE, pci_func);
205
206 if (dev->path.pci.devfn != new_devfn) {
207 printk(BIOS_DEBUG,
208 "PCH: PCIe map %02x.%1x -> %02x.%1x\n",
209 PCI_SLOT(dev->path.pci.devfn),
210 PCI_FUNC(dev->path.pci.devfn),
211 PCI_SLOT(new_devfn), PCI_FUNC(new_devfn));
212
213 dev->path.pci.devfn = new_devfn;
214 }
215}
216
217static void pcie_enable_clock_gating(void)
218{
219 int i;
220 int enabled_ports = 0;
Kane Chen4fef5a22014-08-27 15:21:32 -0700221 int is_broadwell = !!(cpu_family_model() == BROADWELL_FAMILY_ULT);
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700222
223 for (i = 0; i < rpc.num_ports; i++) {
224 device_t dev;
225 int rp;
226
227 dev = rpc.ports[i];
228 rp = root_port_number(dev);
229
230 if (!dev->enabled) {
231 /* Configure shared resource clock gating. */
232 if (rp == 1 || rp == 5 || rp == 6)
233 pcie_update_cfg8(dev, 0xe1, 0xc3, 0x3c);
234
235 pcie_update_cfg8(dev, 0xe2, ~(3 << 4), (3 << 4));
236 pcie_update_cfg(dev, 0x420, ~(1 << 31), (1 << 31));
237
238 /* Per-Port CLKREQ# handling. */
239 if (gpio_is_native(18 + rp - 1))
240 pcie_update_cfg(dev, 0x420, ~0, (3 << 29));
241
242 /* Enable static clock gating. */
243 if (rp == 1 && !rpc.ports[1]->enabled &&
244 !rpc.ports[2]->enabled && !rpc.ports[3]->enabled) {
245 pcie_update_cfg8(dev, 0xe2, ~1, 1);
246 pcie_update_cfg8(dev, 0xe1, 0x7f, 0x80);
247 } else if (rp == 5 || rp == 6) {
248 pcie_update_cfg8(dev, 0xe2, ~1, 1);
249 pcie_update_cfg8(dev, 0xe1, 0x7f, 0x80);
250 }
251 continue;
252 }
253
254 enabled_ports++;
255
256 /* Enable dynamic clock gating. */
257 pcie_update_cfg8(dev, 0xe1, 0xfc, 0x03);
258 pcie_update_cfg8(dev, 0xe2, ~(1 << 6), (1 << 6));
259 pcie_update_cfg8(dev, 0xe8, ~(3 << 2), (2 << 2));
260
261 /* Update PECR1 register. */
Kane Chen4fef5a22014-08-27 15:21:32 -0700262 pcie_update_cfg8(dev, 0xe8, ~0, 3);
263 if (is_broadwell) {
264 pcie_update_cfg(dev, 0x324, ~((1 << 5) | (1 << 14)),
265 ((1 << 5) | (1 << 14)));
266 } else {
267 pcie_update_cfg(dev, 0x324, ~(1 << 5), (1 << 5));
268 }
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700269 /* Per-Port CLKREQ# handling. */
270 if (gpio_is_native(18 + rp - 1))
Kenji Chene8f36642014-10-04 02:59:06 +0800271 /*
272 * In addition to D28Fx PCICFG 420h[30:29] = 11b,
273 * set 420h[17] = 0b and 420[0] = 1b for L1 SubState.
274 */
275 pcie_update_cfg(dev, 0x420, ~0x20000, (3 << 29) | 1);
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700276
277 /* Configure shared resource clock gating. */
278 if (rp == 1 || rp == 5 || rp == 6)
279 pcie_update_cfg8(dev, 0xe1, 0xc3, 0x3c);
Duncan Laurie446fb8e2014-08-08 09:59:43 -0700280
281 /* CLKREQ# VR Idle Enable */
282 RCBA32_OR(0x2b1c, (1 << (16 + i)));
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700283 }
284
285 if (!enabled_ports)
286 pcie_update_cfg8(rpc.ports[0], 0xe1, ~(1 << 6), (1 << 6));
287}
288
289static void root_port_commit_config(void)
290{
291 int i;
292
293 /* If the first root port is disabled the coalesce ports. */
294 if (!rpc.ports[0]->enabled)
295 rpc.coalesce = 1;
296
297 /* Perform clock gating configuration. */
298 pcie_enable_clock_gating();
299
300 for (i = 0; i < rpc.num_ports; i++) {
301 device_t dev;
302 u32 reg32;
303
304 dev = rpc.ports[i];
305
306 if (dev == NULL) {
307 printk(BIOS_ERR, "Root Port %d device is NULL?\n", i+1);
308 continue;
309 }
310
311 if (dev->enabled)
312 continue;
313
314 printk(BIOS_DEBUG, "%s: Disabling device\n", dev_path(dev));
315
316 /* Ensure memory, io, and bus master are all disabled */
317 reg32 = pci_read_config32(dev, PCI_COMMAND);
318 reg32 &= ~(PCI_COMMAND_MASTER |
319 PCI_COMMAND_MEMORY | PCI_COMMAND_IO);
320 pci_write_config32(dev, PCI_COMMAND, reg32);
321
322 /* Disable this device if possible */
323 pch_disable_devfn(dev);
324 }
325
326 if (rpc.coalesce) {
327 int current_func;
328
329 /* For all Root Ports N enabled ports get assigned the lower
330 * PCI function number. The disabled ones get upper PCI
331 * function numbers. */
332 current_func = 0;
333 for (i = 0; i < rpc.num_ports; i++) {
334 if (!rpc.ports[i]->enabled)
335 continue;
336 pch_pcie_device_set_func(i, current_func);
337 current_func++;
338 }
339
340 /* Allocate the disabled devices' PCI function number. */
341 for (i = 0; i < rpc.num_ports; i++) {
342 if (rpc.ports[i]->enabled)
343 continue;
344 pch_pcie_device_set_func(i, current_func);
345 current_func++;
346 }
347 }
348
349 printk(BIOS_SPEW, "PCH: RPFN 0x%08x -> 0x%08x\n",
350 rpc.orig_rpfn, rpc.new_rpfn);
351 RCBA32(RPFN) = rpc.new_rpfn;
352}
353
354static void root_port_mark_disable(device_t dev)
355{
356 /* Mark device as disabled. */
357 dev->enabled = 0;
358 /* Mark device to be hidden. */
359 rpc.new_rpfn |= RPFN_HIDE(PCI_FUNC(dev->path.pci.devfn));
360}
361
362static void root_port_check_disable(device_t dev)
363{
364 int rp;
365
366 /* Device already disabled. */
367 if (!dev->enabled) {
368 root_port_mark_disable(dev);
369 return;
370 }
371
372 rp = root_port_number(dev);
373
374 /* Is the GbE port mapped to this Root Port? */
375 if (rp == rpc.gbe_port) {
376 root_port_mark_disable(dev);
377 return;
378 }
379
380 /* Check Root Port Configuration. */
381 switch (rp) {
382 case 2:
383 /* Root Port 2 is disabled for all lane configurations
384 * but config 00b (4x1 links). */
385 if ((rpc.strpfusecfg1 >> 14) & 0x3) {
386 root_port_mark_disable(dev);
387 return;
388 }
389 break;
390 case 3:
391 /* Root Port 3 is disabled in config 11b (1x4 links). */
392 if (((rpc.strpfusecfg1 >> 14) & 0x3) == 0x3) {
393 root_port_mark_disable(dev);
394 return;
395 }
396 break;
397 case 4:
398 /* Root Port 4 is disabled in configs 11b (1x4 links)
399 * and 10b (2x2 links). */
400 if ((rpc.strpfusecfg1 >> 14) & 0x2) {
401 root_port_mark_disable(dev);
402 return;
403 }
404 break;
405 }
406
407 /* Check Pin Ownership. */
408 switch (rp) {
409 case 1:
410 /* Bit 0 is Root Port 1 ownership. */
411 if ((rpc.pin_ownership & 0x1) == 0) {
412 root_port_mark_disable(dev);
413 return;
414 }
415 break;
416 case 2:
417 /* Bit 2 is Root Port 2 ownership. */
418 if ((rpc.pin_ownership & 0x4) == 0) {
419 root_port_mark_disable(dev);
420 return;
421 }
422 break;
423 case 6:
424 /* Bits 7:4 are Root Port 6 pin-lane ownership. */
425 if ((rpc.pin_ownership & 0xf0) == 0) {
426 root_port_mark_disable(dev);
427 return;
428 }
429 break;
430 }
431}
432
433static void pcie_update_cfg8(device_t dev, int reg, u8 mask, u8 or)
434{
435 u8 reg8;
436
437 reg8 = pci_read_config8(dev, reg);
438 reg8 &= mask;
439 reg8 |= or;
440 pci_write_config8(dev, reg, reg8);
441}
442
443static void pcie_update_cfg(device_t dev, int reg, u32 mask, u32 or)
444{
445 u32 reg32;
446
447 reg32 = pci_read_config32(dev, reg);
448 reg32 &= mask;
449 reg32 |= or;
450 pci_write_config32(dev, reg, reg32);
451}
452
453static void pcie_add_0x0202000_iobp(u32 reg)
454{
455 u32 reg32;
456
457 reg32 = pch_iobp_read(reg);
458 reg32 += (0x2 << 16) | (0x2 << 8);
459 pch_iobp_write(reg, reg32);
460}
461
462static void pch_pcie_early(struct device *dev)
463{
464 config_t *config = dev->chip_info;
465 int do_aspm = 0;
466 int rp = root_port_number(dev);
467
468 switch (rp) {
469 case 1:
470 case 2:
471 case 3:
472 case 4:
473 /*
Martin Rothde7ed6f2014-12-07 14:58:18 -0700474 * Bits 31:28 of b0d28f0 0x32c register correspond to
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700475 * Root Ports 4:1.
476 */
477 do_aspm = !!(rpc.b0d28f0_32c & (1 << (28 + rp - 1)));
478 break;
479 case 5:
480 /*
Martin Rothde7ed6f2014-12-07 14:58:18 -0700481 * Bit 28 of b0d28f4 0x32c register correspond to
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700482 * Root Ports 4:1.
483 */
484 do_aspm = !!(rpc.b0d28f4_32c & (1 << 28));
485 break;
486 case 6:
487 /*
Martin Rothde7ed6f2014-12-07 14:58:18 -0700488 * Bit 28 of b0d28f5 0x32c register correspond to
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700489 * Root Ports 4:1.
490 */
491 do_aspm = !!(rpc.b0d28f5_32c & (1 << 28));
492 break;
493 }
494
495 /* Allow ASPM to be forced on in devicetree */
496 if (config && (config->pcie_port_force_aspm & (1 << (rp - 1))))
497 do_aspm = 1;
498
499 printk(BIOS_DEBUG, "PCIe Root Port %d ASPM is %sabled\n",
500 rp, do_aspm ? "en" : "dis");
501
502 if (do_aspm) {
503 /* Set ASPM bits in MPC2 register. */
504 pcie_update_cfg(dev, 0xd4, ~(0x3 << 2), (1 << 4) | (0x2 << 2));
505
506 /* Set unique clock exit latency in MPC register. */
507 pcie_update_cfg(dev, 0xd8, ~(0x7 << 18), (0x7 << 18));
508
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700509 switch (rp) {
510 case 1:
511 pcie_add_0x0202000_iobp(0xe9002440);
512 break;
513 case 2:
514 pcie_add_0x0202000_iobp(0xe9002640);
515 break;
516 case 3:
517 pcie_add_0x0202000_iobp(0xe9000840);
518 break;
519 case 4:
520 pcie_add_0x0202000_iobp(0xe9000a40);
521 break;
522 case 5:
523 pcie_add_0x0202000_iobp(0xe9000c40);
524 pcie_add_0x0202000_iobp(0xe9000e40);
525 pcie_add_0x0202000_iobp(0xe9001040);
526 pcie_add_0x0202000_iobp(0xe9001240);
527 break;
528 case 6:
529 /* Update IOBP based on lane ownership. */
530 if (rpc.pin_ownership & (1 << 4))
531 pcie_add_0x0202000_iobp(0xea002040);
532 if (rpc.pin_ownership & (1 << 5))
533 pcie_add_0x0202000_iobp(0xea002240);
534 if (rpc.pin_ownership & (1 << 6))
535 pcie_add_0x0202000_iobp(0xea002440);
536 if (rpc.pin_ownership & (1 << 7))
537 pcie_add_0x0202000_iobp(0xea002640);
538 break;
539 }
540
541 pcie_update_cfg(dev, 0x338, ~(1 << 26), 0);
542 }
543
Kenji Chenc373f502014-09-26 02:48:16 +0800544 /* Enable LTR in Root Port. Disable OBFF. */
545 pcie_update_cfg(dev, 0x64, ~(1 << 11) & ~(3 << 18), (1 << 11));
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700546 pcie_update_cfg(dev, 0x68, ~(1 << 10), (1 << 10));
547
548 pcie_update_cfg(dev, 0x318, ~(0xffff << 16), (0x1414 << 16));
549
550 /* Set L1 exit latency in LCAP register. */
551 if (!do_aspm && (pci_read_config8(dev, 0xf5) & 0x1))
552 pcie_update_cfg(dev, 0x4c, ~(0x7 << 15), (0x4 << 15));
553 else
554 pcie_update_cfg(dev, 0x4c, ~(0x7 << 15), (0x2 << 15));
555
556 pcie_update_cfg(dev, 0x314, 0x0, 0x743a361b);
557
558 /* Set Common Clock Exit Latency in MPC register. */
559 pcie_update_cfg(dev, 0xd8, ~(0x7 << 15), (0x3 << 15));
560
561 pcie_update_cfg(dev, 0x33c, ~0x00ffffff, 0x854c74);
562
Martin Rothde7ed6f2014-12-07 14:58:18 -0700563 /* Set Invalid Receive Range Check Enable in MPC register. */
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700564 pcie_update_cfg(dev, 0xd8, ~0, (1 << 25));
565
Kane Chen4fef5a22014-08-27 15:21:32 -0700566 pcie_update_cfg8(dev, 0xf5, 0x0f, 0);
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700567
Kenji Chen94fea492014-09-30 14:17:35 +0800568 /* Set AER Extended Cap ID to 01h and Next Cap Pointer to 200h. */
Kenji Chen8ef55ee2014-09-25 21:34:42 +0800569 pcie_update_cfg(dev, 0x100, ~(1 << 29) & ~0xfffff, (1 << 29) | 0x10001);
570
Kenji Chen94fea492014-09-30 14:17:35 +0800571 /* Set L1 Sub-State Cap ID to 1Eh and Next Cap Pointer to None. */
572 pcie_update_cfg(dev, 0x200, ~0xffff, 0x001e);
573
Kenji Chenc373f502014-09-26 02:48:16 +0800574 pcie_update_cfg(dev, 0x320, ~(3 << 20) & ~(7 << 6),
575 (1 << 20) | (3 << 6));
576 /* Enable Relaxed Order from Root Port. */
577 pcie_update_cfg(dev, 0x320, ~(3 << 23), (3 << 23));
578
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700579 if (rp == 1 || rp == 5 || rp == 6)
580 pcie_update_cfg8(dev, 0xf7, ~0xc, 0);
581
582 /* Set EOI forwarding disable. */
583 pcie_update_cfg(dev, 0xd4, ~0, (1 << 1));
584
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700585 /* Read and write back write-once capability registers. */
586 pcie_update_cfg(dev, 0x34, ~0, 0);
587 pcie_update_cfg(dev, 0x40, ~0, 0);
588 pcie_update_cfg(dev, 0x80, ~0, 0);
589 pcie_update_cfg(dev, 0x90, ~0, 0);
590}
591
592static void pch_pcie_init(struct device *dev)
593{
594 u16 reg16;
595 u32 reg32;
596
597 printk(BIOS_DEBUG, "Initializing PCH PCIe bridge.\n");
598
599 /* Enable SERR */
600 reg32 = pci_read_config32(dev, PCI_COMMAND);
601 reg32 |= PCI_COMMAND_SERR;
602 pci_write_config32(dev, PCI_COMMAND, reg32);
603
604 /* Enable Bus Master */
605 reg32 = pci_read_config32(dev, PCI_COMMAND);
606 reg32 |= PCI_COMMAND_MASTER;
607 pci_write_config32(dev, PCI_COMMAND, reg32);
608
609 /* Set Cache Line Size to 0x10 */
610 pci_write_config8(dev, 0x0c, 0x10);
611
612 reg16 = pci_read_config16(dev, 0x3e);
613 reg16 &= ~(1 << 0); /* disable parity error response */
614 reg16 |= (1 << 2); /* ISA enable */
615 pci_write_config16(dev, 0x3e, reg16);
616
617#ifdef EVEN_MORE_DEBUG
618 reg32 = pci_read_config32(dev, 0x20);
619 printk(BIOS_SPEW, " MBL = 0x%08x\n", reg32);
620 reg32 = pci_read_config32(dev, 0x24);
621 printk(BIOS_SPEW, " PMBL = 0x%08x\n", reg32);
622 reg32 = pci_read_config32(dev, 0x28);
623 printk(BIOS_SPEW, " PMBU32 = 0x%08x\n", reg32);
624 reg32 = pci_read_config32(dev, 0x2c);
625 printk(BIOS_SPEW, " PMLU32 = 0x%08x\n", reg32);
626#endif
627
628 /* Clear errors in status registers */
629 reg16 = pci_read_config16(dev, 0x06);
630 pci_write_config16(dev, 0x06, reg16);
631 reg16 = pci_read_config16(dev, 0x1e);
632 pci_write_config16(dev, 0x1e, reg16);
633}
634
635static void pch_pcie_enable(device_t dev)
636{
637 /* Add this device to the root port config structure. */
638 root_port_init_config(dev);
639
640 /* Check to see if this Root Port should be disabled. */
641 root_port_check_disable(dev);
642
643 /* Power Management init before enumeration */
644 if (dev->enabled)
645 pch_pcie_early(dev);
646
647 /*
648 * When processing the last PCIe root port we can now
649 * update the Root Port Function Number and Hide register.
650 */
651 if (root_port_is_last(dev))
652 root_port_commit_config();
653}
654
655static void pcie_set_subsystem(device_t dev, unsigned vendor, unsigned device)
656{
657 /* NOTE: This is not the default position! */
658 if (!vendor || !device)
659 pci_write_config32(dev, 0x94, pci_read_config32(dev, 0));
660 else
661 pci_write_config32(dev, 0x94, (device << 16) | vendor);
662}
663
Kenji Chenb71d9b82014-10-10 03:08:15 +0800664static void pcie_set_L1_ss_max_latency(device_t dev, unsigned int off)
665{
666 /* Set max snoop and non-snoop latency for Broadwell */
667 pci_mmio_write_config32(dev, off, 0x10031003);
668}
669
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700670static struct pci_operations pcie_ops = {
671 .set_subsystem = pcie_set_subsystem,
Kenji Chenb71d9b82014-10-10 03:08:15 +0800672 .set_L1_ss_latency = pcie_set_L1_ss_max_latency,
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700673};
674
675static struct device_operations device_ops = {
676 .read_resources = pci_bus_read_resources,
677 .set_resources = pci_dev_set_resources,
678 .enable_resources = pci_bus_enable_resources,
679 .init = pch_pcie_init,
680 .enable = pch_pcie_enable,
681 .scan_bus = pciexp_scan_bridge,
682 .ops_pci = &pcie_ops,
683};
684
685static const unsigned short pcie_device_ids[] = {
686 /* Lynxpoint-LP */
687 0x9c10, 0x9c12, 0x9c14, 0x9c16, 0x9c18, 0x9c1a,
688 /* WildcatPoint */
689 0x9c90, 0x9c92, 0x9c94, 0x9c96, 0x9c98, 0x9c9a, 0x2448,
690 0
691};
692
693static const struct pci_driver pch_pcie __pci_driver = {
694 .ops = &device_ops,
695 .vendor = PCI_VENDOR_ID_INTEL,
696 .devices = pcie_device_ids,
697};