coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
me.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
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 
11 #include <acpi/acpi.h>
12 #include <console/console.h>
13 #include <device/device.h>
14 #include <device/mmio.h>
15 #include <device/pci.h>
16 #include <device/pci_def.h>
17 #include <device/pci_ids.h>
18 #include <device/pci_ops.h>
19 #include <string.h>
20 #include <delay.h>
21 #include <elog.h>
22 
23 #include "me.h"
24 #include "pch.h"
25 
26 /* Path that the BIOS should take based on ME state */
27 static const char *me_bios_path_values[] __unused = {
28  [ME_NORMAL_BIOS_PATH] = "Normal",
29  [ME_S3WAKE_BIOS_PATH] = "S3 Wake",
30  [ME_ERROR_BIOS_PATH] = "Error",
31  [ME_RECOVERY_BIOS_PATH] = "Recovery",
32  [ME_DISABLE_BIOS_PATH] = "Disable",
33  [ME_FIRMWARE_UPDATE_BIOS_PATH] = "Firmware Update",
34 };
35 
36 /* MMIO base address for MEI interface */
38 
39 static void mei_dump(void *ptr, int dword, int offset, const char *type)
40 {
41  struct mei_csr *csr;
42 
43  if (!CONFIG(DEBUG_INTEL_ME))
44  return;
45 
46  printk(BIOS_SPEW, "%-9s[%02x] : ", type, offset);
47 
48  switch (offset) {
49  case MEI_H_CSR:
50  case MEI_ME_CSR_HA:
51  csr = ptr;
52  if (!csr) {
53  printk(BIOS_SPEW, "ERROR: 0x%08x\n", dword);
54  break;
55  }
56  printk(BIOS_SPEW, "cbd=%u cbrp=%02u cbwp=%02u ready=%u "
57  "reset=%u ig=%u is=%u ie=%u\n", csr->buffer_depth,
59  csr->ready, csr->reset, csr->interrupt_generate,
61  break;
62  case MEI_ME_CB_RW:
63  case MEI_H_CB_WW:
64  printk(BIOS_SPEW, "CB: 0x%08x\n", dword);
65  break;
66  default:
67  printk(BIOS_SPEW, "0x%08x\n", offset);
68  break;
69  }
70 }
71 
72 /*
73  * ME/MEI access helpers using memcpy to avoid aliasing.
74  */
75 
76 static inline void mei_read_dword_ptr(void *ptr, int offset)
77 {
78  u32 dword = read32(mei_base_address + (offset/sizeof(u32)));
79  memcpy(ptr, &dword, sizeof(dword));
80  mei_dump(ptr, dword, offset, "READ");
81 }
82 
83 static inline void mei_write_dword_ptr(void *ptr, int offset)
84 {
85  u32 dword = 0;
86  memcpy(&dword, ptr, sizeof(dword));
87  write32(mei_base_address + (offset/sizeof(u32)), dword);
88  mei_dump(ptr, dword, offset, "WRITE");
89 }
90 
91 #ifndef __SIMPLE_DEVICE__
92 static inline void pci_read_dword_ptr(struct device *dev,void *ptr,
93  int offset)
94 {
95  u32 dword = pci_read_config32(dev, offset);
96  memcpy(ptr, &dword, sizeof(dword));
97  mei_dump(ptr, dword, offset, "PCI READ");
98 }
99 #endif
100 
101 static inline void read_host_csr(struct mei_csr *csr)
102 {
104 }
105 
106 static inline void write_host_csr(struct mei_csr *csr)
107 {
109 }
110 
111 static inline void read_me_csr(struct mei_csr *csr)
112 {
114 }
115 
116 static inline void write_cb(u32 dword)
117 {
118  write32(mei_base_address + (MEI_H_CB_WW / sizeof(u32)), dword);
119  mei_dump(NULL, dword, MEI_H_CB_WW, "WRITE");
120 }
121 
122 static inline u32 read_cb(void)
123 {
124  u32 dword = read32(mei_base_address + (MEI_ME_CB_RW / sizeof(u32)));
125  mei_dump(NULL, dword, MEI_ME_CB_RW, "READ");
126  return dword;
127 }
128 
129 /* Wait for ME ready bit to be asserted */
130 static int mei_wait_for_me_ready(void)
131 {
132  struct mei_csr me;
133  unsigned int try = ME_RETRY;
134 
135  while (try--) {
136  read_me_csr(&me);
137  if (me.ready)
138  return 0;
139  udelay(ME_DELAY);
140  }
141 
142  printk(BIOS_ERR, "ME: failed to become ready\n");
143  return -1;
144 }
145 
146 static void mei_reset(void)
147 {
148  struct mei_csr host;
149 
150  if (mei_wait_for_me_ready() < 0)
151  return;
152 
153  /* Reset host and ME circular buffers for next message */
154  read_host_csr(&host);
155  host.reset = 1;
156  host.interrupt_generate = 1;
157  write_host_csr(&host);
158 
159  if (mei_wait_for_me_ready() < 0)
160  return;
161 
162  /* Re-init and indicate host is ready */
163  read_host_csr(&host);
164  host.interrupt_generate = 1;
165  host.ready = 1;
166  host.reset = 0;
167  write_host_csr(&host);
168 }
169 
170 static int mei_send_msg(struct mei_header *mei, struct mkhi_header *mkhi,
171  void *req_data)
172 {
173  struct mei_csr host;
174  unsigned int ndata, n;
175  u32 *data;
176 
177  /* Number of dwords to write, ignoring MKHI */
178  ndata = mei->length >> 2;
179 
180  /* Pad non-dword aligned request message length */
181  if (mei->length & 3)
182  ndata++;
183  if (!ndata) {
184  printk(BIOS_DEBUG, "ME: request does not include MKHI\n");
185  return -1;
186  }
187  ndata++; /* Add MEI header */
188 
189  /*
190  * Make sure there is still room left in the circular buffer.
191  * Reset the buffer pointers if the requested message will not fit.
192  */
193  read_host_csr(&host);
194  if ((host.buffer_depth - host.buffer_write_ptr) < ndata) {
195  printk(BIOS_ERR, "ME: circular buffer full, resetting...\n");
196  mei_reset();
197  read_host_csr(&host);
198  }
199 
200  /*
201  * This implementation does not handle splitting large messages
202  * across multiple transactions. Ensure the requested length
203  * will fit in the available circular buffer depth.
204  */
205  if ((host.buffer_depth - host.buffer_write_ptr) < ndata) {
206  printk(BIOS_ERR, "ME: message (%u) too large for buffer (%u)\n",
207  ndata + 2, host.buffer_depth);
208  return -1;
209  }
210 
211  /* Write MEI header */
213  ndata--;
214 
215  /* Write MKHI header */
217  ndata--;
218 
219  /* Write message data */
220  data = req_data;
221  for (n = 0; n < ndata; ++n)
222  write_cb(*data++);
223 
224  /* Generate interrupt to the ME */
225  read_host_csr(&host);
226  host.interrupt_generate = 1;
227  write_host_csr(&host);
228 
229  /* Make sure ME is ready after sending request data */
230  return mei_wait_for_me_ready();
231 }
232 
233 static int mei_recv_msg(struct mei_header *mei, struct mkhi_header *mkhi,
234  void *rsp_data, int rsp_bytes)
235 {
236  struct mei_header mei_rsp;
237  struct mkhi_header mkhi_rsp;
238  struct mei_csr me, host;
239  unsigned int ndata, n;
240  unsigned int expected;
241  u32 *data;
242 
243  /* Total number of dwords to read from circular buffer */
244  expected = (rsp_bytes + sizeof(mei_rsp) + sizeof(mkhi_rsp)) >> 2;
245  if (rsp_bytes & 3)
246  expected++;
247 
248  /*
249  * The interrupt status bit does not appear to indicate that the
250  * message has actually been received. Instead we wait until the
251  * expected number of dwords are present in the circular buffer.
252  */
253  for (n = ME_RETRY; n; --n) {
254  read_me_csr(&me);
255  if ((me.buffer_write_ptr - me.buffer_read_ptr) >= expected)
256  break;
257  udelay(ME_DELAY);
258  }
259  if (!n) {
260  printk(BIOS_ERR, "ME: timeout waiting for data: expected %u, available %u\n",
261  expected, me.buffer_write_ptr - me.buffer_read_ptr);
262  return -1;
263  }
264 
265  /* Read and verify MEI response header from the ME */
266  mei_read_dword_ptr(&mei_rsp, MEI_ME_CB_RW);
267  if (!mei_rsp.is_complete) {
268  printk(BIOS_ERR, "ME: response is not complete\n");
269  return -1;
270  }
271 
272  /* Handle non-dword responses and expect at least MKHI header */
273  ndata = mei_rsp.length >> 2;
274  if (mei_rsp.length & 3)
275  ndata++;
276  if (ndata != (expected - 1)) {
277  printk(BIOS_ERR, "ME: response is missing data\n");
278  return -1;
279  }
280 
281  /* Read and verify MKHI response header from the ME */
282  mei_read_dword_ptr(&mkhi_rsp, MEI_ME_CB_RW);
283  if (!mkhi_rsp.is_response ||
284  mkhi->group_id != mkhi_rsp.group_id ||
285  mkhi->command != mkhi_rsp.command) {
286  printk(BIOS_ERR, "ME: invalid response, group %u ?= %u, "
287  "command %u ?= %u, is_response %u\n", mkhi->group_id,
288  mkhi_rsp.group_id, mkhi->command, mkhi_rsp.command,
289  mkhi_rsp.is_response);
290  return -1;
291  }
292  ndata--; /* MKHI header has been read */
293 
294  /* Make sure caller passed a buffer with enough space */
295  if (ndata != (rsp_bytes >> 2)) {
296  printk(BIOS_ERR, "ME: not enough room in response buffer: %u != %u\n",
297  ndata, rsp_bytes >> 2);
298  return -1;
299  }
300 
301  /* Read response data from the circular buffer */
302  data = rsp_data;
303  for (n = 0; n < ndata; ++n)
304  *data++ = read_cb();
305 
306  /* Tell the ME that we have consumed the response */
307  read_host_csr(&host);
308  host.interrupt_status = 1;
309  host.interrupt_generate = 1;
310  write_host_csr(&host);
311 
312  return mei_wait_for_me_ready();
313 }
314 
315 static inline int mei_sendrecv(struct mei_header *mei, struct mkhi_header *mkhi,
316  void *req_data, void *rsp_data, int rsp_bytes)
317 {
318  if (mei_send_msg(mei, mkhi, req_data) < 0)
319  return -1;
320  if (mei_recv_msg(mei, mkhi, rsp_data, rsp_bytes) < 0)
321  return -1;
322  return 0;
323 }
324 
325 /* Determine the path that we should take based on ME status */
326 static me_bios_path intel_me_path(struct device *dev)
327 {
329  struct me_hfs hfs;
330  struct me_gmes gmes;
331 
332  /* S3 wake skips all MKHI messages */
333  if (acpi_is_wakeup_s3())
334  return ME_S3WAKE_BIOS_PATH;
335 
336  pci_read_dword_ptr(dev, &hfs, PCI_ME_HFS);
337  pci_read_dword_ptr(dev, &gmes, PCI_ME_GMES);
338 
339  /* Check and dump status */
340  intel_me_status(&hfs, &gmes);
341 
342  /* Check Current Working State */
343  switch (hfs.working_state) {
344  case ME_HFS_CWS_NORMAL:
345  path = ME_NORMAL_BIOS_PATH;
346  break;
347  case ME_HFS_CWS_REC:
348  path = ME_RECOVERY_BIOS_PATH;
349  break;
350  default:
351  path = ME_DISABLE_BIOS_PATH;
352  break;
353  }
354 
355  /* Check Current Operation Mode */
356  switch (hfs.operation_mode) {
357  case ME_HFS_MODE_NORMAL:
358  break;
359  case ME_HFS_MODE_DEBUG:
360  case ME_HFS_MODE_DIS:
363  default:
364  path = ME_DISABLE_BIOS_PATH;
365  break;
366  }
367 
368  /* Check for any error code and valid firmware */
369  if (hfs.error_code || hfs.fpt_bad)
370  path = ME_ERROR_BIOS_PATH;
371 
372  if (CONFIG(ELOG) && path != ME_NORMAL_BIOS_PATH) {
373  struct elog_event_data_me_extended data = {
375  .operation_state = hfs.operation_state,
376  .operation_mode = hfs.operation_mode,
377  .error_code = hfs.error_code,
378  .progress_code = gmes.progress_code,
379  .current_pmevent = gmes.current_pmevent,
380  .current_state = gmes.current_state,
381  };
384  &data, sizeof(data));
385  }
386 
387  return path;
388 }
389 
390 /* Prepare ME for MEI messages */
391 static int intel_mei_setup(struct device *dev)
392 {
393  struct resource *res;
394  struct mei_csr host;
395  u16 reg16;
396 
397  /* Find the MMIO base for the ME interface */
399  if (!res || res->base == 0 || res->size == 0) {
400  printk(BIOS_DEBUG, "ME: MEI resource not present!\n");
401  return -1;
402  }
403  mei_base_address = (u32 *)(uintptr_t)res->base;
404 
405  /* Ensure Memory and Bus Master bits are set */
406  reg16 = pci_read_config16(dev, PCI_COMMAND);
408  pci_write_config16(dev, PCI_COMMAND, reg16);
409 
410  /* Clean up status for next message */
411  read_host_csr(&host);
412  host.interrupt_generate = 1;
413  host.ready = 1;
414  host.reset = 0;
415  write_host_csr(&host);
416 
417  return 0;
418 }
419 
420 /* Read the Extend register hash of ME firmware */
421 static int intel_me_extend_valid(struct device *dev)
422 {
423  struct me_heres status;
424  u32 extend[8] = {0};
425  int i, count = 0;
426 
427  pci_read_dword_ptr(dev, &status, PCI_ME_HERES);
428  if (!status.extend_feature_present) {
429  printk(BIOS_ERR, "ME: Extend Feature not present\n");
430  return -1;
431  }
432 
433  if (!status.extend_reg_valid) {
434  printk(BIOS_ERR, "ME: Extend Register not valid\n");
435  return -1;
436  }
437 
438  switch (status.extend_reg_algorithm) {
439  case PCI_ME_EXT_SHA1:
440  count = 5;
441  printk(BIOS_DEBUG, "ME: Extend SHA-1: ");
442  break;
443  case PCI_ME_EXT_SHA256:
444  count = 8;
445  printk(BIOS_DEBUG, "ME: Extend SHA-256: ");
446  break;
447  default:
448  printk(BIOS_ERR, "ME: Extend Algorithm %d unknown\n",
449  status.extend_reg_algorithm);
450  return -1;
451  }
452 
453  for (i = 0; i < count; ++i) {
454  extend[i] = pci_read_config32(dev, PCI_ME_HER(i));
455  printk(BIOS_DEBUG, "%08x", extend[i]);
456  }
457  printk(BIOS_DEBUG, "\n");
458 
459  return 0;
460 }
461 
462 /* Hide the ME virtual PCI devices */
463 static void intel_me_hide(struct device *dev)
464 {
465  dev->enabled = 0;
466  pch_enable(dev);
467 }
468 
469 /* Check whether ME is present and do basic init */
470 static void intel_me_init(struct device *dev)
471 {
472  me_bios_path path = intel_me_path(dev);
473 
474  /* Do initial setup and determine the BIOS path */
475  printk(BIOS_NOTICE, "ME: BIOS path: %s\n", me_bios_path_values[path]);
476 
477  switch (path) {
478  case ME_S3WAKE_BIOS_PATH:
480 #if CONFIG(HIDE_MEI_ON_ERROR)
481  case ME_ERROR_BIOS_PATH:
482 #endif
483  intel_me_hide(dev);
484  break;
485 
486  case ME_NORMAL_BIOS_PATH:
487  /* Validate the extend register */
488  if (intel_me_extend_valid(dev) < 0)
489  break; /* TODO: force recovery mode */
490 
491  /* Prepare MEI MMIO interface */
492  if (intel_mei_setup(dev) < 0)
493  break;
494 
495  /*
496  * Leave the ME unlocked in this path.
497  * It will be locked via SMI command later.
498  */
499  break;
500 
501 #if !CONFIG(HIDE_MEI_ON_ERROR)
502  case ME_ERROR_BIOS_PATH:
503 #endif
506  break;
507  }
508 }
509 
510 static struct device_operations device_ops = {
512  .set_resources = pci_dev_set_resources,
513  .enable_resources = pci_dev_enable_resources,
514  .init = intel_me_init,
515  .ops_pci = &pci_dev_ops_pci,
516 };
517 
518 static const unsigned short pci_device_ids[] = {
519  0x1c3a,
521  0
522 };
523 
524 static const struct pci_driver intel_me __pci_driver = {
525  .ops = &device_ops,
526  .vendor = PCI_VID_INTEL,
527  .devices = pci_device_ids
528 };
static int acpi_is_wakeup_s3(void)
Definition: acpi.h:9
static void write32(void *addr, uint32_t val)
Definition: mmio.h:40
static uint32_t read32(const void *addr)
Definition: mmio.h:22
void * memcpy(void *dest, const void *src, size_t n)
Definition: memcpy.c:7
#define ELOG_TYPE_MANAGEMENT_ENGINE
Definition: elog.h:212
#define ELOG_TYPE_MANAGEMENT_ENGINE_EXT
Definition: elog.h:220
#define printk(level,...)
Definition: stdlib.h:16
struct resource * probe_resource(const struct device *dev, unsigned int index)
See if a resource structure already exists for a given index.
Definition: device_util.c:323
int elog_add_event_raw(u8 event_type, void *data, u8 data_size)
Definition: elog.c:798
int elog_add_event_byte(u8 event_type, u8 data)
Definition: elog.c:868
@ CONFIG
Definition: dsi_common.h:201
static size_t offset
Definition: flashconsole.c:16
static __always_inline u16 pci_read_config16(const struct device *dev, u16 reg)
Definition: pci_ops.h:52
static __always_inline u32 pci_read_config32(const struct device *dev, u16 reg)
Definition: pci_ops.h:58
static __always_inline void pci_write_config16(const struct device *dev, u16 reg, u16 val)
Definition: pci_ops.h:70
unsigned int type
Definition: edid.c:57
#define BIOS_DEBUG
BIOS_DEBUG - Verbose output.
Definition: loglevel.h:128
#define BIOS_NOTICE
BIOS_NOTICE - Unexpected but relatively insignificant.
Definition: loglevel.h:100
#define BIOS_ERR
BIOS_ERR - System in incomplete state.
Definition: loglevel.h:72
#define BIOS_SPEW
BIOS_SPEW - Excessively verbose output.
Definition: loglevel.h:142
#define PCI_COMMAND_MASTER
Definition: pci_def.h:13
#define PCI_COMMAND_MEMORY
Definition: pci_def.h:12
#define PCI_BASE_ADDRESS_0
Definition: pci_def.h:63
#define PCI_COMMAND
Definition: pci_def.h:10
void pci_dev_enable_resources(struct device *dev)
Definition: pci_device.c:721
void pci_dev_read_resources(struct device *dev)
Definition: pci_device.c:534
struct pci_operations pci_dev_ops_pci
Default device operation for PCI devices.
Definition: pci_device.c:911
void pci_dev_set_resources(struct device *dev)
Definition: pci_device.c:691
#define PCI_DID_INTEL_IBEXPEAK_HECI1
Definition: pci_ids.h:2814
#define PCI_VID_INTEL
Definition: pci_ids.h:2157
#define ME_RETRY
Definition: me.h:8
#define PCI_ME_HERES
Definition: me.h:192
#define ME_DELAY
Definition: me.h:9
#define MEI_H_CSR
Definition: me.h:209
#define ME_HFS_CWS_REC
Definition: me.h:21
#define ME_HFS_MODE_NORMAL
Definition: me.h:36
#define ME_HFS_MODE_DIS
Definition: me.h:38
#define ME_HFS_MODE_OVER_MEI
Definition: me.h:40
#define MEI_ME_CSR_HA
Definition: me.h:211
#define PCI_ME_HFS
Definition: me.h:18
#define ME_HFS_CWS_NORMAL
Definition: me.h:22
#define MEI_ME_CB_RW
Definition: me.h:210
#define PCI_ME_HER(x)
Definition: me.h:195
#define PCI_ME_EXT_SHA256
Definition: me.h:194
#define ME_HFS_MODE_OVER_JMPR
Definition: me.h:39
me_bios_path
Definition: me.h:310
@ ME_ERROR_BIOS_PATH
Definition: me.h:313
@ ME_RECOVERY_BIOS_PATH
Definition: me.h:314
@ ME_DISABLE_BIOS_PATH
Definition: me.h:315
@ ME_FIRMWARE_UPDATE_BIOS_PATH
Definition: me.h:316
@ ME_S3WAKE_BIOS_PATH
Definition: me.h:312
@ ME_NORMAL_BIOS_PATH
Definition: me.h:311
#define ME_HFS_MODE_DEBUG
Definition: me.h:37
#define MEI_H_CB_WW
Definition: me.h:208
#define PCI_ME_EXT_SHA1
Definition: me.h:193
static const char * me_bios_path_values[]
Definition: me.c:33
void intel_me_status(void)
Definition: me.c:184
#define PCI_ME_GMES
Definition: me.h:101
void pch_enable(struct device *dev)
Definition: pch.c:404
static void mei_dump(void *ptr, int dword, int offset, const char *type)
Definition: me.c:39
static struct device_operations device_ops
Definition: me.c:510
static void read_me_csr(struct mei_csr *csr)
Definition: me.c:111
static const struct pci_driver intel_me __pci_driver
Definition: me.c:524
static int mei_wait_for_me_ready(void)
Definition: me.c:130
static void read_host_csr(struct mei_csr *csr)
Definition: me.c:101
static void intel_me_hide(struct device *dev)
Definition: me.c:463
static void mei_read_dword_ptr(void *ptr, int offset)
Definition: me.c:76
static int mei_send_msg(struct mei_header *mei, struct mkhi_header *mkhi, void *req_data)
Definition: me.c:170
static void write_cb(u32 dword)
Definition: me.c:116
static void intel_me_init(struct device *dev)
Definition: me.c:470
static void mei_write_dword_ptr(void *ptr, int offset)
Definition: me.c:83
static int intel_mei_setup(struct device *dev)
Definition: me.c:391
static me_bios_path intel_me_path(struct device *dev)
Definition: me.c:326
static void write_host_csr(struct mei_csr *csr)
Definition: me.c:106
static int intel_me_extend_valid(struct device *dev)
Definition: me.c:421
static void pci_read_dword_ptr(struct device *dev, void *ptr, int offset)
Definition: me.c:92
static const unsigned short pci_device_ids[]
Definition: me.c:518
static u32 read_cb(void)
Definition: me.c:122
static void mei_reset(void)
Definition: me.c:146
static int mei_recv_msg(struct mei_header *mei, struct mkhi_header *mkhi, void *rsp_data, int rsp_bytes)
Definition: me.c:233
static u32 * mei_base_address
Definition: me.c:37
static const char *me_bios_path_values[] __unused
Definition: me.c:27
static int mei_sendrecv(struct mei_header *mei, struct mkhi_header *mkhi, void *req_data, void *rsp_data, int rsp_bytes)
Definition: me.c:315
#define NULL
Definition: stddef.h:19
uint32_t u32
Definition: stdint.h:51
unsigned long uintptr_t
Definition: stdint.h:21
uint16_t u16
Definition: stdint.h:48
void(* read_resources)(struct device *dev)
Definition: device.h:39
Definition: device.h:107
unsigned int enabled
Definition: device.h:122
uint8_t current_working_state
Definition: elog.h:229
Definition: me.h:197
u32 extend_reg_valid
Definition: me.h:201
u32 extend_reg_algorithm
Definition: me.h:198
u32 extend_feature_present
Definition: me.h:200
Definition: me.h:51
u32 fpt_bad
Definition: me.h:54
u32 operation_state
Definition: me.h:55
u32 working_state
Definition: me.h:52
u32 operation_mode
Definition: me.h:60
u32 error_code
Definition: me.h:59
Definition: me.h:213
u32 interrupt_enable
Definition: me.h:214
u32 buffer_read_ptr
Definition: me.h:220
u32 interrupt_status
Definition: me.h:215
u32 buffer_depth
Definition: me.h:222
u32 reset
Definition: me.h:218
u32 interrupt_generate
Definition: me.h:216
u32 ready
Definition: me.h:217
u32 buffer_write_ptr
Definition: me.h:221
Definition: me.h:235
u32 is_complete
Definition: me.h:240
u32 length
Definition: me.h:238
u32 is_response
Definition: me.h:261
u32 group_id
Definition: me.h:259
u32 command
Definition: me.h:260
resource_t base
Definition: resource.h:45
resource_t size
Definition: resource.h:46
void udelay(uint32_t us)
Definition: udelay.c:15
Definition: me.h:110
u32 current_pmevent
Definition: me.h:124
u32 progress_code
Definition: me.h:125
u32 current_state
Definition: me.h:123
#define count