blob: a1625e81b0972a87fab6fa7c88457fd9b8608b3f [file] [log] [blame]
Angel Pons182dbde2020-04-02 23:49:05 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Aaron Durbin76c37002012-10-30 09:03:43 -05002
3/*
4 * This is a ramstage driver for the Intel Management Engine found in the
5 * 6-series chipset. It handles the required boot-time messages over the
6 * MMIO-based Management Engine Interface to tell the ME that the BIOS is
7 * finished with POST. Additional messages are defined for debug but are
8 * not used unless the console loglevel is high enough.
9 */
10
Furquan Shaikh76cedd22020-05-02 10:24:23 -070011#include <acpi/acpi.h>
Kyösti Mälkki13f66502019-03-03 08:01:05 +020012#include <device/mmio.h>
Kyösti Mälkkif1b58b72019-03-01 13:43:02 +020013#include <device/pci_ops.h>
Aaron Durbin76c37002012-10-30 09:03:43 -050014#include <console/console.h>
Stefan Reinauer24d1d4b2013-03-21 11:51:41 -070015#include <device/device.h>
16#include <device/pci.h>
Aaron Durbin76c37002012-10-30 09:03:43 -050017#include <device/pci_ids.h>
18#include <device/pci_def.h>
19#include <string.h>
20#include <delay.h>
21#include <elog.h>
Elyes HAOUAS400f9ca2019-06-23 07:01:22 +020022#include <stdlib.h>
Aaron Durbin76c37002012-10-30 09:03:43 -050023
Kyösti Mälkki12b121c2019-08-18 16:33:39 +030024#include "chip.h"
Aaron Durbin76c37002012-10-30 09:03:43 -050025#include "me.h"
26#include "pch.h"
27
Aaron Durbin76c37002012-10-30 09:03:43 -050028#include <vendorcode/google/chromeos/chromeos.h>
Aaron Durbin76c37002012-10-30 09:03:43 -050029
Aaron Durbin76c37002012-10-30 09:03:43 -050030/* Path that the BIOS should take based on ME state */
Angel Pons10274d82021-02-23 14:19:28 +010031static const char *const me_bios_path_values[] = {
Aaron Durbin76c37002012-10-30 09:03:43 -050032 [ME_NORMAL_BIOS_PATH] = "Normal",
33 [ME_S3WAKE_BIOS_PATH] = "S3 Wake",
34 [ME_ERROR_BIOS_PATH] = "Error",
35 [ME_RECOVERY_BIOS_PATH] = "Recovery",
36 [ME_DISABLE_BIOS_PATH] = "Disable",
37 [ME_FIRMWARE_UPDATE_BIOS_PATH] = "Firmware Update",
38};
Aaron Durbin76c37002012-10-30 09:03:43 -050039
40/* MMIO base address for MEI interface */
Angel Ponsa3492d72021-02-23 14:12:25 +010041static u8 *mei_base_address;
Aaron Durbin76c37002012-10-30 09:03:43 -050042
Aaron Durbin76c37002012-10-30 09:03:43 -050043static void mei_dump(void *ptr, int dword, int offset, const char *type)
44{
45 struct mei_csr *csr;
46
Kyösti Mälkkic86fc8e2019-11-06 06:32:27 +020047 if (!CONFIG(DEBUG_INTEL_ME))
48 return;
49
Aaron Durbin76c37002012-10-30 09:03:43 -050050 printk(BIOS_SPEW, "%-9s[%02x] : ", type, offset);
51
52 switch (offset) {
53 case MEI_H_CSR:
54 case MEI_ME_CSR_HA:
55 csr = ptr;
56 if (!csr) {
57 printk(BIOS_SPEW, "ERROR: 0x%08x\n", dword);
58 break;
59 }
60 printk(BIOS_SPEW, "cbd=%u cbrp=%02u cbwp=%02u ready=%u "
61 "reset=%u ig=%u is=%u ie=%u\n", csr->buffer_depth,
62 csr->buffer_read_ptr, csr->buffer_write_ptr,
63 csr->ready, csr->reset, csr->interrupt_generate,
64 csr->interrupt_status, csr->interrupt_enable);
65 break;
66 case MEI_ME_CB_RW:
67 case MEI_H_CB_WW:
68 printk(BIOS_SPEW, "CB: 0x%08x\n", dword);
69 break;
70 default:
71 printk(BIOS_SPEW, "0x%08x\n", offset);
72 break;
73 }
74}
Aaron Durbin76c37002012-10-30 09:03:43 -050075
76/*
77 * ME/MEI access helpers using memcpy to avoid aliasing.
78 */
79
80static inline void mei_read_dword_ptr(void *ptr, int offset)
81{
Angel Ponsa3492d72021-02-23 14:12:25 +010082 u32 dword = read32(mei_base_address + offset);
Aaron Durbin76c37002012-10-30 09:03:43 -050083 memcpy(ptr, &dword, sizeof(dword));
84 mei_dump(ptr, dword, offset, "READ");
85}
86
87static inline void mei_write_dword_ptr(void *ptr, int offset)
88{
89 u32 dword = 0;
90 memcpy(&dword, ptr, sizeof(dword));
Angel Ponsa3492d72021-02-23 14:12:25 +010091 write32(mei_base_address + offset, dword);
Aaron Durbin76c37002012-10-30 09:03:43 -050092 mei_dump(ptr, dword, offset, "WRITE");
93}
94
Aaron Durbin76c37002012-10-30 09:03:43 -050095static inline void read_host_csr(struct mei_csr *csr)
96{
97 mei_read_dword_ptr(csr, MEI_H_CSR);
98}
99
100static inline void write_host_csr(struct mei_csr *csr)
101{
102 mei_write_dword_ptr(csr, MEI_H_CSR);
103}
104
105static inline void read_me_csr(struct mei_csr *csr)
106{
107 mei_read_dword_ptr(csr, MEI_ME_CSR_HA);
108}
109
110static inline void write_cb(u32 dword)
111{
Angel Ponsa3492d72021-02-23 14:12:25 +0100112 write32(mei_base_address + MEI_H_CB_WW, dword);
Aaron Durbin76c37002012-10-30 09:03:43 -0500113 mei_dump(NULL, dword, MEI_H_CB_WW, "WRITE");
114}
115
116static inline u32 read_cb(void)
117{
Angel Ponsa3492d72021-02-23 14:12:25 +0100118 u32 dword = read32(mei_base_address + MEI_ME_CB_RW);
Aaron Durbin76c37002012-10-30 09:03:43 -0500119 mei_dump(NULL, dword, MEI_ME_CB_RW, "READ");
120 return dword;
121}
122
123/* Wait for ME ready bit to be asserted */
124static int mei_wait_for_me_ready(void)
125{
126 struct mei_csr me;
Martin Rothff744bf2019-10-23 21:46:03 -0600127 unsigned int try = ME_RETRY;
Aaron Durbin76c37002012-10-30 09:03:43 -0500128
129 while (try--) {
130 read_me_csr(&me);
131 if (me.ready)
132 return 0;
133 udelay(ME_DELAY);
134 }
135
136 printk(BIOS_ERR, "ME: failed to become ready\n");
137 return -1;
138}
139
140static void mei_reset(void)
141{
142 struct mei_csr host;
143
144 if (mei_wait_for_me_ready() < 0)
145 return;
146
147 /* Reset host and ME circular buffers for next message */
148 read_host_csr(&host);
149 host.reset = 1;
150 host.interrupt_generate = 1;
151 write_host_csr(&host);
152
153 if (mei_wait_for_me_ready() < 0)
154 return;
155
156 /* Re-init and indicate host is ready */
157 read_host_csr(&host);
158 host.interrupt_generate = 1;
159 host.ready = 1;
160 host.reset = 0;
161 write_host_csr(&host);
162}
163
Duncan Laurie2017b4a2013-08-08 15:07:12 -0700164static int mei_send_packet(struct mei_header *mei, void *req_data)
Aaron Durbin76c37002012-10-30 09:03:43 -0500165{
166 struct mei_csr host;
Martin Rothff744bf2019-10-23 21:46:03 -0600167 unsigned int ndata, n;
Aaron Durbin76c37002012-10-30 09:03:43 -0500168 u32 *data;
169
Duncan Laurie2017b4a2013-08-08 15:07:12 -0700170 /* Number of dwords to write */
Aaron Durbin76c37002012-10-30 09:03:43 -0500171 ndata = mei->length >> 2;
172
173 /* Pad non-dword aligned request message length */
174 if (mei->length & 3)
175 ndata++;
176 if (!ndata) {
Duncan Laurie2017b4a2013-08-08 15:07:12 -0700177 printk(BIOS_DEBUG, "ME: request has no data\n");
Aaron Durbin76c37002012-10-30 09:03:43 -0500178 return -1;
179 }
180 ndata++; /* Add MEI header */
181
182 /*
183 * Make sure there is still room left in the circular buffer.
184 * Reset the buffer pointers if the requested message will not fit.
185 */
186 read_host_csr(&host);
187 if ((host.buffer_depth - host.buffer_write_ptr) < ndata) {
188 printk(BIOS_ERR, "ME: circular buffer full, resetting...\n");
189 mei_reset();
190 read_host_csr(&host);
191 }
192
Duncan Laurie2017b4a2013-08-08 15:07:12 -0700193 /* Ensure the requested length will fit in the circular buffer. */
Aaron Durbin76c37002012-10-30 09:03:43 -0500194 if ((host.buffer_depth - host.buffer_write_ptr) < ndata) {
195 printk(BIOS_ERR, "ME: message (%u) too large for buffer (%u)\n",
196 ndata + 2, host.buffer_depth);
197 return -1;
198 }
199
200 /* Write MEI header */
201 mei_write_dword_ptr(mei, MEI_H_CB_WW);
202 ndata--;
203
Aaron Durbin76c37002012-10-30 09:03:43 -0500204 /* Write message data */
205 data = req_data;
206 for (n = 0; n < ndata; ++n)
207 write_cb(*data++);
208
209 /* Generate interrupt to the ME */
210 read_host_csr(&host);
211 host.interrupt_generate = 1;
212 write_host_csr(&host);
213
214 /* Make sure ME is ready after sending request data */
215 return mei_wait_for_me_ready();
216}
217
Duncan Laurie2017b4a2013-08-08 15:07:12 -0700218static int mei_send_data(u8 me_address, u8 host_address,
219 void *req_data, int req_bytes)
220{
221 struct mei_header header = {
222 .client_address = me_address,
223 .host_address = host_address,
224 };
225 struct mei_csr host;
226 int current = 0;
227 u8 *req_ptr = req_data;
228
229 while (!header.is_complete) {
230 int remain = req_bytes - current;
231 int buf_len;
232
233 read_host_csr(&host);
234 buf_len = host.buffer_depth - host.buffer_write_ptr;
235
236 if (buf_len > remain) {
237 /* Send all remaining data as final message */
238 header.length = req_bytes - current;
239 header.is_complete = 1;
240 } else {
241 /* Send as much data as the buffer can hold */
242 header.length = buf_len;
243 }
244
245 mei_send_packet(&header, req_ptr);
246
247 req_ptr += header.length;
248 current += header.length;
249 }
250
251 return 0;
252}
253
254static int mei_send_header(u8 me_address, u8 host_address,
255 void *header, int header_len, int complete)
256{
257 struct mei_header mei = {
258 .client_address = me_address,
259 .host_address = host_address,
260 .length = header_len,
261 .is_complete = complete,
262 };
263 return mei_send_packet(&mei, header);
264}
265
266static int mei_recv_msg(void *header, int header_bytes,
Aaron Durbin76c37002012-10-30 09:03:43 -0500267 void *rsp_data, int rsp_bytes)
268{
269 struct mei_header mei_rsp;
Aaron Durbin76c37002012-10-30 09:03:43 -0500270 struct mei_csr me, host;
Martin Rothff744bf2019-10-23 21:46:03 -0600271 unsigned int ndata, n;
272 unsigned int expected;
Aaron Durbin76c37002012-10-30 09:03:43 -0500273 u32 *data;
274
275 /* Total number of dwords to read from circular buffer */
Duncan Laurie2017b4a2013-08-08 15:07:12 -0700276 expected = (rsp_bytes + sizeof(mei_rsp) + header_bytes) >> 2;
Aaron Durbin76c37002012-10-30 09:03:43 -0500277 if (rsp_bytes & 3)
278 expected++;
279
Duncan Laurie2017b4a2013-08-08 15:07:12 -0700280 if (mei_wait_for_me_ready() < 0)
281 return -1;
282
Aaron Durbin76c37002012-10-30 09:03:43 -0500283 /*
284 * The interrupt status bit does not appear to indicate that the
285 * message has actually been received. Instead we wait until the
286 * expected number of dwords are present in the circular buffer.
287 */
288 for (n = ME_RETRY; n; --n) {
289 read_me_csr(&me);
290 if ((me.buffer_write_ptr - me.buffer_read_ptr) >= expected)
291 break;
292 udelay(ME_DELAY);
293 }
294 if (!n) {
295 printk(BIOS_ERR, "ME: timeout waiting for data: expected "
296 "%u, available %u\n", expected,
297 me.buffer_write_ptr - me.buffer_read_ptr);
298 return -1;
299 }
300
301 /* Read and verify MEI response header from the ME */
302 mei_read_dword_ptr(&mei_rsp, MEI_ME_CB_RW);
303 if (!mei_rsp.is_complete) {
304 printk(BIOS_ERR, "ME: response is not complete\n");
305 return -1;
306 }
307
Duncan Laurie2017b4a2013-08-08 15:07:12 -0700308 /* Handle non-dword responses and expect at least the header */
Aaron Durbin76c37002012-10-30 09:03:43 -0500309 ndata = mei_rsp.length >> 2;
310 if (mei_rsp.length & 3)
311 ndata++;
312 if (ndata != (expected - 1)) {
313 printk(BIOS_ERR, "ME: response is missing data %d != %d\n",
314 ndata, (expected - 1));
315 return -1;
316 }
317
Duncan Laurie2017b4a2013-08-08 15:07:12 -0700318 /* Read response header from the ME */
319 data = header;
320 for (n = 0; n < (header_bytes >> 2); ++n)
321 *data++ = read_cb();
322 ndata -= header_bytes >> 2;
Aaron Durbin76c37002012-10-30 09:03:43 -0500323
324 /* Make sure caller passed a buffer with enough space */
325 if (ndata != (rsp_bytes >> 2)) {
326 printk(BIOS_ERR, "ME: not enough room in response buffer: "
327 "%u != %u\n", ndata, rsp_bytes >> 2);
328 return -1;
329 }
330
331 /* Read response data from the circular buffer */
332 data = rsp_data;
333 for (n = 0; n < ndata; ++n)
334 *data++ = read_cb();
335
336 /* Tell the ME that we have consumed the response */
337 read_host_csr(&host);
338 host.interrupt_status = 1;
339 host.interrupt_generate = 1;
340 write_host_csr(&host);
341
342 return mei_wait_for_me_ready();
343}
344
Duncan Laurie2017b4a2013-08-08 15:07:12 -0700345static inline int mei_sendrecv_mkhi(struct mkhi_header *mkhi,
346 void *req_data, int req_bytes,
347 void *rsp_data, int rsp_bytes)
Aaron Durbin76c37002012-10-30 09:03:43 -0500348{
Duncan Laurie2017b4a2013-08-08 15:07:12 -0700349 struct mkhi_header mkhi_rsp;
350
351 /* Send header */
352 if (mei_send_header(MEI_ADDRESS_MKHI, MEI_HOST_ADDRESS,
353 mkhi, sizeof(*mkhi), req_bytes ? 0 : 1) < 0)
Aaron Durbin76c37002012-10-30 09:03:43 -0500354 return -1;
Duncan Laurie2017b4a2013-08-08 15:07:12 -0700355
356 /* Send data if available */
357 if (req_bytes && mei_send_data(MEI_ADDRESS_MKHI, MEI_HOST_ADDRESS,
358 req_data, req_bytes) < 0)
Aaron Durbin76c37002012-10-30 09:03:43 -0500359 return -1;
Duncan Laurie2017b4a2013-08-08 15:07:12 -0700360
361 /* Return now if no response expected */
362 if (!rsp_bytes)
363 return 0;
364
365 /* Read header and data */
366 if (mei_recv_msg(&mkhi_rsp, sizeof(mkhi_rsp),
367 rsp_data, rsp_bytes) < 0)
368 return -1;
369
370 if (!mkhi_rsp.is_response ||
371 mkhi->group_id != mkhi_rsp.group_id ||
372 mkhi->command != mkhi_rsp.command) {
373 printk(BIOS_ERR, "ME: invalid response, group %u ?= %u,"
374 "command %u ?= %u, is_response %u\n", mkhi->group_id,
375 mkhi_rsp.group_id, mkhi->command, mkhi_rsp.command,
376 mkhi_rsp.is_response);
377 return -1;
378 }
379
Aaron Durbin76c37002012-10-30 09:03:43 -0500380 return 0;
381}
Duncan Laurie0dc0d132013-08-08 15:31:51 -0700382
Angel Pons7f8da792021-02-23 14:27:39 +0100383static inline int mei_sendrecv_icc(struct icc_header *icc,
384 void *req_data, int req_bytes,
385 void *rsp_data, int rsp_bytes)
386{
387 struct icc_header icc_rsp;
388
389 /* Send header */
390 if (mei_send_header(MEI_ADDRESS_ICC, MEI_HOST_ADDRESS,
391 icc, sizeof(*icc), req_bytes ? 0 : 1) < 0)
392 return -1;
393
394 /* Send data if available */
395 if (req_bytes && mei_send_data(MEI_ADDRESS_ICC, MEI_HOST_ADDRESS,
396 req_data, req_bytes) < 0)
397 return -1;
398
399 /* Read header and data, if needed */
400 if (rsp_bytes && mei_recv_msg(&icc_rsp, sizeof(icc_rsp),
401 rsp_data, rsp_bytes) < 0)
402 return -1;
403
404 return 0;
405}
406
Duncan Laurie3d299c42013-07-19 08:48:05 -0700407/*
408 * mbp give up routine. This path is taken if hfs.mpb_rdy is 0 or the read
409 * state machine on the BIOS end doesn't match the ME's state machine.
410 */
Elyes HAOUAS1dcd8db2018-12-05 10:59:42 +0100411static void intel_me_mbp_give_up(struct device *dev)
Duncan Laurie3d299c42013-07-19 08:48:05 -0700412{
413 struct mei_csr csr;
414
415 pci_write_config32(dev, PCI_ME_H_GS2, PCI_ME_MBP_GIVE_UP);
416
417 read_host_csr(&csr);
418 csr.reset = 1;
419 csr.interrupt_generate = 1;
420 write_host_csr(&csr);
421}
422
423/*
424 * mbp clear routine. This will wait for the ME to indicate that
425 * the MBP has been read and cleared.
426 */
Angel Pons10274d82021-02-23 14:19:28 +0100427static void intel_me_mbp_clear(struct device *dev)
Duncan Laurie3d299c42013-07-19 08:48:05 -0700428{
429 int count;
Angel Pons032255c2021-11-24 14:12:38 +0100430 union me_hfs2 hfs2;
Duncan Laurie3d299c42013-07-19 08:48:05 -0700431
432 /* Wait for the mbp_cleared indicator */
433 for (count = ME_RETRY; count > 0; --count) {
Angel Pons032255c2021-11-24 14:12:38 +0100434 hfs2.raw = pci_read_config32(dev, PCI_ME_HFS2);
Duncan Laurie3d299c42013-07-19 08:48:05 -0700435 if (hfs2.mbp_cleared)
436 break;
437 udelay(ME_DELAY);
438 }
439
440 if (count == 0) {
441 printk(BIOS_WARNING, "ME: Timeout waiting for mbp_cleared\n");
442 intel_me_mbp_give_up(dev);
443 } else {
444 printk(BIOS_INFO, "ME: MBP cleared\n");
445 }
446}
447
Angel Pons01c9b982021-11-24 11:58:04 +0100448static void me_print_fw_version(struct mbp_fw_version_name *vers_name)
Aaron Durbin76c37002012-10-30 09:03:43 -0500449{
Aaron Durbinbe985242012-12-12 12:40:33 -0600450 if (!vers_name) {
Aaron Durbin76c37002012-10-30 09:03:43 -0500451 printk(BIOS_ERR, "ME: mbp missing version report\n");
452 return;
453 }
454
455 printk(BIOS_DEBUG, "ME: found version %d.%d.%d.%d\n",
456 vers_name->major_version, vers_name->minor_version,
457 vers_name->hotfix_version, vers_name->build_version);
458}
459
Edward O'Callaghan7bf4f482014-06-17 15:12:09 +1000460static inline void print_cap(const char *name, int state)
461{
462 printk(BIOS_DEBUG, "ME Capability: %-41s : %sabled\n",
463 name, state ? " en" : "dis");
464}
465
Aaron Durbin76c37002012-10-30 09:03:43 -0500466/* Get ME Firmware Capabilities */
Angel Pons01c9b982021-11-24 11:58:04 +0100467static int mkhi_get_fwcaps(struct mbp_mefwcaps *cap)
Aaron Durbin76c37002012-10-30 09:03:43 -0500468{
469 u32 rule_id = 0;
470 struct me_fwcaps cap_msg;
471 struct mkhi_header mkhi = {
472 .group_id = MKHI_GROUP_ID_FWCAPS,
473 .command = MKHI_FWCAPS_GET_RULE,
474 };
Aaron Durbin76c37002012-10-30 09:03:43 -0500475
476 /* Send request and wait for response */
Duncan Laurie2017b4a2013-08-08 15:07:12 -0700477 if (mei_sendrecv_mkhi(&mkhi, &rule_id, sizeof(u32),
478 &cap_msg, sizeof(cap_msg)) < 0) {
Aaron Durbin76c37002012-10-30 09:03:43 -0500479 printk(BIOS_ERR, "ME: GET FWCAPS message failed\n");
480 return -1;
Elyes HAOUASba28e8d2016-08-31 19:22:16 +0200481 }
Aaron Durbin76c37002012-10-30 09:03:43 -0500482 *cap = cap_msg.caps_sku;
483 return 0;
484}
485
486/* Get ME Firmware Capabilities */
Angel Pons01c9b982021-11-24 11:58:04 +0100487static void me_print_fwcaps(struct mbp_mefwcaps *cap)
Aaron Durbin76c37002012-10-30 09:03:43 -0500488{
Angel Pons01c9b982021-11-24 11:58:04 +0100489 struct mbp_mefwcaps local_caps;
Aaron Durbinbe985242012-12-12 12:40:33 -0600490 if (!cap) {
491 cap = &local_caps;
Aaron Durbin76c37002012-10-30 09:03:43 -0500492 printk(BIOS_ERR, "ME: mbp missing fwcaps report\n");
493 if (mkhi_get_fwcaps(cap))
494 return;
495 }
496
497 print_cap("Full Network manageability", cap->full_net);
498 print_cap("Regular Network manageability", cap->std_net);
499 print_cap("Manageability", cap->manageability);
Aaron Durbin76c37002012-10-30 09:03:43 -0500500 print_cap("IntelR Anti-Theft (AT)", cap->intel_at);
501 print_cap("IntelR Capability Licensing Service (CLS)", cap->intel_cls);
502 print_cap("IntelR Power Sharing Technology (MPC)", cap->intel_mpc);
503 print_cap("ICC Over Clocking", cap->icc_over_clocking);
Edward O'Callaghan7bf4f482014-06-17 15:12:09 +1000504 print_cap("Protected Audio Video Path (PAVP)", cap->pavp);
Aaron Durbin76c37002012-10-30 09:03:43 -0500505 print_cap("IPV6", cap->ipv6);
506 print_cap("KVM Remote Control (KVM)", cap->kvm);
507 print_cap("Outbreak Containment Heuristic (OCH)", cap->och);
508 print_cap("Virtual LAN (VLAN)", cap->vlan);
509 print_cap("TLS", cap->tls);
510 print_cap("Wireless LAN (WLAN)", cap->wlan);
511}
Aaron Durbin76c37002012-10-30 09:03:43 -0500512
Aaron Durbin76c37002012-10-30 09:03:43 -0500513/* Send END OF POST message to the ME */
Angel Pons10274d82021-02-23 14:19:28 +0100514static int mkhi_end_of_post(void)
Aaron Durbin76c37002012-10-30 09:03:43 -0500515{
516 struct mkhi_header mkhi = {
517 .group_id = MKHI_GROUP_ID_GEN,
518 .command = MKHI_END_OF_POST,
519 };
Aaron Durbin76c37002012-10-30 09:03:43 -0500520 u32 eop_ack;
521
522 /* Send request and wait for response */
Angel Pons08e8cab2020-06-18 15:20:37 +0200523 printk(BIOS_NOTICE, "ME: %s\n", __func__);
Duncan Laurie2017b4a2013-08-08 15:07:12 -0700524 if (mei_sendrecv_mkhi(&mkhi, NULL, 0, &eop_ack, sizeof(eop_ack)) < 0) {
Aaron Durbin76c37002012-10-30 09:03:43 -0500525 printk(BIOS_ERR, "ME: END OF POST message failed\n");
526 return -1;
527 }
528
529 printk(BIOS_INFO, "ME: END OF POST message successful (%d)\n", eop_ack);
530 return 0;
531}
532
Angel Pons10274d82021-02-23 14:19:28 +0100533void intel_me_finalize(struct device *dev)
Duncan Laurieaf980622013-07-18 23:02:18 -0700534{
Angel Pons032255c2021-11-24 14:12:38 +0100535 union me_hfs hfs;
Duncan Laurieaf980622013-07-18 23:02:18 -0700536 u32 reg32;
537
Angel Pons10274d82021-02-23 14:19:28 +0100538 reg32 = pci_read_config32(dev, PCI_BASE_ADDRESS_0);
Angel Ponsa3492d72021-02-23 14:12:25 +0100539 mei_base_address = (u8 *)(uintptr_t)(reg32 & ~PCI_BASE_ADDRESS_MEM_ATTR_MASK);
Duncan Laurieaf980622013-07-18 23:02:18 -0700540
541 /* S3 path will have hidden this device already */
Angel Ponsa3492d72021-02-23 14:12:25 +0100542 if (!mei_base_address || mei_base_address == (u8 *)0xfffffff0)
Duncan Laurieaf980622013-07-18 23:02:18 -0700543 return;
544
Duncan Laurie3d299c42013-07-19 08:48:05 -0700545 /* Wait for ME MBP Cleared indicator */
Angel Pons10274d82021-02-23 14:19:28 +0100546 intel_me_mbp_clear(dev);
Duncan Laurie3d299c42013-07-19 08:48:05 -0700547
Duncan Laurieaf980622013-07-18 23:02:18 -0700548 /* Make sure ME is in a mode that expects EOP */
Angel Pons032255c2021-11-24 14:12:38 +0100549 hfs.raw = pci_read_config32(dev, PCI_ME_HFS);
Duncan Laurieaf980622013-07-18 23:02:18 -0700550
551 /* Abort and leave device alone if not normal mode */
552 if (hfs.fpt_bad ||
553 hfs.working_state != ME_HFS_CWS_NORMAL ||
554 hfs.operation_mode != ME_HFS_MODE_NORMAL)
555 return;
556
557 /* Try to send EOP command so ME stops accepting other commands */
558 mkhi_end_of_post();
559
560 /* Make sure IO is disabled */
Angel Pons10274d82021-02-23 14:19:28 +0100561 pci_and_config16(dev, PCI_COMMAND,
Angel Ponsbf9bc502020-06-08 00:12:43 +0200562 ~(PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY | PCI_COMMAND_IO));
Duncan Laurieaf980622013-07-18 23:02:18 -0700563
564 /* Hide the PCI device */
565 RCBA32_OR(FD2, PCH_DISABLE_MEI1);
566}
567
Duncan Laurie0dc0d132013-08-08 15:31:51 -0700568static int me_icc_set_clock_enables(u32 mask)
569{
570 struct icc_clock_enables_msg clk = {
571 .clock_enables = 0, /* Turn off specified clocks */
572 .clock_mask = mask,
573 .no_response = 1, /* Do not expect response */
574 };
575 struct icc_header icc = {
576 .api_version = ICC_API_VERSION_LYNXPOINT,
577 .icc_command = ICC_SET_CLOCK_ENABLES,
578 .length = sizeof(clk),
579 };
580
581 /* Send request and wait for response */
582 if (mei_sendrecv_icc(&icc, &clk, sizeof(clk), NULL, 0) < 0) {
583 printk(BIOS_ERR, "ME: ICC SET CLOCK ENABLES message failed\n");
584 return -1;
Duncan Laurie0dc0d132013-08-08 15:31:51 -0700585 }
Elyes HAOUAS54f94242018-10-25 10:57:39 +0200586 printk(BIOS_INFO, "ME: ICC SET CLOCK ENABLES 0x%08x\n", mask);
Duncan Laurie0dc0d132013-08-08 15:31:51 -0700587 return 0;
588}
589
Aaron Durbin76c37002012-10-30 09:03:43 -0500590/* Determine the path that we should take based on ME status */
Angel Pons9f043742021-11-24 12:46:12 +0100591static enum me_bios_path intel_me_path(struct device *dev)
Aaron Durbin76c37002012-10-30 09:03:43 -0500592{
Angel Pons9f043742021-11-24 12:46:12 +0100593 enum me_bios_path path = ME_DISABLE_BIOS_PATH;
Angel Pons032255c2021-11-24 14:12:38 +0100594 union me_hfs hfs = { .raw = pci_read_config32(dev, PCI_ME_HFS) };
595 union me_hfs2 hfs2 = { .raw = pci_read_config32(dev, PCI_ME_HFS2) };
Aaron Durbin76c37002012-10-30 09:03:43 -0500596
597 /* Check and dump status */
Aaron Durbin9aa031e2012-11-02 09:16:46 -0500598 intel_me_status(&hfs, &hfs2);
Aaron Durbin76c37002012-10-30 09:03:43 -0500599
600 /* Check Current Working State */
601 switch (hfs.working_state) {
602 case ME_HFS_CWS_NORMAL:
603 path = ME_NORMAL_BIOS_PATH;
604 break;
605 case ME_HFS_CWS_REC:
606 path = ME_RECOVERY_BIOS_PATH;
607 break;
608 default:
609 path = ME_DISABLE_BIOS_PATH;
610 break;
611 }
612
613 /* Check Current Operation Mode */
614 switch (hfs.operation_mode) {
615 case ME_HFS_MODE_NORMAL:
616 break;
617 case ME_HFS_MODE_DEBUG:
618 case ME_HFS_MODE_DIS:
619 case ME_HFS_MODE_OVER_JMPR:
620 case ME_HFS_MODE_OVER_MEI:
621 default:
622 path = ME_DISABLE_BIOS_PATH;
623 break;
624 }
625
626 /* Check for any error code and valid firmware and MBP */
627 if (hfs.error_code || hfs.fpt_bad)
628 path = ME_ERROR_BIOS_PATH;
629
630 /* Check if the MBP is ready */
Aaron Durbin9aa031e2012-11-02 09:16:46 -0500631 if (!hfs2.mbp_rdy) {
Aaron Durbin76c37002012-10-30 09:03:43 -0500632 printk(BIOS_CRIT, "%s: mbp is not ready!\n",
Angel Pons08e8cab2020-06-18 15:20:37 +0200633 __func__);
Aaron Durbin76c37002012-10-30 09:03:43 -0500634 path = ME_ERROR_BIOS_PATH;
635 }
636
Kyösti Mälkkibe5317f2019-11-06 12:07:21 +0200637 if (CONFIG(ELOG) && path != ME_NORMAL_BIOS_PATH) {
Aaron Durbin76c37002012-10-30 09:03:43 -0500638 struct elog_event_data_me_extended data = {
639 .current_working_state = hfs.working_state,
640 .operation_state = hfs.operation_state,
641 .operation_mode = hfs.operation_mode,
642 .error_code = hfs.error_code,
Aaron Durbin9aa031e2012-11-02 09:16:46 -0500643 .progress_code = hfs2.progress_code,
644 .current_pmevent = hfs2.current_pmevent,
645 .current_state = hfs2.current_state,
Aaron Durbin76c37002012-10-30 09:03:43 -0500646 };
647 elog_add_event_byte(ELOG_TYPE_MANAGEMENT_ENGINE, path);
648 elog_add_event_raw(ELOG_TYPE_MANAGEMENT_ENGINE_EXT,
649 &data, sizeof(data));
650 }
Aaron Durbin76c37002012-10-30 09:03:43 -0500651
652 return path;
653}
654
655/* Prepare ME for MEI messages */
Elyes HAOUAS1dcd8db2018-12-05 10:59:42 +0100656static int intel_mei_setup(struct device *dev)
Aaron Durbin76c37002012-10-30 09:03:43 -0500657{
658 struct resource *res;
659 struct mei_csr host;
Aaron Durbin76c37002012-10-30 09:03:43 -0500660
661 /* Find the MMIO base for the ME interface */
Angel Ponsf32ae102021-11-03 13:07:14 +0100662 res = probe_resource(dev, PCI_BASE_ADDRESS_0);
Aaron Durbin76c37002012-10-30 09:03:43 -0500663 if (!res || res->base == 0 || res->size == 0) {
664 printk(BIOS_DEBUG, "ME: MEI resource not present!\n");
665 return -1;
666 }
Angel Ponsd32b5142021-02-23 14:23:49 +0100667 mei_base_address = res2mmio(res, 0, 0);
Aaron Durbin76c37002012-10-30 09:03:43 -0500668
669 /* Ensure Memory and Bus Master bits are set */
Angel Ponsd5d4fbc2020-05-31 01:03:59 +0200670 pci_or_config16(dev, PCI_COMMAND, PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY);
Aaron Durbin76c37002012-10-30 09:03:43 -0500671
672 /* Clean up status for next message */
673 read_host_csr(&host);
674 host.interrupt_generate = 1;
675 host.ready = 1;
676 host.reset = 0;
677 write_host_csr(&host);
678
679 return 0;
680}
681
682/* Read the Extend register hash of ME firmware */
Elyes HAOUAS1dcd8db2018-12-05 10:59:42 +0100683static int intel_me_extend_valid(struct device *dev)
Aaron Durbin76c37002012-10-30 09:03:43 -0500684{
Angel Pons032255c2021-11-24 14:12:38 +0100685 union me_heres status = { .raw = pci_read_config32(dev, PCI_ME_HERES) };
Aaron Durbin76c37002012-10-30 09:03:43 -0500686 u32 extend[8] = {0};
687 int i, count = 0;
688
Aaron Durbin76c37002012-10-30 09:03:43 -0500689 if (!status.extend_feature_present) {
690 printk(BIOS_ERR, "ME: Extend Feature not present\n");
691 return -1;
692 }
693
694 if (!status.extend_reg_valid) {
695 printk(BIOS_ERR, "ME: Extend Register not valid\n");
696 return -1;
697 }
698
699 switch (status.extend_reg_algorithm) {
700 case PCI_ME_EXT_SHA1:
701 count = 5;
702 printk(BIOS_DEBUG, "ME: Extend SHA-1: ");
703 break;
704 case PCI_ME_EXT_SHA256:
705 count = 8;
706 printk(BIOS_DEBUG, "ME: Extend SHA-256: ");
707 break;
708 default:
709 printk(BIOS_ERR, "ME: Extend Algorithm %d unknown\n",
710 status.extend_reg_algorithm);
711 return -1;
712 }
713
714 for (i = 0; i < count; ++i) {
715 extend[i] = pci_read_config32(dev, PCI_ME_HER(i));
716 printk(BIOS_DEBUG, "%08x", extend[i]);
717 }
718 printk(BIOS_DEBUG, "\n");
719
Aaron Durbin76c37002012-10-30 09:03:43 -0500720 /* Save hash in NVS for the OS to verify */
Kyösti Mälkki84d10cc2021-02-10 17:53:34 +0200721 if (CONFIG(CHROMEOS_NVS))
Kyösti Mälkki26e0f4c2020-12-19 19:10:45 +0200722 chromeos_set_me_hash(extend, count);
Aaron Durbin76c37002012-10-30 09:03:43 -0500723
724 return 0;
725}
726
Aaron Durbin76c37002012-10-30 09:03:43 -0500727static u32 me_to_host_words_pending(void)
728{
729 struct mei_csr me;
730 read_me_csr(&me);
731 if (!me.ready)
732 return 0;
733 return (me.buffer_write_ptr - me.buffer_read_ptr) &
734 (me.buffer_depth - 1);
735}
736
Aaron Durbinbe985242012-12-12 12:40:33 -0600737struct mbp_payload {
Angel Pons01c9b982021-11-24 11:58:04 +0100738 struct mbp_header header;
Aaron Durbinbe985242012-12-12 12:40:33 -0600739 u32 data[0];
740};
741
Aaron Durbin76c37002012-10-30 09:03:43 -0500742/*
Angel Pons7f8da792021-02-23 14:27:39 +0100743 * Read and print ME MBP data
744 *
745 * Return -1 to indicate a problem (give up)
746 * Return 0 to indicate success (send LOCK+EOP)
Aaron Durbin76c37002012-10-30 09:03:43 -0500747 */
Angel Pons01c9b982021-11-24 11:58:04 +0100748static int intel_me_read_mbp(struct me_bios_payload *mbp_data, struct device *dev)
Aaron Durbin76c37002012-10-30 09:03:43 -0500749{
Angel Pons01c9b982021-11-24 11:58:04 +0100750 struct mbp_header mbp_hdr;
Aaron Durbin76c37002012-10-30 09:03:43 -0500751 u32 me2host_pending;
Aaron Durbin76c37002012-10-30 09:03:43 -0500752 struct mei_csr host;
Angel Pons032255c2021-11-24 14:12:38 +0100753 union me_hfs2 hfs2 = { .raw = pci_read_config32(dev, PCI_ME_HFS2) };
Aaron Durbinbe985242012-12-12 12:40:33 -0600754 struct mbp_payload *mbp;
755 int i;
Aaron Durbin9aa031e2012-11-02 09:16:46 -0500756
Aaron Durbin9aa031e2012-11-02 09:16:46 -0500757 if (!hfs2.mbp_rdy) {
758 printk(BIOS_ERR, "ME: MBP not ready\n");
759 goto mbp_failure;
760 }
Aaron Durbin76c37002012-10-30 09:03:43 -0500761
762 me2host_pending = me_to_host_words_pending();
763 if (!me2host_pending) {
764 printk(BIOS_ERR, "ME: no mbp data!\n");
Aaron Durbin9aa031e2012-11-02 09:16:46 -0500765 goto mbp_failure;
Aaron Durbin76c37002012-10-30 09:03:43 -0500766 }
767
768 /* we know for sure that at least the header is there */
769 mei_read_dword_ptr(&mbp_hdr, MEI_ME_CB_RW);
770
771 if ((mbp_hdr.num_entries > (mbp_hdr.mbp_size / 2)) ||
772 (me2host_pending < mbp_hdr.mbp_size)) {
773 printk(BIOS_ERR, "ME: mbp of %d entries, total size %d words"
774 " buffer contains %d words\n",
775 mbp_hdr.num_entries, mbp_hdr.mbp_size,
776 me2host_pending);
Aaron Durbin9aa031e2012-11-02 09:16:46 -0500777 goto mbp_failure;
Aaron Durbin76c37002012-10-30 09:03:43 -0500778 }
Aaron Durbinbe985242012-12-12 12:40:33 -0600779 mbp = malloc(mbp_hdr.mbp_size * sizeof(u32));
780 if (!mbp)
781 goto mbp_failure;
Aaron Durbin76c37002012-10-30 09:03:43 -0500782
Aaron Durbinbe985242012-12-12 12:40:33 -0600783 mbp->header = mbp_hdr;
Aaron Durbin76c37002012-10-30 09:03:43 -0500784 me2host_pending--;
Aaron Durbin76c37002012-10-30 09:03:43 -0500785
Aaron Durbinbe985242012-12-12 12:40:33 -0600786 i = 0;
787 while (i != me2host_pending) {
788 mei_read_dword_ptr(&mbp->data[i], MEI_ME_CB_RW);
789 i++;
Aaron Durbin76c37002012-10-30 09:03:43 -0500790 }
791
Aaron Durbinbe985242012-12-12 12:40:33 -0600792 /* Signal to the ME that the host has finished reading the MBP. */
Aaron Durbin76c37002012-10-30 09:03:43 -0500793 read_host_csr(&host);
794 host.interrupt_generate = 1;
795 write_host_csr(&host);
796
Aaron Durbinbe985242012-12-12 12:40:33 -0600797 /* Dump out the MBP contents. */
Kyösti Mälkkic86fc8e2019-11-06 06:32:27 +0200798 if (CONFIG_DEFAULT_CONSOLE_LOGLEVEL >= BIOS_DEBUG) {
799 printk(BIOS_INFO, "ME MBP: Header: items: %d, size dw: %d\n",
800 mbp->header.num_entries, mbp->header.mbp_size);
801 if (CONFIG(DEBUG_INTEL_ME)) {
802 for (i = 0; i < mbp->header.mbp_size - 1; i++) {
803 printk(BIOS_INFO, "ME MBP: %04x: 0x%08x\n", i, mbp->data[i]);
804 }
805 }
Aaron Durbinbe985242012-12-12 12:40:33 -0600806 }
Aaron Durbinbe985242012-12-12 12:40:33 -0600807
808 #define ASSIGN_FIELD_PTR(field_,val_) \
809 { \
810 mbp_data->field_ = (typeof(mbp_data->field_))(void *)val_; \
811 break; \
812 }
813 /* Setup the pointers in the me_bios_payload structure. */
814 for (i = 0; i < mbp->header.mbp_size - 1;) {
Angel Pons01c9b982021-11-24 11:58:04 +0100815 struct mbp_item_header *item = (void *)&mbp->data[i];
Aaron Durbinbe985242012-12-12 12:40:33 -0600816
Elyes HAOUASf9de5a42018-05-03 17:21:02 +0200817 switch (MBP_MAKE_IDENT(item->app_id, item->item_id)) {
Aaron Durbinbe985242012-12-12 12:40:33 -0600818 case MBP_IDENT(KERNEL, FW_VER):
819 ASSIGN_FIELD_PTR(fw_version_name, &mbp->data[i+1]);
820
821 case MBP_IDENT(ICC, PROFILE):
822 ASSIGN_FIELD_PTR(icc_profile, &mbp->data[i+1]);
823
824 case MBP_IDENT(INTEL_AT, STATE):
825 ASSIGN_FIELD_PTR(at_state, &mbp->data[i+1]);
826
827 case MBP_IDENT(KERNEL, FW_CAP):
828 ASSIGN_FIELD_PTR(fw_capabilities, &mbp->data[i+1]);
829
830 case MBP_IDENT(KERNEL, ROM_BIST):
831 ASSIGN_FIELD_PTR(rom_bist_data, &mbp->data[i+1]);
832
833 case MBP_IDENT(KERNEL, PLAT_KEY):
834 ASSIGN_FIELD_PTR(platform_key, &mbp->data[i+1]);
835
836 case MBP_IDENT(KERNEL, FW_TYPE):
837 ASSIGN_FIELD_PTR(fw_plat_type, &mbp->data[i+1]);
838
839 case MBP_IDENT(KERNEL, MFS_FAILURE):
840 ASSIGN_FIELD_PTR(mfsintegrity, &mbp->data[i+1]);
841
Duncan Laurie144f7b22013-05-01 11:27:58 -0700842 case MBP_IDENT(KERNEL, PLAT_TIME):
843 ASSIGN_FIELD_PTR(plat_time, &mbp->data[i+1]);
844
845 case MBP_IDENT(NFC, SUPPORT_DATA):
846 ASSIGN_FIELD_PTR(nfc_data, &mbp->data[i+1]);
847
Aaron Durbinbe985242012-12-12 12:40:33 -0600848 default:
Duncan Laurie0b3cd362013-08-08 15:40:01 -0700849 printk(BIOS_ERR, "ME MBP: unknown item 0x%x @ "
850 "dw offset 0x%x\n", mbp->data[i], i);
Aaron Durbinbe985242012-12-12 12:40:33 -0600851 break;
852 }
853 i += item->length;
854 }
855 #undef ASSIGN_FIELD_PTR
856
Aaron Durbin76c37002012-10-30 09:03:43 -0500857 return 0;
Aaron Durbin9aa031e2012-11-02 09:16:46 -0500858
859mbp_failure:
860 intel_me_mbp_give_up(dev);
861 return -1;
Aaron Durbin76c37002012-10-30 09:03:43 -0500862}
Angel Pons7f8da792021-02-23 14:27:39 +0100863
864/* Check whether ME is present and do basic init */
865static void intel_me_init(struct device *dev)
866{
867 struct southbridge_intel_lynxpoint_config *config = dev->chip_info;
Angel Pons9f043742021-11-24 12:46:12 +0100868 enum me_bios_path path = intel_me_path(dev);
Angel Pons01c9b982021-11-24 11:58:04 +0100869 struct me_bios_payload mbp_data;
Angel Pons7f8da792021-02-23 14:27:39 +0100870
871 /* Do initial setup and determine the BIOS path */
872 printk(BIOS_NOTICE, "ME: BIOS path: %s\n", me_bios_path_values[path]);
873
874 if (path == ME_NORMAL_BIOS_PATH) {
875 /* Validate the extend register */
876 intel_me_extend_valid(dev);
877 }
878
879 memset(&mbp_data, 0, sizeof(mbp_data));
880
881 /*
882 * According to the ME9 BWG, BIOS is required to fetch MBP data in
883 * all boot flows except S3 Resume.
884 */
885
886 /* Prepare MEI MMIO interface */
887 if (intel_mei_setup(dev) < 0)
888 return;
889
890 if (intel_me_read_mbp(&mbp_data, dev))
891 return;
892
893 if (CONFIG_DEFAULT_CONSOLE_LOGLEVEL >= BIOS_DEBUG) {
894 me_print_fw_version(mbp_data.fw_version_name);
895
896 if (CONFIG(DEBUG_INTEL_ME))
897 me_print_fwcaps(mbp_data.fw_capabilities);
898
899 if (mbp_data.plat_time) {
900 printk(BIOS_DEBUG, "ME: Wake Event to ME Reset: %u ms\n",
901 mbp_data.plat_time->wake_event_mrst_time_ms);
902 printk(BIOS_DEBUG, "ME: ME Reset to Platform Reset: %u ms\n",
903 mbp_data.plat_time->mrst_pltrst_time_ms);
904 printk(BIOS_DEBUG, "ME: Platform Reset to CPU Reset: %u ms\n",
905 mbp_data.plat_time->pltrst_cpurst_time_ms);
906 }
907 }
908
909 /* Set clock enables according to devicetree */
910 if (config && config->icc_clock_disable)
911 me_icc_set_clock_enables(config->icc_clock_disable);
912
913 /*
914 * Leave the ME unlocked. It will be locked later.
915 */
916}
917
918static void intel_me_enable(struct device *dev)
919{
920 /* Avoid talking to the device in S3 path */
921 if (acpi_is_wakeup_s3()) {
922 dev->enabled = 0;
923 pch_disable_devfn(dev);
924 }
925}
926
927static struct device_operations device_ops = {
928 .read_resources = pci_dev_read_resources,
929 .set_resources = pci_dev_set_resources,
930 .enable_resources = pci_dev_enable_resources,
931 .enable = intel_me_enable,
932 .init = intel_me_init,
933 .final = intel_me_finalize,
934 .ops_pci = &pci_dev_ops_pci,
935};
936
937static const unsigned short pci_device_ids[] = {
938 PCI_DEVICE_ID_INTEL_LPT_H_MEI,
939 PCI_DEVICE_ID_INTEL_LPT_LP_MEI,
940 0
941};
942
943static const struct pci_driver intel_me __pci_driver = {
944 .ops = &device_ops,
945 .vendor = PCI_VENDOR_ID_INTEL,
946 .devices = pci_device_ids,
947};