blob: d4b88f1a0b8517005c5178539131e31ff8366b33 [file] [log] [blame]
Angel Ponsf94ac9a2020-04-05 15:46:48 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Duncan Lauriec88c54c2014-04-30 16:36:13 -07002
3#include <console/console.h>
Kyösti Mälkkif1b58b72019-03-01 13:43:02 +02004#include <device/pci_ops.h>
Duncan Lauriec88c54c2014-04-30 16:36:13 -07005#include <device/device.h>
6#include <device/pci.h>
7#include <device/pci_def.h>
Julius Werner4ee4bd52014-10-20 13:46:39 -07008#include <soc/iobp.h>
9#include <soc/pch.h>
10#include <soc/pci_devs.h>
11#include <soc/ramstage.h>
12#include <soc/rcba.h>
13#include <soc/serialio.h>
14#include <soc/spi.h>
Duncan Lauriec88c54c2014-04-30 16:36:13 -070015
16u8 pch_revision(void)
17{
18 return pci_read_config8(PCH_DEV_LPC, PCI_REVISION_ID);
19}
20
21u16 pch_type(void)
22{
23 return pci_read_config16(PCH_DEV_LPC, PCI_DEVICE_ID);
24}
25
26/* Return 1 if PCH type is WildcatPoint */
27int pch_is_wpt(void)
28{
29 return ((pch_type() & 0xfff0) == 0x9cc0) ? 1 : 0;
30}
31
32/* Return 1 if PCH type is WildcatPoint ULX */
33int pch_is_wpt_ulx(void)
34{
35 u16 lpcid = pch_type();
36
37 switch (lpcid) {
38 case PCH_WPT_BDW_Y_SAMPLE:
39 case PCH_WPT_BDW_Y_PREMIUM:
40 case PCH_WPT_BDW_Y_BASE:
41 return 1;
42 }
43
44 return 0;
45}
46
47u32 pch_read_soft_strap(int id)
48{
49 u32 fdoc;
50
51 fdoc = SPIBAR32(SPIBAR_FDOC);
52 fdoc &= ~0x00007ffc;
53 SPIBAR32(SPIBAR_FDOC) = fdoc;
54
55 fdoc |= 0x00004000;
56 fdoc |= id * 4;
57 SPIBAR32(SPIBAR_FDOC) = fdoc;
58
59 return SPIBAR32(SPIBAR_FDOD);
60}
61
Kyösti Mälkki55d0ab52019-09-12 15:44:28 +030062#ifndef __SIMPLE_DEVICE__
Duncan Lauriec88c54c2014-04-30 16:36:13 -070063
64/* Put device in D3Hot Power State */
Elyes HAOUAS4658a982018-09-20 08:46:35 +020065static void pch_enable_d3hot(struct device *dev)
Duncan Lauriec88c54c2014-04-30 16:36:13 -070066{
Angel Pons2ead3632020-09-24 16:50:05 +020067 pci_or_config32(dev, PCH_PCS, PCH_PCS_PS_D3HOT);
Duncan Lauriec88c54c2014-04-30 16:36:13 -070068}
69
Wenkai Duaec24422014-10-15 11:19:16 -070070/* RCBA function disable and posting read to flush the transaction */
71static void rcba_function_disable(u32 reg, u32 bit)
72{
73 RCBA32_OR(reg, bit);
74 RCBA32(reg);
75}
76
Martin Rothde7ed6f2014-12-07 14:58:18 -070077/* Set bit in Function Disable register to hide this device */
Elyes HAOUAS4658a982018-09-20 08:46:35 +020078void pch_disable_devfn(struct device *dev)
Duncan Lauriec88c54c2014-04-30 16:36:13 -070079{
80 switch (dev->path.pci.devfn) {
Duncan Laurie61680272014-05-05 12:42:35 -050081 case PCH_DEVFN_ADSP: /* Audio DSP */
Wenkai Duaec24422014-10-15 11:19:16 -070082 rcba_function_disable(FD, PCH_DISABLE_ADSPD);
Duncan Lauriec88c54c2014-04-30 16:36:13 -070083 break;
Duncan Laurie61680272014-05-05 12:42:35 -050084 case PCH_DEVFN_XHCI: /* XHCI */
Wenkai Duaec24422014-10-15 11:19:16 -070085 rcba_function_disable(FD, PCH_DISABLE_XHCI);
Duncan Lauriec88c54c2014-04-30 16:36:13 -070086 break;
Duncan Laurie61680272014-05-05 12:42:35 -050087 case PCH_DEVFN_SDMA: /* DMA */
Duncan Lauriec88c54c2014-04-30 16:36:13 -070088 pch_enable_d3hot(dev);
89 pch_iobp_update(SIO_IOBP_FUNCDIS0, ~0UL, SIO_IOBP_FUNCDIS_DIS);
90 break;
Duncan Laurie61680272014-05-05 12:42:35 -050091 case PCH_DEVFN_I2C0: /* I2C0 */
Duncan Lauriec88c54c2014-04-30 16:36:13 -070092 pch_enable_d3hot(dev);
93 pch_iobp_update(SIO_IOBP_FUNCDIS1, ~0UL, SIO_IOBP_FUNCDIS_DIS);
94 break;
Duncan Laurie61680272014-05-05 12:42:35 -050095 case PCH_DEVFN_I2C1: /* I2C1 */
Duncan Lauriec88c54c2014-04-30 16:36:13 -070096 pch_enable_d3hot(dev);
97 pch_iobp_update(SIO_IOBP_FUNCDIS2, ~0UL, SIO_IOBP_FUNCDIS_DIS);
98 break;
Duncan Laurie61680272014-05-05 12:42:35 -050099 case PCH_DEVFN_SPI0: /* SPI0 */
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700100 pch_enable_d3hot(dev);
101 pch_iobp_update(SIO_IOBP_FUNCDIS3, ~0UL, SIO_IOBP_FUNCDIS_DIS);
102 break;
Duncan Laurie61680272014-05-05 12:42:35 -0500103 case PCH_DEVFN_SPI1: /* SPI1 */
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700104 pch_enable_d3hot(dev);
105 pch_iobp_update(SIO_IOBP_FUNCDIS4, ~0UL, SIO_IOBP_FUNCDIS_DIS);
106 break;
Duncan Laurie61680272014-05-05 12:42:35 -0500107 case PCH_DEVFN_UART0: /* UART0 */
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700108 pch_enable_d3hot(dev);
109 pch_iobp_update(SIO_IOBP_FUNCDIS5, ~0UL, SIO_IOBP_FUNCDIS_DIS);
110 break;
Duncan Laurie61680272014-05-05 12:42:35 -0500111 case PCH_DEVFN_UART1: /* UART1 */
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700112 pch_enable_d3hot(dev);
113 pch_iobp_update(SIO_IOBP_FUNCDIS6, ~0UL, SIO_IOBP_FUNCDIS_DIS);
114 break;
Duncan Laurie61680272014-05-05 12:42:35 -0500115 case PCH_DEVFN_ME: /* MEI #1 */
Wenkai Duaec24422014-10-15 11:19:16 -0700116 rcba_function_disable(FD2, PCH_DISABLE_MEI1);
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700117 break;
Duncan Laurie61680272014-05-05 12:42:35 -0500118 case PCH_DEVFN_ME_2: /* MEI #2 */
Wenkai Duaec24422014-10-15 11:19:16 -0700119 rcba_function_disable(FD2, PCH_DISABLE_MEI2);
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700120 break;
Duncan Laurie61680272014-05-05 12:42:35 -0500121 case PCH_DEVFN_ME_IDER: /* IDE-R */
Wenkai Duaec24422014-10-15 11:19:16 -0700122 rcba_function_disable(FD2, PCH_DISABLE_IDER);
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700123 break;
Duncan Laurie61680272014-05-05 12:42:35 -0500124 case PCH_DEVFN_ME_KT: /* KT */
Wenkai Duaec24422014-10-15 11:19:16 -0700125 rcba_function_disable(FD2, PCH_DISABLE_KT);
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700126 break;
Duncan Laurie61680272014-05-05 12:42:35 -0500127 case PCH_DEVFN_SDIO: /* SDIO */
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700128 pch_enable_d3hot(dev);
129 pch_iobp_update(SIO_IOBP_FUNCDIS7, ~0UL, SIO_IOBP_FUNCDIS_DIS);
130 break;
Duncan Laurie61680272014-05-05 12:42:35 -0500131 case PCH_DEVFN_GBE: /* Gigabit Ethernet */
Wenkai Duaec24422014-10-15 11:19:16 -0700132 rcba_function_disable(BUC, PCH_DISABLE_GBE);
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700133 break;
Duncan Laurie61680272014-05-05 12:42:35 -0500134 case PCH_DEVFN_HDA: /* HD Audio Controller */
Wenkai Duaec24422014-10-15 11:19:16 -0700135 rcba_function_disable(FD, PCH_DISABLE_HD_AUDIO);
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700136 break;
Duncan Laurie61680272014-05-05 12:42:35 -0500137 case PCI_DEVFN(PCH_DEV_SLOT_PCIE, 0): /* PCI Express Root Port 1 */
138 case PCI_DEVFN(PCH_DEV_SLOT_PCIE, 1): /* PCI Express Root Port 2 */
139 case PCI_DEVFN(PCH_DEV_SLOT_PCIE, 2): /* PCI Express Root Port 3 */
140 case PCI_DEVFN(PCH_DEV_SLOT_PCIE, 3): /* PCI Express Root Port 4 */
141 case PCI_DEVFN(PCH_DEV_SLOT_PCIE, 4): /* PCI Express Root Port 5 */
142 case PCI_DEVFN(PCH_DEV_SLOT_PCIE, 5): /* PCI Express Root Port 6 */
143 case PCI_DEVFN(PCH_DEV_SLOT_PCIE, 6): /* PCI Express Root Port 7 */
144 case PCI_DEVFN(PCH_DEV_SLOT_PCIE, 7): /* PCI Express Root Port 8 */
Wenkai Duaec24422014-10-15 11:19:16 -0700145 rcba_function_disable(FD,
146 PCH_DISABLE_PCIE(PCI_FUNC(dev->path.pci.devfn)));
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700147 break;
Duncan Laurie61680272014-05-05 12:42:35 -0500148 case PCH_DEVFN_EHCI: /* EHCI #1 */
Wenkai Duaec24422014-10-15 11:19:16 -0700149 rcba_function_disable(FD, PCH_DISABLE_EHCI1);
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700150 break;
Duncan Laurie61680272014-05-05 12:42:35 -0500151 case PCH_DEVFN_LPC: /* LPC */
Wenkai Duaec24422014-10-15 11:19:16 -0700152 rcba_function_disable(FD, PCH_DISABLE_LPC);
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700153 break;
Duncan Laurie61680272014-05-05 12:42:35 -0500154 case PCH_DEVFN_SATA: /* SATA #1 */
Wenkai Duaec24422014-10-15 11:19:16 -0700155 rcba_function_disable(FD, PCH_DISABLE_SATA1);
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700156 break;
Duncan Laurie61680272014-05-05 12:42:35 -0500157 case PCH_DEVFN_SMBUS: /* SMBUS */
Wenkai Duaec24422014-10-15 11:19:16 -0700158 rcba_function_disable(FD, PCH_DISABLE_SMBUS);
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700159 break;
Duncan Laurie61680272014-05-05 12:42:35 -0500160 case PCH_DEVFN_SATA2: /* SATA #2 */
Wenkai Duaec24422014-10-15 11:19:16 -0700161 rcba_function_disable(FD, PCH_DISABLE_SATA2);
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700162 break;
Duncan Laurie61680272014-05-05 12:42:35 -0500163 case PCH_DEVFN_THERMAL: /* Thermal Subsystem */
Wenkai Duaec24422014-10-15 11:19:16 -0700164 rcba_function_disable(FD, PCH_DISABLE_THERMAL);
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700165 break;
166 }
167}
168
Angel Pons3cc2c382020-10-23 20:38:23 +0200169static void broadwell_pch_enable_dev(struct device *dev)
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700170{
Angel Pons3cc2c382020-10-23 20:38:23 +0200171 if (dev->path.type != DEVICE_PATH_PCI)
172 return;
173
174 if (dev->ops && dev->ops->enable)
175 return;
176
Duncan Laurie61680272014-05-05 12:42:35 -0500177 /* These devices need special enable/disable handling */
178 switch (PCI_SLOT(dev->path.pci.devfn)) {
179 case PCH_DEV_SLOT_PCIE:
180 case PCH_DEV_SLOT_EHCI:
181 case PCH_DEV_SLOT_HDA:
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700182 return;
Duncan Laurie61680272014-05-05 12:42:35 -0500183 }
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700184
185 if (!dev->enabled) {
186 printk(BIOS_DEBUG, "%s: Disabling device\n", dev_path(dev));
187
188 /* Ensure memory, io, and bus master are all disabled */
Angel Pons6b486e12020-10-28 14:16:06 +0100189 pci_and_config16(dev, PCI_COMMAND,
190 ~(PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY | PCI_COMMAND_IO));
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700191
192 /* Disable this device if possible */
193 pch_disable_devfn(dev);
194 } else {
195 /* Enable SERR */
Elyes HAOUASb887adf2020-04-29 10:42:34 +0200196 pci_or_config16(dev, PCI_COMMAND, PCI_COMMAND_SERR);
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700197 }
198}
199
Angel Pons3cc2c382020-10-23 20:38:23 +0200200struct chip_operations soc_intel_broadwell_pch_ops = {
201 CHIP_NAME("Intel Broadwell PCH")
202 .enable_dev = &broadwell_pch_enable_dev,
203};
204
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700205#endif