1 /* SPDX-License-Identifier: GPL-2.0-only */
2
3 #define __SIMPLE_DEVICE__
4
5 #include <assert.h>
6 #include <commonlib/bsd/helpers.h>
7 #include <console/console.h>
8 #include <device/mmio.h>
9 #include <device/pci_def.h>
10 #include <device/pci_ops.h>
11 #include <device/pci_type.h>
12 #include <intelblocks/pcr.h>
13 #include <soc/pci_devs.h>
14 #include <timer.h>
15 #include <types.h>
16
17 #if (CONFIG_PCR_BASE_ADDRESS == 0)
18 #error "PCR_BASE_ADDRESS need to be non-zero!"
19 #endif
20
21 #if !CONFIG(PCR_COMMON_IOSF_1_0)
22
23 #define PCR_SBI_CMD_TIMEOUT 10 /* 10ms */
24
25 /* P2SB PCI configuration register */
26 #define P2SB_CR_SBI_ADDR 0xd0
27 #define P2SB_CR_SBI_DESTID 24
28 #define P2SB_CR_SBI_DATA 0xd4
29 #define P2SB_CR_SBI_STATUS 0xd8
30 /* Bit 15:8 */
31 #define P2SB_CR_SBI_OPCODE 8
32 #define P2SB_CR_SBI_OPCODE_MASK 0xFF00
33 /* Bit 7 */
34 #define P2SB_CR_SBI_POSTED 7
35 #define P2SB_CR_SBI_POSTED_MASK 0x0080
36 /* Bit 2-1 */
37 #define P2SB_CR_SBI_STATUS_MASK 0x0006
38 #define P2SB_CR_SBI_STATUS_SUCCESS 0
39 #define P2SB_CR_SBI_STATUS_NOT_SUPPORTED 1
40 #define P2SB_CR_SBI_STATUS_POWERED_DOWN 2
41 #define P2SB_CR_SBI_STATUS_MULTI_CAST_MIXED 3
42 /* Bit 0 */
43 #define P2SB_CR_SBI_STATUS_READY 0
44 #define P2SB_CR_SBI_STATUS_BUSY 1
45 #define P2SB_CR_SBI_ROUTE_IDEN 0xda
46 /* Bit 15-12 */
47 #define P2SB_CR_SBI_FBE 12
48 #define P2SB_CR_SBI_FBE_MASK 0xF
49 /* Bit 10-8 */
50 #define P2SB_CR_SBI_BAR 8
51 #define P2SB_CR_SBI_MASK 0x7
52 /* Bit 7-0 */
53 #define P2SB_CR_SBI_FID 0
54 #define P2SB_CR_SBI_FID_MASK 0xFF
55 #define P2SB_CR_SBI_EXT_ADDR 0xdc
56 #endif
57
__pcr_reg_address(uint8_t pid,uint16_t offset)58 static void *__pcr_reg_address(uint8_t pid, uint16_t offset)
59 {
60 uintptr_t reg_addr;
61
62 /* Create an address based off of port id and offset. */
63 reg_addr = CONFIG_PCR_BASE_ADDRESS;
64 reg_addr += ((uintptr_t)pid) << PCR_PORTID_SHIFT;
65 reg_addr += (uintptr_t)offset;
66
67 return (void *)reg_addr;
68 }
69
pcr_reg_address(uint8_t pid,uint16_t offset)70 void *pcr_reg_address(uint8_t pid, uint16_t offset)
71 {
72 if (CONFIG(PCR_COMMON_IOSF_1_0))
73 assert(IS_ALIGNED(offset, sizeof(uint32_t)));
74
75 return __pcr_reg_address(pid, offset);
76 }
77
78 /*
79 * The mapping of addresses via the SBREG_BAR assumes the IOSF-SB
80 * agents are using 32-bit aligned accesses for their configuration
81 * registers. For IOSF versions greater than 1_0, IOSF-SB
82 * agents can use any access (8/16/32 bit aligned) for their
83 * configuration registers
84 */
check_pcr_offset_align(uint16_t offset,size_t size)85 static inline void check_pcr_offset_align(uint16_t offset, size_t size)
86 {
87 const size_t align = CONFIG(PCR_COMMON_IOSF_1_0) ?
88 sizeof(uint32_t) : size;
89
90 assert(IS_ALIGNED(offset, align));
91 }
92
pcr_read32(uint8_t pid,uint16_t offset)93 uint32_t pcr_read32(uint8_t pid, uint16_t offset)
94 {
95 /* Ensure the PCR offset is correctly aligned. */
96 assert(IS_ALIGNED(offset, sizeof(uint32_t)));
97
98 return read32(__pcr_reg_address(pid, offset));
99 }
100
pcr_read16(uint8_t pid,uint16_t offset)101 uint16_t pcr_read16(uint8_t pid, uint16_t offset)
102 {
103 /* Ensure the PCR offset is correctly aligned. */
104 check_pcr_offset_align(offset, sizeof(uint16_t));
105
106 return read16(__pcr_reg_address(pid, offset));
107 }
108
pcr_read8(uint8_t pid,uint16_t offset)109 uint8_t pcr_read8(uint8_t pid, uint16_t offset)
110 {
111 /* Ensure the PCR offset is correctly aligned. */
112 check_pcr_offset_align(offset, sizeof(uint8_t));
113
114 return read8(__pcr_reg_address(pid, offset));
115 }
116
117 /*
118 * After every write one needs to perform a read an innocuous register to
119 * ensure the writes are completed for certain ports. This is done for
120 * all ports so that the callers don't need the per-port knowledge for
121 * each transaction.
122 */
write_completion(uint8_t pid,uint16_t offset)123 static inline void write_completion(uint8_t pid, uint16_t offset)
124 {
125 read32(__pcr_reg_address(pid, ALIGN_DOWN(offset, sizeof(uint32_t))));
126 }
127
pcr_write32(uint8_t pid,uint16_t offset,uint32_t indata)128 void pcr_write32(uint8_t pid, uint16_t offset, uint32_t indata)
129 {
130 /* Ensure the PCR offset is correctly aligned. */
131 assert(IS_ALIGNED(offset, sizeof(indata)));
132
133 write32(__pcr_reg_address(pid, offset), indata);
134 /* Ensure the writes complete. */
135 write_completion(pid, offset);
136 }
137
pcr_write16(uint8_t pid,uint16_t offset,uint16_t indata)138 void pcr_write16(uint8_t pid, uint16_t offset, uint16_t indata)
139 {
140 /* Ensure the PCR offset is correctly aligned. */
141 check_pcr_offset_align(offset, sizeof(uint16_t));
142
143 write16(__pcr_reg_address(pid, offset), indata);
144 /* Ensure the writes complete. */
145 write_completion(pid, offset);
146 }
147
pcr_write8(uint8_t pid,uint16_t offset,uint8_t indata)148 void pcr_write8(uint8_t pid, uint16_t offset, uint8_t indata)
149 {
150 /* Ensure the PCR offset is correctly aligned. */
151 check_pcr_offset_align(offset, sizeof(uint8_t));
152
153 write8(__pcr_reg_address(pid, offset), indata);
154 /* Ensure the writes complete. */
155 write_completion(pid, offset);
156 }
157
pcr_rmw32(uint8_t pid,uint16_t offset,uint32_t anddata,uint32_t ordata)158 void pcr_rmw32(uint8_t pid, uint16_t offset, uint32_t anddata, uint32_t ordata)
159 {
160 uint32_t data32;
161
162 data32 = pcr_read32(pid, offset);
163 data32 &= anddata;
164 data32 |= ordata;
165 pcr_write32(pid, offset, data32);
166 }
167
pcr_rmw16(uint8_t pid,uint16_t offset,uint16_t anddata,uint16_t ordata)168 void pcr_rmw16(uint8_t pid, uint16_t offset, uint16_t anddata, uint16_t ordata)
169 {
170 uint16_t data16;
171
172 data16 = pcr_read16(pid, offset);
173 data16 &= anddata;
174 data16 |= ordata;
175 pcr_write16(pid, offset, data16);
176 }
177
pcr_rmw8(uint8_t pid,uint16_t offset,uint8_t anddata,uint8_t ordata)178 void pcr_rmw8(uint8_t pid, uint16_t offset, uint8_t anddata, uint8_t ordata)
179 {
180 uint8_t data8;
181
182 data8 = pcr_read8(pid, offset);
183 data8 &= anddata;
184 data8 |= ordata;
185 pcr_write8(pid, offset, data8);
186 }
187
pcr_or32(uint8_t pid,uint16_t offset,uint32_t ordata)188 void pcr_or32(uint8_t pid, uint16_t offset, uint32_t ordata)
189 {
190 uint32_t data32;
191
192 data32 = pcr_read32(pid, offset);
193 data32 |= ordata;
194 pcr_write32(pid, offset, data32);
195 }
196
pcr_or16(uint8_t pid,uint16_t offset,uint16_t ordata)197 void pcr_or16(uint8_t pid, uint16_t offset, uint16_t ordata)
198 {
199 uint16_t data16;
200
201 data16 = pcr_read16(pid, offset);
202 data16 |= ordata;
203 pcr_write16(pid, offset, data16);
204 }
205
pcr_or8(uint8_t pid,uint16_t offset,uint8_t ordata)206 void pcr_or8(uint8_t pid, uint16_t offset, uint8_t ordata)
207 {
208 uint8_t data8;
209
210 data8 = pcr_read8(pid, offset);
211 data8 |= ordata;
212 pcr_write8(pid, offset, data8);
213 }
214
215 #if !CONFIG(PCR_COMMON_IOSF_1_0)
216
pcr_wait_for_completion(const pci_devfn_t dev)217 static int pcr_wait_for_completion(const pci_devfn_t dev)
218 {
219 struct stopwatch sw;
220
221 stopwatch_init_msecs_expire(&sw, PCR_SBI_CMD_TIMEOUT);
222 do {
223 if ((pci_read_config16(dev, P2SB_CR_SBI_STATUS) &
224 P2SB_CR_SBI_STATUS_BUSY) == 0)
225 return 0;
226 } while (!stopwatch_expired(&sw));
227
228 return -1;
229 }
230
231 /*
232 * API to perform sideband communication
233 *
234 * Input:
235 * struct pcr_sbi_msg
236 * data - read/write for sbi message
237 * response -
238 * 0 - successful
239 * 1 - unsuccessful
240 * 2 - powered down
241 * 3 - multi-cast mixed
242 *
243 * Output:
244 * 0: SBI message is successfully completed
245 * -1: SBI message failure
246 */
pcr_execute_sideband_msg(pci_devfn_t dev,struct pcr_sbi_msg * msg,uint32_t * data,uint8_t * response)247 int pcr_execute_sideband_msg(pci_devfn_t dev, struct pcr_sbi_msg *msg, uint32_t *data,
248 uint8_t *response)
249 {
250 uint32_t sbi_data;
251 uint16_t sbi_status;
252 uint16_t sbi_rid;
253
254 if (!msg || !data || !response) {
255 printk(BIOS_ERR, "Pointer checked for NULL Fail! "
256 "msg = %p \t data = %p \t response = %p\n",
257 msg, data, response);
258 return -1;
259 }
260
261 switch (msg->opcode) {
262 case MEM_READ:
263 case MEM_WRITE:
264 case PCI_CONFIG_READ:
265 case PCI_CONFIG_WRITE:
266 case PCR_READ:
267 case PCR_WRITE:
268 case GPIO_LOCK_UNLOCK:
269 break;
270 default:
271 printk(BIOS_ERR, "SBI Failure: Wrong Input = %x!\n",
272 msg->opcode);
273 return -1;
274 }
275
276 if (pci_read_config16(dev, PCI_VENDOR_ID) == 0xffff) {
277 printk(BIOS_ERR, "SBI Failure: P2SB device Hidden!\n");
278 return -1;
279 }
280
281 /*
282 * BWG Section 2.2.1
283 * 1. Poll P2SB PCI offset D8h[0] = 0b
284 * Make sure the previous operation is completed.
285 */
286 if (pcr_wait_for_completion(dev)) {
287 printk(BIOS_ERR, "SBI Failure: Time Out!\n");
288 return -1;
289 }
290
291 /* Initial Response status */
292 *response = P2SB_CR_SBI_STATUS_NOT_SUPPORTED;
293
294 /*
295 * 2. Write P2SB PCI offset D0h[31:0] with Address
296 * and Destination Port ID
297 */
298 pci_write_config32(dev, P2SB_CR_SBI_ADDR,
299 (msg->pid << P2SB_CR_SBI_DESTID) | msg->offset);
300
301 /*
302 * 3. Write P2SB PCI offset DCh[31:0] with extended address,
303 * which is expected to be 0
304 */
305 pci_write_config32(dev, P2SB_CR_SBI_EXT_ADDR, msg->offset >> 16);
306
307 /*
308 * 4. Set P2SB PCI offset D8h[15:8] = 00000110b for read
309 * Set P2SB PCI offset D8h[15:8] = 00000111b for write
310 *
311 * Set SBISTAT[15:8] to the opcode passed in
312 * Set SBISTAT[7] to the posted passed in
313 */
314 sbi_status = pci_read_config16(dev, P2SB_CR_SBI_STATUS);
315 sbi_status &= ~(P2SB_CR_SBI_OPCODE_MASK | P2SB_CR_SBI_POSTED_MASK);
316 sbi_status |= (msg->opcode << P2SB_CR_SBI_OPCODE) |
317 (msg->is_posted << P2SB_CR_SBI_POSTED);
318 pci_write_config16(dev, P2SB_CR_SBI_STATUS, sbi_status);
319
320 /*
321 * 5. Write P2SB PCI offset DAh[15:0] = F000h
322 *
323 * Set RID[15:0] = Fbe << 12 | Bar << 8 | Fid
324 */
325 sbi_rid = ((msg->fast_byte_enable & P2SB_CR_SBI_FBE_MASK)
326 << P2SB_CR_SBI_FBE) |
327 ((msg->bar & P2SB_CR_SBI_MASK) << P2SB_CR_SBI_BAR) |
328 (msg->fid & P2SB_CR_SBI_FID_MASK);
329 pci_write_config16(dev, P2SB_CR_SBI_ROUTE_IDEN, sbi_rid);
330
331 switch (msg->opcode) {
332 case MEM_WRITE:
333 case PCI_CONFIG_WRITE:
334 case PCR_WRITE:
335 case GPIO_LOCK_UNLOCK:
336 /*
337 * 6. Write P2SB PCI offset D4h[31:0] with the
338 * intended data accordingly
339 */
340 sbi_data = *data;
341 pci_write_config32(dev, P2SB_CR_SBI_DATA, sbi_data);
342 break;
343 default:
344 /* 6. Write P2SB PCI offset D4h[31:0] with dummy data */
345 pci_write_config32(dev, P2SB_CR_SBI_DATA, 0);
346 break;
347 }
348
349 /*
350 * 7. Set P2SB PCI offset D8h[0] = 1b, Poll P2SB PCI offset D8h[0] = 0b
351 *
352 * Set SBISTAT[0] = 1b, trigger the SBI operation
353 */
354 sbi_status = pci_read_config16(dev, P2SB_CR_SBI_STATUS);
355 sbi_status |= P2SB_CR_SBI_STATUS_BUSY;
356 pci_write_config16(dev, P2SB_CR_SBI_STATUS, sbi_status);
357
358 /* Poll SBISTAT[0] = 0b, Polling for Busy bit */
359 if (pcr_wait_for_completion(dev)) {
360 printk(BIOS_ERR, "SBI Failure: Time Out!\n");
361 return -1;
362 }
363
364 /*
365 * 8. Check if P2SB PCI offset D8h[2:1] = 00b for
366 * successful transaction
367 */
368 *response = (sbi_status & P2SB_CR_SBI_STATUS_MASK) >> 1;
369 if (*response == P2SB_CR_SBI_STATUS_SUCCESS) {
370 switch (msg->opcode) {
371 case MEM_READ:
372 case PCI_CONFIG_READ:
373 case PCR_READ:
374 sbi_data = pci_read_config32(dev, P2SB_CR_SBI_DATA);
375 *data = sbi_data;
376 break;
377 default:
378 break;
379 }
380 return 0;
381 }
382 printk(BIOS_ERR, "SBI Failure: Transaction Status = %x\n",
383 *response);
384 return -1;
385 }
386 #endif
387