1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 /* Useful direct commands to the EC host interface */
17 
18 #define LOG_TAG "fwtool"
19 
20 #include <errno.h>
21 #include <stdint.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <unistd.h>
25 
26 #include "ec_commands.h"
27 #include "debug_cmd.h"
28 #include "flash_device.h"
29 #include "update_log.h"
30 
31 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
32 
33 static void *ec;
34 
get_ec(void)35 static void *get_ec(void)
36 {
37 	if (!ec)
38 		ec = flash_open("ec", NULL);
39 
40 	return ec;
41 }
42 
ec_readmem(int offset,int bytes,void * dest)43 static int ec_readmem(int offset, int bytes, void *dest)
44 {
45 	struct ec_params_read_memmap r_mem;
46 	int r;
47 
48 	r_mem.offset = offset;
49 	r_mem.size = bytes;
50 	return flash_cmd(ec, EC_CMD_READ_MEMMAP, 0,
51 			 &r_mem, sizeof(r_mem), dest, bytes);
52 }
53 
ec_readmem8(int offset)54 static uint8_t ec_readmem8(int offset)
55 {
56 	uint8_t val;
57 	int ret;
58 	ret = ec_readmem(offset, sizeof(val), &val);
59 	return ret ? 0 : val;
60 }
61 
ec_readmem32(int offset)62 static uint32_t ec_readmem32(int offset)
63 {
64 	uint32_t val;
65 	int ret;
66 	ret = ec_readmem(offset, sizeof(val), &val);
67 	return ret ? 0 : val;
68 }
69 
cmd_ec_battery(int argc,const char ** argv)70 static int cmd_ec_battery(int argc, const char **argv)
71 {
72 	char batt_text[EC_MEMMAP_TEXT_MAX + 1];
73 	uint32_t val;
74 
75 	if (!get_ec())
76 		return -ENODEV;
77 
78 	printf("Battery info:\n");
79 
80 	val = ec_readmem8(EC_MEMMAP_BATTERY_VERSION);
81 	if (val < 1) {
82 		fprintf(stderr, "Battery version %d is not supported\n", val);
83 		return -EINVAL;
84 	}
85 
86 	memset(batt_text, 0, EC_MEMMAP_TEXT_MAX + 1);
87 	ec_readmem(EC_MEMMAP_BATT_MFGR, sizeof(batt_text), batt_text);
88 	printf("  OEM name:               %s\n", batt_text);
89 	ec_readmem(EC_MEMMAP_BATT_MODEL, sizeof(batt_text), batt_text);
90 	printf("  Model number:           %s\n", batt_text);
91 	printf("  Chemistry   :           %s\n", batt_text);
92 	ec_readmem(EC_MEMMAP_BATT_SERIAL, sizeof(batt_text), batt_text);
93 	printf("  Serial number:          %s\n", batt_text);
94 	val = ec_readmem32(EC_MEMMAP_BATT_DCAP);
95 	printf("  Design capacity:        %u mAh\n", val);
96 	val = ec_readmem32(EC_MEMMAP_BATT_LFCC);
97 	printf("  Last full charge:       %u mAh\n", val);
98 	val = ec_readmem32(EC_MEMMAP_BATT_DVLT);
99 	printf("  Design output voltage   %u mV\n", val);
100 	val = ec_readmem32(EC_MEMMAP_BATT_CCNT);
101 	printf("  Cycle count             %u\n", val);
102 	val = ec_readmem32(EC_MEMMAP_BATT_VOLT);
103 	printf("  Present voltage         %u mV\n", val);
104 	val = ec_readmem32(EC_MEMMAP_BATT_RATE);
105 	printf("  Present current         %u mA\n", val);
106 	val = ec_readmem32(EC_MEMMAP_BATT_CAP);
107 	printf("  Remaining capacity      %u mAh\n", val);
108 	val = ec_readmem8(EC_MEMMAP_BATT_FLAG);
109 	printf("  Flags                   0x%02x", val);
110 	if (val & EC_BATT_FLAG_AC_PRESENT)
111 		printf(" AC_PRESENT");
112 	if (val & EC_BATT_FLAG_BATT_PRESENT)
113 		printf(" BATT_PRESENT");
114 	if (val & EC_BATT_FLAG_DISCHARGING)
115 		printf(" DISCHARGING");
116 	if (val & EC_BATT_FLAG_CHARGING)
117 		printf(" CHARGING");
118 	if (val & EC_BATT_FLAG_LEVEL_CRITICAL)
119 		printf(" LEVEL_CRITICAL");
120 	printf("\n");
121 
122 	return 0;
123 }
124 
125 /* BQ25892 I2C registers */
126 #define BQ2589X_ADDR         (0x6B << 1)
127 #define BQ2589X_REG_CFG1            0x02
128 #define BQ2589X_CFG1_CONV_START     (1<<7)
129 #define BQ2589X_REG_ADC_BATT_VOLT   0x0E
130 #define BQ2589X_REG_ADC_SYS_VOLT    0x0F
131 #define BQ2589X_REG_ADC_TS          0x10
132 #define BQ2589X_REG_ADC_VBUS_VOLT   0x11
133 #define BQ2589X_REG_ADC_CHG_CURR    0x12
134 #define BQ2589X_REG_ADC_INPUT_CURR  0x13
135 
bq25892_read(int reg,int * value)136 static int bq25892_read(int reg, int *value)
137 {
138 	int rv;
139 	struct ec_response_i2c_read r;
140 	struct ec_params_i2c_read p = {
141 		.port = 0, .read_size = 8, .addr = BQ2589X_ADDR, .offset = reg
142 	};
143 
144 	rv = flash_cmd(ec, EC_CMD_I2C_READ, 0, &p, sizeof(p), &r, sizeof(r));
145 	if (rv < 0) {
146 		*value = -1;
147 		return rv;
148 	}
149 
150 	*value = r.data;
151 	return 0;
152 }
153 
bq25892_write(int reg,int value)154 static int bq25892_write(int reg, int value)
155 {
156 	int rv;
157 	struct ec_params_i2c_write p = {
158 		.port = 0, .write_size = 8, .addr = BQ2589X_ADDR,
159 		.offset = reg, .data = value
160 	};
161 
162 	rv = flash_cmd(ec, EC_CMD_I2C_WRITE, 0, &p, sizeof(p), NULL, 0);
163 	return rv < 0 ? rv : 0;
164 }
165 
cmd_ec_bq25892(int argc,const char ** argv)166 static int cmd_ec_bq25892(int argc, const char **argv)
167 {
168 	int i;
169 	int value;
170 	int rv;
171 	int batt_mv, sys_mv, vbus_mv, chg_ma, input_ma;
172 
173 
174 	if (!get_ec())
175 		return -ENODEV;
176 
177 	/* Trigger one ADC conversion */
178 	bq25892_read(BQ2589X_REG_CFG1, &value);
179 	bq25892_write(BQ2589X_REG_CFG1, value | BQ2589X_CFG1_CONV_START);
180 	do {
181 		rv = bq25892_read(BQ2589X_REG_CFG1, &value);
182 	} while ((value & BQ2589X_CFG1_CONV_START) || (rv < 0));
183 
184 	bq25892_read(BQ2589X_REG_ADC_BATT_VOLT, &batt_mv);
185 	bq25892_read(BQ2589X_REG_ADC_SYS_VOLT, &sys_mv);
186 	bq25892_read(BQ2589X_REG_ADC_VBUS_VOLT, &vbus_mv);
187 	bq25892_read(BQ2589X_REG_ADC_CHG_CURR, &chg_ma);
188 	bq25892_read(BQ2589X_REG_ADC_INPUT_CURR, &input_ma);
189 	printf("ADC Batt %dmV Sys %dmV VBUS %dmV Chg %dmA Input %dmA\n",
190 		2304 + (batt_mv & 0x7f) * 20, 2304 + sys_mv * 20,
191 		2600 + (vbus_mv & 0x7f) * 100,
192 		chg_ma * 50, 100 + (input_ma & 0x3f) * 50);
193 
194 	printf("REG:");
195 	for (i = 0; i <= 0x14; ++i)
196 		printf(" %02x", i);
197 	printf("\n");
198 
199 	printf("VAL:");
200 	for (i = 0; i <= 0x14; ++i) {
201 		rv = bq25892_read(i, &value);
202 		if (rv)
203 			return rv;
204 		printf(" %02x", value);
205 	}
206 	printf("\n");
207 	return 0;
208 }
209 
210 /* BQ27742 I2C registers */
211 #define BQ27742_ADDR         	    0xAA
212 #define BQ27742_REG_CTRL            0x00
213 #define BQ27742_REG_FLAGS           0x0A
214 #define BQ27742_REG_CHARGING_MV     0x30
215 #define BQ27742_REG_CHARGING_MA     0x32
216 #define BQ27742_REG_PROTECTOR       0x6D
217 
bq27742_read(int reg,int size,int * value)218 static int bq27742_read(int reg, int size, int *value)
219 {
220 	int rv;
221 	struct ec_response_i2c_read r;
222 	struct ec_params_i2c_read p = {
223 		.port = 0, .read_size = size, .addr = BQ27742_ADDR,
224 		.offset = reg
225 	};
226 
227 	rv = flash_cmd(ec, EC_CMD_I2C_READ, 0, &p, sizeof(p), &r, sizeof(r));
228 	if (rv < 0) {
229 		*value = -1;
230 		return rv;
231 	}
232 
233 	*value = r.data;
234 	return 0;
235 }
236 
bq27742_write(int reg,int size,int value)237 static int bq27742_write(int reg, int size, int value)
238 {
239 	int rv;
240 	struct ec_params_i2c_write p = {
241 		.port = 0, .write_size = size, .addr = BQ27742_ADDR,
242 		.offset = reg, .data = value
243 	};
244 
245 	rv = flash_cmd(ec, EC_CMD_I2C_WRITE, 0, &p, sizeof(p), NULL, 0);
246 	return rv < 0 ? rv : 0;
247 }
248 
cmd_ec_bq27742(int argc,const char ** argv)249 static int cmd_ec_bq27742(int argc, const char **argv)
250 {
251 	int i;
252 	int value;
253 	int rv;
254 	int chg_mv, chg_ma;
255 
256 
257 	if (!get_ec())
258 		return -ENODEV;
259 
260 	/* Get chip ID in Control subcommand DEVICE_TYPE (0x1) */
261 	bq27742_write(BQ27742_REG_CTRL, 16, 0x1);
262 	bq27742_read(BQ27742_REG_CTRL, 16, &value);
263 	printf("ID: BQ27%3x\n", value);
264 
265 	bq27742_read(BQ27742_REG_CHARGING_MV, 16, &chg_mv);
266 	bq27742_read(BQ27742_REG_CHARGING_MA, 16, &chg_ma);
267 	printf("Requested charge: %d mV %d mA\n", chg_mv, chg_ma);
268 
269 	bq27742_read(BQ27742_REG_FLAGS, 16, &value);
270 	printf("Flags: %04x\n", value);
271 	bq27742_read(BQ27742_REG_PROTECTOR, 8, &value);
272 	printf("ProtectorState: %02x\n", value);
273 
274 	return 0;
275 }
276 
cmd_ec_chargecontrol(int argc,const char ** argv)277 static int cmd_ec_chargecontrol(int argc, const char **argv)
278 {
279 	struct ec_params_charge_control p;
280 	int rv;
281 
282 	if (argc != 2) {
283 		fprintf(stderr, "Usage: %s <normal | idle | discharge>\n",
284 			argv[0]);
285 		return -EINVAL;
286 	}
287 
288 	if (!strcasecmp(argv[1], "normal")) {
289 		p.mode = CHARGE_CONTROL_NORMAL;
290 	} else if (!strcasecmp(argv[1], "idle")) {
291 		p.mode = CHARGE_CONTROL_IDLE;
292 	} else if (!strcasecmp(argv[1], "discharge")) {
293 		p.mode = CHARGE_CONTROL_DISCHARGE;
294 	} else {
295 		fprintf(stderr, "Bad value.\n");
296 		return -EINVAL;
297 	}
298 
299 	if (!get_ec())
300 		return -ENODEV;
301 
302 	rv = flash_cmd(ec, EC_CMD_CHARGE_CONTROL, 1, &p, sizeof(p), NULL, 0);
303 	if (rv < 0) {
304 		fprintf(stderr, "Is AC connected?\n");
305 		return rv;
306 	}
307 
308 	switch (p.mode) {
309 	case CHARGE_CONTROL_NORMAL:
310 		printf("Charge state machine normal mode.\n");
311 		break;
312 	case CHARGE_CONTROL_IDLE:
313 		printf("Charge state machine force idle.\n");
314 		break;
315 	case CHARGE_CONTROL_DISCHARGE:
316 		printf("Charge state machine force discharge.\n");
317 		break;
318 	default:
319 		break;
320 	}
321 	return 0;
322 }
323 
cmd_ec_console(int argc,const char ** argv)324 static int cmd_ec_console(int argc, const char **argv)
325 {
326 	char data[128];
327 	int rv;
328 
329 	if (!get_ec())
330 		return -ENODEV;
331 
332 	/* Snapshot the EC console */
333 	rv = flash_cmd(ec, EC_CMD_CONSOLE_SNAPSHOT, 0, NULL, 0, NULL, 0);
334 	if (rv < 0)
335 		return rv;
336 
337 	/* Loop and read from the snapshot until it's done */
338 	while (1) {
339 		memset(data, 0, sizeof(data));
340 		rv = flash_cmd(ec, EC_CMD_CONSOLE_READ, 0,
341 			       NULL, 0, data, sizeof(data));
342 		if (rv)
343 			return rv;
344 
345 		/* Empty response means done */
346 		if (!data[0])
347 			break;
348 
349 		/* Make sure output is null-terminated, then dump it */
350 		data[sizeof(data) - 1] = '\0';
351 		fputs(data, stdout);
352 	}
353 	printf("\n");
354 	return 0;
355 }
356 
cmd_ec_gpioget(int argc,const char ** argv)357 static int cmd_ec_gpioget(int argc, const char **argv)
358 {
359 	struct ec_params_gpio_get_v1 p_v1;
360 	struct ec_response_gpio_get_v1 r_v1;
361 	int i, rv, subcmd, num_gpios;
362 
363 	if (!get_ec())
364 		return -ENODEV;
365 
366 	if (argc > 2) {
367 		printf("Usage: %s [<subcmd> <GPIO name>]\n", argv[0]);
368 		printf("'gpioget <GPIO_NAME>' - Get value by name\n");
369 		printf("'gpioget count' - Get count of GPIOS\n");
370 		printf("'gpioget all' - Get info for all GPIOs\n");
371 		return -1;
372 	}
373 
374 	/* Keeping it consistent with console command behavior */
375 	if (argc == 1)
376 		subcmd = EC_GPIO_GET_INFO;
377 	else if (!strcmp(argv[1], "count"))
378 		subcmd = EC_GPIO_GET_COUNT;
379 	else if (!strcmp(argv[1], "all"))
380 		subcmd = EC_GPIO_GET_INFO;
381 	else
382 		subcmd = EC_GPIO_GET_BY_NAME;
383 
384 	if (subcmd == EC_GPIO_GET_BY_NAME) {
385 		p_v1.subcmd = EC_GPIO_GET_BY_NAME;
386 		if (strlen(argv[1]) + 1 > sizeof(p_v1.get_value_by_name.name)) {
387 			fprintf(stderr, "GPIO name too long.\n");
388 			return -1;
389 		}
390 		strcpy(p_v1.get_value_by_name.name, argv[1]);
391 
392 		rv = flash_cmd(ec, EC_CMD_GPIO_GET, 1, &p_v1,
393 				sizeof(p_v1), &r_v1, sizeof(r_v1));
394 
395 		if (rv < 0)
396 			return rv;
397 
398 		printf("GPIO %s = %d\n", p_v1.get_value_by_name.name,
399 			r_v1.get_value_by_name.val);
400 		return 0;
401 	}
402 
403 	/* Need GPIO count for EC_GPIO_GET_COUNT or EC_GPIO_GET_INFO */
404 	p_v1.subcmd = EC_GPIO_GET_COUNT;
405 	rv = flash_cmd(ec, EC_CMD_GPIO_GET, 1, &p_v1,
406 			sizeof(p_v1), &r_v1, sizeof(r_v1));
407 	if (rv < 0)
408 		return rv;
409 
410 	if (subcmd == EC_GPIO_GET_COUNT) {
411 		printf("GPIO COUNT = %d\n", r_v1.get_count.val);
412 		return 0;
413 	}
414 
415 	/* subcmd EC_GPIO_GET_INFO */
416 	num_gpios = r_v1.get_count.val;
417 	p_v1.subcmd = EC_GPIO_GET_INFO;
418 
419 	for (i = 0; i < num_gpios; i++) {
420 		p_v1.get_info.index = i;
421 
422 		rv = flash_cmd(ec, EC_CMD_GPIO_GET, 1, &p_v1,
423 				sizeof(p_v1), &r_v1, sizeof(r_v1));
424 		if (rv < 0)
425 			return rv;
426 
427 		printf("%2d %-32s 0x%04X\n", r_v1.get_info.val,
428 			r_v1.get_info.name, r_v1.get_info.flags);
429 	}
430 
431 	return 0;
432 }
433 
434 
cmd_ec_gpioset(int argc,const char ** argv)435 static int cmd_ec_gpioset(int argc, const char **argv)
436 {
437 	struct ec_params_gpio_set p;
438 	char *e;
439 	int rv;
440 
441 	if (!get_ec())
442 		return -ENODEV;
443 
444 	if (argc != 3) {
445 		fprintf(stderr, "Usage: %s <GPIO name> <0 | 1>\n", argv[0]);
446 		return -1;
447 	}
448 
449 	if (strlen(argv[1]) + 1 > sizeof(p.name)) {
450 		fprintf(stderr, "GPIO name too long.\n");
451 		return -1;
452 	}
453 	strcpy(p.name, argv[1]);
454 
455 	p.val = strtol(argv[2], &e, 0);
456 	if (e && *e) {
457 		fprintf(stderr, "Bad value.\n");
458 		return -1;
459 	}
460 
461 	rv = flash_cmd(ec, EC_CMD_GPIO_SET, 0, &p, sizeof(p), NULL, 0);
462 	if (rv < 0)
463 		return rv;
464 
465 	printf("GPIO %s set to %d\n", p.name, p.val);
466 	return 0;
467 }
468 
ec_hash_print(const struct ec_response_vboot_hash * r)469 static int ec_hash_print(const struct ec_response_vboot_hash *r)
470 {
471 	int i;
472 
473 	if (r->status == EC_VBOOT_HASH_STATUS_BUSY) {
474 		printf("status:  busy\n");
475 		return 0;
476 	} else if (r->status == EC_VBOOT_HASH_STATUS_NONE) {
477 		printf("status:  unavailable\n");
478 		return 0;
479 	} else if (r->status != EC_VBOOT_HASH_STATUS_DONE) {
480 		printf("status:  %d\n", r->status);
481 		return 0;
482 	}
483 
484 	printf("status:  done\n");
485 	if (r->hash_type == EC_VBOOT_HASH_TYPE_SHA256)
486 		printf("type:    SHA-256\n");
487 	else
488 		printf("type:    %d\n", r->hash_type);
489 
490 	printf("offset:  0x%08x\n", r->offset);
491 	printf("size:    0x%08x\n", r->size);
492 
493 	printf("hash:    ");
494 	for (i = 0; i < r->digest_size; i++)
495 		printf("%02x", r->hash_digest[i]);
496 	printf("\n");
497 	return 0;
498 }
499 
cmd_ec_echash(int argc,const char ** argv)500 static int cmd_ec_echash(int argc, const char **argv)
501 {
502 	struct ec_params_vboot_hash p;
503 	struct ec_response_vboot_hash r;
504 	char *e;
505 	int rv;
506 
507 	if (!get_ec())
508 		return -ENODEV;
509 
510 	if (argc < 2) {
511 		/* Get hash status */
512 		p.cmd = EC_VBOOT_HASH_GET;
513 		rv = flash_cmd(ec, EC_CMD_VBOOT_HASH, 0,
514 				&p, sizeof(p), &r, sizeof(r));
515 		if (rv < 0)
516 			return rv;
517 
518 		return ec_hash_print(&r);
519 	}
520 
521 	if (argc == 2 && !strcasecmp(argv[1], "abort")) {
522 		/* Abort hash calculation */
523 		p.cmd = EC_VBOOT_HASH_ABORT;
524 		rv = flash_cmd(ec, EC_CMD_VBOOT_HASH, 0,
525 				&p, sizeof(p), &r, sizeof(r));
526 		return (rv < 0 ? rv : 0);
527 	}
528 
529 	/* The only other commands are start and recalc */
530 	if (!strcasecmp(argv[1], "start"))
531 		p.cmd = EC_VBOOT_HASH_START;
532 	else if (!strcasecmp(argv[1], "recalc"))
533 		p.cmd = EC_VBOOT_HASH_RECALC;
534 	else
535 		return -EINVAL;
536 
537 	p.hash_type = EC_VBOOT_HASH_TYPE_SHA256;
538 
539 	if (argc < 3) {
540 		fprintf(stderr, "Must specify offset\n");
541 		return -1;
542 	}
543 
544 	if (!strcasecmp(argv[2], "ro")) {
545 		p.offset = EC_VBOOT_HASH_OFFSET_RO;
546 		p.size = 0;
547 		printf("Hashing EC-RO...\n");
548 	} else if (!strcasecmp(argv[2], "rw")) {
549 		p.offset = EC_VBOOT_HASH_OFFSET_RW;
550 		p.size = 0;
551 		printf("Hashing EC-RW...\n");
552 	} else if (argc < 4) {
553 		fprintf(stderr, "Must specify size\n");
554 		return -1;
555 	} else {
556 		p.offset = strtol(argv[2], &e, 0);
557 		if (e && *e) {
558 			fprintf(stderr, "Bad offset.\n");
559 			return -1;
560 		}
561 		p.size = strtol(argv[3], &e, 0);
562 		if (e && *e) {
563 			fprintf(stderr, "Bad size.\n");
564 			return -1;
565 		}
566 		printf("Hashing %d bytes at offset %d...\n", p.size, p.offset);
567 	}
568 
569 	if (argc == 5) {
570 		/*
571 		 * Technically nonce can be any binary data up to 64 bytes,
572 		 * but this command only supports a 32-bit value.
573 		 */
574 		uint32_t nonce = strtol(argv[4], &e, 0);
575 		if (e && *e) {
576 			fprintf(stderr, "Bad nonce integer.\n");
577 			return -1;
578 		}
579 		memcpy(p.nonce_data, &nonce, sizeof(nonce));
580 		p.nonce_size = sizeof(nonce);
581 	} else
582 		p.nonce_size = 0;
583 
584 	rv = flash_cmd(ec, EC_CMD_VBOOT_HASH, 0, &p, sizeof(p), &r, sizeof(r));
585 	if (rv < 0)
586 		return rv;
587 
588 	/* Start command doesn't wait for hashing to finish */
589 	if (p.cmd == EC_VBOOT_HASH_START)
590 		return 0;
591 
592 	/* Recalc command does wait around, so a result is ready now */
593 	return ec_hash_print(&r);
594 }
595 
596 #define LIGHTBAR_NUM_SEQUENCES 13
597 
lb_do_cmd(enum lightbar_command cmd,struct ec_params_lightbar * in,struct ec_response_lightbar * out)598 static int lb_do_cmd(enum lightbar_command cmd,
599 		     struct ec_params_lightbar *in,
600 		     struct ec_response_lightbar *out)
601 {
602 	int rv;
603 	in->cmd = cmd;
604 	rv = flash_cmd(ec, EC_CMD_LIGHTBAR_CMD, 0,
605 			in, 120,
606 			out, 120);
607 	return (rv < 0 ? rv : 0);
608 }
609 
cmd_ec_lightbar(int argc,const char ** argv)610 static int cmd_ec_lightbar(int argc, const char **argv)
611 {
612 	unsigned i;
613 	int r;
614 	struct ec_params_lightbar param;
615 	struct ec_response_lightbar resp;
616 
617 	if (!get_ec())
618 		return -ENODEV;
619 
620 	if (1 == argc) {		/* no args = dump 'em all */
621 		r = lb_do_cmd(LIGHTBAR_CMD_DUMP, &param, &resp);
622 		if (r)
623 			return r;
624 		for (i = 0; i < ARRAY_SIZE(resp.dump.vals); i++) {
625 			printf(" %02x     %02x     %02x\n",
626 			       resp.dump.vals[i].reg,
627 			       resp.dump.vals[i].ic0,
628 			       resp.dump.vals[i].ic1);
629 		}
630 		return 0;
631 	}
632 
633 	if (argc == 2 && !strcasecmp(argv[1], "init"))
634 		return lb_do_cmd(LIGHTBAR_CMD_INIT, &param, &resp);
635 
636 	if (argc == 2 && !strcasecmp(argv[1], "off"))
637 		return lb_do_cmd(LIGHTBAR_CMD_OFF, &param, &resp);
638 
639 	if (argc == 2 && !strcasecmp(argv[1], "on"))
640 		return lb_do_cmd(LIGHTBAR_CMD_ON, &param, &resp);
641 
642 	if (!strcasecmp(argv[1], "version")) {
643 		r = lb_do_cmd(LIGHTBAR_CMD_VERSION, &param, &resp);
644 		if (!r)
645 			printf("version %d flags 0x%x\n",
646 			       resp.version.num, resp.version.flags);
647 		return r;
648 	}
649 
650 	if (argc > 1 && !strcasecmp(argv[1], "brightness")) {
651 		char *e;
652 		int rv;
653 		if (argc > 2) {
654 			param.set_brightness.num = 0xff &
655 				strtoul(argv[2], &e, 16);
656 			return lb_do_cmd(LIGHTBAR_CMD_SET_BRIGHTNESS,
657 					 &param, &resp);
658 		}
659 		rv = lb_do_cmd(LIGHTBAR_CMD_GET_BRIGHTNESS,
660 			       &param, &resp);
661 		if (rv)
662 			return rv;
663 		printf("%02x\n", resp.get_brightness.num);
664 		return 0;
665 	}
666 
667 	if (argc > 1 && !strcasecmp(argv[1], "demo")) {
668 		int rv;
669 		if (argc > 2) {
670 			if (!strcasecmp(argv[2], "on") || argv[2][0] == '1')
671 				param.demo.num = 1;
672 			else if (!strcasecmp(argv[2], "off") ||
673 				 argv[2][0] == '0')
674 				param.demo.num = 0;
675 			else {
676 				fprintf(stderr, "Invalid arg\n");
677 				return -1;
678 			}
679 			return lb_do_cmd(LIGHTBAR_CMD_DEMO, &param, &resp);
680 		}
681 
682 		rv = lb_do_cmd(LIGHTBAR_CMD_GET_DEMO, &param, &resp);
683 		if (rv)
684 			return rv;
685 		printf("%s\n", resp.get_demo.num ? "on" : "off");
686 		return 0;
687 	}
688 
689 	if (argc > 2 && !strcasecmp(argv[1], "seq")) {
690 		char *e;
691 		uint8_t num;
692 		num = 0xff & strtoul(argv[2], &e, 16);
693 		if (e && *e) {
694 			if (!strcasecmp(argv[2], "stop"))
695 				num = 0x8;
696 			else if (!strcasecmp(argv[2], "run"))
697 				num = 0x9;
698 			else if (!strcasecmp(argv[2], "konami"))
699 				num = 0xA;
700 			else
701 				num = LIGHTBAR_NUM_SEQUENCES;
702 		}
703 		if (num >= LIGHTBAR_NUM_SEQUENCES) {
704 			fprintf(stderr, "Invalid arg\n");
705 			return -1;
706 		}
707 		param.seq.num = num;
708 		return lb_do_cmd(LIGHTBAR_CMD_SEQ, &param, &resp);
709 	}
710 
711 	if (argc == 4) {
712 		char *e;
713 		param.reg.ctrl = 0xff & strtoul(argv[1], &e, 16);
714 		param.reg.reg = 0xff & strtoul(argv[2], &e, 16);
715 		param.reg.value = 0xff & strtoul(argv[3], &e, 16);
716 		return lb_do_cmd(LIGHTBAR_CMD_REG, &param, &resp);
717 	}
718 
719 	if (argc == 5) {
720 		char *e;
721 		param.set_rgb.led = strtoul(argv[1], &e, 16);
722 		param.set_rgb.red = strtoul(argv[2], &e, 16);
723 		param.set_rgb.green = strtoul(argv[3], &e, 16);
724 		param.set_rgb.blue = strtoul(argv[4], &e, 16);
725 		return lb_do_cmd(LIGHTBAR_CMD_SET_RGB, &param, &resp);
726 	}
727 
728 	/* Only thing left is to try to read an LED value */
729 	if (argc == 2) {
730 		char *e;
731 		param.get_rgb.led = strtoul(argv[1], &e, 0);
732 		if (!(e && *e)) {
733 			r = lb_do_cmd(LIGHTBAR_CMD_GET_RGB, &param, &resp);
734 			if (r)
735 				return r;
736 			printf("%02x %02x %02x\n",
737 			       resp.get_rgb.red,
738 			       resp.get_rgb.green,
739 			       resp.get_rgb.blue);
740 			return 0;
741 		}
742 	}
743 
744 	return 0;
745 }
746 
747 /* PI3USB9281 I2C registers */
748 #define PI3USB9281_ADDR      (0x25 << 1)
749 #define PI3USB9281_REG_DEV_ID       0x01
750 #define PI3USB9281_REG_CONTROL      0x02
751 #define PI3USB9281_REG_INT          0x03
752 #define PI3USB9281_REG_INT_MASK     0x05
753 #define PI3USB9281_REG_DEV_TYPE     0x0a
754 #define PI3USB9281_REG_CHG_STATUS   0x0e
755 #define PI3USB9281_REG_MANUAL       0x13
756 #define PI3USB9281_REG_RESET        0x1b
757 #define PI3USB9281_REG_VBUS         0x1d
758 
759 static const uint8_t pi3usb9281_regs[] = {
760 	PI3USB9281_REG_DEV_ID, PI3USB9281_REG_CONTROL, PI3USB9281_REG_INT,
761 	PI3USB9281_REG_INT_MASK, PI3USB9281_REG_DEV_TYPE, PI3USB9281_REG_CHG_STATUS,
762 	PI3USB9281_REG_MANUAL, PI3USB9281_REG_VBUS
763 };
764 #define PI3USB9281_COUNT ARRAY_SIZE(pi3usb9281_regs)
765 
pi3usb9281_read(int reg,int * value)766 static int pi3usb9281_read(int reg, int *value)
767 {
768 	int rv;
769 	struct ec_response_i2c_read r;
770 	struct ec_params_i2c_read p = {
771 		.port = 0, .read_size = 8, .addr = PI3USB9281_ADDR, .offset = reg
772 	};
773 
774 	rv = flash_cmd(ec, EC_CMD_I2C_READ, 0, &p, sizeof(p), &r, sizeof(r));
775 	if (rv < 0) {
776 		*value = -1;
777 		return rv;
778 	}
779 
780 	*value = r.data;
781 	return 0;
782 }
783 
cmd_ec_pi3usb9281(int argc,const char ** argv)784 static int cmd_ec_pi3usb9281(int argc, const char **argv)
785 {
786 	unsigned i;
787 	int value;
788 	int rv;
789 	int dev_type, chg_stat, vbus;
790 	char *apple_chg = "", *proprio_chg = "";
791 
792 	if (!get_ec())
793 		return -ENODEV;
794 
795 	pi3usb9281_read(PI3USB9281_REG_DEV_TYPE, &dev_type);
796 	pi3usb9281_read(PI3USB9281_REG_CHG_STATUS, &chg_stat);
797 	pi3usb9281_read(PI3USB9281_REG_VBUS, &vbus);
798 	switch((chg_stat>>2)&7) {
799 	case 4: apple_chg = "Apple 2.4A"; break;
800 	case 2: apple_chg = "Apple 2A"; break;
801 	case 1: apple_chg = "Apple 1A"; break;
802 	}
803 	switch(chg_stat&3) {
804 	case 3: proprio_chg = "type-2"; break;
805 	case 2: proprio_chg = "type-1"; break;
806 	case 1: proprio_chg = "rsvd"; break;
807 	}
808 	printf("USB: %s%s%s%s%s%s Charger: %s%s VBUS: %d\n",
809 		dev_type & (1<<6) ? "DCP" : " ",
810 		dev_type & (1<<5) ? "CDP" : " ",
811 		dev_type & (1<<4) ? "CarKit" : " ",
812 		dev_type & (1<<2) ? "SDP" : " ",
813 		dev_type & (1<<1) ? "OTG" : " ",
814 		dev_type & (1<<0) ? "MHL" : " ",
815 		apple_chg,
816 		proprio_chg,
817 		!!(vbus & 2));
818 
819 	printf("REG:");
820 	for (i = 0; i < PI3USB9281_COUNT; ++i)
821 		printf(" %02x", pi3usb9281_regs[i]);
822 	printf("\n");
823 
824 	printf("VAL:");
825 	for (i = 0; i < PI3USB9281_COUNT; ++i) {
826 		rv = pi3usb9281_read(pi3usb9281_regs[i], &value);
827 		if (rv)
828 			return rv;
829 		printf(" %02x", value);
830 	}
831 	printf("\n");
832 	return 0;
833 }
834 
835 #define PD_ROLE_SINK   0
836 #define PD_ROLE_SOURCE 1
837 #define PD_ROLE_UFP    0
838 #define PD_ROLE_DFP    1
839 
cmd_ec_usbpd(int argc,const char ** argv)840 static int cmd_ec_usbpd(int argc, const char **argv)
841 {
842 	const char *role_str[] = {"", "toggle", "toggle-off", "sink", "source"};
843 	const char *mux_str[] = {"", "none", "usb", "dp", "dock", "auto"};
844 	const char *swap_str[] = {"", "dr_swap", "pr_swap", "vconn_swap"};
845 	struct ec_params_usb_pd_control p;
846 	struct ec_response_usb_pd_control_v1 r;
847 	int rv, i;
848         unsigned j;
849 	int option_ok;
850 	char *e;
851 
852 	if (!get_ec())
853 		return -ENODEV;
854 
855 	p.role = USB_PD_CTRL_ROLE_NO_CHANGE;
856 	p.mux = USB_PD_CTRL_MUX_NO_CHANGE;
857 	p.swap = USB_PD_CTRL_SWAP_NONE;
858 
859 	if (argc < 2) {
860 		fprintf(stderr, "No port specified.\n");
861 		return -1;
862 	}
863 
864 	p.port = strtol(argv[1], &e, 0);
865 	if (e && *e) {
866 		fprintf(stderr, "Invalid param (port)\n");
867 		return -1;
868 	}
869 
870 	for (i = 2; i < argc; ++i) {
871 		option_ok = 0;
872 		if (!strcmp(argv[i], "auto")) {
873 			if (argc != 3) {
874 				fprintf(stderr, "\"auto\" may not be used "
875 						"with other options.\n");
876 				return -1;
877 			}
878 			p.role = USB_PD_CTRL_ROLE_TOGGLE_ON;
879 			p.mux = USB_PD_CTRL_MUX_AUTO;
880 			continue;
881 		}
882 
883 		for (j = 0; j < ARRAY_SIZE(role_str); ++j) {
884 			if (!strcmp(argv[i], role_str[j])) {
885 				if (p.role != USB_PD_CTRL_ROLE_NO_CHANGE) {
886 					fprintf(stderr,
887 						"Only one role allowed.\n");
888 					return -1;
889 				}
890 				p.role = j;
891 				option_ok = 1;
892 				break;
893 			}
894 		}
895 		if (option_ok)
896 			continue;
897 
898 		for (j = 0; j < ARRAY_SIZE(mux_str); ++j) {
899 			if (!strcmp(argv[i], mux_str[j])) {
900 				if (p.mux != USB_PD_CTRL_MUX_NO_CHANGE) {
901 					fprintf(stderr,
902 						"Only one mux type allowed.\n");
903 					return -1;
904 				}
905 				p.mux = j;
906 				option_ok = 1;
907 				break;
908 			}
909 		}
910 		if (option_ok)
911 			continue;
912 
913 		for (j = 0; j < ARRAY_SIZE(swap_str); ++j) {
914 			if (!strcmp(argv[i], swap_str[j])) {
915 				if (p.swap != USB_PD_CTRL_SWAP_NONE) {
916 					fprintf(stderr,
917 						"Only one swap type allowed.\n");
918 					return -1;
919 				}
920 				p.swap = j;
921 				option_ok = 1;
922 				break;
923 			}
924 		}
925 
926 
927 		if (!option_ok) {
928 			fprintf(stderr, "Unknown option: %s\n", argv[i]);
929 			return -1;
930 		}
931 	}
932 
933 	rv = flash_cmd(ec, EC_CMD_USB_PD_CONTROL, 1, &p, sizeof(p),
934 			&r, sizeof(r));
935 
936 	if (rv < 0 || argc != 2)
937 		return (rv < 0) ? rv : 0;
938 
939 	printf("Port C%d is %s,%s, Role:%s %s%s Polarity:CC%d State:%s\n",
940 	       p.port, (r.enabled & 1) ? "enabled" : "disabled",
941 	       (r.enabled & 2) ? "connected" : "disconnected",
942 	       r.role & PD_ROLE_SOURCE ? "SRC" : "SNK",
943 	       r.role & (PD_ROLE_DFP << 1) ? "DFP" : "UFP",
944 	       r.role & (1 << 2) ? " VCONN" : "",
945 	       r.polarity + 1, r.state);
946 
947 	return (rv < 0 ? rv : 0);
948 }
949 
print_pd_power_info(struct ec_response_usb_pd_power_info * r)950 static void print_pd_power_info(struct ec_response_usb_pd_power_info *r)
951 {
952 	switch (r->role) {
953 	case USB_PD_PORT_POWER_DISCONNECTED:
954 		printf("Disconnected");
955 		break;
956 	case USB_PD_PORT_POWER_SOURCE:
957 		printf("SRC");
958 		break;
959 	case USB_PD_PORT_POWER_SINK:
960 		printf("SNK");
961 		break;
962 	case USB_PD_PORT_POWER_SINK_NOT_CHARGING:
963 		printf("SNK (not charging)");
964 		break;
965 	default:
966 		printf("Unknown");
967 	}
968 
969 	if ((r->role == USB_PD_PORT_POWER_DISCONNECTED) ||
970 	    (r->role == USB_PD_PORT_POWER_SOURCE)) {
971 		printf("\n");
972 		return;
973 	}
974 
975 	printf(r->dualrole ? " DRP" : " Charger");
976 	switch (r->type) {
977 	case USB_CHG_TYPE_PD:
978 		printf(" PD");
979 		break;
980 	case USB_CHG_TYPE_C:
981 		printf(" Type-C");
982 		break;
983 	case USB_CHG_TYPE_PROPRIETARY:
984 		printf(" Proprietary");
985 		break;
986 	case USB_CHG_TYPE_BC12_DCP:
987 		printf(" DCP");
988 		break;
989 	case USB_CHG_TYPE_BC12_CDP:
990 		printf(" CDP");
991 		break;
992 	case USB_CHG_TYPE_BC12_SDP:
993 		printf(" SDP");
994 		break;
995 	case USB_CHG_TYPE_OTHER:
996 		printf(" Other");
997 		break;
998 	case USB_CHG_TYPE_VBUS:
999 		printf(" VBUS");
1000 		break;
1001 	case USB_CHG_TYPE_UNKNOWN:
1002 		printf(" Unknown");
1003 		break;
1004 	}
1005 	printf(" %dmV / %dmA, max %dmV / %dmA",
1006 		r->meas.voltage_now, r->meas.current_lim, r->meas.voltage_max,
1007 		r->meas.current_max);
1008 	if (r->max_power)
1009 		printf(" / %dmW", r->max_power / 1000);
1010 	printf("\n");
1011 }
1012 
cmd_ec_usbpdpower(int argc,const char ** argv)1013 static int cmd_ec_usbpdpower(int argc, const char **argv)
1014 {
1015 	struct ec_params_usb_pd_power_info p;
1016 	struct ec_response_usb_pd_power_info r;
1017 	struct ec_response_usb_pd_ports rp;
1018 	int i, rv;
1019 
1020 	if (!get_ec())
1021 		return -ENODEV;
1022 
1023 	rv = flash_cmd(ec, EC_CMD_USB_PD_PORTS, 0, NULL, 0, &rp, sizeof(rp));
1024 	if (rv)
1025 		return rv;
1026 
1027 	for (i = 0; i < rp.num_ports; i++) {
1028 		p.port = i;
1029 		rv = flash_cmd(ec, EC_CMD_USB_PD_POWER_INFO, 0,
1030 				&p, sizeof(p), &r, sizeof(r));
1031 		if (rv)
1032 			return rv;
1033 
1034 		printf("Port %d: ", i);
1035 		print_pd_power_info(&r);
1036 	}
1037 
1038 	return 0;
1039 }
1040 
cmd_ec_version(int argc,const char ** argv)1041 static int cmd_ec_version(int argc, const char **argv)
1042 {
1043         static const char * const image_names[] = {"unknown", "RO", "RW"};
1044 	struct ec_response_get_version r;
1045 	char build_string[128];
1046 	int rv;
1047 
1048 	if (!get_ec())
1049 		return -ENODEV;
1050 
1051 	rv = flash_cmd(ec, EC_CMD_GET_VERSION, 0, NULL, 0, &r, sizeof(r));
1052 	if (rv < 0) {
1053 		fprintf(stderr, "ERROR: EC_CMD_GET_VERSION failed: %d\n", rv);
1054 		return rv;
1055 	}
1056 	rv = flash_cmd(ec, EC_CMD_GET_BUILD_INFO, 0,
1057 			NULL, 0, build_string, sizeof(build_string));
1058 	if (rv < 0) {
1059 		fprintf(stderr, "ERROR: EC_CMD_GET_BUILD_INFO failed: %d\n",
1060 				rv);
1061 		return rv;
1062 	}
1063 
1064 	/* Ensure versions are null-terminated before we print them */
1065 	r.version_string_ro[sizeof(r.version_string_ro) - 1] = '\0';
1066 	r.version_string_rw[sizeof(r.version_string_rw) - 1] = '\0';
1067 	build_string[sizeof(build_string) - 1] = '\0';
1068 
1069 	/* Print versions */
1070 	printf("RO version:    %s\n", r.version_string_ro);
1071 	printf("RW version:    %s\n", r.version_string_rw);
1072 	printf("Firmware copy: %s\n",
1073 	       (r.current_image < ARRAY_SIZE(image_names) ?
1074 		image_names[r.current_image] : "?"));
1075 	printf("Build info:    %s\n", build_string);
1076 
1077 	return 0;
1078 }
1079 
1080 struct command subcmds_ec[] = {
1081 	CMD(ec_battery, "Show battery status"),
1082 	CMD(ec_bq25892, "Dump the state of the bq25892 charger chip"),
1083 	CMD(ec_bq27742, "Dump the state of the bq27742 gas gauge"),
1084 	CMD(ec_chargecontrol, "Force the battery to stop charging/discharge"),
1085 	CMD(ec_console, "Prints the last output to the EC debug console"),
1086 	CMD(ec_gpioget, "Get the value of GPIO signal"),
1087 	CMD(ec_gpioset, "Set the value of GPIO signal"),
1088 	CMD(ec_echash, "Various EC hash commands"),
1089 	CMD(ec_lightbar, "Lightbar control commands"),
1090 	CMD(ec_pi3usb9281, "Dump the state of the Pericom PI3USB9281 chip"),
1091 	CMD(ec_usbpd, "Control USB PD/type-C"),
1092 	CMD(ec_usbpdpower, "Power information about USB PD ports"),
1093 	CMD(ec_version, "Prints EC version"),
1094 	CMD_GUARD_LAST
1095 };
1096