blob: 80ffe2b9ac2bbba41a69e4976d960c1ec146de3b [file] [log] [blame]
Angel Ponsf94ac9a2020-04-05 15:46:48 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Duncan Lauriec88c54c2014-04-30 16:36:13 -07002
3/*
4 * This is a ramstage driver for the Intel Management Engine found in the
5 * southbridge. 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>
Duncan Lauriec88c54c2014-04-30 16:36:13 -070014#include <console/console.h>
15#include <device/device.h>
16#include <device/pci.h>
17#include <device/pci_ids.h>
18#include <device/pci_def.h>
Elyes HAOUAS70a03dd2019-12-02 20:47:50 +010019#include <stdlib.h>
Duncan Lauriec88c54c2014-04-30 16:36:13 -070020#include <string.h>
21#include <delay.h>
22#include <elog.h>
Julius Werner4ee4bd52014-10-20 13:46:39 -070023#include <soc/me.h>
24#include <soc/lpc.h>
25#include <soc/pch.h>
26#include <soc/pci_devs.h>
27#include <soc/ramstage.h>
28#include <soc/rcba.h>
29#include <soc/intel/broadwell/chip.h>
Duncan Lauriec88c54c2014-04-30 16:36:13 -070030
Julius Wernercd49cce2019-03-05 16:53:33 -080031#if CONFIG(CHROMEOS)
Duncan Lauriec88c54c2014-04-30 16:36:13 -070032#include <vendorcode/google/chromeos/chromeos.h>
33#include <vendorcode/google/chromeos/gnvs.h>
34#endif
35
36/* Path that the BIOS should take based on ME state */
37static const char *me_bios_path_values[] = {
38 [ME_NORMAL_BIOS_PATH] = "Normal",
39 [ME_S3WAKE_BIOS_PATH] = "S3 Wake",
40 [ME_ERROR_BIOS_PATH] = "Error",
41 [ME_RECOVERY_BIOS_PATH] = "Recovery",
42 [ME_DISABLE_BIOS_PATH] = "Disable",
43 [ME_FIRMWARE_UPDATE_BIOS_PATH] = "Firmware Update",
44};
Duncan Lauriec88c54c2014-04-30 16:36:13 -070045
46/* MMIO base address for MEI interface */
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -080047static u8 *mei_base_address;
Duncan Lauriec88c54c2014-04-30 16:36:13 -070048
Duncan Lauriec88c54c2014-04-30 16:36:13 -070049static void mei_dump(void *ptr, int dword, int offset, const char *type)
50{
51 struct mei_csr *csr;
52
Kyösti Mälkkic86fc8e2019-11-06 06:32:27 +020053 if (!CONFIG(DEBUG_INTEL_ME))
54 return;
55
Duncan Lauriec88c54c2014-04-30 16:36:13 -070056 printk(BIOS_SPEW, "%-9s[%02x] : ", type, offset);
57
58 switch (offset) {
59 case MEI_H_CSR:
60 case MEI_ME_CSR_HA:
61 csr = ptr;
62 if (!csr) {
63 printk(BIOS_SPEW, "ERROR: 0x%08x\n", dword);
64 break;
65 }
66 printk(BIOS_SPEW, "cbd=%u cbrp=%02u cbwp=%02u ready=%u "
67 "reset=%u ig=%u is=%u ie=%u\n", csr->buffer_depth,
68 csr->buffer_read_ptr, csr->buffer_write_ptr,
69 csr->ready, csr->reset, csr->interrupt_generate,
70 csr->interrupt_status, csr->interrupt_enable);
71 break;
72 case MEI_ME_CB_RW:
73 case MEI_H_CB_WW:
74 printk(BIOS_SPEW, "CB: 0x%08x\n", dword);
75 break;
76 default:
77 printk(BIOS_SPEW, "0x%08x\n", offset);
78 break;
79 }
80}
Duncan Lauriec88c54c2014-04-30 16:36:13 -070081
82/*
83 * ME/MEI access helpers using memcpy to avoid aliasing.
84 */
85
86static inline void mei_read_dword_ptr(void *ptr, int offset)
87{
88 u32 dword = read32(mei_base_address + offset);
89 memcpy(ptr, &dword, sizeof(dword));
90 mei_dump(ptr, dword, offset, "READ");
91}
92
93static inline void mei_write_dword_ptr(void *ptr, int offset)
94{
95 u32 dword = 0;
96 memcpy(&dword, ptr, sizeof(dword));
97 write32(mei_base_address + offset, dword);
98 mei_dump(ptr, dword, offset, "WRITE");
99}
100
Elyes HAOUAS040aff22018-05-27 16:30:36 +0200101static inline void pci_read_dword_ptr(struct device *dev, void *ptr, int offset)
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700102{
103 u32 dword = pci_read_config32(dev, offset);
104 memcpy(ptr, &dword, sizeof(dword));
105 mei_dump(ptr, dword, offset, "PCI READ");
106}
107
108static inline void read_host_csr(struct mei_csr *csr)
109{
110 mei_read_dword_ptr(csr, MEI_H_CSR);
111}
112
113static inline void write_host_csr(struct mei_csr *csr)
114{
115 mei_write_dword_ptr(csr, MEI_H_CSR);
116}
117
118static inline void read_me_csr(struct mei_csr *csr)
119{
120 mei_read_dword_ptr(csr, MEI_ME_CSR_HA);
121}
122
123static inline void write_cb(u32 dword)
124{
125 write32(mei_base_address + MEI_H_CB_WW, dword);
126 mei_dump(NULL, dword, MEI_H_CB_WW, "WRITE");
127}
128
129static inline u32 read_cb(void)
130{
131 u32 dword = read32(mei_base_address + MEI_ME_CB_RW);
132 mei_dump(NULL, dword, MEI_ME_CB_RW, "READ");
133 return dword;
134}
135
136/* Wait for ME ready bit to be asserted */
137static int mei_wait_for_me_ready(void)
138{
139 struct mei_csr me;
Lee Leahy23602df2017-03-16 19:00:37 -0700140 unsigned int try = ME_RETRY;
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700141
142 while (try--) {
143 read_me_csr(&me);
144 if (me.ready)
145 return 0;
146 udelay(ME_DELAY);
147 }
148
149 printk(BIOS_ERR, "ME: failed to become ready\n");
150 return -1;
151}
152
153static void mei_reset(void)
154{
155 struct mei_csr host;
156
157 if (mei_wait_for_me_ready() < 0)
158 return;
159
160 /* Reset host and ME circular buffers for next message */
161 read_host_csr(&host);
162 host.reset = 1;
163 host.interrupt_generate = 1;
164 write_host_csr(&host);
165
166 if (mei_wait_for_me_ready() < 0)
167 return;
168
169 /* Re-init and indicate host is ready */
170 read_host_csr(&host);
171 host.interrupt_generate = 1;
172 host.ready = 1;
173 host.reset = 0;
174 write_host_csr(&host);
175}
176
177static int mei_send_packet(struct mei_header *mei, void *req_data)
178{
179 struct mei_csr host;
Lee Leahy23602df2017-03-16 19:00:37 -0700180 unsigned int ndata, n;
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700181 u32 *data;
182
183 /* Number of dwords to write */
184 ndata = mei->length >> 2;
185
186 /* Pad non-dword aligned request message length */
187 if (mei->length & 3)
188 ndata++;
189 if (!ndata) {
190 printk(BIOS_DEBUG, "ME: request has no data\n");
191 return -1;
192 }
193 ndata++; /* Add MEI header */
194
195 /*
196 * Make sure there is still room left in the circular buffer.
197 * Reset the buffer pointers if the requested message will not fit.
198 */
199 read_host_csr(&host);
200 if ((host.buffer_depth - host.buffer_write_ptr) < ndata) {
201 printk(BIOS_ERR, "ME: circular buffer full, resetting...\n");
202 mei_reset();
203 read_host_csr(&host);
204 }
205
206 /* Ensure the requested length will fit in the circular buffer. */
207 if ((host.buffer_depth - host.buffer_write_ptr) < ndata) {
208 printk(BIOS_ERR, "ME: message (%u) too large for buffer (%u)\n",
209 ndata + 2, host.buffer_depth);
210 return -1;
211 }
212
213 /* Write MEI header */
214 mei_write_dword_ptr(mei, MEI_H_CB_WW);
215 ndata--;
216
217 /* Write message data */
218 data = req_data;
219 for (n = 0; n < ndata; ++n)
220 write_cb(*data++);
221
222 /* Generate interrupt to the ME */
223 read_host_csr(&host);
224 host.interrupt_generate = 1;
225 write_host_csr(&host);
226
227 /* Make sure ME is ready after sending request data */
228 return mei_wait_for_me_ready();
229}
230
231static int mei_send_data(u8 me_address, u8 host_address,
232 void *req_data, int req_bytes)
233{
234 struct mei_header header = {
235 .client_address = me_address,
236 .host_address = host_address,
237 };
238 struct mei_csr host;
239 int current = 0;
240 u8 *req_ptr = req_data;
241
242 while (!header.is_complete) {
243 int remain = req_bytes - current;
244 int buf_len;
245
246 read_host_csr(&host);
247 buf_len = host.buffer_depth - host.buffer_write_ptr;
248
249 if (buf_len > remain) {
250 /* Send all remaining data as final message */
251 header.length = req_bytes - current;
252 header.is_complete = 1;
253 } else {
254 /* Send as much data as the buffer can hold */
255 header.length = buf_len;
256 }
257
258 mei_send_packet(&header, req_ptr);
259
260 req_ptr += header.length;
261 current += header.length;
262 }
263
264 return 0;
265}
266
267static int mei_send_header(u8 me_address, u8 host_address,
268 void *header, int header_len, int complete)
269{
270 struct mei_header mei = {
271 .client_address = me_address,
272 .host_address = host_address,
273 .length = header_len,
274 .is_complete = complete,
275 };
276 return mei_send_packet(&mei, header);
277}
278
279static int mei_recv_msg(void *header, int header_bytes,
280 void *rsp_data, int rsp_bytes)
281{
282 struct mei_header mei_rsp;
283 struct mei_csr me, host;
Lee Leahy23602df2017-03-16 19:00:37 -0700284 unsigned int ndata, n;
285 unsigned int expected;
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700286 u32 *data;
287
288 /* Total number of dwords to read from circular buffer */
289 expected = (rsp_bytes + sizeof(mei_rsp) + header_bytes) >> 2;
290 if (rsp_bytes & 3)
291 expected++;
292
293 if (mei_wait_for_me_ready() < 0)
294 return -1;
295
296 /*
297 * The interrupt status bit does not appear to indicate that the
298 * message has actually been received. Instead we wait until the
299 * expected number of dwords are present in the circular buffer.
300 */
301 for (n = ME_RETRY; n; --n) {
302 read_me_csr(&me);
303 if ((me.buffer_write_ptr - me.buffer_read_ptr) >= expected)
304 break;
305 udelay(ME_DELAY);
306 }
307 if (!n) {
308 printk(BIOS_ERR, "ME: timeout waiting for data: expected "
309 "%u, available %u\n", expected,
310 me.buffer_write_ptr - me.buffer_read_ptr);
311 return -1;
312 }
313
314 /* Read and verify MEI response header from the ME */
315 mei_read_dword_ptr(&mei_rsp, MEI_ME_CB_RW);
316 if (!mei_rsp.is_complete) {
317 printk(BIOS_ERR, "ME: response is not complete\n");
318 return -1;
319 }
320
321 /* Handle non-dword responses and expect at least the header */
322 ndata = mei_rsp.length >> 2;
323 if (mei_rsp.length & 3)
324 ndata++;
325 if (ndata != (expected - 1)) {
326 printk(BIOS_ERR, "ME: response is missing data %d != %d\n",
327 ndata, (expected - 1));
328 return -1;
329 }
330
331 /* Read response header from the ME */
332 data = header;
333 for (n = 0; n < (header_bytes >> 2); ++n)
334 *data++ = read_cb();
335 ndata -= header_bytes >> 2;
336
337 /* Make sure caller passed a buffer with enough space */
338 if (ndata != (rsp_bytes >> 2)) {
339 printk(BIOS_ERR, "ME: not enough room in response buffer: "
340 "%u != %u\n", ndata, rsp_bytes >> 2);
341 return -1;
342 }
343
344 /* Read response data from the circular buffer */
345 data = rsp_data;
346 for (n = 0; n < ndata; ++n)
347 *data++ = read_cb();
348
349 /* Tell the ME that we have consumed the response */
350 read_host_csr(&host);
351 host.interrupt_status = 1;
352 host.interrupt_generate = 1;
353 write_host_csr(&host);
354
355 return mei_wait_for_me_ready();
356}
357
358static inline int mei_sendrecv_mkhi(struct mkhi_header *mkhi,
359 void *req_data, int req_bytes,
360 void *rsp_data, int rsp_bytes)
361{
362 struct mkhi_header mkhi_rsp;
363
364 /* Send header */
365 if (mei_send_header(MEI_ADDRESS_MKHI, MEI_HOST_ADDRESS,
366 mkhi, sizeof(*mkhi), req_bytes ? 0 : 1) < 0)
367 return -1;
368
369 /* Send data if available */
370 if (req_bytes && mei_send_data(MEI_ADDRESS_MKHI, MEI_HOST_ADDRESS,
371 req_data, req_bytes) < 0)
372 return -1;
373
374 /* Return now if no response expected */
375 if (!rsp_bytes)
376 return 0;
377
378 /* Read header and data */
379 if (mei_recv_msg(&mkhi_rsp, sizeof(mkhi_rsp),
380 rsp_data, rsp_bytes) < 0)
381 return -1;
382
383 if (!mkhi_rsp.is_response ||
384 mkhi->group_id != mkhi_rsp.group_id ||
385 mkhi->command != mkhi_rsp.command) {
386 printk(BIOS_ERR, "ME: invalid response, group %u ?= %u,"
387 "command %u ?= %u, is_response %u\n", mkhi->group_id,
388 mkhi_rsp.group_id, mkhi->command, mkhi_rsp.command,
389 mkhi_rsp.is_response);
390 return -1;
391 }
392
393 return 0;
394}
395
396static inline int mei_sendrecv_icc(struct icc_header *icc,
397 void *req_data, int req_bytes,
398 void *rsp_data, int rsp_bytes)
399{
400 struct icc_header icc_rsp;
401
402 /* Send header */
403 if (mei_send_header(MEI_ADDRESS_ICC, MEI_HOST_ADDRESS,
404 icc, sizeof(*icc), req_bytes ? 0 : 1) < 0)
405 return -1;
406
407 /* Send data if available */
408 if (req_bytes && mei_send_data(MEI_ADDRESS_ICC, MEI_HOST_ADDRESS,
409 req_data, req_bytes) < 0)
410 return -1;
411
412 /* Read header and data, if needed */
413 if (rsp_bytes && mei_recv_msg(&icc_rsp, sizeof(icc_rsp),
414 rsp_data, rsp_bytes) < 0)
415 return -1;
416
417 return 0;
418}
419
420/*
421 * mbp give up routine. This path is taken if hfs.mpb_rdy is 0 or the read
422 * state machine on the BIOS end doesn't match the ME's state machine.
423 */
Elyes HAOUAS040aff22018-05-27 16:30:36 +0200424static void intel_me_mbp_give_up(struct device *dev)
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700425{
426 struct mei_csr csr;
427
428 pci_write_config32(dev, PCI_ME_H_GS2, PCI_ME_MBP_GIVE_UP);
429
430 read_host_csr(&csr);
431 csr.reset = 1;
432 csr.interrupt_generate = 1;
433 write_host_csr(&csr);
434}
435
436/*
437 * mbp clear routine. This will wait for the ME to indicate that
438 * the MBP has been read and cleared.
439 */
Elyes HAOUAS040aff22018-05-27 16:30:36 +0200440static void intel_me_mbp_clear(struct device *dev)
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700441{
442 int count;
443 struct me_hfs2 hfs2;
444
445 /* Wait for the mbp_cleared indicator */
446 for (count = ME_RETRY; count > 0; --count) {
447 pci_read_dword_ptr(dev, &hfs2, PCI_ME_HFS2);
448 if (hfs2.mbp_cleared)
449 break;
450 udelay(ME_DELAY);
451 }
452
453 if (count == 0) {
454 printk(BIOS_WARNING, "ME: Timeout waiting for mbp_cleared\n");
455 intel_me_mbp_give_up(dev);
456 } else {
457 printk(BIOS_INFO, "ME: MBP cleared\n");
458 }
459}
460
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700461static void me_print_fw_version(mbp_fw_version_name *vers_name)
462{
463 if (!vers_name) {
464 printk(BIOS_ERR, "ME: mbp missing version report\n");
465 return;
466 }
467
468 printk(BIOS_DEBUG, "ME: found version %d.%d.%d.%d\n",
469 vers_name->major_version, vers_name->minor_version,
470 vers_name->hotfix_version, vers_name->build_version);
471}
472
Edward O'Callaghan8cc5dc12015-01-07 15:50:43 +1100473static inline void print_cap(const char *name, int state)
474{
475 printk(BIOS_DEBUG, "ME Capability: %-41s : %sabled\n",
476 name, state ? " en" : "dis");
477}
478
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700479/* Get ME Firmware Capabilities */
480static int mkhi_get_fwcaps(mbp_mefwcaps *cap)
481{
482 u32 rule_id = 0;
483 struct me_fwcaps cap_msg;
484 struct mkhi_header mkhi = {
485 .group_id = MKHI_GROUP_ID_FWCAPS,
486 .command = MKHI_FWCAPS_GET_RULE,
487 };
488
489 /* Send request and wait for response */
490 if (mei_sendrecv_mkhi(&mkhi, &rule_id, sizeof(u32),
491 &cap_msg, sizeof(cap_msg)) < 0) {
492 printk(BIOS_ERR, "ME: GET FWCAPS message failed\n");
493 return -1;
Lee Leahy26b7cd02017-03-16 18:47:55 -0700494 }
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700495 *cap = cap_msg.caps_sku;
496 return 0;
497}
498
499/* Get ME Firmware Capabilities */
500static void me_print_fwcaps(mbp_mefwcaps *cap)
501{
502 mbp_mefwcaps local_caps;
503 if (!cap) {
504 cap = &local_caps;
505 printk(BIOS_ERR, "ME: mbp missing fwcaps report\n");
506 if (mkhi_get_fwcaps(cap))
507 return;
508 }
509
510 print_cap("Full Network manageability", cap->full_net);
511 print_cap("Regular Network manageability", cap->std_net);
512 print_cap("Manageability", cap->manageability);
513 print_cap("IntelR Anti-Theft (AT)", cap->intel_at);
514 print_cap("IntelR Capability Licensing Service (CLS)", cap->intel_cls);
515 print_cap("IntelR Power Sharing Technology (MPC)", cap->intel_mpc);
516 print_cap("ICC Over Clocking", cap->icc_over_clocking);
Edward O'Callaghan8cc5dc12015-01-07 15:50:43 +1100517 print_cap("Protected Audio Video Path (PAVP)", cap->pavp);
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700518 print_cap("IPV6", cap->ipv6);
519 print_cap("KVM Remote Control (KVM)", cap->kvm);
520 print_cap("Outbreak Containment Heuristic (OCH)", cap->och);
521 print_cap("Virtual LAN (VLAN)", cap->vlan);
522 print_cap("TLS", cap->tls);
523 print_cap("Wireless LAN (WLAN)", cap->wlan);
524}
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700525
526/* Send END OF POST message to the ME */
527static int mkhi_end_of_post(void)
528{
529 struct mkhi_header mkhi = {
530 .group_id = MKHI_GROUP_ID_GEN,
531 .command = MKHI_END_OF_POST,
532 };
533 u32 eop_ack;
534
535 /* Send request and wait for response */
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700536 if (mei_sendrecv_mkhi(&mkhi, NULL, 0, &eop_ack, sizeof(eop_ack)) < 0) {
537 printk(BIOS_ERR, "ME: END OF POST message failed\n");
538 return -1;
539 }
540
541 printk(BIOS_INFO, "ME: END OF POST message successful (%d)\n", eop_ack);
542 return 0;
543}
544
Duncan Lauriec99681f2014-12-10 08:11:09 -0800545/* Send END OF POST message to the ME */
546static int mkhi_end_of_post_noack(void)
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700547{
Duncan Lauriec99681f2014-12-10 08:11:09 -0800548 struct mkhi_header mkhi = {
549 .group_id = MKHI_GROUP_ID_GEN,
550 .command = MKHI_END_OF_POST_NOACK,
551 };
552
553 /* Send request, do not wait for response */
554 if (mei_sendrecv_mkhi(&mkhi, NULL, 0, NULL, 0) < 0) {
555 printk(BIOS_ERR, "ME: END OF POST NOACK message failed\n");
556 return -1;
557 }
558
559 printk(BIOS_INFO, "ME: END OF POST NOACK message successful\n");
560 return 0;
561}
562
563/* Send HMRFPO LOCK message to the ME */
564static int mkhi_hmrfpo_lock(void)
565{
566 struct mkhi_header mkhi = {
567 .group_id = MKHI_GROUP_ID_HMRFPO,
568 .command = MKHI_HMRFPO_LOCK,
569 };
570 u32 ack;
571
572 /* Send request and wait for response */
573 if (mei_sendrecv_mkhi(&mkhi, NULL, 0, &ack, sizeof(ack)) < 0) {
574 printk(BIOS_ERR, "ME: HMRFPO LOCK message failed\n");
575 return -1;
576 }
577
Angel Ponscac22172018-10-01 09:56:32 +0200578 printk(BIOS_INFO, "ME: HMRFPO LOCK message successful (%d)\n", ack);
Duncan Lauriec99681f2014-12-10 08:11:09 -0800579 return 0;
580}
581
582/* Send HMRFPO LOCK message to the ME, do not wait for response */
583static int mkhi_hmrfpo_lock_noack(void)
584{
585 struct mkhi_header mkhi = {
586 .group_id = MKHI_GROUP_ID_HMRFPO,
587 .command = MKHI_HMRFPO_LOCK_NOACK,
588 };
589
590 /* Send request, do not wait for response */
591 if (mei_sendrecv_mkhi(&mkhi, NULL, 0, NULL, 0) < 0) {
592 printk(BIOS_ERR, "ME: HMRFPO LOCK NOACK message failed\n");
593 return -1;
594 }
595
Angel Ponscac22172018-10-01 09:56:32 +0200596 printk(BIOS_INFO, "ME: HMRFPO LOCK NOACK message successful\n");
Duncan Lauriec99681f2014-12-10 08:11:09 -0800597 return 0;
598}
599
Elyes HAOUAS040aff22018-05-27 16:30:36 +0200600static void intel_me_finalize(struct device *dev)
Duncan Lauriec99681f2014-12-10 08:11:09 -0800601{
Elyes HAOUASb887adf2020-04-29 10:42:34 +0200602 u16 reg16;
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700603
604 /* S3 path will have hidden this device already */
Lee Leahy26b7cd02017-03-16 18:47:55 -0700605 if (!mei_base_address || mei_base_address == (u8 *) 0xfffffff0)
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700606 return;
607
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700608 /* Make sure IO is disabled */
Elyes HAOUASb887adf2020-04-29 10:42:34 +0200609 reg16 = pci_read_config16(dev, PCI_COMMAND);
610 reg16 &= ~(PCI_COMMAND_MASTER |
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700611 PCI_COMMAND_MEMORY | PCI_COMMAND_IO);
Elyes HAOUASb887adf2020-04-29 10:42:34 +0200612 pci_write_config16(dev, PCI_COMMAND, reg16);
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700613
614 /* Hide the PCI device */
615 RCBA32_OR(FD2, PCH_DISABLE_MEI1);
Duncan Lauriec99681f2014-12-10 08:11:09 -0800616 RCBA32(FD2);
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700617}
618
619static int me_icc_set_clock_enables(u32 mask)
620{
621 struct icc_clock_enables_msg clk = {
622 .clock_enables = 0, /* Turn off specified clocks */
623 .clock_mask = mask,
624 .no_response = 1, /* Do not expect response */
625 };
626 struct icc_header icc = {
627 .api_version = ICC_API_VERSION_LYNXPOINT,
628 .icc_command = ICC_SET_CLOCK_ENABLES,
629 .length = sizeof(clk),
630 };
631
632 /* Send request and wait for response */
633 if (mei_sendrecv_icc(&icc, &clk, sizeof(clk), NULL, 0) < 0) {
634 printk(BIOS_ERR, "ME: ICC SET CLOCK ENABLES message failed\n");
635 return -1;
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700636 }
Lee Leahy8a9c7dc2017-03-17 10:43:25 -0700637 printk(BIOS_INFO, "ME: ICC SET CLOCK ENABLES 0x%08x\n", mask);
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700638 return 0;
639}
640
641/* Determine the path that we should take based on ME status */
Elyes HAOUAS040aff22018-05-27 16:30:36 +0200642static me_bios_path intel_me_path(struct device *dev)
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700643{
644 me_bios_path path = ME_DISABLE_BIOS_PATH;
645 struct me_hfs hfs;
646 struct me_hfs2 hfs2;
647
648 /* Check and dump status */
649 intel_me_status();
650
651 pci_read_dword_ptr(dev, &hfs, PCI_ME_HFS);
652 pci_read_dword_ptr(dev, &hfs2, PCI_ME_HFS2);
653
654 /* Check Current Working State */
655 switch (hfs.working_state) {
656 case ME_HFS_CWS_NORMAL:
657 path = ME_NORMAL_BIOS_PATH;
658 break;
659 case ME_HFS_CWS_REC:
660 path = ME_RECOVERY_BIOS_PATH;
661 break;
662 default:
663 path = ME_DISABLE_BIOS_PATH;
664 break;
665 }
666
667 /* Check Current Operation Mode */
668 switch (hfs.operation_mode) {
669 case ME_HFS_MODE_NORMAL:
670 break;
671 case ME_HFS_MODE_DEBUG:
672 case ME_HFS_MODE_DIS:
673 case ME_HFS_MODE_OVER_JMPR:
674 case ME_HFS_MODE_OVER_MEI:
675 default:
676 path = ME_DISABLE_BIOS_PATH;
677 break;
678 }
679
680 /* Check for any error code and valid firmware and MBP */
681 if (hfs.error_code || hfs.fpt_bad)
682 path = ME_ERROR_BIOS_PATH;
683
684 /* Check if the MBP is ready */
685 if (!hfs2.mbp_rdy) {
686 printk(BIOS_CRIT, "%s: mbp is not ready!\n",
Lee Leahy6ef51922017-03-17 10:56:08 -0700687 __func__);
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700688 path = ME_ERROR_BIOS_PATH;
689 }
690
Kyösti Mälkkibe5317f2019-11-06 12:07:21 +0200691 if (CONFIG(ELOG) && path != ME_NORMAL_BIOS_PATH) {
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700692 struct elog_event_data_me_extended data = {
693 .current_working_state = hfs.working_state,
694 .operation_state = hfs.operation_state,
695 .operation_mode = hfs.operation_mode,
696 .error_code = hfs.error_code,
697 .progress_code = hfs2.progress_code,
698 .current_pmevent = hfs2.current_pmevent,
699 .current_state = hfs2.current_state,
700 };
701 elog_add_event_byte(ELOG_TYPE_MANAGEMENT_ENGINE, path);
702 elog_add_event_raw(ELOG_TYPE_MANAGEMENT_ENGINE_EXT,
703 &data, sizeof(data));
704 }
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700705
706 return path;
707}
708
709/* Prepare ME for MEI messages */
Elyes HAOUAS040aff22018-05-27 16:30:36 +0200710static int intel_mei_setup(struct device *dev)
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700711{
712 struct resource *res;
713 struct mei_csr host;
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700714
715 /* Find the MMIO base for the ME interface */
716 res = find_resource(dev, PCI_BASE_ADDRESS_0);
717 if (!res || res->base == 0 || res->size == 0) {
718 printk(BIOS_DEBUG, "ME: MEI resource not present!\n");
719 return -1;
720 }
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800721 mei_base_address = res2mmio(res, 0, 0);
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700722
723 /* Ensure Memory and Bus Master bits are set */
Elyes HAOUASb887adf2020-04-29 10:42:34 +0200724 pci_or_config16(dev, PCI_COMMAND, PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY);
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700725
726 /* Clean up status for next message */
727 read_host_csr(&host);
728 host.interrupt_generate = 1;
729 host.ready = 1;
730 host.reset = 0;
731 write_host_csr(&host);
732
733 return 0;
734}
735
736/* Read the Extend register hash of ME firmware */
Elyes HAOUAS040aff22018-05-27 16:30:36 +0200737static int intel_me_extend_valid(struct device *dev)
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700738{
739 struct me_heres status;
740 u32 extend[8] = {0};
741 int i, count = 0;
742
743 pci_read_dword_ptr(dev, &status, PCI_ME_HERES);
744 if (!status.extend_feature_present) {
745 printk(BIOS_ERR, "ME: Extend Feature not present\n");
746 return -1;
747 }
748
749 if (!status.extend_reg_valid) {
750 printk(BIOS_ERR, "ME: Extend Register not valid\n");
751 return -1;
752 }
753
754 switch (status.extend_reg_algorithm) {
755 case PCI_ME_EXT_SHA1:
756 count = 5;
757 printk(BIOS_DEBUG, "ME: Extend SHA-1: ");
758 break;
759 case PCI_ME_EXT_SHA256:
760 count = 8;
761 printk(BIOS_DEBUG, "ME: Extend SHA-256: ");
762 break;
763 default:
764 printk(BIOS_ERR, "ME: Extend Algorithm %d unknown\n",
765 status.extend_reg_algorithm);
766 return -1;
767 }
768
769 for (i = 0; i < count; ++i) {
770 extend[i] = pci_read_config32(dev, PCI_ME_HER(i));
771 printk(BIOS_DEBUG, "%08x", extend[i]);
772 }
773 printk(BIOS_DEBUG, "\n");
774
Julius Wernercd49cce2019-03-05 16:53:33 -0800775#if CONFIG(CHROMEOS)
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700776 /* Save hash in NVS for the OS to verify */
777 chromeos_set_me_hash(extend, count);
778#endif
779
780 return 0;
781}
782
Duncan Lauriec99681f2014-12-10 08:11:09 -0800783static void intel_me_print_mbp(me_bios_payload *mbp_data)
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700784{
Duncan Lauriec99681f2014-12-10 08:11:09 -0800785 me_print_fw_version(mbp_data->fw_version_name);
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700786
Kyösti Mälkkic86fc8e2019-11-06 06:32:27 +0200787 if (CONFIG(DEBUG_INTEL_ME))
788 me_print_fwcaps(mbp_data->fw_capabilities);
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700789
Duncan Lauriec99681f2014-12-10 08:11:09 -0800790 if (mbp_data->plat_time) {
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700791 printk(BIOS_DEBUG, "ME: Wake Event to ME Reset: %u ms\n",
Duncan Lauriec99681f2014-12-10 08:11:09 -0800792 mbp_data->plat_time->wake_event_mrst_time_ms);
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700793 printk(BIOS_DEBUG, "ME: ME Reset to Platform Reset: %u ms\n",
Duncan Lauriec99681f2014-12-10 08:11:09 -0800794 mbp_data->plat_time->mrst_pltrst_time_ms);
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700795 printk(BIOS_DEBUG, "ME: Platform Reset to CPU Reset: %u ms\n",
Duncan Lauriec99681f2014-12-10 08:11:09 -0800796 mbp_data->plat_time->pltrst_cpurst_time_ms);
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700797 }
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700798}
799
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700800static u32 me_to_host_words_pending(void)
801{
802 struct mei_csr me;
803 read_me_csr(&me);
804 if (!me.ready)
805 return 0;
806 return (me.buffer_write_ptr - me.buffer_read_ptr) &
807 (me.buffer_depth - 1);
808}
809
810struct mbp_payload {
811 mbp_header header;
812 u32 data[0];
813};
814
815/*
Duncan Lauriec99681f2014-12-10 08:11:09 -0800816 * Read and print ME MBP data
817 *
818 * Return -1 to indicate a problem (give up)
819 * Return 0 to indicate success (send LOCK+EOP)
820 * Return 1 to indicate success (send LOCK+EOP with NOACK)
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700821 */
Elyes HAOUAS040aff22018-05-27 16:30:36 +0200822static int intel_me_read_mbp(me_bios_payload *mbp_data, struct device *dev)
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700823{
824 mbp_header mbp_hdr;
825 u32 me2host_pending;
826 struct mei_csr host;
827 struct me_hfs2 hfs2;
828 struct mbp_payload *mbp;
829 int i;
Duncan Lauriec99681f2014-12-10 08:11:09 -0800830 int ret = 0;
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700831
832 pci_read_dword_ptr(dev, &hfs2, PCI_ME_HFS2);
833
834 if (!hfs2.mbp_rdy) {
835 printk(BIOS_ERR, "ME: MBP not ready\n");
Duncan Lauriec99681f2014-12-10 08:11:09 -0800836 intel_me_mbp_give_up(dev);
837 return -1;
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700838 }
839
840 me2host_pending = me_to_host_words_pending();
841 if (!me2host_pending) {
842 printk(BIOS_ERR, "ME: no mbp data!\n");
Duncan Lauriec99681f2014-12-10 08:11:09 -0800843 intel_me_mbp_give_up(dev);
844 return -1;
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700845 }
846
847 /* we know for sure that at least the header is there */
848 mei_read_dword_ptr(&mbp_hdr, MEI_ME_CB_RW);
849
850 if ((mbp_hdr.num_entries > (mbp_hdr.mbp_size / 2)) ||
851 (me2host_pending < mbp_hdr.mbp_size)) {
852 printk(BIOS_ERR, "ME: mbp of %d entries, total size %d words"
853 " buffer contains %d words\n",
854 mbp_hdr.num_entries, mbp_hdr.mbp_size,
855 me2host_pending);
Duncan Lauriec99681f2014-12-10 08:11:09 -0800856 intel_me_mbp_give_up(dev);
857 return -1;
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700858 }
859 mbp = malloc(mbp_hdr.mbp_size * sizeof(u32));
Duncan Lauriec99681f2014-12-10 08:11:09 -0800860 if (!mbp) {
861 intel_me_mbp_give_up(dev);
862 return -1;
863 }
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700864
865 mbp->header = mbp_hdr;
866 me2host_pending--;
867
868 i = 0;
869 while (i != me2host_pending) {
870 mei_read_dword_ptr(&mbp->data[i], MEI_ME_CB_RW);
871 i++;
872 }
873
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700874 read_host_csr(&host);
Duncan Lauriec99681f2014-12-10 08:11:09 -0800875
876 /* Check that read and write pointers are equal. */
877 if (host.buffer_read_ptr != host.buffer_write_ptr) {
878 printk(BIOS_INFO, "ME: MBP Read/Write pointer mismatch\n");
879 printk(BIOS_INFO, "ME: MBP Waiting for MBP cleared flag\n");
880
881 /* Tell ME that the host has finished reading the MBP. */
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700882 host.interrupt_generate = 1;
Duncan Lauriec99681f2014-12-10 08:11:09 -0800883 host.reset = 0;
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700884 write_host_csr(&host);
885
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700886 /* Wait for the mbp_cleared indicator. */
887 intel_me_mbp_clear(dev);
Duncan Lauriec99681f2014-12-10 08:11:09 -0800888 } else {
889 /* Indicate NOACK messages should be used. */
890 ret = 1;
891 }
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700892
893 /* Dump out the MBP contents. */
Kyösti Mälkkic86fc8e2019-11-06 06:32:27 +0200894 if (CONFIG(DEBUG_INTEL_ME)) {
895 printk(BIOS_INFO, "ME MBP: Header: items: %d, size dw: %d\n",
896 mbp->header.num_entries, mbp->header.mbp_size);
897 for (i = 0; i < mbp->header.mbp_size - 1; i++)
898 printk(BIOS_INFO, "ME MBP: %04x: 0x%08x\n", i, mbp->data[i]);
899 }
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700900
Lee Leahy26b7cd02017-03-16 18:47:55 -0700901#define ASSIGN_FIELD_PTR(field_, val_) \
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700902 { \
903 mbp_data->field_ = (typeof(mbp_data->field_))(void *)val_; \
904 break; \
905 }
906
907 /* Setup the pointers in the me_bios_payload structure. */
908 for (i = 0; i < mbp->header.mbp_size - 1;) {
909 mbp_item_header *item = (void *)&mbp->data[i];
910
Lee Leahy26b7cd02017-03-16 18:47:55 -0700911 switch (MBP_MAKE_IDENT(item->app_id, item->item_id)) {
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700912 case MBP_IDENT(KERNEL, FW_VER):
913 ASSIGN_FIELD_PTR(fw_version_name, &mbp->data[i+1]);
914
915 case MBP_IDENT(ICC, PROFILE):
916 ASSIGN_FIELD_PTR(icc_profile, &mbp->data[i+1]);
917
918 case MBP_IDENT(INTEL_AT, STATE):
919 ASSIGN_FIELD_PTR(at_state, &mbp->data[i+1]);
920
921 case MBP_IDENT(KERNEL, FW_CAP):
922 ASSIGN_FIELD_PTR(fw_capabilities, &mbp->data[i+1]);
923
924 case MBP_IDENT(KERNEL, ROM_BIST):
925 ASSIGN_FIELD_PTR(rom_bist_data, &mbp->data[i+1]);
926
927 case MBP_IDENT(KERNEL, PLAT_KEY):
928 ASSIGN_FIELD_PTR(platform_key, &mbp->data[i+1]);
929
930 case MBP_IDENT(KERNEL, FW_TYPE):
931 ASSIGN_FIELD_PTR(fw_plat_type, &mbp->data[i+1]);
932
933 case MBP_IDENT(KERNEL, MFS_FAILURE):
934 ASSIGN_FIELD_PTR(mfsintegrity, &mbp->data[i+1]);
935
936 case MBP_IDENT(KERNEL, PLAT_TIME):
937 ASSIGN_FIELD_PTR(plat_time, &mbp->data[i+1]);
938
939 case MBP_IDENT(NFC, SUPPORT_DATA):
940 ASSIGN_FIELD_PTR(nfc_data, &mbp->data[i+1]);
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700941 }
942 i += item->length;
943 }
944 #undef ASSIGN_FIELD_PTR
945
Patrick Georgib753eeb2016-10-18 19:46:33 +0200946 free(mbp);
Duncan Lauriec99681f2014-12-10 08:11:09 -0800947 return ret;
Duncan Lauriec88c54c2014-04-30 16:36:13 -0700948}
Duncan Lauriec99681f2014-12-10 08:11:09 -0800949
950/* Check whether ME is present and do basic init */
Elyes HAOUAS040aff22018-05-27 16:30:36 +0200951static void intel_me_init(struct device *dev)
Duncan Lauriec99681f2014-12-10 08:11:09 -0800952{
Kyösti Mälkki8950cfb2019-07-13 22:16:25 +0300953 config_t *config = config_of(dev);
Duncan Lauriec99681f2014-12-10 08:11:09 -0800954 me_bios_path path = intel_me_path(dev);
955 me_bios_payload mbp_data;
956 int mbp_ret;
957 struct me_hfs hfs;
958 struct mei_csr csr;
959
960 /* Do initial setup and determine the BIOS path */
961 printk(BIOS_NOTICE, "ME: BIOS path: %s\n", me_bios_path_values[path]);
962
963 if (path == ME_NORMAL_BIOS_PATH) {
964 /* Validate the extend register */
965 intel_me_extend_valid(dev);
966}
967
968 memset(&mbp_data, 0, sizeof(mbp_data));
969
970 /*
971 * According to the ME9 BWG, BIOS is required to fetch MBP data in
972 * all boot flows except S3 Resume.
973 */
974
975 /* Prepare MEI MMIO interface */
976 if (intel_mei_setup(dev) < 0)
977 return;
978
979 /* Read ME MBP data */
980 mbp_ret = intel_me_read_mbp(&mbp_data, dev);
981 if (mbp_ret < 0)
982 return;
983 intel_me_print_mbp(&mbp_data);
984
985 /* Set clock enables according to devicetree */
Kyösti Mälkki8950cfb2019-07-13 22:16:25 +0300986 if (config->icc_clock_disable)
Duncan Lauriec99681f2014-12-10 08:11:09 -0800987 me_icc_set_clock_enables(config->icc_clock_disable);
988
989 /* Make sure ME is in a mode that expects EOP */
990 pci_read_dword_ptr(dev, &hfs, PCI_ME_HFS);
991
992 /* Abort and leave device alone if not normal mode */
993 if (hfs.fpt_bad ||
994 hfs.working_state != ME_HFS_CWS_NORMAL ||
995 hfs.operation_mode != ME_HFS_MODE_NORMAL)
996 return;
997
998 if (mbp_ret) {
999 /*
1000 * MBP Cleared wait is skipped,
1001 * Do not expect ACK and reset when complete.
1002 */
1003
1004 /* Send HMRFPO Lock command, no response */
1005 mkhi_hmrfpo_lock_noack();
1006
1007 /* Send END OF POST command, no response */
1008 mkhi_end_of_post_noack();
1009
1010 /* Assert reset and interrupt */
1011 read_host_csr(&csr);
1012 csr.interrupt_generate = 1;
1013 csr.reset = 1;
1014 write_host_csr(&csr);
1015 } else {
1016 /*
1017 * MBP Cleared wait was not skipped
1018 */
1019
1020 /* Send HMRFPO LOCK command */
1021 mkhi_hmrfpo_lock();
1022
1023 /* Send EOP command so ME stops accepting other commands */
1024 mkhi_end_of_post();
1025 }
1026}
1027
Elyes HAOUAS040aff22018-05-27 16:30:36 +02001028static void intel_me_enable(struct device *dev)
Duncan Lauriec99681f2014-12-10 08:11:09 -08001029{
Duncan Lauriec99681f2014-12-10 08:11:09 -08001030 /* Avoid talking to the device in S3 path */
Kyösti Mälkki1ec23c92015-05-29 06:18:18 +03001031 if (acpi_is_wakeup_s3()) {
Duncan Lauriec99681f2014-12-10 08:11:09 -08001032 dev->enabled = 0;
1033 pch_disable_devfn(dev);
1034 }
Duncan Lauriec99681f2014-12-10 08:11:09 -08001035}
1036
1037static struct device_operations device_ops = {
1038 .read_resources = &pci_dev_read_resources,
1039 .set_resources = &pci_dev_set_resources,
1040 .enable_resources = &pci_dev_enable_resources,
1041 .enable = &intel_me_enable,
1042 .init = &intel_me_init,
1043 .final = &intel_me_finalize,
Angel Ponscb2080f2020-10-23 15:45:44 +02001044 .ops_pci = &pci_dev_ops_pci,
Duncan Lauriec99681f2014-12-10 08:11:09 -08001045};
1046
1047static const unsigned short pci_device_ids[] = {
1048 0x9c3a, /* Low Power */
1049 0x9cba, /* WildcatPoint */
1050 0
1051};
1052
1053static const struct pci_driver intel_me __pci_driver = {
1054 .ops = &device_ops,
1055 .vendor = PCI_VENDOR_ID_INTEL,
1056 .devices = pci_device_ids,
1057};