blob: 3fd8d1e1c588540c679b1eb9092e809125342166 [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.
Aaron Durbin76c37002012-10-30 09:03:43 -050015 */
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_ids.h>
22#include "pch.h"
Patrick Rudolph273a8dc2016-02-06 18:07:59 +010023#include <southbridge/intel/common/gpio.h>
Aaron Durbin76c37002012-10-30 09:03:43 -050024
Aaron Durbinc0254e62013-06-20 01:20:30 -050025/* LynxPoint-LP has 6 root ports while non-LP has 8. */
26#define MAX_NUM_ROOT_PORTS 8
27#define H_NUM_ROOT_PORTS MAX_NUM_ROOT_PORTS
28#define LP_NUM_ROOT_PORTS (MAX_NUM_ROOT_PORTS - 2)
29
30struct root_port_config {
31 /* RPFN is a write-once register so keep a copy until it is written */
32 u32 orig_rpfn;
33 u32 new_rpfn;
34 u32 pin_ownership;
35 u32 strpfusecfg1;
36 u32 strpfusecfg2;
37 u32 strpfusecfg3;
Stefan Reinauerab365af2013-12-03 12:13:26 -080038 u32 b0d28f0_32c;
39 u32 b0d28f4_32c;
40 u32 b0d28f5_32c;
Aaron Durbinc0254e62013-06-20 01:20:30 -050041 int coalesce;
42 int gbe_port;
43 int num_ports;
44 device_t ports[MAX_NUM_ROOT_PORTS];
45};
46
47static struct root_port_config rpc;
48
49static inline int max_root_ports(void)
Aaron Durbin60f82082013-06-19 13:28:04 -050050{
Aaron Durbinc0254e62013-06-20 01:20:30 -050051 if (pch_is_lp())
52 return LP_NUM_ROOT_PORTS;
53 else
54 return H_NUM_ROOT_PORTS;
Aaron Durbin60f82082013-06-19 13:28:04 -050055}
56
Aaron Durbinc0254e62013-06-20 01:20:30 -050057static inline int root_port_is_first(device_t dev)
Aaron Durbin60f82082013-06-19 13:28:04 -050058{
Aaron Durbinc0254e62013-06-20 01:20:30 -050059 return PCI_FUNC(dev->path.pci.devfn) == 0;
60}
Aaron Durbin60f82082013-06-19 13:28:04 -050061
Aaron Durbinc0254e62013-06-20 01:20:30 -050062static inline int root_port_is_last(device_t dev)
63{
64 return PCI_FUNC(dev->path.pci.devfn) == (rpc.num_ports - 1);
65}
Aaron Durbin60f82082013-06-19 13:28:04 -050066
Aaron Durbinc0254e62013-06-20 01:20:30 -050067/* Root ports are numbered 1..N in the documentation. */
68static inline int root_port_number(device_t dev)
69{
70 return PCI_FUNC(dev->path.pci.devfn) + 1;
71}
Aaron Durbin60f82082013-06-19 13:28:04 -050072
Aaron Durbinc0254e62013-06-20 01:20:30 -050073static void root_port_config_update_gbe_port(void)
74{
75 /* Is the Gbe Port enabled? */
76 if (!((rpc.strpfusecfg1 >> 19) & 1))
77 return;
78
79 if (pch_is_lp()) {
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 } else {
98 /* Non-LP has 1:1 mapping with root ports. */
99 rpc.gbe_port = ((rpc.strpfusecfg1 >> 16) & 0x7) + 1;
100 }
101}
102
103static void root_port_init_config(device_t dev)
104{
105 int rp;
106
107 if (root_port_is_first(dev)) {
108 rpc.orig_rpfn = RCBA32(RPFN);
109 rpc.new_rpfn = rpc.orig_rpfn;
110 rpc.num_ports = max_root_ports();
111 rpc.gbe_port = -1;
112
113 rpc.pin_ownership = pci_read_config32(dev, 0x410);
114 root_port_config_update_gbe_port();
115
116 if (dev->chip_info != NULL) {
117 struct southbridge_intel_lynxpoint_config *config;
118
119 config = dev->chip_info;
120 rpc.coalesce = config->pcie_port_coalesce;
121 }
122 }
123
124 rp = root_port_number(dev);
125 if (rp > rpc.num_ports) {
126 printk(BIOS_ERR, "Found Root Port %d, expecting %d\n",
127 rp, rpc.num_ports);
128 return;
129 }
130
131 /* Read the fuse configuration and pin ownership. */
132 switch (rp) {
133 case 1:
134 rpc.strpfusecfg1 = pci_read_config32(dev, 0xfc);
Stefan Reinauerab365af2013-12-03 12:13:26 -0800135 rpc.b0d28f0_32c = pci_read_config32(dev, 0x32c);
Aaron Durbinc0254e62013-06-20 01:20:30 -0500136 break;
137 case 5:
138 rpc.strpfusecfg2 = pci_read_config32(dev, 0xfc);
Stefan Reinauerab365af2013-12-03 12:13:26 -0800139 rpc.b0d28f4_32c = pci_read_config32(dev, 0x32c);
Aaron Durbinc0254e62013-06-20 01:20:30 -0500140 break;
141 case 6:
Stefan Reinauerab365af2013-12-03 12:13:26 -0800142 rpc.b0d28f5_32c = pci_read_config32(dev, 0x32c);
Aaron Durbinc0254e62013-06-20 01:20:30 -0500143 rpc.strpfusecfg3 = pci_read_config32(dev, 0xfc);
144 break;
145 default:
146 break;
147 }
148
149 /* Cache pci device. */
150 rpc.ports[rp - 1] = dev;
Aaron Durbin60f82082013-06-19 13:28:04 -0500151}
152
153/* Update devicetree with new Root Port function number assignment */
Aaron Durbinc0254e62013-06-20 01:20:30 -0500154static void pch_pcie_device_set_func(int index, int pci_func)
Aaron Durbin60f82082013-06-19 13:28:04 -0500155{
156 device_t dev;
Aaron Durbinc0254e62013-06-20 01:20:30 -0500157 unsigned new_devfn;
Aaron Durbin60f82082013-06-19 13:28:04 -0500158
Aaron Durbinc0254e62013-06-20 01:20:30 -0500159 dev = rpc.ports[index];
Aaron Durbin60f82082013-06-19 13:28:04 -0500160
Aaron Durbinc0254e62013-06-20 01:20:30 -0500161 /* 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);
Aaron Durbin60f82082013-06-19 13:28:04 -0500164
Aaron Durbinc0254e62013-06-20 01:20:30 -0500165 /* Determine the new devfn for this port */
166 new_devfn = PCI_DEVFN(PCH_PCIE_DEV_SLOT, pci_func);
Aaron Durbin60f82082013-06-19 13:28:04 -0500167
Aaron Durbinc0254e62013-06-20 01:20:30 -0500168 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));
Aaron Durbin60f82082013-06-19 13:28:04 -0500174
Aaron Durbinc0254e62013-06-20 01:20:30 -0500175 dev->path.pci.devfn = new_devfn;
Aaron Durbin60f82082013-06-19 13:28:04 -0500176 }
177}
178
Aaron Durbin1c4289d2013-06-21 14:06:11 -0500179static void pcie_enable_clock_gating(void)
180{
181 int i;
182 int is_lp;
183 int enabled_ports;
184
185 is_lp = pch_is_lp();
186 enabled_ports = 0;
187
188 for (i = 0; i < rpc.num_ports; i++) {
189 device_t dev;
190 int rp;
191
192 dev = rpc.ports[i];
193 rp = root_port_number(dev);
194
195 if (!dev->enabled) {
196 /* Configure shared resource clock gating. */
197 if (rp == 1 || rp == 5 || (rp == 6 && is_lp))
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300198 pci_update_config8(dev, 0xe1, 0xc3, 0x3c);
Aaron Durbin1c4289d2013-06-21 14:06:11 -0500199
200 if (!is_lp) {
201 if (rp == 1 && !rpc.ports[1]->enabled &&
202 !rpc.ports[2]->enabled &&
203 !rpc.ports[3]->enabled) {
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300204 pci_update_config8(dev, 0xe2, ~1, 1);
205 pci_update_config8(dev, 0xe1, 0x7f, 0x80);
Aaron Durbin1c4289d2013-06-21 14:06:11 -0500206 }
207 if (rp == 5 && !rpc.ports[5]->enabled &&
208 !rpc.ports[6]->enabled &&
209 !rpc.ports[7]->enabled) {
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300210 pci_update_config8(dev, 0xe2, ~1, 1);
211 pci_update_config8(dev, 0xe1, 0x7f, 0x80);
Aaron Durbin1c4289d2013-06-21 14:06:11 -0500212 }
213 continue;
214 }
215
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300216 pci_update_config8(dev, 0xe2, ~(3 << 4), (3 << 4));
217 pci_update_config32(dev, 0x420, ~(1 << 31), (1 << 31));
Aaron Durbin1c4289d2013-06-21 14:06:11 -0500218
219 /* Per-Port CLKREQ# handling. */
220 if (is_lp && gpio_is_native(18 + rp - 1))
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300221 pci_update_config32(dev, 0x420, ~0, (3 << 29));
Aaron Durbin1c4289d2013-06-21 14:06:11 -0500222
223 /* Enable static clock gating. */
224 if (rp == 1 && !rpc.ports[1]->enabled &&
225 !rpc.ports[2]->enabled && !rpc.ports[3]->enabled) {
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300226 pci_update_config8(dev, 0xe2, ~1, 1);
227 pci_update_config8(dev, 0xe1, 0x7f, 0x80);
Aaron Durbin1c4289d2013-06-21 14:06:11 -0500228 } else if (rp == 5 || rp == 6) {
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300229 pci_update_config8(dev, 0xe2, ~1, 1);
230 pci_update_config8(dev, 0xe1, 0x7f, 0x80);
Aaron Durbin1c4289d2013-06-21 14:06:11 -0500231 }
232 continue;
233 }
234
235 enabled_ports++;
236
237 /* Enable dynamic clock gating. */
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300238 pci_update_config8(dev, 0xe1, 0xfc, 0x03);
Aaron Durbin1c4289d2013-06-21 14:06:11 -0500239
240 if (is_lp) {
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300241 pci_update_config8(dev, 0xe2, ~(1 << 6), (1 << 6));
242 pci_update_config8(dev, 0xe8, ~(3 << 2), (2 << 2));
Aaron Durbin1c4289d2013-06-21 14:06:11 -0500243 }
244
245 /* Update PECR1 register. */
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300246 pci_update_config8(dev, 0xe8, ~0, 1);
Aaron Durbin1c4289d2013-06-21 14:06:11 -0500247
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300248 pci_update_config8(dev, 0x324, ~(1 << 5), (1 < 5));
Aaron Durbin1c4289d2013-06-21 14:06:11 -0500249
250 /* Per-Port CLKREQ# handling. */
251 if (is_lp && gpio_is_native(18 + rp - 1))
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300252 pci_update_config32(dev, 0x420, ~0, (3 << 29));
Aaron Durbin1c4289d2013-06-21 14:06:11 -0500253
254 /* Configure shared resource clock gating. */
255 if (rp == 1 || rp == 5 || (rp == 6 && is_lp))
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300256 pci_update_config8(dev, 0xe1, 0xc3, 0x3c);
Aaron Durbin1c4289d2013-06-21 14:06:11 -0500257 }
258
259 if (!enabled_ports && is_lp)
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300260 pci_update_config8(rpc.ports[0], 0xe1, ~(1 << 6), (1 << 6));
Aaron Durbin1c4289d2013-06-21 14:06:11 -0500261}
262
Aaron Durbinc0254e62013-06-20 01:20:30 -0500263static void root_port_commit_config(void)
Aaron Durbin60f82082013-06-19 13:28:04 -0500264{
Aaron Durbinc0254e62013-06-20 01:20:30 -0500265 int i;
Aaron Durbin60f82082013-06-19 13:28:04 -0500266
Aaron Durbinc0254e62013-06-20 01:20:30 -0500267 /* If the first root port is disabled the coalesce ports. */
268 if (!rpc.ports[0]->enabled)
269 rpc.coalesce = 1;
Aaron Durbin60f82082013-06-19 13:28:04 -0500270
Aaron Durbin1c4289d2013-06-21 14:06:11 -0500271 /* Perform clock gating configuration. */
272 pcie_enable_clock_gating();
273
Aaron Durbinc0254e62013-06-20 01:20:30 -0500274 for (i = 0; i < rpc.num_ports; i++) {
275 device_t dev;
276 u32 reg32;
Aaron Durbin60f82082013-06-19 13:28:04 -0500277
Aaron Durbinc0254e62013-06-20 01:20:30 -0500278 dev = rpc.ports[i];
Aaron Durbin60f82082013-06-19 13:28:04 -0500279
Aaron Durbinc0254e62013-06-20 01:20:30 -0500280 if (dev == NULL) {
281 printk(BIOS_ERR, "Root Port %d device is NULL?\n", i+1);
282 continue;
Aaron Durbin60f82082013-06-19 13:28:04 -0500283 }
284
Aaron Durbinc0254e62013-06-20 01:20:30 -0500285 if (dev->enabled)
286 continue;
287
288 printk(BIOS_DEBUG, "%s: Disabling device\n", dev_path(dev));
289
Aaron Durbin60f82082013-06-19 13:28:04 -0500290 /* Ensure memory, io, and bus master are all disabled */
291 reg32 = pci_read_config32(dev, PCI_COMMAND);
292 reg32 &= ~(PCI_COMMAND_MASTER |
293 PCI_COMMAND_MEMORY | PCI_COMMAND_IO);
294 pci_write_config32(dev, PCI_COMMAND, reg32);
295
Aaron Durbin60f82082013-06-19 13:28:04 -0500296 /* Disable this device if possible */
297 pch_disable_devfn(dev);
Aaron Durbin60f82082013-06-19 13:28:04 -0500298 }
299
Aaron Durbinc0254e62013-06-20 01:20:30 -0500300 if (rpc.coalesce) {
301 int current_func;
Aaron Durbin60f82082013-06-19 13:28:04 -0500302
Aaron Durbinc0254e62013-06-20 01:20:30 -0500303 /* For all Root Ports N enabled ports get assigned the lower
304 * PCI function number. The disabled ones get upper PCI
305 * function numbers. */
306 current_func = 0;
307 for (i = 0; i < rpc.num_ports; i++) {
308 if (!rpc.ports[i]->enabled)
309 continue;
310 pch_pcie_device_set_func(i, current_func);
311 current_func++;
312 }
313
314 /* Allocate the disabled devices' PCI function number. */
315 for (i = 0; i < rpc.num_ports; i++) {
316 if (rpc.ports[i]->enabled)
317 continue;
318 pch_pcie_device_set_func(i, current_func);
319 current_func++;
320 }
321 }
322
323 printk(BIOS_SPEW, "PCH: RPFN 0x%08x -> 0x%08x\n",
324 rpc.orig_rpfn, rpc.new_rpfn);
325 RCBA32(RPFN) = rpc.new_rpfn;
326}
327
328static void root_port_mark_disable(device_t dev)
329{
330 /* Mark device as disabled. */
331 dev->enabled = 0;
332 /* Mark device to be hidden. */
333 rpc.new_rpfn |= RPFN_HIDE(PCI_FUNC(dev->path.pci.devfn));
334}
335
336static void root_port_check_disable(device_t dev)
337{
338 int rp;
339 int is_lp;
340
341 /* Device already disabled. */
342 if (!dev->enabled) {
343 root_port_mark_disable(dev);
344 return;
345 }
346
347 rp = root_port_number(dev);
348
349 /* Is the GbE port mapped to this Root Port? */
350 if (rp == rpc.gbe_port) {
351 root_port_mark_disable(dev);
352 return;
353 }
354
355 is_lp = pch_is_lp();
356
357 /* Check Root Port Configuration. */
358 switch (rp) {
359 case 2:
360 /* Root Port 2 is disabled for all lane configurations
361 * but config 00b (4x1 links). */
362 if ((rpc.strpfusecfg1 >> 14) & 0x3) {
363 root_port_mark_disable(dev);
364 return;
365 }
366 break;
367 case 3:
368 /* Root Port 3 is disabled in config 11b (1x4 links). */
369 if (((rpc.strpfusecfg1 >> 14) & 0x3) == 0x3) {
370 root_port_mark_disable(dev);
371 return;
372 }
373 break;
374 case 4:
375 /* Root Port 4 is disabled in configs 11b (1x4 links)
376 * and 10b (2x2 links). */
377 if ((rpc.strpfusecfg1 >> 14) & 0x2) {
378 root_port_mark_disable(dev);
379 return;
380 }
381 break;
382 case 6:
383 if (is_lp)
384 break;
385 /* Root Port 6 is disabled for all lane configurations
386 * but config 00b (4x1 links). */
387 if ((rpc.strpfusecfg2 >> 14) & 0x3) {
388 root_port_mark_disable(dev);
389 return;
390 }
391 break;
392 case 7:
393 if (is_lp)
394 break;
395 /* Root Port 3 is disabled in config 11b (1x4 links). */
396 if (((rpc.strpfusecfg2 >> 14) & 0x3) == 0x3) {
397 root_port_mark_disable(dev);
398 return;
399 }
400 break;
401 case 8:
402 if (is_lp)
403 break;
404 /* Root Port 8 is disabled in configs 11b (1x4 links)
405 * and 10b (2x2 links). */
406 if ((rpc.strpfusecfg2 >> 14) & 0x2) {
407 root_port_mark_disable(dev);
408 return;
409 }
410 break;
411 }
412
413 /* Check Pin Ownership. */
414 if (is_lp) {
415 switch (rp) {
416 case 1:
417 /* Bit 0 is Root Port 1 ownership. */
418 if ((rpc.pin_ownership & 0x1) == 0) {
419 root_port_mark_disable(dev);
420 return;
421 }
422 break;
423 case 2:
424 /* Bit 2 is Root Port 2 ownership. */
425 if ((rpc.pin_ownership & 0x4) == 0) {
426 root_port_mark_disable(dev);
427 return;
428 }
429 break;
430 case 6:
431 /* Bits 7:4 are Root Port 6 pin-lane ownership. */
432 if ((rpc.pin_ownership & 0xf0) == 0) {
433 root_port_mark_disable(dev);
434 return;
435 }
436 break;
437 }
438 } else {
439 switch (rp) {
440 case 1:
441 /* Bits 4 and 0 are Root Port 1 ownership. */
442 if ((rpc.pin_ownership & 0x11) == 0) {
443 root_port_mark_disable(dev);
444 return;
445 }
446 break;
447 case 2:
448 /* Bits 5 and 2 are Root Port 2 ownership. */
449 if ((rpc.pin_ownership & 0x24) == 0) {
450 root_port_mark_disable(dev);
451 return;
452 }
453 break;
454 }
Aaron Durbin60f82082013-06-19 13:28:04 -0500455 }
456}
457
Stefan Reinauerab365af2013-12-03 12:13:26 -0800458static void pcie_add_0x0202000_iobp(u32 reg)
459{
460 u32 reg32;
Aaron Durbin76c37002012-10-30 09:03:43 -0500461
Stefan Reinauerab365af2013-12-03 12:13:26 -0800462 reg32 = pch_iobp_read(reg);
463 reg32 += (0x2 << 16) | (0x2 << 8);
464 pch_iobp_write(reg, reg32);
465}
Aaron Durbin76c37002012-10-30 09:03:43 -0500466
Stefan Reinauerab365af2013-12-03 12:13:26 -0800467static void pch_pcie_early(struct device *dev)
468{
469 int rp;
470 int do_aspm;
471 int is_lp;
Duncan Laurie249a03b2013-08-09 09:06:41 -0700472 struct southbridge_intel_lynxpoint_config *config = dev->chip_info;
Aaron Durbin76c37002012-10-30 09:03:43 -0500473
Stefan Reinauerab365af2013-12-03 12:13:26 -0800474 rp = root_port_number(dev);
475 do_aspm = 0;
476 is_lp = pch_is_lp();
Aaron Durbin76c37002012-10-30 09:03:43 -0500477
Stefan Reinauerab365af2013-12-03 12:13:26 -0800478 if (is_lp) {
479 switch (rp) {
480 case 1:
481 case 2:
482 case 3:
483 case 4:
484 /* Bits 31:28 of b0d28f0 0x32c register correspnd to
485 * Root Ports 4:1. */
486 do_aspm = !!(rpc.b0d28f0_32c & (1 << (28 + rp - 1)));
487 break;
488 case 5:
489 /* Bit 28 of b0d28f4 0x32c register correspnd to
490 * Root Ports 4:1. */
491 do_aspm = !!(rpc.b0d28f4_32c & (1 << 28));
492 break;
493 case 6:
494 /* Bit 28 of b0d28f5 0x32c register correspnd to
495 * Root Ports 4:1. */
496 do_aspm = !!(rpc.b0d28f5_32c & (1 << 28));
497 break;
498 }
499 } else {
500 switch (rp) {
501 case 1:
502 case 2:
503 case 3:
504 case 4:
505 /* Bits 31:28 of b0d28f0 0x32c register correspnd to
506 * Root Ports 4:1. */
507 do_aspm = !!(rpc.b0d28f0_32c & (1 << (28 + rp - 1)));
508 break;
509 case 5:
510 case 6:
511 case 7:
512 case 8:
513 /* Bit 31:28 of b0d28f4 0x32c register correspnd to
514 * Root Ports 8:5. */
515 do_aspm = !!(rpc.b0d28f4_32c & (1 << (28 + rp - 5)));
516 break;
517 }
Aaron Durbin76c37002012-10-30 09:03:43 -0500518 }
Stefan Reinauerab365af2013-12-03 12:13:26 -0800519
Duncan Laurie249a03b2013-08-09 09:06:41 -0700520 /* Allow ASPM to be forced on in devicetree */
521 if (config && (config->pcie_port_force_aspm & (1 << (rp - 1))))
522 do_aspm = 1;
523
524 printk(BIOS_DEBUG, "PCIe Root Port %d ASPM is %sabled\n",
525 rp, do_aspm ? "en" : "dis");
526
Stefan Reinauerab365af2013-12-03 12:13:26 -0800527 if (do_aspm) {
528 /* Set ASPM bits in MPC2 register. */
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300529 pci_update_config32(dev, 0xd4, ~(0x3 << 2), (1 << 4) | (0x2 << 2));
Stefan Reinauerab365af2013-12-03 12:13:26 -0800530
531 /* Set unique clock exit latency in MPC register. */
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300532 pci_update_config32(dev, 0xd8, ~(0x7 << 18), (0x7 << 18));
Stefan Reinauerab365af2013-12-03 12:13:26 -0800533
534 /* Set L1 exit latency in LCAP register. */
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300535 pci_update_config32(dev, 0x4c, ~(0x7 << 15), (0x4 << 15));
Stefan Reinauerab365af2013-12-03 12:13:26 -0800536
537 if (is_lp) {
538 switch (rp) {
539 case 1:
540 pcie_add_0x0202000_iobp(0xe9002440);
541 break;
542 case 2:
543 pcie_add_0x0202000_iobp(0xe9002640);
544 break;
545 case 3:
546 pcie_add_0x0202000_iobp(0xe9000840);
547 break;
548 case 4:
549 pcie_add_0x0202000_iobp(0xe9000a40);
550 break;
551 case 5:
552 pcie_add_0x0202000_iobp(0xe9000c40);
553 pcie_add_0x0202000_iobp(0xe9000e40);
554 pcie_add_0x0202000_iobp(0xe9001040);
555 pcie_add_0x0202000_iobp(0xe9001240);
556 break;
557 case 6:
558 /* Update IOBP based on lane ownership. */
559 if (rpc.pin_ownership & (1 << 4))
560 pcie_add_0x0202000_iobp(0xea002040);
561 if (rpc.pin_ownership & (1 << 5))
562 pcie_add_0x0202000_iobp(0xea002240);
563 if (rpc.pin_ownership & (1 << 6))
564 pcie_add_0x0202000_iobp(0xea002440);
565 if (rpc.pin_ownership & (1 << 7))
566 pcie_add_0x0202000_iobp(0xea002640);
567 break;
568 }
569 } else {
570 switch (rp) {
571 case 1:
572 if ((rpc.pin_ownership & 0x3) == 1)
573 pcie_add_0x0202000_iobp(0xe9002e40);
574 else
575 pcie_add_0x0202000_iobp(0xea002040);
576 break;
577 case 2:
578 if ((rpc.pin_ownership & 0xc) == 0x4)
579 pcie_add_0x0202000_iobp(0xe9002c40);
580 else
581 pcie_add_0x0202000_iobp(0xea002240);
582 break;
583 case 3:
584 pcie_add_0x0202000_iobp(0xe9002a40);
585 break;
586 case 4:
587 pcie_add_0x0202000_iobp(0xe9002840);
588 break;
589 case 5:
590 pcie_add_0x0202000_iobp(0xe9002640);
591 break;
592 case 6:
593 pcie_add_0x0202000_iobp(0xe9002440);
594 break;
595 case 7:
596 pcie_add_0x0202000_iobp(0xe9002240);
597 break;
598 case 8:
599 pcie_add_0x0202000_iobp(0xe9002040);
600 break;
601 }
602 }
603
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300604 pci_update_config32(dev, 0x338, ~(1 << 26), 0);
Stefan Reinauerab365af2013-12-03 12:13:26 -0800605 }
606
607 /* Enable LTR in Root Port. */
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300608 pci_update_config32(dev, 0x64, ~(1 << 11), (1 << 11));
609 pci_update_config32(dev, 0x68, ~(1 << 10), (1 << 10));
Stefan Reinauerab365af2013-12-03 12:13:26 -0800610
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300611 pci_update_config32(dev, 0x318, ~(0xffff << 16), (0x1414 << 16));
Stefan Reinauerab365af2013-12-03 12:13:26 -0800612
613 /* Set L1 exit latency in LCAP register. */
614 if (!do_aspm && (pci_read_config8(dev, 0xf5) & 0x1))
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300615 pci_update_config32(dev, 0x4c, ~(0x7 << 15), (0x4 << 15));
Stefan Reinauerab365af2013-12-03 12:13:26 -0800616 else
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300617 pci_update_config32(dev, 0x4c, ~(0x7 << 15), (0x2 << 15));
Stefan Reinauerab365af2013-12-03 12:13:26 -0800618
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300619 pci_update_config32(dev, 0x314, 0x0, 0x743a361b);
Stefan Reinauerab365af2013-12-03 12:13:26 -0800620
621 /* Set Common Clock Exit Latency in MPC register. */
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300622 pci_update_config32(dev, 0xd8, ~(0x7 << 15), (0x3 << 15));
Stefan Reinauerab365af2013-12-03 12:13:26 -0800623
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300624 pci_update_config32(dev, 0x33c, ~0x00ffffff, 0x854c74);
Stefan Reinauerab365af2013-12-03 12:13:26 -0800625
Stefan Reinauerab365af2013-12-03 12:13:26 -0800626 /* Set Invalid Recieve Range Check Enable in MPC register. */
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300627 pci_update_config32(dev, 0xd8, ~0, (1 << 25));
Stefan Reinauerab365af2013-12-03 12:13:26 -0800628
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300629 pci_update_config8(dev, 0xf5, 0x3f, 0);
Stefan Reinauerab365af2013-12-03 12:13:26 -0800630
631 if (rp == 1 || rp == 5 || (is_lp && rp == 6))
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300632 pci_update_config8(dev, 0xf7, ~0xc, 0);
Stefan Reinauerab365af2013-12-03 12:13:26 -0800633
634 /* Set EOI forwarding disable. */
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300635 pci_update_config32(dev, 0xd4, ~0, (1 << 1));
Stefan Reinauerab365af2013-12-03 12:13:26 -0800636
637 /* Set something involving advanced error reporting. */
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300638 pci_update_config32(dev, 0x100, ~((1 << 20) - 1), 0x10001);
Stefan Reinauerab365af2013-12-03 12:13:26 -0800639
640 if (is_lp)
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300641 pci_update_config32(dev, 0x100, ~0, (1 << 29));
Stefan Reinauerab365af2013-12-03 12:13:26 -0800642
643 /* Read and write back write-once capability registers. */
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300644 pci_update_config32(dev, 0x34, ~0, 0);
645 pci_update_config32(dev, 0x40, ~0, 0);
646 pci_update_config32(dev, 0x80, ~0, 0);
647 pci_update_config32(dev, 0x90, ~0, 0);
Aaron Durbin76c37002012-10-30 09:03:43 -0500648}
649
650static void pci_init(struct device *dev)
651{
652 u16 reg16;
653 u32 reg32;
654
655 printk(BIOS_DEBUG, "Initializing PCH PCIe bridge.\n");
656
Aaron Durbinc0254e62013-06-20 01:20:30 -0500657 /* Enable SERR */
658 reg32 = pci_read_config32(dev, PCI_COMMAND);
659 reg32 |= PCI_COMMAND_SERR;
660 pci_write_config32(dev, PCI_COMMAND, reg32);
661
Aaron Durbin76c37002012-10-30 09:03:43 -0500662 /* Enable Bus Master */
663 reg32 = pci_read_config32(dev, PCI_COMMAND);
664 reg32 |= PCI_COMMAND_MASTER;
665 pci_write_config32(dev, PCI_COMMAND, reg32);
666
667 /* Set Cache Line Size to 0x10 */
668 // This has no effect but the OS might expect it
669 pci_write_config8(dev, 0x0c, 0x10);
670
671 reg16 = pci_read_config16(dev, 0x3e);
672 reg16 &= ~(1 << 0); /* disable parity error response */
673 // reg16 &= ~(1 << 1); /* disable SERR */
674 reg16 |= (1 << 2); /* ISA enable */
675 pci_write_config16(dev, 0x3e, reg16);
676
677#ifdef EVEN_MORE_DEBUG
678 reg32 = pci_read_config32(dev, 0x20);
679 printk(BIOS_SPEW, " MBL = 0x%08x\n", reg32);
680 reg32 = pci_read_config32(dev, 0x24);
681 printk(BIOS_SPEW, " PMBL = 0x%08x\n", reg32);
682 reg32 = pci_read_config32(dev, 0x28);
683 printk(BIOS_SPEW, " PMBU32 = 0x%08x\n", reg32);
684 reg32 = pci_read_config32(dev, 0x2c);
685 printk(BIOS_SPEW, " PMLU32 = 0x%08x\n", reg32);
686#endif
687
688 /* Clear errors in status registers */
689 reg16 = pci_read_config16(dev, 0x06);
Aaron Durbin76c37002012-10-30 09:03:43 -0500690 pci_write_config16(dev, 0x06, reg16);
Aaron Durbin76c37002012-10-30 09:03:43 -0500691 reg16 = pci_read_config16(dev, 0x1e);
Aaron Durbin76c37002012-10-30 09:03:43 -0500692 pci_write_config16(dev, 0x1e, reg16);
Aaron Durbin76c37002012-10-30 09:03:43 -0500693}
694
695static void pch_pcie_enable(device_t dev)
696{
Aaron Durbinc0254e62013-06-20 01:20:30 -0500697 /* Add this device to the root port config structure. */
698 root_port_init_config(dev);
699
700 /* Check to see if this Root Port should be disabled. */
701 root_port_check_disable(dev);
702
Aaron Durbin76c37002012-10-30 09:03:43 -0500703 /* Power Management init before enumeration */
Aaron Durbinc0254e62013-06-20 01:20:30 -0500704 if (dev->enabled)
Stefan Reinauerab365af2013-12-03 12:13:26 -0800705 pch_pcie_early(dev);
Aaron Durbinc0254e62013-06-20 01:20:30 -0500706
707 /*
708 * When processing the last PCIe root port we can now
709 * update the Root Port Function Number and Hide register.
710 */
711 if (root_port_is_last(dev))
712 root_port_commit_config();
Aaron Durbin76c37002012-10-30 09:03:43 -0500713}
714
715static void pcie_set_subsystem(device_t dev, unsigned vendor, unsigned device)
716{
717 /* NOTE: This is not the default position! */
718 if (!vendor || !device) {
719 pci_write_config32(dev, 0x94,
720 pci_read_config32(dev, 0));
721 } else {
722 pci_write_config32(dev, 0x94,
723 ((device & 0xffff) << 16) | (vendor & 0xffff));
724 }
725}
726
727static struct pci_operations pci_ops = {
728 .set_subsystem = pcie_set_subsystem,
729};
730
731static struct device_operations device_ops = {
732 .read_resources = pci_bus_read_resources,
733 .set_resources = pci_dev_set_resources,
734 .enable_resources = pci_bus_enable_resources,
735 .init = pci_init,
736 .enable = pch_pcie_enable,
737 .scan_bus = pciexp_scan_bridge,
738 .ops_pci = &pci_ops,
739};
740
Duncan Laurie74c0d052012-12-17 11:31:40 -0800741static const unsigned short pci_device_ids[] = {
742 /* Lynxpoint Mobile */
743 0x8c10, 0x8c12, 0x8c14, 0x8c16, 0x8c18, 0x8c1a, 0x8c1c, 0x8c1e,
744 /* Lynxpoint Low Power */
745 0x9c10, 0x9c12, 0x9c14, 0x9c16, 0x9c18, 0x9c1a,
746 0
747};
Aaron Durbin76c37002012-10-30 09:03:43 -0500748
749static const struct pci_driver pch_pcie __pci_driver = {
750 .ops = &device_ops,
751 .vendor = PCI_VENDOR_ID_INTEL,
752 .devices = pci_device_ids,
753};