summaryrefslogtreecommitdiff
path: root/driver
diff options
context:
space:
mode:
authorDerek Huang <derekhuang@google.com>2022-12-14 10:01:02 +0000
committerChromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com>2023-03-08 03:52:46 +0000
commit42a911f7d9ca7db0933315c0eed6367ba7469681 (patch)
tree8e33ceba1068d2e14253d26918930ea046280792 /driver
parent1fbdcd9f057bc34d9b15b6a0d5eafee19df33152 (diff)
downloadchrome-ec-42a911f7d9ca7db0933315c0eed6367ba7469681.tar.gz
driver/wpc/cps8100.c: Add support of CPS8200 firmware update
This patch adds cps8200_update_open, cps8200_update_write and cps8200_update_close functions which allow the host updater (e.g. ectool) to update firmware of cps8200 via I2C. Example: localhost ~ # ectool pchg 0 update 0x3 0x0 /path/to/image.bin Opened update session (port=0 ver=0x3 bsize=128): 0x0 /path/to/image.bin Writing /path/to/image.bin (33980 bytes) ************************************************************** Firmware was updated successfully (CRC32=0xfe43d401). BUG=b:195708351 BRANCH=none TEST=ectool pchg 0 update 0x3 0x0 ./CPS8200_A0_40_V3_CRCBEA6.bin Change-Id: I4e17a308714c94dc2b9335943536a732297b86fc Signed-off-by: Derek Huang <derekhuang@google.com> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/4105947 Reviewed-by: Daisuke Nojiri <dnojiri@chromium.org>
Diffstat (limited to 'driver')
-rw-r--r--driver/wpc/cps8100.c487
-rw-r--r--driver/wpc/cps8100.h1
-rw-r--r--driver/wpc/cps8200_bootloader.h85
3 files changed, 535 insertions, 38 deletions
diff --git a/driver/wpc/cps8100.c b/driver/wpc/cps8100.c
index bac911d167..006a42f131 100644
--- a/driver/wpc/cps8100.c
+++ b/driver/wpc/cps8100.c
@@ -6,6 +6,8 @@
#include "chipset.h"
#include "common.h"
#include "console.h"
+#include "cps8200_bootloader.h"
+#include "crc.h"
#include "gpio.h"
#include "i2c.h"
#include "peripheral_charger.h"
@@ -56,11 +58,36 @@
#define CPS8200_REG_I2C_ENABLE 0xFFFFFF00
#define CPS8200_REG_PASSWORD 0x400140FC
+/* Firmware update */
+#define CPS8200_ADDR_SRAM 0x20000000
+#define CPS8200_ADDR_BUFFER0 0x20002800
+#define CPS8200_ADDR_BUFFER1 0x20003000
+#define CPS8200_ADDR_CMD 0x200038F8
+#define CPS8200_ADDR_CMD_STATUS 0x200038FC
+#define CPS8200_ADDR_BUF_SIZE 0x200038F4
+#define CFG_BUFF_SIZE 128
+#define CPS8200_CMD_TIMEOUT (3 * SECOND)
+/* CMD and CMD status. Lower 4 bits are for command ID */
+#define CMD_PGM_BUFFER0 (0x1 << 4)
+#define CMD_PGM_BUFFER1 (0x2 << 4)
+#define CMD_PGM_WR_FLAG (0x8 << 4)
+#define CMD_CACL_CRC_APP (0x9 << 4)
+#define CMD_CACL_CRC_BOOT (0xB << 4)
+#define CMD_STATUS_RUNNING (0x1 << 4)
+#define CMD_STATUS_PASS (0x2 << 4)
+#define CMD_STATUS_FAIL (0x3 << 4)
+#define CMD_STATUS_ILLEGAL (0x4 << 4)
+
#define CPS8100_STATUS_PROFILE(r) (((r)&GENMASK(5, 4)) >> 4)
#define CPS8100_STATUS_CHARGE(r) ((r)&BIT(6))
#define CPS8100_STATUS_DEVICE(r) ((r)&BIT(7))
#define CPS8100_STATUS_BATTERY(r) (((r)&GENMASK(15, 8)) >> 8)
#define CPS8100_IRQ_TYPE(r) (((r)&GENMASK(23, 20)) >> 20)
+#define CPS8200_CMD_STATUS(flag) ((flag)&GENMASK(7, 4))
+#define CPS8X00_GET_FW_VER(value) ((value)&GENMASK(7, 0))
+#define CPS8X00_BAD_FW_VERSION 0xff
+#define CPS8200_CMD_MASK GENMASK(7, 4)
+#define CPS8200_CMD_ID_MASK GENMASK(3, 0)
/* Status flags in ALERT_INFO register */
#define CPS8100_STATUS_FOD BIT(0)
@@ -72,7 +99,15 @@
/* Buffer size for i2c read & write */
#define CPS8100_MESSAGE_BUFFER_SIZE 0x20
+/*
+ * CPS8100 needs 100~120ms delay and CPS8200 needs 40~50ms delay between
+ * reset and the first access to I2C register.
+ */
+#define CPS8200_POWER_ON_DELAY_MS 50
+#define CPS8100_POWER_ON_DELAY_MS 120
+
static uint32_t chip_id;
+static const int short_sleep_ms = 2;
/* TODO: Check datasheet how to wake up and how long it takes to wake up. */
static const int cps8100_wake_up_delay_ms = 10;
@@ -305,6 +340,23 @@ static int cps8100_read32(int port, uint32_t reg, uint32_t *val)
sizeof(*val));
}
+static int cps8200_write32(int port, uint32_t reg, uint32_t val)
+{
+ uint8_t buf[8];
+
+ buf[0] = (reg >> 24) & 0xff;
+ buf[1] = (reg >> 16) & 0xff;
+ buf[2] = (reg >> 8) & 0xff;
+ buf[3] = (reg >> 0) & 0xff;
+
+ buf[4] = (val >> 0) & 0xff;
+ buf[5] = (val >> 8) & 0xff;
+ buf[6] = (val >> 16) & 0xff;
+ buf[7] = (val >> 24) & 0xff;
+
+ return cps8100_i2c_write(port, CPS8200_I2C_ADDR, buf, sizeof(buf));
+}
+
static int cps8200_read32(int port, uint32_t reg, uint32_t *val)
{
uint8_t buf[4];
@@ -314,10 +366,36 @@ static int cps8200_read32(int port, uint32_t reg, uint32_t *val)
buf[2] = (reg >> 8) & 0xff;
buf[3] = (reg >> 0) & 0xff;
- return i2c_xfer(port, CPS8200_I2C_ADDR, buf, 4, (void *)val,
+ return i2c_xfer(port, CPS8200_I2C_ADDR, buf, sizeof(buf), (void *)val,
sizeof(*val));
}
+static int cps8200_write_mem(int port, uint32_t addr, uint8_t *data, size_t len)
+{
+ int rv;
+ uint8_t buf[4];
+
+ buf[0] = (addr >> 24) & 0xff;
+ buf[1] = (addr >> 16) & 0xff;
+ buf[2] = (addr >> 8) & 0xff;
+ buf[3] = (addr >> 0) & 0xff;
+
+ i2c_lock(port, 1);
+ /* Addr */
+ rv = i2c_xfer_unlocked(port, CPS8200_I2C_ADDR, buf, sizeof(buf), NULL,
+ 0, I2C_XFER_START);
+ if (rv) {
+ i2c_lock(port, 0);
+ return rv;
+ }
+ /* Data */
+ rv = i2c_xfer_unlocked(port, CPS8200_I2C_ADDR, data, len, NULL, 0,
+ I2C_XFER_STOP);
+ i2c_lock(port, 0);
+
+ return rv;
+}
+
static int cps8100_unlock(int port)
{
int rv;
@@ -334,7 +412,80 @@ static int cps8200_unlock(int port)
return rv ? rv : cps8200_set_unlock(port);
}
-static int cps8100_reset(struct pchg *ctx)
+/*
+ * Send command to CPS8200 by writing command to CPS8200_ADDR_CMD register.
+ * command = cmd (higher 4 bits) + id (lower 4 bits), id needs to be increased
+ * every time.
+ */
+static uint8_t cps8200_send_cmd(struct pchg *ctx, uint8_t cmd, uint8_t *id)
+{
+ uint8_t port = ctx->cfg->i2c_port;
+ struct cps8x00_update *upd = &(ctx->update.driver_data.cps8200_update);
+
+ *id = upd->cmd_id;
+ cmd &= CPS8200_CMD_MASK;
+ cmd |= *id;
+ upd->cmd_id++;
+ upd->cmd_id &= CPS8200_CMD_ID_MASK;
+
+ return cps8200_write32(port, CPS8200_ADDR_CMD, (uint32_t)cmd);
+}
+
+/*
+ * Read the response of command by reading CPS8200_ADDR_CMD_STATUS register.
+ * Return EC_SUCCESS if the status is CMD_STATUS_PASS and the id matches to
+ * the id which is expected.
+ */
+static int cps8200_wait_cmd_done(int port, uint8_t id)
+{
+ int rv;
+ uint32_t u32;
+ timestamp_t deadline;
+
+ deadline.val = get_time().val + CPS8200_CMD_TIMEOUT;
+ while (1) {
+ msleep(10);
+ rv = cps8200_read32(port, CPS8200_ADDR_CMD_STATUS, &u32);
+ if (rv)
+ return EC_ERROR_UNKNOWN;
+
+ if ((CMD_STATUS_PASS | id) == (u32 & 0x00ff))
+ break;
+ if (CPS8200_CMD_STATUS(u32) == CMD_STATUS_FAIL ||
+ CPS8200_CMD_STATUS(u32) == CMD_STATUS_ILLEGAL) {
+ CPRINTS("Command failed or illegal: %02x",
+ CPS8200_CMD_STATUS(u32));
+ return EC_ERROR_UNKNOWN;
+ }
+
+ rv = timestamp_expired(deadline, NULL);
+ if (rv) {
+ CPRINTS("Command timeout!");
+ return EC_ERROR_TIMEOUT;
+ }
+ }
+ return EC_SUCCESS;
+}
+
+static int cps8x00_read_firmware_ver(struct pchg *ctx)
+{
+ uint32_t u32;
+ int port = ctx->cfg->i2c_port;
+ int rv;
+
+ rv = cps8x00_read32(port, CPS8100_REG_FW_INFO, &u32);
+ if (!rv) {
+ ctx->fw_version = CPS8X00_GET_FW_VER(u32);
+ } else {
+ ctx->fw_version = CPS8X00_BAD_FW_VERSION;
+ CPRINTS("Failed to read FW info: %d", rv);
+ return EC_ERROR_UNKNOWN;
+ }
+
+ return EC_SUCCESS;
+}
+
+static int cps8x00_reset(struct pchg *ctx)
{
gpio_set_level(GPIO_QI_RESET_L, 0);
cps8100_status_update(ctx, 0);
@@ -344,7 +495,7 @@ static int cps8100_reset(struct pchg *ctx)
return EC_SUCCESS;
}
-static int cps8100_init(struct pchg *ctx)
+static int cps8x00_init(struct pchg *ctx)
{
int port = ctx->cfg->i2c_port;
@@ -357,7 +508,7 @@ static int cps8100_init(struct pchg *ctx)
return EC_ERROR_UNKNOWN;
}
-static int cps8100_enable(struct pchg *ctx, bool enable)
+static int cps8x00_enable(struct pchg *ctx, bool enable)
{
return EC_SUCCESS;
}
@@ -375,30 +526,26 @@ static int cps8100_get_alert_info(struct pchg *ctx, uint32_t *reg)
return EC_SUCCESS;
}
-static int cps8100_get_chip_info(struct pchg *ctx)
+static int cps8x00_get_chip_info(struct pchg *ctx)
{
uint32_t u32;
int port = ctx->cfg->i2c_port;
int rv = EC_ERROR_UNKNOWN;
- /*
- * CPS8100 needs 100~120ms delay, CPS8200 needs 40~50ms delay
- * between reset and the first access to I2C register.
- */
if (chip_id == CPS8100_CHIPID) {
/*
* already probed but unlock again in case it's turned
* off.
*/
- msleep(120);
+ msleep(CPS8100_POWER_ON_DELAY_MS);
return cps8100_unlock(port);
} else if (chip_id == CPS8200_CHIPID) {
- msleep(50);
+ msleep(CPS8200_POWER_ON_DELAY_MS);
return cps8200_unlock(port);
}
/* not probed yet, need to unlock blindly first. */
- msleep(120);
+ msleep(MAX(CPS8100_POWER_ON_DELAY_MS, CPS8200_POWER_ON_DELAY_MS));
if (!cps8100_unlock(port))
rv = cps8100_read32(port, CPS8100_REG_IC_INFO, &u32);
else if (!cps8200_unlock(port))
@@ -409,7 +556,7 @@ static int cps8100_get_chip_info(struct pchg *ctx)
return rv;
}
- /* Probe */;
+ /* Probe */
CPRINTS("IC=0x%08x", u32);
if ((u32 & 0xffff) == CPS8100_CHIPID) {
cps8x00_read32 = cps8100_read32;
@@ -422,12 +569,9 @@ static int cps8100_get_chip_info(struct pchg *ctx)
return EC_ERROR_UNKNOWN;
}
- if (!cps8x00_read32(port, CPS8100_REG_FW_INFO, &u32)) {
- CPRINTS("FW=0x%08x", u32);
- } else {
- CPRINTS("Failed to read FW info!");
- return EC_ERROR_UNKNOWN;
- }
+ rv = cps8x00_read_firmware_ver(ctx);
+ if (!rv)
+ CPRINTS("FW=0x%02x", ctx->fw_version);
return EC_SUCCESS;
}
@@ -445,7 +589,7 @@ static void cps8100_print_alert_info(uint32_t reg)
CPRINTFP("Battery: %d%%\n", CPS8100_STATUS_BATTERY(reg));
}
-static int cps8100_get_event(struct pchg *ctx)
+static int cps8x00_get_event(struct pchg *ctx)
{
uint32_t r1, r2;
int rv;
@@ -486,38 +630,305 @@ static int cps8100_get_event(struct pchg *ctx)
return EC_SUCCESS;
}
-static int cps8100_get_soc(struct pchg *ctx)
+static int cps8x00_get_soc(struct pchg *ctx)
{
ctx->battery_percent = CPS8100_STATUS_BATTERY(cps8100_state.reg);
return EC_SUCCESS;
}
-static int cps8100_update_open(struct pchg *ctx)
+/*
+ * This function does the preparation for firmware update, the steps are:
+ * 1. Enable i2c and unlock.
+ * 2. Reset MCU, reset watchdog, disable DCDC and reset MCU clock.
+ * 3. Program bootloader to SRAM.
+ * 4. Run bootloader.
+ * 5. Check CRC of bootloader.
+ * 6. Ready for firmware download. Configure buffer size for firmware download.
+ */
+static int cps8200_update_open(struct pchg *ctx)
{
- return EC_ERROR_UNIMPLEMENTED;
+ uint32_t u32;
+ uint8_t id;
+ int port = ctx->cfg->i2c_port;
+ int rv;
+ struct cps8x00_update *upd = &(ctx->update.driver_data.cps8200_update);
+
+ upd->cmd_id = 0;
+ upd->crc = 0;
+ upd->firmware_len = 0;
+
+ /* enable i2c and unlock */
+ rv = cps8200_unlock(port);
+ if (rv)
+ return rv;
+
+ /*
+ * The value and address of the registers are from the sample code
+ * and programming guide provided by the vendor in
+ * https://issuetracker.google.com/issues/195708351#comment32
+ */
+
+ /* Reset MCU and halt */
+ rv = cps8200_write32(port, 0x40014028, 0x00010000);
+ if (rv)
+ return rv;
+ msleep(50);
+
+ /* Reset watchdog */
+ rv = cps8200_write32(port, 0x40008400, 0x1ACCE551);
+ if (rv)
+ return rv;
+ msleep(short_sleep_ms);
+ rv = cps8200_write32(port, 0x40008008, 0x0);
+ if (rv)
+ return rv;
+ msleep(short_sleep_ms);
+
+ /* Disable DCDC module */
+ rv = cps8200_write32(port, 0x4000F0A4, 0x0);
+ if (rv)
+ return rv;
+ msleep(50);
+
+ /* Reset MCU clock */
+ rv = cps8200_write32(port, 0x40014020, 0x0);
+ if (rv)
+ return rv;
+ msleep(short_sleep_ms);
+ rv = cps8200_write32(port, 0x40014024, 0x0);
+ if (rv)
+ return rv;
+ msleep(short_sleep_ms);
+ rv = cps8200_write32(port, 0x400140A8, 0x0);
+ if (rv)
+ return rv;
+ msleep(short_sleep_ms);
+
+ /* Program bootloader to SRAM */
+ CPRINTS("Loading bootloader hex!");
+ if (cps8200_write_mem(port, CPS8200_ADDR_SRAM, (uint8_t *)&boot_hex,
+ boot_hex_len * 4)) {
+ CPRINTS("Failed to write bootloader!");
+ return EC_ERROR_UNKNOWN;
+ }
+ msleep(short_sleep_ms);
+
+ /* disable trim */
+ rv = cps8200_write32(port, 0x4001F01C, 0x0);
+ if (rv)
+ return rv;
+ msleep(short_sleep_ms);
+
+ /* enable address remap */
+ rv = cps8200_write32(port, 0x4001F030, 0xFFFFFF00);
+ if (rv)
+ return rv;
+ msleep(short_sleep_ms);
+ rv = cps8200_write32(port, 0x4001F034, 0xFFFFFFFF);
+ if (rv)
+ return rv;
+ msleep(short_sleep_ms);
+ rv = cps8200_write32(port, 0x4001F038, 0xFFFFFFFF);
+ if (rv)
+ return rv;
+ msleep(short_sleep_ms);
+ rv = cps8200_write32(port, 0x4001F03C, 0xFFFFFFFF);
+ if (rv)
+ return rv;
+ msleep(short_sleep_ms);
+
+ /* disable mcu halt, run bootloader */
+ rv = cps8200_write32(port, 0x40014028, 0x101);
+ if (rv)
+ return rv;
+ msleep(short_sleep_ms);
+
+ /* enable i2c and unlock */
+ rv = cps8200_i2c_enable(port);
+ if (rv)
+ return rv;
+ msleep(short_sleep_ms);
+
+ /* write bootloader length */
+ rv = cps8200_write32(port, CPS8200_ADDR_BUFFER0, boot_hex_len * 4);
+ if (rv)
+ return rv;
+ msleep(short_sleep_ms);
+
+ /* calculate CRC of bootloader */
+ rv = cps8200_send_cmd(ctx, CMD_CACL_CRC_BOOT, &id);
+ if (rv)
+ return rv;
+
+ /* check command status */
+ rv = cps8200_wait_cmd_done(port, id);
+ if (rv)
+ return rv;
+ msleep(100);
+
+ /* check CRC */
+ rv = cps8200_read32(port, CPS8200_ADDR_BUFFER0, &u32);
+ if (rv)
+ return rv;
+ upd->crc = cros_crc16((uint8_t *)boot_hex, boot_hex_len * 4, 0);
+ if (upd->crc != (u32 & 0x0000ffff)) {
+ CPRINTS("crc = %04x, expect %04x", u32, upd->crc);
+ CPRINTS("CRC of bootloader is wroing!");
+ return EC_ERROR_UNKNOWN;
+ }
+ CPRINTS("Successfully load bootloader!");
+
+ upd->crc = 0x0000;
+ /* Prepare to download firmware and program flash, change buffer size */
+ rv = cps8200_write32(port, CPS8200_ADDR_BUF_SIZE,
+ ctx->cfg->block_size / 4);
+ if (rv) {
+ CPRINTS("Failed to change buffer size (%d)", rv);
+ return EC_ERROR_UNKNOWN;
+ }
+
+ return EC_SUCCESS;
}
-static int cps8100_update_write(struct pchg *ctx)
+/*
+ * This function writes the firmware block to the chip and returns only after
+ * the write is complete. The steps are:
+ * 1. Write firmware block to the chip buffer.
+ * 2. Send command to the chip.
+ * 3. The chip program the flash.
+ * 4. Calculate and update CRC.
+ */
+static int cps8200_update_write(struct pchg *ctx)
{
- return EC_ERROR_UNIMPLEMENTED;
+ int port = ctx->cfg->i2c_port;
+ int rv;
+ uint8_t id;
+ uint8_t *buf = ctx->update.data;
+ struct cps8x00_update *upd = &(ctx->update.driver_data.cps8200_update);
+
+ /* Write data to buffer */
+ if (cps8200_write_mem(port, CPS8200_ADDR_BUFFER0, buf,
+ ctx->update.size))
+ return EC_ERROR_UNKNOWN;
+ msleep(short_sleep_ms);
+
+ /* Write buffer to flash */
+ rv = cps8200_send_cmd(ctx, CMD_PGM_BUFFER0, &id);
+ if (rv)
+ return rv;
+
+ /* Check the program result */
+ rv = cps8200_wait_cmd_done(port, id);
+ if (rv) {
+ CPRINTS("Failed to write flash : %d", rv);
+ return EC_ERROR_UNKNOWN;
+ }
+
+ /* Calculate and update CRC */
+ upd->firmware_len += ctx->update.size;
+ upd->crc = cros_crc16(ctx->update.data, ctx->update.size, upd->crc);
+
+ return EC_SUCCESS;
}
-static int cps8100_update_close(struct pchg *ctx)
+/*
+ * This function checks firmware update result, power on and power off the chip
+ * if firmware update is successful. The steps are:
+ * 1. Send command to the chip to calculate the firmware CRC.
+ * 2. Read the CRC value from the chip and compare.
+ * 3. If CRC is correct, power off and power on the chip.
+ */
+static int cps8200_update_close(struct pchg *ctx)
{
- return EC_ERROR_UNIMPLEMENTED;
+ int port = ctx->cfg->i2c_port;
+ int rv;
+ uint32_t u32;
+ uint8_t id;
+ struct cps8x00_update *upd = &(ctx->update.driver_data.cps8200_update);
+ uint32_t len = upd->firmware_len;
+
+ /* Write firmware length */
+ rv = cps8200_write32(port, CPS8200_ADDR_BUFFER0, len);
+ if (rv)
+ return rv;
+ msleep(short_sleep_ms);
+
+ /* Check firmware CRC */
+ CPRINTS("Checking Firmware CRC...");
+ rv = cps8200_send_cmd(ctx, CMD_CACL_CRC_APP, &id);
+ if (rv)
+ return rv;
+
+ rv = cps8200_wait_cmd_done(port, id);
+ if (rv) {
+ CPRINTS("Command to calculate CRC timeout or failed: %d", rv);
+ return EC_ERROR_UNKNOWN;
+ }
+ msleep(100);
+
+ cps8200_read32(port, CPS8200_ADDR_BUFFER0, &u32);
+ if (upd->crc != (u32 & 0x0000ffff)) {
+ CPRINTS("crc = %04x, expect %04x", u32, upd->crc);
+ CPRINTS("CRC of firmware is wroing!");
+ return EC_ERROR_UNKNOWN;
+ }
+ CPRINTS("Firmware CRC is correct!");
+ CPRINTS("Successfully update the firmware");
+
+ rv = cps8200_send_cmd(ctx, CMD_PGM_WR_FLAG, &id);
+ if (rv)
+ return rv;
+
+ rv = cps8200_wait_cmd_done(port, id);
+ if (rv) {
+ CPRINTS("Command to program flash failed: %d", rv);
+ return EC_ERROR_UNKNOWN;
+ }
+
+ /*
+ * Due to the CPS8200 issue
+ * (https://issuetracker.google.com/issues/258093708), we can't simply
+ * reset CPS8200. CPS8200 needs to be powered off to completely reset
+ * its internal modules after completing the firmware update, and then
+ * power on after some delay. We need 50ms delay after power on to
+ * ensure there is enough delay before first I2C command
+ */
+
+ /* power off MCU */
+ board_pchg_power_on(PCHG_CTX_TO_PORT(ctx), 0);
+ msleep(short_sleep_ms);
+ /* power on MCU */
+ board_pchg_power_on(PCHG_CTX_TO_PORT(ctx), 1);
+ msleep(CPS8200_POWER_ON_DELAY_MS);
+ /* Update the information of firmware version */
+ cps8200_unlock(port);
+ rv = cps8x00_read_firmware_ver(ctx);
+ if (!rv)
+ CPRINTS("FW=0x%02x", ctx->fw_version);
+
+ return EC_SUCCESS;
}
const struct pchg_drv cps8100_drv = {
- .reset = cps8100_reset,
- .init = cps8100_init,
- .enable = cps8100_enable,
- .get_chip_info = cps8100_get_chip_info,
- .get_event = cps8100_get_event,
- .get_soc = cps8100_get_soc,
- .update_open = cps8100_update_open,
- .update_write = cps8100_update_write,
- .update_close = cps8100_update_close,
+ .reset = cps8x00_reset,
+ .init = cps8x00_init,
+ .enable = cps8x00_enable,
+ .get_chip_info = cps8x00_get_chip_info,
+ .get_event = cps8x00_get_event,
+ .get_soc = cps8x00_get_soc,
+};
+
+const struct pchg_drv cps8200_drv = {
+ .reset = cps8x00_reset,
+ .init = cps8x00_init,
+ .enable = cps8x00_enable,
+ .get_chip_info = cps8x00_get_chip_info,
+ .get_event = cps8x00_get_event,
+ .get_soc = cps8x00_get_soc,
+ .update_open = cps8200_update_open,
+ .update_write = cps8200_update_write,
+ .update_close = cps8200_update_close,
};
static void cps8100_dump(struct pchg *ctx)
@@ -555,8 +966,8 @@ static int cc_cps8100(int argc, const char **argv)
}
if (!strcasecmp(argv[2], "reset")) {
- cps8100_reset(ctx);
- cps8100_init(ctx);
+ cps8x00_reset(ctx);
+ cps8x00_init(ctx);
} else {
return EC_ERROR_PARAM3;
}
diff --git a/driver/wpc/cps8100.h b/driver/wpc/cps8100.h
index 0fb6fe0c4e..644ee37089 100644
--- a/driver/wpc/cps8100.h
+++ b/driver/wpc/cps8100.h
@@ -11,5 +11,6 @@
#include "peripheral_charger.h"
extern struct pchg_drv cps8100_drv;
+extern struct pchg_drv cps8200_drv;
#endif /* __CROS_EC_WPC_CPS8100_H */
diff --git a/driver/wpc/cps8200_bootloader.h b/driver/wpc/cps8200_bootloader.h
new file mode 100644
index 0000000000..32b0af4a23
--- /dev/null
+++ b/driver/wpc/cps8200_bootloader.h
@@ -0,0 +1,85 @@
+/* Copyright 2023 The ChromiumOS Authors
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+const uint32_t boot_hex[] = {
+ 0x20003D00, 0x20000149, 0x20000157, 0x20000159, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x2000015B,
+ 0x00000000, 0x00000000, 0x2000015D, 0x2000015F, 0x20000161, 0x20000161,
+ 0x20000161, 0x20000161, 0x20000161, 0x20000161, 0x20000161, 0x20000161,
+ 0x20000161, 0x20000161, 0x20000161, 0x20000161, 0x20000161, 0x20000161,
+ 0x20000161, 0x20000161, 0x20000161, 0x20000161, 0x20000161, 0x20000161,
+ 0x20000161, 0x20000161, 0x20000161, 0x20000161, 0x20000161, 0x20000161,
+ 0x20000161, 0x20000161, 0x20000161, 0x20000161, 0x20000161, 0x20000161,
+ 0xF802F000, 0xF830F000, 0xC830A00C, 0x18243808, 0x46A2182D, 0x46AB1E67,
+ 0x465D4654, 0xD10142AC, 0xF822F000, 0x3E0F467E, 0x46B6CC0F, 0x42332601,
+ 0x1AFBD000, 0x46AB46A2, 0x47184333, 0x0000061C, 0x0000062C, 0x24002300,
+ 0x26002500, 0xD3013A10, 0xD8FBC178, 0xD3000752, 0xD500C130, 0x4770600B,
+ 0xBD1FB51F, 0xBD10B510, 0xFAC3F000, 0xF7FF4611, 0xF000FFF7, 0xF000FA8C,
+ 0xB403FADB, 0xFFF2F7FF, 0xF000BC03, 0x0000FAE1, 0x490A4809, 0x480A6001,
+ 0x480A4780, 0xE7FE4700, 0xE7FEE7FE, 0xE7FEE7FE, 0x0000E7FE, 0x49074806,
+ 0x4B084A07, 0x00004770, 0x4001F030, 0xFFFFFFFF, 0x200006AB, 0x200000C1,
+ 0x20002060, 0x20003D00, 0x20002460, 0x20003900, 0x48FD49FE, 0x49FE63C8,
+ 0x60082000, 0x202049FC, 0x60083914, 0x210B48FB, 0x60416001, 0x60812100,
+ 0x48F760C1, 0x698130E8, 0x04522201, 0x61814391, 0x09096981, 0x1C490109,
+ 0x49F16181, 0x680A3168, 0x439A0583, 0x6981600A, 0x0112223F, 0x31C04391,
+ 0x69826181, 0x430A1399, 0x69826182, 0x431A1403, 0x4AE96182, 0x1C402000,
+ 0xD3FC4290, 0x38C048E3, 0x438A6B02, 0x6B026302, 0x01D209D2, 0x6302325F,
+ 0x430A6B02, 0x68026302, 0x6002438A, 0x09526802, 0x60020152, 0x430A6802,
+ 0x6A026002, 0x431A2301, 0x68426202, 0x6042438A, 0x09126842, 0x60420112,
+ 0x430A6842, 0x47706042, 0x210348D2, 0x4AD162C1, 0x32C02100, 0x61816391,
+ 0x61C22201, 0x48CB6102, 0x460863C1, 0x4ACB4770, 0x62516210, 0x20082163,
+ 0x43036AD3, 0x1E4962D3, 0x6AD1D2FA, 0x62D14301, 0x43016AD1, 0x6AD162D1,
+ 0x62D14381, 0x06806BD0, 0x2062D4FC, 0xD2FD1E40, 0x47702000, 0x48BA49BB,
+ 0x49BC63C8, 0x62C82003, 0x210148BA, 0x638130C0, 0x63C149BA, 0x47702000,
+ 0x4604B570, 0x4DB82000, 0xE00E4602, 0x021B5CA3, 0x23004058, 0xD5020406,
+ 0x40680040, 0x0040E000, 0xB2801C5B, 0xDBF52B08, 0x428A1C52, 0xBD70D3EE,
+ 0x260048A8, 0x463449A6, 0x4AA863C1, 0x63C661D6, 0xFFD0F7FF, 0x48AA49A9,
+ 0xFFB1F7FF, 0xFFA0F7FF, 0x680849A8, 0xD0FB2800, 0x600A2200, 0x600849A6,
+ 0x400121F0, 0x0F000700, 0x42A04615, 0x48A3D105, 0x22016800, 0x42900252,
+ 0x2040DD05, 0x48A04304, 0x24006004, 0x2010E7E4, 0x43204A9D, 0x4A916010,
+ 0x63D0488F, 0xD01C2990, 0x2910DC06, 0x2920D036, 0x2980D051, 0xE029D163,
+ 0xD02329A0, 0xD15E29B0, 0x68284D94, 0x03092101, 0xDD034288, 0x43C02000,
+ 0xE03C6028, 0x20016829, 0xF7FF0740, 0x6028FF99, 0x4982E052, 0x61C82001,
+ 0x62784F8B, 0x68294D89, 0x07002003, 0xFF8CF7FF, 0x62792100, 0x487B6028,
+ 0xE04161C1, 0x20004983, 0xE03D6008, 0xFF72F7FF, 0x487B4982, 0xFF53F7FF,
+ 0xE0124605, 0xFF6AF7FF, 0xE0082700, 0x00B9487B, 0x46305841, 0xFF47F7FF,
+ 0x1D364305, 0x48751C7F, 0x42876800, 0x4875DBF2, 0xF7FFE01B, 0x1C68FF2D,
+ 0x2D00D019, 0x4620D01C, 0x43082130, 0xF7FFE01A, 0x2700FF4D, 0x4870E008,
+ 0x584100B9, 0xF7FF4630, 0x4305FF2A, 0x1C7F1D36, 0x68004866, 0xDBF24287,
+ 0x60064869, 0x4964E7E1, 0x60082040, 0xE0062400, 0x43202020, 0x60084960,
+ 0x07241C64, 0x49530F24, 0x63C82000, 0x2100E760, 0x43C9485D, 0x63416301,
+ 0x63C16381, 0x62422201, 0x20004A4E, 0x62506210, 0x62D32303, 0x6313230E,
+ 0x4A4A6350, 0x635032C0, 0x63D06390, 0x38404845, 0x08926802, 0x1C520092,
+ 0x68026002, 0x439A230C, 0x60021D12, 0x23306802, 0x3210439A, 0x68026002,
+ 0x439A23C0, 0x60023240, 0x009B6802, 0x6002439A, 0x009B6802, 0x6002439A,
+ 0x009B6802, 0x6002439A, 0x009B6802, 0x6002439A, 0x009B6802, 0x6002439A,
+ 0x009B6802, 0x6002439A, 0x009B6802, 0x6002439A, 0x009B6802, 0x6002439A,
+ 0x009B6802, 0x6002439A, 0x009B6802, 0x6002439A, 0x009B6802, 0x0543439A,
+ 0x600218D2, 0x05C36802, 0x08920092, 0x600218D2, 0x08D26842, 0x1C5200D2,
+ 0x68426042, 0x439A2318, 0x60423208, 0x6101482B, 0x61416041, 0x47702000,
+ 0x4B18B570, 0x63D84816, 0x48274928, 0x4A286008, 0x60902000, 0x49136008,
+ 0x62883940, 0x39C04911, 0x62086248, 0x2201680C, 0x43940412, 0x680C600C,
+ 0x01640964, 0x600C3409, 0x4314680C, 0x684C600C, 0x604C4394, 0x0924684C,
+ 0x1D240124, 0x684C604C, 0x604C4314, 0x60084905, 0x22016048, 0xE029608A,
+ 0x00001250, 0x400140C0, 0x4000F018, 0x40012000, 0x000061A8, 0x00008888,
+ 0x00001021, 0x12345678, 0x000100F8, 0x200038F8, 0x200038F0, 0x200038F4,
+ 0x200038FC, 0x20002800, 0x4001F000, 0x5724E185, 0x20003000, 0x40010000,
+ 0x1ACCE551, 0x40008400, 0x40008000, 0x610A60CA, 0x62CA2203, 0x630A220E,
+ 0x63484923, 0x63C86388, 0x4C234922, 0x49236BCA, 0xD10A42A2, 0x22004C1F,
+ 0x19153C40, 0x682D1856, 0x60351D12, 0xDDF82A28, 0x2200E007, 0x1D121854,
+ 0x2A286020, 0x4A1ADDFA, 0x4A1861CA, 0x32802100, 0x1D09188C, 0x29D46020,
+ 0x63D8DDFA, 0x4B152100, 0x25014C15, 0x008A026D, 0x50A05098, 0x42A91C49,
+ 0x2000DBF9, 0x4911BD70, 0x60082040, 0x20004910, 0x49106008, 0x60082020,
+ 0x480F4910, 0xF7FF6008, 0xF7FFFF5F, 0xF7FFFD91, 0xF7FFFEEA, 0x0000FE39,
+ 0x400120C0, 0x000100C0, 0x7455874E, 0x4000F000, 0x00005030, 0x20002800,
+ 0x20003000, 0x200038F4, 0x200038F8, 0x200038FC, 0x12345678, 0x200038F0,
+ 0x47704770, 0x47704770, 0x46754770, 0xF824F000, 0x000546AE, 0x46534669,
+ 0x00C008C0, 0xB0184685, 0xF7FFB520, 0xBC60FD4B, 0x08492700, 0x260046B6,
+ 0xC5C0C5C0, 0xC5C0C5C0, 0xC5C0C5C0, 0xC5C0C5C0, 0x00493D40, 0x4770468D,
+ 0x4604B510, 0x46C046C0, 0xF7FF4620, 0xBD10FD1E, 0x47704800, 0x20002000,
+ 0x20184901, 0xE7FEBEAB, 0x00020026, 0x00004770, 0x20000728, 0x20002000,
+ 0x00001D00, 0x20000104
+};
+const size_t boot_hex_len = ARRAY_SIZE(boot_hex);
+BUILD_ASSERT(ARRAY_SIZE(boot_hex) == 458);