blob: 83eac8d023a873512372b341f83f98ca36fb1d9f [file] [log] [blame]
Aaron Durbin76c37002012-10-30 09:03:43 -05001/*
2 * This file is part of the coreboot project.
3 *
Aaron Durbin76c37002012-10-30 09:03:43 -05004 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; version 2 of
8 * the License.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
Aaron Durbin76c37002012-10-30 09:03:43 -050014 */
15
Tristan Corrick05b75242018-12-06 22:47:42 +130016#include <assert.h>
17#include <commonlib/helpers.h>
Aaron Durbin76c37002012-10-30 09:03:43 -050018#include <console/console.h>
19#include <device/device.h>
20#include <device/pci.h>
Kyösti Mälkkidf128a52019-09-21 18:35:37 +030021#include <device/pci_def.h>
Aaron Durbin76c37002012-10-30 09:03:43 -050022#include <device/pciexp.h>
23#include <device/pci_ids.h>
Patrick Rudolphe56189c2018-04-18 10:11:59 +020024#include <device/pci_ops.h>
Aaron Durbin76c37002012-10-30 09:03:43 -050025#include "pch.h"
Patrick Rudolph273a8dc2016-02-06 18:07:59 +010026#include <southbridge/intel/common/gpio.h>
Tristan Corrick05b75242018-12-06 22:47:42 +130027#include <stddef.h>
28#include <stdint.h>
Kyösti Mälkki12b121c2019-08-18 16:33:39 +030029#include "chip.h"
Aaron Durbin76c37002012-10-30 09:03:43 -050030
Aaron Durbinc0254e62013-06-20 01:20:30 -050031#define MAX_NUM_ROOT_PORTS 8
Aaron Durbinc0254e62013-06-20 01:20:30 -050032
33struct root_port_config {
34 /* RPFN is a write-once register so keep a copy until it is written */
35 u32 orig_rpfn;
36 u32 new_rpfn;
37 u32 pin_ownership;
38 u32 strpfusecfg1;
39 u32 strpfusecfg2;
40 u32 strpfusecfg3;
Stefan Reinauerab365af2013-12-03 12:13:26 -080041 u32 b0d28f0_32c;
42 u32 b0d28f4_32c;
43 u32 b0d28f5_32c;
Aaron Durbinc0254e62013-06-20 01:20:30 -050044 int coalesce;
45 int gbe_port;
46 int num_ports;
Elyes HAOUAS7a5f7712018-06-08 17:20:38 +020047 struct device *ports[MAX_NUM_ROOT_PORTS];
Aaron Durbinc0254e62013-06-20 01:20:30 -050048};
49
50static struct root_port_config rpc;
51
52static inline int max_root_ports(void)
Aaron Durbin60f82082013-06-19 13:28:04 -050053{
Tristan Corrickd3f01b22018-12-06 22:46:58 +130054 if (pch_is_lp() || pch_silicon_id() == PCI_DEVICE_ID_INTEL_LPT_H81)
55 return 6;
56
57 return 8;
Aaron Durbin60f82082013-06-19 13:28:04 -050058}
59
Elyes HAOUAS7a5f7712018-06-08 17:20:38 +020060static inline int root_port_is_first(struct device *dev)
Aaron Durbin60f82082013-06-19 13:28:04 -050061{
Aaron Durbinc0254e62013-06-20 01:20:30 -050062 return PCI_FUNC(dev->path.pci.devfn) == 0;
63}
Aaron Durbin60f82082013-06-19 13:28:04 -050064
Elyes HAOUAS7a5f7712018-06-08 17:20:38 +020065static inline int root_port_is_last(struct device *dev)
Aaron Durbinc0254e62013-06-20 01:20:30 -050066{
67 return PCI_FUNC(dev->path.pci.devfn) == (rpc.num_ports - 1);
68}
Aaron Durbin60f82082013-06-19 13:28:04 -050069
Aaron Durbinc0254e62013-06-20 01:20:30 -050070/* Root ports are numbered 1..N in the documentation. */
Elyes HAOUAS7a5f7712018-06-08 17:20:38 +020071static inline int root_port_number(struct device *dev)
Aaron Durbinc0254e62013-06-20 01:20:30 -050072{
73 return PCI_FUNC(dev->path.pci.devfn) + 1;
74}
Aaron Durbin60f82082013-06-19 13:28:04 -050075
Tristan Corrick05b75242018-12-06 22:47:42 +130076static bool is_rp_enabled(int rp)
77{
78 ASSERT(rp > 0 && rp <= ARRAY_SIZE(rpc.ports));
79
80 if (rpc.ports[rp - 1] == NULL)
81 return false;
82
83 return rpc.ports[rp - 1]->enabled;
84}
85
Aaron Durbinc0254e62013-06-20 01:20:30 -050086static void root_port_config_update_gbe_port(void)
87{
88 /* Is the Gbe Port enabled? */
89 if (!((rpc.strpfusecfg1 >> 19) & 1))
90 return;
91
92 if (pch_is_lp()) {
93 switch ((rpc.strpfusecfg1 >> 16) & 0x7) {
94 case 0:
95 rpc.gbe_port = 3;
96 break;
97 case 1:
98 rpc.gbe_port = 4;
99 break;
100 case 2:
101 case 3:
102 case 4:
103 case 5:
104 /* Lanes 0-4 of Root Port 5. */
105 rpc.gbe_port = 5;
106 break;
107 default:
108 printk(BIOS_DEBUG, "Invalid GbE Port Selection.\n");
109 }
110 } else {
111 /* Non-LP has 1:1 mapping with root ports. */
112 rpc.gbe_port = ((rpc.strpfusecfg1 >> 16) & 0x7) + 1;
113 }
114}
115
Elyes HAOUAS7a5f7712018-06-08 17:20:38 +0200116static void root_port_init_config(struct device *dev)
Aaron Durbinc0254e62013-06-20 01:20:30 -0500117{
118 int rp;
119
120 if (root_port_is_first(dev)) {
121 rpc.orig_rpfn = RCBA32(RPFN);
122 rpc.new_rpfn = rpc.orig_rpfn;
123 rpc.num_ports = max_root_ports();
124 rpc.gbe_port = -1;
125
126 rpc.pin_ownership = pci_read_config32(dev, 0x410);
127 root_port_config_update_gbe_port();
128
129 if (dev->chip_info != NULL) {
130 struct southbridge_intel_lynxpoint_config *config;
131
132 config = dev->chip_info;
133 rpc.coalesce = config->pcie_port_coalesce;
134 }
135 }
136
137 rp = root_port_number(dev);
138 if (rp > rpc.num_ports) {
139 printk(BIOS_ERR, "Found Root Port %d, expecting %d\n",
140 rp, rpc.num_ports);
141 return;
142 }
143
144 /* Read the fuse configuration and pin ownership. */
145 switch (rp) {
146 case 1:
147 rpc.strpfusecfg1 = pci_read_config32(dev, 0xfc);
Stefan Reinauerab365af2013-12-03 12:13:26 -0800148 rpc.b0d28f0_32c = pci_read_config32(dev, 0x32c);
Aaron Durbinc0254e62013-06-20 01:20:30 -0500149 break;
150 case 5:
151 rpc.strpfusecfg2 = pci_read_config32(dev, 0xfc);
Stefan Reinauerab365af2013-12-03 12:13:26 -0800152 rpc.b0d28f4_32c = pci_read_config32(dev, 0x32c);
Aaron Durbinc0254e62013-06-20 01:20:30 -0500153 break;
154 case 6:
Stefan Reinauerab365af2013-12-03 12:13:26 -0800155 rpc.b0d28f5_32c = pci_read_config32(dev, 0x32c);
Aaron Durbinc0254e62013-06-20 01:20:30 -0500156 rpc.strpfusecfg3 = pci_read_config32(dev, 0xfc);
157 break;
158 default:
159 break;
160 }
161
162 /* Cache pci device. */
163 rpc.ports[rp - 1] = dev;
Aaron Durbin60f82082013-06-19 13:28:04 -0500164}
165
166/* Update devicetree with new Root Port function number assignment */
Aaron Durbinc0254e62013-06-20 01:20:30 -0500167static void pch_pcie_device_set_func(int index, int pci_func)
Aaron Durbin60f82082013-06-19 13:28:04 -0500168{
Elyes HAOUAS7a5f7712018-06-08 17:20:38 +0200169 struct device *dev;
Martin Rothff744bf2019-10-23 21:46:03 -0600170 unsigned int new_devfn;
Aaron Durbin60f82082013-06-19 13:28:04 -0500171
Aaron Durbinc0254e62013-06-20 01:20:30 -0500172 dev = rpc.ports[index];
Aaron Durbin60f82082013-06-19 13:28:04 -0500173
Aaron Durbinc0254e62013-06-20 01:20:30 -0500174 /* Set the new PCI function field for this Root Port. */
175 rpc.new_rpfn &= ~RPFN_FNMASK(index);
176 rpc.new_rpfn |= RPFN_FNSET(index, pci_func);
Aaron Durbin60f82082013-06-19 13:28:04 -0500177
Aaron Durbinc0254e62013-06-20 01:20:30 -0500178 /* Determine the new devfn for this port */
179 new_devfn = PCI_DEVFN(PCH_PCIE_DEV_SLOT, pci_func);
Aaron Durbin60f82082013-06-19 13:28:04 -0500180
Tristan Corrick05b75242018-12-06 22:47:42 +1300181 if (dev && dev->path.pci.devfn != new_devfn) {
Aaron Durbinc0254e62013-06-20 01:20:30 -0500182 printk(BIOS_DEBUG,
183 "PCH: PCIe map %02x.%1x -> %02x.%1x\n",
184 PCI_SLOT(dev->path.pci.devfn),
185 PCI_FUNC(dev->path.pci.devfn),
186 PCI_SLOT(new_devfn), PCI_FUNC(new_devfn));
Aaron Durbin60f82082013-06-19 13:28:04 -0500187
Aaron Durbinc0254e62013-06-20 01:20:30 -0500188 dev->path.pci.devfn = new_devfn;
Aaron Durbin60f82082013-06-19 13:28:04 -0500189 }
190}
191
Aaron Durbin1c4289d2013-06-21 14:06:11 -0500192static void pcie_enable_clock_gating(void)
193{
194 int i;
195 int is_lp;
196 int enabled_ports;
197
198 is_lp = pch_is_lp();
199 enabled_ports = 0;
200
201 for (i = 0; i < rpc.num_ports; i++) {
Elyes HAOUAS7a5f7712018-06-08 17:20:38 +0200202 struct device *dev;
Aaron Durbin1c4289d2013-06-21 14:06:11 -0500203 int rp;
204
205 dev = rpc.ports[i];
Tristan Corrick05b75242018-12-06 22:47:42 +1300206 if (!dev)
207 continue;
208
Aaron Durbin1c4289d2013-06-21 14:06:11 -0500209 rp = root_port_number(dev);
210
Tristan Corrick05b75242018-12-06 22:47:42 +1300211 if (!is_rp_enabled(rp)) {
Ryan Salsamendi3f2fe182017-07-04 13:14:16 -0700212 static const uint32_t high_bit = (1UL << 31);
213
Aaron Durbin1c4289d2013-06-21 14:06:11 -0500214 /* Configure shared resource clock gating. */
215 if (rp == 1 || rp == 5 || (rp == 6 && is_lp))
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300216 pci_update_config8(dev, 0xe1, 0xc3, 0x3c);
Aaron Durbin1c4289d2013-06-21 14:06:11 -0500217
218 if (!is_lp) {
Tristan Corrick05b75242018-12-06 22:47:42 +1300219 if (rp == 1 && !is_rp_enabled(2) &&
220 !is_rp_enabled(3) && !is_rp_enabled(4)) {
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300221 pci_update_config8(dev, 0xe2, ~1, 1);
222 pci_update_config8(dev, 0xe1, 0x7f, 0x80);
Aaron Durbin1c4289d2013-06-21 14:06:11 -0500223 }
Tristan Corrick05b75242018-12-06 22:47:42 +1300224 if (rp == 5 && !is_rp_enabled(6) &&
225 !is_rp_enabled(7) && !is_rp_enabled(8)) {
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 }
229 continue;
230 }
231
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300232 pci_update_config8(dev, 0xe2, ~(3 << 4), (3 << 4));
Ryan Salsamendi3f2fe182017-07-04 13:14:16 -0700233 pci_update_config32(dev, 0x420, ~high_bit, high_bit);
Aaron Durbin1c4289d2013-06-21 14:06:11 -0500234
235 /* Per-Port CLKREQ# handling. */
236 if (is_lp && gpio_is_native(18 + rp - 1))
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300237 pci_update_config32(dev, 0x420, ~0, (3 << 29));
Aaron Durbin1c4289d2013-06-21 14:06:11 -0500238
239 /* Enable static clock gating. */
Tristan Corrick05b75242018-12-06 22:47:42 +1300240 if (rp == 1 && !is_rp_enabled(2) &&
241 !is_rp_enabled(3) && !is_rp_enabled(4)) {
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300242 pci_update_config8(dev, 0xe2, ~1, 1);
243 pci_update_config8(dev, 0xe1, 0x7f, 0x80);
Aaron Durbin1c4289d2013-06-21 14:06:11 -0500244 } else if (rp == 5 || rp == 6) {
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300245 pci_update_config8(dev, 0xe2, ~1, 1);
246 pci_update_config8(dev, 0xe1, 0x7f, 0x80);
Aaron Durbin1c4289d2013-06-21 14:06:11 -0500247 }
248 continue;
249 }
250
251 enabled_ports++;
252
253 /* Enable dynamic clock gating. */
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300254 pci_update_config8(dev, 0xe1, 0xfc, 0x03);
Aaron Durbin1c4289d2013-06-21 14:06:11 -0500255
256 if (is_lp) {
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300257 pci_update_config8(dev, 0xe2, ~(1 << 6), (1 << 6));
258 pci_update_config8(dev, 0xe8, ~(3 << 2), (2 << 2));
Aaron Durbin1c4289d2013-06-21 14:06:11 -0500259 }
260
261 /* Update PECR1 register. */
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300262 pci_update_config8(dev, 0xe8, ~0, 1);
Aaron Durbin1c4289d2013-06-21 14:06:11 -0500263
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300264 pci_update_config8(dev, 0x324, ~(1 << 5), (1 < 5));
Aaron Durbin1c4289d2013-06-21 14:06:11 -0500265
266 /* Per-Port CLKREQ# handling. */
267 if (is_lp && gpio_is_native(18 + rp - 1))
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300268 pci_update_config32(dev, 0x420, ~0, (3 << 29));
Aaron Durbin1c4289d2013-06-21 14:06:11 -0500269
270 /* Configure shared resource clock gating. */
271 if (rp == 1 || rp == 5 || (rp == 6 && is_lp))
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300272 pci_update_config8(dev, 0xe1, 0xc3, 0x3c);
Aaron Durbin1c4289d2013-06-21 14:06:11 -0500273 }
274
Tristan Corrick05b75242018-12-06 22:47:42 +1300275 if (!enabled_ports && is_lp && rpc.ports[0])
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300276 pci_update_config8(rpc.ports[0], 0xe1, ~(1 << 6), (1 << 6));
Aaron Durbin1c4289d2013-06-21 14:06:11 -0500277}
278
Aaron Durbinc0254e62013-06-20 01:20:30 -0500279static void root_port_commit_config(void)
Aaron Durbin60f82082013-06-19 13:28:04 -0500280{
Aaron Durbinc0254e62013-06-20 01:20:30 -0500281 int i;
Aaron Durbin60f82082013-06-19 13:28:04 -0500282
Aaron Durbinc0254e62013-06-20 01:20:30 -0500283 /* If the first root port is disabled the coalesce ports. */
Tristan Corrick05b75242018-12-06 22:47:42 +1300284 if (!is_rp_enabled(1))
Aaron Durbinc0254e62013-06-20 01:20:30 -0500285 rpc.coalesce = 1;
Aaron Durbin60f82082013-06-19 13:28:04 -0500286
Aaron Durbin1c4289d2013-06-21 14:06:11 -0500287 /* Perform clock gating configuration. */
288 pcie_enable_clock_gating();
289
Aaron Durbinc0254e62013-06-20 01:20:30 -0500290 for (i = 0; i < rpc.num_ports; i++) {
Elyes HAOUAS7a5f7712018-06-08 17:20:38 +0200291 struct device *dev;
Aaron Durbinc0254e62013-06-20 01:20:30 -0500292 u32 reg32;
Aaron Durbin60f82082013-06-19 13:28:04 -0500293
Aaron Durbinc0254e62013-06-20 01:20:30 -0500294 dev = rpc.ports[i];
Aaron Durbin60f82082013-06-19 13:28:04 -0500295
Aaron Durbinc0254e62013-06-20 01:20:30 -0500296 if (dev == NULL) {
297 printk(BIOS_ERR, "Root Port %d device is NULL?\n", i+1);
298 continue;
Aaron Durbin60f82082013-06-19 13:28:04 -0500299 }
300
Aaron Durbinc0254e62013-06-20 01:20:30 -0500301 if (dev->enabled)
302 continue;
303
304 printk(BIOS_DEBUG, "%s: Disabling device\n", dev_path(dev));
305
Aaron Durbin60f82082013-06-19 13:28:04 -0500306 /* Ensure memory, io, and bus master are all disabled */
307 reg32 = pci_read_config32(dev, PCI_COMMAND);
308 reg32 &= ~(PCI_COMMAND_MASTER |
309 PCI_COMMAND_MEMORY | PCI_COMMAND_IO);
310 pci_write_config32(dev, PCI_COMMAND, reg32);
311
Aaron Durbin60f82082013-06-19 13:28:04 -0500312 /* Disable this device if possible */
313 pch_disable_devfn(dev);
Aaron Durbin60f82082013-06-19 13:28:04 -0500314 }
315
Aaron Durbinc0254e62013-06-20 01:20:30 -0500316 if (rpc.coalesce) {
317 int current_func;
Aaron Durbin60f82082013-06-19 13:28:04 -0500318
Aaron Durbinc0254e62013-06-20 01:20:30 -0500319 /* For all Root Ports N enabled ports get assigned the lower
320 * PCI function number. The disabled ones get upper PCI
321 * function numbers. */
322 current_func = 0;
323 for (i = 0; i < rpc.num_ports; i++) {
Tristan Corrick05b75242018-12-06 22:47:42 +1300324 if (!is_rp_enabled(i + 1))
Aaron Durbinc0254e62013-06-20 01:20:30 -0500325 continue;
326 pch_pcie_device_set_func(i, current_func);
327 current_func++;
328 }
329
330 /* Allocate the disabled devices' PCI function number. */
331 for (i = 0; i < rpc.num_ports; i++) {
Tristan Corrick05b75242018-12-06 22:47:42 +1300332 if (is_rp_enabled(i + 1))
Aaron Durbinc0254e62013-06-20 01:20:30 -0500333 continue;
334 pch_pcie_device_set_func(i, current_func);
335 current_func++;
336 }
337 }
338
339 printk(BIOS_SPEW, "PCH: RPFN 0x%08x -> 0x%08x\n",
340 rpc.orig_rpfn, rpc.new_rpfn);
341 RCBA32(RPFN) = rpc.new_rpfn;
342}
343
Elyes HAOUAS7a5f7712018-06-08 17:20:38 +0200344static void root_port_mark_disable(struct device *dev)
Aaron Durbinc0254e62013-06-20 01:20:30 -0500345{
346 /* Mark device as disabled. */
347 dev->enabled = 0;
348 /* Mark device to be hidden. */
349 rpc.new_rpfn |= RPFN_HIDE(PCI_FUNC(dev->path.pci.devfn));
350}
351
Elyes HAOUAS7a5f7712018-06-08 17:20:38 +0200352static void root_port_check_disable(struct device *dev)
Aaron Durbinc0254e62013-06-20 01:20:30 -0500353{
354 int rp;
355 int is_lp;
356
357 /* Device already disabled. */
358 if (!dev->enabled) {
359 root_port_mark_disable(dev);
360 return;
361 }
362
363 rp = root_port_number(dev);
364
365 /* Is the GbE port mapped to this Root Port? */
366 if (rp == rpc.gbe_port) {
367 root_port_mark_disable(dev);
368 return;
369 }
370
371 is_lp = pch_is_lp();
372
373 /* Check Root Port Configuration. */
374 switch (rp) {
375 case 2:
376 /* Root Port 2 is disabled for all lane configurations
377 * but config 00b (4x1 links). */
378 if ((rpc.strpfusecfg1 >> 14) & 0x3) {
379 root_port_mark_disable(dev);
380 return;
381 }
382 break;
383 case 3:
384 /* Root Port 3 is disabled in config 11b (1x4 links). */
385 if (((rpc.strpfusecfg1 >> 14) & 0x3) == 0x3) {
386 root_port_mark_disable(dev);
387 return;
388 }
389 break;
390 case 4:
391 /* Root Port 4 is disabled in configs 11b (1x4 links)
392 * and 10b (2x2 links). */
393 if ((rpc.strpfusecfg1 >> 14) & 0x2) {
394 root_port_mark_disable(dev);
395 return;
396 }
397 break;
398 case 6:
399 if (is_lp)
400 break;
401 /* Root Port 6 is disabled for all lane configurations
402 * but config 00b (4x1 links). */
403 if ((rpc.strpfusecfg2 >> 14) & 0x3) {
404 root_port_mark_disable(dev);
405 return;
406 }
407 break;
408 case 7:
409 if (is_lp)
410 break;
Tristan Corrickbaa4c072018-12-06 22:47:21 +1300411 /* Root Port 7 is disabled in config 11b (1x4 links). */
Aaron Durbinc0254e62013-06-20 01:20:30 -0500412 if (((rpc.strpfusecfg2 >> 14) & 0x3) == 0x3) {
413 root_port_mark_disable(dev);
414 return;
415 }
416 break;
417 case 8:
418 if (is_lp)
419 break;
420 /* Root Port 8 is disabled in configs 11b (1x4 links)
421 * and 10b (2x2 links). */
422 if ((rpc.strpfusecfg2 >> 14) & 0x2) {
423 root_port_mark_disable(dev);
424 return;
425 }
426 break;
427 }
428
429 /* Check Pin Ownership. */
430 if (is_lp) {
431 switch (rp) {
432 case 1:
433 /* Bit 0 is Root Port 1 ownership. */
434 if ((rpc.pin_ownership & 0x1) == 0) {
435 root_port_mark_disable(dev);
436 return;
437 }
438 break;
439 case 2:
440 /* Bit 2 is Root Port 2 ownership. */
441 if ((rpc.pin_ownership & 0x4) == 0) {
442 root_port_mark_disable(dev);
443 return;
444 }
445 break;
446 case 6:
447 /* Bits 7:4 are Root Port 6 pin-lane ownership. */
448 if ((rpc.pin_ownership & 0xf0) == 0) {
449 root_port_mark_disable(dev);
450 return;
451 }
452 break;
453 }
454 } else {
455 switch (rp) {
456 case 1:
457 /* Bits 4 and 0 are Root Port 1 ownership. */
458 if ((rpc.pin_ownership & 0x11) == 0) {
459 root_port_mark_disable(dev);
460 return;
461 }
462 break;
463 case 2:
464 /* Bits 5 and 2 are Root Port 2 ownership. */
465 if ((rpc.pin_ownership & 0x24) == 0) {
466 root_port_mark_disable(dev);
467 return;
468 }
469 break;
470 }
Aaron Durbin60f82082013-06-19 13:28:04 -0500471 }
472}
473
Stefan Reinauerab365af2013-12-03 12:13:26 -0800474static void pcie_add_0x0202000_iobp(u32 reg)
475{
476 u32 reg32;
Aaron Durbin76c37002012-10-30 09:03:43 -0500477
Stefan Reinauerab365af2013-12-03 12:13:26 -0800478 reg32 = pch_iobp_read(reg);
479 reg32 += (0x2 << 16) | (0x2 << 8);
480 pch_iobp_write(reg, reg32);
481}
Aaron Durbin76c37002012-10-30 09:03:43 -0500482
Stefan Reinauerab365af2013-12-03 12:13:26 -0800483static void pch_pcie_early(struct device *dev)
484{
485 int rp;
486 int do_aspm;
487 int is_lp;
Duncan Laurie249a03b2013-08-09 09:06:41 -0700488 struct southbridge_intel_lynxpoint_config *config = dev->chip_info;
Aaron Durbin76c37002012-10-30 09:03:43 -0500489
Stefan Reinauerab365af2013-12-03 12:13:26 -0800490 rp = root_port_number(dev);
491 do_aspm = 0;
492 is_lp = pch_is_lp();
Aaron Durbin76c37002012-10-30 09:03:43 -0500493
Stefan Reinauerab365af2013-12-03 12:13:26 -0800494 if (is_lp) {
495 switch (rp) {
496 case 1:
497 case 2:
498 case 3:
499 case 4:
500 /* Bits 31:28 of b0d28f0 0x32c register correspnd to
501 * Root Ports 4:1. */
502 do_aspm = !!(rpc.b0d28f0_32c & (1 << (28 + rp - 1)));
503 break;
504 case 5:
505 /* Bit 28 of b0d28f4 0x32c register correspnd to
506 * Root Ports 4:1. */
507 do_aspm = !!(rpc.b0d28f4_32c & (1 << 28));
508 break;
509 case 6:
510 /* Bit 28 of b0d28f5 0x32c register correspnd to
511 * Root Ports 4:1. */
512 do_aspm = !!(rpc.b0d28f5_32c & (1 << 28));
513 break;
514 }
515 } else {
516 switch (rp) {
517 case 1:
518 case 2:
519 case 3:
520 case 4:
521 /* Bits 31:28 of b0d28f0 0x32c register correspnd to
522 * Root Ports 4:1. */
523 do_aspm = !!(rpc.b0d28f0_32c & (1 << (28 + rp - 1)));
524 break;
525 case 5:
526 case 6:
527 case 7:
528 case 8:
529 /* Bit 31:28 of b0d28f4 0x32c register correspnd to
530 * Root Ports 8:5. */
531 do_aspm = !!(rpc.b0d28f4_32c & (1 << (28 + rp - 5)));
532 break;
533 }
Aaron Durbin76c37002012-10-30 09:03:43 -0500534 }
Stefan Reinauerab365af2013-12-03 12:13:26 -0800535
Duncan Laurie249a03b2013-08-09 09:06:41 -0700536 /* Allow ASPM to be forced on in devicetree */
537 if (config && (config->pcie_port_force_aspm & (1 << (rp - 1))))
538 do_aspm = 1;
539
540 printk(BIOS_DEBUG, "PCIe Root Port %d ASPM is %sabled\n",
541 rp, do_aspm ? "en" : "dis");
542
Stefan Reinauerab365af2013-12-03 12:13:26 -0800543 if (do_aspm) {
544 /* Set ASPM bits in MPC2 register. */
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300545 pci_update_config32(dev, 0xd4, ~(0x3 << 2), (1 << 4) | (0x2 << 2));
Stefan Reinauerab365af2013-12-03 12:13:26 -0800546
547 /* Set unique clock exit latency in MPC register. */
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300548 pci_update_config32(dev, 0xd8, ~(0x7 << 18), (0x7 << 18));
Stefan Reinauerab365af2013-12-03 12:13:26 -0800549
550 /* Set L1 exit latency in LCAP register. */
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300551 pci_update_config32(dev, 0x4c, ~(0x7 << 15), (0x4 << 15));
Stefan Reinauerab365af2013-12-03 12:13:26 -0800552
553 if (is_lp) {
554 switch (rp) {
555 case 1:
556 pcie_add_0x0202000_iobp(0xe9002440);
557 break;
558 case 2:
559 pcie_add_0x0202000_iobp(0xe9002640);
560 break;
561 case 3:
562 pcie_add_0x0202000_iobp(0xe9000840);
563 break;
564 case 4:
565 pcie_add_0x0202000_iobp(0xe9000a40);
566 break;
567 case 5:
568 pcie_add_0x0202000_iobp(0xe9000c40);
569 pcie_add_0x0202000_iobp(0xe9000e40);
570 pcie_add_0x0202000_iobp(0xe9001040);
571 pcie_add_0x0202000_iobp(0xe9001240);
572 break;
573 case 6:
574 /* Update IOBP based on lane ownership. */
575 if (rpc.pin_ownership & (1 << 4))
576 pcie_add_0x0202000_iobp(0xea002040);
577 if (rpc.pin_ownership & (1 << 5))
578 pcie_add_0x0202000_iobp(0xea002240);
579 if (rpc.pin_ownership & (1 << 6))
580 pcie_add_0x0202000_iobp(0xea002440);
581 if (rpc.pin_ownership & (1 << 7))
582 pcie_add_0x0202000_iobp(0xea002640);
583 break;
584 }
585 } else {
586 switch (rp) {
587 case 1:
588 if ((rpc.pin_ownership & 0x3) == 1)
589 pcie_add_0x0202000_iobp(0xe9002e40);
590 else
591 pcie_add_0x0202000_iobp(0xea002040);
592 break;
593 case 2:
594 if ((rpc.pin_ownership & 0xc) == 0x4)
595 pcie_add_0x0202000_iobp(0xe9002c40);
596 else
597 pcie_add_0x0202000_iobp(0xea002240);
598 break;
599 case 3:
600 pcie_add_0x0202000_iobp(0xe9002a40);
601 break;
602 case 4:
603 pcie_add_0x0202000_iobp(0xe9002840);
604 break;
605 case 5:
606 pcie_add_0x0202000_iobp(0xe9002640);
607 break;
608 case 6:
609 pcie_add_0x0202000_iobp(0xe9002440);
610 break;
611 case 7:
612 pcie_add_0x0202000_iobp(0xe9002240);
613 break;
614 case 8:
615 pcie_add_0x0202000_iobp(0xe9002040);
616 break;
617 }
618 }
619
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300620 pci_update_config32(dev, 0x338, ~(1 << 26), 0);
Stefan Reinauerab365af2013-12-03 12:13:26 -0800621 }
622
623 /* Enable LTR in Root Port. */
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300624 pci_update_config32(dev, 0x64, ~(1 << 11), (1 << 11));
625 pci_update_config32(dev, 0x68, ~(1 << 10), (1 << 10));
Stefan Reinauerab365af2013-12-03 12:13:26 -0800626
Ryan Salsamendi0d9b3602017-06-30 17:15:57 -0700627 pci_update_config32(dev, 0x318, ~(0xffffUL << 16), (0x1414UL << 16));
Stefan Reinauerab365af2013-12-03 12:13:26 -0800628
629 /* Set L1 exit latency in LCAP register. */
630 if (!do_aspm && (pci_read_config8(dev, 0xf5) & 0x1))
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300631 pci_update_config32(dev, 0x4c, ~(0x7 << 15), (0x4 << 15));
Stefan Reinauerab365af2013-12-03 12:13:26 -0800632 else
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300633 pci_update_config32(dev, 0x4c, ~(0x7 << 15), (0x2 << 15));
Stefan Reinauerab365af2013-12-03 12:13:26 -0800634
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300635 pci_update_config32(dev, 0x314, 0x0, 0x743a361b);
Stefan Reinauerab365af2013-12-03 12:13:26 -0800636
637 /* Set Common Clock Exit Latency in MPC register. */
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300638 pci_update_config32(dev, 0xd8, ~(0x7 << 15), (0x3 << 15));
Stefan Reinauerab365af2013-12-03 12:13:26 -0800639
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300640 pci_update_config32(dev, 0x33c, ~0x00ffffff, 0x854c74);
Stefan Reinauerab365af2013-12-03 12:13:26 -0800641
Stefan Reinauerab365af2013-12-03 12:13:26 -0800642 /* Set Invalid Recieve Range Check Enable in MPC register. */
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300643 pci_update_config32(dev, 0xd8, ~0, (1 << 25));
Stefan Reinauerab365af2013-12-03 12:13:26 -0800644
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300645 pci_update_config8(dev, 0xf5, 0x3f, 0);
Stefan Reinauerab365af2013-12-03 12:13:26 -0800646
647 if (rp == 1 || rp == 5 || (is_lp && rp == 6))
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300648 pci_update_config8(dev, 0xf7, ~0xc, 0);
Stefan Reinauerab365af2013-12-03 12:13:26 -0800649
650 /* Set EOI forwarding disable. */
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300651 pci_update_config32(dev, 0xd4, ~0, (1 << 1));
Stefan Reinauerab365af2013-12-03 12:13:26 -0800652
653 /* Set something involving advanced error reporting. */
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300654 pci_update_config32(dev, 0x100, ~((1 << 20) - 1), 0x10001);
Stefan Reinauerab365af2013-12-03 12:13:26 -0800655
656 if (is_lp)
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300657 pci_update_config32(dev, 0x100, ~0, (1 << 29));
Stefan Reinauerab365af2013-12-03 12:13:26 -0800658
659 /* Read and write back write-once capability registers. */
Kyösti Mälkki48c389e2013-07-26 08:53:59 +0300660 pci_update_config32(dev, 0x34, ~0, 0);
661 pci_update_config32(dev, 0x40, ~0, 0);
662 pci_update_config32(dev, 0x80, ~0, 0);
663 pci_update_config32(dev, 0x90, ~0, 0);
Aaron Durbin76c37002012-10-30 09:03:43 -0500664}
665
666static void pci_init(struct device *dev)
667{
668 u16 reg16;
669 u32 reg32;
670
671 printk(BIOS_DEBUG, "Initializing PCH PCIe bridge.\n");
672
Aaron Durbinc0254e62013-06-20 01:20:30 -0500673 /* Enable SERR */
674 reg32 = pci_read_config32(dev, PCI_COMMAND);
675 reg32 |= PCI_COMMAND_SERR;
676 pci_write_config32(dev, PCI_COMMAND, reg32);
677
Aaron Durbin76c37002012-10-30 09:03:43 -0500678 /* Enable Bus Master */
679 reg32 = pci_read_config32(dev, PCI_COMMAND);
680 reg32 |= PCI_COMMAND_MASTER;
681 pci_write_config32(dev, PCI_COMMAND, reg32);
682
683 /* Set Cache Line Size to 0x10 */
684 // This has no effect but the OS might expect it
685 pci_write_config8(dev, 0x0c, 0x10);
686
Kyösti Mälkkidf128a52019-09-21 18:35:37 +0300687 reg16 = pci_read_config16(dev, PCI_BRIDGE_CONTROL);
688 reg16 &= ~PCI_BRIDGE_CTL_PARITY;
689 reg16 |= PCI_BRIDGE_CTL_NO_ISA;
690 pci_write_config16(dev, PCI_BRIDGE_CONTROL, reg16);
Aaron Durbin76c37002012-10-30 09:03:43 -0500691
692#ifdef EVEN_MORE_DEBUG
693 reg32 = pci_read_config32(dev, 0x20);
694 printk(BIOS_SPEW, " MBL = 0x%08x\n", reg32);
695 reg32 = pci_read_config32(dev, 0x24);
696 printk(BIOS_SPEW, " PMBL = 0x%08x\n", reg32);
697 reg32 = pci_read_config32(dev, 0x28);
698 printk(BIOS_SPEW, " PMBU32 = 0x%08x\n", reg32);
699 reg32 = pci_read_config32(dev, 0x2c);
700 printk(BIOS_SPEW, " PMLU32 = 0x%08x\n", reg32);
701#endif
702
703 /* Clear errors in status registers */
704 reg16 = pci_read_config16(dev, 0x06);
Aaron Durbin76c37002012-10-30 09:03:43 -0500705 pci_write_config16(dev, 0x06, reg16);
Aaron Durbin76c37002012-10-30 09:03:43 -0500706 reg16 = pci_read_config16(dev, 0x1e);
Aaron Durbin76c37002012-10-30 09:03:43 -0500707 pci_write_config16(dev, 0x1e, reg16);
Aaron Durbin76c37002012-10-30 09:03:43 -0500708}
709
Elyes HAOUAS7a5f7712018-06-08 17:20:38 +0200710static void pch_pcie_enable(struct device *dev)
Aaron Durbin76c37002012-10-30 09:03:43 -0500711{
Aaron Durbinc0254e62013-06-20 01:20:30 -0500712 /* Add this device to the root port config structure. */
713 root_port_init_config(dev);
714
715 /* Check to see if this Root Port should be disabled. */
716 root_port_check_disable(dev);
717
Aaron Durbin76c37002012-10-30 09:03:43 -0500718 /* Power Management init before enumeration */
Aaron Durbinc0254e62013-06-20 01:20:30 -0500719 if (dev->enabled)
Stefan Reinauerab365af2013-12-03 12:13:26 -0800720 pch_pcie_early(dev);
Aaron Durbinc0254e62013-06-20 01:20:30 -0500721
722 /*
723 * When processing the last PCIe root port we can now
724 * update the Root Port Function Number and Hide register.
725 */
726 if (root_port_is_last(dev))
727 root_port_commit_config();
Aaron Durbin76c37002012-10-30 09:03:43 -0500728}
729
Aaron Durbin76c37002012-10-30 09:03:43 -0500730static struct pci_operations pci_ops = {
Subrata Banik15ccbf02019-03-20 15:09:44 +0530731 .set_subsystem = pci_dev_set_subsystem,
Aaron Durbin76c37002012-10-30 09:03:43 -0500732};
733
734static struct device_operations device_ops = {
735 .read_resources = pci_bus_read_resources,
736 .set_resources = pci_dev_set_resources,
737 .enable_resources = pci_bus_enable_resources,
738 .init = pci_init,
739 .enable = pch_pcie_enable,
740 .scan_bus = pciexp_scan_bridge,
741 .ops_pci = &pci_ops,
742};
743
Duncan Laurie74c0d052012-12-17 11:31:40 -0800744static const unsigned short pci_device_ids[] = {
745 /* Lynxpoint Mobile */
746 0x8c10, 0x8c12, 0x8c14, 0x8c16, 0x8c18, 0x8c1a, 0x8c1c, 0x8c1e,
747 /* Lynxpoint Low Power */
748 0x9c10, 0x9c12, 0x9c14, 0x9c16, 0x9c18, 0x9c1a,
749 0
750};
Aaron Durbin76c37002012-10-30 09:03:43 -0500751
752static const struct pci_driver pch_pcie __pci_driver = {
753 .ops = &device_ops,
754 .vendor = PCI_VENDOR_ID_INTEL,
755 .devices = pci_device_ids,
756};