blob: a7966f15e1084b39378d2a24293bccfc539570ba [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>
Patrick Rudolphe56189c2018-04-18 10:11:59 +020022#include <device/pci_ops.h>
Aaron Durbin76c37002012-10-30 09:03:43 -050023#include "pch.h"
Patrick Rudolph273a8dc2016-02-06 18:07:59 +010024#include <southbridge/intel/common/gpio.h>
Aaron Durbin76c37002012-10-30 09:03:43 -050025
Aaron Durbinc0254e62013-06-20 01:20:30 -050026/* LynxPoint-LP has 6 root ports while non-LP has 8. */
27#define MAX_NUM_ROOT_PORTS 8
28#define H_NUM_ROOT_PORTS MAX_NUM_ROOT_PORTS
29#define LP_NUM_ROOT_PORTS (MAX_NUM_ROOT_PORTS - 2)
30
31struct root_port_config {
32 /* RPFN is a write-once register so keep a copy until it is written */
33 u32 orig_rpfn;
34 u32 new_rpfn;
35 u32 pin_ownership;
36 u32 strpfusecfg1;
37 u32 strpfusecfg2;
38 u32 strpfusecfg3;
Stefan Reinauerab365af2013-12-03 12:13:26 -080039 u32 b0d28f0_32c;
40 u32 b0d28f4_32c;
41 u32 b0d28f5_32c;
Aaron Durbinc0254e62013-06-20 01:20:30 -050042 int coalesce;
43 int gbe_port;
44 int num_ports;
Elyes HAOUAS7a5f7712018-06-08 17:20:38 +020045 struct device *ports[MAX_NUM_ROOT_PORTS];
Aaron Durbinc0254e62013-06-20 01:20:30 -050046};
47
48static struct root_port_config rpc;
49
50static inline int max_root_ports(void)
Aaron Durbin60f82082013-06-19 13:28:04 -050051{
Aaron Durbinc0254e62013-06-20 01:20:30 -050052 if (pch_is_lp())
53 return LP_NUM_ROOT_PORTS;
54 else
55 return H_NUM_ROOT_PORTS;
Aaron Durbin60f82082013-06-19 13:28:04 -050056}
57
Elyes HAOUAS7a5f7712018-06-08 17:20:38 +020058static inline int root_port_is_first(struct device *dev)
Aaron Durbin60f82082013-06-19 13:28:04 -050059{
Aaron Durbinc0254e62013-06-20 01:20:30 -050060 return PCI_FUNC(dev->path.pci.devfn) == 0;
61}
Aaron Durbin60f82082013-06-19 13:28:04 -050062
Elyes HAOUAS7a5f7712018-06-08 17:20:38 +020063static inline int root_port_is_last(struct device *dev)
Aaron Durbinc0254e62013-06-20 01:20:30 -050064{
65 return PCI_FUNC(dev->path.pci.devfn) == (rpc.num_ports - 1);
66}
Aaron Durbin60f82082013-06-19 13:28:04 -050067
Aaron Durbinc0254e62013-06-20 01:20:30 -050068/* Root ports are numbered 1..N in the documentation. */
Elyes HAOUAS7a5f7712018-06-08 17:20:38 +020069static inline int root_port_number(struct device *dev)
Aaron Durbinc0254e62013-06-20 01:20:30 -050070{
71 return PCI_FUNC(dev->path.pci.devfn) + 1;
72}
Aaron Durbin60f82082013-06-19 13:28:04 -050073
Aaron Durbinc0254e62013-06-20 01:20:30 -050074static 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 if (pch_is_lp()) {
81 switch ((rpc.strpfusecfg1 >> 16) & 0x7) {
82 case 0:
83 rpc.gbe_port = 3;
84 break;
85 case 1:
86 rpc.gbe_port = 4;
87 break;
88 case 2:
89 case 3:
90 case 4:
91 case 5:
92 /* Lanes 0-4 of Root Port 5. */
93 rpc.gbe_port = 5;
94 break;
95 default:
96 printk(BIOS_DEBUG, "Invalid GbE Port Selection.\n");
97 }
98 } else {
99 /* Non-LP has 1:1 mapping with root ports. */
100 rpc.gbe_port = ((rpc.strpfusecfg1 >> 16) & 0x7) + 1;
101 }
102}
103
Elyes HAOUAS7a5f7712018-06-08 17:20:38 +0200104static void root_port_init_config(struct device *dev)
Aaron Durbinc0254e62013-06-20 01:20:30 -0500105{
106 int rp;
107
108 if (root_port_is_first(dev)) {
109 rpc.orig_rpfn = RCBA32(RPFN);
110 rpc.new_rpfn = rpc.orig_rpfn;
111 rpc.num_ports = max_root_ports();
112 rpc.gbe_port = -1;
113
114 rpc.pin_ownership = pci_read_config32(dev, 0x410);
115 root_port_config_update_gbe_port();
116
117 if (dev->chip_info != NULL) {
118 struct southbridge_intel_lynxpoint_config *config;
119
120 config = dev->chip_info;
121 rpc.coalesce = config->pcie_port_coalesce;
122 }
123 }
124
125 rp = root_port_number(dev);
126 if (rp > rpc.num_ports) {
127 printk(BIOS_ERR, "Found Root Port %d, expecting %d\n",
128 rp, rpc.num_ports);
129 return;
130 }
131
132 /* Read the fuse configuration and pin ownership. */
133 switch (rp) {
134 case 1:
135 rpc.strpfusecfg1 = pci_read_config32(dev, 0xfc);
Stefan Reinauerab365af2013-12-03 12:13:26 -0800136 rpc.b0d28f0_32c = pci_read_config32(dev, 0x32c);
Aaron Durbinc0254e62013-06-20 01:20:30 -0500137 break;
138 case 5:
139 rpc.strpfusecfg2 = pci_read_config32(dev, 0xfc);
Stefan Reinauerab365af2013-12-03 12:13:26 -0800140 rpc.b0d28f4_32c = pci_read_config32(dev, 0x32c);
Aaron Durbinc0254e62013-06-20 01:20:30 -0500141 break;
142 case 6:
Stefan Reinauerab365af2013-12-03 12:13:26 -0800143 rpc.b0d28f5_32c = pci_read_config32(dev, 0x32c);
Aaron Durbinc0254e62013-06-20 01:20:30 -0500144 rpc.strpfusecfg3 = pci_read_config32(dev, 0xfc);
145 break;
146 default:
147 break;
148 }
149
150 /* Cache pci device. */
151 rpc.ports[rp - 1] = dev;
Aaron Durbin60f82082013-06-19 13:28:04 -0500152}
153
154/* Update devicetree with new Root Port function number assignment */
Aaron Durbinc0254e62013-06-20 01:20:30 -0500155static void pch_pcie_device_set_func(int index, int pci_func)
Aaron Durbin60f82082013-06-19 13:28:04 -0500156{
Elyes HAOUAS7a5f7712018-06-08 17:20:38 +0200157 struct device *dev;
Aaron Durbinc0254e62013-06-20 01:20:30 -0500158 unsigned new_devfn;
Aaron Durbin60f82082013-06-19 13:28:04 -0500159
Aaron Durbinc0254e62013-06-20 01:20:30 -0500160 dev = rpc.ports[index];
Aaron Durbin60f82082013-06-19 13:28:04 -0500161
Aaron Durbinc0254e62013-06-20 01:20:30 -0500162 /* Set the new PCI function field for this Root Port. */
163 rpc.new_rpfn &= ~RPFN_FNMASK(index);
164 rpc.new_rpfn |= RPFN_FNSET(index, pci_func);
Aaron Durbin60f82082013-06-19 13:28:04 -0500165
Aaron Durbinc0254e62013-06-20 01:20:30 -0500166 /* Determine the new devfn for this port */
167 new_devfn = PCI_DEVFN(PCH_PCIE_DEV_SLOT, pci_func);
Aaron Durbin60f82082013-06-19 13:28:04 -0500168
Aaron Durbinc0254e62013-06-20 01:20:30 -0500169 if (dev->path.pci.devfn != new_devfn) {
170 printk(BIOS_DEBUG,
171 "PCH: PCIe map %02x.%1x -> %02x.%1x\n",
172 PCI_SLOT(dev->path.pci.devfn),
173 PCI_FUNC(dev->path.pci.devfn),
174 PCI_SLOT(new_devfn), PCI_FUNC(new_devfn));
Aaron Durbin60f82082013-06-19 13:28:04 -0500175
Aaron Durbinc0254e62013-06-20 01:20:30 -0500176 dev->path.pci.devfn = new_devfn;
Aaron Durbin60f82082013-06-19 13:28:04 -0500177 }
178}
179
Aaron Durbin1c4289d2013-06-21 14:06:11 -0500180static void pcie_enable_clock_gating(void)
181{
182 int i;
183 int is_lp;
184 int enabled_ports;
185
186 is_lp = pch_is_lp();
187 enabled_ports = 0;
188
189 for (i = 0; i < rpc.num_ports; i++) {
Elyes HAOUAS7a5f7712018-06-08 17:20:38 +0200190 struct device *dev;
Aaron Durbin1c4289d2013-06-21 14:06:11 -0500191 int rp;
192
193 dev = rpc.ports[i];
194 rp = root_port_number(dev);
195
196 if (!dev->enabled) {
Ryan Salsamendi3f2fe182017-07-04 13:14:16 -0700197 static const uint32_t high_bit = (1UL << 31);
198
Aaron Durbin1c4289d2013-06-21 14:06:11 -0500199 /* Configure shared resource clock gating. */
200 if (rp == 1 || rp == 5 || (rp == 6 && is_lp))
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300201 pci_update_config8(dev, 0xe1, 0xc3, 0x3c);
Aaron Durbin1c4289d2013-06-21 14:06:11 -0500202
203 if (!is_lp) {
204 if (rp == 1 && !rpc.ports[1]->enabled &&
205 !rpc.ports[2]->enabled &&
206 !rpc.ports[3]->enabled) {
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300207 pci_update_config8(dev, 0xe2, ~1, 1);
208 pci_update_config8(dev, 0xe1, 0x7f, 0x80);
Aaron Durbin1c4289d2013-06-21 14:06:11 -0500209 }
210 if (rp == 5 && !rpc.ports[5]->enabled &&
211 !rpc.ports[6]->enabled &&
212 !rpc.ports[7]->enabled) {
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300213 pci_update_config8(dev, 0xe2, ~1, 1);
214 pci_update_config8(dev, 0xe1, 0x7f, 0x80);
Aaron Durbin1c4289d2013-06-21 14:06:11 -0500215 }
216 continue;
217 }
218
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300219 pci_update_config8(dev, 0xe2, ~(3 << 4), (3 << 4));
Ryan Salsamendi3f2fe182017-07-04 13:14:16 -0700220 pci_update_config32(dev, 0x420, ~high_bit, high_bit);
Aaron Durbin1c4289d2013-06-21 14:06:11 -0500221
222 /* Per-Port CLKREQ# handling. */
223 if (is_lp && gpio_is_native(18 + rp - 1))
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300224 pci_update_config32(dev, 0x420, ~0, (3 << 29));
Aaron Durbin1c4289d2013-06-21 14:06:11 -0500225
226 /* Enable static clock gating. */
227 if (rp == 1 && !rpc.ports[1]->enabled &&
228 !rpc.ports[2]->enabled && !rpc.ports[3]->enabled) {
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 } else if (rp == 5 || rp == 6) {
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300232 pci_update_config8(dev, 0xe2, ~1, 1);
233 pci_update_config8(dev, 0xe1, 0x7f, 0x80);
Aaron Durbin1c4289d2013-06-21 14:06:11 -0500234 }
235 continue;
236 }
237
238 enabled_ports++;
239
240 /* Enable dynamic clock gating. */
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300241 pci_update_config8(dev, 0xe1, 0xfc, 0x03);
Aaron Durbin1c4289d2013-06-21 14:06:11 -0500242
243 if (is_lp) {
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300244 pci_update_config8(dev, 0xe2, ~(1 << 6), (1 << 6));
245 pci_update_config8(dev, 0xe8, ~(3 << 2), (2 << 2));
Aaron Durbin1c4289d2013-06-21 14:06:11 -0500246 }
247
248 /* Update PECR1 register. */
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300249 pci_update_config8(dev, 0xe8, ~0, 1);
Aaron Durbin1c4289d2013-06-21 14:06:11 -0500250
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300251 pci_update_config8(dev, 0x324, ~(1 << 5), (1 < 5));
Aaron Durbin1c4289d2013-06-21 14:06:11 -0500252
253 /* Per-Port CLKREQ# handling. */
254 if (is_lp && gpio_is_native(18 + rp - 1))
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300255 pci_update_config32(dev, 0x420, ~0, (3 << 29));
Aaron Durbin1c4289d2013-06-21 14:06:11 -0500256
257 /* Configure shared resource clock gating. */
258 if (rp == 1 || rp == 5 || (rp == 6 && is_lp))
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300259 pci_update_config8(dev, 0xe1, 0xc3, 0x3c);
Aaron Durbin1c4289d2013-06-21 14:06:11 -0500260 }
261
262 if (!enabled_ports && is_lp)
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300263 pci_update_config8(rpc.ports[0], 0xe1, ~(1 << 6), (1 << 6));
Aaron Durbin1c4289d2013-06-21 14:06:11 -0500264}
265
Aaron Durbinc0254e62013-06-20 01:20:30 -0500266static void root_port_commit_config(void)
Aaron Durbin60f82082013-06-19 13:28:04 -0500267{
Aaron Durbinc0254e62013-06-20 01:20:30 -0500268 int i;
Aaron Durbin60f82082013-06-19 13:28:04 -0500269
Aaron Durbinc0254e62013-06-20 01:20:30 -0500270 /* If the first root port is disabled the coalesce ports. */
271 if (!rpc.ports[0]->enabled)
272 rpc.coalesce = 1;
Aaron Durbin60f82082013-06-19 13:28:04 -0500273
Aaron Durbin1c4289d2013-06-21 14:06:11 -0500274 /* Perform clock gating configuration. */
275 pcie_enable_clock_gating();
276
Aaron Durbinc0254e62013-06-20 01:20:30 -0500277 for (i = 0; i < rpc.num_ports; i++) {
Elyes HAOUAS7a5f7712018-06-08 17:20:38 +0200278 struct device *dev;
Aaron Durbinc0254e62013-06-20 01:20:30 -0500279 u32 reg32;
Aaron Durbin60f82082013-06-19 13:28:04 -0500280
Aaron Durbinc0254e62013-06-20 01:20:30 -0500281 dev = rpc.ports[i];
Aaron Durbin60f82082013-06-19 13:28:04 -0500282
Aaron Durbinc0254e62013-06-20 01:20:30 -0500283 if (dev == NULL) {
284 printk(BIOS_ERR, "Root Port %d device is NULL?\n", i+1);
285 continue;
Aaron Durbin60f82082013-06-19 13:28:04 -0500286 }
287
Aaron Durbinc0254e62013-06-20 01:20:30 -0500288 if (dev->enabled)
289 continue;
290
291 printk(BIOS_DEBUG, "%s: Disabling device\n", dev_path(dev));
292
Aaron Durbin60f82082013-06-19 13:28:04 -0500293 /* Ensure memory, io, and bus master are all disabled */
294 reg32 = pci_read_config32(dev, PCI_COMMAND);
295 reg32 &= ~(PCI_COMMAND_MASTER |
296 PCI_COMMAND_MEMORY | PCI_COMMAND_IO);
297 pci_write_config32(dev, PCI_COMMAND, reg32);
298
Aaron Durbin60f82082013-06-19 13:28:04 -0500299 /* Disable this device if possible */
300 pch_disable_devfn(dev);
Aaron Durbin60f82082013-06-19 13:28:04 -0500301 }
302
Aaron Durbinc0254e62013-06-20 01:20:30 -0500303 if (rpc.coalesce) {
304 int current_func;
Aaron Durbin60f82082013-06-19 13:28:04 -0500305
Aaron Durbinc0254e62013-06-20 01:20:30 -0500306 /* For all Root Ports N enabled ports get assigned the lower
307 * PCI function number. The disabled ones get upper PCI
308 * function numbers. */
309 current_func = 0;
310 for (i = 0; i < rpc.num_ports; i++) {
311 if (!rpc.ports[i]->enabled)
312 continue;
313 pch_pcie_device_set_func(i, current_func);
314 current_func++;
315 }
316
317 /* Allocate the disabled devices' PCI function number. */
318 for (i = 0; i < rpc.num_ports; i++) {
319 if (rpc.ports[i]->enabled)
320 continue;
321 pch_pcie_device_set_func(i, current_func);
322 current_func++;
323 }
324 }
325
326 printk(BIOS_SPEW, "PCH: RPFN 0x%08x -> 0x%08x\n",
327 rpc.orig_rpfn, rpc.new_rpfn);
328 RCBA32(RPFN) = rpc.new_rpfn;
329}
330
Elyes HAOUAS7a5f7712018-06-08 17:20:38 +0200331static void root_port_mark_disable(struct device *dev)
Aaron Durbinc0254e62013-06-20 01:20:30 -0500332{
333 /* Mark device as disabled. */
334 dev->enabled = 0;
335 /* Mark device to be hidden. */
336 rpc.new_rpfn |= RPFN_HIDE(PCI_FUNC(dev->path.pci.devfn));
337}
338
Elyes HAOUAS7a5f7712018-06-08 17:20:38 +0200339static void root_port_check_disable(struct device *dev)
Aaron Durbinc0254e62013-06-20 01:20:30 -0500340{
341 int rp;
342 int is_lp;
343
344 /* Device already disabled. */
345 if (!dev->enabled) {
346 root_port_mark_disable(dev);
347 return;
348 }
349
350 rp = root_port_number(dev);
351
352 /* Is the GbE port mapped to this Root Port? */
353 if (rp == rpc.gbe_port) {
354 root_port_mark_disable(dev);
355 return;
356 }
357
358 is_lp = pch_is_lp();
359
360 /* Check Root Port Configuration. */
361 switch (rp) {
362 case 2:
363 /* Root Port 2 is disabled for all lane configurations
364 * but config 00b (4x1 links). */
365 if ((rpc.strpfusecfg1 >> 14) & 0x3) {
366 root_port_mark_disable(dev);
367 return;
368 }
369 break;
370 case 3:
371 /* Root Port 3 is disabled in config 11b (1x4 links). */
372 if (((rpc.strpfusecfg1 >> 14) & 0x3) == 0x3) {
373 root_port_mark_disable(dev);
374 return;
375 }
376 break;
377 case 4:
378 /* Root Port 4 is disabled in configs 11b (1x4 links)
379 * and 10b (2x2 links). */
380 if ((rpc.strpfusecfg1 >> 14) & 0x2) {
381 root_port_mark_disable(dev);
382 return;
383 }
384 break;
385 case 6:
386 if (is_lp)
387 break;
388 /* Root Port 6 is disabled for all lane configurations
389 * but config 00b (4x1 links). */
390 if ((rpc.strpfusecfg2 >> 14) & 0x3) {
391 root_port_mark_disable(dev);
392 return;
393 }
394 break;
395 case 7:
396 if (is_lp)
397 break;
398 /* Root Port 3 is disabled in config 11b (1x4 links). */
399 if (((rpc.strpfusecfg2 >> 14) & 0x3) == 0x3) {
400 root_port_mark_disable(dev);
401 return;
402 }
403 break;
404 case 8:
405 if (is_lp)
406 break;
407 /* Root Port 8 is disabled in configs 11b (1x4 links)
408 * and 10b (2x2 links). */
409 if ((rpc.strpfusecfg2 >> 14) & 0x2) {
410 root_port_mark_disable(dev);
411 return;
412 }
413 break;
414 }
415
416 /* Check Pin Ownership. */
417 if (is_lp) {
418 switch (rp) {
419 case 1:
420 /* Bit 0 is Root Port 1 ownership. */
421 if ((rpc.pin_ownership & 0x1) == 0) {
422 root_port_mark_disable(dev);
423 return;
424 }
425 break;
426 case 2:
427 /* Bit 2 is Root Port 2 ownership. */
428 if ((rpc.pin_ownership & 0x4) == 0) {
429 root_port_mark_disable(dev);
430 return;
431 }
432 break;
433 case 6:
434 /* Bits 7:4 are Root Port 6 pin-lane ownership. */
435 if ((rpc.pin_ownership & 0xf0) == 0) {
436 root_port_mark_disable(dev);
437 return;
438 }
439 break;
440 }
441 } else {
442 switch (rp) {
443 case 1:
444 /* Bits 4 and 0 are Root Port 1 ownership. */
445 if ((rpc.pin_ownership & 0x11) == 0) {
446 root_port_mark_disable(dev);
447 return;
448 }
449 break;
450 case 2:
451 /* Bits 5 and 2 are Root Port 2 ownership. */
452 if ((rpc.pin_ownership & 0x24) == 0) {
453 root_port_mark_disable(dev);
454 return;
455 }
456 break;
457 }
Aaron Durbin60f82082013-06-19 13:28:04 -0500458 }
459}
460
Stefan Reinauerab365af2013-12-03 12:13:26 -0800461static void pcie_add_0x0202000_iobp(u32 reg)
462{
463 u32 reg32;
Aaron Durbin76c37002012-10-30 09:03:43 -0500464
Stefan Reinauerab365af2013-12-03 12:13:26 -0800465 reg32 = pch_iobp_read(reg);
466 reg32 += (0x2 << 16) | (0x2 << 8);
467 pch_iobp_write(reg, reg32);
468}
Aaron Durbin76c37002012-10-30 09:03:43 -0500469
Stefan Reinauerab365af2013-12-03 12:13:26 -0800470static void pch_pcie_early(struct device *dev)
471{
472 int rp;
473 int do_aspm;
474 int is_lp;
Duncan Laurie249a03b2013-08-09 09:06:41 -0700475 struct southbridge_intel_lynxpoint_config *config = dev->chip_info;
Aaron Durbin76c37002012-10-30 09:03:43 -0500476
Stefan Reinauerab365af2013-12-03 12:13:26 -0800477 rp = root_port_number(dev);
478 do_aspm = 0;
479 is_lp = pch_is_lp();
Aaron Durbin76c37002012-10-30 09:03:43 -0500480
Stefan Reinauerab365af2013-12-03 12:13:26 -0800481 if (is_lp) {
482 switch (rp) {
483 case 1:
484 case 2:
485 case 3:
486 case 4:
487 /* Bits 31:28 of b0d28f0 0x32c register correspnd to
488 * Root Ports 4:1. */
489 do_aspm = !!(rpc.b0d28f0_32c & (1 << (28 + rp - 1)));
490 break;
491 case 5:
492 /* Bit 28 of b0d28f4 0x32c register correspnd to
493 * Root Ports 4:1. */
494 do_aspm = !!(rpc.b0d28f4_32c & (1 << 28));
495 break;
496 case 6:
497 /* Bit 28 of b0d28f5 0x32c register correspnd to
498 * Root Ports 4:1. */
499 do_aspm = !!(rpc.b0d28f5_32c & (1 << 28));
500 break;
501 }
502 } else {
503 switch (rp) {
504 case 1:
505 case 2:
506 case 3:
507 case 4:
508 /* Bits 31:28 of b0d28f0 0x32c register correspnd to
509 * Root Ports 4:1. */
510 do_aspm = !!(rpc.b0d28f0_32c & (1 << (28 + rp - 1)));
511 break;
512 case 5:
513 case 6:
514 case 7:
515 case 8:
516 /* Bit 31:28 of b0d28f4 0x32c register correspnd to
517 * Root Ports 8:5. */
518 do_aspm = !!(rpc.b0d28f4_32c & (1 << (28 + rp - 5)));
519 break;
520 }
Aaron Durbin76c37002012-10-30 09:03:43 -0500521 }
Stefan Reinauerab365af2013-12-03 12:13:26 -0800522
Duncan Laurie249a03b2013-08-09 09:06:41 -0700523 /* Allow ASPM to be forced on in devicetree */
524 if (config && (config->pcie_port_force_aspm & (1 << (rp - 1))))
525 do_aspm = 1;
526
527 printk(BIOS_DEBUG, "PCIe Root Port %d ASPM is %sabled\n",
528 rp, do_aspm ? "en" : "dis");
529
Stefan Reinauerab365af2013-12-03 12:13:26 -0800530 if (do_aspm) {
531 /* Set ASPM bits in MPC2 register. */
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300532 pci_update_config32(dev, 0xd4, ~(0x3 << 2), (1 << 4) | (0x2 << 2));
Stefan Reinauerab365af2013-12-03 12:13:26 -0800533
534 /* Set unique clock exit latency in MPC register. */
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300535 pci_update_config32(dev, 0xd8, ~(0x7 << 18), (0x7 << 18));
Stefan Reinauerab365af2013-12-03 12:13:26 -0800536
537 /* Set L1 exit latency in LCAP register. */
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300538 pci_update_config32(dev, 0x4c, ~(0x7 << 15), (0x4 << 15));
Stefan Reinauerab365af2013-12-03 12:13:26 -0800539
540 if (is_lp) {
541 switch (rp) {
542 case 1:
543 pcie_add_0x0202000_iobp(0xe9002440);
544 break;
545 case 2:
546 pcie_add_0x0202000_iobp(0xe9002640);
547 break;
548 case 3:
549 pcie_add_0x0202000_iobp(0xe9000840);
550 break;
551 case 4:
552 pcie_add_0x0202000_iobp(0xe9000a40);
553 break;
554 case 5:
555 pcie_add_0x0202000_iobp(0xe9000c40);
556 pcie_add_0x0202000_iobp(0xe9000e40);
557 pcie_add_0x0202000_iobp(0xe9001040);
558 pcie_add_0x0202000_iobp(0xe9001240);
559 break;
560 case 6:
561 /* Update IOBP based on lane ownership. */
562 if (rpc.pin_ownership & (1 << 4))
563 pcie_add_0x0202000_iobp(0xea002040);
564 if (rpc.pin_ownership & (1 << 5))
565 pcie_add_0x0202000_iobp(0xea002240);
566 if (rpc.pin_ownership & (1 << 6))
567 pcie_add_0x0202000_iobp(0xea002440);
568 if (rpc.pin_ownership & (1 << 7))
569 pcie_add_0x0202000_iobp(0xea002640);
570 break;
571 }
572 } else {
573 switch (rp) {
574 case 1:
575 if ((rpc.pin_ownership & 0x3) == 1)
576 pcie_add_0x0202000_iobp(0xe9002e40);
577 else
578 pcie_add_0x0202000_iobp(0xea002040);
579 break;
580 case 2:
581 if ((rpc.pin_ownership & 0xc) == 0x4)
582 pcie_add_0x0202000_iobp(0xe9002c40);
583 else
584 pcie_add_0x0202000_iobp(0xea002240);
585 break;
586 case 3:
587 pcie_add_0x0202000_iobp(0xe9002a40);
588 break;
589 case 4:
590 pcie_add_0x0202000_iobp(0xe9002840);
591 break;
592 case 5:
593 pcie_add_0x0202000_iobp(0xe9002640);
594 break;
595 case 6:
596 pcie_add_0x0202000_iobp(0xe9002440);
597 break;
598 case 7:
599 pcie_add_0x0202000_iobp(0xe9002240);
600 break;
601 case 8:
602 pcie_add_0x0202000_iobp(0xe9002040);
603 break;
604 }
605 }
606
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300607 pci_update_config32(dev, 0x338, ~(1 << 26), 0);
Stefan Reinauerab365af2013-12-03 12:13:26 -0800608 }
609
610 /* Enable LTR in Root Port. */
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300611 pci_update_config32(dev, 0x64, ~(1 << 11), (1 << 11));
612 pci_update_config32(dev, 0x68, ~(1 << 10), (1 << 10));
Stefan Reinauerab365af2013-12-03 12:13:26 -0800613
Ryan Salsamendi0d9b3602017-06-30 17:15:57 -0700614 pci_update_config32(dev, 0x318, ~(0xffffUL << 16), (0x1414UL << 16));
Stefan Reinauerab365af2013-12-03 12:13:26 -0800615
616 /* Set L1 exit latency in LCAP register. */
617 if (!do_aspm && (pci_read_config8(dev, 0xf5) & 0x1))
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300618 pci_update_config32(dev, 0x4c, ~(0x7 << 15), (0x4 << 15));
Stefan Reinauerab365af2013-12-03 12:13:26 -0800619 else
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300620 pci_update_config32(dev, 0x4c, ~(0x7 << 15), (0x2 << 15));
Stefan Reinauerab365af2013-12-03 12:13:26 -0800621
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300622 pci_update_config32(dev, 0x314, 0x0, 0x743a361b);
Stefan Reinauerab365af2013-12-03 12:13:26 -0800623
624 /* Set Common Clock Exit Latency in MPC register. */
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300625 pci_update_config32(dev, 0xd8, ~(0x7 << 15), (0x3 << 15));
Stefan Reinauerab365af2013-12-03 12:13:26 -0800626
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300627 pci_update_config32(dev, 0x33c, ~0x00ffffff, 0x854c74);
Stefan Reinauerab365af2013-12-03 12:13:26 -0800628
Stefan Reinauerab365af2013-12-03 12:13:26 -0800629 /* Set Invalid Recieve Range Check Enable in MPC register. */
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300630 pci_update_config32(dev, 0xd8, ~0, (1 << 25));
Stefan Reinauerab365af2013-12-03 12:13:26 -0800631
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300632 pci_update_config8(dev, 0xf5, 0x3f, 0);
Stefan Reinauerab365af2013-12-03 12:13:26 -0800633
634 if (rp == 1 || rp == 5 || (is_lp && rp == 6))
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300635 pci_update_config8(dev, 0xf7, ~0xc, 0);
Stefan Reinauerab365af2013-12-03 12:13:26 -0800636
637 /* Set EOI forwarding disable. */
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300638 pci_update_config32(dev, 0xd4, ~0, (1 << 1));
Stefan Reinauerab365af2013-12-03 12:13:26 -0800639
640 /* Set something involving advanced error reporting. */
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300641 pci_update_config32(dev, 0x100, ~((1 << 20) - 1), 0x10001);
Stefan Reinauerab365af2013-12-03 12:13:26 -0800642
643 if (is_lp)
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300644 pci_update_config32(dev, 0x100, ~0, (1 << 29));
Stefan Reinauerab365af2013-12-03 12:13:26 -0800645
646 /* Read and write back write-once capability registers. */
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300647 pci_update_config32(dev, 0x34, ~0, 0);
648 pci_update_config32(dev, 0x40, ~0, 0);
649 pci_update_config32(dev, 0x80, ~0, 0);
650 pci_update_config32(dev, 0x90, ~0, 0);
Aaron Durbin76c37002012-10-30 09:03:43 -0500651}
652
653static void pci_init(struct device *dev)
654{
655 u16 reg16;
656 u32 reg32;
657
658 printk(BIOS_DEBUG, "Initializing PCH PCIe bridge.\n");
659
Aaron Durbinc0254e62013-06-20 01:20:30 -0500660 /* Enable SERR */
661 reg32 = pci_read_config32(dev, PCI_COMMAND);
662 reg32 |= PCI_COMMAND_SERR;
663 pci_write_config32(dev, PCI_COMMAND, reg32);
664
Aaron Durbin76c37002012-10-30 09:03:43 -0500665 /* Enable Bus Master */
666 reg32 = pci_read_config32(dev, PCI_COMMAND);
667 reg32 |= PCI_COMMAND_MASTER;
668 pci_write_config32(dev, PCI_COMMAND, reg32);
669
670 /* Set Cache Line Size to 0x10 */
671 // This has no effect but the OS might expect it
672 pci_write_config8(dev, 0x0c, 0x10);
673
674 reg16 = pci_read_config16(dev, 0x3e);
675 reg16 &= ~(1 << 0); /* disable parity error response */
676 // reg16 &= ~(1 << 1); /* disable SERR */
677 reg16 |= (1 << 2); /* ISA enable */
678 pci_write_config16(dev, 0x3e, reg16);
679
680#ifdef EVEN_MORE_DEBUG
681 reg32 = pci_read_config32(dev, 0x20);
682 printk(BIOS_SPEW, " MBL = 0x%08x\n", reg32);
683 reg32 = pci_read_config32(dev, 0x24);
684 printk(BIOS_SPEW, " PMBL = 0x%08x\n", reg32);
685 reg32 = pci_read_config32(dev, 0x28);
686 printk(BIOS_SPEW, " PMBU32 = 0x%08x\n", reg32);
687 reg32 = pci_read_config32(dev, 0x2c);
688 printk(BIOS_SPEW, " PMLU32 = 0x%08x\n", reg32);
689#endif
690
691 /* Clear errors in status registers */
692 reg16 = pci_read_config16(dev, 0x06);
Aaron Durbin76c37002012-10-30 09:03:43 -0500693 pci_write_config16(dev, 0x06, reg16);
Aaron Durbin76c37002012-10-30 09:03:43 -0500694 reg16 = pci_read_config16(dev, 0x1e);
Aaron Durbin76c37002012-10-30 09:03:43 -0500695 pci_write_config16(dev, 0x1e, reg16);
Aaron Durbin76c37002012-10-30 09:03:43 -0500696}
697
Elyes HAOUAS7a5f7712018-06-08 17:20:38 +0200698static void pch_pcie_enable(struct device *dev)
Aaron Durbin76c37002012-10-30 09:03:43 -0500699{
Aaron Durbinc0254e62013-06-20 01:20:30 -0500700 /* Add this device to the root port config structure. */
701 root_port_init_config(dev);
702
703 /* Check to see if this Root Port should be disabled. */
704 root_port_check_disable(dev);
705
Aaron Durbin76c37002012-10-30 09:03:43 -0500706 /* Power Management init before enumeration */
Aaron Durbinc0254e62013-06-20 01:20:30 -0500707 if (dev->enabled)
Stefan Reinauerab365af2013-12-03 12:13:26 -0800708 pch_pcie_early(dev);
Aaron Durbinc0254e62013-06-20 01:20:30 -0500709
710 /*
711 * When processing the last PCIe root port we can now
712 * update the Root Port Function Number and Hide register.
713 */
714 if (root_port_is_last(dev))
715 root_port_commit_config();
Aaron Durbin76c37002012-10-30 09:03:43 -0500716}
717
Elyes HAOUAS7a5f7712018-06-08 17:20:38 +0200718static void pcie_set_subsystem(struct device *dev, unsigned vendor,
719 unsigned device)
Aaron Durbin76c37002012-10-30 09:03:43 -0500720{
721 /* NOTE: This is not the default position! */
722 if (!vendor || !device) {
723 pci_write_config32(dev, 0x94,
724 pci_read_config32(dev, 0));
725 } else {
726 pci_write_config32(dev, 0x94,
727 ((device & 0xffff) << 16) | (vendor & 0xffff));
728 }
729}
730
731static struct pci_operations pci_ops = {
732 .set_subsystem = pcie_set_subsystem,
733};
734
735static struct device_operations device_ops = {
736 .read_resources = pci_bus_read_resources,
737 .set_resources = pci_dev_set_resources,
738 .enable_resources = pci_bus_enable_resources,
739 .init = pci_init,
740 .enable = pch_pcie_enable,
741 .scan_bus = pciexp_scan_bridge,
742 .ops_pci = &pci_ops,
743};
744
Duncan Laurie74c0d052012-12-17 11:31:40 -0800745static const unsigned short pci_device_ids[] = {
746 /* Lynxpoint Mobile */
747 0x8c10, 0x8c12, 0x8c14, 0x8c16, 0x8c18, 0x8c1a, 0x8c1c, 0x8c1e,
748 /* Lynxpoint Low Power */
749 0x9c10, 0x9c12, 0x9c14, 0x9c16, 0x9c18, 0x9c1a,
750 0
751};
Aaron Durbin76c37002012-10-30 09:03:43 -0500752
753static const struct pci_driver pch_pcie __pci_driver = {
754 .ops = &device_ops,
755 .vendor = PCI_VENDOR_ID_INTEL,
756 .devices = pci_device_ids,
757};