soc/intel/{cnl,icl,skl,tgl,common}: Make changes to send_heci_reset_req_message()
[coreboot.git] / src / soc / intel / common / block / cse / cse.c
blobc82f3bdc7aaa826615fb601932f62cac90645d26
1 /*
2 * This file is part of the coreboot project.
4 * Copyright 2017-2018 Intel Inc.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
16 #include <assert.h>
17 #include <commonlib/helpers.h>
18 #include <console/console.h>
19 #include <device/mmio.h>
20 #include <delay.h>
21 #include <device/pci.h>
22 #include <device/pci_ids.h>
23 #include <device/pci_ops.h>
24 #include <intelblocks/cse.h>
25 #include <soc/iomap.h>
26 #include <soc/pci_devs.h>
27 #include <soc/me.h>
28 #include <string.h>
29 #include <timer.h>
31 #define MAX_HECI_MESSAGE_RETRY_COUNT 5
33 /* Wait up to 15 sec for HECI to get ready */
34 #define HECI_DELAY_READY (15 * 1000)
35 /* Wait up to 100 usec between circular buffer polls */
36 #define HECI_DELAY 100
37 /* Wait up to 5 sec for CSE to chew something we sent */
38 #define HECI_SEND_TIMEOUT (5 * 1000)
39 /* Wait up to 5 sec for CSE to blurp a reply */
40 #define HECI_READ_TIMEOUT (5 * 1000)
42 #define SLOT_SIZE sizeof(uint32_t)
44 #define MMIO_CSE_CB_WW 0x00
45 #define MMIO_HOST_CSR 0x04
46 #define MMIO_CSE_CB_RW 0x08
47 #define MMIO_CSE_CSR 0x0c
49 #define CSR_IE (1 << 0)
50 #define CSR_IS (1 << 1)
51 #define CSR_IG (1 << 2)
52 #define CSR_READY (1 << 3)
53 #define CSR_RESET (1 << 4)
54 #define CSR_RP_START 8
55 #define CSR_RP (((1 << 8) - 1) << CSR_RP_START)
56 #define CSR_WP_START 16
57 #define CSR_WP (((1 << 8) - 1) << CSR_WP_START)
58 #define CSR_CBD_START 24
59 #define CSR_CBD (((1 << 8) - 1) << CSR_CBD_START)
61 #define MEI_HDR_IS_COMPLETE (1 << 31)
62 #define MEI_HDR_LENGTH_START 16
63 #define MEI_HDR_LENGTH_SIZE 9
64 #define MEI_HDR_LENGTH (((1 << MEI_HDR_LENGTH_SIZE) - 1) \
65 << MEI_HDR_LENGTH_START)
66 #define MEI_HDR_HOST_ADDR_START 8
67 #define MEI_HDR_HOST_ADDR (((1 << 8) - 1) << MEI_HDR_HOST_ADDR_START)
68 #define MEI_HDR_CSE_ADDR_START 0
69 #define MEI_HDR_CSE_ADDR (((1 << 8) - 1) << MEI_HDR_CSE_ADDR_START)
71 static struct cse_device {
72 uintptr_t sec_bar;
73 } cse;
76 * Initialize the device with provided temporary BAR. If BAR is 0 use a
77 * default. This is intended for pre-mem usage only where BARs haven't been
78 * assigned yet and devices are not enabled.
80 void heci_init(uintptr_t tempbar)
82 #if defined(__SIMPLE_DEVICE__)
83 pci_devfn_t dev = PCH_DEV_CSE;
84 #else
85 struct device *dev = PCH_DEV_CSE;
86 #endif
87 u8 pcireg;
89 /* Assume it is already initialized, nothing else to do */
90 if (cse.sec_bar)
91 return;
93 /* Use default pre-ram bar */
94 if (!tempbar)
95 tempbar = HECI1_BASE_ADDRESS;
97 /* Assign Resources to HECI1 */
98 /* Clear BIT 1-2 of Command Register */
99 pcireg = pci_read_config8(dev, PCI_COMMAND);
100 pcireg &= ~(PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY);
101 pci_write_config8(dev, PCI_COMMAND, pcireg);
103 /* Program Temporary BAR for HECI1 */
104 pci_write_config32(dev, PCI_BASE_ADDRESS_0, tempbar);
105 pci_write_config32(dev, PCI_BASE_ADDRESS_1, 0x0);
107 /* Enable Bus Master and MMIO Space */
108 pcireg = pci_read_config8(dev, PCI_COMMAND);
109 pcireg |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
110 pci_write_config8(dev, PCI_COMMAND, pcireg);
112 cse.sec_bar = tempbar;
115 /* Get HECI BAR 0 from PCI configuration space */
116 static uint32_t get_cse_bar(void)
118 uintptr_t bar;
120 bar = pci_read_config32(PCH_DEV_CSE, PCI_BASE_ADDRESS_0);
121 assert(bar != 0);
123 * Bits 31-12 are the base address as per EDS for SPI,
124 * Don't care about 0-11 bit
126 return bar & ~PCI_BASE_ADDRESS_MEM_ATTR_MASK;
129 static uint32_t read_bar(uint32_t offset)
131 /* Load and cache BAR */
132 if (!cse.sec_bar)
133 cse.sec_bar = get_cse_bar();
134 return read32((void *)(cse.sec_bar + offset));
137 static void write_bar(uint32_t offset, uint32_t val)
139 /* Load and cache BAR */
140 if (!cse.sec_bar)
141 cse.sec_bar = get_cse_bar();
142 return write32((void *)(cse.sec_bar + offset), val);
145 static uint32_t read_cse_csr(void)
147 return read_bar(MMIO_CSE_CSR);
150 static uint32_t read_host_csr(void)
152 return read_bar(MMIO_HOST_CSR);
155 static void write_host_csr(uint32_t data)
157 write_bar(MMIO_HOST_CSR, data);
160 static size_t filled_slots(uint32_t data)
162 uint8_t wp, rp;
163 rp = data >> CSR_RP_START;
164 wp = data >> CSR_WP_START;
165 return (uint8_t) (wp - rp);
168 static size_t cse_filled_slots(void)
170 return filled_slots(read_cse_csr());
173 static size_t host_empty_slots(void)
175 uint32_t csr;
176 csr = read_host_csr();
178 return ((csr & CSR_CBD) >> CSR_CBD_START) - filled_slots(csr);
181 static void clear_int(void)
183 uint32_t csr;
184 csr = read_host_csr();
185 csr |= CSR_IS;
186 write_host_csr(csr);
189 static uint32_t read_slot(void)
191 return read_bar(MMIO_CSE_CB_RW);
194 static void write_slot(uint32_t val)
196 write_bar(MMIO_CSE_CB_WW, val);
199 static int wait_write_slots(size_t cnt)
201 struct stopwatch sw;
203 stopwatch_init_msecs_expire(&sw, HECI_SEND_TIMEOUT);
204 while (host_empty_slots() < cnt) {
205 udelay(HECI_DELAY);
206 if (stopwatch_expired(&sw)) {
207 printk(BIOS_ERR, "HECI: timeout, buffer not drained\n");
208 return 0;
211 return 1;
214 static int wait_read_slots(size_t cnt)
216 struct stopwatch sw;
218 stopwatch_init_msecs_expire(&sw, HECI_READ_TIMEOUT);
219 while (cse_filled_slots() < cnt) {
220 udelay(HECI_DELAY);
221 if (stopwatch_expired(&sw)) {
222 printk(BIOS_ERR, "HECI: timed out reading answer!\n");
223 return 0;
226 return 1;
229 /* get number of full 4-byte slots */
230 static size_t bytes_to_slots(size_t bytes)
232 return ALIGN_UP(bytes, SLOT_SIZE) / SLOT_SIZE;
235 static int cse_ready(void)
237 uint32_t csr;
238 csr = read_cse_csr();
239 return csr & CSR_READY;
242 static bool cse_check_hfs1_com(int mode)
244 union me_hfsts1 hfs1;
245 hfs1.data = me_read_config32(PCI_ME_HFSTS1);
246 return hfs1.fields.operation_mode == mode;
249 bool cse_is_hfs1_cws_normal(void)
251 union me_hfsts1 hfs1;
252 hfs1.data = me_read_config32(PCI_ME_HFSTS1);
253 if (hfs1.fields.working_state == ME_HFS1_CWS_NORMAL)
254 return true;
255 return false;
258 bool cse_is_hfs1_com_normal(void)
260 return cse_check_hfs1_com(ME_HFS1_COM_NORMAL);
263 bool cse_is_hfs1_com_secover_mei_msg(void)
265 return cse_check_hfs1_com(ME_HFS1_COM_SECOVER_MEI_MSG);
268 bool cse_is_hfs1_com_soft_temp_disable(void)
270 return cse_check_hfs1_com(ME_HFS1_COM_SOFT_TEMP_DISABLE);
273 /* Makes the host ready to communicate with CSE */
274 void cse_set_host_ready(void)
276 uint32_t csr;
277 csr = read_host_csr();
278 csr &= ~CSR_RESET;
279 csr |= (CSR_IG | CSR_READY);
280 write_host_csr(csr);
283 /* Polls for ME mode ME_HFS1_COM_SECOVER_MEI_MSG for 15 seconds */
284 uint8_t cse_wait_sec_override_mode(void)
286 struct stopwatch sw;
287 stopwatch_init_msecs_expire(&sw, HECI_DELAY_READY);
288 while (!cse_is_hfs1_com_secover_mei_msg()) {
289 udelay(HECI_DELAY);
290 if (stopwatch_expired(&sw)) {
291 printk(BIOS_ERR, "HECI: Timed out waiting for SEC_OVERRIDE mode!\n");
292 return 0;
295 printk(BIOS_DEBUG, "HECI: CSE took %lu ms to enter security override mode\n",
296 stopwatch_duration_msecs(&sw));
297 return 1;
300 static int wait_heci_ready(void)
302 struct stopwatch sw;
304 stopwatch_init_msecs_expire(&sw, HECI_DELAY_READY);
305 while (!cse_ready()) {
306 udelay(HECI_DELAY);
307 if (stopwatch_expired(&sw))
308 return 0;
311 return 1;
314 static void host_gen_interrupt(void)
316 uint32_t csr;
317 csr = read_host_csr();
318 csr |= CSR_IG;
319 write_host_csr(csr);
322 static size_t hdr_get_length(uint32_t hdr)
324 return (hdr & MEI_HDR_LENGTH) >> MEI_HDR_LENGTH_START;
327 static int
328 send_one_message(uint32_t hdr, const void *buff)
330 size_t pend_len, pend_slots, remainder, i;
331 uint32_t tmp;
332 const uint32_t *p = buff;
334 /* Get space for the header */
335 if (!wait_write_slots(1))
336 return 0;
338 /* First, write header */
339 write_slot(hdr);
341 pend_len = hdr_get_length(hdr);
342 pend_slots = bytes_to_slots(pend_len);
344 if (!wait_write_slots(pend_slots))
345 return 0;
347 /* Write the body in whole slots */
348 i = 0;
349 while (i < ALIGN_DOWN(pend_len, SLOT_SIZE)) {
350 write_slot(*p++);
351 i += SLOT_SIZE;
354 remainder = pend_len % SLOT_SIZE;
355 /* Pad to 4 bytes not touching caller's buffer */
356 if (remainder) {
357 memcpy(&tmp, p, remainder);
358 write_slot(tmp);
361 host_gen_interrupt();
363 /* Make sure nothing bad happened during transmission */
364 if (!cse_ready())
365 return 0;
367 return pend_len;
371 heci_send(const void *msg, size_t len, uint8_t host_addr, uint8_t client_addr)
373 uint8_t retry;
374 uint32_t csr, hdr;
375 size_t sent, remaining, cb_size, max_length;
376 const uint8_t *p;
378 if (!msg || !len)
379 return 0;
381 clear_int();
383 for (retry = 0; retry < MAX_HECI_MESSAGE_RETRY_COUNT; retry++) {
384 p = msg;
386 if (!wait_heci_ready()) {
387 printk(BIOS_ERR, "HECI: not ready\n");
388 continue;
391 csr = read_host_csr();
392 cb_size = ((csr & CSR_CBD) >> CSR_CBD_START) * SLOT_SIZE;
394 * Reserve one slot for the header. Limit max message
395 * length by 9 bits that are available in the header.
397 max_length = MIN(cb_size, (1 << MEI_HDR_LENGTH_SIZE) - 1)
398 - SLOT_SIZE;
399 remaining = len;
402 * Fragment the message into smaller messages not exceeding
403 * useful circular buffer length. Mark last message complete.
405 do {
406 hdr = MIN(max_length, remaining)
407 << MEI_HDR_LENGTH_START;
408 hdr |= client_addr << MEI_HDR_CSE_ADDR_START;
409 hdr |= host_addr << MEI_HDR_HOST_ADDR_START;
410 hdr |= (MIN(max_length, remaining) == remaining) ?
411 MEI_HDR_IS_COMPLETE : 0;
412 sent = send_one_message(hdr, p);
413 p += sent;
414 remaining -= sent;
415 } while (remaining > 0 && sent != 0);
417 if (!remaining)
418 return 1;
420 return 0;
423 static size_t
424 recv_one_message(uint32_t *hdr, void *buff, size_t maxlen)
426 uint32_t reg, *p = buff;
427 size_t recv_slots, recv_len, remainder, i;
429 /* first get the header */
430 if (!wait_read_slots(1))
431 return 0;
433 *hdr = read_slot();
434 recv_len = hdr_get_length(*hdr);
436 if (!recv_len)
437 printk(BIOS_WARNING, "HECI: message is zero-sized\n");
439 recv_slots = bytes_to_slots(recv_len);
441 i = 0;
442 if (recv_len > maxlen) {
443 printk(BIOS_ERR, "HECI: response is too big\n");
444 return 0;
447 /* wait for the rest of messages to arrive */
448 wait_read_slots(recv_slots);
450 /* fetch whole slots first */
451 while (i < ALIGN_DOWN(recv_len, SLOT_SIZE)) {
452 *p++ = read_slot();
453 i += SLOT_SIZE;
457 * If ME is not ready, something went wrong and
458 * we received junk
460 if (!cse_ready())
461 return 0;
463 remainder = recv_len % SLOT_SIZE;
465 if (remainder) {
466 reg = read_slot();
467 memcpy(p, &reg, remainder);
470 return recv_len;
473 int heci_receive(void *buff, size_t *maxlen)
475 uint8_t retry;
476 size_t left, received;
477 uint32_t hdr = 0;
478 uint8_t *p;
480 if (!buff || !maxlen || !*maxlen)
481 return 0;
483 clear_int();
485 for (retry = 0; retry < MAX_HECI_MESSAGE_RETRY_COUNT; retry++) {
486 p = buff;
487 left = *maxlen;
489 if (!wait_heci_ready()) {
490 printk(BIOS_ERR, "HECI: not ready\n");
491 continue;
495 * Receive multiple packets until we meet one marked
496 * complete or we run out of space in caller-provided buffer.
498 do {
499 received = recv_one_message(&hdr, p, left);
500 if (!received) {
501 printk(BIOS_ERR, "HECI: Failed to receive!\n");
502 return 0;
504 left -= received;
505 p += received;
506 /* If we read out everything ping to send more */
507 if (!(hdr & MEI_HDR_IS_COMPLETE) && !cse_filled_slots())
508 host_gen_interrupt();
509 } while (received && !(hdr & MEI_HDR_IS_COMPLETE) && left > 0);
511 if ((hdr & MEI_HDR_IS_COMPLETE) && received) {
512 *maxlen = p - (uint8_t *) buff;
513 return 1;
516 return 0;
519 int heci_send_receive(const void *snd_msg, size_t snd_sz, void *rcv_msg, size_t *rcv_sz)
521 if (!heci_send(snd_msg, snd_sz, BIOS_HOST_ADDR, HECI_MKHI_ADDR)) {
522 printk(BIOS_ERR, "HECI: send Failed\n");
523 return 0;
526 if (rcv_msg != NULL) {
527 if (!heci_receive(rcv_msg, rcv_sz)) {
528 printk(BIOS_ERR, "HECI: receive Failed\n");
529 return 0;
532 return 1;
536 * Attempt to reset the device. This is useful when host and ME are out
537 * of sync during transmission or ME didn't understand the message.
539 int heci_reset(void)
541 uint32_t csr;
543 /* Send reset request */
544 csr = read_host_csr();
545 csr |= (CSR_RESET | CSR_IG);
546 write_host_csr(csr);
548 if (wait_heci_ready()) {
549 /* Device is back on its imaginary feet, clear reset */
550 cse_set_host_ready();
551 return 1;
554 printk(BIOS_CRIT, "HECI: reset failed\n");
556 return 0;
559 bool is_cse_enabled(void)
561 const struct device *cse_dev = pcidev_path_on_root(PCH_DEVFN_CSE);
563 if (!cse_dev || !cse_dev->enabled) {
564 printk(BIOS_WARNING, "HECI: No CSE device\n");
565 return false;
568 if (pci_read_config16(PCH_DEV_CSE, PCI_VENDOR_ID) == 0xFFFF) {
569 printk(BIOS_WARNING, "HECI: CSE device is hidden\n");
570 return false;
573 return true;
576 uint32_t me_read_config32(int offset)
578 return pci_read_config32(PCH_DEV_CSE, offset);
582 * Sends GLOBAL_RESET_REQ cmd to CSE.The reset type can be GLOBAL_RESET/
583 * HOST_RESET_ONLY/CSE_RESET_ONLY.
585 int cse_request_global_reset(enum rst_req_type rst_type)
587 int status;
588 struct mkhi_hdr reply;
589 struct reset_message {
590 struct mkhi_hdr hdr;
591 uint8_t req_origin;
592 uint8_t reset_type;
593 } __packed;
594 struct reset_message msg = {
595 .hdr = {
596 .group_id = MKHI_GROUP_ID_CBM,
597 .command = MKHI_CBM_GLOBAL_RESET_REQ,
599 .req_origin = GR_ORIGIN_BIOS_POST,
600 .reset_type = rst_type
602 size_t reply_size;
604 printk(BIOS_DEBUG, "HECI: Global Reset(Type:%d) Command\n", rst_type);
605 if (!((rst_type == GLOBAL_RESET) ||
606 (rst_type == HOST_RESET_ONLY) || (rst_type == CSE_RESET_ONLY))) {
607 printk(BIOS_ERR, "HECI: Unsupported reset type is requested\n");
608 return 0;
611 heci_reset();
613 reply_size = sizeof(reply);
614 memset(&reply, 0, reply_size);
616 if (rst_type == CSE_RESET_ONLY)
617 status = heci_send(&msg, sizeof(msg), BIOS_HOST_ADDR, HECI_MKHI_ADDR);
618 else
619 status = heci_send_receive(&msg, sizeof(msg), &reply, &reply_size);
621 printk(BIOS_DEBUG, "HECI: Global Reset %s!\n", status ? "success" : "failure");
622 return status;
625 /* Sends HMRFPO Enable command to CSE */
626 int cse_hmrfpo_enable(void)
628 struct hmrfpo_enable_msg {
629 struct mkhi_hdr hdr;
630 uint32_t nonce[2];
631 } __packed;
633 /* HMRFPO Enable message */
634 struct hmrfpo_enable_msg msg = {
635 .hdr = {
636 .group_id = MKHI_GROUP_ID_HMRFPO,
637 .command = MKHI_HMRFPO_ENABLE,
639 .nonce = {0},
642 /* HMRFPO Enable response */
643 struct hmrfpo_enable_resp {
644 struct mkhi_hdr hdr;
645 /* Base addr for factory data area, not relevant for client SKUs */
646 uint32_t fct_base;
647 /* Length of factory data area, not relevant for client SKUs */
648 uint32_t fct_limit;
649 uint8_t status;
650 uint8_t padding[3];
651 } __packed;
653 struct hmrfpo_enable_resp resp;
654 size_t resp_size = sizeof(struct hmrfpo_enable_resp);
656 printk(BIOS_DEBUG, "HECI: Send HMRFPO Enable Command\n");
658 * This command can be run only if:
659 * - Working state is normal and
660 * - Operation mode is normal or temporary disable mode.
662 if (!cse_is_hfs1_cws_normal() ||
663 (!cse_is_hfs1_com_normal() && !cse_is_hfs1_com_soft_temp_disable())) {
664 printk(BIOS_ERR, "HECI: ME not in required Mode\n");
665 goto failed;
668 if (!heci_send_receive(&msg, sizeof(struct hmrfpo_enable_msg),
669 &resp, &resp_size))
670 goto failed;
672 if (resp.hdr.result) {
673 printk(BIOS_ERR, "HECI: Resp Failed:%d\n", resp.hdr.result);
674 goto failed;
676 return 1;
678 failed:
679 return 0;
683 * Sends HMRFPO Get Status command to CSE to get the HMRFPO status.
684 * The status can be DISABLED/LOCKED/ENABLED
686 int cse_hmrfpo_get_status(void)
688 struct hmrfpo_get_status_msg {
689 struct mkhi_hdr hdr;
690 } __packed;
692 struct hmrfpo_get_status_resp {
693 struct mkhi_hdr hdr;
694 uint8_t status;
695 uint8_t reserved[3];
696 } __packed;
698 struct hmrfpo_get_status_msg msg = {
699 .hdr = {
700 .group_id = MKHI_GROUP_ID_HMRFPO,
701 .command = MKHI_HMRFPO_GET_STATUS,
704 struct hmrfpo_get_status_resp resp;
705 size_t resp_size = sizeof(struct hmrfpo_get_status_resp);
707 printk(BIOS_INFO, "HECI: Sending Get HMRFPO Status Command\n");
709 if (!heci_send_receive(&msg, sizeof(struct hmrfpo_get_status_msg),
710 &resp, &resp_size)) {
711 printk(BIOS_ERR, "HECI: HMRFPO send/receive fail\n");
712 return -1;
715 if (resp.hdr.result) {
716 printk(BIOS_ERR, "HECI: HMRFPO Resp Failed:%d\n",
717 resp.hdr.result);
718 return -1;
721 return resp.status;
724 #if ENV_RAMSTAGE
726 static void update_sec_bar(struct device *dev)
728 cse.sec_bar = find_resource(dev, PCI_BASE_ADDRESS_0)->base;
731 static void cse_set_resources(struct device *dev)
733 if (dev->path.pci.devfn == PCH_DEVFN_CSE)
734 update_sec_bar(dev);
736 pci_dev_set_resources(dev);
739 static struct device_operations cse_ops = {
740 .set_resources = cse_set_resources,
741 .read_resources = pci_dev_read_resources,
742 .enable_resources = pci_dev_enable_resources,
743 .init = pci_dev_init,
744 .ops_pci = &pci_dev_ops_pci,
747 static const unsigned short pci_device_ids[] = {
748 PCI_DEVICE_ID_INTEL_APL_CSE0,
749 PCI_DEVICE_ID_INTEL_GLK_CSE0,
750 PCI_DEVICE_ID_INTEL_CNL_CSE0,
751 PCI_DEVICE_ID_INTEL_SKL_CSE0,
752 PCI_DEVICE_ID_INTEL_LWB_CSE0,
753 PCI_DEVICE_ID_INTEL_LWB_CSE0_SUPER,
754 PCI_DEVICE_ID_INTEL_CNP_H_CSE0,
755 PCI_DEVICE_ID_INTEL_ICL_CSE0,
756 PCI_DEVICE_ID_INTEL_CMP_CSE0,
757 PCI_DEVICE_ID_INTEL_CMP_H_CSE0,
758 PCI_DEVICE_ID_INTEL_TGL_CSE0,
759 PCI_DEVICE_ID_INTEL_JSP_PRE_PROD_CSE0,
760 PCI_DEVICE_ID_INTEL_MCC_CSE0,
761 PCI_DEVICE_ID_INTEL_MCC_CSE1,
762 PCI_DEVICE_ID_INTEL_MCC_CSE2,
763 PCI_DEVICE_ID_INTEL_MCC_CSE3,
767 static const struct pci_driver cse_driver __pci_driver = {
768 .ops = &cse_ops,
769 .vendor = PCI_VENDOR_ID_INTEL,
770 /* SoC/chipset needs to provide PCI device ID */
771 .devices = pci_device_ids
774 #endif