1 /* 2 * Copyright (C) 2017 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 17 #include <ctype.h> 18 #include <errno.h> 19 #include <fcntl.h> 20 #include <getopt.h> 21 #include <signal.h> 22 #include <stdarg.h> 23 #include <stdint.h> 24 #include <stdio.h> 25 #include <stdlib.h> 26 #include <string.h> 27 #include <sys/stat.h> 28 #include <sys/types.h> 29 #include <unistd.h> 30 31 /* From Nugget OS */ 32 #include <application.h> 33 #include <app_nugget.h> 34 35 #include <nos/device.h> 36 #include <nos/transport.h> 37 38 /* Our connection to Citadel */ 39 static struct nos_device dev; 40 41 /* Our big transfer buffer. Apps may have smaller size limits. */ 42 static uint8_t buf[0x4000]; 43 44 enum { 45 BOARD_BINDER, 46 BOARD_PROTO1, 47 BOARD_EVT, 48 }; 49 50 /* Global options */ 51 static struct option_s { 52 /* program-specific options */ 53 uint8_t app_id; 54 uint16_t param; 55 int more; 56 int ascii; 57 int binary; 58 int verbose; 59 int buttons; 60 int board; 61 /* generic connection options */ 62 const char *device; 63 } option = { 64 .board = BOARD_EVT, 65 }; 66 67 enum no_short_opts_for_these { 68 OPT_DEVICE = 1000, 69 OPT_BUTTONS, 70 OPT_BINDER, 71 OPT_PROTO1, 72 OPT_EVT, 73 }; 74 75 static char *short_opts = ":hi:p:m:abv"; 76 static const struct option long_opts[] = { 77 /* name hasarg *flag val */ 78 {"id", 1, NULL, 'i'}, 79 {"param", 1, NULL, 'p'}, 80 {"more", 1, NULL, 'm'}, 81 {"ascii", 0, NULL, 'a'}, 82 {"binary", 0, NULL, 'b'}, 83 {"verbose", 0, NULL, 'v'}, 84 {"buttons", 0, NULL, OPT_BUTTONS}, 85 {"binder", 0, &option.board, BOARD_BINDER}, 86 {"proto1", 0, &option.board, BOARD_PROTO1}, 87 {"evt", 0, &option.board, BOARD_EVT}, 88 {"device", 1, NULL, OPT_DEVICE}, 89 {"help", 0, NULL, 'h'}, 90 {NULL, 0, NULL, 0}, 91 }; 92 93 static void usage(const char *progname) 94 { 95 fprintf(stderr, "\n"); 96 fprintf(stderr, "Usage: %s\n" 97 "Usage: %s test\n\n" 98 " Quick test to see if Citadel is responsive\n" 99 "\n" 100 " Options:\n" 101 " --buttons Prompt to press buttons\n" 102 " --binder | --proto1 | --evt Specify the board\n\n", 103 progname, progname); 104 fprintf(stderr, "Usage: %s tpm COMMAND [BYTE ...]\n" 105 "\n" 106 " Transmit the COMMAND and possibly any BYTEs using the\n" 107 " TPM Wait mode driver. COMMAND and BYTEs are hex values.\n" 108 "\n" 109 " Options:\n" 110 " -m, --more NUM Exchange NUM additional bytes\n\n", 111 progname); 112 fprintf(stderr, "Usage: %s app [BYTE [BYTE...]]\n" 113 "\n" 114 " Call an application function, passing any BYTEs as args\n" 115 "\n" 116 " Options:\n" 117 " -i --id HEX App ID (default 0x00)\n" 118 " -p, --param HEX Set the command Param field to HEX" 119 " (default 0x0000)\n\n", 120 progname); 121 fprintf(stderr, "Usage: %s rw ADDRESS [VALUE]\n" 122 "\n" 123 " Read or write a memory address on Citadel. Both ADDRESS\n" 124 " and VALUE are 32-bit hex numbers.\n\n", 125 progname); 126 fprintf(stderr, "Common options:\n\n" 127 " -a, --ascii Print response as ASCII string\n" 128 " -b, --binary Dump binary response to stdout\n" 129 " -v, --verbose Increase verbosity. More is noisier\n" 130 " --device PATH spidev device file to open\n" 131 " -h, --help Show this message\n" 132 "\n\n"); 133 } 134 135 /****************************************************************************/ 136 /* Handy stuff */ 137 138 #ifndef MIN 139 #define MIN(a, b) ((a) < (b) ? (a) : (b)) 140 #endif 141 142 static int errorcnt; 143 static void Error(const char *format, ...) 144 { 145 va_list ap; 146 147 va_start(ap, format); 148 fprintf(stderr, "ERROR: "); 149 vfprintf(stderr, format, ap); 150 fprintf(stderr, "\n"); 151 va_end(ap); 152 153 errorcnt++; 154 } 155 156 static void debug(int lvl, const char *format, ...) 157 { 158 va_list ap; 159 160 if (lvl > option.verbose) 161 return; 162 163 va_start(ap, format); 164 vfprintf(stderr, format, ap); 165 va_end(ap); 166 } 167 168 static void debug_buf(int lvl, uint8_t *buf, int bufsize) 169 { 170 int i; 171 172 if (lvl > option.verbose) 173 return; 174 175 if (bufsize <= 0) 176 return; 177 178 if (option.binary) { 179 fwrite(buf, bufsize, 1, stdout); 180 return; 181 } 182 183 if (option.ascii) { 184 for (i = 0; i < bufsize; i++) 185 printf("%c", isprint(buf[i]) ? buf[i] : '.'); 186 printf("\n"); 187 return; 188 } 189 190 for (i = 0; i < bufsize;) { 191 if (!(i % 16)) 192 printf("0x%06x: ", i); 193 printf(" %02x", buf[i]); 194 i++; 195 if (!(i % 16)) 196 printf("\n"); 197 } 198 if (i % 16) 199 printf("\n"); 200 } 201 202 static void debug_retval(int lvl, uint32_t retval, uint32_t replycount) 203 { 204 if (lvl > option.verbose) 205 return; 206 207 printf("retval 0x%08x (", retval); 208 switch (retval) { 209 case APP_SUCCESS: 210 printf("success"); 211 break; 212 case APP_ERROR_BOGUS_ARGS: 213 printf("bogus args"); 214 break; 215 case APP_ERROR_INTERNAL: 216 printf("app is being stupid"); 217 break; 218 case APP_ERROR_TOO_MUCH: 219 printf("caller sent too much data"); 220 break; 221 default: 222 if (retval >= APP_SPECIFIC_ERROR && retval < APP_LINE_NUMBER_BASE) 223 printf("app-specific error #%d", retval - APP_SPECIFIC_ERROR); 224 else if (retval >= APP_LINE_NUMBER_BASE) 225 printf("error at line %d", retval - APP_LINE_NUMBER_BASE); 226 else 227 printf("unknown"); 228 } 229 printf("), replycount 0x%x (%d)\n", replycount, replycount); 230 } 231 232 /****************************************************************************/ 233 /* Functionality */ 234 235 static void do_tpm(int argc, char *argv[]) 236 { 237 char *e = 0; 238 int i, rv, argcount, optind = 1; 239 uint32_t command, buflen; 240 241 /* Must have a command */ 242 if (optind < argc) { 243 command = strtoul(argv[optind], &e, 16); 244 if (e && *e) 245 Error("%s: Invalid COMMAND: \"%s\"", argv[0], argv[optind]); 246 optind++; 247 } else { 248 Error("%s: Missing required COMMAND", argv[0]); 249 return; 250 } 251 252 /* how many bytes to exchange? */ 253 argcount = argc - optind; 254 255 buflen = option.more + argcount; 256 if (buflen > MAX_DEVICE_TRANSFER) { 257 Error("%s: Too much to send", argv[0]); 258 return; 259 } 260 261 /* preload BYTEs from command line */ 262 for (i = 0; i < argcount; i++) { 263 buf[i] = 0xff & strtoul(argv[optind], &e, 16); 264 if (e && *e) { 265 Error("%s: Invalid byte value: \"%s\"", argv[0], argv[optind]); 266 return; 267 } 268 optind++; 269 } 270 271 /* Okay, let's do something */ 272 debug(1, "Command 0x%08x, buflen 0x%x\n", command, buflen); 273 274 if (command & 0x80000000) 275 rv = dev.ops.read(dev.ctx, command, buf, buflen); 276 else 277 rv = dev.ops.write(dev.ctx, command, buf, buflen); 278 279 if (rv != 0) 280 Error("%s: nuts", argv[0]); 281 else if (command & 0x80000000) 282 debug_buf(0, buf, buflen); 283 } 284 285 static void do_app(int argc, char *argv[]) 286 { 287 char *e = 0; 288 int optind = 1; 289 uint32_t i, buflen, replycount, retval; 290 291 /* preload BYTEs from command line */ 292 buflen = argc - optind; 293 for (i = 0; i < buflen; i++) { 294 buf[i] = 0xff & strtoul(argv[optind], &e, 16); 295 if (e && *e) { 296 Error("%s: Invalid byte value: \"%s\"", argv[0], argv[optind]); 297 return; 298 } 299 optind++; 300 } 301 302 debug(1, "AppID 0x%02x, App param 0x%04x, buflen 0x%x\n", 303 option.app_id, option.param, buflen); 304 305 replycount = sizeof(buf); 306 retval = nos_call_application(&dev, option.app_id, option.param, 307 buf, buflen, buf, &replycount); 308 debug_retval(1, retval, replycount); 309 debug_buf(0, buf, replycount); 310 } 311 312 /****************************************************************************/ 313 /* Available for bringup/debug only. See b/65067435 */ 314 315 static uint32_t read32(uint32_t address, uint32_t *valptr) 316 { 317 uint32_t buflen, replycount, retval; 318 319 debug(2, "read from 0x%08x\n", address); 320 buflen = sizeof(address); 321 memcpy(buf, &address, buflen); 322 replycount = sizeof(buf); 323 retval = nos_call_application(&dev, APP_ID_NUGGET, NUGGET_PARAM_READ32, 324 buf, buflen, buf, &replycount); 325 debug_retval(2, retval, replycount); 326 if (replycount == sizeof(*valptr)) { 327 memcpy(valptr, buf, sizeof(*valptr)); 328 debug(2, "value is 0x%08x\n", *valptr); 329 } 330 331 return retval; 332 } 333 334 static uint32_t write32(uint32_t address, uint32_t value) 335 { 336 uint32_t buflen, replycount, retval; 337 struct nugget_app_write32 w32; 338 339 /* Writing to address */ 340 debug(2, "write to 0x%08x with value 0x%08x\n", address, value); 341 w32.address = address; 342 w32.value = value; 343 buflen = sizeof(w32); 344 memcpy(buf, &w32, buflen); 345 replycount = sizeof(buf); 346 retval = nos_call_application(&dev, APP_ID_NUGGET, NUGGET_PARAM_WRITE32, 347 buf, buflen, buf, &replycount); 348 debug_retval(2, retval, replycount); 349 350 return retval; 351 } 352 353 static void do_rw(int argc, char *argv[]) 354 { 355 char *e = 0; 356 uint32_t retval, address, value; 357 358 argc = MIN(argc, 3); /* ignore any extra args */ 359 switch (argc) { 360 case 3: 361 value = strtoul(argv[2], &e, 16); 362 if (e && *e) { 363 Error("%s: Invalid value: \"%s\"", argv[0], argv[2]); 364 return; 365 } 366 /* fall through */ 367 case 2: 368 address = strtoul(argv[1], &e, 16); 369 if (e && *e) { 370 Error("%s: Invalid address: \"%s\"", argv[0], argv[1]); 371 return; 372 } 373 break; 374 default: 375 Error("%s: Missing required address", argv[0]); 376 return; 377 } 378 379 if (argc == 2) { 380 retval = read32(address, &value); 381 if (APP_SUCCESS != retval) 382 Error("%s: Read failed", argv[0]); 383 else 384 printf("0x%08x\n", value); 385 } else { 386 retval = write32(address, value); 387 if (APP_SUCCESS != retval) 388 Error("%s: Write failed", argv[0]); 389 } 390 } 391 392 /****************************************************************************/ 393 /* 394 * This stuff is a quick dead-or-alive test for SMT. We assume that the Citadel 395 * chip itself will work because it's passed its own manufacturing tests, but 396 * we need to know that the chip is powered up and the SPI bus and GPIOs are 397 * working. UART passthrough will have to be tested externally. 398 */ 399 400 /* ARM GPIO config registers */ 401 #define GPIO_DATA 0x40550000 402 #define GPIO_DATAOUT 0x40550004 403 #define GPIO_OUTENSET 0x40550010 404 405 /* Return true on success */ 406 static int write_to_file(const char *filename, const char *string) 407 { 408 int fd, rv; 409 ssize_t len, num; 410 411 /* Assume valid input */ 412 len = strlen(string); 413 414 fd = open(filename, O_WRONLY | O_SYNC); 415 if (fd < 0) { 416 debug(1, "can't open %s for writing: %s", filename, strerror(errno)); 417 return 0; 418 } 419 420 num = write(fd, string, len); 421 422 debug(2, "%s(%s, %s) wrote %d / %d\n", __func__, filename, string, num, len); 423 424 if (len != num) { 425 debug(1, "can't write %d bytes to %s: %s", len, filename, 426 strerror(errno)); 427 rv = close(fd); 428 if (rv) 429 debug(1, "can't close the file descriptor either: %s", 430 strerror(errno)); 431 return 0; 432 } 433 434 rv = close(fd); 435 if (rv) { 436 debug(1, "can't close the file descriptor for %s: %s", 437 filename, strerror(errno)); 438 return 0; 439 } 440 441 return 1; 442 } 443 444 /* Return true on success */ 445 static int read_from_file(const char *filename, char *buf, ssize_t bufsize) 446 { 447 int fd, rv; 448 ssize_t num; 449 450 fd = open(filename, O_RDONLY); 451 if (fd < 0) { 452 debug(2, "can't open %s for reading: %s", filename, strerror(errno)); 453 return 0; 454 } 455 456 num = read(fd, buf, bufsize - 1); /* leave room for '\0' */ 457 458 debug(2, "%s(%s) read %d bytes\n", __func__, filename, num); 459 460 if (num < 0) { 461 debug(1, "can't read from %s: %s", filename, strerror(errno)); 462 rv = close(fd); 463 if (rv) 464 debug(1, "can't close the file descriptor either: %s", 465 strerror(errno)); 466 return 0; 467 } 468 469 if (num == 0) { 470 debug(1, "file %s contains no data", filename); 471 rv = close(fd); 472 if (rv) 473 debug(1, "can't close the file descriptor either: %s", 474 strerror(errno)); 475 return 0; 476 477 } 478 479 debug_buf(2, (unsigned char *)buf, num); 480 481 rv = close(fd); 482 if (rv) 483 debug(1, "can't close the file descriptor for %s: %s", 484 filename, strerror(errno)); 485 486 return 1; 487 } 488 489 /* Returns true if we're able to export this gpio */ 490 static int is_ap_exported(uint32_t num) 491 { 492 char filename[80]; 493 char buf[80]; 494 495 debug(1, "%s(%d)\n", __func__, num); 496 497 /* It might already be exported. Try to read the value to see. */ 498 sprintf(filename, "/sys/class/gpio/gpio%d/value", num); 499 memset(buf, 0, sizeof(buf)); 500 if (read_from_file(filename, buf, sizeof(buf))) 501 return 1; /* yep */ 502 503 /* Request it */ 504 sprintf(buf, "%d", num); 505 if (!write_to_file("/sys/class/gpio/export", buf)) { 506 Error("%s: Can't request export of gpio %d", __func__, num); 507 return 0; 508 } 509 510 /* Try reading the value again */ 511 memset(buf, 0, sizeof(buf)); 512 if (read_from_file(filename, buf, sizeof(buf))) 513 return 1; /* yep */ 514 515 Error("%s: Nuts. Can't get export of gpio %d", __func__, num); 516 return 0; 517 } 518 519 /* Returns true if we're able to set this gpio to an output */ 520 static int is_ap_output(uint32_t num) 521 { 522 char filename[80]; 523 char buf[80]; 524 525 debug(1, "%s(%d)\n", __func__, num); 526 527 /* It might already be an output. Let's see. */ 528 sprintf(filename, "/sys/class/gpio/gpio%d/direction", num); 529 memset(buf, 0, sizeof(buf)); 530 if (!read_from_file(filename, buf, sizeof(buf))) { 531 debug(1, "Can't determine the direction of gpio %d", num); 532 return 0; 533 } 534 if (!strncmp("out", buf, 3)) 535 return 1; /* already an output */ 536 537 /* Set the direction */ 538 sprintf(buf, "%s", "out"); 539 if (!write_to_file(filename, buf)) { 540 Error("%s: Can't set the direction of gpio %d", __func__, num); 541 return 0; 542 } 543 544 /* Check again */ 545 memset(buf, 0, sizeof(buf)); 546 if (!read_from_file(filename, buf, sizeof(buf))) { 547 Error("%s: Can't determine the direction of gpio %d", __func__, num); 548 return 0; 549 } 550 if (!strncmp("out", buf, 3)) 551 return 1; /* yep, it's an output */ 552 553 Error("%s: Nuts. Can't set the direction of gpio %d", __func__, num); 554 return 0; 555 } 556 557 /* Return true on success */ 558 static int set_ap_value(uint32_t num, int val) 559 { 560 char filename[80]; 561 char buf[80]; 562 563 debug(1, "%s(%d, %d)\n", __func__, num, val); 564 565 sprintf(filename, "/sys/class/gpio/gpio%d/value", num); 566 sprintf(buf, "%d", val); 567 if (!write_to_file(filename, buf)) { 568 Error("%s: can't set gpio %d to %d", __func__, num, val); 569 return 0; 570 } 571 572 return 1; 573 } 574 575 /* This wiggles a GPIO on the AP and checks to make sure Citadel saw it */ 576 static void ap_wiggle(const char *name, uint32_t cit_gpio, uint32_t ap_gpio) 577 { 578 uint32_t prev, curr; 579 uint32_t cit_bit; 580 581 cit_bit = (1 << cit_gpio); 582 583 printf("Test %s AP gpio %d => Citadel gpio %d\n", name, ap_gpio, cit_gpio); 584 585 /* Configure AP for output */ 586 if (!is_ap_exported(ap_gpio)) 587 return; 588 if (!is_ap_output(ap_gpio)) 589 return; 590 591 debug(1, "cit_bit 0x%08x\n", cit_bit); 592 593 /* drive low, confirm low */ 594 if (!set_ap_value(ap_gpio, 0)) 595 return; 596 if (0 != read32(GPIO_DATA, &curr)) { 597 Error("%s: can't read Citadel GPIOs", __func__); 598 return; 599 } 600 debug(1, "citadel 0x%08x\n", curr); 601 if (curr & cit_bit) 602 Error("%s: expected cit_gpio %d low, was high", __func__, cit_gpio); 603 prev = curr; 604 605 /* Drive high, confirm high, no other bits changed */ 606 if (!set_ap_value(ap_gpio, 1)) 607 return; 608 if (0 != read32(GPIO_DATA, &curr)) { 609 Error("%s: can't read Citadel GPIOs", __func__); 610 return; 611 } 612 debug(1, "citadel 0x%08x\n", curr); 613 if (!(curr & cit_bit)) 614 Error("expected cit_gpio %d high, was low", cit_gpio); 615 if (prev != curr && (prev ^ curr) != cit_bit) 616 Error("unexpected GPIO change: prev 0x%08x cur 0x%08x", prev, curr); 617 prev = curr; 618 619 /* Drive Low, confirm low again, no other bits changed */ 620 if (!set_ap_value(ap_gpio, 0)) 621 return; 622 if (0 != read32(GPIO_DATA, &curr)) { 623 Error("%s: can't read Citadel GPIOs", __func__); 624 return; 625 } 626 debug(1, "citadel 0x%08x\n", curr); 627 if (curr & cit_bit) 628 Error("expected cit_gpio %d low, was high", cit_gpio); 629 if (prev != curr && (prev ^ curr) != cit_bit) 630 Error("unexpected GPIO change: prev 0x%08x cur 0x%08x", prev, curr); 631 } 632 633 static int stopped; 634 static void sig_handler(int sig) 635 { 636 stopped = 1; 637 printf("Signal %d recognized\n", sig); 638 } 639 640 /* This prompts the user to push a button and waits for Citadel to see it */ 641 static void phys_wiggle(uint32_t cit_gpio, const char *button) 642 { 643 uint32_t prev, curr; 644 uint32_t cit_bit; 645 646 stopped = 0; 647 signal(SIGINT, sig_handler); 648 649 cit_bit = (1 << cit_gpio); 650 651 debug(1, "%s(%d) cit_bit 0x%08x\n", __func__, cit_gpio, cit_bit); 652 653 /* read initial value */ 654 if (0 != read32(GPIO_DATA, &curr)) { 655 Error("%s: can't read Citadel GPIOs", __func__); 656 return; 657 } 658 debug(1, "initial value 0x%08x\n", curr); 659 prev = curr; 660 661 printf("\nPlease PRESS the %s button...\n", button); 662 do { 663 usleep(100 * 1000); 664 if (0 != read32(GPIO_DATA, &curr)) { 665 Error("%s: can't read Citadel GPIOs", __func__); 666 return; 667 } 668 } while (prev == curr && !stopped); 669 debug(1, "new value 0x%08x\n", curr); 670 if ((prev ^ curr) != cit_bit) 671 Error("%s: multiple cit_gpios changed: prev 0x%08x cur 0x%08x", 672 __func__, prev, curr); 673 prev = curr; 674 675 printf("Please RELEASE the %s button...\n", button); 676 do { 677 usleep(100 * 1000); 678 if (0 != read32(GPIO_DATA, &curr)) { 679 Error("%s: can't read Citadel GPIOs", __func__); 680 return; 681 } 682 } while (prev == curr && !stopped); 683 debug(1, "new value 0x%08x\n", curr); 684 if ((prev ^ curr) != cit_bit) 685 Error("%s: multiple cit_gpios changed: prev 0x%08x cur 0x%08x", 686 __func__, prev, curr); 687 688 signal(SIGINT, SIG_DFL); 689 } 690 691 /* How long to wait for an interrupt to trigger (msecs) */ 692 #define INTERRUPT_TIMEOUT 100 693 694 /* Make Citadel wiggle its CTDL_AP_IRQ output, which we should notice */ 695 static void cit_interrupt(const char *name, uint32_t cit_gpio) 696 { 697 uint32_t curr; 698 uint32_t cit_bit; 699 int rv; 700 701 printf("Test %s Citadel gpio %d => AP kernel driver\n", name, cit_gpio); 702 703 cit_bit = (1 << cit_gpio); 704 705 debug(1, "%s(%s, %d) cit_bit 0x%08x\n", __func__, name, cit_gpio, cit_bit); 706 707 /* First, let's see what Citadel is driving */ 708 if (0 != read32(GPIO_DATAOUT, &curr)) { 709 Error("%s: can't read Citadel GPIOs", __func__); 710 return; 711 } 712 713 debug(1, "initial value 0x%08x\n", curr); 714 if (curr & cit_bit) { 715 /* Citadel is already driving it, so we should see it immediately */ 716 rv = dev.ops.wait_for_interrupt(dev.ctx, INTERRUPT_TIMEOUT); 717 if (rv > 1) { 718 debug(2, "CTDL_AP_IRQ is already asserted\n"); 719 } else { 720 Error("%s: CTDL_AP_IRQ is 1, but wait_for_interrupt() returned %d", 721 __func__, rv); 722 return; 723 } 724 725 /* Tell Citadel to stop driving it */ 726 if (0 != write32(GPIO_DATAOUT, curr & (~cit_bit))) { 727 Error("%s: can't write Citadel GPIOs", __func__); 728 return; 729 } 730 731 /* Make sure it obeyed */ 732 if (0 != read32(GPIO_DATAOUT, &curr)) { 733 Error("%s: can't read Citadel GPIOs", __func__); 734 return; 735 } 736 if (curr & cit_bit) { 737 Error("%s: Citadel isn't changing its GPIOs", __func__); 738 return; 739 } 740 } 741 742 debug(1, "there should be no immediate interrupt\n"); 743 rv = dev.ops.wait_for_interrupt(dev.ctx, INTERRUPT_TIMEOUT); 744 if (rv == 0) { 745 debug(2, "CTDL_AP_IRQ not asserted and not triggered\n"); 746 } else { 747 Error("%s: CTDL_AP_IRQ is 0, but wait_for_interrupt() returned %d", 748 __func__, rv); 749 return; 750 } 751 752 debug(1, "tell Citadel to trigger an interrupt\n"); 753 if (0 != write32(GPIO_DATAOUT, curr | cit_bit)) { 754 Error("%s: can't write Citadel GPIOs", __func__); 755 return; 756 } 757 758 rv = dev.ops.wait_for_interrupt(dev.ctx, INTERRUPT_TIMEOUT); 759 if (rv > 0) { 760 debug(2, "CTDL_AP_IRQ is asserted and triggered\n"); 761 } else { 762 Error("%s: CTDL_AP_IRQ is 1, but wait_for_interrupt() returned %d", 763 __func__, rv); 764 return; 765 } 766 767 /* Tell Citadel to stop driving it */ 768 if (0 != write32(GPIO_DATAOUT, curr & (~cit_bit))) { 769 Error("%s: can't write Citadel GPIOs", __func__); 770 return; 771 } 772 } 773 774 static void do_test(void) 775 { 776 uint32_t retval, replycount, value; 777 int ctdl_ap_irq_is_driven = 0; 778 779 /* Using the Transport API only. Nugget OS doesn't have any Datagram apps. */ 780 printf("Get version string...\n"); 781 replycount = sizeof(buf); 782 retval = nos_call_application(&dev, APP_ID_NUGGET, NUGGET_PARAM_VERSION, 783 buf, 0, buf, &replycount); 784 if (retval != 0) { 785 Error("Get version failed with 0x%08x", retval); 786 debug_retval(0, retval, replycount); 787 goto done; 788 } 789 if (replycount < 4 || replycount > 1024) 790 Error("Get version returned %d bytes, which seems wrong", replycount); 791 /* might be okay, though */ 792 debug_buf(1, buf, replycount); 793 794 /* 795 * We want to drive each GPIO from the AP side and just check that 796 * Citadel can see it wiggle. Citadel treats them all as inputs for 797 * now. We'll have to update our tests when that changes, of course. 798 */ 799 800 printf("Read GPIO direction\n"); 801 retval = read32(GPIO_OUTENSET, &value); 802 if (retval != 0) { 803 Error("Reading GPIO direction failed with 0x%08x", retval); 804 goto done; 805 } 806 switch (value) { 807 case 0x00000000: 808 debug(1, "Citadel's GPIOs are all inputs\n"); 809 break; 810 case 0x00000080: 811 debug(1, "Citadel is driving CTDL_AP_IRQ\n"); 812 ctdl_ap_irq_is_driven = 1; 813 break; 814 default: 815 /* This is unexpected, but keep going */ 816 Error("GPIO direction = 0x%08x\n", value); 817 } 818 819 /* 820 * The MSM GPIOs have moved all around with each revision. 821 * 822 * Net Name Citadel Pin BINDER B1PROTO1 B1EVT1 823 * 824 * CTDL_AP_IRQ DIOA5 7 96 96 129 825 * AP_CTDL_IRQ DIOA11 6 94 94 135 826 * AP_SEC_STATE DIOB7 4 76 76 76 827 * AP_PWR_STATE DIOB8 5 69 69 69 828 * CCD_CABLE_DET DIOA6 8 127 126 126 829 */ 830 831 if (ctdl_ap_irq_is_driven) { 832 /* Citadel should interrupt us */ 833 cit_interrupt("CTDL_AP_IRQ", 7); 834 } else { 835 /* We'll wiggle the AP's GPIO and make sure Citadel sees it */ 836 if (option.board == BOARD_EVT) 837 ap_wiggle("CTDL_AP_IRQ", 7, 129); 838 else 839 ap_wiggle("CTDL_AP_IRQ", 7, 96); 840 } 841 842 if (option.board == BOARD_EVT) 843 ap_wiggle("AP_CTDL_IRQ", 6, 135); 844 else 845 ap_wiggle("AP_CTDL_IRQ", 6, 94); 846 847 ap_wiggle("AP_SEC_STATE", 4, 76); 848 ap_wiggle("AP_PWR_STATE", 5, 69); 849 850 if (option.board == BOARD_BINDER) 851 ap_wiggle("CCD_CABLE_DET", 8, 127); 852 else 853 ap_wiggle("CCD_CABLE_DET", 8, 126); 854 855 /* 856 * Citadel should be able to drive all the physical buttons under 857 * certain circumstances, but I don't know how to confirm whether the 858 * AP sees them change. We'll have to prompt the user to poke them to 859 * verify the connectivity. That's probably tested elsewhere, though. 860 */ 861 if (option.buttons) { 862 863 if (option.board != BOARD_PROTO1) 864 /* We had to cut this trace on proto1 (b/66976641) */ 865 phys_wiggle(0, "Power"); 866 867 phys_wiggle(1, "Volume Down"); 868 phys_wiggle(2, "Volume Up"); 869 870 if (option.board == BOARD_BINDER) 871 /* There's only a button on the binder board */ 872 phys_wiggle(10, "Forced USB Boot"); 873 } 874 875 /* 876 * These are harder to test. We'll have to change the UART passthrough 877 * to access the Citadel console and do these manually: 878 * 879 * Citadel GPIO 3 MSM_RST_OUT_L should wiggle when the phone reboots 880 * Citadel GPIO 9 PM_MSM_RST_L should force the AP to reboot 881 */ 882 883 done: 884 if (errorcnt) 885 printf("\nFAIL FAIL FAIL\n\n"); 886 else 887 printf("\nPASS PASS PASS\n\n"); 888 } 889 890 /****************************************************************************/ 891 892 /* 893 * Any SPI bus activity will wake Citadel from deep sleep, so we'll just send 894 * it a single bogus command. If Citadel's already awake, it will ignore it. 895 * We don't bother tracking or reporting errors. The test will report any real 896 * errors. 897 */ 898 #define IGNORED_COMMAND (CMD_ID(APP_ID_TEST) | CMD_PARAM(0xffff)) 899 static void poke_citadel(void) 900 { 901 int rv; 902 903 rv = dev.ops.write(dev.ctx, IGNORED_COMMAND, 0, 0); 904 905 /* If Citadel was asleep, give it some time to wake up */ 906 if (rv == -EAGAIN) 907 usleep(50000); 908 } 909 910 911 static int stopping_citadeld_fixed_it; 912 static int connect_to_citadel(void) 913 { 914 int rv = nos_device_open(option.device, &dev); 915 916 if (rv == -EBUSY) { 917 /* Try stopping citadeld */ 918 debug(1, "citadel device is busy, stopping citadeld...\n"); 919 if (system("setprop ctl.stop vendor.citadeld") == 0) { 920 /* See if that helped */ 921 rv = nos_device_open(option.device, &dev); 922 if (rv == 0) { 923 debug(1, " okay, that worked\n"); 924 stopping_citadeld_fixed_it = 1; 925 return rv; 926 } else { 927 debug(1, " nope, didn't help\n"); 928 } 929 } else { 930 debug(1, " huh. couldn't stop it\n"); 931 } 932 } 933 934 if (rv) 935 Error("Unable to connect to Citadel: %s", strerror(-rv)); 936 937 return rv; 938 } 939 940 static void disconnect_from_citadel(void) 941 { 942 dev.ops.close(dev.ctx); 943 if (stopping_citadeld_fixed_it) { 944 debug(1, "We stopped citadeld earlier, so start it up again\n"); 945 (void)system("setprop ctl.start vendor.citadeld"); 946 } 947 } 948 949 int main(int argc, char *argv[]) 950 { 951 int i; 952 int idx = 0; 953 char *e = 0; 954 char *this_prog; 955 956 this_prog= strrchr(argv[0], '/'); 957 if (this_prog) 958 this_prog++; 959 else 960 this_prog = argv[0]; 961 962 opterr = 0; /* quiet, you */ 963 while ((i = getopt_long(argc, argv, short_opts, long_opts, &idx)) != -1) { 964 switch (i) { 965 /* program-specific options */ 966 case 'i': 967 option.app_id = (uint8_t)strtoul(optarg, &e, 16); 968 if (!*optarg || (e && *e)) 969 Error("Invalid argument: \"%s\"", optarg); 970 break; 971 case 'p': 972 option.param = (uint16_t)strtoul(optarg, &e, 16); 973 if (!*optarg || (e && *e)) 974 Error("Invalid argument: \"%s\"", optarg); 975 break; 976 case 'm': 977 option.more = (uint32_t)strtoul(optarg, &e, 0); 978 if (!*optarg || (e && *e) || option.more < 0) 979 Error("Invalid argument: \"%s\"", optarg); 980 break; 981 case 'a': 982 option.ascii = 1; 983 option.binary = 0; 984 break; 985 case 'b': 986 option.ascii = 0; 987 option.binary = 1; 988 break; 989 case 'v': 990 option.verbose++; 991 break; 992 case OPT_BUTTONS: 993 option.buttons = 1; 994 break; 995 996 /* generic options below */ 997 case OPT_DEVICE: 998 option.device = optarg; 999 break; 1000 case 'h': 1001 usage(this_prog); 1002 return 0; 1003 case 0: 1004 break; 1005 case '?': 1006 if (optopt) 1007 Error("Unrecognized option: -%c", optopt); 1008 else 1009 Error("Unrecognized option: %s", argv[optind - 1]); 1010 usage(this_prog); 1011 break; 1012 case ':': 1013 Error("Missing argument to %s", argv[optind - 1]); 1014 break; 1015 default: 1016 Error("Internal error at %s:%d", __FILE__, __LINE__); 1017 exit(1); 1018 } 1019 } 1020 1021 if (errorcnt) 1022 return !!errorcnt; 1023 1024 if (connect_to_citadel() != 0) 1025 return !!errorcnt; 1026 1027 /* Wake Citadel from deep sleep */ 1028 poke_citadel(); 1029 1030 /* 1031 * We can freely intermingle options and args, so the function should 1032 * be the first non-option. Try to pick it out if it exists. 1033 */ 1034 if (argc > optind) { 1035 if (!strcmp("tpm", argv[optind])) 1036 do_tpm(argc - optind, argv + optind); 1037 else if (!strcmp("app", argv[optind])) 1038 do_app(argc - optind, argv + optind); 1039 else if (!strcmp("rw", argv[optind])) 1040 do_rw(argc - optind, argv + optind); 1041 else 1042 do_test(); 1043 /* 1044 * "test" is the default function, but it doesn't take any args 1045 * so anything not listed is just silently ignored. Too bad. 1046 */ 1047 } else { 1048 do_test(); 1049 } 1050 1051 disconnect_from_citadel(); 1052 return !!errorcnt; 1053 } 1054