blob: 479323dd5683354ee1237120234302542af5fc20 [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{
67 u32 reg32 = pci_read_config32(dev, PCH_PCS);
68 reg32 |= PCH_PCS_PS_D3HOT;
69 pci_write_config32(dev, PCH_PCS, reg32);
70}
71
Wenkai Duaec24422014-10-15 11:19:16 -070072/* RCBA function disable and posting read to flush the transaction */
73static void rcba_function_disable(u32 reg, u32 bit)
74{
75 RCBA32_OR(reg, bit);
76 RCBA32(reg);
77}
78
Martin Rothde7ed6f2014-12-07 14:58:18 -070079/* Set bit in Function Disable register to hide this device */
Elyes HAOUAS4658a982018-09-20 08:46:35 +020080void pch_disable_devfn(struct device *dev)
Duncan Lauriec88c54c2014-04-30 16:36:13 -070081{
82 switch (dev->path.pci.devfn) {
Duncan Laurie61680272014-05-05 12:42:35 -050083 case PCH_DEVFN_ADSP: /* Audio DSP */
Wenkai Duaec24422014-10-15 11:19:16 -070084 rcba_function_disable(FD, PCH_DISABLE_ADSPD);
Duncan Lauriec88c54c2014-04-30 16:36:13 -070085 break;
Duncan Laurie61680272014-05-05 12:42:35 -050086 case PCH_DEVFN_XHCI: /* XHCI */
Wenkai Duaec24422014-10-15 11:19:16 -070087 rcba_function_disable(FD, PCH_DISABLE_XHCI);
Duncan Lauriec88c54c2014-04-30 16:36:13 -070088 break;
Duncan Laurie61680272014-05-05 12:42:35 -050089 case PCH_DEVFN_SDMA: /* DMA */
Duncan Lauriec88c54c2014-04-30 16:36:13 -070090 pch_enable_d3hot(dev);
91 pch_iobp_update(SIO_IOBP_FUNCDIS0, ~0UL, SIO_IOBP_FUNCDIS_DIS);
92 break;
Duncan Laurie61680272014-05-05 12:42:35 -050093 case PCH_DEVFN_I2C0: /* I2C0 */
Duncan Lauriec88c54c2014-04-30 16:36:13 -070094 pch_enable_d3hot(dev);
95 pch_iobp_update(SIO_IOBP_FUNCDIS1, ~0UL, SIO_IOBP_FUNCDIS_DIS);
96 break;
Duncan Laurie61680272014-05-05 12:42:35 -050097 case PCH_DEVFN_I2C1: /* I2C1 */
Duncan Lauriec88c54c2014-04-30 16:36:13 -070098 pch_enable_d3hot(dev);
99 pch_iobp_update(SIO_IOBP_FUNCDIS2, ~0UL, SIO_IOBP_FUNCDIS_DIS);
100 break;
Duncan Laurie61680272014-05-05 12:42:35 -0500101 case PCH_DEVFN_SPI0: /* SPI0 */
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700102 pch_enable_d3hot(dev);
103 pch_iobp_update(SIO_IOBP_FUNCDIS3, ~0UL, SIO_IOBP_FUNCDIS_DIS);
104 break;
Duncan Laurie61680272014-05-05 12:42:35 -0500105 case PCH_DEVFN_SPI1: /* SPI1 */
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700106 pch_enable_d3hot(dev);
107 pch_iobp_update(SIO_IOBP_FUNCDIS4, ~0UL, SIO_IOBP_FUNCDIS_DIS);
108 break;
Duncan Laurie61680272014-05-05 12:42:35 -0500109 case PCH_DEVFN_UART0: /* UART0 */
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700110 pch_enable_d3hot(dev);
111 pch_iobp_update(SIO_IOBP_FUNCDIS5, ~0UL, SIO_IOBP_FUNCDIS_DIS);
112 break;
Duncan Laurie61680272014-05-05 12:42:35 -0500113 case PCH_DEVFN_UART1: /* UART1 */
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700114 pch_enable_d3hot(dev);
115 pch_iobp_update(SIO_IOBP_FUNCDIS6, ~0UL, SIO_IOBP_FUNCDIS_DIS);
116 break;
Duncan Laurie61680272014-05-05 12:42:35 -0500117 case PCH_DEVFN_ME: /* MEI #1 */
Wenkai Duaec24422014-10-15 11:19:16 -0700118 rcba_function_disable(FD2, PCH_DISABLE_MEI1);
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700119 break;
Duncan Laurie61680272014-05-05 12:42:35 -0500120 case PCH_DEVFN_ME_2: /* MEI #2 */
Wenkai Duaec24422014-10-15 11:19:16 -0700121 rcba_function_disable(FD2, PCH_DISABLE_MEI2);
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700122 break;
Duncan Laurie61680272014-05-05 12:42:35 -0500123 case PCH_DEVFN_ME_IDER: /* IDE-R */
Wenkai Duaec24422014-10-15 11:19:16 -0700124 rcba_function_disable(FD2, PCH_DISABLE_IDER);
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700125 break;
Duncan Laurie61680272014-05-05 12:42:35 -0500126 case PCH_DEVFN_ME_KT: /* KT */
Wenkai Duaec24422014-10-15 11:19:16 -0700127 rcba_function_disable(FD2, PCH_DISABLE_KT);
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700128 break;
Duncan Laurie61680272014-05-05 12:42:35 -0500129 case PCH_DEVFN_SDIO: /* SDIO */
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700130 pch_enable_d3hot(dev);
131 pch_iobp_update(SIO_IOBP_FUNCDIS7, ~0UL, SIO_IOBP_FUNCDIS_DIS);
132 break;
Duncan Laurie61680272014-05-05 12:42:35 -0500133 case PCH_DEVFN_GBE: /* Gigabit Ethernet */
Wenkai Duaec24422014-10-15 11:19:16 -0700134 rcba_function_disable(BUC, PCH_DISABLE_GBE);
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700135 break;
Duncan Laurie61680272014-05-05 12:42:35 -0500136 case PCH_DEVFN_HDA: /* HD Audio Controller */
Wenkai Duaec24422014-10-15 11:19:16 -0700137 rcba_function_disable(FD, PCH_DISABLE_HD_AUDIO);
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700138 break;
Duncan Laurie61680272014-05-05 12:42:35 -0500139 case PCI_DEVFN(PCH_DEV_SLOT_PCIE, 0): /* PCI Express Root Port 1 */
140 case PCI_DEVFN(PCH_DEV_SLOT_PCIE, 1): /* PCI Express Root Port 2 */
141 case PCI_DEVFN(PCH_DEV_SLOT_PCIE, 2): /* PCI Express Root Port 3 */
142 case PCI_DEVFN(PCH_DEV_SLOT_PCIE, 3): /* PCI Express Root Port 4 */
143 case PCI_DEVFN(PCH_DEV_SLOT_PCIE, 4): /* PCI Express Root Port 5 */
144 case PCI_DEVFN(PCH_DEV_SLOT_PCIE, 5): /* PCI Express Root Port 6 */
145 case PCI_DEVFN(PCH_DEV_SLOT_PCIE, 6): /* PCI Express Root Port 7 */
146 case PCI_DEVFN(PCH_DEV_SLOT_PCIE, 7): /* PCI Express Root Port 8 */
Wenkai Duaec24422014-10-15 11:19:16 -0700147 rcba_function_disable(FD,
148 PCH_DISABLE_PCIE(PCI_FUNC(dev->path.pci.devfn)));
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700149 break;
Duncan Laurie61680272014-05-05 12:42:35 -0500150 case PCH_DEVFN_EHCI: /* EHCI #1 */
Wenkai Duaec24422014-10-15 11:19:16 -0700151 rcba_function_disable(FD, PCH_DISABLE_EHCI1);
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700152 break;
Duncan Laurie61680272014-05-05 12:42:35 -0500153 case PCH_DEVFN_LPC: /* LPC */
Wenkai Duaec24422014-10-15 11:19:16 -0700154 rcba_function_disable(FD, PCH_DISABLE_LPC);
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700155 break;
Duncan Laurie61680272014-05-05 12:42:35 -0500156 case PCH_DEVFN_SATA: /* SATA #1 */
Wenkai Duaec24422014-10-15 11:19:16 -0700157 rcba_function_disable(FD, PCH_DISABLE_SATA1);
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700158 break;
Duncan Laurie61680272014-05-05 12:42:35 -0500159 case PCH_DEVFN_SMBUS: /* SMBUS */
Wenkai Duaec24422014-10-15 11:19:16 -0700160 rcba_function_disable(FD, PCH_DISABLE_SMBUS);
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700161 break;
Duncan Laurie61680272014-05-05 12:42:35 -0500162 case PCH_DEVFN_SATA2: /* SATA #2 */
Wenkai Duaec24422014-10-15 11:19:16 -0700163 rcba_function_disable(FD, PCH_DISABLE_SATA2);
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700164 break;
Duncan Laurie61680272014-05-05 12:42:35 -0500165 case PCH_DEVFN_THERMAL: /* Thermal Subsystem */
Wenkai Duaec24422014-10-15 11:19:16 -0700166 rcba_function_disable(FD, PCH_DISABLE_THERMAL);
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700167 break;
168 }
169}
170
Elyes HAOUAS4658a982018-09-20 08:46:35 +0200171void broadwell_pch_enable_dev(struct device *dev)
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700172{
Elyes HAOUASb887adf2020-04-29 10:42:34 +0200173 u16 reg16;
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700174
Duncan Laurie61680272014-05-05 12:42:35 -0500175 /* These devices need special enable/disable handling */
176 switch (PCI_SLOT(dev->path.pci.devfn)) {
177 case PCH_DEV_SLOT_PCIE:
178 case PCH_DEV_SLOT_EHCI:
179 case PCH_DEV_SLOT_HDA:
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700180 return;
Duncan Laurie61680272014-05-05 12:42:35 -0500181 }
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700182
183 if (!dev->enabled) {
184 printk(BIOS_DEBUG, "%s: Disabling device\n", dev_path(dev));
185
186 /* Ensure memory, io, and bus master are all disabled */
Elyes HAOUASb887adf2020-04-29 10:42:34 +0200187 reg16 = pci_read_config16(dev, PCI_COMMAND);
188 reg16 &= ~(PCI_COMMAND_MASTER |
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700189 PCI_COMMAND_MEMORY | PCI_COMMAND_IO);
Elyes HAOUASb887adf2020-04-29 10:42:34 +0200190 pci_write_config16(dev, PCI_COMMAND, reg16);
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
200#endif