blob: bde4e9d97a1f0ef81c16ec5ef7aced03e73b5920 [file] [log] [blame]
Aaron Durbin76c37002012-10-30 09:03:43 -05001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2011 The Chromium OS Authors. All rights reserved.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; version 2 of
9 * the License.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
19 * MA 02110-1301 USA
20 */
21
22/*
23 * This is a ramstage driver for the Intel Management Engine found in the
24 * 6-series chipset. It handles the required boot-time messages over the
25 * MMIO-based Management Engine Interface to tell the ME that the BIOS is
26 * finished with POST. Additional messages are defined for debug but are
27 * not used unless the console loglevel is high enough.
28 */
29
30#include <arch/acpi.h>
31#include <arch/hlt.h>
32#include <arch/io.h>
33#include <console/console.h>
Stefan Reinauer24d1d4b2013-03-21 11:51:41 -070034#include <device/device.h>
35#include <device/pci.h>
Aaron Durbin76c37002012-10-30 09:03:43 -050036#include <device/pci_ids.h>
37#include <device/pci_def.h>
38#include <string.h>
39#include <delay.h>
40#include <elog.h>
41
Aaron Durbin76c37002012-10-30 09:03:43 -050042#include "me.h"
43#include "pch.h"
44
45#if CONFIG_CHROMEOS
46#include <vendorcode/google/chromeos/chromeos.h>
47#include <vendorcode/google/chromeos/gnvs.h>
48#endif
49
Aaron Durbin76c37002012-10-30 09:03:43 -050050/* Path that the BIOS should take based on ME state */
51static const char *me_bios_path_values[] = {
52 [ME_NORMAL_BIOS_PATH] = "Normal",
53 [ME_S3WAKE_BIOS_PATH] = "S3 Wake",
54 [ME_ERROR_BIOS_PATH] = "Error",
55 [ME_RECOVERY_BIOS_PATH] = "Recovery",
56 [ME_DISABLE_BIOS_PATH] = "Disable",
57 [ME_FIRMWARE_UPDATE_BIOS_PATH] = "Firmware Update",
58};
Aaron Durbin9aa031e2012-11-02 09:16:46 -050059static int intel_me_read_mbp(me_bios_payload *mbp_data, device_t dev);
Aaron Durbin76c37002012-10-30 09:03:43 -050060
61/* MMIO base address for MEI interface */
62static u32 mei_base_address;
63
64#if CONFIG_DEBUG_INTEL_ME
65static void mei_dump(void *ptr, int dword, int offset, const char *type)
66{
67 struct mei_csr *csr;
68
69 printk(BIOS_SPEW, "%-9s[%02x] : ", type, offset);
70
71 switch (offset) {
72 case MEI_H_CSR:
73 case MEI_ME_CSR_HA:
74 csr = ptr;
75 if (!csr) {
76 printk(BIOS_SPEW, "ERROR: 0x%08x\n", dword);
77 break;
78 }
79 printk(BIOS_SPEW, "cbd=%u cbrp=%02u cbwp=%02u ready=%u "
80 "reset=%u ig=%u is=%u ie=%u\n", csr->buffer_depth,
81 csr->buffer_read_ptr, csr->buffer_write_ptr,
82 csr->ready, csr->reset, csr->interrupt_generate,
83 csr->interrupt_status, csr->interrupt_enable);
84 break;
85 case MEI_ME_CB_RW:
86 case MEI_H_CB_WW:
87 printk(BIOS_SPEW, "CB: 0x%08x\n", dword);
88 break;
89 default:
90 printk(BIOS_SPEW, "0x%08x\n", offset);
91 break;
92 }
93}
94#else
95# define mei_dump(ptr,dword,offset,type) do {} while (0)
96#endif
97
98/*
99 * ME/MEI access helpers using memcpy to avoid aliasing.
100 */
101
102static inline void mei_read_dword_ptr(void *ptr, int offset)
103{
104 u32 dword = read32(mei_base_address + offset);
105 memcpy(ptr, &dword, sizeof(dword));
106 mei_dump(ptr, dword, offset, "READ");
107}
108
109static inline void mei_write_dword_ptr(void *ptr, int offset)
110{
111 u32 dword = 0;
112 memcpy(&dword, ptr, sizeof(dword));
113 write32(mei_base_address + offset, dword);
114 mei_dump(ptr, dword, offset, "WRITE");
115}
116
Aaron Durbin76c37002012-10-30 09:03:43 -0500117static inline void pci_read_dword_ptr(device_t dev, void *ptr, int offset)
118{
119 u32 dword = pci_read_config32(dev, offset);
120 memcpy(ptr, &dword, sizeof(dword));
121 mei_dump(ptr, dword, offset, "PCI READ");
122}
Aaron Durbin76c37002012-10-30 09:03:43 -0500123
124static inline void read_host_csr(struct mei_csr *csr)
125{
126 mei_read_dword_ptr(csr, MEI_H_CSR);
127}
128
129static inline void write_host_csr(struct mei_csr *csr)
130{
131 mei_write_dword_ptr(csr, MEI_H_CSR);
132}
133
134static inline void read_me_csr(struct mei_csr *csr)
135{
136 mei_read_dword_ptr(csr, MEI_ME_CSR_HA);
137}
138
139static inline void write_cb(u32 dword)
140{
141 write32(mei_base_address + MEI_H_CB_WW, dword);
142 mei_dump(NULL, dword, MEI_H_CB_WW, "WRITE");
143}
144
145static inline u32 read_cb(void)
146{
147 u32 dword = read32(mei_base_address + MEI_ME_CB_RW);
148 mei_dump(NULL, dword, MEI_ME_CB_RW, "READ");
149 return dword;
150}
151
152/* Wait for ME ready bit to be asserted */
153static int mei_wait_for_me_ready(void)
154{
155 struct mei_csr me;
156 unsigned try = ME_RETRY;
157
158 while (try--) {
159 read_me_csr(&me);
160 if (me.ready)
161 return 0;
162 udelay(ME_DELAY);
163 }
164
165 printk(BIOS_ERR, "ME: failed to become ready\n");
166 return -1;
167}
168
169static void mei_reset(void)
170{
171 struct mei_csr host;
172
173 if (mei_wait_for_me_ready() < 0)
174 return;
175
176 /* Reset host and ME circular buffers for next message */
177 read_host_csr(&host);
178 host.reset = 1;
179 host.interrupt_generate = 1;
180 write_host_csr(&host);
181
182 if (mei_wait_for_me_ready() < 0)
183 return;
184
185 /* Re-init and indicate host is ready */
186 read_host_csr(&host);
187 host.interrupt_generate = 1;
188 host.ready = 1;
189 host.reset = 0;
190 write_host_csr(&host);
191}
192
193static int mei_send_msg(struct mei_header *mei, struct mkhi_header *mkhi,
194 void *req_data)
195{
196 struct mei_csr host;
197 unsigned ndata, n;
198 u32 *data;
199
200 /* Number of dwords to write, ignoring MKHI */
201 ndata = mei->length >> 2;
202
203 /* Pad non-dword aligned request message length */
204 if (mei->length & 3)
205 ndata++;
206 if (!ndata) {
207 printk(BIOS_DEBUG, "ME: request does not include MKHI\n");
208 return -1;
209 }
210 ndata++; /* Add MEI header */
211
212 /*
213 * Make sure there is still room left in the circular buffer.
214 * Reset the buffer pointers if the requested message will not fit.
215 */
216 read_host_csr(&host);
217 if ((host.buffer_depth - host.buffer_write_ptr) < ndata) {
218 printk(BIOS_ERR, "ME: circular buffer full, resetting...\n");
219 mei_reset();
220 read_host_csr(&host);
221 }
222
223 /*
224 * This implementation does not handle splitting large messages
225 * across multiple transactions. Ensure the requested length
226 * will fit in the available circular buffer depth.
227 */
228 if ((host.buffer_depth - host.buffer_write_ptr) < ndata) {
229 printk(BIOS_ERR, "ME: message (%u) too large for buffer (%u)\n",
230 ndata + 2, host.buffer_depth);
231 return -1;
232 }
233
234 /* Write MEI header */
235 mei_write_dword_ptr(mei, MEI_H_CB_WW);
236 ndata--;
237
238 /* Write MKHI header */
239 mei_write_dword_ptr(mkhi, MEI_H_CB_WW);
240 ndata--;
241
242 /* Write message data */
243 data = req_data;
244 for (n = 0; n < ndata; ++n)
245 write_cb(*data++);
246
247 /* Generate interrupt to the ME */
248 read_host_csr(&host);
249 host.interrupt_generate = 1;
250 write_host_csr(&host);
251
252 /* Make sure ME is ready after sending request data */
253 return mei_wait_for_me_ready();
254}
255
256static int mei_recv_msg(struct mkhi_header *mkhi,
257 void *rsp_data, int rsp_bytes)
258{
259 struct mei_header mei_rsp;
260 struct mkhi_header mkhi_rsp;
261 struct mei_csr me, host;
262 unsigned ndata, n/*, me_data_len*/;
263 unsigned expected;
264 u32 *data;
265
266 /* Total number of dwords to read from circular buffer */
267 expected = (rsp_bytes + sizeof(mei_rsp) + sizeof(mkhi_rsp)) >> 2;
268 if (rsp_bytes & 3)
269 expected++;
270
271 /*
272 * The interrupt status bit does not appear to indicate that the
273 * message has actually been received. Instead we wait until the
274 * expected number of dwords are present in the circular buffer.
275 */
276 for (n = ME_RETRY; n; --n) {
277 read_me_csr(&me);
278 if ((me.buffer_write_ptr - me.buffer_read_ptr) >= expected)
279 break;
280 udelay(ME_DELAY);
281 }
282 if (!n) {
283 printk(BIOS_ERR, "ME: timeout waiting for data: expected "
284 "%u, available %u\n", expected,
285 me.buffer_write_ptr - me.buffer_read_ptr);
286 return -1;
287 }
288
289 /* Read and verify MEI response header from the ME */
290 mei_read_dword_ptr(&mei_rsp, MEI_ME_CB_RW);
291 if (!mei_rsp.is_complete) {
292 printk(BIOS_ERR, "ME: response is not complete\n");
293 return -1;
294 }
295
296 /* Handle non-dword responses and expect at least MKHI header */
297 ndata = mei_rsp.length >> 2;
298 if (mei_rsp.length & 3)
299 ndata++;
300 if (ndata != (expected - 1)) {
301 printk(BIOS_ERR, "ME: response is missing data %d != %d\n",
302 ndata, (expected - 1));
303 return -1;
304 }
305
306 /* Read and verify MKHI response header from the ME */
307 mei_read_dword_ptr(&mkhi_rsp, MEI_ME_CB_RW);
308 if (!mkhi_rsp.is_response ||
309 mkhi->group_id != mkhi_rsp.group_id ||
310 mkhi->command != mkhi_rsp.command) {
311 printk(BIOS_ERR, "ME: invalid response, group %u ?= %u,"
312 "command %u ?= %u, is_response %u\n", mkhi->group_id,
313 mkhi_rsp.group_id, mkhi->command, mkhi_rsp.command,
314 mkhi_rsp.is_response);
315 return -1;
316 }
317 ndata--; /* MKHI header has been read */
318
319 /* Make sure caller passed a buffer with enough space */
320 if (ndata != (rsp_bytes >> 2)) {
321 printk(BIOS_ERR, "ME: not enough room in response buffer: "
322 "%u != %u\n", ndata, rsp_bytes >> 2);
323 return -1;
324 }
325
326 /* Read response data from the circular buffer */
327 data = rsp_data;
328 for (n = 0; n < ndata; ++n)
329 *data++ = read_cb();
330
331 /* Tell the ME that we have consumed the response */
332 read_host_csr(&host);
333 host.interrupt_status = 1;
334 host.interrupt_generate = 1;
335 write_host_csr(&host);
336
337 return mei_wait_for_me_ready();
338}
339
340static inline int mei_sendrecv(struct mei_header *mei, struct mkhi_header *mkhi,
341 void *req_data, void *rsp_data, int rsp_bytes)
342{
343 if (mei_send_msg(mei, mkhi, req_data) < 0)
344 return -1;
345 if (mei_recv_msg(mkhi, rsp_data, rsp_bytes) < 0)
346 return -1;
347 return 0;
348}
349
Duncan Laurie1d048ca2013-05-01 11:30:24 -0700350#if (CONFIG_DEFAULT_CONSOLE_LOGLEVEL >= BIOS_DEBUG)
Aaron Durbin76c37002012-10-30 09:03:43 -0500351static inline void print_cap(const char *name, int state)
352{
353 printk(BIOS_DEBUG, "ME Capability: %-41s : %sabled\n",
354 name, state ? " en" : "dis");
355}
356
357static void me_print_fw_version(mbp_fw_version_name *vers_name)
358{
Aaron Durbinbe985242012-12-12 12:40:33 -0600359 if (!vers_name) {
Aaron Durbin76c37002012-10-30 09:03:43 -0500360 printk(BIOS_ERR, "ME: mbp missing version report\n");
361 return;
362 }
363
364 printk(BIOS_DEBUG, "ME: found version %d.%d.%d.%d\n",
365 vers_name->major_version, vers_name->minor_version,
366 vers_name->hotfix_version, vers_name->build_version);
367}
368
369/* Get ME Firmware Capabilities */
Aaron Durbinbe985242012-12-12 12:40:33 -0600370static int mkhi_get_fwcaps(mbp_mefwcaps *cap)
Aaron Durbin76c37002012-10-30 09:03:43 -0500371{
372 u32 rule_id = 0;
373 struct me_fwcaps cap_msg;
374 struct mkhi_header mkhi = {
375 .group_id = MKHI_GROUP_ID_FWCAPS,
376 .command = MKHI_FWCAPS_GET_RULE,
377 };
378 struct mei_header mei = {
379 .is_complete = 1,
380 .host_address = MEI_HOST_ADDRESS,
381 .client_address = MEI_ADDRESS_MKHI,
382 .length = sizeof(mkhi) + sizeof(rule_id),
383 };
384
385 /* Send request and wait for response */
386 if (mei_sendrecv(&mei, &mkhi, &rule_id, &cap_msg, sizeof(cap_msg))
387 < 0) {
388 printk(BIOS_ERR, "ME: GET FWCAPS message failed\n");
389 return -1;
390 }
391 *cap = cap_msg.caps_sku;
392 return 0;
393}
394
395/* Get ME Firmware Capabilities */
Aaron Durbinbe985242012-12-12 12:40:33 -0600396static void me_print_fwcaps(mbp_mefwcaps *cap)
Aaron Durbin76c37002012-10-30 09:03:43 -0500397{
Aaron Durbinbe985242012-12-12 12:40:33 -0600398 mbp_mefwcaps local_caps;
399 if (!cap) {
400 cap = &local_caps;
Aaron Durbin76c37002012-10-30 09:03:43 -0500401 printk(BIOS_ERR, "ME: mbp missing fwcaps report\n");
402 if (mkhi_get_fwcaps(cap))
403 return;
404 }
405
406 print_cap("Full Network manageability", cap->full_net);
407 print_cap("Regular Network manageability", cap->std_net);
408 print_cap("Manageability", cap->manageability);
Aaron Durbin76c37002012-10-30 09:03:43 -0500409 print_cap("IntelR Anti-Theft (AT)", cap->intel_at);
410 print_cap("IntelR Capability Licensing Service (CLS)", cap->intel_cls);
411 print_cap("IntelR Power Sharing Technology (MPC)", cap->intel_mpc);
412 print_cap("ICC Over Clocking", cap->icc_over_clocking);
413 print_cap("Protected Audio Video Path (PAVP)", cap->pavp);
414 print_cap("IPV6", cap->ipv6);
415 print_cap("KVM Remote Control (KVM)", cap->kvm);
416 print_cap("Outbreak Containment Heuristic (OCH)", cap->och);
417 print_cap("Virtual LAN (VLAN)", cap->vlan);
418 print_cap("TLS", cap->tls);
419 print_cap("Wireless LAN (WLAN)", cap->wlan);
420}
421#endif
422
423#if CONFIG_CHROMEOS && 0 /* DISABLED */
424/* Tell ME to issue a global reset */
425static int mkhi_global_reset(void)
426{
427 struct me_global_reset reset = {
428 .request_origin = GLOBAL_RESET_BIOS_POST,
429 .reset_type = CBM_RR_GLOBAL_RESET,
430 };
431 struct mkhi_header mkhi = {
432 .group_id = MKHI_GROUP_ID_CBM,
433 .command = MKHI_GLOBAL_RESET,
434 };
435 struct mei_header mei = {
436 .is_complete = 1,
437 .length = sizeof(mkhi) + sizeof(reset),
438 .host_address = MEI_HOST_ADDRESS,
439 .client_address = MEI_ADDRESS_MKHI,
440 };
441
442 /* Send request and wait for response */
443 printk(BIOS_NOTICE, "ME: %s\n", __FUNCTION__);
444 if (mei_sendrecv(&mei, &mkhi, &reset, NULL, 0) < 0) {
445 /* No response means reset will happen shortly... */
446 hlt();
447 }
448
449 /* If the ME responded it rejected the reset request */
450 printk(BIOS_ERR, "ME: Global Reset failed\n");
451 return -1;
452}
453#endif
454
Aaron Durbin76c37002012-10-30 09:03:43 -0500455/* Send END OF POST message to the ME */
456static int mkhi_end_of_post(void)
457{
458 struct mkhi_header mkhi = {
459 .group_id = MKHI_GROUP_ID_GEN,
460 .command = MKHI_END_OF_POST,
461 };
462 struct mei_header mei = {
463 .is_complete = 1,
464 .host_address = MEI_HOST_ADDRESS,
465 .client_address = MEI_ADDRESS_MKHI,
466 .length = sizeof(mkhi),
467 };
468
469 u32 eop_ack;
470
471 /* Send request and wait for response */
472 printk(BIOS_NOTICE, "ME: %s\n", __FUNCTION__);
473 if (mei_sendrecv(&mei, &mkhi, NULL, &eop_ack, sizeof(eop_ack)) < 0) {
474 printk(BIOS_ERR, "ME: END OF POST message failed\n");
475 return -1;
476 }
477
478 printk(BIOS_INFO, "ME: END OF POST message successful (%d)\n", eop_ack);
479 return 0;
480}
481
Aaron Durbin76c37002012-10-30 09:03:43 -0500482/* Determine the path that we should take based on ME status */
483static me_bios_path intel_me_path(device_t dev)
484{
485 me_bios_path path = ME_DISABLE_BIOS_PATH;
486 struct me_hfs hfs;
Aaron Durbin9aa031e2012-11-02 09:16:46 -0500487 struct me_hfs2 hfs2;
Aaron Durbin76c37002012-10-30 09:03:43 -0500488
489#if CONFIG_HAVE_ACPI_RESUME
490 /* S3 wake skips all MKHI messages */
491 if (acpi_slp_type == 3) {
492 return ME_S3WAKE_BIOS_PATH;
493 }
494#endif
495
496 pci_read_dword_ptr(dev, &hfs, PCI_ME_HFS);
Aaron Durbin9aa031e2012-11-02 09:16:46 -0500497 pci_read_dword_ptr(dev, &hfs2, PCI_ME_HFS2);
Aaron Durbin76c37002012-10-30 09:03:43 -0500498
499 /* Check and dump status */
Aaron Durbin9aa031e2012-11-02 09:16:46 -0500500 intel_me_status(&hfs, &hfs2);
Aaron Durbin76c37002012-10-30 09:03:43 -0500501
502 /* Check Current Working State */
503 switch (hfs.working_state) {
504 case ME_HFS_CWS_NORMAL:
505 path = ME_NORMAL_BIOS_PATH;
506 break;
507 case ME_HFS_CWS_REC:
508 path = ME_RECOVERY_BIOS_PATH;
509 break;
510 default:
511 path = ME_DISABLE_BIOS_PATH;
512 break;
513 }
514
515 /* Check Current Operation Mode */
516 switch (hfs.operation_mode) {
517 case ME_HFS_MODE_NORMAL:
518 break;
519 case ME_HFS_MODE_DEBUG:
520 case ME_HFS_MODE_DIS:
521 case ME_HFS_MODE_OVER_JMPR:
522 case ME_HFS_MODE_OVER_MEI:
523 default:
524 path = ME_DISABLE_BIOS_PATH;
525 break;
526 }
527
528 /* Check for any error code and valid firmware and MBP */
529 if (hfs.error_code || hfs.fpt_bad)
530 path = ME_ERROR_BIOS_PATH;
531
532 /* Check if the MBP is ready */
Aaron Durbin9aa031e2012-11-02 09:16:46 -0500533 if (!hfs2.mbp_rdy) {
Aaron Durbin76c37002012-10-30 09:03:43 -0500534 printk(BIOS_CRIT, "%s: mbp is not ready!\n",
535 __FUNCTION__);
536 path = ME_ERROR_BIOS_PATH;
537 }
538
539#if CONFIG_ELOG
540 if (path != ME_NORMAL_BIOS_PATH) {
541 struct elog_event_data_me_extended data = {
542 .current_working_state = hfs.working_state,
543 .operation_state = hfs.operation_state,
544 .operation_mode = hfs.operation_mode,
545 .error_code = hfs.error_code,
Aaron Durbin9aa031e2012-11-02 09:16:46 -0500546 .progress_code = hfs2.progress_code,
547 .current_pmevent = hfs2.current_pmevent,
548 .current_state = hfs2.current_state,
Aaron Durbin76c37002012-10-30 09:03:43 -0500549 };
550 elog_add_event_byte(ELOG_TYPE_MANAGEMENT_ENGINE, path);
551 elog_add_event_raw(ELOG_TYPE_MANAGEMENT_ENGINE_EXT,
552 &data, sizeof(data));
553 }
554#endif
555
556 return path;
557}
558
559/* Prepare ME for MEI messages */
560static int intel_mei_setup(device_t dev)
561{
562 struct resource *res;
563 struct mei_csr host;
564 u32 reg32;
565
566 /* Find the MMIO base for the ME interface */
567 res = find_resource(dev, PCI_BASE_ADDRESS_0);
568 if (!res || res->base == 0 || res->size == 0) {
569 printk(BIOS_DEBUG, "ME: MEI resource not present!\n");
570 return -1;
571 }
572 mei_base_address = res->base;
573
574 /* Ensure Memory and Bus Master bits are set */
575 reg32 = pci_read_config32(dev, PCI_COMMAND);
576 reg32 |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
577 pci_write_config32(dev, PCI_COMMAND, reg32);
578
579 /* Clean up status for next message */
580 read_host_csr(&host);
581 host.interrupt_generate = 1;
582 host.ready = 1;
583 host.reset = 0;
584 write_host_csr(&host);
585
586 return 0;
587}
588
589/* Read the Extend register hash of ME firmware */
590static int intel_me_extend_valid(device_t dev)
591{
592 struct me_heres status;
593 u32 extend[8] = {0};
594 int i, count = 0;
595
596 pci_read_dword_ptr(dev, &status, PCI_ME_HERES);
597 if (!status.extend_feature_present) {
598 printk(BIOS_ERR, "ME: Extend Feature not present\n");
599 return -1;
600 }
601
602 if (!status.extend_reg_valid) {
603 printk(BIOS_ERR, "ME: Extend Register not valid\n");
604 return -1;
605 }
606
607 switch (status.extend_reg_algorithm) {
608 case PCI_ME_EXT_SHA1:
609 count = 5;
610 printk(BIOS_DEBUG, "ME: Extend SHA-1: ");
611 break;
612 case PCI_ME_EXT_SHA256:
613 count = 8;
614 printk(BIOS_DEBUG, "ME: Extend SHA-256: ");
615 break;
616 default:
617 printk(BIOS_ERR, "ME: Extend Algorithm %d unknown\n",
618 status.extend_reg_algorithm);
619 return -1;
620 }
621
622 for (i = 0; i < count; ++i) {
623 extend[i] = pci_read_config32(dev, PCI_ME_HER(i));
624 printk(BIOS_DEBUG, "%08x", extend[i]);
625 }
626 printk(BIOS_DEBUG, "\n");
627
628#if CONFIG_CHROMEOS
629 /* Save hash in NVS for the OS to verify */
630 chromeos_set_me_hash(extend, count);
631#endif
632
633 return 0;
634}
635
636/* Hide the ME virtual PCI devices */
637static void intel_me_hide(device_t dev)
638{
Duncan Laurie1d048ca2013-05-01 11:30:24 -0700639 /* Make sure IO is disabled */
640 u32 reg32 = pci_read_config32(dev, PCI_COMMAND);
641 reg32 &= ~(PCI_COMMAND_MASTER |
642 PCI_COMMAND_MEMORY | PCI_COMMAND_IO);
643 pci_write_config32(dev, PCI_COMMAND, reg32);
644
Aaron Durbin76c37002012-10-30 09:03:43 -0500645 dev->enabled = 0;
646 pch_enable(dev);
647}
648
649/* Check whether ME is present and do basic init */
650static void intel_me_init(device_t dev)
651{
652 me_bios_path path = intel_me_path(dev);
653 me_bios_payload mbp_data;
654
655 /* Do initial setup and determine the BIOS path */
656 printk(BIOS_NOTICE, "ME: BIOS path: %s\n", me_bios_path_values[path]);
657
Aaron Durbin9aa031e2012-11-02 09:16:46 -0500658 if (path == ME_S3WAKE_BIOS_PATH) {
Aaron Durbin76c37002012-10-30 09:03:43 -0500659 intel_me_hide(dev);
Aaron Durbin9aa031e2012-11-02 09:16:46 -0500660 return;
661 } else if (path == ME_NORMAL_BIOS_PATH) {
Aaron Durbin76c37002012-10-30 09:03:43 -0500662 /* Validate the extend register */
Aaron Durbin9aa031e2012-11-02 09:16:46 -0500663 /* FIXME: force recovery mode on failure. */
664 intel_me_extend_valid(dev);
665 }
Aaron Durbin76c37002012-10-30 09:03:43 -0500666
Aaron Durbinbe985242012-12-12 12:40:33 -0600667 memset(&mbp_data, 0, sizeof(mbp_data));
668
Aaron Durbin9aa031e2012-11-02 09:16:46 -0500669 /*
670 * According to the ME9 BWG, BIOS is required to fetch MBP data in
671 * all boot flows except S3 Resume.
672 */
Aaron Durbin76c37002012-10-30 09:03:43 -0500673
Aaron Durbin9aa031e2012-11-02 09:16:46 -0500674 /* Prepare MEI MMIO interface */
675 if (intel_mei_setup(dev) < 0)
676 return;
Aaron Durbin76c37002012-10-30 09:03:43 -0500677
Duncan Laurie144f7b22013-05-01 11:27:58 -0700678 if (intel_me_read_mbp(&mbp_data, dev))
Aaron Durbin9aa031e2012-11-02 09:16:46 -0500679 return;
Aaron Durbin76c37002012-10-30 09:03:43 -0500680
681#if (CONFIG_DEFAULT_CONSOLE_LOGLEVEL >= BIOS_DEBUG)
Aaron Durbinbe985242012-12-12 12:40:33 -0600682 me_print_fw_version(mbp_data.fw_version_name);
683 me_print_fwcaps(mbp_data.fw_capabilities);
Duncan Laurie144f7b22013-05-01 11:27:58 -0700684
685 if (mbp_data.plat_time) {
686 printk(BIOS_DEBUG, "ME: Wake Event to ME Reset: %u ms\n",
687 mbp_data.plat_time->wake_event_mrst_time_ms);
688 printk(BIOS_DEBUG, "ME: ME Reset to Platform Reset: %u ms\n",
689 mbp_data.plat_time->mrst_pltrst_time_ms);
690 printk(BIOS_DEBUG, "ME: Platform Reset to CPU Reset: %u ms\n",
691 mbp_data.plat_time->pltrst_cpurst_time_ms);
692 }
Aaron Durbin76c37002012-10-30 09:03:43 -0500693#endif
694
Duncan Laurie1d048ca2013-05-01 11:30:24 -0700695 /* Lock down and hide Management Engine */
696 mkhi_end_of_post();
697 intel_me_hide(dev);
Aaron Durbin76c37002012-10-30 09:03:43 -0500698}
699
700static void set_subsystem(device_t dev, unsigned vendor, unsigned device)
701{
702 if (!vendor || !device) {
703 pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
704 pci_read_config32(dev, PCI_VENDOR_ID));
705 } else {
706 pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
707 ((device & 0xffff) << 16) | (vendor & 0xffff));
708 }
709}
710
711static struct pci_operations pci_ops = {
712 .set_subsystem = set_subsystem,
713};
714
715static struct device_operations device_ops = {
716 .read_resources = pci_dev_read_resources,
717 .set_resources = pci_dev_set_resources,
718 .enable_resources = pci_dev_enable_resources,
719 .init = intel_me_init,
720 .scan_bus = scan_static_bus,
721 .ops_pci = &pci_ops,
722};
723
Duncan Laurie26e7dd72012-12-19 09:12:31 -0800724static const unsigned short pci_device_ids[] = {
725 0x8c3a, /* Mobile */
726 0x9c3a, /* Low Power */
727 0
728};
729
Aaron Durbin76c37002012-10-30 09:03:43 -0500730static const struct pci_driver intel_me __pci_driver = {
731 .ops = &device_ops,
732 .vendor = PCI_VENDOR_ID_INTEL,
Duncan Laurie26e7dd72012-12-19 09:12:31 -0800733 .devices= pci_device_ids,
Aaron Durbin76c37002012-10-30 09:03:43 -0500734};
735
736/******************************************************************************
737 * */
738static u32 me_to_host_words_pending(void)
739{
740 struct mei_csr me;
741 read_me_csr(&me);
742 if (!me.ready)
743 return 0;
744 return (me.buffer_write_ptr - me.buffer_read_ptr) &
745 (me.buffer_depth - 1);
746}
747
748#if 0
749/* This function is not yet being used, keep it in for the future. */
750static u32 host_to_me_words_room(void)
751{
752 struct mei_csr csr;
753
754 read_me_csr(&csr);
755 if (!csr.ready)
756 return 0;
757
758 read_host_csr(&csr);
759 return (csr.buffer_read_ptr - csr.buffer_write_ptr - 1) &
760 (csr.buffer_depth - 1);
761}
762#endif
Aaron Durbin9aa031e2012-11-02 09:16:46 -0500763
764/*
765 * mbp give up routine. This path is taken if hfs.mpb_rdy is 0 or the read
766 * state machine on the BIOS end doesn't match the ME's state machine.
767 */
768static void intel_me_mbp_give_up(device_t dev)
769{
770 u32 reg32;
771 struct mei_csr csr;
772
773 reg32 = PCI_ME_MBP_GIVE_UP;
Aaron Durbinb37d1fb2013-02-25 10:51:52 -0600774 pci_write_config32(dev, PCI_ME_H_GS2, reg32);
Aaron Durbin9aa031e2012-11-02 09:16:46 -0500775 read_host_csr(&csr);
776 csr.reset = 1;
777 csr.interrupt_generate = 1;
778 write_host_csr(&csr);
779}
780
Aaron Durbinbe985242012-12-12 12:40:33 -0600781struct mbp_payload {
782 mbp_header header;
783 u32 data[0];
784};
785
Aaron Durbin76c37002012-10-30 09:03:43 -0500786/*
787 * mbp seems to be following its own flow, let's retrieve it in a dedicated
788 * function.
789 */
Aaron Durbin9aa031e2012-11-02 09:16:46 -0500790static int intel_me_read_mbp(me_bios_payload *mbp_data, device_t dev)
Aaron Durbin76c37002012-10-30 09:03:43 -0500791{
792 mbp_header mbp_hdr;
Aaron Durbin76c37002012-10-30 09:03:43 -0500793 u32 me2host_pending;
Aaron Durbin76c37002012-10-30 09:03:43 -0500794 struct mei_csr host;
Aaron Durbin9aa031e2012-11-02 09:16:46 -0500795 struct me_hfs2 hfs2;
796 int count;
Aaron Durbinbe985242012-12-12 12:40:33 -0600797 struct mbp_payload *mbp;
798 int i;
Aaron Durbin9aa031e2012-11-02 09:16:46 -0500799
800 pci_read_dword_ptr(dev, &hfs2, PCI_ME_HFS2);
801
802 if (!hfs2.mbp_rdy) {
803 printk(BIOS_ERR, "ME: MBP not ready\n");
804 goto mbp_failure;
805 }
Aaron Durbin76c37002012-10-30 09:03:43 -0500806
807 me2host_pending = me_to_host_words_pending();
808 if (!me2host_pending) {
809 printk(BIOS_ERR, "ME: no mbp data!\n");
Aaron Durbin9aa031e2012-11-02 09:16:46 -0500810 goto mbp_failure;
Aaron Durbin76c37002012-10-30 09:03:43 -0500811 }
812
813 /* we know for sure that at least the header is there */
814 mei_read_dword_ptr(&mbp_hdr, MEI_ME_CB_RW);
815
816 if ((mbp_hdr.num_entries > (mbp_hdr.mbp_size / 2)) ||
817 (me2host_pending < mbp_hdr.mbp_size)) {
818 printk(BIOS_ERR, "ME: mbp of %d entries, total size %d words"
819 " buffer contains %d words\n",
820 mbp_hdr.num_entries, mbp_hdr.mbp_size,
821 me2host_pending);
Aaron Durbin9aa031e2012-11-02 09:16:46 -0500822 goto mbp_failure;
Aaron Durbin76c37002012-10-30 09:03:43 -0500823 }
Aaron Durbinbe985242012-12-12 12:40:33 -0600824 mbp = malloc(mbp_hdr.mbp_size * sizeof(u32));
825 if (!mbp)
826 goto mbp_failure;
Aaron Durbin76c37002012-10-30 09:03:43 -0500827
Aaron Durbinbe985242012-12-12 12:40:33 -0600828 mbp->header = mbp_hdr;
Aaron Durbin76c37002012-10-30 09:03:43 -0500829 me2host_pending--;
Aaron Durbin76c37002012-10-30 09:03:43 -0500830
Aaron Durbinbe985242012-12-12 12:40:33 -0600831 i = 0;
832 while (i != me2host_pending) {
833 mei_read_dword_ptr(&mbp->data[i], MEI_ME_CB_RW);
834 i++;
Aaron Durbin76c37002012-10-30 09:03:43 -0500835 }
836
Aaron Durbinbe985242012-12-12 12:40:33 -0600837 /* Signal to the ME that the host has finished reading the MBP. */
Aaron Durbin76c37002012-10-30 09:03:43 -0500838 read_host_csr(&host);
839 host.interrupt_generate = 1;
840 write_host_csr(&host);
841
Aaron Durbinbe985242012-12-12 12:40:33 -0600842 /* Wait for the mbp_cleared indicator. */
Aaron Durbin9aa031e2012-11-02 09:16:46 -0500843 for (count = ME_RETRY; count > 0; --count) {
844 pci_read_dword_ptr(dev, &hfs2, PCI_ME_HFS2);
845 if (hfs2.mbp_cleared)
846 break;
847 udelay(ME_DELAY);
848 }
849
850 if (count == 0) {
851 printk(BIOS_WARNING, "ME: Timeout waiting for mbp_cleared\n");
852 intel_me_mbp_give_up(dev);
Aaron Durbin76c37002012-10-30 09:03:43 -0500853 }
854
Aaron Durbinbe985242012-12-12 12:40:33 -0600855 /* Dump out the MBP contents. */
856#if (CONFIG_DEFAULT_CONSOLE_LOGLEVEL >= BIOS_DEBUG)
857 printk(BIOS_INFO, "ME MBP: Header: items: %d, size dw: %d\n",
858 mbp->header.num_entries, mbp->header.mbp_size);
859 for (i = 0; i < mbp->header.mbp_size - 1; i++) {
860 printk(BIOS_INFO, "ME MBP: %04x: 0x%08x\n", i, mbp->data[i]);
861 }
862#endif
863
864 #define ASSIGN_FIELD_PTR(field_,val_) \
865 { \
866 mbp_data->field_ = (typeof(mbp_data->field_))(void *)val_; \
867 break; \
868 }
869 /* Setup the pointers in the me_bios_payload structure. */
870 for (i = 0; i < mbp->header.mbp_size - 1;) {
871 mbp_item_header *item = (void *)&mbp->data[i];
872
873 switch(MBP_MAKE_IDENT(item->app_id, item->item_id)) {
874 case MBP_IDENT(KERNEL, FW_VER):
875 ASSIGN_FIELD_PTR(fw_version_name, &mbp->data[i+1]);
876
877 case MBP_IDENT(ICC, PROFILE):
878 ASSIGN_FIELD_PTR(icc_profile, &mbp->data[i+1]);
879
880 case MBP_IDENT(INTEL_AT, STATE):
881 ASSIGN_FIELD_PTR(at_state, &mbp->data[i+1]);
882
883 case MBP_IDENT(KERNEL, FW_CAP):
884 ASSIGN_FIELD_PTR(fw_capabilities, &mbp->data[i+1]);
885
886 case MBP_IDENT(KERNEL, ROM_BIST):
887 ASSIGN_FIELD_PTR(rom_bist_data, &mbp->data[i+1]);
888
889 case MBP_IDENT(KERNEL, PLAT_KEY):
890 ASSIGN_FIELD_PTR(platform_key, &mbp->data[i+1]);
891
892 case MBP_IDENT(KERNEL, FW_TYPE):
893 ASSIGN_FIELD_PTR(fw_plat_type, &mbp->data[i+1]);
894
895 case MBP_IDENT(KERNEL, MFS_FAILURE):
896 ASSIGN_FIELD_PTR(mfsintegrity, &mbp->data[i+1]);
897
Duncan Laurie144f7b22013-05-01 11:27:58 -0700898 case MBP_IDENT(KERNEL, PLAT_TIME):
899 ASSIGN_FIELD_PTR(plat_time, &mbp->data[i+1]);
900
901 case MBP_IDENT(NFC, SUPPORT_DATA):
902 ASSIGN_FIELD_PTR(nfc_data, &mbp->data[i+1]);
903
Aaron Durbinbe985242012-12-12 12:40:33 -0600904 default:
905 printk(BIOS_ERR, "ME MBP: unknown item 0x%x @ dw offset 0x%x\n",
906 mbp->data[i], i);
907 break;
908 }
909 i += item->length;
910 }
911 #undef ASSIGN_FIELD_PTR
912
Aaron Durbin76c37002012-10-30 09:03:43 -0500913 return 0;
Aaron Durbin9aa031e2012-11-02 09:16:46 -0500914
915mbp_failure:
916 intel_me_mbp_give_up(dev);
917 return -1;
Aaron Durbin76c37002012-10-30 09:03:43 -0500918}