blob: b7f1c97179370d9702dd498bf984f11252f882fc [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 "flash.h"
David Hendricksa5c5cf82014-08-11 16:40:17 -070052#include "cros_ec_commands.h"
53#include "cros_ec.h"
Simon Glasscd597032013-05-23 17:18:44 -070054#include "programmer.h"
55
David Hendricks664e3352016-09-28 16:22:52 -070056#define CROS_EC_DEV_PREFIX "/dev/cros_"
David Hendricksb907de32014-08-11 16:47:09 -070057#define CROS_EC_COMMAND_RETRIES 50
Simon Glasscd597032013-05-23 17:18:44 -070058
Duncan Laurie6a40fb92014-11-24 07:13:27 -080059int cros_ec_fd; /* File descriptor for kernel device */
Simon Glasscd597032013-05-23 17:18:44 -070060
Edward O'Callaghanaad6ac82020-07-28 16:51:22 +100061/* The names of the different device that can be found in a machine. */
62static const char *ec_type[] = {
63 "ec",
64 "pd",
65 "sh",
66 "fp",
67 "tp",
68};
69
Edward O'Callaghane40e7e72020-04-11 23:20:21 +100070/*
71 * @version: Command version number (often 0)
72 * @command: Command to send (EC_CMD_...)
73 * @outdata: Outgoing data to EC
74 * @outsize: Outgoing length in bytes
75 * @indata: Where to put the incoming data from EC
76 * @insize: Incoming length in bytes (filled in by EC)
77 * @result: EC's response to the command (separate from communication failure)
78 */
79struct cros_ec_command {
80 uint32_t version;
81 uint32_t command;
82 const uint8_t *outdata;
83 uint32_t outsize;
84 uint8_t *indata;
85 uint32_t insize;
86 uint32_t result;
87};
88
89#define CROS_EC_DEV_IOC ':'
90#define CROS_EC_DEV_IOCXCMD _IOWR(':', 0, struct cros_ec_command)
91
92/*
93 * @version: Command version number (often 0)
94 * @command: Command to send (EC_CMD_...)
95 * @outsize: Outgoing length in bytes
96 * @insize: Max number of bytes to accept from EC
97 * @result: EC's response to the command (separate from communication failure)
98 * @data: Where to put the incoming data from EC and outgoing data to EC
99 */
100struct cros_ec_command_v2 {
101 uint32_t version;
102 uint32_t command;
103 uint32_t outsize;
104 uint32_t insize;
105 uint32_t result;
106 uint8_t data[0];
107};
108
109#define CROS_EC_DEV_IOC_V2 0xEC
110#define CROS_EC_DEV_IOCXCMD_V2 _IOWR(CROS_EC_DEV_IOC_V2, 0, \
111 struct cros_ec_command_v2)
112
113#define CROS_EC_DEV_RETRY 3
114
Guenter Roeck51822fd2016-04-08 13:58:11 -0700115/* ec device interface v1 (used with Chrome OS v3.18 and earlier) */
116
Simon Glasscd597032013-05-23 17:18:44 -0700117/**
118 * Wait for a command to complete, then return the response
119 *
120 * This is called when we get an EAGAIN response from the EC. We need to
121 * send EC_CMD_GET_COMMS_STATUS commands until the EC indicates it is
122 * finished the command that we originally sent.
123 *
124 * returns 0 if command is successful, <0 to indicate timeout or error
125 */
126static int command_wait_for_response(void)
127{
128 struct ec_response_get_comms_status status;
129 struct cros_ec_command cmd;
130 int ret;
131 int i;
132
133 cmd.version = 0;
134 cmd.command = EC_CMD_GET_COMMS_STATUS;
135 cmd.outdata = NULL;
136 cmd.outsize = 0;
137 cmd.indata = (uint8_t *)&status;
138 cmd.insize = sizeof(status);
139
Simon Glass0599cae2013-07-16 13:31:53 -0600140 /* FIXME: magic delay until we fix the underlying problem (probably in
141 the kernel driver) */
142 usleep(10 * 1000);
David Hendricksb907de32014-08-11 16:47:09 -0700143 for (i = 1; i <= CROS_EC_COMMAND_RETRIES; i++) {
144 ret = ioctl(cros_ec_fd, CROS_EC_DEV_IOCXCMD, &cmd, sizeof(cmd));
Simon Glass018f0e12013-07-16 09:36:10 -0600145 if (ret < 0) {
146 msg_perr("%s(): CrOS EC command failed: %d, errno=%d\n",
147 __func__, ret, errno);
Simon Glasscd597032013-05-23 17:18:44 -0700148 ret = -EC_RES_ERROR;
149 break;
150 }
151
Simon Glass018f0e12013-07-16 09:36:10 -0600152 if (cmd.result) {
153 msg_perr("%s(): CrOS EC command failed: result=%d\n",
154 __func__, cmd.result);
155 ret = -cmd.result;
156 break;
157 }
158
Simon Glasscd597032013-05-23 17:18:44 -0700159 if (!(status.flags & EC_COMMS_STATUS_PROCESSING)) {
160 ret = -EC_RES_SUCCESS;
161 break;
162 }
163
164 usleep(1000);
165 }
166
167 return ret;
168}
169
170/*
Duncan Laurie02c368a2016-03-01 10:17:10 -0800171 * __cros_ec_command_dev - Issue command to CROS_EC device
Simon Glasscd597032013-05-23 17:18:44 -0700172 *
173 * @command: command code
174 * @outdata: data to send to EC
175 * @outsize: number of bytes in outbound payload
176 * @indata: (unallocated) buffer to store data received from EC
177 * @insize: number of bytes in inbound payload
178 *
179 * This uses the kernel Chrome OS EC driver to communicate with the EC.
180 *
181 * The outdata and indata buffers contain payload data (if any); command
182 * and response codes as well as checksum data are handled transparently by
183 * this function.
184 *
185 * Returns >=0 for success, or negative if other error.
186 */
Duncan Laurie02c368a2016-03-01 10:17:10 -0800187static int __cros_ec_command_dev(int command, int version,
Simon Glasscd597032013-05-23 17:18:44 -0700188 const void *outdata, int outsize,
189 void *indata, int insize)
190{
191 struct cros_ec_command cmd;
192 int ret;
193
194 cmd.version = version;
195 cmd.command = command;
196 cmd.outdata = outdata;
197 cmd.outsize = outsize;
198 cmd.indata = indata;
199 cmd.insize = insize;
David Hendricksb907de32014-08-11 16:47:09 -0700200 ret = ioctl(cros_ec_fd, CROS_EC_DEV_IOCXCMD, &cmd, sizeof(cmd));
Simon Glass018f0e12013-07-16 09:36:10 -0600201 if (ret < 0 && errno == EAGAIN) {
Simon Glasscd597032013-05-23 17:18:44 -0700202 ret = command_wait_for_response();
Simon Glass018f0e12013-07-16 09:36:10 -0600203 cmd.result = 0;
204 }
205 if (ret < 0) {
David Hendricks15e4dc92015-04-02 13:04:55 -0700206 msg_perr("%s(): Command 0x%02x failed: %d, errno=%d\n",
207 __func__, command, ret, errno);
Simon Glasscd597032013-05-23 17:18:44 -0700208 return -EC_RES_ERROR;
209 }
Simon Glass018f0e12013-07-16 09:36:10 -0600210 if (cmd.result) {
David Hendricks5cbeb6b2016-11-02 12:56:28 -0700211 msg_pdbg("%s(): Command 0x%02x returned result: %d\n",
Simon Glass018f0e12013-07-16 09:36:10 -0600212 __func__, command, cmd.result);
213 return -cmd.result;
214 }
Simon Glasscd597032013-05-23 17:18:44 -0700215
Simon Glass018f0e12013-07-16 09:36:10 -0600216 return ret;
Simon Glasscd597032013-05-23 17:18:44 -0700217}
218
Duncan Laurie02c368a2016-03-01 10:17:10 -0800219/*
Guenter Roeck51822fd2016-04-08 13:58:11 -0700220 * ec device interface v2
221 * (used with upstream kernel as well as with Chrome OS v4.4 and later)
222 */
223
224static int command_wait_for_response_v2(void)
225{
226 uint8_t s_cmd_buf[sizeof(struct cros_ec_command_v2) +
227 sizeof(struct ec_response_get_comms_status)];
228 struct ec_response_get_comms_status *status;
229 struct cros_ec_command_v2 *s_cmd;
230 int ret;
231 int i;
232
233 s_cmd = (struct cros_ec_command_v2 *)s_cmd_buf;
234 status = (struct ec_response_get_comms_status *)s_cmd->data;
235
236 s_cmd->version = 0;
237 s_cmd->command = EC_CMD_GET_COMMS_STATUS;
238 s_cmd->outsize = 0;
239 s_cmd->insize = sizeof(*status);
240
241 /*
242 * FIXME: magic delay until we fix the underlying problem (probably in
243 * the kernel driver)
244 */
245 usleep(10 * 1000);
246 for (i = 1; i <= CROS_EC_COMMAND_RETRIES; i++) {
247 ret = ioctl(cros_ec_fd, CROS_EC_DEV_IOCXCMD_V2, s_cmd_buf,
248 sizeof(s_cmd_buf));
Vincent Palatin9e130a22017-04-30 17:00:08 -0700249 if (ret < 0) {
Guenter Roeck51822fd2016-04-08 13:58:11 -0700250 msg_perr("%s(): CrOS EC command failed: %d, errno=%d\n",
251 __func__, ret, errno);
252 ret = -EC_RES_ERROR;
253 break;
254 }
255 if (s_cmd->result) {
256 msg_perr("%s(): CrOS EC command failed: result=%d\n",
257 __func__, s_cmd->result);
258 ret = -s_cmd->result;
259 break;
260 }
261
262 if (!(status->flags & EC_COMMS_STATUS_PROCESSING)) {
263 ret = -EC_RES_SUCCESS;
264 break;
265 }
266
267 usleep(1000);
268 }
269
270 return ret;
271}
272
273static int __cros_ec_command_dev_v2(int command, int version,
274 const void *outdata, int outsize,
275 void *indata, int insize)
276{
277 struct cros_ec_command_v2 *s_cmd;
278 int size = sizeof(struct cros_ec_command_v2) + max(outsize, insize);
279 int ret;
280
281 assert(outsize == 0 || outdata != NULL);
282 assert(insize == 0 || indata != NULL);
283
284 s_cmd = malloc(size);
285 if (s_cmd == NULL)
286 return -EC_RES_ERROR;
287
288 s_cmd->command = command;
289 s_cmd->version = version;
290 s_cmd->result = 0xff;
291 s_cmd->outsize = outsize;
292 s_cmd->insize = insize;
293 memcpy(s_cmd->data, outdata, outsize);
294
295 ret = ioctl(cros_ec_fd, CROS_EC_DEV_IOCXCMD_V2, s_cmd, size);
Vincent Palatin9e130a22017-04-30 17:00:08 -0700296 if (ret < 0 && errno == EAGAIN) {
Guenter Roeck51822fd2016-04-08 13:58:11 -0700297 ret = command_wait_for_response_v2();
298 s_cmd->result = 0;
299 }
300 if (ret < 0) {
301 msg_perr("%s(): Command 0x%02x failed: %d, errno=%d\n",
302 __func__, command, ret, errno);
303 free(s_cmd);
304 return -EC_RES_ERROR;
305 }
306 if (s_cmd->result) {
David Hendricks5cbeb6b2016-11-02 12:56:28 -0700307 msg_pdbg("%s(): Command 0x%02x returned result: %d\n",
Guenter Roeck51822fd2016-04-08 13:58:11 -0700308 __func__, command, s_cmd->result);
309 free(s_cmd);
310 return -s_cmd->result;
311 }
312
313 memcpy(indata, s_cmd->data, min(ret, insize));
314 free(s_cmd);
315 return min(ret, insize);
316}
317
318/*
319 * Attempt to communicate with kernel using old ioctl format.
320 * If it returns ENOTTY, assume that this kernel uses the new format.
321 */
322static int ec_dev_is_v2()
323{
324 struct ec_params_hello h_req = {
325 .in_data = 0xa0b0c0d0
326 };
327 struct ec_response_hello h_resp;
328 struct cros_ec_command s_cmd = { };
329 int r;
330
331 s_cmd.command = EC_CMD_HELLO;
332 s_cmd.result = 0xff;
333 s_cmd.outsize = sizeof(h_req);
334 s_cmd.outdata = (uint8_t *)&h_req;
335 s_cmd.insize = sizeof(h_resp);
336 s_cmd.indata = (uint8_t *)&h_resp;
337
338 r = ioctl(cros_ec_fd, CROS_EC_DEV_IOCXCMD, &s_cmd, sizeof(s_cmd));
339 if (r < 0 && errno == ENOTTY)
340 return 1;
341
342 return 0;
343}
344
345static int (*__cros_ec_command_dev_fn)(int command, int version,
346 const void *outdata, int outsize, void *indata, int insize);
347
348/*
Duncan Laurie02c368a2016-03-01 10:17:10 -0800349 * cros_ec_command_dev - Issue command to CROS_EC device with retry
350 *
351 * @command: command code
352 * @outdata: data to send to EC
353 * @outsize: number of bytes in outbound payload
354 * @indata: (unallocated) buffer to store data received from EC
355 * @insize: number of bytes in inbound payload
356 *
357 * This uses the kernel Chrome OS EC driver to communicate with the EC.
358 *
359 * The outdata and indata buffers contain payload data (if any); command
360 * and response codes as well as checksum data are handled transparently by
361 * this function.
362 *
363 * Returns >=0 for success, or negative if other error.
364 */
365static int cros_ec_command_dev(int command, int version,
366 const void *outdata, int outsize,
367 void *indata, int insize)
368{
369 int ret = EC_RES_ERROR;
370 int try;
371
372 for (try = 0; try < CROS_EC_DEV_RETRY; try++) {
Guenter Roeck51822fd2016-04-08 13:58:11 -0700373 ret = __cros_ec_command_dev_fn(command, version, outdata,
374 outsize, indata, insize);
Duncan Laurie02c368a2016-03-01 10:17:10 -0800375 if (ret >= 0)
376 return ret;
377 }
378
379 return ret;
380}
381
Edward O'Callaghan1003ec02020-07-28 16:54:34 +1000382static void cros_ec_set_max_size(struct cros_ec_priv *priv, struct opaque_master *op)
383{
384 struct ec_response_get_protocol_info info;
385 int rc = 0;
386
387 msg_pdbg("%s: sending protoinfo command\n", __func__);
388 rc = priv->ec_command(EC_CMD_GET_PROTOCOL_INFO, 0, NULL, 0,
389 &info, sizeof(info));
390 msg_pdbg("%s: rc:%d\n", __func__, rc);
391
392 /*
393 * Use V3 large size only if v2 protocol is not supported.
394 * When v2 is supported, we may be using a kernel without v3 support,
395 * leading to sending larger commands the kernel can support.
396 */
397 if (rc == sizeof(info) && ((info.protocol_versions & (1<<2)) == 0)) {
Sam McNally6ac63c12020-10-27 10:12:19 +1100398 /* Allow overriding the max response size in case EC is incorrect */
399 if (priv->max_response_size)
400 info.max_response_packet_size = priv->max_response_size;
401
Edward O'Callaghan1003ec02020-07-28 16:54:34 +1000402 op->max_data_write = info.max_request_packet_size -
403 sizeof(struct ec_host_request);
404 op->max_data_read = info.max_response_packet_size -
405 sizeof(struct ec_host_response);
406 /*
407 * Due to a bug in NPCX SPI code (chromium:725580),
408 * The EC may responds 163 when it meant 160; it should not
409 * have included header and footer.
410 */
411 op->max_data_read &= ~3;
412 msg_pdbg("%s: max_write:%d max_read:%d\n", __func__,
413 op->max_data_write, op->max_data_read);
414 }
415}
416
Edward O'Callaghanaad6ac82020-07-28 16:51:22 +1000417/*
418 * Returns 0 to indicate success, non-zero otherwise
419 *
420 * This function parses programmer parameters from the command line. Since
421 * CrOS EC hangs off the "internal programmer" (AP, PCH, etc) this gets
422 * run during internal programmer initialization.
423 */
424static int cros_ec_parse_param(struct cros_ec_priv *priv)
425{
426 char *p;
427
428 p = extract_programmer_param("type");
429 if (p) {
430 unsigned int index;
431 for (index = 0; index < ARRAY_SIZE(ec_type); index++)
432 if (!strcmp(p, ec_type[index]))
433 break;
434 if (index == ARRAY_SIZE(ec_type)) {
435 msg_perr("Invalid argument: \"%s\"\n", p);
436 free(p);
437 return 1;
438 }
439 priv->dev = ec_type[index];
440 msg_pdbg("Target %s used\n", priv->dev);
441 }
442 free(p);
443
444 p = extract_programmer_param("block");
445 if (p) {
446 unsigned int block;
447 char *endptr = NULL;
448
449 errno = 0;
450 block = strtoul(p, &endptr, 0);
451 if (errno || (strlen(p) > 10) || (endptr != (p + strlen(p)))) {
452 msg_perr("Invalid argument: \"%s\"\n", p);
453 free(p);
454 return 1;
455 }
456
457 if (block <= 0) {
458 msg_perr("%s: Invalid block size\n", __func__);
459 free(p);
460 return 1;
461 }
462
463 msg_pdbg("Override block size to 0x%x\n", block);
464 priv->erase_block_size = block;
465 }
466 free(p);
467
Sam McNally6ac63c12020-10-27 10:12:19 +1100468 p = extract_programmer_param("max_response_size");
469 if (p) {
470 unsigned int max_response_size;
471 char *endptr = NULL;
472
473 errno = 0;
474 max_response_size = strtoul(p, &endptr, 0);
475 if (errno || (strlen(p) > 10) || (endptr != (p + strlen(p)))) {
476 msg_perr("Invalid max_response_size: \"%s\"\n", p);
477 free(p);
478 return 1;
479 }
480
481 if (max_response_size <= 0) {
482 msg_perr("%s: Invalid max_response_size\n", __func__);
483 free(p);
484 return 1;
485 }
486
487 msg_pdbg("Override max response size to 0x%x\n", max_response_size);
488 priv->max_response_size = max_response_size;
489 }
490 free(p);
491
Edward O'Callaghanaad6ac82020-07-28 16:51:22 +1000492 return 0;
493}
494
Edward O'Callaghan6aaca912020-07-28 17:06:20 +1000495/* perform basic "hello" test to see if we can talk to the EC */
496static int cros_ec_test(struct cros_ec_priv *priv)
497{
498 struct ec_params_hello request;
499 struct ec_response_hello response;
500 int rc = 0;
501
502 /* Say hello to EC. */
503 request.in_data = 0xf0e0d0c0; /* Expect EC will add on 0x01020304. */
504 msg_pdbg("%s: sending HELLO request with 0x%08x\n",
505 __func__, request.in_data);
506 rc = priv->ec_command(EC_CMD_HELLO, 0, &request,
507 sizeof(request), &response, sizeof(response));
508 msg_pdbg("%s: response: 0x%08x\n", __func__, response.out_data);
509
510 if (rc < 0 || response.out_data != 0xf1e2d3c4) {
511 msg_pdbg("response.out_data is not 0xf1e2d3c4.\n"
512 "rc=%d, request=0x%x response=0x%x\n",
513 rc, request.in_data, response.out_data);
514 return 1;
515 }
516
517 return 0;
518}
519
Edward O'Callaghanaad6ac82020-07-28 16:51:22 +1000520
David Hendricksb907de32014-08-11 16:47:09 -0700521static struct cros_ec_priv cros_ec_dev_priv = {
Simon Glasscd597032013-05-23 17:18:44 -0700522 .detected = 0,
David Hendricksb907de32014-08-11 16:47:09 -0700523 .ec_command = cros_ec_command_dev,
Gwendal Grignou94e87d62014-11-25 15:34:15 -0800524 .dev = "ec",
Simon Glasscd597032013-05-23 17:18:44 -0700525};
526
Edward O'Callaghanabd30192019-05-14 15:58:19 +1000527static struct opaque_master opaque_master_cros_ec_dev = {
David Hendricks2d6db772013-07-10 21:07:48 -0700528 .max_data_read = 128,
529 .max_data_write = 128,
David Hendricksb907de32014-08-11 16:47:09 -0700530 .probe = cros_ec_probe_size,
531 .read = cros_ec_read,
532 .write = cros_ec_write,
533 .erase = cros_ec_block_erase,
Simon Glasscd597032013-05-23 17:18:44 -0700534};
535
David Hendricks93784b42016-08-09 17:00:38 -0700536static int cros_ec_dev_shutdown(void *data)
David Hendrickse3ab2f12013-06-20 22:14:26 -0700537{
David Hendricksb907de32014-08-11 16:47:09 -0700538 close(cros_ec_fd);
David Hendrickse3ab2f12013-06-20 22:14:26 -0700539 return 0;
540}
541
David Hendricksac1d25c2016-08-09 17:00:58 -0700542int cros_ec_probe_dev(void)
Simon Glasscd597032013-05-23 17:18:44 -0700543{
David Hendricks664e3352016-09-28 16:22:52 -0700544 char dev_path[32];
Duncan Laurie6a40fb92014-11-24 07:13:27 -0800545
David Hendricks14935fe2014-08-14 17:38:24 -0700546 if (cros_ec_parse_param(&cros_ec_dev_priv))
547 return 1;
548
David Hendricks664e3352016-09-28 16:22:52 -0700549 snprintf(dev_path, sizeof(dev_path), "%s%s",
550 CROS_EC_DEV_PREFIX, cros_ec_dev_priv.dev);
Duncan Laurie6a40fb92014-11-24 07:13:27 -0800551
David Hendricks664e3352016-09-28 16:22:52 -0700552 msg_pdbg("%s: probing for CROS_EC at %s\n", __func__, dev_path);
553 cros_ec_fd = open(dev_path, O_RDWR);
David Hendricksb907de32014-08-11 16:47:09 -0700554 if (cros_ec_fd < 0)
555 return cros_ec_fd;
Simon Glasscd597032013-05-23 17:18:44 -0700556
Guenter Roeck51822fd2016-04-08 13:58:11 -0700557 if (ec_dev_is_v2())
558 __cros_ec_command_dev_fn = __cros_ec_command_dev_v2;
559 else
560 __cros_ec_command_dev_fn = __cros_ec_command_dev;
561
David Hendricksb907de32014-08-11 16:47:09 -0700562 if (cros_ec_test(&cros_ec_dev_priv))
David Hendricks31d487e2013-11-04 17:49:00 -0800563 return 1;
564
Edward O'Callaghanabd30192019-05-14 15:58:19 +1000565 cros_ec_set_max_size(&cros_ec_dev_priv, &opaque_master_cros_ec_dev);
Puthikorn Voravootivatc0993cf2014-08-28 16:04:58 -0700566
Edward O'Callaghanc66827e2020-10-09 12:22:04 +1100567 internal_buses_supported &= ~(BUS_LPC|BUS_SPI);
568
David Hendricks664e3352016-09-28 16:22:52 -0700569 msg_pdbg("CROS_EC detected at %s\n", dev_path);
Edward O'Callaghanabd30192019-05-14 15:58:19 +1000570 register_opaque_master(&opaque_master_cros_ec_dev);
David Hendricksb907de32014-08-11 16:47:09 -0700571 register_shutdown(cros_ec_dev_shutdown, NULL);
572 cros_ec_dev_priv.detected = 1;
Souvik Ghosh586968a2016-08-11 17:56:24 -0700573 cros_ec_priv = &cros_ec_dev_priv;
Simon Glasscd597032013-05-23 17:18:44 -0700574
575 return 0;
576}