Home | History | Annotate | Download | only in manual_tests
      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