diff options
author | Daisuke Nojiri <dnojiri@chromium.org> | 2022-10-06 15:27:38 -0700 |
---|---|---|
committer | Chromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com> | 2022-11-09 01:01:24 +0000 |
commit | 08e85b79b18a89314fcd14ef33ff8bb2cac53e3d (patch) | |
tree | ff241bd31f26eb079372c6992acd99df9a02e22d | |
parent | eb859ecdb21d67a74641b1485072d621087ae0ac (diff) | |
download | chrome-ec-08e85b79b18a89314fcd14ef33ff8bb2cac53e3d.tar.gz |
PCHG: Add pass-through modestabilize-quickfix-15183.78.B-mainstabilize-15183.69.B-main
In pass-through (passthru in short) mode, EC stops handling PCHG events
but reports IRQs to the host. This mode allows the host to directly
communicate with a chip using I2C pass-through, for example.
A host sends EC_CMD_PCHG_UPDATE with EC_PCHG_UPDATE_CMD_ENABLE_PASSTHRU
sub-command or EC_PCHG_UPDATE_CMD_RESET_TO_NORMAL sub-command to enter
or exit the mode.
BUG=b:245764044
BRANCH=None
TEST=Redrix
Signed-off-by: Daisuke Nojiri <dnojiri@chromium.org>
Change-Id: I16fe3f6ccd4a78bf3417fe3c0e86b5428a954acd
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3938411
Reviewed-by: caveh jalali <caveh@chromium.org>
(cherry picked from commit dfd2865721bd6d151d76b8beac53e5cc0d1e9164)
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/4014812
-rw-r--r-- | common/peripheral_charger.c | 51 | ||||
-rw-r--r-- | driver/nfc/ctn730.c | 25 | ||||
-rw-r--r-- | driver/nfc/ctn730.h | 6 | ||||
-rw-r--r-- | include/ec_commands.h | 4 | ||||
-rw-r--r-- | include/peripheral_charger.h | 3 | ||||
-rw-r--r-- | util/ectool.cc | 55 |
6 files changed, 122 insertions, 22 deletions
diff --git a/common/peripheral_charger.c b/common/peripheral_charger.c index 5767315a78..caaf535976 100644 --- a/common/peripheral_charger.c +++ b/common/peripheral_charger.c @@ -68,6 +68,21 @@ static const char *_text_state(enum pchg_state state) return state_names[state]; } +static const char *_text_mode(enum pchg_mode mode) +{ + static const char *const mode_names[] = { + [PCHG_MODE_NORMAL] = "NORMAL", + [PCHG_MODE_DOWNLOAD] = "DOWNLOAD", + [PCHG_MODE_PASSTHRU] = "PASSTHRU", + }; + BUILD_ASSERT(ARRAY_SIZE(mode_names) == PCHG_MODE_COUNT); + + if (mode < 0 || mode >= PCHG_MODE_COUNT) + return "UNDEF"; + + return mode_names[mode]; +} + static const char *_text_event(enum pchg_event event) { /* TODO: Use "S%d" for normal build. */ @@ -140,10 +155,10 @@ static enum pchg_state pchg_reset(struct pchg *ctx) } else if (rv != EC_SUCCESS_IN_PROGRESS) { CPRINTS("ERR: Failed to reset to normal mode"); } - } else { + } else if (ctx->mode == PCHG_MODE_DOWNLOAD) { state = PCHG_STATE_DOWNLOAD; pchg_queue_event(ctx, PCHG_EVENT_UPDATE_OPEN); - } + } /* No-op for passthru mode */ return state; } @@ -442,11 +457,17 @@ static int pchg_run(struct pchg *ctx) CPRINTS("P%d Run in STATE_%s for EVENT_%s", port, _text_state(ctx->state), _text_event(ctx->event)); + /* + * IRQ event is further translated to an actual event unless we're + * in passthru mode, where IRQ events will be passed to the host. + */ if (ctx->event == PCHG_EVENT_IRQ) { - rv = ctx->cfg->drv->get_event(ctx); - if (rv) { - CPRINTS("ERR: Failed to get event (%d)", rv); - return 0; + if (ctx->mode != PCHG_MODE_PASSTHRU) { + rv = ctx->cfg->drv->get_event(ctx); + if (rv) { + CPRINTS("ERR: Failed to get event (%d)", rv); + return 0; + } } CPRINTS(" EVENT_%s", _text_event(ctx->event)); } @@ -747,6 +768,23 @@ static enum ec_status hc_pchg_update(struct host_cmd_handler_args *args) ctx->update.crc32 = p->crc32; pchg_queue_event(ctx, PCHG_EVENT_UPDATE_CLOSE); break; + + case EC_PCHG_UPDATE_CMD_RESET: + HCPRINTS("Resetting"); + + gpio_disable_interrupt(ctx->cfg->irq_pin); + _clear_port(ctx); + ctx->cfg->drv->reset(ctx); + gpio_enable_interrupt(ctx->cfg->irq_pin); + break; + + case EC_PCHG_UPDATE_CMD_ENABLE_PASSTHRU: + HCPRINTS("Enabling passthru mode"); + mutex_lock(&ctx->mtx); + ctx->mode = PCHG_MODE_PASSTHRU; + mutex_unlock(&ctx->mtx); + break; + default: return EC_RES_INVALID_PARAM; } @@ -775,6 +813,7 @@ static int cc_pchg(int argc, const char **argv) ccprintf("P%d STATE_%s EVENT_%s SOC=%d%%\n", port, _text_state(ctx->state), _text_event(ctx->event), ctx->battery_percent); + ccprintf("mode=%s\n", _text_mode(ctx->mode)); ccprintf("error=0x%x dropped=%u fw_version=0x%x\n", ctx->error, ctx->dropped_event_count, ctx->fw_version); return EC_SUCCESS; diff --git a/driver/nfc/ctn730.c b/driver/nfc/ctn730.c index 090c140864..7d22927403 100644 --- a/driver/nfc/ctn730.c +++ b/driver/nfc/ctn730.c @@ -205,9 +205,9 @@ static int ctn730_init(struct pchg *ctx) cmd->message_type = CTN730_MESSAGE_TYPE_COMMAND; cmd->instruction = WLC_HOST_CTRL_RESET; cmd->length = WLC_HOST_CTRL_RESET_CMD_SIZE; - cmd->payload[0] = ctx->mode == PCHG_MODE_NORMAL ? - WLC_HOST_CTRL_RESET_CMD_MODE_NORMAL : - WLC_HOST_CTRL_RESET_CMD_MODE_DOWNLOAD; + cmd->payload[0] = ctx->mode == PCHG_MODE_DOWNLOAD ? + WLC_HOST_CTRL_RESET_CMD_MODE_DOWNLOAD : + WLC_HOST_CTRL_RESET_CMD_MODE_NORMAL; /* TODO: Run 1 sec timeout timer. */ rv = _send_command(ctx, cmd); @@ -341,6 +341,9 @@ static int _process_payload_response(struct pchg *ctx, struct ctn730_msg *res) ctx->event = PCHG_EVENT_CHARGE_UPDATE; } break; + case WLC_HOST_CTRL_BIST: + CPRINTS("Received BIST response"); + break; default: CPRINTS("Received unknown response (%d)", res->instruction); break; @@ -590,6 +593,13 @@ static int ctn730_update_close(struct pchg *ctx) return EC_SUCCESS_IN_PROGRESS; } +static int ctn730_passthru(struct pchg *ctx, bool enable) +{ + ctx->mode = enable ? PCHG_MODE_PASSTHRU : PCHG_MODE_NORMAL; + + return EC_SUCCESS; +} + /** * Send command in blocking loop * @@ -661,6 +671,7 @@ const struct pchg_drv ctn730_drv = { .update_open = ctn730_update_open, .update_write = ctn730_update_write, .update_close = ctn730_update_close, + .passthru = ctn730_passthru, }; static int cc_ctn730(int argc, const char **argv) @@ -700,12 +711,12 @@ static int cc_ctn730(int argc, const char **argv) cmd->payload[0] = id; switch (id) { - case 0x01: - /* Switch on RF field. Tx driver conf not implemented */ + case WLC_BIST_CMD_RF_SWITCH_ON: + case WLC_BIST_CMD_RF_SWITCH_OFF: + /* Tx driver configuration is not implemented. */ cmd->length = 1; break; - case 0x04: - /* WLC device activation test */ + case WLC_BIST_CMD_DEVICE_ACTIVATION_TEST: cmd->length = 1; break; default: diff --git a/driver/nfc/ctn730.h b/driver/nfc/ctn730.h index 6911d4fa5e..1689e93b00 100644 --- a/driver/nfc/ctn730.h +++ b/driver/nfc/ctn730.h @@ -91,6 +91,12 @@ #define WLC_CHG_CTRL_CHARGING_INFO_RSP_SIZE 2 #define WLC_CHG_CTRL_CHARGING_INFO_EVT_SIZE 5 +/* WLC_HOST_CTRL_BIST_CMD constants */ +#define WLC_BIST_RSP_SIZE 1 +#define WLC_BIST_CMD_RF_SWITCH_ON 0x01 +#define WLC_BIST_CMD_RF_SWITCH_OFF 0x02 +#define WLC_BIST_CMD_DEVICE_ACTIVATION_TEST 0x04 + /* Status Codes */ enum wlc_host_status { WLC_HOST_STATUS_OK = 0x00, diff --git a/include/ec_commands.h b/include/ec_commands.h index 7bb1f2b3d9..ee1e0664fb 100644 --- a/include/ec_commands.h +++ b/include/ec_commands.h @@ -7137,6 +7137,10 @@ enum ec_pchg_update_cmd { EC_PCHG_UPDATE_CMD_WRITE, /* Close update session. */ EC_PCHG_UPDATE_CMD_CLOSE, + /* Reset chip (without mode change). */ + EC_PCHG_UPDATE_CMD_RESET, + /* Enable pass-through mode. */ + EC_PCHG_UPDATE_CMD_ENABLE_PASSTHRU, /* End of commands */ EC_PCHG_UPDATE_CMD_COUNT, }; diff --git a/include/peripheral_charger.h b/include/peripheral_charger.h index ac193ba2da..2c3a334ed5 100644 --- a/include/peripheral_charger.h +++ b/include/peripheral_charger.h @@ -148,6 +148,7 @@ enum pchg_error { enum pchg_mode { PCHG_MODE_NORMAL = 0, PCHG_MODE_DOWNLOAD, + PCHG_MODE_PASSTHRU, /* Add no more entries below here. */ PCHG_MODE_COUNT, }; @@ -247,6 +248,8 @@ struct pchg_drv { int (*update_write)(struct pchg *ctx); /* close update session */ int (*update_close)(struct pchg *ctx); + /* Toggle pass-through mode. */ + int (*passthru)(struct pchg *ctx, bool enable); }; /** diff --git a/util/ectool.cc b/util/ectool.cc index c116b35fcc..b94be8a9de 100644 --- a/util/ectool.cc +++ b/util/ectool.cc @@ -9616,12 +9616,15 @@ static void cmd_pchg_help(char *cmd) " Usage2: %s <port>\n" " Print the status of <port>.\n" "\n" - " Usage3: %s <port> reset\n" - " Reset <port>.\n" + " Usage3: %s <port> reset [mode]\n" + " Reset <port> to [mode]. [mode]: 'normal'.\n" "\n" " Usage4: %s <port> update <version> <addr1> <file1> <addr2> <file2> ...\n" - " Update firmware of <port>.\n", - cmd, cmd, cmd, cmd); + " Update firmware of <port>.\n" + "\n" + " Usage5: %s <port> passthru <on/off> ...\n" + " Enable passthru mode for <port>.\n", + cmd, cmd, cmd, cmd, cmd); } static int cmd_pchg_info(const struct ec_response_pchg *res) @@ -9851,13 +9854,22 @@ static int cmd_pchg(int argc, char *argv[]) if (argc == 2) { /* Usage.2 */ return cmd_pchg_info(&r); - } else if (argc == 3 && !strcmp(argv[2], "reset")) { + } else if (argc >= 3 && !strcmp(argv[2], "reset")) { /* Usage.3 */ - struct ec_params_pchg_update *u = - (struct ec_params_pchg_update *)(ec_outbuf); + struct ec_params_pchg_update u; - u->cmd = EC_PCHG_UPDATE_CMD_RESET_TO_NORMAL; - rv = ec_command(EC_CMD_PCHG_UPDATE, 0, u, sizeof(*u), NULL, 0); + u.port = port; + + if (argc == 3) { + u.cmd = EC_PCHG_UPDATE_CMD_RESET; + } else if (argc == 4 && !strcmp(argv[3], "normal")) { + u.cmd = EC_PCHG_UPDATE_CMD_RESET_TO_NORMAL; + } else { + fprintf(stderr, "\nInvalid mode: '%s'\n", argv[3]); + return -1; + } + + rv = ec_command(EC_CMD_PCHG_UPDATE, 0, &u, sizeof(u), NULL, 0); if (rv < 0) { fprintf(stderr, "\nFailed to reset port %d: %d\n", port, rv); @@ -9926,6 +9938,31 @@ static int cmd_pchg(int argc, char *argv[]) } return 0; + } else if (argc >= 4 && !strcmp(argv[2], "passthru")) { + /* + * Usage 5 + */ + struct ec_params_pchg_update u; + int onoff; + + if (!parse_bool(argv[3], &onoff)) { + fprintf(stderr, "\nInvalid arg: '%s'\n", argv[3]); + return -1; + } + + u.port = port; + u.cmd = EC_PCHG_UPDATE_CMD_ENABLE_PASSTHRU; + + rv = ec_command(EC_CMD_PCHG_UPDATE, 0, &u, sizeof(u), NULL, 0); + if (rv < 0) { + fprintf(stderr, "\nFailed to enable pass-through: %d\n", + rv); + return rv; + } + + printf("Pass-through is %s for port %d\n", + onoff ? "enabled" : "disabled", port); + return 0; } fprintf(stderr, "Invalid parameter\n\n"); |