blob: 8651297905da0004c3c2a27e3a76e36b93878d9e [file] [log] [blame]
Andrey Petrov04a72c42017-03-01 15:51:57 -08001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright 2017 Intel Inc.
5 *
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
16#include <arch/early_variables.h>
Subrata Banik05e06cd2017-11-09 15:04:09 +053017#include <assert.h>
Andrey Petrov04a72c42017-03-01 15:51:57 -080018#include <commonlib/helpers.h>
19#include <console/console.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>
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
70
71struct cse_device {
72 uintptr_t sec_bar;
73} g_cse CAR_GLOBAL;
74
75/*
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.
79 */
80void heci_init(uintptr_t tempbar)
81{
82 struct cse_device *cse = car_get_var_ptr(&g_cse);
Elyes HAOUAS68c851b2018-06-12 22:06:09 +020083#if defined(__SIMPLE_DEVICE__)
84 pci_devfn_t dev = PCH_DEV_CSE;
85#else
86 struct device *dev = PCH_DEV_CSE;
87#endif
Andrey Petrov04a72c42017-03-01 15:51:57 -080088 u8 pcireg;
89
90 /* Assume it is already initialized, nothing else to do */
91 if (cse->sec_bar)
92 return;
93
94 /* Use default pre-ram bar */
95 if (!tempbar)
96 tempbar = HECI1_BASE_ADDRESS;
97
98 /* Assign Resources to HECI1 */
99 /* Clear BIT 1-2 of Command Register */
100 pcireg = pci_read_config8(dev, PCI_COMMAND);
101 pcireg &= ~(PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY);
102 pci_write_config8(dev, PCI_COMMAND, pcireg);
103
104 /* Program Temporary BAR for HECI1 */
105 pci_write_config32(dev, PCI_BASE_ADDRESS_0, tempbar);
106 pci_write_config32(dev, PCI_BASE_ADDRESS_1, 0x0);
107
108 /* Enable Bus Master and MMIO Space */
109 pcireg = pci_read_config8(dev, PCI_COMMAND);
110 pcireg |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
111 pci_write_config8(dev, PCI_COMMAND, pcireg);
112
113 cse->sec_bar = tempbar;
114}
115
Subrata Banik05e06cd2017-11-09 15:04:09 +0530116/* Get HECI BAR 0 from PCI configuration space */
117static uint32_t get_cse_bar(void)
118{
119 uintptr_t bar;
120
121 bar = pci_read_config32(PCH_DEV_CSE, PCI_BASE_ADDRESS_0);
122 assert(bar != 0);
123 /*
124 * Bits 31-12 are the base address as per EDS for SPI,
125 * Don't care about 0-11 bit
126 */
127 return bar & ~PCI_BASE_ADDRESS_MEM_ATTR_MASK;
128}
129
Andrey Petrov04a72c42017-03-01 15:51:57 -0800130static uint32_t read_bar(uint32_t offset)
131{
132 struct cse_device *cse = car_get_var_ptr(&g_cse);
Jonathan Neuschäfer5268b762018-02-12 12:24:25 +0100133 /* Reach PCI config space to get BAR in case CAR global not available */
Subrata Banik05e06cd2017-11-09 15:04:09 +0530134 if (!cse->sec_bar)
135 cse->sec_bar = get_cse_bar();
Andrey Petrov04a72c42017-03-01 15:51:57 -0800136 return read32((void *)(cse->sec_bar + offset));
137}
138
139static void write_bar(uint32_t offset, uint32_t val)
140{
141 struct cse_device *cse = car_get_var_ptr(&g_cse);
Jonathan Neuschäfer5268b762018-02-12 12:24:25 +0100142 /* Reach PCI config space to get BAR in case CAR global not available */
Subrata Banik05e06cd2017-11-09 15:04:09 +0530143 if (!cse->sec_bar)
144 cse->sec_bar = get_cse_bar();
Andrey Petrov04a72c42017-03-01 15:51:57 -0800145 return write32((void *)(cse->sec_bar + offset), val);
146}
147
148static uint32_t read_cse_csr(void)
149{
150 return read_bar(MMIO_CSE_CSR);
151}
152
153static uint32_t read_host_csr(void)
154{
155 return read_bar(MMIO_HOST_CSR);
156}
157
158static void write_host_csr(uint32_t data)
159{
160 write_bar(MMIO_HOST_CSR, data);
161}
162
163static size_t filled_slots(uint32_t data)
164{
165 uint8_t wp, rp;
166 rp = data >> CSR_RP_START;
167 wp = data >> CSR_WP_START;
168 return (uint8_t) (wp - rp);
169}
170
171static size_t cse_filled_slots(void)
172{
173 return filled_slots(read_cse_csr());
174}
175
176static size_t host_empty_slots(void)
177{
178 uint32_t csr;
179 csr = read_host_csr();
180
181 return ((csr & CSR_CBD) >> CSR_CBD_START) - filled_slots(csr);
182}
183
184static void clear_int(void)
185{
186 uint32_t csr;
187 csr = read_host_csr();
188 csr |= CSR_IS;
189 write_host_csr(csr);
190}
191
192static uint32_t read_slot(void)
193{
194 return read_bar(MMIO_CSE_CB_RW);
195}
196
197static void write_slot(uint32_t val)
198{
199 write_bar(MMIO_CSE_CB_WW, val);
200}
201
202static int wait_write_slots(size_t cnt)
203{
204 struct stopwatch sw;
205
206 stopwatch_init_msecs_expire(&sw, HECI_SEND_TIMEOUT);
207 while (host_empty_slots() < cnt) {
208 udelay(HECI_DELAY);
209 if (stopwatch_expired(&sw)) {
210 printk(BIOS_ERR, "HECI: timeout, buffer not drained\n");
211 return 0;
212 }
213 }
214 return 1;
215}
216
217static int wait_read_slots(size_t cnt)
218{
219 struct stopwatch sw;
220
221 stopwatch_init_msecs_expire(&sw, HECI_READ_TIMEOUT);
222 while (cse_filled_slots() < cnt) {
223 udelay(HECI_DELAY);
224 if (stopwatch_expired(&sw)) {
225 printk(BIOS_ERR, "HECI: timed out reading answer!\n");
226 return 0;
227 }
228 }
229 return 1;
230}
231
232/* get number of full 4-byte slots */
233static size_t bytes_to_slots(size_t bytes)
234{
235 return ALIGN_UP(bytes, SLOT_SIZE) / SLOT_SIZE;
236}
237
238static int cse_ready(void)
239{
240 uint32_t csr;
241 csr = read_cse_csr();
242 return csr & CSR_READY;
243}
244
245static int wait_heci_ready(void)
246{
247 struct stopwatch sw;
248
249 stopwatch_init_msecs_expire(&sw, HECI_DELAY_READY);
250 while (!cse_ready()) {
251 udelay(HECI_DELAY);
252 if (stopwatch_expired(&sw))
253 return 0;
254 }
255
256 return 1;
257}
258
259static void host_gen_interrupt(void)
260{
261 uint32_t csr;
262 csr = read_host_csr();
263 csr |= CSR_IG;
264 write_host_csr(csr);
265}
266
267static size_t hdr_get_length(uint32_t hdr)
268{
269 return (hdr & MEI_HDR_LENGTH) >> MEI_HDR_LENGTH_START;
270}
271
272static int
273send_one_message(uint32_t hdr, const void *buff)
274{
275 size_t pend_len, pend_slots, remainder, i;
276 uint32_t tmp;
277 const uint32_t *p = buff;
278
279 /* Get space for the header */
280 if (!wait_write_slots(1))
281 return 0;
282
283 /* First, write header */
284 write_slot(hdr);
285
286 pend_len = hdr_get_length(hdr);
287 pend_slots = bytes_to_slots(pend_len);
288
289 if (!wait_write_slots(pend_slots))
290 return 0;
291
292 /* Write the body in whole slots */
293 i = 0;
294 while (i < ALIGN_DOWN(pend_len, SLOT_SIZE)) {
295 write_slot(*p++);
296 i += SLOT_SIZE;
297 }
298
299 remainder = pend_len % SLOT_SIZE;
300 /* Pad to 4 bytes not touching caller's buffer */
301 if (remainder) {
302 memcpy(&tmp, p, remainder);
303 write_slot(tmp);
304 }
305
306 host_gen_interrupt();
307
308 /* Make sure nothing bad happened during transmission */
309 if (!cse_ready())
310 return 0;
311
312 return pend_len;
313}
314
315int
316heci_send(const void *msg, size_t len, uint8_t host_addr, uint8_t client_addr)
317{
Subrata Banik5c08c732017-11-13 14:54:37 +0530318 uint8_t retry;
Andrey Petrov04a72c42017-03-01 15:51:57 -0800319 uint32_t csr, hdr;
Subrata Banik5c08c732017-11-13 14:54:37 +0530320 size_t sent, remaining, cb_size, max_length;
321 const uint8_t *p;
Andrey Petrov04a72c42017-03-01 15:51:57 -0800322
323 if (!msg || !len)
324 return 0;
325
326 clear_int();
327
Subrata Banik5c08c732017-11-13 14:54:37 +0530328 for (retry = 0; retry < MAX_HECI_MESSAGE_RETRY_COUNT; retry++) {
329 p = msg;
Andrey Petrov04a72c42017-03-01 15:51:57 -0800330
Subrata Banik5c08c732017-11-13 14:54:37 +0530331 if (!wait_heci_ready()) {
332 printk(BIOS_ERR, "HECI: not ready\n");
333 continue;
334 }
Andrey Petrov04a72c42017-03-01 15:51:57 -0800335
Subrata Banik4a722f52017-11-13 14:56:42 +0530336 csr = read_host_csr();
Subrata Banik5c08c732017-11-13 14:54:37 +0530337 cb_size = ((csr & CSR_CBD) >> CSR_CBD_START) * SLOT_SIZE;
338 /*
339 * Reserve one slot for the header. Limit max message
340 * length by 9 bits that are available in the header.
341 */
342 max_length = MIN(cb_size, (1 << MEI_HDR_LENGTH_SIZE) - 1)
343 - SLOT_SIZE;
344 remaining = len;
345
346 /*
347 * Fragment the message into smaller messages not exceeding
Jonathan Neuschäfer5268b762018-02-12 12:24:25 +0100348 * useful circular buffer length. Mark last message complete.
Subrata Banik5c08c732017-11-13 14:54:37 +0530349 */
350 do {
351 hdr = MIN(max_length, remaining)
352 << MEI_HDR_LENGTH_START;
353 hdr |= client_addr << MEI_HDR_CSE_ADDR_START;
354 hdr |= host_addr << MEI_HDR_HOST_ADDR_START;
355 hdr |= (MIN(max_length, remaining) == remaining) ?
Lee Leahy68ab0b52017-03-10 13:42:34 -0800356 MEI_HDR_IS_COMPLETE : 0;
Subrata Banik5c08c732017-11-13 14:54:37 +0530357 sent = send_one_message(hdr, p);
358 p += sent;
359 remaining -= sent;
360 } while (remaining > 0 && sent != 0);
Andrey Petrov04a72c42017-03-01 15:51:57 -0800361
Subrata Banik5c08c732017-11-13 14:54:37 +0530362 if (!remaining)
363 return 1;
364 }
365 return 0;
Andrey Petrov04a72c42017-03-01 15:51:57 -0800366}
367
368static size_t
369recv_one_message(uint32_t *hdr, void *buff, size_t maxlen)
370{
371 uint32_t reg, *p = buff;
372 size_t recv_slots, recv_len, remainder, i;
373
374 /* first get the header */
375 if (!wait_read_slots(1))
376 return 0;
377
378 *hdr = read_slot();
379 recv_len = hdr_get_length(*hdr);
380
381 if (!recv_len)
382 printk(BIOS_WARNING, "HECI: message is zero-sized\n");
383
384 recv_slots = bytes_to_slots(recv_len);
385
386 i = 0;
387 if (recv_len > maxlen) {
388 printk(BIOS_ERR, "HECI: response is too big\n");
389 return 0;
390 }
391
392 /* wait for the rest of messages to arrive */
393 wait_read_slots(recv_slots);
394
395 /* fetch whole slots first */
396 while (i < ALIGN_DOWN(recv_len, SLOT_SIZE)) {
397 *p++ = read_slot();
398 i += SLOT_SIZE;
399 }
400
Subrata Banik5c08c732017-11-13 14:54:37 +0530401 /*
402 * If ME is not ready, something went wrong and
403 * we received junk
404 */
405 if (!cse_ready())
406 return 0;
407
Andrey Petrov04a72c42017-03-01 15:51:57 -0800408 remainder = recv_len % SLOT_SIZE;
409
410 if (remainder) {
411 reg = read_slot();
412 memcpy(p, &reg, remainder);
413 }
414
415 return recv_len;
416}
417
418int heci_receive(void *buff, size_t *maxlen)
419{
Subrata Banik5c08c732017-11-13 14:54:37 +0530420 uint8_t retry;
Andrey Petrov04a72c42017-03-01 15:51:57 -0800421 size_t left, received;
422 uint32_t hdr = 0;
Subrata Banik5c08c732017-11-13 14:54:37 +0530423 uint8_t *p;
Andrey Petrov04a72c42017-03-01 15:51:57 -0800424
425 if (!buff || !maxlen || !*maxlen)
426 return 0;
427
Andrey Petrov04a72c42017-03-01 15:51:57 -0800428 clear_int();
429
Subrata Banik5c08c732017-11-13 14:54:37 +0530430 for (retry = 0; retry < MAX_HECI_MESSAGE_RETRY_COUNT; retry++) {
431 p = buff;
432 left = *maxlen;
433
434 if (!wait_heci_ready()) {
435 printk(BIOS_ERR, "HECI: not ready\n");
436 continue;
437 }
438
439 /*
440 * Receive multiple packets until we meet one marked
441 * complete or we run out of space in caller-provided buffer.
442 */
443 do {
444 received = recv_one_message(&hdr, p, left);
Lijian Zhaoc50296d2017-12-15 19:10:18 -0800445 if (!received) {
446 printk(BIOS_ERR, "HECI: Failed to recieve!\n");
447 return 0;
448 }
Subrata Banik5c08c732017-11-13 14:54:37 +0530449 left -= received;
450 p += received;
451 /* If we read out everything ping to send more */
452 if (!(hdr & MEI_HDR_IS_COMPLETE) && !cse_filled_slots())
453 host_gen_interrupt();
454 } while (received && !(hdr & MEI_HDR_IS_COMPLETE) && left > 0);
455
456 if ((hdr & MEI_HDR_IS_COMPLETE) && received) {
457 *maxlen = p - (uint8_t *) buff;
458 return 1;
459 }
Andrey Petrov04a72c42017-03-01 15:51:57 -0800460 }
Subrata Banik5c08c732017-11-13 14:54:37 +0530461 return 0;
Andrey Petrov04a72c42017-03-01 15:51:57 -0800462}
463
464/*
465 * Attempt to reset the device. This is useful when host and ME are out
466 * of sync during transmission or ME didn't understand the message.
467 */
468int heci_reset(void)
469{
470 uint32_t csr;
471
472 /* Send reset request */
473 csr = read_host_csr();
474 csr |= CSR_RESET;
475 csr |= CSR_IG;
476 write_host_csr(csr);
477
478 if (wait_heci_ready()) {
479 /* Device is back on its imaginary feet, clear reset */
480 csr = read_host_csr();
481 csr &= ~CSR_RESET;
482 csr |= CSR_IG;
483 csr |= CSR_READY;
484 write_host_csr(csr);
485 return 1;
486 }
487
488 printk(BIOS_CRIT, "HECI: reset failed\n");
489
490 return 0;
491}
492
493#if ENV_RAMSTAGE
494
495static void update_sec_bar(struct device *dev)
496{
497 g_cse.sec_bar = find_resource(dev, PCI_BASE_ADDRESS_0)->base;
498}
499
500static void cse_set_resources(struct device *dev)
501{
Subrata Banik2ee54db2017-03-05 12:37:00 +0530502 if (dev->path.pci.devfn == PCH_DEVFN_CSE)
Andrey Petrov04a72c42017-03-01 15:51:57 -0800503 update_sec_bar(dev);
504
505 pci_dev_set_resources(dev);
506}
507
508static struct device_operations cse_ops = {
509 .set_resources = cse_set_resources,
510 .read_resources = pci_dev_read_resources,
511 .enable_resources = pci_dev_enable_resources,
512 .init = pci_dev_init,
Subrata Banik6bbc91a2017-12-07 14:55:51 +0530513 .ops_pci = &pci_dev_ops_pci,
Andrey Petrov04a72c42017-03-01 15:51:57 -0800514};
515
Hannah Williams63142152017-06-12 14:03:18 -0700516static const unsigned short pci_device_ids[] = {
517 PCI_DEVICE_ID_INTEL_APL_CSE0,
518 PCI_DEVICE_ID_INTEL_GLK_CSE0,
Andrey Petrov0405de92017-06-05 13:25:29 -0700519 PCI_DEVICE_ID_INTEL_CNL_CSE0,
Subrata Banikd0586d22017-11-27 13:28:41 +0530520 PCI_DEVICE_ID_INTEL_SKL_CSE0,
Hannah Williams63142152017-06-12 14:03:18 -0700521 0,
522};
523
Andrey Petrov04a72c42017-03-01 15:51:57 -0800524static const struct pci_driver cse_driver __pci_driver = {
525 .ops = &cse_ops,
526 .vendor = PCI_VENDOR_ID_INTEL,
527 /* SoC/chipset needs to provide PCI device ID */
Andrey Petrov0405de92017-06-05 13:25:29 -0700528 .devices = pci_device_ids
Andrey Petrov04a72c42017-03-01 15:51:57 -0800529};
530
531#endif