blob: 01b20501a7c298c58235b04a9200b3ce56f35f5f [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
Sridhar Siricillab9d075b2019-08-31 11:38:33 +053070#define HECI_OP_MODE_SEC_OVERRIDE 5
Andrey Petrov04a72c42017-03-01 15:51:57 -080071
Sridhar Siricillad415c202019-08-31 14:54:57 +053072/* Global Reset Command ID */
73#define MKHI_GLOBAL_RESET_REQ 0xb
74#define MKHI_GROUP_ID_CBM 0
75
76/* RST Origin */
77#define GR_ORIGIN_BIOS_POST 2
78
Arthur Heymans3d6ccd02019-05-27 17:25:23 +020079static struct cse_device {
Andrey Petrov04a72c42017-03-01 15:51:57 -080080 uintptr_t sec_bar;
Arthur Heymansa5eed802019-05-25 10:28:11 +020081} g_cse;
Andrey Petrov04a72c42017-03-01 15:51:57 -080082
Sridhar Siricillad415c202019-08-31 14:54:57 +053083/* HECI Message Header */
84struct mkhi_hdr {
85 uint8_t group_id;
86 uint8_t command:7;
87 uint8_t is_resp:1;
88 uint8_t rsvd;
89 uint8_t result;
90} __packed;
Andrey Petrov04a72c42017-03-01 15:51:57 -080091/*
92 * Initialize the device with provided temporary BAR. If BAR is 0 use a
93 * default. This is intended for pre-mem usage only where BARs haven't been
94 * assigned yet and devices are not enabled.
95 */
96void heci_init(uintptr_t tempbar)
97{
Elyes HAOUAS68c851b2018-06-12 22:06:09 +020098#if defined(__SIMPLE_DEVICE__)
99 pci_devfn_t dev = PCH_DEV_CSE;
100#else
101 struct device *dev = PCH_DEV_CSE;
102#endif
Andrey Petrov04a72c42017-03-01 15:51:57 -0800103 u8 pcireg;
104
105 /* Assume it is already initialized, nothing else to do */
Arthur Heymansa5eed802019-05-25 10:28:11 +0200106 if (g_cse.sec_bar)
Andrey Petrov04a72c42017-03-01 15:51:57 -0800107 return;
108
109 /* Use default pre-ram bar */
110 if (!tempbar)
111 tempbar = HECI1_BASE_ADDRESS;
112
113 /* Assign Resources to HECI1 */
114 /* Clear BIT 1-2 of Command Register */
115 pcireg = pci_read_config8(dev, PCI_COMMAND);
116 pcireg &= ~(PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY);
117 pci_write_config8(dev, PCI_COMMAND, pcireg);
118
119 /* Program Temporary BAR for HECI1 */
120 pci_write_config32(dev, PCI_BASE_ADDRESS_0, tempbar);
121 pci_write_config32(dev, PCI_BASE_ADDRESS_1, 0x0);
122
123 /* Enable Bus Master and MMIO Space */
124 pcireg = pci_read_config8(dev, PCI_COMMAND);
125 pcireg |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
126 pci_write_config8(dev, PCI_COMMAND, pcireg);
127
Arthur Heymansa5eed802019-05-25 10:28:11 +0200128 g_cse.sec_bar = tempbar;
Andrey Petrov04a72c42017-03-01 15:51:57 -0800129}
130
Subrata Banik05e06cd2017-11-09 15:04:09 +0530131/* Get HECI BAR 0 from PCI configuration space */
132static uint32_t get_cse_bar(void)
133{
134 uintptr_t bar;
135
136 bar = pci_read_config32(PCH_DEV_CSE, PCI_BASE_ADDRESS_0);
137 assert(bar != 0);
138 /*
139 * Bits 31-12 are the base address as per EDS for SPI,
140 * Don't care about 0-11 bit
141 */
142 return bar & ~PCI_BASE_ADDRESS_MEM_ATTR_MASK;
143}
144
Andrey Petrov04a72c42017-03-01 15:51:57 -0800145static uint32_t read_bar(uint32_t offset)
146{
Jonathan Neuschäfer5268b762018-02-12 12:24:25 +0100147 /* Reach PCI config space to get BAR in case CAR global not available */
Arthur Heymansa5eed802019-05-25 10:28:11 +0200148 if (!g_cse.sec_bar)
149 g_cse.sec_bar = get_cse_bar();
150 return read32((void *)(g_cse.sec_bar + offset));
Andrey Petrov04a72c42017-03-01 15:51:57 -0800151}
152
153static void write_bar(uint32_t offset, uint32_t val)
154{
Jonathan Neuschäfer5268b762018-02-12 12:24:25 +0100155 /* Reach PCI config space to get BAR in case CAR global not available */
Arthur Heymansa5eed802019-05-25 10:28:11 +0200156 if (!g_cse.sec_bar)
157 g_cse.sec_bar = get_cse_bar();
158 return write32((void *)(g_cse.sec_bar + offset), val);
Andrey Petrov04a72c42017-03-01 15:51:57 -0800159}
160
161static uint32_t read_cse_csr(void)
162{
163 return read_bar(MMIO_CSE_CSR);
164}
165
166static uint32_t read_host_csr(void)
167{
168 return read_bar(MMIO_HOST_CSR);
169}
170
171static void write_host_csr(uint32_t data)
172{
173 write_bar(MMIO_HOST_CSR, data);
174}
175
176static size_t filled_slots(uint32_t data)
177{
178 uint8_t wp, rp;
179 rp = data >> CSR_RP_START;
180 wp = data >> CSR_WP_START;
181 return (uint8_t) (wp - rp);
182}
183
184static size_t cse_filled_slots(void)
185{
186 return filled_slots(read_cse_csr());
187}
188
189static size_t host_empty_slots(void)
190{
191 uint32_t csr;
192 csr = read_host_csr();
193
194 return ((csr & CSR_CBD) >> CSR_CBD_START) - filled_slots(csr);
195}
196
197static void clear_int(void)
198{
199 uint32_t csr;
200 csr = read_host_csr();
201 csr |= CSR_IS;
202 write_host_csr(csr);
203}
204
205static uint32_t read_slot(void)
206{
207 return read_bar(MMIO_CSE_CB_RW);
208}
209
210static void write_slot(uint32_t val)
211{
212 write_bar(MMIO_CSE_CB_WW, val);
213}
214
215static int wait_write_slots(size_t cnt)
216{
217 struct stopwatch sw;
218
219 stopwatch_init_msecs_expire(&sw, HECI_SEND_TIMEOUT);
220 while (host_empty_slots() < cnt) {
221 udelay(HECI_DELAY);
222 if (stopwatch_expired(&sw)) {
223 printk(BIOS_ERR, "HECI: timeout, buffer not drained\n");
224 return 0;
225 }
226 }
227 return 1;
228}
229
230static int wait_read_slots(size_t cnt)
231{
232 struct stopwatch sw;
233
234 stopwatch_init_msecs_expire(&sw, HECI_READ_TIMEOUT);
235 while (cse_filled_slots() < cnt) {
236 udelay(HECI_DELAY);
237 if (stopwatch_expired(&sw)) {
238 printk(BIOS_ERR, "HECI: timed out reading answer!\n");
239 return 0;
240 }
241 }
242 return 1;
243}
244
245/* get number of full 4-byte slots */
246static size_t bytes_to_slots(size_t bytes)
247{
248 return ALIGN_UP(bytes, SLOT_SIZE) / SLOT_SIZE;
249}
250
251static int cse_ready(void)
252{
253 uint32_t csr;
254 csr = read_cse_csr();
255 return csr & CSR_READY;
256}
257
Sridhar Siricillab9d075b2019-08-31 11:38:33 +0530258/*
259 * Checks if CSE is in SEC_OVERRIDE operation mode. This is the mode where
260 * CSE will allow reflashing of CSE region.
261 */
262static uint8_t check_cse_sec_override_mode(void)
263{
264 union me_hfsts1 hfs1;
265 hfs1.data = me_read_config32(PCI_ME_HFSTS1);
266 if (hfs1.fields.operation_mode == HECI_OP_MODE_SEC_OVERRIDE)
267 return 1;
268 return 0;
269}
270
271/* Makes the host ready to communicate with CSE */
272void set_host_ready(void)
273{
274 uint32_t csr;
275 csr = read_host_csr();
276 csr &= ~CSR_RESET;
277 csr |= (CSR_IG | CSR_READY);
278 write_host_csr(csr);
279}
280
281/* Polls for ME state 'HECI_OP_MODE_SEC_OVERRIDE' for 15 seconds */
282uint8_t wait_cse_sec_override_mode(void)
283{
284 struct stopwatch sw;
285 stopwatch_init_msecs_expire(&sw, HECI_DELAY_READY);
286 while (!check_cse_sec_override_mode()) {
287 udelay(HECI_DELAY);
288 if (stopwatch_expired(&sw))
289 return 0;
290 }
291
292 return 1;
293}
294
Andrey Petrov04a72c42017-03-01 15:51:57 -0800295static int wait_heci_ready(void)
296{
297 struct stopwatch sw;
298
299 stopwatch_init_msecs_expire(&sw, HECI_DELAY_READY);
300 while (!cse_ready()) {
301 udelay(HECI_DELAY);
302 if (stopwatch_expired(&sw))
303 return 0;
304 }
305
306 return 1;
307}
308
309static void host_gen_interrupt(void)
310{
311 uint32_t csr;
312 csr = read_host_csr();
313 csr |= CSR_IG;
314 write_host_csr(csr);
315}
316
317static size_t hdr_get_length(uint32_t hdr)
318{
319 return (hdr & MEI_HDR_LENGTH) >> MEI_HDR_LENGTH_START;
320}
321
322static int
323send_one_message(uint32_t hdr, const void *buff)
324{
325 size_t pend_len, pend_slots, remainder, i;
326 uint32_t tmp;
327 const uint32_t *p = buff;
328
329 /* Get space for the header */
330 if (!wait_write_slots(1))
331 return 0;
332
333 /* First, write header */
334 write_slot(hdr);
335
336 pend_len = hdr_get_length(hdr);
337 pend_slots = bytes_to_slots(pend_len);
338
339 if (!wait_write_slots(pend_slots))
340 return 0;
341
342 /* Write the body in whole slots */
343 i = 0;
344 while (i < ALIGN_DOWN(pend_len, SLOT_SIZE)) {
345 write_slot(*p++);
346 i += SLOT_SIZE;
347 }
348
349 remainder = pend_len % SLOT_SIZE;
350 /* Pad to 4 bytes not touching caller's buffer */
351 if (remainder) {
352 memcpy(&tmp, p, remainder);
353 write_slot(tmp);
354 }
355
356 host_gen_interrupt();
357
358 /* Make sure nothing bad happened during transmission */
359 if (!cse_ready())
360 return 0;
361
362 return pend_len;
363}
364
365int
366heci_send(const void *msg, size_t len, uint8_t host_addr, uint8_t client_addr)
367{
Subrata Banik5c08c732017-11-13 14:54:37 +0530368 uint8_t retry;
Andrey Petrov04a72c42017-03-01 15:51:57 -0800369 uint32_t csr, hdr;
Subrata Banik5c08c732017-11-13 14:54:37 +0530370 size_t sent, remaining, cb_size, max_length;
371 const uint8_t *p;
Andrey Petrov04a72c42017-03-01 15:51:57 -0800372
373 if (!msg || !len)
374 return 0;
375
376 clear_int();
377
Subrata Banik5c08c732017-11-13 14:54:37 +0530378 for (retry = 0; retry < MAX_HECI_MESSAGE_RETRY_COUNT; retry++) {
379 p = msg;
Andrey Petrov04a72c42017-03-01 15:51:57 -0800380
Subrata Banik5c08c732017-11-13 14:54:37 +0530381 if (!wait_heci_ready()) {
382 printk(BIOS_ERR, "HECI: not ready\n");
383 continue;
384 }
Andrey Petrov04a72c42017-03-01 15:51:57 -0800385
Subrata Banik4a722f52017-11-13 14:56:42 +0530386 csr = read_host_csr();
Subrata Banik5c08c732017-11-13 14:54:37 +0530387 cb_size = ((csr & CSR_CBD) >> CSR_CBD_START) * SLOT_SIZE;
388 /*
389 * Reserve one slot for the header. Limit max message
390 * length by 9 bits that are available in the header.
391 */
392 max_length = MIN(cb_size, (1 << MEI_HDR_LENGTH_SIZE) - 1)
393 - SLOT_SIZE;
394 remaining = len;
395
396 /*
397 * Fragment the message into smaller messages not exceeding
Jonathan Neuschäfer5268b762018-02-12 12:24:25 +0100398 * useful circular buffer length. Mark last message complete.
Subrata Banik5c08c732017-11-13 14:54:37 +0530399 */
400 do {
401 hdr = MIN(max_length, remaining)
402 << MEI_HDR_LENGTH_START;
403 hdr |= client_addr << MEI_HDR_CSE_ADDR_START;
404 hdr |= host_addr << MEI_HDR_HOST_ADDR_START;
405 hdr |= (MIN(max_length, remaining) == remaining) ?
Lee Leahy68ab0b52017-03-10 13:42:34 -0800406 MEI_HDR_IS_COMPLETE : 0;
Subrata Banik5c08c732017-11-13 14:54:37 +0530407 sent = send_one_message(hdr, p);
408 p += sent;
409 remaining -= sent;
410 } while (remaining > 0 && sent != 0);
Andrey Petrov04a72c42017-03-01 15:51:57 -0800411
Subrata Banik5c08c732017-11-13 14:54:37 +0530412 if (!remaining)
413 return 1;
414 }
415 return 0;
Andrey Petrov04a72c42017-03-01 15:51:57 -0800416}
417
418static size_t
419recv_one_message(uint32_t *hdr, void *buff, size_t maxlen)
420{
421 uint32_t reg, *p = buff;
422 size_t recv_slots, recv_len, remainder, i;
423
424 /* first get the header */
425 if (!wait_read_slots(1))
426 return 0;
427
428 *hdr = read_slot();
429 recv_len = hdr_get_length(*hdr);
430
431 if (!recv_len)
432 printk(BIOS_WARNING, "HECI: message is zero-sized\n");
433
434 recv_slots = bytes_to_slots(recv_len);
435
436 i = 0;
437 if (recv_len > maxlen) {
438 printk(BIOS_ERR, "HECI: response is too big\n");
439 return 0;
440 }
441
442 /* wait for the rest of messages to arrive */
443 wait_read_slots(recv_slots);
444
445 /* fetch whole slots first */
446 while (i < ALIGN_DOWN(recv_len, SLOT_SIZE)) {
447 *p++ = read_slot();
448 i += SLOT_SIZE;
449 }
450
Subrata Banik5c08c732017-11-13 14:54:37 +0530451 /*
452 * If ME is not ready, something went wrong and
453 * we received junk
454 */
455 if (!cse_ready())
456 return 0;
457
Andrey Petrov04a72c42017-03-01 15:51:57 -0800458 remainder = recv_len % SLOT_SIZE;
459
460 if (remainder) {
461 reg = read_slot();
462 memcpy(p, &reg, remainder);
463 }
464
465 return recv_len;
466}
467
468int heci_receive(void *buff, size_t *maxlen)
469{
Subrata Banik5c08c732017-11-13 14:54:37 +0530470 uint8_t retry;
Andrey Petrov04a72c42017-03-01 15:51:57 -0800471 size_t left, received;
472 uint32_t hdr = 0;
Subrata Banik5c08c732017-11-13 14:54:37 +0530473 uint8_t *p;
Andrey Petrov04a72c42017-03-01 15:51:57 -0800474
475 if (!buff || !maxlen || !*maxlen)
476 return 0;
477
Andrey Petrov04a72c42017-03-01 15:51:57 -0800478 clear_int();
479
Subrata Banik5c08c732017-11-13 14:54:37 +0530480 for (retry = 0; retry < MAX_HECI_MESSAGE_RETRY_COUNT; retry++) {
481 p = buff;
482 left = *maxlen;
483
484 if (!wait_heci_ready()) {
485 printk(BIOS_ERR, "HECI: not ready\n");
486 continue;
487 }
488
489 /*
490 * Receive multiple packets until we meet one marked
491 * complete or we run out of space in caller-provided buffer.
492 */
493 do {
494 received = recv_one_message(&hdr, p, left);
Lijian Zhaoc50296d2017-12-15 19:10:18 -0800495 if (!received) {
Elyes HAOUAS3d450002018-08-09 18:55:58 +0200496 printk(BIOS_ERR, "HECI: Failed to receive!\n");
Lijian Zhaoc50296d2017-12-15 19:10:18 -0800497 return 0;
498 }
Subrata Banik5c08c732017-11-13 14:54:37 +0530499 left -= received;
500 p += received;
501 /* If we read out everything ping to send more */
502 if (!(hdr & MEI_HDR_IS_COMPLETE) && !cse_filled_slots())
503 host_gen_interrupt();
504 } while (received && !(hdr & MEI_HDR_IS_COMPLETE) && left > 0);
505
506 if ((hdr & MEI_HDR_IS_COMPLETE) && received) {
507 *maxlen = p - (uint8_t *) buff;
508 return 1;
509 }
Andrey Petrov04a72c42017-03-01 15:51:57 -0800510 }
Subrata Banik5c08c732017-11-13 14:54:37 +0530511 return 0;
Andrey Petrov04a72c42017-03-01 15:51:57 -0800512}
513
Sridhar Siricillaa5208f52019-08-30 17:10:24 +0530514int heci_send_receive(const void *snd_msg, size_t snd_sz, void *rcv_msg, size_t *rcv_sz)
515{
516 if (!heci_send(snd_msg, snd_sz, BIOS_HOST_ADDR, HECI_MKHI_ADDR)) {
517 printk(BIOS_ERR, "HECI: send Failed\n");
518 return 0;
519 }
520
521 if (rcv_msg != NULL) {
522 if (!heci_receive(rcv_msg, rcv_sz)) {
523 printk(BIOS_ERR, "HECI: receive Failed\n");
524 return 0;
525 }
526 }
527 return 1;
528}
529
Andrey Petrov04a72c42017-03-01 15:51:57 -0800530/*
531 * Attempt to reset the device. This is useful when host and ME are out
532 * of sync during transmission or ME didn't understand the message.
533 */
534int heci_reset(void)
535{
536 uint32_t csr;
537
538 /* Send reset request */
539 csr = read_host_csr();
Sridhar Siricillab9d075b2019-08-31 11:38:33 +0530540 csr |= (CSR_RESET | CSR_IG);
Andrey Petrov04a72c42017-03-01 15:51:57 -0800541 write_host_csr(csr);
542
543 if (wait_heci_ready()) {
544 /* Device is back on its imaginary feet, clear reset */
Sridhar Siricillab9d075b2019-08-31 11:38:33 +0530545 set_host_ready();
Andrey Petrov04a72c42017-03-01 15:51:57 -0800546 return 1;
547 }
548
549 printk(BIOS_CRIT, "HECI: reset failed\n");
550
551 return 0;
552}
553
Sridhar Siricilla2cc66912019-08-31 11:20:34 +0530554bool is_cse_enabled(void)
555{
556 const struct device *cse_dev = pcidev_path_on_root(PCH_DEVFN_CSE);
557
558 if (!cse_dev || !cse_dev->enabled) {
559 printk(BIOS_WARNING, "HECI: No CSE device\n");
560 return false;
561 }
562
563 if (pci_read_config16(PCH_DEV_CSE, PCI_VENDOR_ID) == 0xFFFF) {
564 printk(BIOS_WARNING, "HECI: CSE device is hidden\n");
565 return false;
566 }
567
568 return true;
569}
570
571uint32_t me_read_config32(int offset)
572{
573 return pci_read_config32(PCH_DEV_CSE, offset);
574}
575
Sridhar Siricillad415c202019-08-31 14:54:57 +0530576/*
577 * Sends GLOBAL_RESET_REQ cmd to CSE.The reset type can be GLOBAL_RESET/
578 * HOST_RESET_ONLY/CSE_RESET_ONLY.
579 */
580int send_heci_reset_req_message(uint8_t rst_type)
581{
582 int status;
583 struct mkhi_hdr reply;
584 struct reset_message {
585 struct mkhi_hdr hdr;
586 uint8_t req_origin;
587 uint8_t reset_type;
588 } __packed;
589 struct reset_message msg = {
590 .hdr = {
591 .group_id = MKHI_GROUP_ID_CBM,
592 .command = MKHI_GLOBAL_RESET_REQ,
593 },
594 .req_origin = GR_ORIGIN_BIOS_POST,
595 .reset_type = rst_type
596 };
597 size_t reply_size;
598
599 if (!((rst_type == GLOBAL_RESET) ||
600 (rst_type == HOST_RESET_ONLY) || (rst_type == CSE_RESET_ONLY)))
601 return -1;
602
603 heci_reset();
604
605 reply_size = sizeof(reply);
606 memset(&reply, 0, reply_size);
607
608 printk(BIOS_DEBUG, "HECI: Global Reset(Type:%d) Command\n", rst_type);
609 if (rst_type == CSE_RESET_ONLY)
610 status = heci_send_receive(&msg, sizeof(msg), NULL, 0);
611 else
612 status = heci_send_receive(&msg, sizeof(msg), &reply,
613 &reply_size);
614
615 if (status != 1)
616 return -1;
617
618 printk(BIOS_DEBUG, "HECI: Global Reset success!\n");
619 return 0;
620}
621
Andrey Petrov04a72c42017-03-01 15:51:57 -0800622#if ENV_RAMSTAGE
623
624static void update_sec_bar(struct device *dev)
625{
626 g_cse.sec_bar = find_resource(dev, PCI_BASE_ADDRESS_0)->base;
627}
628
629static void cse_set_resources(struct device *dev)
630{
Subrata Banik2ee54db2017-03-05 12:37:00 +0530631 if (dev->path.pci.devfn == PCH_DEVFN_CSE)
Andrey Petrov04a72c42017-03-01 15:51:57 -0800632 update_sec_bar(dev);
633
634 pci_dev_set_resources(dev);
635}
636
637static struct device_operations cse_ops = {
638 .set_resources = cse_set_resources,
639 .read_resources = pci_dev_read_resources,
640 .enable_resources = pci_dev_enable_resources,
641 .init = pci_dev_init,
Subrata Banik6bbc91a2017-12-07 14:55:51 +0530642 .ops_pci = &pci_dev_ops_pci,
Andrey Petrov04a72c42017-03-01 15:51:57 -0800643};
644
Hannah Williams63142152017-06-12 14:03:18 -0700645static const unsigned short pci_device_ids[] = {
646 PCI_DEVICE_ID_INTEL_APL_CSE0,
647 PCI_DEVICE_ID_INTEL_GLK_CSE0,
Andrey Petrov0405de92017-06-05 13:25:29 -0700648 PCI_DEVICE_ID_INTEL_CNL_CSE0,
Subrata Banikd0586d22017-11-27 13:28:41 +0530649 PCI_DEVICE_ID_INTEL_SKL_CSE0,
Maxim Polyakov571d07d2019-08-22 13:11:32 +0300650 PCI_DEVICE_ID_INTEL_LWB_CSE0,
651 PCI_DEVICE_ID_INTEL_LWB_CSE0_SUPER,
praveen hodagatta praneshe26c4a42018-09-20 03:49:45 +0800652 PCI_DEVICE_ID_INTEL_CNP_H_CSE0,
Aamir Bohra9eac0392018-06-30 12:07:04 +0530653 PCI_DEVICE_ID_INTEL_ICL_CSE0,
Ronak Kanabarda7ffb482019-02-05 01:51:13 +0530654 PCI_DEVICE_ID_INTEL_CMP_CSE0,
Hannah Williams63142152017-06-12 14:03:18 -0700655 0,
656};
657
Andrey Petrov04a72c42017-03-01 15:51:57 -0800658static const struct pci_driver cse_driver __pci_driver = {
659 .ops = &cse_ops,
660 .vendor = PCI_VENDOR_ID_INTEL,
661 /* SoC/chipset needs to provide PCI device ID */
Andrey Petrov0405de92017-06-05 13:25:29 -0700662 .devices = pci_device_ids
Andrey Petrov04a72c42017-03-01 15:51:57 -0800663};
664
665#endif