blob: e41e3375501b276a9ada40269ffb633db7df7530 [file] [log] [blame]
Angel Pons0612b272020-04-05 15:46:56 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Andrey Petrov04a72c42017-03-01 15:51:57 -08002
Subrata Banikc6e25522021-09-30 18:14:09 +05303#define __SIMPLE_DEVICE__
4
Subrata Banik05e06cd2017-11-09 15:04:09 +05305#include <assert.h>
Andrey Petrov04a72c42017-03-01 15:51:57 -08006#include <commonlib/helpers.h>
7#include <console/console.h>
Kyösti Mälkki13f66502019-03-03 08:01:05 +02008#include <device/mmio.h>
Andrey Petrov04a72c42017-03-01 15:51:57 -08009#include <delay.h>
10#include <device/pci.h>
11#include <device/pci_ids.h>
12#include <device/pci_ops.h>
13#include <intelblocks/cse.h>
Tim Wawrzynczak09635f42021-06-18 10:08:47 -060014#include <security/vboot/misc.h>
15#include <security/vboot/vboot_common.h>
Subrata Banik05e06cd2017-11-09 15:04:09 +053016#include <soc/iomap.h>
Andrey Petrov04a72c42017-03-01 15:51:57 -080017#include <soc/pci_devs.h>
Sridhar Siricilla8e465452019-09-23 20:59:38 +053018#include <soc/me.h>
Andrey Petrov04a72c42017-03-01 15:51:57 -080019#include <string.h>
20#include <timer.h>
21
Subrata Banik5c08c732017-11-13 14:54:37 +053022#define MAX_HECI_MESSAGE_RETRY_COUNT 5
23
Andrey Petrov04a72c42017-03-01 15:51:57 -080024/* Wait up to 15 sec for HECI to get ready */
Subrata Banik03aef282021-09-28 18:10:24 +053025#define HECI_DELAY_READY_MS (15 * 1000)
Jonathan Neuschäfer5268b762018-02-12 12:24:25 +010026/* Wait up to 100 usec between circular buffer polls */
Subrata Banik03aef282021-09-28 18:10:24 +053027#define HECI_DELAY_US 100
Andrey Petrov04a72c42017-03-01 15:51:57 -080028/* Wait up to 5 sec for CSE to chew something we sent */
Subrata Banik03aef282021-09-28 18:10:24 +053029#define HECI_SEND_TIMEOUT_MS (5 * 1000)
Andrey Petrov04a72c42017-03-01 15:51:57 -080030/* Wait up to 5 sec for CSE to blurp a reply */
Subrata Banik03aef282021-09-28 18:10:24 +053031#define HECI_READ_TIMEOUT_MS (5 * 1000)
Subrata Banika219edb2021-09-25 15:02:37 +053032/* Wait up to 1 ms for CSE CIP */
Subrata Banik03aef282021-09-28 18:10:24 +053033#define HECI_CIP_TIMEOUT_US 1000
Subrata Banikf5765812021-09-30 13:37:10 +053034/* Wait up to 5 seconds for CSE to boot from RO(BP1) */
35#define CSE_DELAY_BOOT_TO_RO_MS (5 * 1000)
Andrey Petrov04a72c42017-03-01 15:51:57 -080036
37#define SLOT_SIZE sizeof(uint32_t)
38
39#define MMIO_CSE_CB_WW 0x00
40#define MMIO_HOST_CSR 0x04
41#define MMIO_CSE_CB_RW 0x08
42#define MMIO_CSE_CSR 0x0c
Subrata Banika219edb2021-09-25 15:02:37 +053043#define MMIO_CSE_DEVIDLE 0x800
44#define CSE_DEV_IDLE (1 << 2)
45#define CSE_DEV_CIP (1 << 0)
Andrey Petrov04a72c42017-03-01 15:51:57 -080046
47#define CSR_IE (1 << 0)
48#define CSR_IS (1 << 1)
49#define CSR_IG (1 << 2)
50#define CSR_READY (1 << 3)
51#define CSR_RESET (1 << 4)
52#define CSR_RP_START 8
53#define CSR_RP (((1 << 8) - 1) << CSR_RP_START)
54#define CSR_WP_START 16
55#define CSR_WP (((1 << 8) - 1) << CSR_WP_START)
56#define CSR_CBD_START 24
57#define CSR_CBD (((1 << 8) - 1) << CSR_CBD_START)
58
59#define MEI_HDR_IS_COMPLETE (1 << 31)
60#define MEI_HDR_LENGTH_START 16
61#define MEI_HDR_LENGTH_SIZE 9
62#define MEI_HDR_LENGTH (((1 << MEI_HDR_LENGTH_SIZE) - 1) \
63 << MEI_HDR_LENGTH_START)
64#define MEI_HDR_HOST_ADDR_START 8
65#define MEI_HDR_HOST_ADDR (((1 << 8) - 1) << MEI_HDR_HOST_ADDR_START)
66#define MEI_HDR_CSE_ADDR_START 0
67#define MEI_HDR_CSE_ADDR (((1 << 8) - 1) << MEI_HDR_CSE_ADDR_START)
68
Subrata Banik38abbda2021-09-30 13:15:50 +053069/* Get HECI BAR 0 from PCI configuration space */
Subrata Banikc6e25522021-09-30 18:14:09 +053070static uintptr_t get_cse_bar(pci_devfn_t dev)
Subrata Banik38abbda2021-09-30 13:15:50 +053071{
72 uintptr_t bar;
73
Subrata Banikc6e25522021-09-30 18:14:09 +053074 bar = pci_read_config32(dev, PCI_BASE_ADDRESS_0);
Subrata Banik38abbda2021-09-30 13:15:50 +053075 assert(bar != 0);
76 /*
77 * Bits 31-12 are the base address as per EDS for SPI,
78 * Don't care about 0-11 bit
79 */
80 return bar & ~PCI_BASE_ADDRESS_MEM_ATTR_MASK;
81}
Andrey Petrov04a72c42017-03-01 15:51:57 -080082
83/*
84 * Initialize the device with provided temporary BAR. If BAR is 0 use a
85 * default. This is intended for pre-mem usage only where BARs haven't been
86 * assigned yet and devices are not enabled.
87 */
88void heci_init(uintptr_t tempbar)
89{
Elyes HAOUAS68c851b2018-06-12 22:06:09 +020090 pci_devfn_t dev = PCH_DEV_CSE;
Subrata Banikc6e25522021-09-30 18:14:09 +053091
Elyes HAOUAS2ec1c132020-04-29 09:57:05 +020092 u16 pcireg;
Andrey Petrov04a72c42017-03-01 15:51:57 -080093
94 /* Assume it is already initialized, nothing else to do */
Subrata Banikc6e25522021-09-30 18:14:09 +053095 if (get_cse_bar(dev))
Andrey Petrov04a72c42017-03-01 15:51:57 -080096 return;
97
98 /* Use default pre-ram bar */
99 if (!tempbar)
100 tempbar = HECI1_BASE_ADDRESS;
101
102 /* Assign Resources to HECI1 */
103 /* Clear BIT 1-2 of Command Register */
Elyes HAOUAS2ec1c132020-04-29 09:57:05 +0200104 pcireg = pci_read_config16(dev, PCI_COMMAND);
Andrey Petrov04a72c42017-03-01 15:51:57 -0800105 pcireg &= ~(PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY);
Elyes HAOUAS2ec1c132020-04-29 09:57:05 +0200106 pci_write_config16(dev, PCI_COMMAND, pcireg);
Andrey Petrov04a72c42017-03-01 15:51:57 -0800107
108 /* Program Temporary BAR for HECI1 */
109 pci_write_config32(dev, PCI_BASE_ADDRESS_0, tempbar);
110 pci_write_config32(dev, PCI_BASE_ADDRESS_1, 0x0);
111
112 /* Enable Bus Master and MMIO Space */
Elyes HAOUAS2ec1c132020-04-29 09:57:05 +0200113 pci_or_config16(dev, PCI_COMMAND, PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY);
Subrata Banik05e06cd2017-11-09 15:04:09 +0530114}
115
Subrata Banikc6e25522021-09-30 18:14:09 +0530116static uint32_t read_bar(pci_devfn_t dev, uint32_t offset)
Andrey Petrov04a72c42017-03-01 15:51:57 -0800117{
Subrata Banikc6e25522021-09-30 18:14:09 +0530118 return read32p(get_cse_bar(dev) + offset);
Andrey Petrov04a72c42017-03-01 15:51:57 -0800119}
120
Subrata Banikc6e25522021-09-30 18:14:09 +0530121static void write_bar(pci_devfn_t dev, uint32_t offset, uint32_t val)
Andrey Petrov04a72c42017-03-01 15:51:57 -0800122{
Subrata Banikc6e25522021-09-30 18:14:09 +0530123 return write32p(get_cse_bar(dev) + offset, val);
Andrey Petrov04a72c42017-03-01 15:51:57 -0800124}
125
126static uint32_t read_cse_csr(void)
127{
Subrata Banikc6e25522021-09-30 18:14:09 +0530128 return read_bar(PCH_DEV_CSE, MMIO_CSE_CSR);
Andrey Petrov04a72c42017-03-01 15:51:57 -0800129}
130
131static uint32_t read_host_csr(void)
132{
Subrata Banikc6e25522021-09-30 18:14:09 +0530133 return read_bar(PCH_DEV_CSE, MMIO_HOST_CSR);
Andrey Petrov04a72c42017-03-01 15:51:57 -0800134}
135
136static void write_host_csr(uint32_t data)
137{
Subrata Banikc6e25522021-09-30 18:14:09 +0530138 write_bar(PCH_DEV_CSE, MMIO_HOST_CSR, data);
Andrey Petrov04a72c42017-03-01 15:51:57 -0800139}
140
141static size_t filled_slots(uint32_t data)
142{
143 uint8_t wp, rp;
144 rp = data >> CSR_RP_START;
145 wp = data >> CSR_WP_START;
146 return (uint8_t) (wp - rp);
147}
148
149static size_t cse_filled_slots(void)
150{
151 return filled_slots(read_cse_csr());
152}
153
154static size_t host_empty_slots(void)
155{
156 uint32_t csr;
157 csr = read_host_csr();
158
159 return ((csr & CSR_CBD) >> CSR_CBD_START) - filled_slots(csr);
160}
161
162static void clear_int(void)
163{
164 uint32_t csr;
165 csr = read_host_csr();
166 csr |= CSR_IS;
167 write_host_csr(csr);
168}
169
170static uint32_t read_slot(void)
171{
Subrata Banikc6e25522021-09-30 18:14:09 +0530172 return read_bar(PCH_DEV_CSE, MMIO_CSE_CB_RW);
Andrey Petrov04a72c42017-03-01 15:51:57 -0800173}
174
175static void write_slot(uint32_t val)
176{
Subrata Banikc6e25522021-09-30 18:14:09 +0530177 write_bar(PCH_DEV_CSE, MMIO_CSE_CB_WW, val);
Andrey Petrov04a72c42017-03-01 15:51:57 -0800178}
179
180static int wait_write_slots(size_t cnt)
181{
182 struct stopwatch sw;
183
Subrata Banik03aef282021-09-28 18:10:24 +0530184 stopwatch_init_msecs_expire(&sw, HECI_SEND_TIMEOUT_MS);
Andrey Petrov04a72c42017-03-01 15:51:57 -0800185 while (host_empty_slots() < cnt) {
Subrata Banik03aef282021-09-28 18:10:24 +0530186 udelay(HECI_DELAY_US);
Andrey Petrov04a72c42017-03-01 15:51:57 -0800187 if (stopwatch_expired(&sw)) {
188 printk(BIOS_ERR, "HECI: timeout, buffer not drained\n");
189 return 0;
190 }
191 }
192 return 1;
193}
194
195static int wait_read_slots(size_t cnt)
196{
197 struct stopwatch sw;
198
Subrata Banik03aef282021-09-28 18:10:24 +0530199 stopwatch_init_msecs_expire(&sw, HECI_READ_TIMEOUT_MS);
Andrey Petrov04a72c42017-03-01 15:51:57 -0800200 while (cse_filled_slots() < cnt) {
Subrata Banik03aef282021-09-28 18:10:24 +0530201 udelay(HECI_DELAY_US);
Andrey Petrov04a72c42017-03-01 15:51:57 -0800202 if (stopwatch_expired(&sw)) {
203 printk(BIOS_ERR, "HECI: timed out reading answer!\n");
204 return 0;
205 }
206 }
207 return 1;
208}
209
210/* get number of full 4-byte slots */
211static size_t bytes_to_slots(size_t bytes)
212{
213 return ALIGN_UP(bytes, SLOT_SIZE) / SLOT_SIZE;
214}
215
216static int cse_ready(void)
217{
218 uint32_t csr;
219 csr = read_cse_csr();
220 return csr & CSR_READY;
221}
222
Sridhar Siricilla8e465452019-09-23 20:59:38 +0530223static bool cse_check_hfs1_com(int mode)
Sridhar Siricillab9d075b2019-08-31 11:38:33 +0530224{
225 union me_hfsts1 hfs1;
226 hfs1.data = me_read_config32(PCI_ME_HFSTS1);
Sridhar Siricilla8e465452019-09-23 20:59:38 +0530227 return hfs1.fields.operation_mode == mode;
228}
229
230bool cse_is_hfs1_cws_normal(void)
231{
232 union me_hfsts1 hfs1;
233 hfs1.data = me_read_config32(PCI_ME_HFSTS1);
234 if (hfs1.fields.working_state == ME_HFS1_CWS_NORMAL)
235 return true;
236 return false;
237}
238
239bool cse_is_hfs1_com_normal(void)
240{
241 return cse_check_hfs1_com(ME_HFS1_COM_NORMAL);
242}
243
244bool cse_is_hfs1_com_secover_mei_msg(void)
245{
246 return cse_check_hfs1_com(ME_HFS1_COM_SECOVER_MEI_MSG);
247}
248
249bool cse_is_hfs1_com_soft_temp_disable(void)
250{
251 return cse_check_hfs1_com(ME_HFS1_COM_SOFT_TEMP_DISABLE);
Sridhar Siricillab9d075b2019-08-31 11:38:33 +0530252}
253
Sridhar Siricilla99dbca32020-05-12 21:05:04 +0530254bool cse_is_hfs3_fw_sku_lite(void)
Sridhar Siricilla3465d272020-02-06 15:31:04 +0530255{
256 union me_hfsts3 hfs3;
257 hfs3.data = me_read_config32(PCI_ME_HFSTS3);
Sridhar Siricilla99dbca32020-05-12 21:05:04 +0530258 return hfs3.fields.fw_sku == ME_HFS3_FW_SKU_LITE;
Sridhar Siricilla3465d272020-02-06 15:31:04 +0530259}
260
Sridhar Siricillab9d075b2019-08-31 11:38:33 +0530261/* Makes the host ready to communicate with CSE */
Sridhar Siricillaff072e62019-11-27 14:55:16 +0530262void cse_set_host_ready(void)
Sridhar Siricillab9d075b2019-08-31 11:38:33 +0530263{
264 uint32_t csr;
265 csr = read_host_csr();
266 csr &= ~CSR_RESET;
267 csr |= (CSR_IG | CSR_READY);
268 write_host_csr(csr);
269}
270
Sridhar Siricillaff072e62019-11-27 14:55:16 +0530271/* Polls for ME mode ME_HFS1_COM_SECOVER_MEI_MSG for 15 seconds */
272uint8_t cse_wait_sec_override_mode(void)
Sridhar Siricillab9d075b2019-08-31 11:38:33 +0530273{
274 struct stopwatch sw;
Subrata Banik03aef282021-09-28 18:10:24 +0530275 stopwatch_init_msecs_expire(&sw, HECI_DELAY_READY_MS);
Sridhar Siricilla8e465452019-09-23 20:59:38 +0530276 while (!cse_is_hfs1_com_secover_mei_msg()) {
Subrata Banik03aef282021-09-28 18:10:24 +0530277 udelay(HECI_DELAY_US);
Sridhar Siricillaff072e62019-11-27 14:55:16 +0530278 if (stopwatch_expired(&sw)) {
279 printk(BIOS_ERR, "HECI: Timed out waiting for SEC_OVERRIDE mode!\n");
Sridhar Siricillab9d075b2019-08-31 11:38:33 +0530280 return 0;
Sridhar Siricillaff072e62019-11-27 14:55:16 +0530281 }
Sridhar Siricillab9d075b2019-08-31 11:38:33 +0530282 }
Sridhar Siricillaff072e62019-11-27 14:55:16 +0530283 printk(BIOS_DEBUG, "HECI: CSE took %lu ms to enter security override mode\n",
284 stopwatch_duration_msecs(&sw));
Sridhar Siricillab9d075b2019-08-31 11:38:33 +0530285 return 1;
286}
287
Sridhar Siricilla09ea3712019-11-12 23:35:50 +0530288/*
289 * Polls for CSE's current operation mode 'Soft Temporary Disable'.
290 * The CSE enters the current operation mode when it boots from RO(BP1).
291 */
292uint8_t cse_wait_com_soft_temp_disable(void)
293{
294 struct stopwatch sw;
Subrata Banikf5765812021-09-30 13:37:10 +0530295 stopwatch_init_msecs_expire(&sw, CSE_DELAY_BOOT_TO_RO_MS);
Sridhar Siricilla09ea3712019-11-12 23:35:50 +0530296 while (!cse_is_hfs1_com_soft_temp_disable()) {
Subrata Banik03aef282021-09-28 18:10:24 +0530297 udelay(HECI_DELAY_US);
Sridhar Siricilla09ea3712019-11-12 23:35:50 +0530298 if (stopwatch_expired(&sw)) {
299 printk(BIOS_ERR, "HECI: Timed out waiting for CSE to boot from RO!\n");
300 return 0;
301 }
302 }
303 printk(BIOS_SPEW, "HECI: CSE took %lu ms to boot from RO\n",
304 stopwatch_duration_msecs(&sw));
305 return 1;
306}
307
Andrey Petrov04a72c42017-03-01 15:51:57 -0800308static int wait_heci_ready(void)
309{
310 struct stopwatch sw;
311
Subrata Banik03aef282021-09-28 18:10:24 +0530312 stopwatch_init_msecs_expire(&sw, HECI_DELAY_READY_MS);
Andrey Petrov04a72c42017-03-01 15:51:57 -0800313 while (!cse_ready()) {
Subrata Banik03aef282021-09-28 18:10:24 +0530314 udelay(HECI_DELAY_US);
Andrey Petrov04a72c42017-03-01 15:51:57 -0800315 if (stopwatch_expired(&sw))
316 return 0;
317 }
318
319 return 1;
320}
321
322static void host_gen_interrupt(void)
323{
324 uint32_t csr;
325 csr = read_host_csr();
326 csr |= CSR_IG;
327 write_host_csr(csr);
328}
329
330static size_t hdr_get_length(uint32_t hdr)
331{
332 return (hdr & MEI_HDR_LENGTH) >> MEI_HDR_LENGTH_START;
333}
334
335static int
336send_one_message(uint32_t hdr, const void *buff)
337{
338 size_t pend_len, pend_slots, remainder, i;
339 uint32_t tmp;
340 const uint32_t *p = buff;
341
342 /* Get space for the header */
343 if (!wait_write_slots(1))
344 return 0;
345
346 /* First, write header */
347 write_slot(hdr);
348
349 pend_len = hdr_get_length(hdr);
350 pend_slots = bytes_to_slots(pend_len);
351
352 if (!wait_write_slots(pend_slots))
353 return 0;
354
355 /* Write the body in whole slots */
356 i = 0;
357 while (i < ALIGN_DOWN(pend_len, SLOT_SIZE)) {
358 write_slot(*p++);
359 i += SLOT_SIZE;
360 }
361
362 remainder = pend_len % SLOT_SIZE;
363 /* Pad to 4 bytes not touching caller's buffer */
364 if (remainder) {
365 memcpy(&tmp, p, remainder);
366 write_slot(tmp);
367 }
368
369 host_gen_interrupt();
370
371 /* Make sure nothing bad happened during transmission */
372 if (!cse_ready())
373 return 0;
374
375 return pend_len;
376}
377
Rizwan Qureshi957857d2021-08-30 16:43:57 +0530378/*
379 * Send message msg of size len to host from host_addr to cse_addr.
380 * Returns 1 on success and 0 otherwise.
381 * In case of error heci_reset() may be required.
382 */
383static int
Andrey Petrov04a72c42017-03-01 15:51:57 -0800384heci_send(const void *msg, size_t len, uint8_t host_addr, uint8_t client_addr)
385{
Subrata Banik5c08c732017-11-13 14:54:37 +0530386 uint8_t retry;
Andrey Petrov04a72c42017-03-01 15:51:57 -0800387 uint32_t csr, hdr;
Subrata Banik5c08c732017-11-13 14:54:37 +0530388 size_t sent, remaining, cb_size, max_length;
389 const uint8_t *p;
Andrey Petrov04a72c42017-03-01 15:51:57 -0800390
391 if (!msg || !len)
392 return 0;
393
394 clear_int();
395
Subrata Banik5c08c732017-11-13 14:54:37 +0530396 for (retry = 0; retry < MAX_HECI_MESSAGE_RETRY_COUNT; retry++) {
397 p = msg;
Andrey Petrov04a72c42017-03-01 15:51:57 -0800398
Subrata Banik5c08c732017-11-13 14:54:37 +0530399 if (!wait_heci_ready()) {
400 printk(BIOS_ERR, "HECI: not ready\n");
401 continue;
402 }
Andrey Petrov04a72c42017-03-01 15:51:57 -0800403
Subrata Banik4a722f52017-11-13 14:56:42 +0530404 csr = read_host_csr();
Subrata Banik5c08c732017-11-13 14:54:37 +0530405 cb_size = ((csr & CSR_CBD) >> CSR_CBD_START) * SLOT_SIZE;
406 /*
407 * Reserve one slot for the header. Limit max message
408 * length by 9 bits that are available in the header.
409 */
410 max_length = MIN(cb_size, (1 << MEI_HDR_LENGTH_SIZE) - 1)
411 - SLOT_SIZE;
412 remaining = len;
413
414 /*
415 * Fragment the message into smaller messages not exceeding
Jonathan Neuschäfer5268b762018-02-12 12:24:25 +0100416 * useful circular buffer length. Mark last message complete.
Subrata Banik5c08c732017-11-13 14:54:37 +0530417 */
418 do {
419 hdr = MIN(max_length, remaining)
420 << MEI_HDR_LENGTH_START;
421 hdr |= client_addr << MEI_HDR_CSE_ADDR_START;
422 hdr |= host_addr << MEI_HDR_HOST_ADDR_START;
423 hdr |= (MIN(max_length, remaining) == remaining) ?
Lee Leahy68ab0b52017-03-10 13:42:34 -0800424 MEI_HDR_IS_COMPLETE : 0;
Subrata Banik5c08c732017-11-13 14:54:37 +0530425 sent = send_one_message(hdr, p);
426 p += sent;
427 remaining -= sent;
428 } while (remaining > 0 && sent != 0);
Andrey Petrov04a72c42017-03-01 15:51:57 -0800429
Subrata Banik5c08c732017-11-13 14:54:37 +0530430 if (!remaining)
431 return 1;
432 }
433 return 0;
Andrey Petrov04a72c42017-03-01 15:51:57 -0800434}
435
436static size_t
437recv_one_message(uint32_t *hdr, void *buff, size_t maxlen)
438{
439 uint32_t reg, *p = buff;
440 size_t recv_slots, recv_len, remainder, i;
441
442 /* first get the header */
443 if (!wait_read_slots(1))
444 return 0;
445
446 *hdr = read_slot();
447 recv_len = hdr_get_length(*hdr);
448
449 if (!recv_len)
450 printk(BIOS_WARNING, "HECI: message is zero-sized\n");
451
452 recv_slots = bytes_to_slots(recv_len);
453
454 i = 0;
455 if (recv_len > maxlen) {
456 printk(BIOS_ERR, "HECI: response is too big\n");
457 return 0;
458 }
459
460 /* wait for the rest of messages to arrive */
461 wait_read_slots(recv_slots);
462
463 /* fetch whole slots first */
464 while (i < ALIGN_DOWN(recv_len, SLOT_SIZE)) {
465 *p++ = read_slot();
466 i += SLOT_SIZE;
467 }
468
Subrata Banik5c08c732017-11-13 14:54:37 +0530469 /*
470 * If ME is not ready, something went wrong and
471 * we received junk
472 */
473 if (!cse_ready())
474 return 0;
475
Andrey Petrov04a72c42017-03-01 15:51:57 -0800476 remainder = recv_len % SLOT_SIZE;
477
478 if (remainder) {
479 reg = read_slot();
480 memcpy(p, &reg, remainder);
481 }
482
483 return recv_len;
484}
485
Rizwan Qureshi957857d2021-08-30 16:43:57 +0530486/*
487 * Receive message into buff not exceeding maxlen. Message is considered
488 * successfully received if a 'complete' indication is read from ME side
489 * and there was enough space in the buffer to fit that message. maxlen
490 * is updated with size of message that was received. Returns 0 on failure
491 * and 1 on success.
492 * In case of error heci_reset() may be required.
493 */
494static int heci_receive(void *buff, size_t *maxlen)
Andrey Petrov04a72c42017-03-01 15:51:57 -0800495{
Subrata Banik5c08c732017-11-13 14:54:37 +0530496 uint8_t retry;
Andrey Petrov04a72c42017-03-01 15:51:57 -0800497 size_t left, received;
498 uint32_t hdr = 0;
Subrata Banik5c08c732017-11-13 14:54:37 +0530499 uint8_t *p;
Andrey Petrov04a72c42017-03-01 15:51:57 -0800500
501 if (!buff || !maxlen || !*maxlen)
502 return 0;
503
Andrey Petrov04a72c42017-03-01 15:51:57 -0800504 clear_int();
505
Subrata Banik5c08c732017-11-13 14:54:37 +0530506 for (retry = 0; retry < MAX_HECI_MESSAGE_RETRY_COUNT; retry++) {
507 p = buff;
508 left = *maxlen;
509
510 if (!wait_heci_ready()) {
511 printk(BIOS_ERR, "HECI: not ready\n");
512 continue;
513 }
514
515 /*
516 * Receive multiple packets until we meet one marked
517 * complete or we run out of space in caller-provided buffer.
518 */
519 do {
520 received = recv_one_message(&hdr, p, left);
Lijian Zhaoc50296d2017-12-15 19:10:18 -0800521 if (!received) {
Elyes HAOUAS3d450002018-08-09 18:55:58 +0200522 printk(BIOS_ERR, "HECI: Failed to receive!\n");
Lijian Zhaoc50296d2017-12-15 19:10:18 -0800523 return 0;
524 }
Subrata Banik5c08c732017-11-13 14:54:37 +0530525 left -= received;
526 p += received;
527 /* If we read out everything ping to send more */
528 if (!(hdr & MEI_HDR_IS_COMPLETE) && !cse_filled_slots())
529 host_gen_interrupt();
530 } while (received && !(hdr & MEI_HDR_IS_COMPLETE) && left > 0);
531
532 if ((hdr & MEI_HDR_IS_COMPLETE) && received) {
533 *maxlen = p - (uint8_t *) buff;
534 return 1;
535 }
Andrey Petrov04a72c42017-03-01 15:51:57 -0800536 }
Subrata Banik5c08c732017-11-13 14:54:37 +0530537 return 0;
Andrey Petrov04a72c42017-03-01 15:51:57 -0800538}
539
Rizwan Qureshi957857d2021-08-30 16:43:57 +0530540int heci_send_receive(const void *snd_msg, size_t snd_sz, void *rcv_msg, size_t *rcv_sz,
541 uint8_t cse_addr)
Sridhar Siricillaa5208f52019-08-30 17:10:24 +0530542{
Rizwan Qureshi957857d2021-08-30 16:43:57 +0530543 if (!heci_send(snd_msg, snd_sz, BIOS_HOST_ADDR, cse_addr)) {
Sridhar Siricillaa5208f52019-08-30 17:10:24 +0530544 printk(BIOS_ERR, "HECI: send Failed\n");
545 return 0;
546 }
547
548 if (rcv_msg != NULL) {
549 if (!heci_receive(rcv_msg, rcv_sz)) {
550 printk(BIOS_ERR, "HECI: receive Failed\n");
551 return 0;
552 }
553 }
554 return 1;
555}
556
Andrey Petrov04a72c42017-03-01 15:51:57 -0800557/*
558 * Attempt to reset the device. This is useful when host and ME are out
559 * of sync during transmission or ME didn't understand the message.
560 */
561int heci_reset(void)
562{
563 uint32_t csr;
564
Duncan Laurie15ca9032020-11-05 10:09:07 -0800565 /* Clear post code to prevent eventlog entry from unknown code. */
566 post_code(0);
567
Andrey Petrov04a72c42017-03-01 15:51:57 -0800568 /* Send reset request */
569 csr = read_host_csr();
Sridhar Siricillab9d075b2019-08-31 11:38:33 +0530570 csr |= (CSR_RESET | CSR_IG);
Andrey Petrov04a72c42017-03-01 15:51:57 -0800571 write_host_csr(csr);
572
573 if (wait_heci_ready()) {
574 /* Device is back on its imaginary feet, clear reset */
Sridhar Siricillaff072e62019-11-27 14:55:16 +0530575 cse_set_host_ready();
Andrey Petrov04a72c42017-03-01 15:51:57 -0800576 return 1;
577 }
578
579 printk(BIOS_CRIT, "HECI: reset failed\n");
580
581 return 0;
582}
583
Subrata Banik3710e992021-09-30 16:59:09 +0530584bool is_cse_devfn_visible(unsigned int devfn)
Sridhar Siricilla2cc66912019-08-31 11:20:34 +0530585{
Subrata Banik3710e992021-09-30 16:59:09 +0530586 int slot = PCI_SLOT(devfn);
587 int func = PCI_FUNC(devfn);
Sridhar Siricilla2cc66912019-08-31 11:20:34 +0530588
Subrata Banik3710e992021-09-30 16:59:09 +0530589 if (!is_devfn_enabled(devfn)) {
590 printk(BIOS_WARNING, "HECI: CSE device %02x.%01x is disabled\n", slot, func);
Sridhar Siricilla2cc66912019-08-31 11:20:34 +0530591 return false;
592 }
593
Subrata Banik3710e992021-09-30 16:59:09 +0530594 if (pci_read_config16(PCI_DEV(0, slot, func), PCI_VENDOR_ID) == 0xFFFF) {
595 printk(BIOS_WARNING, "HECI: CSE device %02x.%01x is hidden\n", slot, func);
Sridhar Siricilla2cc66912019-08-31 11:20:34 +0530596 return false;
597 }
598
599 return true;
600}
601
Subrata Banik3710e992021-09-30 16:59:09 +0530602bool is_cse_enabled(void)
603{
604 return is_cse_devfn_visible(PCH_DEVFN_CSE);
605}
606
Sridhar Siricilla2cc66912019-08-31 11:20:34 +0530607uint32_t me_read_config32(int offset)
608{
609 return pci_read_config32(PCH_DEV_CSE, offset);
610}
611
Sridhar Siricilla59c7cb7d2020-02-07 11:59:30 +0530612static bool cse_is_global_reset_allowed(void)
613{
614 /*
615 * Allow sending GLOBAL_RESET command only if:
616 * - CSE's current working state is Normal and current operation mode is Normal.
617 * - (or) CSE's current working state is normal and current operation mode can
618 * be Soft Temp Disable or Security Override Mode if CSE's Firmware SKU is
Sridhar Siricilla99dbca32020-05-12 21:05:04 +0530619 * Lite.
Sridhar Siricilla59c7cb7d2020-02-07 11:59:30 +0530620 */
621 if (!cse_is_hfs1_cws_normal())
622 return false;
623
624 if (cse_is_hfs1_com_normal())
625 return true;
626
Sridhar Siricilla99dbca32020-05-12 21:05:04 +0530627 if (cse_is_hfs3_fw_sku_lite()) {
Sridhar Siricilla59c7cb7d2020-02-07 11:59:30 +0530628 if (cse_is_hfs1_com_soft_temp_disable() || cse_is_hfs1_com_secover_mei_msg())
629 return true;
630 }
631 return false;
632}
633
Sridhar Siricillad415c202019-08-31 14:54:57 +0530634/*
Subrata Banikf463dc02020-09-14 19:04:03 +0530635 * Sends GLOBAL_RESET_REQ cmd to CSE with reset type GLOBAL_RESET.
636 * Returns 0 on failure and 1 on success.
Sridhar Siricillad415c202019-08-31 14:54:57 +0530637 */
Subrata Banikf463dc02020-09-14 19:04:03 +0530638static int cse_request_reset(enum rst_req_type rst_type)
Sridhar Siricillad415c202019-08-31 14:54:57 +0530639{
640 int status;
641 struct mkhi_hdr reply;
642 struct reset_message {
643 struct mkhi_hdr hdr;
644 uint8_t req_origin;
645 uint8_t reset_type;
646 } __packed;
647 struct reset_message msg = {
648 .hdr = {
649 .group_id = MKHI_GROUP_ID_CBM,
Sridhar Siricillae202e672020-01-07 23:36:40 +0530650 .command = MKHI_CBM_GLOBAL_RESET_REQ,
Sridhar Siricillad415c202019-08-31 14:54:57 +0530651 },
652 .req_origin = GR_ORIGIN_BIOS_POST,
653 .reset_type = rst_type
654 };
655 size_t reply_size;
656
Sridhar Siricillaf2eb6872019-12-05 19:54:16 +0530657 printk(BIOS_DEBUG, "HECI: Global Reset(Type:%d) Command\n", rst_type);
Sridhar Siricilla59c7cb7d2020-02-07 11:59:30 +0530658
Sridhar Siricillac2a2d2b2020-02-27 17:16:13 +0530659 if (!(rst_type == GLOBAL_RESET || rst_type == CSE_RESET_ONLY)) {
Sridhar Siricillaf2eb6872019-12-05 19:54:16 +0530660 printk(BIOS_ERR, "HECI: Unsupported reset type is requested\n");
661 return 0;
662 }
Sridhar Siricillad415c202019-08-31 14:54:57 +0530663
Subrata Banikf463dc02020-09-14 19:04:03 +0530664 if (!cse_is_global_reset_allowed() || !is_cse_enabled()) {
Sridhar Siricilla59c7cb7d2020-02-07 11:59:30 +0530665 printk(BIOS_ERR, "HECI: CSE does not meet required prerequisites\n");
666 return 0;
667 }
668
Sridhar Siricillad415c202019-08-31 14:54:57 +0530669 heci_reset();
670
671 reply_size = sizeof(reply);
672 memset(&reply, 0, reply_size);
673
Sridhar Siricillad415c202019-08-31 14:54:57 +0530674 if (rst_type == CSE_RESET_ONLY)
Sridhar Siricillaf2eb6872019-12-05 19:54:16 +0530675 status = heci_send(&msg, sizeof(msg), BIOS_HOST_ADDR, HECI_MKHI_ADDR);
Sridhar Siricillad415c202019-08-31 14:54:57 +0530676 else
Rizwan Qureshi957857d2021-08-30 16:43:57 +0530677 status = heci_send_receive(&msg, sizeof(msg), &reply, &reply_size,
678 HECI_MKHI_ADDR);
Sridhar Siricillad415c202019-08-31 14:54:57 +0530679
Sridhar Siricillaf2eb6872019-12-05 19:54:16 +0530680 printk(BIOS_DEBUG, "HECI: Global Reset %s!\n", status ? "success" : "failure");
681 return status;
Sridhar Siricillad415c202019-08-31 14:54:57 +0530682}
683
Subrata Banikf463dc02020-09-14 19:04:03 +0530684int cse_request_global_reset(void)
685{
686 return cse_request_reset(GLOBAL_RESET);
687}
688
Sridhar Siricillad16187e2019-11-27 16:02:47 +0530689static bool cse_is_hmrfpo_enable_allowed(void)
690{
691 /*
692 * Allow sending HMRFPO ENABLE command only if:
693 * - CSE's current working state is Normal and current operation mode is Normal
694 * - (or) cse's current working state is normal and current operation mode is
Sridhar Siricilla99dbca32020-05-12 21:05:04 +0530695 * Soft Temp Disable if CSE's Firmware SKU is Lite
Sridhar Siricillad16187e2019-11-27 16:02:47 +0530696 */
697 if (!cse_is_hfs1_cws_normal())
698 return false;
699
700 if (cse_is_hfs1_com_normal())
701 return true;
702
Sridhar Siricilla99dbca32020-05-12 21:05:04 +0530703 if (cse_is_hfs3_fw_sku_lite() && cse_is_hfs1_com_soft_temp_disable())
Sridhar Siricillad16187e2019-11-27 16:02:47 +0530704 return true;
705
706 return false;
707}
708
Sridhar Siricillae30a0e62019-08-31 16:12:21 +0530709/* Sends HMRFPO Enable command to CSE */
Sridhar Siricillaff072e62019-11-27 14:55:16 +0530710int cse_hmrfpo_enable(void)
Sridhar Siricillae30a0e62019-08-31 16:12:21 +0530711{
712 struct hmrfpo_enable_msg {
713 struct mkhi_hdr hdr;
714 uint32_t nonce[2];
715 } __packed;
716
717 /* HMRFPO Enable message */
718 struct hmrfpo_enable_msg msg = {
719 .hdr = {
Sridhar Siricillae202e672020-01-07 23:36:40 +0530720 .group_id = MKHI_GROUP_ID_HMRFPO,
Sridhar Siricillae30a0e62019-08-31 16:12:21 +0530721 .command = MKHI_HMRFPO_ENABLE,
722 },
723 .nonce = {0},
724 };
725
726 /* HMRFPO Enable response */
727 struct hmrfpo_enable_resp {
728 struct mkhi_hdr hdr;
Sridhar Siricillae202e672020-01-07 23:36:40 +0530729 /* Base addr for factory data area, not relevant for client SKUs */
Sridhar Siricillae30a0e62019-08-31 16:12:21 +0530730 uint32_t fct_base;
Sridhar Siricillae202e672020-01-07 23:36:40 +0530731 /* Length of factory data area, not relevant for client SKUs */
Sridhar Siricillae30a0e62019-08-31 16:12:21 +0530732 uint32_t fct_limit;
733 uint8_t status;
Sridhar Siricillad16187e2019-11-27 16:02:47 +0530734 uint8_t reserved[3];
Sridhar Siricillae30a0e62019-08-31 16:12:21 +0530735 } __packed;
736
737 struct hmrfpo_enable_resp resp;
738 size_t resp_size = sizeof(struct hmrfpo_enable_resp);
Sridhar Siricillae30a0e62019-08-31 16:12:21 +0530739
740 printk(BIOS_DEBUG, "HECI: Send HMRFPO Enable Command\n");
Sridhar Siricillad16187e2019-11-27 16:02:47 +0530741
742 if (!cse_is_hmrfpo_enable_allowed()) {
743 printk(BIOS_ERR, "HECI: CSE does not meet required prerequisites\n");
744 return 0;
Sridhar Siricillae30a0e62019-08-31 16:12:21 +0530745 }
746
747 if (!heci_send_receive(&msg, sizeof(struct hmrfpo_enable_msg),
Rizwan Qureshi957857d2021-08-30 16:43:57 +0530748 &resp, &resp_size, HECI_MKHI_ADDR))
Sridhar Siricillad16187e2019-11-27 16:02:47 +0530749 return 0;
Sridhar Siricillae30a0e62019-08-31 16:12:21 +0530750
751 if (resp.hdr.result) {
752 printk(BIOS_ERR, "HECI: Resp Failed:%d\n", resp.hdr.result);
Sridhar Siricillad16187e2019-11-27 16:02:47 +0530753 return 0;
Sridhar Siricillae30a0e62019-08-31 16:12:21 +0530754 }
Sridhar Siricillae30a0e62019-08-31 16:12:21 +0530755
Sridhar Siricillad16187e2019-11-27 16:02:47 +0530756 if (resp.status) {
757 printk(BIOS_ERR, "HECI: HMRFPO_Enable Failed (resp status: %d)\n", resp.status);
758 return 0;
759 }
760
761 return 1;
Sridhar Siricillae30a0e62019-08-31 16:12:21 +0530762}
763
764/*
765 * Sends HMRFPO Get Status command to CSE to get the HMRFPO status.
Sridhar Siricilla63be9182020-01-19 12:38:56 +0530766 * The status can be DISABLED/LOCKED/ENABLED
Sridhar Siricillae30a0e62019-08-31 16:12:21 +0530767 */
Sridhar Siricillaff072e62019-11-27 14:55:16 +0530768int cse_hmrfpo_get_status(void)
Sridhar Siricillae30a0e62019-08-31 16:12:21 +0530769{
770 struct hmrfpo_get_status_msg {
771 struct mkhi_hdr hdr;
772 } __packed;
773
774 struct hmrfpo_get_status_resp {
775 struct mkhi_hdr hdr;
776 uint8_t status;
Sridhar Siricilla63be9182020-01-19 12:38:56 +0530777 uint8_t reserved[3];
Sridhar Siricillae30a0e62019-08-31 16:12:21 +0530778 } __packed;
779
780 struct hmrfpo_get_status_msg msg = {
781 .hdr = {
Sridhar Siricillae202e672020-01-07 23:36:40 +0530782 .group_id = MKHI_GROUP_ID_HMRFPO,
Sridhar Siricillae30a0e62019-08-31 16:12:21 +0530783 .command = MKHI_HMRFPO_GET_STATUS,
784 },
785 };
786 struct hmrfpo_get_status_resp resp;
787 size_t resp_size = sizeof(struct hmrfpo_get_status_resp);
788
789 printk(BIOS_INFO, "HECI: Sending Get HMRFPO Status Command\n");
790
Sridhar Siricilla206905c2020-02-06 18:48:22 +0530791 if (!cse_is_hfs1_cws_normal()) {
792 printk(BIOS_ERR, "HECI: CSE's current working state is not Normal\n");
793 return -1;
794 }
795
Sridhar Siricillae30a0e62019-08-31 16:12:21 +0530796 if (!heci_send_receive(&msg, sizeof(struct hmrfpo_get_status_msg),
Rizwan Qureshi957857d2021-08-30 16:43:57 +0530797 &resp, &resp_size, HECI_MKHI_ADDR)) {
Sridhar Siricillae30a0e62019-08-31 16:12:21 +0530798 printk(BIOS_ERR, "HECI: HMRFPO send/receive fail\n");
799 return -1;
800 }
801
802 if (resp.hdr.result) {
803 printk(BIOS_ERR, "HECI: HMRFPO Resp Failed:%d\n",
804 resp.hdr.result);
805 return -1;
806 }
807
808 return resp.status;
809}
810
Sridhar Siricilla24a974a2020-02-19 14:41:36 +0530811void print_me_fw_version(void *unused)
812{
813 struct version {
814 uint16_t minor;
815 uint16_t major;
816 uint16_t build;
817 uint16_t hotfix;
818 } __packed;
819
820 struct fw_ver_resp {
821 struct mkhi_hdr hdr;
822 struct version code;
823 struct version rec;
824 struct version fitc;
825 } __packed;
826
827 const struct mkhi_hdr fw_ver_msg = {
828 .group_id = MKHI_GROUP_ID_GEN,
829 .command = MKHI_GEN_GET_FW_VERSION,
830 };
831
832 struct fw_ver_resp resp;
833 size_t resp_size = sizeof(resp);
834
835 /* Ignore if UART debugging is disabled */
836 if (!CONFIG(CONSOLE_SERIAL))
837 return;
838
Wim Vervoorn8602fb72020-03-30 12:17:54 +0200839 /* Ignore if CSE is disabled */
840 if (!is_cse_enabled())
841 return;
842
Sridhar Siricilla24a974a2020-02-19 14:41:36 +0530843 /*
Sridhar Siricilla99dbca32020-05-12 21:05:04 +0530844 * Ignore if ME Firmware SKU type is Lite since
Sridhar Siricilla24a974a2020-02-19 14:41:36 +0530845 * print_boot_partition_info() logs RO(BP1) and RW(BP2) versions.
846 */
Sridhar Siricilla99dbca32020-05-12 21:05:04 +0530847 if (cse_is_hfs3_fw_sku_lite())
Sridhar Siricilla24a974a2020-02-19 14:41:36 +0530848 return;
849
850 /*
851 * Prerequisites:
852 * 1) HFSTS1 Current Working State is Normal
853 * 2) HFSTS1 Current Operation Mode is Normal
854 * 3) It's after DRAM INIT DONE message (taken care of by calling it
855 * during ramstage
856 */
857 if (!cse_is_hfs1_cws_normal() || !cse_is_hfs1_com_normal())
858 goto fail;
859
860 heci_reset();
861
Rizwan Qureshi957857d2021-08-30 16:43:57 +0530862 if (!heci_send_receive(&fw_ver_msg, sizeof(fw_ver_msg), &resp, &resp_size,
863 HECI_MKHI_ADDR))
Sridhar Siricilla24a974a2020-02-19 14:41:36 +0530864 goto fail;
865
866 if (resp.hdr.result)
867 goto fail;
868
869 printk(BIOS_DEBUG, "ME: Version: %d.%d.%d.%d\n", resp.code.major,
870 resp.code.minor, resp.code.hotfix, resp.code.build);
871 return;
872
873fail:
874 printk(BIOS_DEBUG, "ME: Version: Unavailable\n");
875}
876
Tim Wawrzynczak09635f42021-06-18 10:08:47 -0600877void cse_trigger_vboot_recovery(enum csme_failure_reason reason)
878{
879 printk(BIOS_DEBUG, "cse: CSE status registers: HFSTS1: 0x%x, HFSTS2: 0x%x "
880 "HFSTS3: 0x%x\n", me_read_config32(PCI_ME_HFSTS1),
881 me_read_config32(PCI_ME_HFSTS2), me_read_config32(PCI_ME_HFSTS3));
882
883 if (CONFIG(VBOOT)) {
884 struct vb2_context *ctx = vboot_get_context();
885 if (ctx == NULL)
886 goto failure;
887 vb2api_fail(ctx, VB2_RECOVERY_INTEL_CSE_LITE_SKU, reason);
888 vboot_save_data(ctx);
889 vboot_reboot();
890 }
891failure:
892 die("cse: Failed to trigger recovery mode(recovery subcode:%d)\n", reason);
893}
894
Subrata Banikc6e25522021-09-30 18:14:09 +0530895static bool disable_cse_idle(pci_devfn_t dev)
Subrata Banika219edb2021-09-25 15:02:37 +0530896{
897 struct stopwatch sw;
Subrata Banikc6e25522021-09-30 18:14:09 +0530898 uint32_t dev_idle_ctrl = read_bar(dev, MMIO_CSE_DEVIDLE);
Subrata Banika219edb2021-09-25 15:02:37 +0530899 dev_idle_ctrl &= ~CSE_DEV_IDLE;
Subrata Banikc6e25522021-09-30 18:14:09 +0530900 write_bar(dev, MMIO_CSE_DEVIDLE, dev_idle_ctrl);
Subrata Banika219edb2021-09-25 15:02:37 +0530901
Subrata Banik03aef282021-09-28 18:10:24 +0530902 stopwatch_init_usecs_expire(&sw, HECI_CIP_TIMEOUT_US);
Subrata Banika219edb2021-09-25 15:02:37 +0530903 do {
Subrata Banikc6e25522021-09-30 18:14:09 +0530904 dev_idle_ctrl = read_bar(dev, MMIO_CSE_DEVIDLE);
Subrata Banika219edb2021-09-25 15:02:37 +0530905 if ((dev_idle_ctrl & CSE_DEV_CIP) == CSE_DEV_CIP)
906 return true;
Subrata Banik03aef282021-09-28 18:10:24 +0530907 udelay(HECI_DELAY_US);
Subrata Banika219edb2021-09-25 15:02:37 +0530908 } while (!stopwatch_expired(&sw));
909
910 return false;
911}
912
Subrata Banikc6e25522021-09-30 18:14:09 +0530913static void enable_cse_idle(pci_devfn_t dev)
Subrata Banika219edb2021-09-25 15:02:37 +0530914{
Subrata Banikc6e25522021-09-30 18:14:09 +0530915 uint32_t dev_idle_ctrl = read_bar(dev, MMIO_CSE_DEVIDLE);
Subrata Banika219edb2021-09-25 15:02:37 +0530916 dev_idle_ctrl |= CSE_DEV_IDLE;
Subrata Banikc6e25522021-09-30 18:14:09 +0530917 write_bar(dev, MMIO_CSE_DEVIDLE, dev_idle_ctrl);
Subrata Banika219edb2021-09-25 15:02:37 +0530918}
919
Subrata Banikc6e25522021-09-30 18:14:09 +0530920enum cse_device_state get_cse_device_state(unsigned int devfn)
Subrata Banika219edb2021-09-25 15:02:37 +0530921{
Subrata Banikc6e25522021-09-30 18:14:09 +0530922 pci_devfn_t dev = PCI_DEV(0, PCI_SLOT(devfn), PCI_FUNC(devfn));
923 uint32_t dev_idle_ctrl = read_bar(dev, MMIO_CSE_DEVIDLE);
Subrata Banika219edb2021-09-25 15:02:37 +0530924 if ((dev_idle_ctrl & CSE_DEV_IDLE) == CSE_DEV_IDLE)
925 return DEV_IDLE;
926
927 return DEV_ACTIVE;
928}
929
Subrata Banikc6e25522021-09-30 18:14:09 +0530930static enum cse_device_state ensure_cse_active(pci_devfn_t dev)
Subrata Banika219edb2021-09-25 15:02:37 +0530931{
Subrata Banikc6e25522021-09-30 18:14:09 +0530932 if (!disable_cse_idle(dev))
Subrata Banika219edb2021-09-25 15:02:37 +0530933 return DEV_IDLE;
Subrata Banikc6e25522021-09-30 18:14:09 +0530934 pci_or_config32(dev, PCI_COMMAND, PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
Subrata Banika219edb2021-09-25 15:02:37 +0530935
936 return DEV_ACTIVE;
937}
938
Subrata Banikc6e25522021-09-30 18:14:09 +0530939static void ensure_cse_idle(pci_devfn_t dev)
Subrata Banika219edb2021-09-25 15:02:37 +0530940{
Subrata Banikc6e25522021-09-30 18:14:09 +0530941 enable_cse_idle(dev);
Subrata Banika219edb2021-09-25 15:02:37 +0530942
Subrata Banikc6e25522021-09-30 18:14:09 +0530943 pci_and_config32(dev, PCI_COMMAND, ~(PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER));
Subrata Banika219edb2021-09-25 15:02:37 +0530944}
945
Subrata Banikc6e25522021-09-30 18:14:09 +0530946bool set_cse_device_state(unsigned int devfn, enum cse_device_state requested_state)
Subrata Banika219edb2021-09-25 15:02:37 +0530947{
Subrata Banikc6e25522021-09-30 18:14:09 +0530948 enum cse_device_state current_state = get_cse_device_state(devfn);
949 pci_devfn_t dev = PCI_DEV(0, PCI_SLOT(devfn), PCI_FUNC(devfn));
Subrata Banika219edb2021-09-25 15:02:37 +0530950
951 if (current_state == requested_state)
952 return true;
953
954 if (requested_state == DEV_ACTIVE)
Subrata Banikc6e25522021-09-30 18:14:09 +0530955 return ensure_cse_active(dev) == requested_state;
Subrata Banika219edb2021-09-25 15:02:37 +0530956 else
Subrata Banikc6e25522021-09-30 18:14:09 +0530957 ensure_cse_idle(dev);
Subrata Banika219edb2021-09-25 15:02:37 +0530958
959 return true;
960}
961
Andrey Petrov04a72c42017-03-01 15:51:57 -0800962#if ENV_RAMSTAGE
963
Andrey Petrov04a72c42017-03-01 15:51:57 -0800964static struct device_operations cse_ops = {
Subrata Banik38abbda2021-09-30 13:15:50 +0530965 .set_resources = pci_dev_set_resources,
Andrey Petrov04a72c42017-03-01 15:51:57 -0800966 .read_resources = pci_dev_read_resources,
967 .enable_resources = pci_dev_enable_resources,
968 .init = pci_dev_init,
Subrata Banik6bbc91a2017-12-07 14:55:51 +0530969 .ops_pci = &pci_dev_ops_pci,
Andrey Petrov04a72c42017-03-01 15:51:57 -0800970};
971
Hannah Williams63142152017-06-12 14:03:18 -0700972static const unsigned short pci_device_ids[] = {
973 PCI_DEVICE_ID_INTEL_APL_CSE0,
974 PCI_DEVICE_ID_INTEL_GLK_CSE0,
Andrey Petrov0405de92017-06-05 13:25:29 -0700975 PCI_DEVICE_ID_INTEL_CNL_CSE0,
Subrata Banikd0586d22017-11-27 13:28:41 +0530976 PCI_DEVICE_ID_INTEL_SKL_CSE0,
Maxim Polyakov571d07d2019-08-22 13:11:32 +0300977 PCI_DEVICE_ID_INTEL_LWB_CSE0,
978 PCI_DEVICE_ID_INTEL_LWB_CSE0_SUPER,
praveen hodagatta praneshe26c4a42018-09-20 03:49:45 +0800979 PCI_DEVICE_ID_INTEL_CNP_H_CSE0,
Aamir Bohra9eac0392018-06-30 12:07:04 +0530980 PCI_DEVICE_ID_INTEL_ICL_CSE0,
Ronak Kanabarda7ffb482019-02-05 01:51:13 +0530981 PCI_DEVICE_ID_INTEL_CMP_CSE0,
Gaggery Tsai12a651c2019-12-05 11:23:20 -0800982 PCI_DEVICE_ID_INTEL_CMP_H_CSE0,
Ravi Sarawadi6b5bf402019-10-21 22:25:04 -0700983 PCI_DEVICE_ID_INTEL_TGL_CSE0,
Jeremy Soller191a8d72021-08-10 14:06:51 -0600984 PCI_DEVICE_ID_INTEL_TGL_H_CSE0,
Tan, Lean Sheng26136092020-01-20 19:13:56 -0800985 PCI_DEVICE_ID_INTEL_MCC_CSE0,
986 PCI_DEVICE_ID_INTEL_MCC_CSE1,
987 PCI_DEVICE_ID_INTEL_MCC_CSE2,
988 PCI_DEVICE_ID_INTEL_MCC_CSE3,
Meera Ravindranath3f4af0d2020-02-12 16:01:22 +0530989 PCI_DEVICE_ID_INTEL_JSP_CSE0,
990 PCI_DEVICE_ID_INTEL_JSP_CSE1,
991 PCI_DEVICE_ID_INTEL_JSP_CSE2,
992 PCI_DEVICE_ID_INTEL_JSP_CSE3,
Subrata Banikf672f7f2020-08-03 14:29:25 +0530993 PCI_DEVICE_ID_INTEL_ADP_P_CSE0,
994 PCI_DEVICE_ID_INTEL_ADP_P_CSE1,
995 PCI_DEVICE_ID_INTEL_ADP_P_CSE2,
996 PCI_DEVICE_ID_INTEL_ADP_P_CSE3,
997 PCI_DEVICE_ID_INTEL_ADP_S_CSE0,
998 PCI_DEVICE_ID_INTEL_ADP_S_CSE1,
999 PCI_DEVICE_ID_INTEL_ADP_S_CSE2,
1000 PCI_DEVICE_ID_INTEL_ADP_S_CSE3,
Varshit Pandyaf4d98fdd22021-01-17 18:39:29 +05301001 PCI_DEVICE_ID_INTEL_ADP_M_CSE0,
1002 PCI_DEVICE_ID_INTEL_ADP_M_CSE1,
1003 PCI_DEVICE_ID_INTEL_ADP_M_CSE2,
1004 PCI_DEVICE_ID_INTEL_ADP_M_CSE3,
Hannah Williams63142152017-06-12 14:03:18 -07001005 0,
1006};
1007
Andrey Petrov04a72c42017-03-01 15:51:57 -08001008static const struct pci_driver cse_driver __pci_driver = {
1009 .ops = &cse_ops,
1010 .vendor = PCI_VENDOR_ID_INTEL,
1011 /* SoC/chipset needs to provide PCI device ID */
Andrey Petrov0405de92017-06-05 13:25:29 -07001012 .devices = pci_device_ids
Andrey Petrov04a72c42017-03-01 15:51:57 -08001013};
1014
1015#endif