blob: 92dd02e2ed3d1022f5fa1ae0e88e98407673aa11 [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
Tristan Corrick05b75242018-12-06 22:47:42 +130017#include <assert.h>
18#include <commonlib/helpers.h>
Aaron Durbin76c37002012-10-30 09:03:43 -050019#include <console/console.h>
20#include <device/device.h>
21#include <device/pci.h>
Kyösti Mälkkidf128a52019-09-21 18:35:37 +030022#include <device/pci_def.h>
Aaron Durbin76c37002012-10-30 09:03:43 -050023#include <device/pciexp.h>
24#include <device/pci_ids.h>
Patrick Rudolphe56189c2018-04-18 10:11:59 +020025#include <device/pci_ops.h>
Aaron Durbin76c37002012-10-30 09:03:43 -050026#include "pch.h"
Patrick Rudolph273a8dc2016-02-06 18:07:59 +010027#include <southbridge/intel/common/gpio.h>
Tristan Corrick05b75242018-12-06 22:47:42 +130028#include <stddef.h>
29#include <stdint.h>
Kyösti Mälkki12b121c2019-08-18 16:33:39 +030030#include "chip.h"
Aaron Durbin76c37002012-10-30 09:03:43 -050031
Aaron Durbinc0254e62013-06-20 01:20:30 -050032#define MAX_NUM_ROOT_PORTS 8
Aaron Durbinc0254e62013-06-20 01:20:30 -050033
34struct root_port_config {
35 /* RPFN is a write-once register so keep a copy until it is written */
36 u32 orig_rpfn;
37 u32 new_rpfn;
38 u32 pin_ownership;
39 u32 strpfusecfg1;
40 u32 strpfusecfg2;
41 u32 strpfusecfg3;
Stefan Reinauerab365af2013-12-03 12:13:26 -080042 u32 b0d28f0_32c;
43 u32 b0d28f4_32c;
44 u32 b0d28f5_32c;
Aaron Durbinc0254e62013-06-20 01:20:30 -050045 int coalesce;
46 int gbe_port;
47 int num_ports;
Elyes HAOUAS7a5f7712018-06-08 17:20:38 +020048 struct device *ports[MAX_NUM_ROOT_PORTS];
Aaron Durbinc0254e62013-06-20 01:20:30 -050049};
50
51static struct root_port_config rpc;
52
53static inline int max_root_ports(void)
Aaron Durbin60f82082013-06-19 13:28:04 -050054{
Tristan Corrickd3f01b22018-12-06 22:46:58 +130055 if (pch_is_lp() || pch_silicon_id() == PCI_DEVICE_ID_INTEL_LPT_H81)
56 return 6;
57
58 return 8;
Aaron Durbin60f82082013-06-19 13:28:04 -050059}
60
Elyes HAOUAS7a5f7712018-06-08 17:20:38 +020061static inline int root_port_is_first(struct device *dev)
Aaron Durbin60f82082013-06-19 13:28:04 -050062{
Aaron Durbinc0254e62013-06-20 01:20:30 -050063 return PCI_FUNC(dev->path.pci.devfn) == 0;
64}
Aaron Durbin60f82082013-06-19 13:28:04 -050065
Elyes HAOUAS7a5f7712018-06-08 17:20:38 +020066static inline int root_port_is_last(struct device *dev)
Aaron Durbinc0254e62013-06-20 01:20:30 -050067{
68 return PCI_FUNC(dev->path.pci.devfn) == (rpc.num_ports - 1);
69}
Aaron Durbin60f82082013-06-19 13:28:04 -050070
Aaron Durbinc0254e62013-06-20 01:20:30 -050071/* Root ports are numbered 1..N in the documentation. */
Elyes HAOUAS7a5f7712018-06-08 17:20:38 +020072static inline int root_port_number(struct device *dev)
Aaron Durbinc0254e62013-06-20 01:20:30 -050073{
74 return PCI_FUNC(dev->path.pci.devfn) + 1;
75}
Aaron Durbin60f82082013-06-19 13:28:04 -050076
Tristan Corrick05b75242018-12-06 22:47:42 +130077static bool is_rp_enabled(int rp)
78{
79 ASSERT(rp > 0 && rp <= ARRAY_SIZE(rpc.ports));
80
81 if (rpc.ports[rp - 1] == NULL)
82 return false;
83
84 return rpc.ports[rp - 1]->enabled;
85}
86
Aaron Durbinc0254e62013-06-20 01:20:30 -050087static void root_port_config_update_gbe_port(void)
88{
89 /* Is the Gbe Port enabled? */
90 if (!((rpc.strpfusecfg1 >> 19) & 1))
91 return;
92
93 if (pch_is_lp()) {
94 switch ((rpc.strpfusecfg1 >> 16) & 0x7) {
95 case 0:
96 rpc.gbe_port = 3;
97 break;
98 case 1:
99 rpc.gbe_port = 4;
100 break;
101 case 2:
102 case 3:
103 case 4:
104 case 5:
105 /* Lanes 0-4 of Root Port 5. */
106 rpc.gbe_port = 5;
107 break;
108 default:
109 printk(BIOS_DEBUG, "Invalid GbE Port Selection.\n");
110 }
111 } else {
112 /* Non-LP has 1:1 mapping with root ports. */
113 rpc.gbe_port = ((rpc.strpfusecfg1 >> 16) & 0x7) + 1;
114 }
115}
116
Elyes HAOUAS7a5f7712018-06-08 17:20:38 +0200117static void root_port_init_config(struct device *dev)
Aaron Durbinc0254e62013-06-20 01:20:30 -0500118{
119 int rp;
120
121 if (root_port_is_first(dev)) {
122 rpc.orig_rpfn = RCBA32(RPFN);
123 rpc.new_rpfn = rpc.orig_rpfn;
124 rpc.num_ports = max_root_ports();
125 rpc.gbe_port = -1;
126
127 rpc.pin_ownership = pci_read_config32(dev, 0x410);
128 root_port_config_update_gbe_port();
129
130 if (dev->chip_info != NULL) {
131 struct southbridge_intel_lynxpoint_config *config;
132
133 config = dev->chip_info;
134 rpc.coalesce = config->pcie_port_coalesce;
135 }
136 }
137
138 rp = root_port_number(dev);
139 if (rp > rpc.num_ports) {
140 printk(BIOS_ERR, "Found Root Port %d, expecting %d\n",
141 rp, rpc.num_ports);
142 return;
143 }
144
145 /* Read the fuse configuration and pin ownership. */
146 switch (rp) {
147 case 1:
148 rpc.strpfusecfg1 = pci_read_config32(dev, 0xfc);
Stefan Reinauerab365af2013-12-03 12:13:26 -0800149 rpc.b0d28f0_32c = pci_read_config32(dev, 0x32c);
Aaron Durbinc0254e62013-06-20 01:20:30 -0500150 break;
151 case 5:
152 rpc.strpfusecfg2 = pci_read_config32(dev, 0xfc);
Stefan Reinauerab365af2013-12-03 12:13:26 -0800153 rpc.b0d28f4_32c = pci_read_config32(dev, 0x32c);
Aaron Durbinc0254e62013-06-20 01:20:30 -0500154 break;
155 case 6:
Stefan Reinauerab365af2013-12-03 12:13:26 -0800156 rpc.b0d28f5_32c = pci_read_config32(dev, 0x32c);
Aaron Durbinc0254e62013-06-20 01:20:30 -0500157 rpc.strpfusecfg3 = pci_read_config32(dev, 0xfc);
158 break;
159 default:
160 break;
161 }
162
163 /* Cache pci device. */
164 rpc.ports[rp - 1] = dev;
Aaron Durbin60f82082013-06-19 13:28:04 -0500165}
166
167/* Update devicetree with new Root Port function number assignment */
Aaron Durbinc0254e62013-06-20 01:20:30 -0500168static void pch_pcie_device_set_func(int index, int pci_func)
Aaron Durbin60f82082013-06-19 13:28:04 -0500169{
Elyes HAOUAS7a5f7712018-06-08 17:20:38 +0200170 struct device *dev;
Martin Rothff744bf2019-10-23 21:46:03 -0600171 unsigned int new_devfn;
Aaron Durbin60f82082013-06-19 13:28:04 -0500172
Aaron Durbinc0254e62013-06-20 01:20:30 -0500173 dev = rpc.ports[index];
Aaron Durbin60f82082013-06-19 13:28:04 -0500174
Aaron Durbinc0254e62013-06-20 01:20:30 -0500175 /* Set the new PCI function field for this Root Port. */
176 rpc.new_rpfn &= ~RPFN_FNMASK(index);
177 rpc.new_rpfn |= RPFN_FNSET(index, pci_func);
Aaron Durbin60f82082013-06-19 13:28:04 -0500178
Aaron Durbinc0254e62013-06-20 01:20:30 -0500179 /* Determine the new devfn for this port */
180 new_devfn = PCI_DEVFN(PCH_PCIE_DEV_SLOT, pci_func);
Aaron Durbin60f82082013-06-19 13:28:04 -0500181
Tristan Corrick05b75242018-12-06 22:47:42 +1300182 if (dev && dev->path.pci.devfn != new_devfn) {
Aaron Durbinc0254e62013-06-20 01:20:30 -0500183 printk(BIOS_DEBUG,
184 "PCH: PCIe map %02x.%1x -> %02x.%1x\n",
185 PCI_SLOT(dev->path.pci.devfn),
186 PCI_FUNC(dev->path.pci.devfn),
187 PCI_SLOT(new_devfn), PCI_FUNC(new_devfn));
Aaron Durbin60f82082013-06-19 13:28:04 -0500188
Aaron Durbinc0254e62013-06-20 01:20:30 -0500189 dev->path.pci.devfn = new_devfn;
Aaron Durbin60f82082013-06-19 13:28:04 -0500190 }
191}
192
Aaron Durbin1c4289d2013-06-21 14:06:11 -0500193static void pcie_enable_clock_gating(void)
194{
195 int i;
196 int is_lp;
197 int enabled_ports;
198
199 is_lp = pch_is_lp();
200 enabled_ports = 0;
201
202 for (i = 0; i < rpc.num_ports; i++) {
Elyes HAOUAS7a5f7712018-06-08 17:20:38 +0200203 struct device *dev;
Aaron Durbin1c4289d2013-06-21 14:06:11 -0500204 int rp;
205
206 dev = rpc.ports[i];
Tristan Corrick05b75242018-12-06 22:47:42 +1300207 if (!dev)
208 continue;
209
Aaron Durbin1c4289d2013-06-21 14:06:11 -0500210 rp = root_port_number(dev);
211
Tristan Corrick05b75242018-12-06 22:47:42 +1300212 if (!is_rp_enabled(rp)) {
Ryan Salsamendi3f2fe182017-07-04 13:14:16 -0700213 static const uint32_t high_bit = (1UL << 31);
214
Aaron Durbin1c4289d2013-06-21 14:06:11 -0500215 /* Configure shared resource clock gating. */
216 if (rp == 1 || rp == 5 || (rp == 6 && is_lp))
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300217 pci_update_config8(dev, 0xe1, 0xc3, 0x3c);
Aaron Durbin1c4289d2013-06-21 14:06:11 -0500218
219 if (!is_lp) {
Tristan Corrick05b75242018-12-06 22:47:42 +1300220 if (rp == 1 && !is_rp_enabled(2) &&
221 !is_rp_enabled(3) && !is_rp_enabled(4)) {
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300222 pci_update_config8(dev, 0xe2, ~1, 1);
223 pci_update_config8(dev, 0xe1, 0x7f, 0x80);
Aaron Durbin1c4289d2013-06-21 14:06:11 -0500224 }
Tristan Corrick05b75242018-12-06 22:47:42 +1300225 if (rp == 5 && !is_rp_enabled(6) &&
226 !is_rp_enabled(7) && !is_rp_enabled(8)) {
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300227 pci_update_config8(dev, 0xe2, ~1, 1);
228 pci_update_config8(dev, 0xe1, 0x7f, 0x80);
Aaron Durbin1c4289d2013-06-21 14:06:11 -0500229 }
230 continue;
231 }
232
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300233 pci_update_config8(dev, 0xe2, ~(3 << 4), (3 << 4));
Ryan Salsamendi3f2fe182017-07-04 13:14:16 -0700234 pci_update_config32(dev, 0x420, ~high_bit, high_bit);
Aaron Durbin1c4289d2013-06-21 14:06:11 -0500235
236 /* Per-Port CLKREQ# handling. */
237 if (is_lp && gpio_is_native(18 + rp - 1))
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300238 pci_update_config32(dev, 0x420, ~0, (3 << 29));
Aaron Durbin1c4289d2013-06-21 14:06:11 -0500239
240 /* Enable static clock gating. */
Tristan Corrick05b75242018-12-06 22:47:42 +1300241 if (rp == 1 && !is_rp_enabled(2) &&
242 !is_rp_enabled(3) && !is_rp_enabled(4)) {
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300243 pci_update_config8(dev, 0xe2, ~1, 1);
244 pci_update_config8(dev, 0xe1, 0x7f, 0x80);
Aaron Durbin1c4289d2013-06-21 14:06:11 -0500245 } else if (rp == 5 || rp == 6) {
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300246 pci_update_config8(dev, 0xe2, ~1, 1);
247 pci_update_config8(dev, 0xe1, 0x7f, 0x80);
Aaron Durbin1c4289d2013-06-21 14:06:11 -0500248 }
249 continue;
250 }
251
252 enabled_ports++;
253
254 /* Enable dynamic clock gating. */
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300255 pci_update_config8(dev, 0xe1, 0xfc, 0x03);
Aaron Durbin1c4289d2013-06-21 14:06:11 -0500256
257 if (is_lp) {
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300258 pci_update_config8(dev, 0xe2, ~(1 << 6), (1 << 6));
259 pci_update_config8(dev, 0xe8, ~(3 << 2), (2 << 2));
Aaron Durbin1c4289d2013-06-21 14:06:11 -0500260 }
261
262 /* Update PECR1 register. */
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300263 pci_update_config8(dev, 0xe8, ~0, 1);
Aaron Durbin1c4289d2013-06-21 14:06:11 -0500264
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300265 pci_update_config8(dev, 0x324, ~(1 << 5), (1 < 5));
Aaron Durbin1c4289d2013-06-21 14:06:11 -0500266
267 /* Per-Port CLKREQ# handling. */
268 if (is_lp && gpio_is_native(18 + rp - 1))
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300269 pci_update_config32(dev, 0x420, ~0, (3 << 29));
Aaron Durbin1c4289d2013-06-21 14:06:11 -0500270
271 /* Configure shared resource clock gating. */
272 if (rp == 1 || rp == 5 || (rp == 6 && is_lp))
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300273 pci_update_config8(dev, 0xe1, 0xc3, 0x3c);
Aaron Durbin1c4289d2013-06-21 14:06:11 -0500274 }
275
Tristan Corrick05b75242018-12-06 22:47:42 +1300276 if (!enabled_ports && is_lp && rpc.ports[0])
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300277 pci_update_config8(rpc.ports[0], 0xe1, ~(1 << 6), (1 << 6));
Aaron Durbin1c4289d2013-06-21 14:06:11 -0500278}
279
Aaron Durbinc0254e62013-06-20 01:20:30 -0500280static void root_port_commit_config(void)
Aaron Durbin60f82082013-06-19 13:28:04 -0500281{
Aaron Durbinc0254e62013-06-20 01:20:30 -0500282 int i;
Aaron Durbin60f82082013-06-19 13:28:04 -0500283
Aaron Durbinc0254e62013-06-20 01:20:30 -0500284 /* If the first root port is disabled the coalesce ports. */
Tristan Corrick05b75242018-12-06 22:47:42 +1300285 if (!is_rp_enabled(1))
Aaron Durbinc0254e62013-06-20 01:20:30 -0500286 rpc.coalesce = 1;
Aaron Durbin60f82082013-06-19 13:28:04 -0500287
Aaron Durbin1c4289d2013-06-21 14:06:11 -0500288 /* Perform clock gating configuration. */
289 pcie_enable_clock_gating();
290
Aaron Durbinc0254e62013-06-20 01:20:30 -0500291 for (i = 0; i < rpc.num_ports; i++) {
Elyes HAOUAS7a5f7712018-06-08 17:20:38 +0200292 struct device *dev;
Aaron Durbinc0254e62013-06-20 01:20:30 -0500293 u32 reg32;
Aaron Durbin60f82082013-06-19 13:28:04 -0500294
Aaron Durbinc0254e62013-06-20 01:20:30 -0500295 dev = rpc.ports[i];
Aaron Durbin60f82082013-06-19 13:28:04 -0500296
Aaron Durbinc0254e62013-06-20 01:20:30 -0500297 if (dev == NULL) {
298 printk(BIOS_ERR, "Root Port %d device is NULL?\n", i+1);
299 continue;
Aaron Durbin60f82082013-06-19 13:28:04 -0500300 }
301
Aaron Durbinc0254e62013-06-20 01:20:30 -0500302 if (dev->enabled)
303 continue;
304
305 printk(BIOS_DEBUG, "%s: Disabling device\n", dev_path(dev));
306
Aaron Durbin60f82082013-06-19 13:28:04 -0500307 /* Ensure memory, io, and bus master are all disabled */
308 reg32 = pci_read_config32(dev, PCI_COMMAND);
309 reg32 &= ~(PCI_COMMAND_MASTER |
310 PCI_COMMAND_MEMORY | PCI_COMMAND_IO);
311 pci_write_config32(dev, PCI_COMMAND, reg32);
312
Aaron Durbin60f82082013-06-19 13:28:04 -0500313 /* Disable this device if possible */
314 pch_disable_devfn(dev);
Aaron Durbin60f82082013-06-19 13:28:04 -0500315 }
316
Aaron Durbinc0254e62013-06-20 01:20:30 -0500317 if (rpc.coalesce) {
318 int current_func;
Aaron Durbin60f82082013-06-19 13:28:04 -0500319
Aaron Durbinc0254e62013-06-20 01:20:30 -0500320 /* For all Root Ports N enabled ports get assigned the lower
321 * PCI function number. The disabled ones get upper PCI
322 * function numbers. */
323 current_func = 0;
324 for (i = 0; i < rpc.num_ports; i++) {
Tristan Corrick05b75242018-12-06 22:47:42 +1300325 if (!is_rp_enabled(i + 1))
Aaron Durbinc0254e62013-06-20 01:20:30 -0500326 continue;
327 pch_pcie_device_set_func(i, current_func);
328 current_func++;
329 }
330
331 /* Allocate the disabled devices' PCI function number. */
332 for (i = 0; i < rpc.num_ports; i++) {
Tristan Corrick05b75242018-12-06 22:47:42 +1300333 if (is_rp_enabled(i + 1))
Aaron Durbinc0254e62013-06-20 01:20:30 -0500334 continue;
335 pch_pcie_device_set_func(i, current_func);
336 current_func++;
337 }
338 }
339
340 printk(BIOS_SPEW, "PCH: RPFN 0x%08x -> 0x%08x\n",
341 rpc.orig_rpfn, rpc.new_rpfn);
342 RCBA32(RPFN) = rpc.new_rpfn;
343}
344
Elyes HAOUAS7a5f7712018-06-08 17:20:38 +0200345static void root_port_mark_disable(struct device *dev)
Aaron Durbinc0254e62013-06-20 01:20:30 -0500346{
347 /* Mark device as disabled. */
348 dev->enabled = 0;
349 /* Mark device to be hidden. */
350 rpc.new_rpfn |= RPFN_HIDE(PCI_FUNC(dev->path.pci.devfn));
351}
352
Elyes HAOUAS7a5f7712018-06-08 17:20:38 +0200353static void root_port_check_disable(struct device *dev)
Aaron Durbinc0254e62013-06-20 01:20:30 -0500354{
355 int rp;
356 int is_lp;
357
358 /* Device already disabled. */
359 if (!dev->enabled) {
360 root_port_mark_disable(dev);
361 return;
362 }
363
364 rp = root_port_number(dev);
365
366 /* Is the GbE port mapped to this Root Port? */
367 if (rp == rpc.gbe_port) {
368 root_port_mark_disable(dev);
369 return;
370 }
371
372 is_lp = pch_is_lp();
373
374 /* Check Root Port Configuration. */
375 switch (rp) {
376 case 2:
377 /* Root Port 2 is disabled for all lane configurations
378 * but config 00b (4x1 links). */
379 if ((rpc.strpfusecfg1 >> 14) & 0x3) {
380 root_port_mark_disable(dev);
381 return;
382 }
383 break;
384 case 3:
385 /* Root Port 3 is disabled in config 11b (1x4 links). */
386 if (((rpc.strpfusecfg1 >> 14) & 0x3) == 0x3) {
387 root_port_mark_disable(dev);
388 return;
389 }
390 break;
391 case 4:
392 /* Root Port 4 is disabled in configs 11b (1x4 links)
393 * and 10b (2x2 links). */
394 if ((rpc.strpfusecfg1 >> 14) & 0x2) {
395 root_port_mark_disable(dev);
396 return;
397 }
398 break;
399 case 6:
400 if (is_lp)
401 break;
402 /* Root Port 6 is disabled for all lane configurations
403 * but config 00b (4x1 links). */
404 if ((rpc.strpfusecfg2 >> 14) & 0x3) {
405 root_port_mark_disable(dev);
406 return;
407 }
408 break;
409 case 7:
410 if (is_lp)
411 break;
Tristan Corrickbaa4c072018-12-06 22:47:21 +1300412 /* Root Port 7 is disabled in config 11b (1x4 links). */
Aaron Durbinc0254e62013-06-20 01:20:30 -0500413 if (((rpc.strpfusecfg2 >> 14) & 0x3) == 0x3) {
414 root_port_mark_disable(dev);
415 return;
416 }
417 break;
418 case 8:
419 if (is_lp)
420 break;
421 /* Root Port 8 is disabled in configs 11b (1x4 links)
422 * and 10b (2x2 links). */
423 if ((rpc.strpfusecfg2 >> 14) & 0x2) {
424 root_port_mark_disable(dev);
425 return;
426 }
427 break;
428 }
429
430 /* Check Pin Ownership. */
431 if (is_lp) {
432 switch (rp) {
433 case 1:
434 /* Bit 0 is Root Port 1 ownership. */
435 if ((rpc.pin_ownership & 0x1) == 0) {
436 root_port_mark_disable(dev);
437 return;
438 }
439 break;
440 case 2:
441 /* Bit 2 is Root Port 2 ownership. */
442 if ((rpc.pin_ownership & 0x4) == 0) {
443 root_port_mark_disable(dev);
444 return;
445 }
446 break;
447 case 6:
448 /* Bits 7:4 are Root Port 6 pin-lane ownership. */
449 if ((rpc.pin_ownership & 0xf0) == 0) {
450 root_port_mark_disable(dev);
451 return;
452 }
453 break;
454 }
455 } else {
456 switch (rp) {
457 case 1:
458 /* Bits 4 and 0 are Root Port 1 ownership. */
459 if ((rpc.pin_ownership & 0x11) == 0) {
460 root_port_mark_disable(dev);
461 return;
462 }
463 break;
464 case 2:
465 /* Bits 5 and 2 are Root Port 2 ownership. */
466 if ((rpc.pin_ownership & 0x24) == 0) {
467 root_port_mark_disable(dev);
468 return;
469 }
470 break;
471 }
Aaron Durbin60f82082013-06-19 13:28:04 -0500472 }
473}
474
Stefan Reinauerab365af2013-12-03 12:13:26 -0800475static void pcie_add_0x0202000_iobp(u32 reg)
476{
477 u32 reg32;
Aaron Durbin76c37002012-10-30 09:03:43 -0500478
Stefan Reinauerab365af2013-12-03 12:13:26 -0800479 reg32 = pch_iobp_read(reg);
480 reg32 += (0x2 << 16) | (0x2 << 8);
481 pch_iobp_write(reg, reg32);
482}
Aaron Durbin76c37002012-10-30 09:03:43 -0500483
Stefan Reinauerab365af2013-12-03 12:13:26 -0800484static void pch_pcie_early(struct device *dev)
485{
486 int rp;
487 int do_aspm;
488 int is_lp;
Duncan Laurie249a03b2013-08-09 09:06:41 -0700489 struct southbridge_intel_lynxpoint_config *config = dev->chip_info;
Aaron Durbin76c37002012-10-30 09:03:43 -0500490
Stefan Reinauerab365af2013-12-03 12:13:26 -0800491 rp = root_port_number(dev);
492 do_aspm = 0;
493 is_lp = pch_is_lp();
Aaron Durbin76c37002012-10-30 09:03:43 -0500494
Stefan Reinauerab365af2013-12-03 12:13:26 -0800495 if (is_lp) {
496 switch (rp) {
497 case 1:
498 case 2:
499 case 3:
500 case 4:
501 /* Bits 31:28 of b0d28f0 0x32c register correspnd to
502 * Root Ports 4:1. */
503 do_aspm = !!(rpc.b0d28f0_32c & (1 << (28 + rp - 1)));
504 break;
505 case 5:
506 /* Bit 28 of b0d28f4 0x32c register correspnd to
507 * Root Ports 4:1. */
508 do_aspm = !!(rpc.b0d28f4_32c & (1 << 28));
509 break;
510 case 6:
511 /* Bit 28 of b0d28f5 0x32c register correspnd to
512 * Root Ports 4:1. */
513 do_aspm = !!(rpc.b0d28f5_32c & (1 << 28));
514 break;
515 }
516 } else {
517 switch (rp) {
518 case 1:
519 case 2:
520 case 3:
521 case 4:
522 /* Bits 31:28 of b0d28f0 0x32c register correspnd to
523 * Root Ports 4:1. */
524 do_aspm = !!(rpc.b0d28f0_32c & (1 << (28 + rp - 1)));
525 break;
526 case 5:
527 case 6:
528 case 7:
529 case 8:
530 /* Bit 31:28 of b0d28f4 0x32c register correspnd to
531 * Root Ports 8:5. */
532 do_aspm = !!(rpc.b0d28f4_32c & (1 << (28 + rp - 5)));
533 break;
534 }
Aaron Durbin76c37002012-10-30 09:03:43 -0500535 }
Stefan Reinauerab365af2013-12-03 12:13:26 -0800536
Duncan Laurie249a03b2013-08-09 09:06:41 -0700537 /* Allow ASPM to be forced on in devicetree */
538 if (config && (config->pcie_port_force_aspm & (1 << (rp - 1))))
539 do_aspm = 1;
540
541 printk(BIOS_DEBUG, "PCIe Root Port %d ASPM is %sabled\n",
542 rp, do_aspm ? "en" : "dis");
543
Stefan Reinauerab365af2013-12-03 12:13:26 -0800544 if (do_aspm) {
545 /* Set ASPM bits in MPC2 register. */
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300546 pci_update_config32(dev, 0xd4, ~(0x3 << 2), (1 << 4) | (0x2 << 2));
Stefan Reinauerab365af2013-12-03 12:13:26 -0800547
548 /* Set unique clock exit latency in MPC register. */
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300549 pci_update_config32(dev, 0xd8, ~(0x7 << 18), (0x7 << 18));
Stefan Reinauerab365af2013-12-03 12:13:26 -0800550
551 /* Set L1 exit latency in LCAP register. */
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300552 pci_update_config32(dev, 0x4c, ~(0x7 << 15), (0x4 << 15));
Stefan Reinauerab365af2013-12-03 12:13:26 -0800553
554 if (is_lp) {
555 switch (rp) {
556 case 1:
557 pcie_add_0x0202000_iobp(0xe9002440);
558 break;
559 case 2:
560 pcie_add_0x0202000_iobp(0xe9002640);
561 break;
562 case 3:
563 pcie_add_0x0202000_iobp(0xe9000840);
564 break;
565 case 4:
566 pcie_add_0x0202000_iobp(0xe9000a40);
567 break;
568 case 5:
569 pcie_add_0x0202000_iobp(0xe9000c40);
570 pcie_add_0x0202000_iobp(0xe9000e40);
571 pcie_add_0x0202000_iobp(0xe9001040);
572 pcie_add_0x0202000_iobp(0xe9001240);
573 break;
574 case 6:
575 /* Update IOBP based on lane ownership. */
576 if (rpc.pin_ownership & (1 << 4))
577 pcie_add_0x0202000_iobp(0xea002040);
578 if (rpc.pin_ownership & (1 << 5))
579 pcie_add_0x0202000_iobp(0xea002240);
580 if (rpc.pin_ownership & (1 << 6))
581 pcie_add_0x0202000_iobp(0xea002440);
582 if (rpc.pin_ownership & (1 << 7))
583 pcie_add_0x0202000_iobp(0xea002640);
584 break;
585 }
586 } else {
587 switch (rp) {
588 case 1:
589 if ((rpc.pin_ownership & 0x3) == 1)
590 pcie_add_0x0202000_iobp(0xe9002e40);
591 else
592 pcie_add_0x0202000_iobp(0xea002040);
593 break;
594 case 2:
595 if ((rpc.pin_ownership & 0xc) == 0x4)
596 pcie_add_0x0202000_iobp(0xe9002c40);
597 else
598 pcie_add_0x0202000_iobp(0xea002240);
599 break;
600 case 3:
601 pcie_add_0x0202000_iobp(0xe9002a40);
602 break;
603 case 4:
604 pcie_add_0x0202000_iobp(0xe9002840);
605 break;
606 case 5:
607 pcie_add_0x0202000_iobp(0xe9002640);
608 break;
609 case 6:
610 pcie_add_0x0202000_iobp(0xe9002440);
611 break;
612 case 7:
613 pcie_add_0x0202000_iobp(0xe9002240);
614 break;
615 case 8:
616 pcie_add_0x0202000_iobp(0xe9002040);
617 break;
618 }
619 }
620
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300621 pci_update_config32(dev, 0x338, ~(1 << 26), 0);
Stefan Reinauerab365af2013-12-03 12:13:26 -0800622 }
623
624 /* Enable LTR in Root Port. */
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300625 pci_update_config32(dev, 0x64, ~(1 << 11), (1 << 11));
626 pci_update_config32(dev, 0x68, ~(1 << 10), (1 << 10));
Stefan Reinauerab365af2013-12-03 12:13:26 -0800627
Ryan Salsamendi0d9b3602017-06-30 17:15:57 -0700628 pci_update_config32(dev, 0x318, ~(0xffffUL << 16), (0x1414UL << 16));
Stefan Reinauerab365af2013-12-03 12:13:26 -0800629
630 /* Set L1 exit latency in LCAP register. */
631 if (!do_aspm && (pci_read_config8(dev, 0xf5) & 0x1))
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300632 pci_update_config32(dev, 0x4c, ~(0x7 << 15), (0x4 << 15));
Stefan Reinauerab365af2013-12-03 12:13:26 -0800633 else
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300634 pci_update_config32(dev, 0x4c, ~(0x7 << 15), (0x2 << 15));
Stefan Reinauerab365af2013-12-03 12:13:26 -0800635
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300636 pci_update_config32(dev, 0x314, 0x0, 0x743a361b);
Stefan Reinauerab365af2013-12-03 12:13:26 -0800637
638 /* Set Common Clock Exit Latency in MPC register. */
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300639 pci_update_config32(dev, 0xd8, ~(0x7 << 15), (0x3 << 15));
Stefan Reinauerab365af2013-12-03 12:13:26 -0800640
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300641 pci_update_config32(dev, 0x33c, ~0x00ffffff, 0x854c74);
Stefan Reinauerab365af2013-12-03 12:13:26 -0800642
Stefan Reinauerab365af2013-12-03 12:13:26 -0800643 /* Set Invalid Recieve Range Check Enable in MPC register. */
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300644 pci_update_config32(dev, 0xd8, ~0, (1 << 25));
Stefan Reinauerab365af2013-12-03 12:13:26 -0800645
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300646 pci_update_config8(dev, 0xf5, 0x3f, 0);
Stefan Reinauerab365af2013-12-03 12:13:26 -0800647
648 if (rp == 1 || rp == 5 || (is_lp && rp == 6))
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300649 pci_update_config8(dev, 0xf7, ~0xc, 0);
Stefan Reinauerab365af2013-12-03 12:13:26 -0800650
651 /* Set EOI forwarding disable. */
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300652 pci_update_config32(dev, 0xd4, ~0, (1 << 1));
Stefan Reinauerab365af2013-12-03 12:13:26 -0800653
654 /* Set something involving advanced error reporting. */
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300655 pci_update_config32(dev, 0x100, ~((1 << 20) - 1), 0x10001);
Stefan Reinauerab365af2013-12-03 12:13:26 -0800656
657 if (is_lp)
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300658 pci_update_config32(dev, 0x100, ~0, (1 << 29));
Stefan Reinauerab365af2013-12-03 12:13:26 -0800659
660 /* Read and write back write-once capability registers. */
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300661 pci_update_config32(dev, 0x34, ~0, 0);
662 pci_update_config32(dev, 0x40, ~0, 0);
663 pci_update_config32(dev, 0x80, ~0, 0);
664 pci_update_config32(dev, 0x90, ~0, 0);
Aaron Durbin76c37002012-10-30 09:03:43 -0500665}
666
667static void pci_init(struct device *dev)
668{
669 u16 reg16;
670 u32 reg32;
671
672 printk(BIOS_DEBUG, "Initializing PCH PCIe bridge.\n");
673
Aaron Durbinc0254e62013-06-20 01:20:30 -0500674 /* Enable SERR */
675 reg32 = pci_read_config32(dev, PCI_COMMAND);
676 reg32 |= PCI_COMMAND_SERR;
677 pci_write_config32(dev, PCI_COMMAND, reg32);
678
Aaron Durbin76c37002012-10-30 09:03:43 -0500679 /* Enable Bus Master */
680 reg32 = pci_read_config32(dev, PCI_COMMAND);
681 reg32 |= PCI_COMMAND_MASTER;
682 pci_write_config32(dev, PCI_COMMAND, reg32);
683
684 /* Set Cache Line Size to 0x10 */
685 // This has no effect but the OS might expect it
686 pci_write_config8(dev, 0x0c, 0x10);
687
Kyösti Mälkkidf128a52019-09-21 18:35:37 +0300688 reg16 = pci_read_config16(dev, PCI_BRIDGE_CONTROL);
689 reg16 &= ~PCI_BRIDGE_CTL_PARITY;
690 reg16 |= PCI_BRIDGE_CTL_NO_ISA;
691 pci_write_config16(dev, PCI_BRIDGE_CONTROL, reg16);
Aaron Durbin76c37002012-10-30 09:03:43 -0500692
693#ifdef EVEN_MORE_DEBUG
694 reg32 = pci_read_config32(dev, 0x20);
695 printk(BIOS_SPEW, " MBL = 0x%08x\n", reg32);
696 reg32 = pci_read_config32(dev, 0x24);
697 printk(BIOS_SPEW, " PMBL = 0x%08x\n", reg32);
698 reg32 = pci_read_config32(dev, 0x28);
699 printk(BIOS_SPEW, " PMBU32 = 0x%08x\n", reg32);
700 reg32 = pci_read_config32(dev, 0x2c);
701 printk(BIOS_SPEW, " PMLU32 = 0x%08x\n", reg32);
702#endif
703
704 /* Clear errors in status registers */
705 reg16 = pci_read_config16(dev, 0x06);
Aaron Durbin76c37002012-10-30 09:03:43 -0500706 pci_write_config16(dev, 0x06, reg16);
Aaron Durbin76c37002012-10-30 09:03:43 -0500707 reg16 = pci_read_config16(dev, 0x1e);
Aaron Durbin76c37002012-10-30 09:03:43 -0500708 pci_write_config16(dev, 0x1e, reg16);
Aaron Durbin76c37002012-10-30 09:03:43 -0500709}
710
Elyes HAOUAS7a5f7712018-06-08 17:20:38 +0200711static void pch_pcie_enable(struct device *dev)
Aaron Durbin76c37002012-10-30 09:03:43 -0500712{
Aaron Durbinc0254e62013-06-20 01:20:30 -0500713 /* Add this device to the root port config structure. */
714 root_port_init_config(dev);
715
716 /* Check to see if this Root Port should be disabled. */
717 root_port_check_disable(dev);
718
Aaron Durbin76c37002012-10-30 09:03:43 -0500719 /* Power Management init before enumeration */
Aaron Durbinc0254e62013-06-20 01:20:30 -0500720 if (dev->enabled)
Stefan Reinauerab365af2013-12-03 12:13:26 -0800721 pch_pcie_early(dev);
Aaron Durbinc0254e62013-06-20 01:20:30 -0500722
723 /*
724 * When processing the last PCIe root port we can now
725 * update the Root Port Function Number and Hide register.
726 */
727 if (root_port_is_last(dev))
728 root_port_commit_config();
Aaron Durbin76c37002012-10-30 09:03:43 -0500729}
730
Aaron Durbin76c37002012-10-30 09:03:43 -0500731static struct pci_operations pci_ops = {
Subrata Banik15ccbf02019-03-20 15:09:44 +0530732 .set_subsystem = pci_dev_set_subsystem,
Aaron Durbin76c37002012-10-30 09:03:43 -0500733};
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};