summaryrefslogtreecommitdiff
path: root/driver/nfc/ctn730.c
diff options
context:
space:
mode:
Diffstat (limited to 'driver/nfc/ctn730.c')
-rw-r--r--driver/nfc/ctn730.c711
1 files changed, 0 insertions, 711 deletions
diff --git a/driver/nfc/ctn730.c b/driver/nfc/ctn730.c
deleted file mode 100644
index 6f711c509e..0000000000
--- a/driver/nfc/ctn730.c
+++ /dev/null
@@ -1,711 +0,0 @@
-/* Copyright 2020 The Chromium OS Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "chipset.h"
-#include "ctn730.h"
-#include "common.h"
-#include "console.h"
-#include "gpio.h"
-#include "i2c.h"
-#include "peripheral_charger.h"
-#include "timer.h"
-#include "util.h"
-#include "watchdog.h"
-
-/*
- * Configuration
- */
-
-/* Print additional data */
-#define CTN730_DEBUG
-
-/*
- * When ctn730 is asleep, I2C is ignored but can wake it up. I2C will be resent
- * after this delay.
- */
-static const int _wake_up_delay_ms = 10;
-
-/* Device detection interval */
-static const int _detection_interval_ms = 500;
-
-/* Buffer size for i2c read & write */
-#define CTN730_MESSAGE_BUFFER_SIZE 0x20
-
-/* This driver isn't compatible with big endian. */
-BUILD_ASSERT(__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__);
-
-#define CPRINTS(fmt, args...) cprints(CC_PCHG, "CTN730: " fmt, ##args)
-
-static const char *_text_instruction(uint8_t instruction)
-{
- /* TODO: For normal build, use %pb and BINARY_VALUE(res->inst, 6) */
- switch (instruction) {
- case WLC_HOST_CTRL_RESET:
- return "RESET";
- case WLC_HOST_CTRL_DL_OPEN_SESSION:
- return "DL_OPEN";
- case WLC_HOST_CTRL_DL_COMMIT_SESSION:
- return "DL_COMMIT";
- case WLC_HOST_CTRL_DL_WRITE_FLASH:
- return "DL_WRITE";
- case WLC_HOST_CTRL_DUMP_STATUS:
- return "DUMP_STATUS";
- case WLC_HOST_CTRL_GENERIC_ERROR:
- return "GENERIC_ERROR";
- case WLC_HOST_CTRL_BIST:
- return "BIST";
- case WLC_CHG_CTRL_ENABLE:
- return "ENABLE";
- case WLC_CHG_CTRL_DISABLE:
- return "DISABLE";
- case WLC_CHG_CTRL_DEVICE_STATE:
- return "DEVICE_STATE";
- case WLC_CHG_CTRL_CHARGING_STATE:
- return "CHARGING_STATE";
- case WLC_CHG_CTRL_CHARGING_INFO:
- return "CHARGING_INFO";
- default:
- return "UNDEF";
- }
-}
-
-static const char *_text_message_type(uint8_t type)
-{
- switch (type) {
- case CTN730_MESSAGE_TYPE_COMMAND:
- return "CMD";
- case CTN730_MESSAGE_TYPE_RESPONSE:
- return "RSP";
- case CTN730_MESSAGE_TYPE_EVENT:
- return "EVT";
- default:
- return "BAD";
- }
-}
-
-static const char *_text_status_code(uint8_t code)
-{
- switch (code) {
- case WLC_HOST_STATUS_OK:
- return "OK";
- case WLC_HOST_STATUS_PARAMETER_ERROR:
- return "PARAMETER_ERR";
- case WLC_HOST_STATUS_STATE_ERROR:
- return "STATE_ERR";
- case WLC_HOST_STATUS_VALUE_ERROR:
- return "VALUE_ERR";
- case WLC_HOST_STATUS_REJECTED:
- return "REJECTED";
- case WLC_HOST_STATUS_RESOURCE_ERROR:
- return "RESOURCE_ERR";
- case WLC_HOST_STATUS_TXLDO_ERROR:
- return "TXLDO_ERR";
- case WLC_HOST_STATUS_ANTENNA_SELECTION_ERROR:
- return "ANTENNA_SELECTION_ERR";
- case WLC_HOST_STATUS_BIST_FAILED:
- return "BIST_FAILED";
- case WLC_HOST_STATUS_BIST_NO_WLC_CAP:
- return "BIST_NO_WLC_CAP";
- case WLC_HOST_STATUS_BIST_TXLDO_CURRENT_OVERFLOW:
- return "BIST_TXLDO_CURRENT_OVERFLOW";
- case WLC_HOST_STATUS_BIST_TXLDO_CURRENT_UNDERFLOW:
- return "BIST_TXLDO_CURRENT_UNDERFLOW";
- case WLC_HOST_STATUS_FW_VERSION_ERROR:
- return "FW_VERSION_ERR";
- case WLC_HOST_STATUS_FW_VERIFICATION_ERROR:
- return "FW_VERIFICATION_ERR";
- case WLC_HOST_STATUS_NTAG_BLOCK_PARAMETER_ERROR:
- return "NTAG_BLOCK_PARAMETER_ERR";
- case WLC_HOST_STATUS_NTAG_READ_ERROR:
- return "NTAG_READ_ERR";
- default:
- return "UNDEF";
- }
-}
-
-static const char *_text_reset_reason(uint8_t code)
-{
- switch (code) {
- case WLC_HOST_CTRL_RESET_REASON_INTENDED:
- return "intended";
- case WLC_HOST_CTRL_RESET_REASON_CORRUPTED:
- return "corrupted";
- case WLC_HOST_CTRL_RESET_REASON_UNRECOVERABLE:
- return "unrecoverable";
- default:
- return "unknown";
- }
-}
-
-static int _i2c_read(int i2c_port, uint8_t *in, int in_len)
-{
- int rv;
-
- memset(in, 0, in_len);
-
- rv = i2c_xfer(i2c_port, CTN730_I2C_ADDR, NULL, 0, in, in_len);
- if (rv) {
- msleep(_wake_up_delay_ms);
- rv = i2c_xfer(i2c_port, CTN730_I2C_ADDR, NULL, 0, in, in_len);
- }
- if (rv)
- CPRINTS("Failed to read: %d", rv);
-
- return rv;
-}
-
-static void _print_header(const struct ctn730_msg *msg)
-{
- CPRINTS("%s_%s",
- _text_instruction(msg->instruction),
- _text_message_type(msg->message_type));
-}
-
-static int _send_command(struct pchg *ctx, const struct ctn730_msg *cmd)
-{
- int i2c_port = ctx->cfg->i2c_port;
- int rv;
-
- _print_header(cmd);
-
- rv = i2c_xfer(i2c_port, CTN730_I2C_ADDR, (void *)cmd,
- sizeof(*cmd) + cmd->length, NULL, 0);
-
- if (rv) {
- msleep(_wake_up_delay_ms);
- rv = i2c_xfer(i2c_port, CTN730_I2C_ADDR, (void *)cmd,
- sizeof(*cmd) + cmd->length, NULL, 0);
- }
- if (rv)
- CPRINTS("Failed to write: %d", rv);
-
- return rv;
-}
-
-static int ctn730_reset(struct pchg *ctx)
-{
- gpio_set_level(GPIO_WLC_NRST_CONN, 0);
- /*
- * Datasheet says minimum is 10 us. This is better not to be a sleep
- * especially if it's long (e.g. ~1 ms) since the PCHG state machine
- * may try to access the I2C bus, which is held low by ctn730.
- */
- udelay(15);
- gpio_set_level(GPIO_WLC_NRST_CONN, 1);
- return EC_SUCCESS_IN_PROGRESS;
-}
-
-static int ctn730_init(struct pchg *ctx)
-{
- uint8_t buf[CTN730_MESSAGE_BUFFER_SIZE];
- struct ctn730_msg *cmd = (void *)buf;
- int rv;
-
- 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;
-
- /* TODO: Run 1 sec timeout timer. */
- rv = _send_command(ctx, cmd);
- if (rv)
- return rv;
-
- /* WLC-host should send EVT_HOST_CTRL_RESET_EVT shortly. */
- return EC_SUCCESS_IN_PROGRESS;
-}
-
-static int ctn730_enable(struct pchg *ctx, bool enable)
-{
- uint8_t buf[CTN730_MESSAGE_BUFFER_SIZE];
- struct ctn730_msg *cmd = (void *)buf;
- uint16_t *interval = (void *)cmd->payload;
- int rv;
-
- cmd->message_type = CTN730_MESSAGE_TYPE_COMMAND;
- if (enable) {
- cmd->instruction = WLC_CHG_CTRL_ENABLE;
- cmd->length = WLC_CHG_CTRL_ENABLE_CMD_SIZE;
- /* Assume core is little endian. Use htole16 for portability. */
- *interval = _detection_interval_ms;
- } else {
- cmd->instruction = WLC_CHG_CTRL_DISABLE;
- cmd->length = WLC_CHG_CTRL_DISABLE_CMD_SIZE;
- }
-
- rv = _send_command(ctx, cmd);
- if (rv)
- return rv;
-
- return EC_SUCCESS_IN_PROGRESS;
-}
-
-static int _process_payload_response(struct pchg *ctx, struct ctn730_msg *res)
-{
- uint8_t len = res->length;
- uint8_t buf[CTN730_MESSAGE_BUFFER_SIZE];
-
- if (sizeof(buf) < len) {
- CPRINTS("Response size (%d) exceeds buffer", len);
- return EC_ERROR_OVERFLOW;
- }
-
- if (len > 0) {
- int rv = _i2c_read(ctx->cfg->i2c_port, buf, len);
- if (rv)
- return rv;
- if (IS_ENABLED(CTN730_DEBUG))
- CPRINTS("Payload: %ph", HEX_BUF(buf, len));
- }
-
- ctx->event = PCHG_EVENT_NONE;
-
- /*
- * Messages with no payload (<len> == 0) is allowed in the spec. So,
- * make sure <len> is checked before reading buf[0].
- */
- switch (res->instruction) {
- case WLC_HOST_CTRL_RESET:
- if (len != WLC_HOST_CTRL_RESET_RSP_SIZE)
- return EC_ERROR_UNKNOWN;
- if (buf[0] != WLC_HOST_STATUS_OK)
- ctx->event = PCHG_EVENT_OTHER_ERROR;
- break;
- case WLC_HOST_CTRL_DL_OPEN_SESSION:
- if (len != WLC_HOST_CTRL_DL_OPEN_SESSION_RSP_SIZE)
- return EC_ERROR_UNKNOWN;
- if (buf[0] != WLC_HOST_STATUS_OK) {
- CPRINTS("FW open session failed for %s",
- _text_status_code(buf[0]));
- ctx->event = PCHG_EVENT_UPDATE_ERROR;
- ctx->error |= PCHG_ERROR_MASK(PCHG_ERROR_FW_VERSION);
- } else {
- ctx->event = PCHG_EVENT_UPDATE_OPENED;
- }
- break;
- case WLC_HOST_CTRL_DL_COMMIT_SESSION:
- if (len != WLC_HOST_CTRL_DL_COMMIT_SESSION_RSP_SIZE)
- return EC_ERROR_UNKNOWN;
- if (buf[0] != WLC_HOST_STATUS_OK) {
- CPRINTS("FW commit failed for %s",
- _text_status_code(buf[0]));
- ctx->event = PCHG_EVENT_UPDATE_ERROR;
- ctx->error |= PCHG_ERROR_MASK(PCHG_ERROR_INVALID_FW);
- } else {
- ctx->event = PCHG_EVENT_UPDATE_CLOSED;
- }
- break;
- case WLC_HOST_CTRL_DL_WRITE_FLASH:
- if (len != WLC_HOST_CTRL_DL_WRITE_FLASH_RSP_SIZE)
- return EC_ERROR_UNKNOWN;
- if (buf[0] != WLC_HOST_STATUS_OK) {
- CPRINTS("FW write failed for %s",
- _text_status_code(buf[0]));
- ctx->event = PCHG_EVENT_UPDATE_ERROR;
- ctx->error |= PCHG_ERROR_MASK(PCHG_ERROR_WRITE_FLASH);
- } else {
- ctx->event = PCHG_EVENT_UPDATE_WRITTEN;
- }
- break;
- case WLC_CHG_CTRL_ENABLE:
- if (len != WLC_CHG_CTRL_ENABLE_RSP_SIZE)
- return EC_ERROR_UNKNOWN;
- if (buf[0] != WLC_HOST_STATUS_OK)
- ctx->event = PCHG_EVENT_OTHER_ERROR;
- else
- ctx->event = PCHG_EVENT_ENABLED;
- break;
- case WLC_CHG_CTRL_DISABLE:
- if (len != WLC_CHG_CTRL_DISABLE_RSP_SIZE)
- return EC_ERROR_UNKNOWN;
- if (buf[0] != WLC_HOST_STATUS_OK)
- ctx->event = PCHG_EVENT_OTHER_ERROR;
- else
- ctx->event = PCHG_EVENT_DISABLED;
- break;
- case WLC_CHG_CTRL_CHARGING_INFO:
- if (len != WLC_CHG_CTRL_CHARGING_INFO_RSP_SIZE)
- return EC_ERROR_UNKNOWN;
- if (buf[0] != WLC_HOST_STATUS_OK) {
- ctx->event = PCHG_EVENT_OTHER_ERROR;
- } else {
- ctx->battery_percent = buf[1];
- ctx->event = PCHG_EVENT_CHARGE_UPDATE;
- }
- break;
- default:
- CPRINTS("Received unknown response (%d)", res->instruction);
- break;
- }
-
- return EC_SUCCESS;
-}
-
-static int _process_payload_event(struct pchg *ctx, struct ctn730_msg *res)
-{
- uint8_t len = res->length;
- uint8_t buf[CTN730_MESSAGE_BUFFER_SIZE];
-
- if (sizeof(buf) < len) {
- CPRINTS("Response size (%d) exceeds buffer", len);
- return EC_ERROR_OVERFLOW;
- }
-
- if (len > 0) {
- int rv = _i2c_read(ctx->cfg->i2c_port, buf, len);
- if (rv)
- return rv;
- if (IS_ENABLED(CTN730_DEBUG))
- CPRINTS("Payload: %ph", HEX_BUF(buf, len));
- }
-
- ctx->event = PCHG_EVENT_NONE;
-
- /*
- * Messages with no payload (<len> == 0) is allowed in the spec. So,
- * make sure <len> is checked before reading buf[0].
- */
- switch (res->instruction) {
- case WLC_HOST_CTRL_RESET:
- if (len < WLC_HOST_CTRL_RESET_EVT_MIN_SIZE)
- return EC_ERROR_INVAL;
- if (buf[0] == WLC_HOST_CTRL_RESET_EVT_NORMAL_MODE) {
- if (len != WLC_HOST_CTRL_RESET_EVT_NORMAL_MODE_SIZE)
- return EC_ERROR_INVAL;
- ctx->event = PCHG_EVENT_IN_NORMAL;
- ctx->fw_version = (uint16_t)buf[1] << 8 | buf[2];
- CPRINTS("Normal Mode (FW=0x%02x.%02x)", buf[1], buf[2]);
- /*
- * ctn730 isn't immediately ready for i2c write after
- * normal mode initialization (b:178096436).
- */
- msleep(5);
- } else if (buf[0] == WLC_HOST_CTRL_RESET_EVT_DOWNLOAD_MODE) {
- if (len != WLC_HOST_CTRL_RESET_EVT_DOWNLOAD_MODE_SIZE)
- return EC_ERROR_INVAL;
- CPRINTS("Download Mode (%s)",
- _text_reset_reason(buf[1]));
- ctx->event = PCHG_EVENT_RESET;
- } else {
- return EC_ERROR_INVAL;
- }
- break;
- case WLC_HOST_CTRL_GENERIC_ERROR:
- break;
- case WLC_CHG_CTRL_DISABLE:
- if (len != WLC_CHG_CTRL_DISABLE_EVT_SIZE)
- return EC_ERROR_INVAL;
- ctx->event = PCHG_EVENT_DISABLED;
- break;
- case WLC_CHG_CTRL_DEVICE_STATE:
- if (len < WLC_CHG_CTRL_DEVICE_STATE_EVT_SIZE)
- return EC_ERROR_INVAL;
- switch (buf[0]) {
- case WLC_CHG_CTRL_DEVICE_STATE_DEVICE_DOCKED:
- if (len != WLC_CHG_CTRL_DEVICE_STATE_EVT_SIZE)
- return EC_ERROR_INVAL;
- ctx->event = PCHG_EVENT_DEVICE_DETECTED;
- break;
- case WLC_CHG_CTRL_DEVICE_STATE_DEVICE_DETECTED:
- if (len != WLC_CHG_CTRL_DEVICE_STATE_EVT_SIZE_DETECTED)
- return EC_ERROR_INVAL;
- ctx->event = PCHG_EVENT_DEVICE_CONNECTED;
- break;
- case WLC_CHG_CTRL_DEVICE_STATE_DEVICE_DEVICE_LOST:
- case WLC_CHG_CTRL_DEVICE_STATE_DEVICE_UNDOCKED:
- if (len != WLC_CHG_CTRL_DEVICE_STATE_EVT_SIZE)
- return EC_ERROR_INVAL;
- ctx->event = PCHG_EVENT_DEVICE_LOST;
- break;
- default:
- return EC_ERROR_INVAL;
- }
- break;
- case WLC_CHG_CTRL_CHARGING_STATE:
- if (len != WLC_CHG_CTRL_CHARGING_STATE_EVT_SIZE)
- return EC_ERROR_INVAL;
- switch (buf[0]) {
- case WLC_CHG_CTRL_CHARGING_STATE_CHARGE_STARTED:
- ctx->event = PCHG_EVENT_CHARGE_STARTED;
- break;
- case WLC_CHG_CTRL_CHARGING_STATE_CHARGE_ENDED:
- ctx->event = PCHG_EVENT_CHARGE_ENDED;
- break;
- case WLC_CHG_CTRL_CHARGING_STATE_CHARGE_STOPPED:
- /* Includes over temp., DISABLE_CMD, device removal. */
- ctx->event = PCHG_EVENT_CHARGE_STOPPED;
- break;
- default:
- return EC_ERROR_INVAL;
- }
- break;
- case WLC_CHG_CTRL_CHARGING_INFO:
- if (len != WLC_CHG_CTRL_CHARGING_INFO_EVT_SIZE || buf[0] > 100)
- return EC_ERROR_INVAL;
- ctx->event = PCHG_EVENT_CHARGE_UPDATE;
- ctx->battery_percent = buf[0];
- break;
- default:
- CPRINTS("Received unknown event (%d)", res->instruction);
- break;
- }
-
- return EC_SUCCESS;
-}
-
-static int ctn730_get_event(struct pchg *ctx)
-{
- struct ctn730_msg res;
- int i2c_port = ctx->cfg->i2c_port;
- int rv;
-
- /* Read message header */
- rv = _i2c_read(i2c_port, (uint8_t *)&res, sizeof(res));
- if (rv)
- return rv;
-
- _print_header(&res);
-
- if (res.message_type == CTN730_MESSAGE_TYPE_RESPONSE) {
- /* TODO: Check 1 sec timeout. */
- return _process_payload_response(ctx, &res);
- } else if (res.message_type == CTN730_MESSAGE_TYPE_EVENT) {
- return _process_payload_event(ctx, &res);
- }
-
- CPRINTS("Invalid message type (%d)", res.message_type);
- return EC_ERROR_UNKNOWN;
-}
-
-static int ctn730_get_soc(struct pchg *ctx)
-{
- struct ctn730_msg cmd;
- int rv;
-
- cmd.message_type = CTN730_MESSAGE_TYPE_COMMAND;
- cmd.instruction = WLC_CHG_CTRL_CHARGING_INFO;
- cmd.length = WLC_CHG_CTRL_CHARGING_INFO_CMD_SIZE;
-
- rv = _send_command(ctx, &cmd);
- if (rv)
- return rv;
-
- return EC_SUCCESS_IN_PROGRESS;
-}
-
-static int ctn730_update_open(struct pchg *ctx)
-{
- uint8_t buf[sizeof(struct ctn730_msg)
- + WLC_HOST_CTRL_DL_OPEN_SESSION_CMD_SIZE];
- struct ctn730_msg *cmd = (void *)buf;
- uint32_t version = ctx->update.version;
- int rv;
-
- cmd->message_type = CTN730_MESSAGE_TYPE_COMMAND;
- cmd->instruction = WLC_HOST_CTRL_DL_OPEN_SESSION;
- cmd->length = WLC_HOST_CTRL_DL_OPEN_SESSION_CMD_SIZE;
- cmd->payload[0] = (version >> 8) & 0xff;
- cmd->payload[1] = version & 0xff;
-
- rv = _send_command(ctx, cmd);
- if (rv)
- return rv;
-
- return EC_SUCCESS_IN_PROGRESS;
-}
-
-static int ctn730_update_write(struct pchg *ctx)
-{
- uint8_t buf[sizeof(struct ctn730_msg)
- + WLC_HOST_CTRL_DL_WRITE_FLASH_CMD_SIZE];
- struct ctn730_msg *cmd = (void *)buf;
- uint32_t *a = (void *)cmd->payload;
- uint8_t *d = (void *)&cmd->payload[CTN730_FLASH_ADDR_SIZE];
- int rv;
-
- /* Address is 3 bytes. FW size must be a multiple of 128 bytes. */
- if (ctx->update.addr & GENMASK(31, 24)
- || ctx->update.size != WLC_HOST_CTRL_DL_WRITE_FLASH_BLOCK_SIZE)
- return EC_ERROR_INVAL;
-
- cmd->message_type = CTN730_MESSAGE_TYPE_COMMAND;
- cmd->instruction = WLC_HOST_CTRL_DL_WRITE_FLASH;
- cmd->length = WLC_HOST_CTRL_DL_WRITE_FLASH_CMD_SIZE;
-
- /* 4th byte will be overwritten by memcpy below. */
- *a = ctx->update.addr;
-
- /* Store data in payload with 0-padding for short blocks. */
- memset(d, 0, WLC_HOST_CTRL_DL_WRITE_FLASH_BLOCK_SIZE);
- memcpy(d, ctx->update.data, ctx->update.size);
-
- rv = _send_command(ctx, cmd);
- if (rv)
- return rv;
-
- return EC_SUCCESS_IN_PROGRESS;
-}
-
-static int ctn730_update_close(struct pchg *ctx)
-{
- uint8_t buf[sizeof(struct ctn730_msg)
- + WLC_HOST_CTRL_DL_COMMIT_SESSION_CMD_SIZE];
- struct ctn730_msg *cmd = (void *)buf;
- uint32_t *crc32 = (void *)cmd->payload;
- int rv;
-
- cmd->message_type = CTN730_MESSAGE_TYPE_COMMAND;
- cmd->instruction = WLC_HOST_CTRL_DL_COMMIT_SESSION;
- cmd->length = WLC_HOST_CTRL_DL_COMMIT_SESSION_CMD_SIZE;
- *crc32 = ctx->update.crc32;
-
- rv = _send_command(ctx, cmd);
- if (rv)
- return rv;
-
- return EC_SUCCESS_IN_PROGRESS;
-}
-
-/**
- * Send command in blocking loop
- *
- * @param ctx PCHG port context
- * @param buf [IN] Command header and payload to send.
- * [OUT] Response header and payload received.
- * @param buf_len Size of <buf>
- * @return enum ec_error_list
- */
-static int _send_command_blocking(struct pchg *ctx, uint8_t *buf, int buf_len)
-{
- int i2c_port = ctx->cfg->i2c_port;
- int irq_pin = ctx->cfg->irq_pin;
- struct ctn730_msg *cmd = (void *)buf;
- struct ctn730_msg *res = (void *)buf;
- timestamp_t deadline;
- int rv;
-
- gpio_disable_interrupt(irq_pin);
-
- rv = _send_command(ctx, cmd);
- if (rv)
- goto exit;
-
- deadline.val = get_time().val + CTN730_COMMAND_TIME_OUT;
-
- /* Busy loop */
- while (gpio_get_level(irq_pin) == 0 && !rv) {
- udelay(1 * MSEC);
- rv = timestamp_expired(deadline, NULL);
- watchdog_reload();
- }
-
- if (rv) {
- ccprintf("Response timeout\n");
- rv = EC_ERROR_TIMEOUT;
- goto exit;
- }
-
- rv = _i2c_read(i2c_port, buf, sizeof(*res));
- if (rv)
- goto exit;
-
- _print_header(res);
-
- if (sizeof(*res) + res->length > buf_len) {
- ccprintf("RSP size exceeds buffer\n");
- rv = EC_ERROR_OVERFLOW;
- goto exit;
- }
-
- rv = _i2c_read(i2c_port, res->payload, res->length);
- if (rv)
- goto exit;
-
-exit:
- gpio_clear_pending_interrupt(irq_pin);
- gpio_enable_interrupt(irq_pin);
-
- return rv;
-}
-
-const struct pchg_drv ctn730_drv = {
- .reset = ctn730_reset,
- .init = ctn730_init,
- .enable = ctn730_enable,
- .get_event = ctn730_get_event,
- .get_soc = ctn730_get_soc,
- .update_open = ctn730_update_open,
- .update_write = ctn730_update_write,
- .update_close = ctn730_update_close,
-};
-
-static int cc_ctn730(int argc, char **argv)
-{
- int port;
- char *end;
- uint8_t buf[CTN730_MESSAGE_BUFFER_SIZE];
- struct ctn730_msg *cmd = (void *)buf;
- struct ctn730_msg *res = (void *)buf;
- int rv;
-
- if (argc < 4)
- return EC_ERROR_PARAM_COUNT;
-
- port = strtoi(argv[1], &end, 0);
- if (*end || port < 0 || pchg_count <= port)
- return EC_ERROR_PARAM2;
-
- cmd->message_type = CTN730_MESSAGE_TYPE_COMMAND;
-
- if (!strcasecmp(argv[2], "dump")) {
- int tag = strtoi(argv[3], &end, 0);
-
- if (*end || tag < 0 || 0x07 < tag)
- return EC_ERROR_PARAM3;
-
- cmd->instruction = WLC_HOST_CTRL_DUMP_STATUS;
- cmd->length = WLC_HOST_CTRL_DUMP_STATUS_CMD_SIZE;
- cmd->payload[0] = tag;
- } else if (!strcasecmp(argv[2], "bist")) {
- int id = strtoi(argv[3], &end, 0);
-
- if (*end || id < 0)
- return EC_ERROR_PARAM3;
-
- cmd->instruction = WLC_HOST_CTRL_BIST;
- cmd->payload[0] = id;
-
- switch (id) {
- case 0x01:
- /* Switch on RF field. Tx driver conf not implemented */
- cmd->length = 1;
- break;
- case 0x04:
- /* WLC device activation test */
- cmd->length = 1;
- break;
- default:
- return EC_ERROR_PARAM3;
- }
- } else {
- return EC_ERROR_PARAM2;
- }
-
- rv = _send_command_blocking(&pchgs[port], buf, sizeof(buf));
- if (rv)
- return rv;
-
- ccprintf("STATUS_%s\n", _text_status_code(res->payload[0]));
- hexdump(res->payload, res->length);
-
- return EC_SUCCESS;
-}
-DECLARE_CONSOLE_COMMAND(ctn730, cc_ctn730,
- "<port> dump/bist <tag/id>"
- "\n\t<port> dump <tag>"
- "\n\t<port> bist <test_id>",
- "Control ctn730");