blob: f63f6d527c4d8e7c321a7139d76f205c9361d040 [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>
27#include <broadwell/gpio.h>
28#include <broadwell/lpc.h>
29#include <broadwell/iobp.h>
30#include <broadwell/pch.h>
31#include <broadwell/pci_devs.h>
32#include <broadwell/rcba.h>
33#include <chip.h>
Kane Chen4fef5a22014-08-27 15:21:32 -070034#include <broadwell/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
102static void root_port_init_config(device_t dev)
103{
104 int rp;
105
106 if (root_port_is_first(dev)) {
107 rpc.orig_rpfn = RCBA32(RPFN);
108 rpc.new_rpfn = rpc.orig_rpfn;
109 rpc.num_ports = NUM_ROOT_PORTS;
110 rpc.gbe_port = -1;
Kane Chen4fef5a22014-08-27 15:21:32 -0700111 pcie_update_cfg8(dev, 0xf5, 0xa, 0x5);
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700112
113 rpc.pin_ownership = pci_read_config32(dev, 0x410);
114 root_port_config_update_gbe_port();
115
Kane Chen642e5982014-09-09 15:53:09 -0700116 pcie_update_cfg8(dev, 0xe2, ~(3 << 4), (3 << 4));
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700117 if (dev->chip_info != NULL) {
118 config_t *config = dev->chip_info;
119 rpc.coalesce = config->pcie_port_coalesce;
120 }
121 }
122
123 rp = root_port_number(dev);
124 if (rp > rpc.num_ports) {
125 printk(BIOS_ERR, "Found Root Port %d, expecting %d\n",
126 rp, rpc.num_ports);
127 return;
128 }
129
130 /* Read the fuse configuration and pin ownership. */
131 switch (rp) {
132 case 1:
133 rpc.strpfusecfg1 = pci_read_config32(dev, 0xfc);
134 rpc.b0d28f0_32c = pci_read_config32(dev, 0x32c);
135 break;
136 case 5:
137 rpc.strpfusecfg2 = pci_read_config32(dev, 0xfc);
138 rpc.b0d28f4_32c = pci_read_config32(dev, 0x32c);
139 break;
140 case 6:
141 rpc.b0d28f5_32c = pci_read_config32(dev, 0x32c);
142 rpc.strpfusecfg3 = pci_read_config32(dev, 0xfc);
143 break;
144 default:
145 break;
146 }
147
Kane Chen46134722014-08-28 17:05:06 -0700148 pcie_update_cfg(dev, 0x418, 0, 0x02000430);
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700149 /* Cache pci device. */
150 rpc.ports[rp - 1] = dev;
151}
152
153/* Update devicetree with new Root Port function number assignment */
154static void pch_pcie_device_set_func(int index, int pci_func)
155{
156 device_t dev;
157 unsigned new_devfn;
158
159 dev = rpc.ports[index];
160
161 /* Set the new PCI function field for this Root Port. */
162 rpc.new_rpfn &= ~RPFN_FNMASK(index);
163 rpc.new_rpfn |= RPFN_FNSET(index, pci_func);
164
165 /* Determine the new devfn for this port */
166 new_devfn = PCI_DEVFN(PCH_DEV_SLOT_PCIE, pci_func);
167
168 if (dev->path.pci.devfn != new_devfn) {
169 printk(BIOS_DEBUG,
170 "PCH: PCIe map %02x.%1x -> %02x.%1x\n",
171 PCI_SLOT(dev->path.pci.devfn),
172 PCI_FUNC(dev->path.pci.devfn),
173 PCI_SLOT(new_devfn), PCI_FUNC(new_devfn));
174
175 dev->path.pci.devfn = new_devfn;
176 }
177}
178
179static void pcie_enable_clock_gating(void)
180{
181 int i;
182 int enabled_ports = 0;
Kane Chen4fef5a22014-08-27 15:21:32 -0700183 int is_broadwell = !!(cpu_family_model() == BROADWELL_FAMILY_ULT);
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700184
185 for (i = 0; i < rpc.num_ports; i++) {
186 device_t dev;
187 int rp;
188
189 dev = rpc.ports[i];
190 rp = root_port_number(dev);
191
192 if (!dev->enabled) {
193 /* Configure shared resource clock gating. */
194 if (rp == 1 || rp == 5 || rp == 6)
195 pcie_update_cfg8(dev, 0xe1, 0xc3, 0x3c);
196
197 pcie_update_cfg8(dev, 0xe2, ~(3 << 4), (3 << 4));
198 pcie_update_cfg(dev, 0x420, ~(1 << 31), (1 << 31));
199
200 /* Per-Port CLKREQ# handling. */
201 if (gpio_is_native(18 + rp - 1))
202 pcie_update_cfg(dev, 0x420, ~0, (3 << 29));
203
204 /* Enable static clock gating. */
205 if (rp == 1 && !rpc.ports[1]->enabled &&
206 !rpc.ports[2]->enabled && !rpc.ports[3]->enabled) {
207 pcie_update_cfg8(dev, 0xe2, ~1, 1);
208 pcie_update_cfg8(dev, 0xe1, 0x7f, 0x80);
209 } else if (rp == 5 || rp == 6) {
210 pcie_update_cfg8(dev, 0xe2, ~1, 1);
211 pcie_update_cfg8(dev, 0xe1, 0x7f, 0x80);
212 }
213 continue;
214 }
215
216 enabled_ports++;
217
218 /* Enable dynamic clock gating. */
219 pcie_update_cfg8(dev, 0xe1, 0xfc, 0x03);
220 pcie_update_cfg8(dev, 0xe2, ~(1 << 6), (1 << 6));
221 pcie_update_cfg8(dev, 0xe8, ~(3 << 2), (2 << 2));
222
223 /* Update PECR1 register. */
Kane Chen4fef5a22014-08-27 15:21:32 -0700224 pcie_update_cfg8(dev, 0xe8, ~0, 3);
225 if (is_broadwell) {
226 pcie_update_cfg(dev, 0x324, ~((1 << 5) | (1 << 14)),
227 ((1 << 5) | (1 << 14)));
228 } else {
229 pcie_update_cfg(dev, 0x324, ~(1 << 5), (1 << 5));
230 }
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700231 /* Per-Port CLKREQ# handling. */
232 if (gpio_is_native(18 + rp - 1))
233 pcie_update_cfg(dev, 0x420, ~0, (3 << 29));
234
235 /* Configure shared resource clock gating. */
236 if (rp == 1 || rp == 5 || rp == 6)
237 pcie_update_cfg8(dev, 0xe1, 0xc3, 0x3c);
Duncan Laurie446fb8e2014-08-08 09:59:43 -0700238
239 /* CLKREQ# VR Idle Enable */
240 RCBA32_OR(0x2b1c, (1 << (16 + i)));
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700241 }
242
243 if (!enabled_ports)
244 pcie_update_cfg8(rpc.ports[0], 0xe1, ~(1 << 6), (1 << 6));
245}
246
247static void root_port_commit_config(void)
248{
249 int i;
250
251 /* If the first root port is disabled the coalesce ports. */
252 if (!rpc.ports[0]->enabled)
253 rpc.coalesce = 1;
254
255 /* Perform clock gating configuration. */
256 pcie_enable_clock_gating();
257
258 for (i = 0; i < rpc.num_ports; i++) {
259 device_t dev;
260 u32 reg32;
261
262 dev = rpc.ports[i];
263
264 if (dev == NULL) {
265 printk(BIOS_ERR, "Root Port %d device is NULL?\n", i+1);
266 continue;
267 }
268
269 if (dev->enabled)
270 continue;
271
272 printk(BIOS_DEBUG, "%s: Disabling device\n", dev_path(dev));
273
274 /* Ensure memory, io, and bus master are all disabled */
275 reg32 = pci_read_config32(dev, PCI_COMMAND);
276 reg32 &= ~(PCI_COMMAND_MASTER |
277 PCI_COMMAND_MEMORY | PCI_COMMAND_IO);
278 pci_write_config32(dev, PCI_COMMAND, reg32);
279
280 /* Disable this device if possible */
281 pch_disable_devfn(dev);
282 }
283
284 if (rpc.coalesce) {
285 int current_func;
286
287 /* For all Root Ports N enabled ports get assigned the lower
288 * PCI function number. The disabled ones get upper PCI
289 * function numbers. */
290 current_func = 0;
291 for (i = 0; i < rpc.num_ports; i++) {
292 if (!rpc.ports[i]->enabled)
293 continue;
294 pch_pcie_device_set_func(i, current_func);
295 current_func++;
296 }
297
298 /* Allocate the disabled devices' PCI function number. */
299 for (i = 0; i < rpc.num_ports; i++) {
300 if (rpc.ports[i]->enabled)
301 continue;
302 pch_pcie_device_set_func(i, current_func);
303 current_func++;
304 }
305 }
306
307 printk(BIOS_SPEW, "PCH: RPFN 0x%08x -> 0x%08x\n",
308 rpc.orig_rpfn, rpc.new_rpfn);
309 RCBA32(RPFN) = rpc.new_rpfn;
310}
311
312static void root_port_mark_disable(device_t dev)
313{
314 /* Mark device as disabled. */
315 dev->enabled = 0;
316 /* Mark device to be hidden. */
317 rpc.new_rpfn |= RPFN_HIDE(PCI_FUNC(dev->path.pci.devfn));
318}
319
320static void root_port_check_disable(device_t dev)
321{
322 int rp;
323
324 /* Device already disabled. */
325 if (!dev->enabled) {
326 root_port_mark_disable(dev);
327 return;
328 }
329
330 rp = root_port_number(dev);
331
332 /* Is the GbE port mapped to this Root Port? */
333 if (rp == rpc.gbe_port) {
334 root_port_mark_disable(dev);
335 return;
336 }
337
338 /* Check Root Port Configuration. */
339 switch (rp) {
340 case 2:
341 /* Root Port 2 is disabled for all lane configurations
342 * but config 00b (4x1 links). */
343 if ((rpc.strpfusecfg1 >> 14) & 0x3) {
344 root_port_mark_disable(dev);
345 return;
346 }
347 break;
348 case 3:
349 /* Root Port 3 is disabled in config 11b (1x4 links). */
350 if (((rpc.strpfusecfg1 >> 14) & 0x3) == 0x3) {
351 root_port_mark_disable(dev);
352 return;
353 }
354 break;
355 case 4:
356 /* Root Port 4 is disabled in configs 11b (1x4 links)
357 * and 10b (2x2 links). */
358 if ((rpc.strpfusecfg1 >> 14) & 0x2) {
359 root_port_mark_disable(dev);
360 return;
361 }
362 break;
363 }
364
365 /* Check Pin Ownership. */
366 switch (rp) {
367 case 1:
368 /* Bit 0 is Root Port 1 ownership. */
369 if ((rpc.pin_ownership & 0x1) == 0) {
370 root_port_mark_disable(dev);
371 return;
372 }
373 break;
374 case 2:
375 /* Bit 2 is Root Port 2 ownership. */
376 if ((rpc.pin_ownership & 0x4) == 0) {
377 root_port_mark_disable(dev);
378 return;
379 }
380 break;
381 case 6:
382 /* Bits 7:4 are Root Port 6 pin-lane ownership. */
383 if ((rpc.pin_ownership & 0xf0) == 0) {
384 root_port_mark_disable(dev);
385 return;
386 }
387 break;
388 }
389}
390
391static void pcie_update_cfg8(device_t dev, int reg, u8 mask, u8 or)
392{
393 u8 reg8;
394
395 reg8 = pci_read_config8(dev, reg);
396 reg8 &= mask;
397 reg8 |= or;
398 pci_write_config8(dev, reg, reg8);
399}
400
401static void pcie_update_cfg(device_t dev, int reg, u32 mask, u32 or)
402{
403 u32 reg32;
404
405 reg32 = pci_read_config32(dev, reg);
406 reg32 &= mask;
407 reg32 |= or;
408 pci_write_config32(dev, reg, reg32);
409}
410
411static void pcie_add_0x0202000_iobp(u32 reg)
412{
413 u32 reg32;
414
415 reg32 = pch_iobp_read(reg);
416 reg32 += (0x2 << 16) | (0x2 << 8);
417 pch_iobp_write(reg, reg32);
418}
419
420static void pch_pcie_early(struct device *dev)
421{
422 config_t *config = dev->chip_info;
423 int do_aspm = 0;
424 int rp = root_port_number(dev);
425
426 switch (rp) {
427 case 1:
428 case 2:
429 case 3:
430 case 4:
431 /*
Martin Rothde7ed6f2014-12-07 14:58:18 -0700432 * Bits 31:28 of b0d28f0 0x32c register correspond to
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700433 * Root Ports 4:1.
434 */
435 do_aspm = !!(rpc.b0d28f0_32c & (1 << (28 + rp - 1)));
436 break;
437 case 5:
438 /*
Martin Rothde7ed6f2014-12-07 14:58:18 -0700439 * Bit 28 of b0d28f4 0x32c register correspond to
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700440 * Root Ports 4:1.
441 */
442 do_aspm = !!(rpc.b0d28f4_32c & (1 << 28));
443 break;
444 case 6:
445 /*
Martin Rothde7ed6f2014-12-07 14:58:18 -0700446 * Bit 28 of b0d28f5 0x32c register correspond to
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700447 * Root Ports 4:1.
448 */
449 do_aspm = !!(rpc.b0d28f5_32c & (1 << 28));
450 break;
451 }
452
453 /* Allow ASPM to be forced on in devicetree */
454 if (config && (config->pcie_port_force_aspm & (1 << (rp - 1))))
455 do_aspm = 1;
456
457 printk(BIOS_DEBUG, "PCIe Root Port %d ASPM is %sabled\n",
458 rp, do_aspm ? "en" : "dis");
459
460 if (do_aspm) {
461 /* Set ASPM bits in MPC2 register. */
462 pcie_update_cfg(dev, 0xd4, ~(0x3 << 2), (1 << 4) | (0x2 << 2));
463
464 /* Set unique clock exit latency in MPC register. */
465 pcie_update_cfg(dev, 0xd8, ~(0x7 << 18), (0x7 << 18));
466
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700467 switch (rp) {
468 case 1:
469 pcie_add_0x0202000_iobp(0xe9002440);
470 break;
471 case 2:
472 pcie_add_0x0202000_iobp(0xe9002640);
473 break;
474 case 3:
475 pcie_add_0x0202000_iobp(0xe9000840);
476 break;
477 case 4:
478 pcie_add_0x0202000_iobp(0xe9000a40);
479 break;
480 case 5:
481 pcie_add_0x0202000_iobp(0xe9000c40);
482 pcie_add_0x0202000_iobp(0xe9000e40);
483 pcie_add_0x0202000_iobp(0xe9001040);
484 pcie_add_0x0202000_iobp(0xe9001240);
485 break;
486 case 6:
487 /* Update IOBP based on lane ownership. */
488 if (rpc.pin_ownership & (1 << 4))
489 pcie_add_0x0202000_iobp(0xea002040);
490 if (rpc.pin_ownership & (1 << 5))
491 pcie_add_0x0202000_iobp(0xea002240);
492 if (rpc.pin_ownership & (1 << 6))
493 pcie_add_0x0202000_iobp(0xea002440);
494 if (rpc.pin_ownership & (1 << 7))
495 pcie_add_0x0202000_iobp(0xea002640);
496 break;
497 }
498
499 pcie_update_cfg(dev, 0x338, ~(1 << 26), 0);
500 }
501
502 /* Enable LTR in Root Port. */
503 pcie_update_cfg(dev, 0x64, ~(1 << 11), (1 << 11));
504 pcie_update_cfg(dev, 0x68, ~(1 << 10), (1 << 10));
505
506 pcie_update_cfg(dev, 0x318, ~(0xffff << 16), (0x1414 << 16));
507
508 /* Set L1 exit latency in LCAP register. */
509 if (!do_aspm && (pci_read_config8(dev, 0xf5) & 0x1))
510 pcie_update_cfg(dev, 0x4c, ~(0x7 << 15), (0x4 << 15));
511 else
512 pcie_update_cfg(dev, 0x4c, ~(0x7 << 15), (0x2 << 15));
513
514 pcie_update_cfg(dev, 0x314, 0x0, 0x743a361b);
515
516 /* Set Common Clock Exit Latency in MPC register. */
517 pcie_update_cfg(dev, 0xd8, ~(0x7 << 15), (0x3 << 15));
518
519 pcie_update_cfg(dev, 0x33c, ~0x00ffffff, 0x854c74);
520
Martin Rothde7ed6f2014-12-07 14:58:18 -0700521 /* Set Invalid Receive Range Check Enable in MPC register. */
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700522 pcie_update_cfg(dev, 0xd8, ~0, (1 << 25));
523
Kane Chen4fef5a22014-08-27 15:21:32 -0700524 pcie_update_cfg8(dev, 0xf5, 0x0f, 0);
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700525
526 if (rp == 1 || rp == 5 || rp == 6)
527 pcie_update_cfg8(dev, 0xf7, ~0xc, 0);
528
529 /* Set EOI forwarding disable. */
530 pcie_update_cfg(dev, 0xd4, ~0, (1 << 1));
531
532 /* Set something involving advanced error reporting. */
533 pcie_update_cfg(dev, 0x100, ~((1 << 20) - 1), 0x10001);
534 pcie_update_cfg(dev, 0x100, ~0, (1 << 29));
535
536 /* Read and write back write-once capability registers. */
537 pcie_update_cfg(dev, 0x34, ~0, 0);
538 pcie_update_cfg(dev, 0x40, ~0, 0);
539 pcie_update_cfg(dev, 0x80, ~0, 0);
540 pcie_update_cfg(dev, 0x90, ~0, 0);
541}
542
543static void pch_pcie_init(struct device *dev)
544{
545 u16 reg16;
546 u32 reg32;
547
548 printk(BIOS_DEBUG, "Initializing PCH PCIe bridge.\n");
549
550 /* Enable SERR */
551 reg32 = pci_read_config32(dev, PCI_COMMAND);
552 reg32 |= PCI_COMMAND_SERR;
553 pci_write_config32(dev, PCI_COMMAND, reg32);
554
555 /* Enable Bus Master */
556 reg32 = pci_read_config32(dev, PCI_COMMAND);
557 reg32 |= PCI_COMMAND_MASTER;
558 pci_write_config32(dev, PCI_COMMAND, reg32);
559
560 /* Set Cache Line Size to 0x10 */
561 pci_write_config8(dev, 0x0c, 0x10);
562
563 reg16 = pci_read_config16(dev, 0x3e);
564 reg16 &= ~(1 << 0); /* disable parity error response */
565 reg16 |= (1 << 2); /* ISA enable */
566 pci_write_config16(dev, 0x3e, reg16);
567
568#ifdef EVEN_MORE_DEBUG
569 reg32 = pci_read_config32(dev, 0x20);
570 printk(BIOS_SPEW, " MBL = 0x%08x\n", reg32);
571 reg32 = pci_read_config32(dev, 0x24);
572 printk(BIOS_SPEW, " PMBL = 0x%08x\n", reg32);
573 reg32 = pci_read_config32(dev, 0x28);
574 printk(BIOS_SPEW, " PMBU32 = 0x%08x\n", reg32);
575 reg32 = pci_read_config32(dev, 0x2c);
576 printk(BIOS_SPEW, " PMLU32 = 0x%08x\n", reg32);
577#endif
578
579 /* Clear errors in status registers */
580 reg16 = pci_read_config16(dev, 0x06);
581 pci_write_config16(dev, 0x06, reg16);
582 reg16 = pci_read_config16(dev, 0x1e);
583 pci_write_config16(dev, 0x1e, reg16);
584}
585
586static void pch_pcie_enable(device_t dev)
587{
588 /* Add this device to the root port config structure. */
589 root_port_init_config(dev);
590
591 /* Check to see if this Root Port should be disabled. */
592 root_port_check_disable(dev);
593
594 /* Power Management init before enumeration */
595 if (dev->enabled)
596 pch_pcie_early(dev);
597
598 /*
599 * When processing the last PCIe root port we can now
600 * update the Root Port Function Number and Hide register.
601 */
602 if (root_port_is_last(dev))
603 root_port_commit_config();
604}
605
606static void pcie_set_subsystem(device_t dev, unsigned vendor, unsigned device)
607{
608 /* NOTE: This is not the default position! */
609 if (!vendor || !device)
610 pci_write_config32(dev, 0x94, pci_read_config32(dev, 0));
611 else
612 pci_write_config32(dev, 0x94, (device << 16) | vendor);
613}
614
615static struct pci_operations pcie_ops = {
616 .set_subsystem = pcie_set_subsystem,
617};
618
619static struct device_operations device_ops = {
620 .read_resources = pci_bus_read_resources,
621 .set_resources = pci_dev_set_resources,
622 .enable_resources = pci_bus_enable_resources,
623 .init = pch_pcie_init,
624 .enable = pch_pcie_enable,
625 .scan_bus = pciexp_scan_bridge,
626 .ops_pci = &pcie_ops,
627};
628
629static const unsigned short pcie_device_ids[] = {
630 /* Lynxpoint-LP */
631 0x9c10, 0x9c12, 0x9c14, 0x9c16, 0x9c18, 0x9c1a,
632 /* WildcatPoint */
633 0x9c90, 0x9c92, 0x9c94, 0x9c96, 0x9c98, 0x9c9a, 0x2448,
634 0
635};
636
637static const struct pci_driver pch_pcie __pci_driver = {
638 .ops = &device_ops,
639 .vendor = PCI_VENDOR_ID_INTEL,
640 .devices = pcie_device_ids,
641};