blob: c03d9c100ba7246777f4bfbcc5daa1bd6d602d9c [file] [log] [blame]
Simon Glasscd597032013-05-23 17:18:44 -07001/*
2 * This file is part of the flashrom project.
3 *
4 * Copyright (C) 2012 Google Inc.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 *
13 * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * Neither the name of Google or the names of contributors or
18 * licensors may be used to endorse or promote products derived from this
19 * software without specific prior written permission.
20 *
21 * This software is provided "AS IS," without a warranty of any kind.
22 * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
23 * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
24 * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
25 * GOOGLE INC AND ITS LICENSORS SHALL NOT BE LIABLE
26 * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
27 * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
28 * GOOGLE OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
29 * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
30 * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
31 * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
32 * EVEN IF GOOGLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
33 */
34
Guenter Roeck51822fd2016-04-08 13:58:11 -070035#include <assert.h>
Simon Glasscd597032013-05-23 17:18:44 -070036#include <errno.h>
37#include <fcntl.h>
38#include <inttypes.h>
39#include <stdio.h>
40#include <stdlib.h>
41#include <string.h>
42#include <unistd.h>
43
44#include <sys/ioctl.h>
45#include <sys/stat.h>
46#include <sys/types.h>
47
Edward O'Callaghane40e7e72020-04-11 23:20:21 +100048#include <linux/ioctl.h>
49#include <linux/types.h>
50
Simon Glasscd597032013-05-23 17:18:44 -070051#include "file.h"
52#include "flash.h"
David Hendricksa5c5cf82014-08-11 16:40:17 -070053#include "cros_ec_commands.h"
54#include "cros_ec.h"
Simon Glasscd597032013-05-23 17:18:44 -070055#include "programmer.h"
56
David Hendricks664e3352016-09-28 16:22:52 -070057#define CROS_EC_DEV_PREFIX "/dev/cros_"
David Hendricksb907de32014-08-11 16:47:09 -070058#define CROS_EC_COMMAND_RETRIES 50
Simon Glasscd597032013-05-23 17:18:44 -070059
Duncan Laurie6a40fb92014-11-24 07:13:27 -080060int cros_ec_fd; /* File descriptor for kernel device */
Simon Glasscd597032013-05-23 17:18:44 -070061
Edward O'Callaghanaad6ac82020-07-28 16:51:22 +100062/* The names of the different device that can be found in a machine. */
63static const char *ec_type[] = {
64 "ec",
65 "pd",
66 "sh",
67 "fp",
68 "tp",
69};
70
Edward O'Callaghane40e7e72020-04-11 23:20:21 +100071/*
72 * @version: Command version number (often 0)
73 * @command: Command to send (EC_CMD_...)
74 * @outdata: Outgoing data to EC
75 * @outsize: Outgoing length in bytes
76 * @indata: Where to put the incoming data from EC
77 * @insize: Incoming length in bytes (filled in by EC)
78 * @result: EC's response to the command (separate from communication failure)
79 */
80struct cros_ec_command {
81 uint32_t version;
82 uint32_t command;
83 const uint8_t *outdata;
84 uint32_t outsize;
85 uint8_t *indata;
86 uint32_t insize;
87 uint32_t result;
88};
89
90#define CROS_EC_DEV_IOC ':'
91#define CROS_EC_DEV_IOCXCMD _IOWR(':', 0, struct cros_ec_command)
92
93/*
94 * @version: Command version number (often 0)
95 * @command: Command to send (EC_CMD_...)
96 * @outsize: Outgoing length in bytes
97 * @insize: Max number of bytes to accept from EC
98 * @result: EC's response to the command (separate from communication failure)
99 * @data: Where to put the incoming data from EC and outgoing data to EC
100 */
101struct cros_ec_command_v2 {
102 uint32_t version;
103 uint32_t command;
104 uint32_t outsize;
105 uint32_t insize;
106 uint32_t result;
107 uint8_t data[0];
108};
109
110#define CROS_EC_DEV_IOC_V2 0xEC
111#define CROS_EC_DEV_IOCXCMD_V2 _IOWR(CROS_EC_DEV_IOC_V2, 0, \
112 struct cros_ec_command_v2)
113
114#define CROS_EC_DEV_RETRY 3
115
Guenter Roeck51822fd2016-04-08 13:58:11 -0700116/* ec device interface v1 (used with Chrome OS v3.18 and earlier) */
117
Simon Glasscd597032013-05-23 17:18:44 -0700118/**
119 * Wait for a command to complete, then return the response
120 *
121 * This is called when we get an EAGAIN response from the EC. We need to
122 * send EC_CMD_GET_COMMS_STATUS commands until the EC indicates it is
123 * finished the command that we originally sent.
124 *
125 * returns 0 if command is successful, <0 to indicate timeout or error
126 */
127static int command_wait_for_response(void)
128{
129 struct ec_response_get_comms_status status;
130 struct cros_ec_command cmd;
131 int ret;
132 int i;
133
134 cmd.version = 0;
135 cmd.command = EC_CMD_GET_COMMS_STATUS;
136 cmd.outdata = NULL;
137 cmd.outsize = 0;
138 cmd.indata = (uint8_t *)&status;
139 cmd.insize = sizeof(status);
140
Simon Glass0599cae2013-07-16 13:31:53 -0600141 /* FIXME: magic delay until we fix the underlying problem (probably in
142 the kernel driver) */
143 usleep(10 * 1000);
David Hendricksb907de32014-08-11 16:47:09 -0700144 for (i = 1; i <= CROS_EC_COMMAND_RETRIES; i++) {
145 ret = ioctl(cros_ec_fd, CROS_EC_DEV_IOCXCMD, &cmd, sizeof(cmd));
Simon Glass018f0e12013-07-16 09:36:10 -0600146 if (ret < 0) {
147 msg_perr("%s(): CrOS EC command failed: %d, errno=%d\n",
148 __func__, ret, errno);
Simon Glasscd597032013-05-23 17:18:44 -0700149 ret = -EC_RES_ERROR;
150 break;
151 }
152
Simon Glass018f0e12013-07-16 09:36:10 -0600153 if (cmd.result) {
154 msg_perr("%s(): CrOS EC command failed: result=%d\n",
155 __func__, cmd.result);
156 ret = -cmd.result;
157 break;
158 }
159
Simon Glasscd597032013-05-23 17:18:44 -0700160 if (!(status.flags & EC_COMMS_STATUS_PROCESSING)) {
161 ret = -EC_RES_SUCCESS;
162 break;
163 }
164
165 usleep(1000);
166 }
167
168 return ret;
169}
170
171/*
Duncan Laurie02c368a2016-03-01 10:17:10 -0800172 * __cros_ec_command_dev - Issue command to CROS_EC device
Simon Glasscd597032013-05-23 17:18:44 -0700173 *
174 * @command: command code
175 * @outdata: data to send to EC
176 * @outsize: number of bytes in outbound payload
177 * @indata: (unallocated) buffer to store data received from EC
178 * @insize: number of bytes in inbound payload
179 *
180 * This uses the kernel Chrome OS EC driver to communicate with the EC.
181 *
182 * The outdata and indata buffers contain payload data (if any); command
183 * and response codes as well as checksum data are handled transparently by
184 * this function.
185 *
186 * Returns >=0 for success, or negative if other error.
187 */
Duncan Laurie02c368a2016-03-01 10:17:10 -0800188static int __cros_ec_command_dev(int command, int version,
Simon Glasscd597032013-05-23 17:18:44 -0700189 const void *outdata, int outsize,
190 void *indata, int insize)
191{
192 struct cros_ec_command cmd;
193 int ret;
194
195 cmd.version = version;
196 cmd.command = command;
197 cmd.outdata = outdata;
198 cmd.outsize = outsize;
199 cmd.indata = indata;
200 cmd.insize = insize;
David Hendricksb907de32014-08-11 16:47:09 -0700201 ret = ioctl(cros_ec_fd, CROS_EC_DEV_IOCXCMD, &cmd, sizeof(cmd));
Simon Glass018f0e12013-07-16 09:36:10 -0600202 if (ret < 0 && errno == EAGAIN) {
Simon Glasscd597032013-05-23 17:18:44 -0700203 ret = command_wait_for_response();
Simon Glass018f0e12013-07-16 09:36:10 -0600204 cmd.result = 0;
205 }
206 if (ret < 0) {
David Hendricks15e4dc92015-04-02 13:04:55 -0700207 msg_perr("%s(): Command 0x%02x failed: %d, errno=%d\n",
208 __func__, command, ret, errno);
Simon Glasscd597032013-05-23 17:18:44 -0700209 return -EC_RES_ERROR;
210 }
Simon Glass018f0e12013-07-16 09:36:10 -0600211 if (cmd.result) {
David Hendricks5cbeb6b2016-11-02 12:56:28 -0700212 msg_pdbg("%s(): Command 0x%02x returned result: %d\n",
Simon Glass018f0e12013-07-16 09:36:10 -0600213 __func__, command, cmd.result);
214 return -cmd.result;
215 }
Simon Glasscd597032013-05-23 17:18:44 -0700216
Simon Glass018f0e12013-07-16 09:36:10 -0600217 return ret;
Simon Glasscd597032013-05-23 17:18:44 -0700218}
219
Duncan Laurie02c368a2016-03-01 10:17:10 -0800220/*
Guenter Roeck51822fd2016-04-08 13:58:11 -0700221 * ec device interface v2
222 * (used with upstream kernel as well as with Chrome OS v4.4 and later)
223 */
224
225static int command_wait_for_response_v2(void)
226{
227 uint8_t s_cmd_buf[sizeof(struct cros_ec_command_v2) +
228 sizeof(struct ec_response_get_comms_status)];
229 struct ec_response_get_comms_status *status;
230 struct cros_ec_command_v2 *s_cmd;
231 int ret;
232 int i;
233
234 s_cmd = (struct cros_ec_command_v2 *)s_cmd_buf;
235 status = (struct ec_response_get_comms_status *)s_cmd->data;
236
237 s_cmd->version = 0;
238 s_cmd->command = EC_CMD_GET_COMMS_STATUS;
239 s_cmd->outsize = 0;
240 s_cmd->insize = sizeof(*status);
241
242 /*
243 * FIXME: magic delay until we fix the underlying problem (probably in
244 * the kernel driver)
245 */
246 usleep(10 * 1000);
247 for (i = 1; i <= CROS_EC_COMMAND_RETRIES; i++) {
248 ret = ioctl(cros_ec_fd, CROS_EC_DEV_IOCXCMD_V2, s_cmd_buf,
249 sizeof(s_cmd_buf));
Vincent Palatin9e130a22017-04-30 17:00:08 -0700250 if (ret < 0) {
Guenter Roeck51822fd2016-04-08 13:58:11 -0700251 msg_perr("%s(): CrOS EC command failed: %d, errno=%d\n",
252 __func__, ret, errno);
253 ret = -EC_RES_ERROR;
254 break;
255 }
256 if (s_cmd->result) {
257 msg_perr("%s(): CrOS EC command failed: result=%d\n",
258 __func__, s_cmd->result);
259 ret = -s_cmd->result;
260 break;
261 }
262
263 if (!(status->flags & EC_COMMS_STATUS_PROCESSING)) {
264 ret = -EC_RES_SUCCESS;
265 break;
266 }
267
268 usleep(1000);
269 }
270
271 return ret;
272}
273
274static int __cros_ec_command_dev_v2(int command, int version,
275 const void *outdata, int outsize,
276 void *indata, int insize)
277{
278 struct cros_ec_command_v2 *s_cmd;
279 int size = sizeof(struct cros_ec_command_v2) + max(outsize, insize);
280 int ret;
281
282 assert(outsize == 0 || outdata != NULL);
283 assert(insize == 0 || indata != NULL);
284
285 s_cmd = malloc(size);
286 if (s_cmd == NULL)
287 return -EC_RES_ERROR;
288
289 s_cmd->command = command;
290 s_cmd->version = version;
291 s_cmd->result = 0xff;
292 s_cmd->outsize = outsize;
293 s_cmd->insize = insize;
294 memcpy(s_cmd->data, outdata, outsize);
295
296 ret = ioctl(cros_ec_fd, CROS_EC_DEV_IOCXCMD_V2, s_cmd, size);
Vincent Palatin9e130a22017-04-30 17:00:08 -0700297 if (ret < 0 && errno == EAGAIN) {
Guenter Roeck51822fd2016-04-08 13:58:11 -0700298 ret = command_wait_for_response_v2();
299 s_cmd->result = 0;
300 }
301 if (ret < 0) {
302 msg_perr("%s(): Command 0x%02x failed: %d, errno=%d\n",
303 __func__, command, ret, errno);
304 free(s_cmd);
305 return -EC_RES_ERROR;
306 }
307 if (s_cmd->result) {
David Hendricks5cbeb6b2016-11-02 12:56:28 -0700308 msg_pdbg("%s(): Command 0x%02x returned result: %d\n",
Guenter Roeck51822fd2016-04-08 13:58:11 -0700309 __func__, command, s_cmd->result);
310 free(s_cmd);
311 return -s_cmd->result;
312 }
313
314 memcpy(indata, s_cmd->data, min(ret, insize));
315 free(s_cmd);
316 return min(ret, insize);
317}
318
319/*
320 * Attempt to communicate with kernel using old ioctl format.
321 * If it returns ENOTTY, assume that this kernel uses the new format.
322 */
323static int ec_dev_is_v2()
324{
325 struct ec_params_hello h_req = {
326 .in_data = 0xa0b0c0d0
327 };
328 struct ec_response_hello h_resp;
329 struct cros_ec_command s_cmd = { };
330 int r;
331
332 s_cmd.command = EC_CMD_HELLO;
333 s_cmd.result = 0xff;
334 s_cmd.outsize = sizeof(h_req);
335 s_cmd.outdata = (uint8_t *)&h_req;
336 s_cmd.insize = sizeof(h_resp);
337 s_cmd.indata = (uint8_t *)&h_resp;
338
339 r = ioctl(cros_ec_fd, CROS_EC_DEV_IOCXCMD, &s_cmd, sizeof(s_cmd));
340 if (r < 0 && errno == ENOTTY)
341 return 1;
342
343 return 0;
344}
345
346static int (*__cros_ec_command_dev_fn)(int command, int version,
347 const void *outdata, int outsize, void *indata, int insize);
348
349/*
Duncan Laurie02c368a2016-03-01 10:17:10 -0800350 * cros_ec_command_dev - Issue command to CROS_EC device with retry
351 *
352 * @command: command code
353 * @outdata: data to send to EC
354 * @outsize: number of bytes in outbound payload
355 * @indata: (unallocated) buffer to store data received from EC
356 * @insize: number of bytes in inbound payload
357 *
358 * This uses the kernel Chrome OS EC driver to communicate with the EC.
359 *
360 * The outdata and indata buffers contain payload data (if any); command
361 * and response codes as well as checksum data are handled transparently by
362 * this function.
363 *
364 * Returns >=0 for success, or negative if other error.
365 */
366static int cros_ec_command_dev(int command, int version,
367 const void *outdata, int outsize,
368 void *indata, int insize)
369{
370 int ret = EC_RES_ERROR;
371 int try;
372
373 for (try = 0; try < CROS_EC_DEV_RETRY; try++) {
Guenter Roeck51822fd2016-04-08 13:58:11 -0700374 ret = __cros_ec_command_dev_fn(command, version, outdata,
375 outsize, indata, insize);
Duncan Laurie02c368a2016-03-01 10:17:10 -0800376 if (ret >= 0)
377 return ret;
378 }
379
380 return ret;
381}
382
Edward O'Callaghan1003ec02020-07-28 16:54:34 +1000383static void cros_ec_set_max_size(struct cros_ec_priv *priv, struct opaque_master *op)
384{
385 struct ec_response_get_protocol_info info;
386 int rc = 0;
387
388 msg_pdbg("%s: sending protoinfo command\n", __func__);
389 rc = priv->ec_command(EC_CMD_GET_PROTOCOL_INFO, 0, NULL, 0,
390 &info, sizeof(info));
391 msg_pdbg("%s: rc:%d\n", __func__, rc);
392
393 /*
394 * Use V3 large size only if v2 protocol is not supported.
395 * When v2 is supported, we may be using a kernel without v3 support,
396 * leading to sending larger commands the kernel can support.
397 */
398 if (rc == sizeof(info) && ((info.protocol_versions & (1<<2)) == 0)) {
Sam McNally6ac63c12020-10-27 10:12:19 +1100399 /* Allow overriding the max response size in case EC is incorrect */
400 if (priv->max_response_size)
401 info.max_response_packet_size = priv->max_response_size;
402
Edward O'Callaghan1003ec02020-07-28 16:54:34 +1000403 op->max_data_write = info.max_request_packet_size -
404 sizeof(struct ec_host_request);
405 op->max_data_read = info.max_response_packet_size -
406 sizeof(struct ec_host_response);
407 /*
408 * Due to a bug in NPCX SPI code (chromium:725580),
409 * The EC may responds 163 when it meant 160; it should not
410 * have included header and footer.
411 */
412 op->max_data_read &= ~3;
413 msg_pdbg("%s: max_write:%d max_read:%d\n", __func__,
414 op->max_data_write, op->max_data_read);
415 }
416}
417
Edward O'Callaghanaad6ac82020-07-28 16:51:22 +1000418/*
419 * Returns 0 to indicate success, non-zero otherwise
420 *
421 * This function parses programmer parameters from the command line. Since
422 * CrOS EC hangs off the "internal programmer" (AP, PCH, etc) this gets
423 * run during internal programmer initialization.
424 */
425static int cros_ec_parse_param(struct cros_ec_priv *priv)
426{
427 char *p;
428
429 p = extract_programmer_param("type");
430 if (p) {
431 unsigned int index;
432 for (index = 0; index < ARRAY_SIZE(ec_type); index++)
433 if (!strcmp(p, ec_type[index]))
434 break;
435 if (index == ARRAY_SIZE(ec_type)) {
436 msg_perr("Invalid argument: \"%s\"\n", p);
437 free(p);
438 return 1;
439 }
440 priv->dev = ec_type[index];
441 msg_pdbg("Target %s used\n", priv->dev);
442 }
443 free(p);
444
445 p = extract_programmer_param("block");
446 if (p) {
447 unsigned int block;
448 char *endptr = NULL;
449
450 errno = 0;
451 block = strtoul(p, &endptr, 0);
452 if (errno || (strlen(p) > 10) || (endptr != (p + strlen(p)))) {
453 msg_perr("Invalid argument: \"%s\"\n", p);
454 free(p);
455 return 1;
456 }
457
458 if (block <= 0) {
459 msg_perr("%s: Invalid block size\n", __func__);
460 free(p);
461 return 1;
462 }
463
464 msg_pdbg("Override block size to 0x%x\n", block);
465 priv->erase_block_size = block;
466 }
467 free(p);
468
Sam McNally6ac63c12020-10-27 10:12:19 +1100469 p = extract_programmer_param("max_response_size");
470 if (p) {
471 unsigned int max_response_size;
472 char *endptr = NULL;
473
474 errno = 0;
475 max_response_size = strtoul(p, &endptr, 0);
476 if (errno || (strlen(p) > 10) || (endptr != (p + strlen(p)))) {
477 msg_perr("Invalid max_response_size: \"%s\"\n", p);
478 free(p);
479 return 1;
480 }
481
482 if (max_response_size <= 0) {
483 msg_perr("%s: Invalid max_response_size\n", __func__);
484 free(p);
485 return 1;
486 }
487
488 msg_pdbg("Override max response size to 0x%x\n", max_response_size);
489 priv->max_response_size = max_response_size;
490 }
491 free(p);
492
Edward O'Callaghanaad6ac82020-07-28 16:51:22 +1000493 return 0;
494}
495
Edward O'Callaghan6aaca912020-07-28 17:06:20 +1000496/* perform basic "hello" test to see if we can talk to the EC */
497static int cros_ec_test(struct cros_ec_priv *priv)
498{
499 struct ec_params_hello request;
500 struct ec_response_hello response;
501 int rc = 0;
502
503 /* Say hello to EC. */
504 request.in_data = 0xf0e0d0c0; /* Expect EC will add on 0x01020304. */
505 msg_pdbg("%s: sending HELLO request with 0x%08x\n",
506 __func__, request.in_data);
507 rc = priv->ec_command(EC_CMD_HELLO, 0, &request,
508 sizeof(request), &response, sizeof(response));
509 msg_pdbg("%s: response: 0x%08x\n", __func__, response.out_data);
510
511 if (rc < 0 || response.out_data != 0xf1e2d3c4) {
512 msg_pdbg("response.out_data is not 0xf1e2d3c4.\n"
513 "rc=%d, request=0x%x response=0x%x\n",
514 rc, request.in_data, response.out_data);
515 return 1;
516 }
517
518 return 0;
519}
520
Edward O'Callaghanaad6ac82020-07-28 16:51:22 +1000521
David Hendricksb907de32014-08-11 16:47:09 -0700522static struct cros_ec_priv cros_ec_dev_priv = {
Simon Glasscd597032013-05-23 17:18:44 -0700523 .detected = 0,
David Hendricksb907de32014-08-11 16:47:09 -0700524 .ec_command = cros_ec_command_dev,
Gwendal Grignou94e87d62014-11-25 15:34:15 -0800525 .dev = "ec",
Simon Glasscd597032013-05-23 17:18:44 -0700526};
527
Edward O'Callaghanabd30192019-05-14 15:58:19 +1000528static struct opaque_master opaque_master_cros_ec_dev = {
David Hendricks2d6db772013-07-10 21:07:48 -0700529 .max_data_read = 128,
530 .max_data_write = 128,
David Hendricksb907de32014-08-11 16:47:09 -0700531 .probe = cros_ec_probe_size,
532 .read = cros_ec_read,
533 .write = cros_ec_write,
534 .erase = cros_ec_block_erase,
Simon Glasscd597032013-05-23 17:18:44 -0700535};
536
David Hendricks93784b42016-08-09 17:00:38 -0700537static int cros_ec_dev_shutdown(void *data)
David Hendrickse3ab2f12013-06-20 22:14:26 -0700538{
David Hendricksb907de32014-08-11 16:47:09 -0700539 close(cros_ec_fd);
David Hendrickse3ab2f12013-06-20 22:14:26 -0700540 return 0;
541}
542
David Hendricksac1d25c2016-08-09 17:00:58 -0700543int cros_ec_probe_dev(void)
Simon Glasscd597032013-05-23 17:18:44 -0700544{
David Hendricks664e3352016-09-28 16:22:52 -0700545 char dev_path[32];
Duncan Laurie6a40fb92014-11-24 07:13:27 -0800546
David Hendricks14935fe2014-08-14 17:38:24 -0700547 if (cros_ec_parse_param(&cros_ec_dev_priv))
548 return 1;
549
David Hendricks664e3352016-09-28 16:22:52 -0700550 snprintf(dev_path, sizeof(dev_path), "%s%s",
551 CROS_EC_DEV_PREFIX, cros_ec_dev_priv.dev);
Duncan Laurie6a40fb92014-11-24 07:13:27 -0800552
David Hendricks664e3352016-09-28 16:22:52 -0700553 msg_pdbg("%s: probing for CROS_EC at %s\n", __func__, dev_path);
554 cros_ec_fd = open(dev_path, O_RDWR);
David Hendricksb907de32014-08-11 16:47:09 -0700555 if (cros_ec_fd < 0)
556 return cros_ec_fd;
Simon Glasscd597032013-05-23 17:18:44 -0700557
Guenter Roeck51822fd2016-04-08 13:58:11 -0700558 if (ec_dev_is_v2())
559 __cros_ec_command_dev_fn = __cros_ec_command_dev_v2;
560 else
561 __cros_ec_command_dev_fn = __cros_ec_command_dev;
562
David Hendricksb907de32014-08-11 16:47:09 -0700563 if (cros_ec_test(&cros_ec_dev_priv))
David Hendricks31d487e2013-11-04 17:49:00 -0800564 return 1;
565
Edward O'Callaghanabd30192019-05-14 15:58:19 +1000566 cros_ec_set_max_size(&cros_ec_dev_priv, &opaque_master_cros_ec_dev);
Puthikorn Voravootivatc0993cf2014-08-28 16:04:58 -0700567
Edward O'Callaghanc66827e2020-10-09 12:22:04 +1100568 internal_buses_supported &= ~(BUS_LPC|BUS_SPI);
569
David Hendricks664e3352016-09-28 16:22:52 -0700570 msg_pdbg("CROS_EC detected at %s\n", dev_path);
Edward O'Callaghanabd30192019-05-14 15:58:19 +1000571 register_opaque_master(&opaque_master_cros_ec_dev);
David Hendricksb907de32014-08-11 16:47:09 -0700572 register_shutdown(cros_ec_dev_shutdown, NULL);
573 cros_ec_dev_priv.detected = 1;
Souvik Ghosh586968a2016-08-11 17:56:24 -0700574 cros_ec_priv = &cros_ec_dev_priv;
Simon Glasscd597032013-05-23 17:18:44 -0700575
576 return 0;
577}