xref: /aosp_15_r20/external/coreboot/src/soc/intel/common/block/p2sb/p2sblib.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #define __SIMPLE_DEVICE__
4 
5 #include <console/console.h>
6 #include <device/pci.h>
7 #include <device/pci_ids.h>
8 #include <intelblocks/p2sb.h>
9 #include <intelblocks/p2sblib.h>
10 #include <intelblocks/pcr.h>
11 #include <soc/pci_devs.h>
12 
p2sb_dev_enable_bar(pci_devfn_t dev,uint64_t bar)13 void p2sb_dev_enable_bar(pci_devfn_t dev, uint64_t bar)
14 {
15 	/* Enable PCR Base addresses */
16 	pci_write_config32(dev, PCI_BASE_ADDRESS_0, (uint32_t)bar);
17 	pci_write_config32(dev, PCI_BASE_ADDRESS_1, (uint32_t)(bar >> 32));
18 
19 	/* Enable P2SB MSE */
20 	pci_write_config16(dev, PCI_COMMAND, PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY);
21 }
22 
p2sb_dev_is_hidden(pci_devfn_t dev)23 bool p2sb_dev_is_hidden(pci_devfn_t dev)
24 {
25 	const uint16_t pci_vid = pci_read_config16(dev, PCI_VENDOR_ID);
26 
27 	if (pci_vid == 0xffff)
28 		return true;
29 	if (pci_vid == PCI_VID_INTEL)
30 		return false;
31 	printk(BIOS_ERR, "P2SB PCI_VENDOR_ID is invalid, unknown if hidden\n");
32 	return true;
33 }
34 
p2sb_dev_set_hide_bit(pci_devfn_t dev,int hide)35 static void p2sb_dev_set_hide_bit(pci_devfn_t dev, int hide)
36 {
37 	const uint16_t reg = P2SBC + 1;
38 	const uint8_t mask = P2SBC_HIDE_BIT;
39 	uint8_t val;
40 
41 	val = pci_read_config8(dev, reg);
42 	val &= ~mask;
43 	if (hide)
44 		val |= mask;
45 	pci_write_config8(dev, reg, val);
46 }
47 
p2sb_dev_unhide(pci_devfn_t dev)48 void p2sb_dev_unhide(pci_devfn_t dev)
49 {
50 	p2sb_dev_set_hide_bit(dev, 0);
51 
52 	if (p2sb_dev_is_hidden(dev))
53 		die_with_post_code(POSTCODE_HW_INIT_FAILURE,
54 				"Unable to unhide the P2SB device!\n");
55 }
56 
p2sb_dev_hide(pci_devfn_t dev)57 void p2sb_dev_hide(pci_devfn_t dev)
58 {
59 	p2sb_dev_set_hide_bit(dev, 1);
60 
61 	if (!p2sb_dev_is_hidden(dev))
62 		die_with_post_code(POSTCODE_HW_INIT_FAILURE,
63 				"Unable to hide the P2SB device!\n");
64 }
65 
p2sb_send_sideband_msg(pci_devfn_t dev,uint8_t cmd,uint8_t pid,uint16_t reg,uint32_t * data)66 static void p2sb_send_sideband_msg(pci_devfn_t dev, uint8_t cmd, uint8_t pid,
67 						uint16_t reg, uint32_t *data)
68 {
69 	struct pcr_sbi_msg msg = {
70 		.pid = pid,
71 		.offset = reg,
72 		.opcode = cmd,
73 		.is_posted = false,
74 		.fast_byte_enable = 0xF,
75 		.bar = 0,
76 		.fid = 0
77 	};
78 	uint8_t response;
79 	int status;
80 
81 	status = pcr_execute_sideband_msg(dev, &msg, data, &response);
82 	if (status || response)
83 		printk(BIOS_ERR, "Fail to execute p2sb sideband access\n");
84 }
85 
p2sb_execute_sbi_in_smm(pci_devfn_t dev,uint8_t cmd,uint8_t pid,uint16_t reg,uint32_t * data)86 static void p2sb_execute_sbi_in_smm(pci_devfn_t dev, uint8_t cmd, uint8_t pid,
87 						uint16_t reg, uint32_t *data)
88 {
89 	/* Unhide the P2SB device */
90 	p2sb_dev_unhide(dev);
91 
92 	p2sb_send_sideband_msg(dev, cmd, pid, reg, data);
93 
94 	/* Hide the P2SB device */
95 	p2sb_dev_hide(dev);
96 }
97 
p2sb_execute_sideband_access(pci_devfn_t dev,uint8_t cmd,uint8_t pid,uint16_t reg,uint32_t * data)98 static void p2sb_execute_sideband_access(pci_devfn_t dev, uint8_t cmd, uint8_t pid,
99 						uint16_t reg, uint32_t *data)
100 {
101 	if (ENV_SMM)
102 		/*
103 		 * FSP-S will hide the P2SB device. With the device hidden, we will not be
104 		 * able to send the sideband interface message. Therefore, we need to unhide
105 		 * the P2SB device which can only be done in SMM requiring that this
106 		 * function is called from SMM.
107 		 */
108 		p2sb_execute_sbi_in_smm(dev, cmd, pid, reg, data);
109 	else if (!p2sb_dev_is_hidden(dev))
110 		p2sb_send_sideband_msg(dev, cmd, pid, reg, data);
111 	else
112 		printk(BIOS_WARNING, "Error: P2SB must be hidden, try calling from SMM!\n");
113 }
114 
p2sb_dev_sbi_read(pci_devfn_t dev,uint8_t pid,uint16_t reg)115 uint32_t p2sb_dev_sbi_read(pci_devfn_t dev, uint8_t pid, uint16_t reg)
116 {
117 	uint32_t val = 0;
118 	p2sb_execute_sideband_access(dev, PCR_READ, pid, reg, &val);
119 	return val;
120 }
121 
p2sb_dev_sbi_write(pci_devfn_t dev,uint8_t pid,uint16_t reg,uint32_t val)122 void p2sb_dev_sbi_write(pci_devfn_t dev, uint8_t pid, uint16_t reg, uint32_t val)
123 {
124 	p2sb_execute_sideband_access(dev, PCR_WRITE, pid, reg, &val);
125 }
126