blob: 762dfd4a334dc183e62d53696c49827e89f31cf3 [file] [log] [blame]
Angel Ponsba38f372020-04-05 15:46:45 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Lee Leahy77ff0b12015-05-05 15:07:29 -07002
Lee Leahy32471722015-04-20 15:20:28 -07003#include "chip.h"
Lee Leahy77ff0b12015-05-05 15:07:29 -07004#include <console/console.h>
5#include <device/device.h>
6#include <device/pci.h>
Kyösti Mälkkif1b58b72019-03-01 13:43:02 +02007#include <device/pci_ops.h>
Lee Leahy77ff0b12015-05-05 15:07:29 -07008#include <device/pciexp.h>
9#include <device/pci_ids.h>
10#include <reg_script.h>
Lee Leahy77ff0b12015-05-05 15:07:29 -070011#include <soc/pci_devs.h>
12#include <soc/pcie.h>
13#include <soc/ramstage.h>
14#include <soc/smm.h>
15
Lee Leahy77ff0b12015-05-05 15:07:29 -070016static int pll_en_off;
17static uint32_t strpfusecfg;
18
Elyes HAOUASb13fac32018-05-24 22:29:44 +020019static inline int root_port_offset(struct device *dev)
Lee Leahy77ff0b12015-05-05 15:07:29 -070020{
21 return PCI_FUNC(dev->path.pci.devfn);
22}
23
Elyes HAOUASb13fac32018-05-24 22:29:44 +020024static inline int is_first_port(struct device *dev)
Lee Leahy77ff0b12015-05-05 15:07:29 -070025{
26 return root_port_offset(dev) == PCIE_PORT1_FUNC;
27}
28
Elyes HAOUASb13fac32018-05-24 22:29:44 +020029static void pcie_init(struct device *dev)
Lee Leahy77ff0b12015-05-05 15:07:29 -070030{
Lee Leahy77ff0b12015-05-05 15:07:29 -070031}
32
33static const struct reg_script no_dev_behind_port[] = {
34 REG_PCI_OR32(PCIEALC, (1 << 26)),
35 REG_PCI_POLL32(PCIESTS1, 0x1f000000, (1 << 24), 50000),
36 REG_PCI_OR32(PHYCTL4, SQDIS),
37 REG_SCRIPT_END,
38};
39
Elyes HAOUASb13fac32018-05-24 22:29:44 +020040static void check_port_enabled(struct device *dev)
Lee Leahy77ff0b12015-05-05 15:07:29 -070041{
42 int rp_config = (strpfusecfg & LANECFG_MASK) >> LANECFG_SHIFT;
43
44 switch (root_port_offset(dev)) {
45 case PCIE_PORT1_FUNC:
46 /* Port 1 cannot be disabled from strapping config. */
47 break;
48 case PCIE_PORT2_FUNC:
49 /* Port 2 disabled in all configs but 4x1. */
50 if (rp_config != 0x0)
51 dev->enabled = 0;
52 break;
53 case PCIE_PORT3_FUNC:
54 /* Port 3 disabled only in 1x4 config. */
55 if (rp_config == 0x3)
56 dev->enabled = 0;
57 break;
58 case PCIE_PORT4_FUNC:
59 /* Port 4 disabled in 1x4 and 2x2 config. */
60 if (rp_config >= 0x2)
61 dev->enabled = 0;
62 break;
63 }
64}
65
Elyes HAOUASb13fac32018-05-24 22:29:44 +020066static void check_device_present(struct device *dev)
Lee Leahy77ff0b12015-05-05 15:07:29 -070067{
Lee Leahy32471722015-04-20 15:20:28 -070068 /* port1_dev will store the dev struct pointer of the PORT1 */
Elyes HAOUASb13fac32018-05-24 22:29:44 +020069 static struct device *port1_dev;
Lee Leahy32471722015-04-20 15:20:28 -070070
71 /*
Angel Ponsaee7ab22020-03-19 00:31:58 +010072 * The SOC has 4 ROOT ports defined with MAX_ROOT_PORTS_BSW. For each port initial
73 * assumption is that, each port will have devices connected to it. Later we will
74 * scan each PORT and if the device is not attached to that port we will update
75 * rootports_in_use. If none of the root port is in use we will disable PORT1
76 * otherwise we will keep PORT1 enabled per spec. In future if the SoC has more
77 * number of PCIe Root ports then change MAX_ROOT_PORTS_BSW value accordingly.
Lee Leahy32471722015-04-20 15:20:28 -070078 */
79
80 static uint32_t rootports_in_use = MAX_ROOT_PORTS_BSW;
81
Lee Leahy77ff0b12015-05-05 15:07:29 -070082 /* Set slot implemented. */
83 pci_write_config32(dev, XCAP, pci_read_config32(dev, XCAP) | SI);
84
85 /* No device present. */
86 if (!(pci_read_config32(dev, SLCTL_SLSTS) & PDS)) {
Lee Leahy32471722015-04-20 15:20:28 -070087 rootports_in_use--;
88 printk(BIOS_DEBUG, "No PCIe device present.");
89
90 /*
Angel Ponsaee7ab22020-03-19 00:31:58 +010091 * Defer PORT1 disabling for now. When we are at Last port we will check
92 * rootports_in_use and disable PORT1 if none of the ports have any device
93 * connected to it.
Lee Leahy32471722015-04-20 15:20:28 -070094 */
95 if (!is_first_port(dev)) {
Lee Leahy77ff0b12015-05-05 15:07:29 -070096 reg_script_run_on_dev(dev, no_dev_behind_port);
97 dev->enabled = 0;
Lee Leahy32471722015-04-20 15:20:28 -070098 } else
99 port1_dev = dev;
100 /*
Angel Ponsaee7ab22020-03-19 00:31:58 +0100101 * If none of the ROOT PORT has devices connected then disable PORT1.
102 * Else, keep the PORT1 enabled.
Lee Leahy32471722015-04-20 15:20:28 -0700103 */
104 if (!rootports_in_use) {
105 reg_script_run_on_dev(port1_dev, no_dev_behind_port);
106 port1_dev->enabled = 0;
107 southcluster_enable_dev(port1_dev);
Lee Leahy77ff0b12015-05-05 15:07:29 -0700108 }
Lee Leahy32471722015-04-20 15:20:28 -0700109 } else if (!dev->enabled) {
Lee Leahy77ff0b12015-05-05 15:07:29 -0700110 /* Port is disabled, but device present. Disable link. */
111 pci_write_config32(dev, LCTL,
112 pci_read_config32(dev, LCTL) | LD);
113 }
114}
115
Elyes HAOUASb13fac32018-05-24 22:29:44 +0200116static void pcie_enable(struct device *dev)
Lee Leahy77ff0b12015-05-05 15:07:29 -0700117{
118 if (is_first_port(dev)) {
Kyösti Mälkki8950cfb2019-07-13 22:16:25 +0300119 struct soc_intel_braswell_config *config = config_of(dev);
Lee Leahy77ff0b12015-05-05 15:07:29 -0700120 uint32_t reg = pci_read_config32(dev, PHYCTL2_IOSFBCTL);
121 pll_en_off = !!(reg & PLL_OFF_EN);
122
123 strpfusecfg = pci_read_config32(dev, STRPFUSECFG);
124
Kyösti Mälkki8950cfb2019-07-13 22:16:25 +0300125 if (config->pcie_wake_enable)
Angel Ponsaee7ab22020-03-19 00:31:58 +0100126 smm_southcluster_save_param(SMM_SAVE_PARAM_PCIE_WAKE_ENABLE, 1);
Lee Leahy77ff0b12015-05-05 15:07:29 -0700127 }
128
129 /* Check if device is enabled in strapping. */
130 check_port_enabled(dev);
131 /* Determine if device is behind port. */
132 check_device_present(dev);
133
134 southcluster_enable_dev(dev);
135}
136
Lee Leahy77ff0b12015-05-05 15:07:29 -0700137static struct device_operations device_ops = {
138 .read_resources = pci_bus_read_resources,
139 .set_resources = pci_dev_set_resources,
140 .enable_resources = pci_bus_enable_resources,
Lee Leahy32471722015-04-20 15:20:28 -0700141 .init = pcie_init,
142 .scan_bus = pciexp_scan_bridge,
143 .enable = pcie_enable,
Angel Pons1fc0edd2020-05-31 00:03:28 +0200144 .ops_pci = &pci_dev_ops_pci,
Lee Leahy77ff0b12015-05-05 15:07:29 -0700145};
146
147static const unsigned short pci_device_ids[] = {
148 PCIE_PORT1_DEVID, PCIE_PORT2_DEVID, PCIE_PORT3_DEVID, PCIE_PORT4_DEVID,
149 0
150};
151
152static const struct pci_driver pcie_root_ports __pci_driver = {
153 .ops = &device_ops,
Felix Singer43b7f412022-03-07 04:34:52 +0100154 .vendor = PCI_VID_INTEL,
Lee Leahy77ff0b12015-05-05 15:07:29 -0700155 .devices = pci_device_ids,
156};