blob: 0f50cc19b0f0eca16e5e96a90a3fad127b17a446 [file] [log] [blame]
Andrey Petrov04a72c42017-03-01 15:51:57 -08001/*
2 * This file is part of the coreboot project.
3 *
praveen hodagatta praneshe26c4a42018-09-20 03:49:45 +08004 * Copyright 2017-2018 Intel Inc.
Andrey Petrov04a72c42017-03-01 15:51:57 -08005 *
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.
9 *
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.
14 */
15
Subrata Banik05e06cd2017-11-09 15:04:09 +053016#include <assert.h>
Andrey Petrov04a72c42017-03-01 15:51:57 -080017#include <commonlib/helpers.h>
18#include <console/console.h>
Kyösti Mälkki13f66502019-03-03 08:01:05 +020019#include <device/mmio.h>
Andrey Petrov04a72c42017-03-01 15:51:57 -080020#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>
Subrata Banik05e06cd2017-11-09 15:04:09 +053025#include <soc/iomap.h>
Andrey Petrov04a72c42017-03-01 15:51:57 -080026#include <soc/pci_devs.h>
Andrey Petrov04a72c42017-03-01 15:51:57 -080027#include <string.h>
28#include <timer.h>
29
Subrata Banik5c08c732017-11-13 14:54:37 +053030#define MAX_HECI_MESSAGE_RETRY_COUNT 5
31
Andrey Petrov04a72c42017-03-01 15:51:57 -080032/* Wait up to 15 sec for HECI to get ready */
33#define HECI_DELAY_READY (15 * 1000)
Jonathan Neuschäfer5268b762018-02-12 12:24:25 +010034/* Wait up to 100 usec between circular buffer polls */
Andrey Petrov04a72c42017-03-01 15:51:57 -080035#define HECI_DELAY 100
36/* Wait up to 5 sec for CSE to chew something we sent */
37#define HECI_SEND_TIMEOUT (5 * 1000)
38/* Wait up to 5 sec for CSE to blurp a reply */
39#define HECI_READ_TIMEOUT (5 * 1000)
40
41#define SLOT_SIZE sizeof(uint32_t)
42
43#define MMIO_CSE_CB_WW 0x00
44#define MMIO_HOST_CSR 0x04
45#define MMIO_CSE_CB_RW 0x08
46#define MMIO_CSE_CSR 0x0c
47
48#define CSR_IE (1 << 0)
49#define CSR_IS (1 << 1)
50#define CSR_IG (1 << 2)
51#define CSR_READY (1 << 3)
52#define CSR_RESET (1 << 4)
53#define CSR_RP_START 8
54#define CSR_RP (((1 << 8) - 1) << CSR_RP_START)
55#define CSR_WP_START 16
56#define CSR_WP (((1 << 8) - 1) << CSR_WP_START)
57#define CSR_CBD_START 24
58#define CSR_CBD (((1 << 8) - 1) << CSR_CBD_START)
59
60#define MEI_HDR_IS_COMPLETE (1 << 31)
61#define MEI_HDR_LENGTH_START 16
62#define MEI_HDR_LENGTH_SIZE 9
63#define MEI_HDR_LENGTH (((1 << MEI_HDR_LENGTH_SIZE) - 1) \
64 << MEI_HDR_LENGTH_START)
65#define MEI_HDR_HOST_ADDR_START 8
66#define MEI_HDR_HOST_ADDR (((1 << 8) - 1) << MEI_HDR_HOST_ADDR_START)
67#define MEI_HDR_CSE_ADDR_START 0
68#define MEI_HDR_CSE_ADDR (((1 << 8) - 1) << MEI_HDR_CSE_ADDR_START)
69
Arthur Heymans3d6ccd02019-05-27 17:25:23 +020070static struct cse_device {
Andrey Petrov04a72c42017-03-01 15:51:57 -080071 uintptr_t sec_bar;
Patrick Georgic9b13592019-11-29 11:47:47 +010072} cse;
Andrey Petrov04a72c42017-03-01 15:51:57 -080073
74/*
75 * Initialize the device with provided temporary BAR. If BAR is 0 use a
76 * default. This is intended for pre-mem usage only where BARs haven't been
77 * assigned yet and devices are not enabled.
78 */
79void heci_init(uintptr_t tempbar)
80{
Elyes HAOUAS68c851b2018-06-12 22:06:09 +020081#if defined(__SIMPLE_DEVICE__)
82 pci_devfn_t dev = PCH_DEV_CSE;
83#else
84 struct device *dev = PCH_DEV_CSE;
85#endif
Andrey Petrov04a72c42017-03-01 15:51:57 -080086 u8 pcireg;
87
88 /* Assume it is already initialized, nothing else to do */
Patrick Georgic9b13592019-11-29 11:47:47 +010089 if (cse.sec_bar)
Andrey Petrov04a72c42017-03-01 15:51:57 -080090 return;
91
92 /* Use default pre-ram bar */
93 if (!tempbar)
94 tempbar = HECI1_BASE_ADDRESS;
95
96 /* Assign Resources to HECI1 */
97 /* Clear BIT 1-2 of Command Register */
98 pcireg = pci_read_config8(dev, PCI_COMMAND);
99 pcireg &= ~(PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY);
100 pci_write_config8(dev, PCI_COMMAND, pcireg);
101
102 /* Program Temporary BAR for HECI1 */
103 pci_write_config32(dev, PCI_BASE_ADDRESS_0, tempbar);
104 pci_write_config32(dev, PCI_BASE_ADDRESS_1, 0x0);
105
106 /* Enable Bus Master and MMIO Space */
107 pcireg = pci_read_config8(dev, PCI_COMMAND);
108 pcireg |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
109 pci_write_config8(dev, PCI_COMMAND, pcireg);
110
Patrick Georgic9b13592019-11-29 11:47:47 +0100111 cse.sec_bar = tempbar;
Andrey Petrov04a72c42017-03-01 15:51:57 -0800112}
113
Subrata Banik05e06cd2017-11-09 15:04:09 +0530114/* Get HECI BAR 0 from PCI configuration space */
115static uint32_t get_cse_bar(void)
116{
117 uintptr_t bar;
118
119 bar = pci_read_config32(PCH_DEV_CSE, PCI_BASE_ADDRESS_0);
120 assert(bar != 0);
121 /*
122 * Bits 31-12 are the base address as per EDS for SPI,
123 * Don't care about 0-11 bit
124 */
125 return bar & ~PCI_BASE_ADDRESS_MEM_ATTR_MASK;
126}
127
Andrey Petrov04a72c42017-03-01 15:51:57 -0800128static uint32_t read_bar(uint32_t offset)
129{
Patrick Georgi08c8cf92019-12-02 11:43:20 +0100130 /* Load and cache BAR */
Patrick Georgic9b13592019-11-29 11:47:47 +0100131 if (!cse.sec_bar)
132 cse.sec_bar = get_cse_bar();
133 return read32((void *)(cse.sec_bar + offset));
Andrey Petrov04a72c42017-03-01 15:51:57 -0800134}
135
136static void write_bar(uint32_t offset, uint32_t val)
137{
Patrick Georgi08c8cf92019-12-02 11:43:20 +0100138 /* Load and cache BAR */
Patrick Georgic9b13592019-11-29 11:47:47 +0100139 if (!cse.sec_bar)
140 cse.sec_bar = get_cse_bar();
141 return write32((void *)(cse.sec_bar + offset), val);
Andrey Petrov04a72c42017-03-01 15:51:57 -0800142}
143
144static uint32_t read_cse_csr(void)
145{
146 return read_bar(MMIO_CSE_CSR);
147}
148
149static uint32_t read_host_csr(void)
150{
151 return read_bar(MMIO_HOST_CSR);
152}
153
154static void write_host_csr(uint32_t data)
155{
156 write_bar(MMIO_HOST_CSR, data);
157}
158
159static size_t filled_slots(uint32_t data)
160{
161 uint8_t wp, rp;
162 rp = data >> CSR_RP_START;
163 wp = data >> CSR_WP_START;
164 return (uint8_t) (wp - rp);
165}
166
167static size_t cse_filled_slots(void)
168{
169 return filled_slots(read_cse_csr());
170}
171
172static size_t host_empty_slots(void)
173{
174 uint32_t csr;
175 csr = read_host_csr();
176
177 return ((csr & CSR_CBD) >> CSR_CBD_START) - filled_slots(csr);
178}
179
180static void clear_int(void)
181{
182 uint32_t csr;
183 csr = read_host_csr();
184 csr |= CSR_IS;
185 write_host_csr(csr);
186}
187
188static uint32_t read_slot(void)
189{
190 return read_bar(MMIO_CSE_CB_RW);
191}
192
193static void write_slot(uint32_t val)
194{
195 write_bar(MMIO_CSE_CB_WW, val);
196}
197
198static int wait_write_slots(size_t cnt)
199{
200 struct stopwatch sw;
201
202 stopwatch_init_msecs_expire(&sw, HECI_SEND_TIMEOUT);
203 while (host_empty_slots() < cnt) {
204 udelay(HECI_DELAY);
205 if (stopwatch_expired(&sw)) {
206 printk(BIOS_ERR, "HECI: timeout, buffer not drained\n");
207 return 0;
208 }
209 }
210 return 1;
211}
212
213static int wait_read_slots(size_t cnt)
214{
215 struct stopwatch sw;
216
217 stopwatch_init_msecs_expire(&sw, HECI_READ_TIMEOUT);
218 while (cse_filled_slots() < cnt) {
219 udelay(HECI_DELAY);
220 if (stopwatch_expired(&sw)) {
221 printk(BIOS_ERR, "HECI: timed out reading answer!\n");
222 return 0;
223 }
224 }
225 return 1;
226}
227
228/* get number of full 4-byte slots */
229static size_t bytes_to_slots(size_t bytes)
230{
231 return ALIGN_UP(bytes, SLOT_SIZE) / SLOT_SIZE;
232}
233
234static int cse_ready(void)
235{
236 uint32_t csr;
237 csr = read_cse_csr();
238 return csr & CSR_READY;
239}
240
Sridhar Siricillab9d075b2019-08-31 11:38:33 +0530241/*
Sridhar Siricillae202e672020-01-07 23:36:40 +0530242 * Checks if CSE is in ME_HFS1_COM_SECOVER_MEI_MSG operation mode. This is the mode where
Sridhar Siricillab9d075b2019-08-31 11:38:33 +0530243 * CSE will allow reflashing of CSE region.
244 */
245static uint8_t check_cse_sec_override_mode(void)
246{
247 union me_hfsts1 hfs1;
248 hfs1.data = me_read_config32(PCI_ME_HFSTS1);
Sridhar Siricillae202e672020-01-07 23:36:40 +0530249 if (hfs1.fields.operation_mode == ME_HFS1_COM_SECOVER_MEI_MSG)
Sridhar Siricillab9d075b2019-08-31 11:38:33 +0530250 return 1;
251 return 0;
252}
253
254/* Makes the host ready to communicate with CSE */
255void set_host_ready(void)
256{
257 uint32_t csr;
258 csr = read_host_csr();
259 csr &= ~CSR_RESET;
260 csr |= (CSR_IG | CSR_READY);
261 write_host_csr(csr);
262}
263
264/* Polls for ME state 'HECI_OP_MODE_SEC_OVERRIDE' for 15 seconds */
265uint8_t wait_cse_sec_override_mode(void)
266{
267 struct stopwatch sw;
268 stopwatch_init_msecs_expire(&sw, HECI_DELAY_READY);
269 while (!check_cse_sec_override_mode()) {
270 udelay(HECI_DELAY);
271 if (stopwatch_expired(&sw))
272 return 0;
273 }
274
275 return 1;
276}
277
Andrey Petrov04a72c42017-03-01 15:51:57 -0800278static int wait_heci_ready(void)
279{
280 struct stopwatch sw;
281
282 stopwatch_init_msecs_expire(&sw, HECI_DELAY_READY);
283 while (!cse_ready()) {
284 udelay(HECI_DELAY);
285 if (stopwatch_expired(&sw))
286 return 0;
287 }
288
289 return 1;
290}
291
292static void host_gen_interrupt(void)
293{
294 uint32_t csr;
295 csr = read_host_csr();
296 csr |= CSR_IG;
297 write_host_csr(csr);
298}
299
300static size_t hdr_get_length(uint32_t hdr)
301{
302 return (hdr & MEI_HDR_LENGTH) >> MEI_HDR_LENGTH_START;
303}
304
305static int
306send_one_message(uint32_t hdr, const void *buff)
307{
308 size_t pend_len, pend_slots, remainder, i;
309 uint32_t tmp;
310 const uint32_t *p = buff;
311
312 /* Get space for the header */
313 if (!wait_write_slots(1))
314 return 0;
315
316 /* First, write header */
317 write_slot(hdr);
318
319 pend_len = hdr_get_length(hdr);
320 pend_slots = bytes_to_slots(pend_len);
321
322 if (!wait_write_slots(pend_slots))
323 return 0;
324
325 /* Write the body in whole slots */
326 i = 0;
327 while (i < ALIGN_DOWN(pend_len, SLOT_SIZE)) {
328 write_slot(*p++);
329 i += SLOT_SIZE;
330 }
331
332 remainder = pend_len % SLOT_SIZE;
333 /* Pad to 4 bytes not touching caller's buffer */
334 if (remainder) {
335 memcpy(&tmp, p, remainder);
336 write_slot(tmp);
337 }
338
339 host_gen_interrupt();
340
341 /* Make sure nothing bad happened during transmission */
342 if (!cse_ready())
343 return 0;
344
345 return pend_len;
346}
347
348int
349heci_send(const void *msg, size_t len, uint8_t host_addr, uint8_t client_addr)
350{
Subrata Banik5c08c732017-11-13 14:54:37 +0530351 uint8_t retry;
Andrey Petrov04a72c42017-03-01 15:51:57 -0800352 uint32_t csr, hdr;
Subrata Banik5c08c732017-11-13 14:54:37 +0530353 size_t sent, remaining, cb_size, max_length;
354 const uint8_t *p;
Andrey Petrov04a72c42017-03-01 15:51:57 -0800355
356 if (!msg || !len)
357 return 0;
358
359 clear_int();
360
Subrata Banik5c08c732017-11-13 14:54:37 +0530361 for (retry = 0; retry < MAX_HECI_MESSAGE_RETRY_COUNT; retry++) {
362 p = msg;
Andrey Petrov04a72c42017-03-01 15:51:57 -0800363
Subrata Banik5c08c732017-11-13 14:54:37 +0530364 if (!wait_heci_ready()) {
365 printk(BIOS_ERR, "HECI: not ready\n");
366 continue;
367 }
Andrey Petrov04a72c42017-03-01 15:51:57 -0800368
Subrata Banik4a722f52017-11-13 14:56:42 +0530369 csr = read_host_csr();
Subrata Banik5c08c732017-11-13 14:54:37 +0530370 cb_size = ((csr & CSR_CBD) >> CSR_CBD_START) * SLOT_SIZE;
371 /*
372 * Reserve one slot for the header. Limit max message
373 * length by 9 bits that are available in the header.
374 */
375 max_length = MIN(cb_size, (1 << MEI_HDR_LENGTH_SIZE) - 1)
376 - SLOT_SIZE;
377 remaining = len;
378
379 /*
380 * Fragment the message into smaller messages not exceeding
Jonathan Neuschäfer5268b762018-02-12 12:24:25 +0100381 * useful circular buffer length. Mark last message complete.
Subrata Banik5c08c732017-11-13 14:54:37 +0530382 */
383 do {
384 hdr = MIN(max_length, remaining)
385 << MEI_HDR_LENGTH_START;
386 hdr |= client_addr << MEI_HDR_CSE_ADDR_START;
387 hdr |= host_addr << MEI_HDR_HOST_ADDR_START;
388 hdr |= (MIN(max_length, remaining) == remaining) ?
Lee Leahy68ab0b52017-03-10 13:42:34 -0800389 MEI_HDR_IS_COMPLETE : 0;
Subrata Banik5c08c732017-11-13 14:54:37 +0530390 sent = send_one_message(hdr, p);
391 p += sent;
392 remaining -= sent;
393 } while (remaining > 0 && sent != 0);
Andrey Petrov04a72c42017-03-01 15:51:57 -0800394
Subrata Banik5c08c732017-11-13 14:54:37 +0530395 if (!remaining)
396 return 1;
397 }
398 return 0;
Andrey Petrov04a72c42017-03-01 15:51:57 -0800399}
400
401static size_t
402recv_one_message(uint32_t *hdr, void *buff, size_t maxlen)
403{
404 uint32_t reg, *p = buff;
405 size_t recv_slots, recv_len, remainder, i;
406
407 /* first get the header */
408 if (!wait_read_slots(1))
409 return 0;
410
411 *hdr = read_slot();
412 recv_len = hdr_get_length(*hdr);
413
414 if (!recv_len)
415 printk(BIOS_WARNING, "HECI: message is zero-sized\n");
416
417 recv_slots = bytes_to_slots(recv_len);
418
419 i = 0;
420 if (recv_len > maxlen) {
421 printk(BIOS_ERR, "HECI: response is too big\n");
422 return 0;
423 }
424
425 /* wait for the rest of messages to arrive */
426 wait_read_slots(recv_slots);
427
428 /* fetch whole slots first */
429 while (i < ALIGN_DOWN(recv_len, SLOT_SIZE)) {
430 *p++ = read_slot();
431 i += SLOT_SIZE;
432 }
433
Subrata Banik5c08c732017-11-13 14:54:37 +0530434 /*
435 * If ME is not ready, something went wrong and
436 * we received junk
437 */
438 if (!cse_ready())
439 return 0;
440
Andrey Petrov04a72c42017-03-01 15:51:57 -0800441 remainder = recv_len % SLOT_SIZE;
442
443 if (remainder) {
444 reg = read_slot();
445 memcpy(p, &reg, remainder);
446 }
447
448 return recv_len;
449}
450
451int heci_receive(void *buff, size_t *maxlen)
452{
Subrata Banik5c08c732017-11-13 14:54:37 +0530453 uint8_t retry;
Andrey Petrov04a72c42017-03-01 15:51:57 -0800454 size_t left, received;
455 uint32_t hdr = 0;
Subrata Banik5c08c732017-11-13 14:54:37 +0530456 uint8_t *p;
Andrey Petrov04a72c42017-03-01 15:51:57 -0800457
458 if (!buff || !maxlen || !*maxlen)
459 return 0;
460
Andrey Petrov04a72c42017-03-01 15:51:57 -0800461 clear_int();
462
Subrata Banik5c08c732017-11-13 14:54:37 +0530463 for (retry = 0; retry < MAX_HECI_MESSAGE_RETRY_COUNT; retry++) {
464 p = buff;
465 left = *maxlen;
466
467 if (!wait_heci_ready()) {
468 printk(BIOS_ERR, "HECI: not ready\n");
469 continue;
470 }
471
472 /*
473 * Receive multiple packets until we meet one marked
474 * complete or we run out of space in caller-provided buffer.
475 */
476 do {
477 received = recv_one_message(&hdr, p, left);
Lijian Zhaoc50296d2017-12-15 19:10:18 -0800478 if (!received) {
Elyes HAOUAS3d450002018-08-09 18:55:58 +0200479 printk(BIOS_ERR, "HECI: Failed to receive!\n");
Lijian Zhaoc50296d2017-12-15 19:10:18 -0800480 return 0;
481 }
Subrata Banik5c08c732017-11-13 14:54:37 +0530482 left -= received;
483 p += received;
484 /* If we read out everything ping to send more */
485 if (!(hdr & MEI_HDR_IS_COMPLETE) && !cse_filled_slots())
486 host_gen_interrupt();
487 } while (received && !(hdr & MEI_HDR_IS_COMPLETE) && left > 0);
488
489 if ((hdr & MEI_HDR_IS_COMPLETE) && received) {
490 *maxlen = p - (uint8_t *) buff;
491 return 1;
492 }
Andrey Petrov04a72c42017-03-01 15:51:57 -0800493 }
Subrata Banik5c08c732017-11-13 14:54:37 +0530494 return 0;
Andrey Petrov04a72c42017-03-01 15:51:57 -0800495}
496
Sridhar Siricillaa5208f52019-08-30 17:10:24 +0530497int heci_send_receive(const void *snd_msg, size_t snd_sz, void *rcv_msg, size_t *rcv_sz)
498{
499 if (!heci_send(snd_msg, snd_sz, BIOS_HOST_ADDR, HECI_MKHI_ADDR)) {
500 printk(BIOS_ERR, "HECI: send Failed\n");
501 return 0;
502 }
503
504 if (rcv_msg != NULL) {
505 if (!heci_receive(rcv_msg, rcv_sz)) {
506 printk(BIOS_ERR, "HECI: receive Failed\n");
507 return 0;
508 }
509 }
510 return 1;
511}
512
Andrey Petrov04a72c42017-03-01 15:51:57 -0800513/*
514 * Attempt to reset the device. This is useful when host and ME are out
515 * of sync during transmission or ME didn't understand the message.
516 */
517int heci_reset(void)
518{
519 uint32_t csr;
520
521 /* Send reset request */
522 csr = read_host_csr();
Sridhar Siricillab9d075b2019-08-31 11:38:33 +0530523 csr |= (CSR_RESET | CSR_IG);
Andrey Petrov04a72c42017-03-01 15:51:57 -0800524 write_host_csr(csr);
525
526 if (wait_heci_ready()) {
527 /* Device is back on its imaginary feet, clear reset */
Sridhar Siricillab9d075b2019-08-31 11:38:33 +0530528 set_host_ready();
Andrey Petrov04a72c42017-03-01 15:51:57 -0800529 return 1;
530 }
531
532 printk(BIOS_CRIT, "HECI: reset failed\n");
533
534 return 0;
535}
536
Sridhar Siricilla2cc66912019-08-31 11:20:34 +0530537bool is_cse_enabled(void)
538{
539 const struct device *cse_dev = pcidev_path_on_root(PCH_DEVFN_CSE);
540
541 if (!cse_dev || !cse_dev->enabled) {
542 printk(BIOS_WARNING, "HECI: No CSE device\n");
543 return false;
544 }
545
546 if (pci_read_config16(PCH_DEV_CSE, PCI_VENDOR_ID) == 0xFFFF) {
547 printk(BIOS_WARNING, "HECI: CSE device is hidden\n");
548 return false;
549 }
550
551 return true;
552}
553
554uint32_t me_read_config32(int offset)
555{
556 return pci_read_config32(PCH_DEV_CSE, offset);
557}
558
Sridhar Siricillad415c202019-08-31 14:54:57 +0530559/*
560 * Sends GLOBAL_RESET_REQ cmd to CSE.The reset type can be GLOBAL_RESET/
561 * HOST_RESET_ONLY/CSE_RESET_ONLY.
562 */
563int send_heci_reset_req_message(uint8_t rst_type)
564{
565 int status;
566 struct mkhi_hdr reply;
567 struct reset_message {
568 struct mkhi_hdr hdr;
569 uint8_t req_origin;
570 uint8_t reset_type;
571 } __packed;
572 struct reset_message msg = {
573 .hdr = {
574 .group_id = MKHI_GROUP_ID_CBM,
Sridhar Siricillae202e672020-01-07 23:36:40 +0530575 .command = MKHI_CBM_GLOBAL_RESET_REQ,
Sridhar Siricillad415c202019-08-31 14:54:57 +0530576 },
577 .req_origin = GR_ORIGIN_BIOS_POST,
578 .reset_type = rst_type
579 };
580 size_t reply_size;
581
582 if (!((rst_type == GLOBAL_RESET) ||
583 (rst_type == HOST_RESET_ONLY) || (rst_type == CSE_RESET_ONLY)))
584 return -1;
585
586 heci_reset();
587
588 reply_size = sizeof(reply);
589 memset(&reply, 0, reply_size);
590
591 printk(BIOS_DEBUG, "HECI: Global Reset(Type:%d) Command\n", rst_type);
592 if (rst_type == CSE_RESET_ONLY)
593 status = heci_send_receive(&msg, sizeof(msg), NULL, 0);
594 else
595 status = heci_send_receive(&msg, sizeof(msg), &reply,
596 &reply_size);
597
598 if (status != 1)
599 return -1;
600
601 printk(BIOS_DEBUG, "HECI: Global Reset success!\n");
602 return 0;
603}
604
Sridhar Siricillae30a0e62019-08-31 16:12:21 +0530605/* Sends HMRFPO Enable command to CSE */
606int send_hmrfpo_enable_msg(void)
607{
608 struct hmrfpo_enable_msg {
609 struct mkhi_hdr hdr;
610 uint32_t nonce[2];
611 } __packed;
612
613 /* HMRFPO Enable message */
614 struct hmrfpo_enable_msg msg = {
615 .hdr = {
Sridhar Siricillae202e672020-01-07 23:36:40 +0530616 .group_id = MKHI_GROUP_ID_HMRFPO,
Sridhar Siricillae30a0e62019-08-31 16:12:21 +0530617 .command = MKHI_HMRFPO_ENABLE,
618 },
619 .nonce = {0},
620 };
621
622 /* HMRFPO Enable response */
623 struct hmrfpo_enable_resp {
624 struct mkhi_hdr hdr;
Sridhar Siricillae202e672020-01-07 23:36:40 +0530625 /* Base addr for factory data area, not relevant for client SKUs */
Sridhar Siricillae30a0e62019-08-31 16:12:21 +0530626 uint32_t fct_base;
Sridhar Siricillae202e672020-01-07 23:36:40 +0530627 /* Length of factory data area, not relevant for client SKUs */
Sridhar Siricillae30a0e62019-08-31 16:12:21 +0530628 uint32_t fct_limit;
629 uint8_t status;
630 uint8_t padding[3];
631 } __packed;
632
633 struct hmrfpo_enable_resp resp;
634 size_t resp_size = sizeof(struct hmrfpo_enable_resp);
635 union me_hfsts1 hfs1;
636
637 printk(BIOS_DEBUG, "HECI: Send HMRFPO Enable Command\n");
638 hfs1.data = me_read_config32(PCI_ME_HFSTS1);
639 /*
640 * This command can be run only if:
641 * - Working state is normal and
642 * - Operation mode is normal or temporary disable mode.
643 */
Sridhar Siricillae202e672020-01-07 23:36:40 +0530644 if (hfs1.fields.working_state != ME_HFS1_CWS_NORMAL ||
645 (hfs1.fields.operation_mode != ME_HFS1_COM_NORMAL &&
646 hfs1.fields.operation_mode != ME_HFS1_COM_SOFT_TEMP_DISABLE)) {
Sridhar Siricillae30a0e62019-08-31 16:12:21 +0530647 printk(BIOS_ERR, "HECI: ME not in required Mode\n");
648 goto failed;
649 }
650
651 if (!heci_send_receive(&msg, sizeof(struct hmrfpo_enable_msg),
652 &resp, &resp_size))
653 goto failed;
654
655 if (resp.hdr.result) {
656 printk(BIOS_ERR, "HECI: Resp Failed:%d\n", resp.hdr.result);
657 goto failed;
658 }
659 return 1;
660
661failed:
662 return 0;
663}
664
665/*
666 * Sends HMRFPO Get Status command to CSE to get the HMRFPO status.
667 * The status can be DISABLES/LOCKED/ENABLED
668 */
669int send_hmrfpo_get_status_msg(void)
670{
671 struct hmrfpo_get_status_msg {
672 struct mkhi_hdr hdr;
673 } __packed;
674
675 struct hmrfpo_get_status_resp {
676 struct mkhi_hdr hdr;
677 uint8_t status;
678 uint8_t padding[3];
679 } __packed;
680
681 struct hmrfpo_get_status_msg msg = {
682 .hdr = {
Sridhar Siricillae202e672020-01-07 23:36:40 +0530683 .group_id = MKHI_GROUP_ID_HMRFPO,
Sridhar Siricillae30a0e62019-08-31 16:12:21 +0530684 .command = MKHI_HMRFPO_GET_STATUS,
685 },
686 };
687 struct hmrfpo_get_status_resp resp;
688 size_t resp_size = sizeof(struct hmrfpo_get_status_resp);
689
690 printk(BIOS_INFO, "HECI: Sending Get HMRFPO Status Command\n");
691
692 if (!heci_send_receive(&msg, sizeof(struct hmrfpo_get_status_msg),
693 &resp, &resp_size)) {
694 printk(BIOS_ERR, "HECI: HMRFPO send/receive fail\n");
695 return -1;
696 }
697
698 if (resp.hdr.result) {
699 printk(BIOS_ERR, "HECI: HMRFPO Resp Failed:%d\n",
700 resp.hdr.result);
701 return -1;
702 }
703
704 return resp.status;
705}
706
Andrey Petrov04a72c42017-03-01 15:51:57 -0800707#if ENV_RAMSTAGE
708
709static void update_sec_bar(struct device *dev)
710{
Patrick Georgic9b13592019-11-29 11:47:47 +0100711 cse.sec_bar = find_resource(dev, PCI_BASE_ADDRESS_0)->base;
Andrey Petrov04a72c42017-03-01 15:51:57 -0800712}
713
714static void cse_set_resources(struct device *dev)
715{
Subrata Banik2ee54db2017-03-05 12:37:00 +0530716 if (dev->path.pci.devfn == PCH_DEVFN_CSE)
Andrey Petrov04a72c42017-03-01 15:51:57 -0800717 update_sec_bar(dev);
718
719 pci_dev_set_resources(dev);
720}
721
722static struct device_operations cse_ops = {
723 .set_resources = cse_set_resources,
724 .read_resources = pci_dev_read_resources,
725 .enable_resources = pci_dev_enable_resources,
726 .init = pci_dev_init,
Subrata Banik6bbc91a2017-12-07 14:55:51 +0530727 .ops_pci = &pci_dev_ops_pci,
Andrey Petrov04a72c42017-03-01 15:51:57 -0800728};
729
Hannah Williams63142152017-06-12 14:03:18 -0700730static const unsigned short pci_device_ids[] = {
731 PCI_DEVICE_ID_INTEL_APL_CSE0,
732 PCI_DEVICE_ID_INTEL_GLK_CSE0,
Andrey Petrov0405de92017-06-05 13:25:29 -0700733 PCI_DEVICE_ID_INTEL_CNL_CSE0,
Subrata Banikd0586d22017-11-27 13:28:41 +0530734 PCI_DEVICE_ID_INTEL_SKL_CSE0,
Maxim Polyakov571d07d2019-08-22 13:11:32 +0300735 PCI_DEVICE_ID_INTEL_LWB_CSE0,
736 PCI_DEVICE_ID_INTEL_LWB_CSE0_SUPER,
praveen hodagatta praneshe26c4a42018-09-20 03:49:45 +0800737 PCI_DEVICE_ID_INTEL_CNP_H_CSE0,
Aamir Bohra9eac0392018-06-30 12:07:04 +0530738 PCI_DEVICE_ID_INTEL_ICL_CSE0,
Ronak Kanabarda7ffb482019-02-05 01:51:13 +0530739 PCI_DEVICE_ID_INTEL_CMP_CSE0,
Gaggery Tsai12a651c2019-12-05 11:23:20 -0800740 PCI_DEVICE_ID_INTEL_CMP_H_CSE0,
Ravi Sarawadi6b5bf402019-10-21 22:25:04 -0700741 PCI_DEVICE_ID_INTEL_TGL_CSE0,
rkanabar263f1292019-11-28 10:41:45 +0530742 PCI_DEVICE_ID_INTEL_JSP_PRE_PROD_CSE0,
Hannah Williams63142152017-06-12 14:03:18 -0700743 0,
744};
745
Andrey Petrov04a72c42017-03-01 15:51:57 -0800746static const struct pci_driver cse_driver __pci_driver = {
747 .ops = &cse_ops,
748 .vendor = PCI_VENDOR_ID_INTEL,
749 /* SoC/chipset needs to provide PCI device ID */
Andrey Petrov0405de92017-06-05 13:25:29 -0700750 .devices = pci_device_ids
Andrey Petrov04a72c42017-03-01 15:51:57 -0800751};
752
753#endif