blob: 05bef2bc4e874edb7010af471e87d28de832a8d4 [file] [log] [blame]
Angel Pons0612b272020-04-05 15:46:56 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Lijian Zhaoa3cbbf72017-10-26 11:59:14 -07002
Kyösti Mälkkif1b58b72019-03-01 13:43:02 +02003#include <device/pci_ops.h>
Lijian Zhaoa3cbbf72017-10-26 11:59:14 -07004#include <console/console.h>
5#include <device/device.h>
6#include <device/pci.h>
7#include <device/pci_ids.h>
Subrata Banik7837c202018-05-07 17:13:40 +05308#include <intelblocks/p2sb.h>
Lijian Zhaoa3cbbf72017-10-26 11:59:14 -07009#include <soc/iomap.h>
Subrata Banik7837c202018-05-07 17:13:40 +053010#include <soc/p2sb.h>
Lijian Zhaoa3cbbf72017-10-26 11:59:14 -070011#include <soc/pci_devs.h>
Subrata Banik7837c202018-05-07 17:13:40 +053012#include <string.h>
Lijian Zhaoa3cbbf72017-10-26 11:59:14 -070013
Subrata Banik7837c202018-05-07 17:13:40 +053014#define PCH_P2SB_EPMASK(mask_number) (PCH_P2SB_EPMASK0 + ((mask_number) * 4))
15
Lijian Zhaoa3cbbf72017-10-26 11:59:14 -070016#define HIDE_BIT (1 << 0)
17
Arthur Heymansa8798a32020-11-12 20:41:57 +010018static bool p2sb_is_hidden(void)
19{
20 const uint16_t pci_vid = pci_read_config16(PCH_DEV_P2SB, PCI_VENDOR_ID);
21
22 if (pci_vid == 0xffff)
23 return true;
24 if (pci_vid == PCI_VENDOR_ID_INTEL)
25 return false;
26 printk(BIOS_ERR, "P2SB PCI_VENDOR_ID is invalid, unknown if hidden\n");
27 return true;
28}
29
Subrata Banik7837c202018-05-07 17:13:40 +053030void p2sb_enable_bar(void)
31{
32 /* Enable PCR Base address in PCH */
Nico Hubere5495032020-02-17 18:26:51 +010033 pci_write_config32(PCH_DEV_P2SB, PCI_BASE_ADDRESS_0, P2SB_BAR);
34 pci_write_config32(PCH_DEV_P2SB, PCI_BASE_ADDRESS_1, 0);
Subrata Banik7837c202018-05-07 17:13:40 +053035
36 /* Enable P2SB MSE */
Elyes HAOUAS2ec1c132020-04-29 09:57:05 +020037 pci_write_config16(PCH_DEV_P2SB, PCI_COMMAND,
Subrata Banik7837c202018-05-07 17:13:40 +053038 PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY);
39}
40
41/*
42 * Enable decoding for HPET range.
43 * This is needed for FspMemoryInit to store and retrieve a global data
44 * pointer.
45 */
46void p2sb_configure_hpet(void)
47{
48 /*
49 * Enable decoding for HPET memory address range.
50 * HPTC_OFFSET(0x60) bit 7, when set the P2SB will decode
51 * the High Performance Timer memory address range
52 * selected by bits 1:0
53 */
Nico Hubere5495032020-02-17 18:26:51 +010054 pci_write_config8(PCH_DEV_P2SB, HPTC_OFFSET, HPTC_ADDR_ENABLE_BIT);
Subrata Banik7837c202018-05-07 17:13:40 +053055}
56
Arthur Heymansf629f7b2020-11-12 21:00:03 +010057union p2sb_bdf p2sb_get_hpet_bdf(void)
58{
59 const bool was_hidden = p2sb_is_hidden();
60 if (was_hidden)
61 p2sb_unhide();
62
63 union p2sb_bdf bdf = { .raw = pci_read_config16(PCH_DEV_P2SB, PCH_P2SB_HBDF) };
64
65 if (was_hidden)
66 p2sb_hide();
67
68 return bdf;
69}
70
71void p2sb_set_hpet_bdf(union p2sb_bdf bdf)
72{
73 pci_write_config16(PCH_DEV_P2SB, PCH_P2SB_HBDF, bdf.raw);
74}
75
Arthur Heymansa1f65be2020-11-12 21:07:13 +010076union p2sb_bdf p2sb_get_ioapic_bdf(void)
77{
78 const bool was_hidden = p2sb_is_hidden();
79 if (was_hidden)
80 p2sb_unhide();
81
82 union p2sb_bdf bdf = { .raw = pci_read_config16(PCH_DEV_P2SB, PCH_P2SB_IBDF) };
83
84 if (was_hidden)
85 p2sb_hide();
86
87 return bdf;
88}
89
90void p2sb_set_ioapic_bdf(union p2sb_bdf bdf)
91{
92 pci_write_config16(PCH_DEV_P2SB, PCH_P2SB_IBDF, bdf.raw);
93}
94
Lijian Zhaoa3cbbf72017-10-26 11:59:14 -070095static void p2sb_set_hide_bit(int hide)
96{
Subrata Banik7837c202018-05-07 17:13:40 +053097 const uint16_t reg = PCH_P2SB_E0 + 1;
Lijian Zhaoa3cbbf72017-10-26 11:59:14 -070098 const uint8_t mask = HIDE_BIT;
99 uint8_t val;
100
Nico Hubere5495032020-02-17 18:26:51 +0100101 val = pci_read_config8(PCH_DEV_P2SB, reg);
Lijian Zhaoa3cbbf72017-10-26 11:59:14 -0700102 val &= ~mask;
103 if (hide)
104 val |= mask;
Nico Hubere5495032020-02-17 18:26:51 +0100105 pci_write_config8(PCH_DEV_P2SB, reg, val);
Lijian Zhaoa3cbbf72017-10-26 11:59:14 -0700106}
107
108void p2sb_unhide(void)
109{
110 p2sb_set_hide_bit(0);
Subrata Banik7837c202018-05-07 17:13:40 +0530111
Arthur Heymansa8798a32020-11-12 20:41:57 +0100112 if (p2sb_is_hidden())
Keith Short15588b02019-05-09 11:40:34 -0600113 die_with_post_code(POST_HW_INIT_FAILURE,
114 "Unable to unhide PCH_DEV_P2SB device !\n");
Lijian Zhaoa3cbbf72017-10-26 11:59:14 -0700115}
116
117void p2sb_hide(void)
118{
119 p2sb_set_hide_bit(1);
Subrata Banik7837c202018-05-07 17:13:40 +0530120
Arthur Heymansa8798a32020-11-12 20:41:57 +0100121 if (!p2sb_is_hidden())
Keith Short15588b02019-05-09 11:40:34 -0600122 die_with_post_code(POST_HW_INIT_FAILURE,
123 "Unable to hide PCH_DEV_P2SB device !\n");
Subrata Banik7837c202018-05-07 17:13:40 +0530124}
125
126static void p2sb_configure_endpoints(int epmask_id, uint32_t mask)
127{
128 uint32_t reg32;
129
Nico Hubere5495032020-02-17 18:26:51 +0100130 reg32 = pci_read_config32(PCH_DEV_P2SB, PCH_P2SB_EPMASK(epmask_id));
131 pci_write_config32(PCH_DEV_P2SB, PCH_P2SB_EPMASK(epmask_id),
Subrata Banik7837c202018-05-07 17:13:40 +0530132 reg32 | mask);
133}
134
135static void p2sb_lock_endpoints(void)
136{
137 uint8_t reg8;
138
139 /* Set the "Endpoint Mask Lock!", P2SB PCI offset E2h bit[1] to 1. */
Nico Hubere5495032020-02-17 18:26:51 +0100140 reg8 = pci_read_config8(PCH_DEV_P2SB, PCH_P2SB_E0 + 2);
141 pci_write_config8(PCH_DEV_P2SB, PCH_P2SB_E0 + 2,
Subrata Banik7837c202018-05-07 17:13:40 +0530142 reg8 | P2SB_E0_MASKLOCK);
143}
144
145void p2sb_disable_sideband_access(void)
146{
147 uint32_t ep_mask[P2SB_EP_MASK_MAX_REG];
148 int i;
149
150 memset(ep_mask, 0, sizeof(ep_mask));
151
152 p2sb_soc_get_sb_mask(ep_mask, ARRAY_SIZE(ep_mask));
153
154 /* Remove the host accessing right to PSF register range. */
155 for (i = 0; i < P2SB_EP_MASK_MAX_REG; i++)
156 p2sb_configure_endpoints(i, ep_mask[i]);
157
158 p2sb_lock_endpoints();
Lijian Zhaoa3cbbf72017-10-26 11:59:14 -0700159}
160
161static void read_resources(struct device *dev)
162{
163 /*
164 * There's only one resource on the P2SB device. It's also already
165 * manually set to a fixed address in earlier boot stages.
Patrick Rudolph8d7a89b2019-10-04 09:22:27 +0200166 * The following code makes sure that it doesn't change if the device
167 * is visible and the resource allocator is being run.
Lijian Zhaoa3cbbf72017-10-26 11:59:14 -0700168 */
169 mmio_resource(dev, PCI_BASE_ADDRESS_0, P2SB_BAR / KiB, P2SB_SIZE / KiB);
170}
171
172static const struct device_operations device_ops = {
173 .read_resources = read_resources,
Nico Huber2f8ba692020-04-05 14:05:24 +0200174 .set_resources = noop_set_resources,
Subrata Banik6bbc91a2017-12-07 14:55:51 +0530175 .ops_pci = &pci_dev_ops_pci,
Lijian Zhaoa3cbbf72017-10-26 11:59:14 -0700176};
177
178static const unsigned short pci_device_ids[] = {
179 PCI_DEVICE_ID_INTEL_APL_P2SB,
180 PCI_DEVICE_ID_INTEL_GLK_P2SB,
Maxim Polyakov571d07d2019-08-22 13:11:32 +0300181 PCI_DEVICE_ID_INTEL_LWB_P2SB,
182 PCI_DEVICE_ID_INTEL_LWB_P2SB_SUPER,
Patrick Rudolph8d7a89b2019-10-04 09:22:27 +0200183 PCI_DEVICE_ID_INTEL_SKL_LP_P2SB,
184 PCI_DEVICE_ID_INTEL_SKL_P2SB,
185 PCI_DEVICE_ID_INTEL_KBL_P2SB,
Lijian Zhaoa3cbbf72017-10-26 11:59:14 -0700186 PCI_DEVICE_ID_INTEL_CNL_P2SB,
praveen hodagatta praneshe26c4a42018-09-20 03:49:45 +0800187 PCI_DEVICE_ID_INTEL_CNP_H_P2SB,
Aamir Bohra9eac0392018-06-30 12:07:04 +0530188 PCI_DEVICE_ID_INTEL_ICL_P2SB,
Ronak Kanabarda7ffb482019-02-05 01:51:13 +0530189 PCI_DEVICE_ID_INTEL_CMP_P2SB,
Gaggery Tsai12a651c2019-12-05 11:23:20 -0800190 PCI_DEVICE_ID_INTEL_CMP_H_P2SB,
Ravi Sarawadi6b5bf402019-10-21 22:25:04 -0700191 PCI_DEVICE_ID_INTEL_TGL_P2SB,
Tan, Lean Sheng26136092020-01-20 19:13:56 -0800192 PCI_DEVICE_ID_INTEL_EHL_P2SB,
Meera Ravindranath3f4af0d2020-02-12 16:01:22 +0530193 PCI_DEVICE_ID_INTEL_JSP_P2SB,
Subrata Banikf672f7f2020-08-03 14:29:25 +0530194 PCI_DEVICE_ID_INTEL_ADP_P_P2SB,
195 PCI_DEVICE_ID_INTEL_ADP_S_P2SB,
Lijian Zhaoa3cbbf72017-10-26 11:59:14 -0700196 0,
197};
198
199static const struct pci_driver pmc __pci_driver = {
200 .ops = &device_ops,
201 .vendor = PCI_VENDOR_ID_INTEL,
202 .devices = pci_device_ids,
203};