summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaisuke Nojiri <dnojiri@chromium.org>2022-10-06 15:27:38 -0700
committerChromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com>2022-11-09 01:01:24 +0000
commit08e85b79b18a89314fcd14ef33ff8bb2cac53e3d (patch)
treeff241bd31f26eb079372c6992acd99df9a02e22d
parenteb859ecdb21d67a74641b1485072d621087ae0ac (diff)
downloadchrome-ec-stabilize-15183.69.B-main.tar.gz
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.c51
-rw-r--r--driver/nfc/ctn730.c25
-rw-r--r--driver/nfc/ctn730.h6
-rw-r--r--include/ec_commands.h4
-rw-r--r--include/peripheral_charger.h3
-rw-r--r--util/ectool.cc55
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");