diff options
Diffstat (limited to 'driver/wpc')
-rw-r--r-- | driver/wpc/cps8100.c | 278 | ||||
-rw-r--r-- | driver/wpc/p9221.c | 808 | ||||
-rw-r--r-- | driver/wpc/p9221.h | 394 |
3 files changed, 396 insertions, 1084 deletions
diff --git a/driver/wpc/cps8100.c b/driver/wpc/cps8100.c index 78aa73fbfd..acfdc06a32 100644 --- a/driver/wpc/cps8100.c +++ b/driver/wpc/cps8100.c @@ -1,4 +1,4 @@ -/* Copyright 2022 The Chromium OS Authors. All rights reserved. +/* Copyright 2022 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -18,49 +18,61 @@ /* Print additional data */ #define CPS8100_DEBUG -#define CPUTS(outstr) cputs(CC_PCHG, outstr) -#define CPRINTS(fmt, args...) cprints(CC_PCHG, "CPS8100: " fmt, ##args) -#define CPRINTFP(fmt, args...) cprintf(CC_PCHG, "CPS8100: " fmt, ##args) -#define CPRINTF(fmt, args...) cprintf(CC_PCHG, fmt, ##args) +#define CPUTS(outstr) cputs(CC_PCHG, outstr) +#define CPRINTS(fmt, args...) cprints(CC_PCHG, "CPS8100: " fmt, ##args) +#define CPRINTFP(fmt, args...) cprintf(CC_PCHG, "CPS8100: " fmt, ##args) +#define CPRINTF(fmt, args...) cprintf(CC_PCHG, fmt, ##args) /* * Configuration */ -#define CPS8100_I2C_ADDR_H 0x31 -#define CPS8100_I2C_ADDR_L 0x30 +#define CPS8100_I2C_ADDR_H 0x31 +#define CPS8100_I2C_ADDR_L 0x30 +#define CPS8200_I2C_ADDR 0x30 /* High address registers (commands?) */ -#define CPS8100_REGH_PASSWORD 0xf500 -#define CPS8100_REGH_ACCESS_MODE 0xf505 -#define CPS8100_REGH_ADDRESS 0xf503 +#define CPS8100_REGH_PASSWORD 0xf500 +#define CPS8100_REGH_ACCESS_MODE 0xf505 +#define CPS8100_REGH_ADDRESS 0xf503 -#define CPS8100_ACCESS_MODE_8 0x00 -#define CPS8100_ACCESS_MODE_16 0x01 -#define CPS8100_ACCESS_MODE_32 0x02 +#define CPS8100_ACCESS_MODE_8 0x00 +#define CPS8100_ACCESS_MODE_16 0x01 +#define CPS8100_ACCESS_MODE_32 0x02 +#define CPS8100_PASSWORD 0x19e5 +#define CPS8100_CHIPID 0x8100 +#define CPS8200_CHIPID 0x8200 + +#define CPS8200_I2C_ENABLE 0x0000000E +#define CPS8200_PASSWORD 0x00001250 /* Registers */ -#define CPS8100_REG_IC_INFO 0x20000000 -#define CPS8100_REG_FW_INFO 0x20000004 -#define CPS8100_REG_FUNC_EN 0x2000003c -#define CPS8100_REG_ALERT_INFO 0x20000158 -#define CPS8100_REG_INT_ENABLE 0x20000160 -#define CPS8100_REG_INT_FLAG 0x20000164 - -#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 CPS8100_REG_IC_INFO 0x20000000 +#define CPS8100_REG_FW_INFO 0x20000004 +#define CPS8100_REG_FUNC_EN 0x2000003c +#define CPS8100_REG_ALERT_INFO 0x20000158 +#define CPS8100_REG_INT_ENABLE 0x20000160 +#define CPS8100_REG_INT_FLAG 0x20000164 + +#define CPS8200_REG_I2C_ENABLE 0xFFFFFF00 +#define CPS8200_REG_PASSWORD 0x400140FC + +#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) /* Status flags in ALERT_INFO register */ -#define CPS8100_STATUS_FOD BIT(0) -#define CPS8100_STATUS_OCP BIT(1) -#define CPS8100_STATUS_OVP BIT(2) -#define CPS8100_STATUS_OTP BIT(3) -#define CPS8100_STATUS_UVP BIT(16) +#define CPS8100_STATUS_FOD BIT(0) +#define CPS8100_STATUS_OCP BIT(1) +#define CPS8100_STATUS_OVP BIT(2) +#define CPS8100_STATUS_OTP BIT(3) +#define CPS8100_STATUS_UVP BIT(16) /* Buffer size for i2c read & write */ -#define CPS8100_MESSAGE_BUFFER_SIZE 0x20 +#define CPS8100_MESSAGE_BUFFER_SIZE 0x20 + +static uint32_t chip_id; /* TODO: Check datasheet how to wake up and how long it takes to wake up. */ static const int cps8100_wake_up_delay_ms = 10; @@ -81,22 +93,15 @@ struct cps8100_msg { uint8_t data[2]; } __packed; +static int (*cps8x00_read32)(int port, uint32_t reg, uint32_t *val); + /* This driver isn't compatible with big endian. */ -BUILD_ASSERT(__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__); - -static const char * const cps8100_func_names[] = { - [0] = "DPL", - [1] = "OPP", - [2] = "OTP", - [3] = "OVPK", - [4] = "OCP", - [5] = "UVP", - [6] = "OVP", - [7] = "FOD", - [8] = "SAMSUNG", - [9] = "APPLE", - [10] = "EPP", - [11] = "HUAWEI", +BUILD_ASSERT(__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__); + +static const char *const cps8100_func_names[] = { + [0] = "DPL", [1] = "OPP", [2] = "OTP", [3] = "OVPK", + [4] = "OCP", [5] = "UVP", [6] = "OVP", [7] = "FOD", + [8] = "SAMSUNG", [9] = "APPLE", [10] = "EPP", [11] = "HUAWEI", [12] = "CPS", }; @@ -114,7 +119,7 @@ enum cps8100_irq_type { CPS8100_IRQ_TYPE_COUNT }; -static const char * const cps8100_irq_type_names[] = { +static const char *const cps8100_irq_type_names[] = { [CPS8100_IRQ_TYPE_FOD] = "FOD", [CPS8100_IRQ_TYPE_OCP] = "OCP", [CPS8100_IRQ_TYPE_OVP] = "OVP", @@ -127,7 +132,7 @@ static const char * const cps8100_irq_type_names[] = { [CPS8100_IRQ_TYPE_RESET] = "RESET", }; -static const char * const cps8100_profile_names[] = { +static const char *const cps8100_profile_names[] = { [0] = "NONE", [1] = "BPP", [2] = "EPP", @@ -211,14 +216,54 @@ static int cps8100_i2c_write(int port, int addr, const uint8_t *buf, size_t len) static int cps8100_set_unlock(int port) { - uint8_t buf[4]; + const uint8_t cps8100_unlock_cmd[] = { + /* Password register address */ + (CPS8100_REGH_PASSWORD >> 8) & 0xff, + (CPS8100_REGH_PASSWORD >> 0) & 0xff, + /* Password */ + (CPS8100_PASSWORD >> 0) & 0xff, + (CPS8100_PASSWORD >> 8) & 0xff, + }; + + return cps8100_i2c_write(port, CPS8100_I2C_ADDR_H, cps8100_unlock_cmd, + 4); +} - buf[0] = 0xf5; - buf[1] = 0x00; /* Password register address */ - buf[2] = 0xe5; - buf[3] = 0x19; /* Password */ +static int cps8200_set_unlock(int port) +{ + const uint8_t cps8200_unlock_cmd[] = { + /* Password register addr */ + (CPS8200_REG_PASSWORD >> 24) & 0xff, + (CPS8200_REG_PASSWORD >> 16) & 0xff, + (CPS8200_REG_PASSWORD >> 8) & 0xff, + (CPS8200_REG_PASSWORD >> 0) & 0xff, + /* Password */ + (CPS8200_PASSWORD >> 0) & 0xff, + (CPS8200_PASSWORD >> 8) & 0xff, + (CPS8200_PASSWORD >> 16) & 0xff, + (CPS8200_PASSWORD >> 24) & 0xff, + }; + + return cps8100_i2c_write(port, CPS8200_I2C_ADDR, cps8200_unlock_cmd, 8); +} - return cps8100_i2c_write(port, CPS8100_I2C_ADDR_H, buf, 4); +static int cps8200_i2c_enable(int port) +{ + const uint8_t cps8200_i2c_enable_cmd[] = { + /* addr */ + (CPS8200_REG_I2C_ENABLE >> 24) & 0xff, + (CPS8200_REG_I2C_ENABLE >> 16) & 0xff, + (CPS8200_REG_I2C_ENABLE >> 8) & 0xff, + (CPS8200_REG_I2C_ENABLE >> 0) & 0xff, + /* data */ + (CPS8200_I2C_ENABLE >> 0) & 0xff, + (CPS8200_I2C_ENABLE >> 8) & 0xff, + (CPS8200_I2C_ENABLE >> 16) & 0xff, + (CPS8200_I2C_ENABLE >> 24) & 0xff, + }; + + return cps8100_i2c_write(port, CPS8200_I2C_ADDR, cps8200_i2c_enable_cmd, + 8); } static int cps8100_set_write_mode(int port, uint8_t mode) @@ -249,17 +294,44 @@ static int cps8100_read32(int port, uint32_t reg, uint32_t *val) { uint8_t buf[CPS8100_MESSAGE_BUFFER_SIZE]; - if (cps8100_set_unlock(port) || - cps8100_set_write_mode(port, CPS8100_ACCESS_MODE_32) || - cps8100_set_high_address(port, reg)) + if (cps8100_set_high_address(port, reg)) return EC_ERROR_UNKNOWN; /* Set low 16 bits of register address and read a byte. */ buf[0] = (reg >> 8) & 0xff; buf[1] = (reg >> 0) & 0xff; - return i2c_xfer(port, CPS8100_I2C_ADDR_L, buf, 2, - (void *)val, sizeof(*val)); + return i2c_xfer(port, CPS8100_I2C_ADDR_L, buf, 2, (void *)val, + sizeof(*val)); +} + +static int cps8200_read32(int port, uint32_t reg, uint32_t *val) +{ + uint8_t buf[4]; + + buf[0] = (reg >> 24) & 0xff; + buf[1] = (reg >> 16) & 0xff; + buf[2] = (reg >> 8) & 0xff; + buf[3] = (reg >> 0) & 0xff; + + return i2c_xfer(port, CPS8200_I2C_ADDR, buf, 4, (void *)val, + sizeof(*val)); +} + +static int cps8100_unlock(int port) +{ + int rv; + + rv = cps8100_set_unlock(port); + return rv ? rv : cps8100_set_write_mode(port, CPS8100_ACCESS_MODE_32); +} + +static int cps8200_unlock(int port) +{ + int rv; + + rv = cps8200_i2c_enable(port); + return rv ? rv : cps8200_set_unlock(port); } static int cps8100_reset(struct pchg *ctx) @@ -274,19 +346,15 @@ static int cps8100_reset(struct pchg *ctx) static int cps8100_init(struct pchg *ctx) { - uint32_t u32; int port = ctx->cfg->i2c_port; - int rv; - rv = cps8100_read32(port, CPS8100_REG_IC_INFO, &u32); - if (!rv) - CPRINTS("IC=0x%08x", u32); - - rv = cps8100_read32(port, CPS8100_REG_FW_INFO, &u32); - if (!rv) - CPRINTS("FW=0x%08x", u32); - - return EC_SUCCESS; + /* Enable I2C, unlock and set mode */; + if (chip_id == CPS8100_CHIPID) + return cps8100_unlock(port); + else if (chip_id == CPS8200_CHIPID) + return cps8200_unlock(port); + else + return EC_ERROR_UNKNOWN; } static int cps8100_enable(struct pchg *ctx, bool enable) @@ -298,7 +366,7 @@ static int cps8100_get_alert_info(struct pchg *ctx, uint32_t *reg) { int rv; - rv = cps8100_read32(ctx->cfg->i2c_port, CPS8100_REG_ALERT_INFO, reg); + rv = cps8x00_read32(ctx->cfg->i2c_port, CPS8100_REG_ALERT_INFO, reg); if (rv) { CPRINTS("Failed to get alert info (%d)", rv); return rv; @@ -307,6 +375,63 @@ static int cps8100_get_alert_info(struct pchg *ctx, uint32_t *reg) return EC_SUCCESS; } +static int cps8100_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); + return cps8100_unlock(port); + } else if (chip_id == CPS8200_CHIPID) { + msleep(50); + return cps8200_unlock(port); + } + + /* not probed yet, need to unlock blindly first. */ + msleep(120); + if (!cps8100_unlock(port)) + rv = cps8100_read32(port, CPS8100_REG_IC_INFO, &u32); + else if (!cps8200_unlock(port)) + rv = cps8200_read32(port, CPS8100_REG_IC_INFO, &u32); + + if (rv) { + CPRINTS("Failed to read IC info!"); + return rv; + } + + /* Probe */; + CPRINTS("IC=0x%08x", u32); + if ((u32 & 0xffff) == CPS8100_CHIPID) { + cps8x00_read32 = cps8100_read32; + chip_id = CPS8100_CHIPID; + } else if ((u32 & 0xffff) == CPS8200_CHIPID) { + cps8x00_read32 = cps8200_read32; + chip_id = CPS8200_CHIPID; + } else { + CPRINTS("Unknown chip!"); + 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; + } + + return EC_SUCCESS; +} + static void cps8100_print_alert_info(uint32_t reg) { cps8100_print_irq_type_names("IRQ_TYPE: ", reg); @@ -315,7 +440,8 @@ static void cps8100_print_alert_info(uint32_t reg) CPRINTFP("Profile: %s\n", cps8100_profile_names[CPS8100_STATUS_PROFILE(reg)]); CPRINTFP("%sCharging\n", CPS8100_STATUS_CHARGE(reg) ? "" : "Not "); - CPRINTFP("Device %sPresent\n", CPS8100_STATUS_DEVICE(reg) ? "":"Not "); + CPRINTFP("Device %sPresent\n", + CPS8100_STATUS_DEVICE(reg) ? "" : "Not "); CPRINTFP("Battery: %d%%\n", CPS8100_STATUS_BATTERY(reg)); } @@ -386,6 +512,7 @@ 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, @@ -398,7 +525,7 @@ static void cps8100_dump(struct pchg *ctx) uint32_t val; int rv; - rv = cps8100_read32(ctx->cfg->i2c_port, CPS8100_REG_FUNC_EN, &val); + rv = cps8x00_read32(ctx->cfg->i2c_port, CPS8100_REG_FUNC_EN, &val); if (rv == EC_SUCCESS) cps8100_print_func_names("FEATURES: ", val); @@ -407,7 +534,7 @@ static void cps8100_dump(struct pchg *ctx) cps8100_print_alert_info(val); } -static int cc_cps8100(int argc, char **argv) +static int cc_cps8100(int argc, const char **argv) { struct pchg *ctx; char *end; @@ -436,6 +563,5 @@ static int cc_cps8100(int argc, char **argv) return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(cps8100, cc_cps8100, - "<port> [reset]", +DECLARE_CONSOLE_COMMAND(cps8100, cc_cps8100, "<port> [reset]", "Print status of or reset CPS8100"); diff --git a/driver/wpc/p9221.c b/driver/wpc/p9221.c deleted file mode 100644 index 973d991240..0000000000 --- a/driver/wpc/p9221.c +++ /dev/null @@ -1,808 +0,0 @@ -/* Copyright 2019 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. - */ - -/* - * IDT P9221-R7 Wireless Power Receiver driver. - */ - -#include "p9221.h" -#include "charge_manager.h" -#include "chipset.h" -#include "common.h" -#include "console.h" -#include "gpio.h" -#include "hooks.h" -#include "power.h" -#include "tcpm/tcpm.h" -#include "timer.h" -#include "usb_charge.h" -#include "usb_pd.h" -#include "util.h" -#include <stdbool.h> -#include "printf.h" - -#define CPRINTS(format, args...) cprints(CC_USBPD, "WPC " format, ## args) - -#define P9221_TX_TIMEOUT_MS (20 * 1000*1000) -#define P9221_DCIN_TIMEOUT_MS (2 * 1000*1000) -#define P9221_VRECT_TIMEOUT_MS (2 * 1000*1000) -#define P9221_NOTIFIER_DELAY_MS (80*1000) -#define P9221R7_ILIM_MAX_UA (1600 * 1000) -#define P9221R7_OVER_CHECK_NUM 3 - -#define OVC_LIMIT 1 -#define OVC_THRESHOLD 1400000 -#define OVC_BACKOFF_LIMIT 900000 -#define OVC_BACKOFF_AMOUNT 100000 - -/* P9221 parameters */ -static struct wpc_charger_info p9221_charger_info = { - .online = false, - .i2c_port = I2C_PORT_WPC, - .pp_buf_valid = false, -}; - -static struct wpc_charger_info *wpc = &p9221_charger_info; - -static void p9221_set_offline(void); - -static const uint32_t p9221_ov_set_lut[] = { - 17000000, 20000000, 15000000, 13000000, - 11000000, 11000000, 11000000, 11000000 -}; - -static int p9221_reg_is_8_bit(uint16_t reg) -{ - switch (reg) { - case P9221_CHIP_REVISION_REG: - case P9221R7_VOUT_SET_REG: - case P9221R7_ILIM_SET_REG: - case P9221R7_CHARGE_STAT_REG: - case P9221R7_EPT_REG: - case P9221R7_SYSTEM_MODE_REG: - case P9221R7_COM_CHAN_RESET_REG: - case P9221R7_COM_CHAN_SEND_SIZE_REG: - case P9221R7_COM_CHAN_SEND_IDX_REG: - case P9221R7_COM_CHAN_RECV_SIZE_REG: - case P9221R7_COM_CHAN_RECV_IDX_REG: - case P9221R7_DEBUG_REG: - case P9221R7_EPP_Q_FACTOR_REG: - case P9221R7_EPP_TX_GUARANTEED_POWER_REG: - case P9221R7_EPP_TX_POTENTIAL_POWER_REG: - case P9221R7_EPP_TX_CAPABILITY_FLAGS_REG: - case P9221R7_EPP_RENEGOTIATION_REG: - case P9221R7_EPP_CUR_RPP_HEADER_REG: - case P9221R7_EPP_CUR_NEGOTIATED_POWER_REG: - case P9221R7_EPP_CUR_MAXIMUM_POWER_REG: - case P9221R7_EPP_CUR_FSK_MODULATION_REG: - case P9221R7_EPP_REQ_RPP_HEADER_REG: - case P9221R7_EPP_REQ_NEGOTIATED_POWER_REG: - case P9221R7_EPP_REQ_MAXIMUM_POWER_REG: - case P9221R7_EPP_REQ_FSK_MODULATION_REG: - case P9221R7_VRECT_TARGET_REG: - case P9221R7_VRECT_KNEE_REG: - case P9221R7_FOD_SECTION_REG: - case P9221R7_VRECT_ADJ_REG: - case P9221R7_ALIGN_X_ADC_REG: - case P9221R7_ALIGN_Y_ADC_REG: - case P9221R7_ASK_MODULATION_DEPTH_REG: - case P9221R7_OVSET_REG: - case P9221R7_EPP_TX_SPEC_REV_REG: - return true; - default: - return false; - } -} - -static int p9221_read8(uint16_t reg, int *val) -{ - return i2c_read_offset16(wpc->i2c_port, P9221_R7_ADDR_FLAGS, - reg, val, 1); -} - -static int p9221_write8(uint16_t reg, int val) -{ - return i2c_write_offset16(wpc->i2c_port, P9221_R7_ADDR_FLAGS, - reg, val, 1); -} - -static int p9221_read16(uint16_t reg, int *val) -{ - return i2c_read_offset16(wpc->i2c_port, P9221_R7_ADDR_FLAGS, - reg, val, 2); -} - -static int p9221_write16(uint16_t reg, int val) -{ - return i2c_write_offset16(wpc->i2c_port, P9221_R7_ADDR_FLAGS, - reg, val, 2); -} - -static int p9221_block_read(uint16_t reg, uint8_t *data, int len) -{ - return i2c_read_offset16_block(wpc->i2c_port, P9221_R7_ADDR_FLAGS, - reg, data, len); -} - -static int p9221_block_write(uint16_t reg, uint8_t *data, int len) -{ - return i2c_write_offset16_block(wpc->i2c_port, P9221_R7_ADDR_FLAGS, - reg, data, len); -} - -static int p9221_set_cmd_reg(uint8_t cmd) -{ - int cur_cmd; - int retry; - int ret; - - for (retry = 0; retry < P9221_COM_CHAN_RETRIES; retry++) { - ret = p9221_read8(P9221_COM_REG, &cur_cmd); - if (ret == EC_SUCCESS && cur_cmd == 0) - break; - msleep(25); - } - - if (retry >= P9221_COM_CHAN_RETRIES) { - CPRINTS("Failed to wait for cmd free %02x", cur_cmd); - return EC_ERROR_TIMEOUT; - } - - ret = p9221_write8(P9221_COM_REG, cmd); - if (ret) - CPRINTS("Failed to set cmd reg %02x: %d", cmd, ret); - - return ret; -} - -/* Convert a register value to uV, Hz, or uA */ -static int p9221_convert_reg_r7(uint16_t reg, uint16_t raw_data, uint32_t *val) -{ - switch (reg) { - case P9221R7_ALIGN_X_ADC_REG: /* raw */ - case P9221R7_ALIGN_Y_ADC_REG: /* raw */ - *val = raw_data; - break; - case P9221R7_VOUT_ADC_REG: /* 12-bit ADC raw */ - case P9221R7_IOUT_ADC_REG: /* 12-bit ADC raw */ - case P9221R7_DIE_TEMP_ADC_REG: /* 12-bit ADC raw */ - case P9221R7_EXT_TEMP_REG: - *val = raw_data & 0xFFF; - break; - case P9221R7_VOUT_SET_REG: /* 0.1V -> uV */ - *val = raw_data * 100 * 1000; - break; - case P9221R7_IOUT_REG: /* mA -> uA */ - case P9221R7_VRECT_REG: /* mV -> uV */ - case P9221R7_VOUT_REG: /* mV -> uV */ - case P9221R7_OP_FREQ_REG: /* kHz -> Hz */ - case P9221R7_TX_PINGFREQ_REG: /* kHz -> Hz */ - *val = raw_data * 1000; - break; - case P9221R7_ILIM_SET_REG: /* 100mA -> uA, 200mA offset */ - *val = ((raw_data * 100) + 200) * 1000; - break; - case P9221R7_OVSET_REG: /* uV */ - raw_data &= P9221R7_OVSET_MASK; - *val = p9221_ov_set_lut[raw_data]; - break; - default: - return -2; - } - - return 0; -} - -static int p9221_reg_read_converted(uint16_t reg, uint32_t *val) -{ - int ret; - int data; - - if (p9221_reg_is_8_bit(reg)) - ret = p9221_read8(reg, &data); - else - ret = p9221_read16(reg, &data); - - if (ret) - return ret; - - return p9221_convert_reg_r7(reg, data, val); -} - -static int p9221_is_online(void) -{ - int chip_id; - - if (p9221_read16(P9221_CHIP_ID_REG, &chip_id) - || chip_id != P9221_CHIP_ID) - return false; - else - return true; -} - -int wpc_chip_is_online(void) -{ - return p9221_is_online(); -} - - -void p9221_interrupt(enum gpio_signal signal) -{ - task_wake(TASK_ID_WPC); -} - -static int p9221r7_clear_interrupts(uint16_t mask) -{ - int ret; - - ret = p9221_write16(P9221R7_INT_CLEAR_REG, mask); - if (ret) { - CPRINTS("Failed to clear INT reg: %d", ret); - return ret; - } - - ret = p9221_set_cmd_reg(P9221_COM_CLEAR_INT_MASK); - if (ret) - CPRINTS("Failed to reset INT: %d", ret); - - return ret; -} - -/* - * Enable interrupts on the P9221 R7, note we don't really need to disable - * interrupts since when the device goes out of field, the P9221 is reset. - */ -static int p9221_enable_interrupts_r7(void) -{ - uint16_t mask = 0; - int ret; - - CPRINTS("Enable interrupts"); - - mask = P9221R7_STAT_LIMIT_MASK | P9221R7_STAT_CC_MASK - | P9221_STAT_VRECT; - - p9221r7_clear_interrupts(mask); - - ret = p9221_write8(P9221_INT_ENABLE_REG, mask); - if (ret) - CPRINTS("Failed to enable INTs: %d", ret); - return ret; -} - -static int p9221_send_csp(uint8_t status) -{ - int ret; - - CPRINTS("Send CSP=%d", status); - mutex_lock(&wpc->cmd_lock); - - ret = p9221_write8(P9221R7_CHARGE_STAT_REG, status); - if (ret == EC_SUCCESS) - ret = p9221_set_cmd_reg(P9221R7_COM_SENDCSP); - - mutex_unlock(&wpc->cmd_lock); - return ret; -} - -static int p9221_send_eop(uint8_t reason) -{ - int rv; - - CPRINTS("Send EOP reason=%d", reason); - mutex_lock(&wpc->cmd_lock); - - rv = p9221_write8(P9221R7_EPT_REG, reason); - if (rv == EC_SUCCESS) - rv = p9221_set_cmd_reg(P9221R7_COM_SENDEPT); - - mutex_unlock(&wpc->cmd_lock); - return rv; -} - -static void print_current_samples(uint32_t *iout_val, int count) -{ - int i; - char temp[P9221R7_OVER_CHECK_NUM * 9 + 1] = { 0 }; - - for (i = 0; i < count ; i++) - snprintf(temp + i * 9, sizeof(temp) - i * 9, - "%08x ", iout_val[i]); - CPRINTS("OVER IOUT_SAMPLES: %s", temp); -} - - -/* - * Number of times to poll the status to see if the current limit condition - * was transient or not. - */ -static void p9221_limit_handler_r7(uint16_t orign_irq_src) -{ - uint8_t reason; - int i; - int ret; - int ovc_count = 0; - uint32_t iout_val[P9221R7_OVER_CHECK_NUM] = { 0 }; - int irq_src = (int)orign_irq_src; - - CPRINTS("OVER INT: %02x", irq_src); - - if (irq_src & P9221R7_STAT_OVV) { - reason = P9221_EOP_OVER_VOLT; - goto send_eop; - } - - if (irq_src & P9221R7_STAT_OVT) { - reason = P9221_EOP_OVER_TEMP; - goto send_eop; - } - - if ((irq_src & P9221R7_STAT_UV) && !(irq_src & P9221R7_STAT_OVC)) - return; - - reason = P9221_EOP_OVER_CURRENT; - for (i = 0; i < P9221R7_OVER_CHECK_NUM; i++) { - ret = p9221r7_clear_interrupts( - irq_src & P9221R7_STAT_LIMIT_MASK); - msleep(50); - if (ret) - continue; - - ret = p9221_reg_read_converted(P9221R7_IOUT_REG, &iout_val[i]); - if (ret) { - CPRINTS("Failed to read IOUT[%d]: %d", i, ret); - continue; - } else if (iout_val[i] > OVC_THRESHOLD) { - ovc_count++; - } - - ret = p9221_read16(P9221_STATUS_REG, &irq_src); - if (ret) { - CPRINTS("Failed to read status: %d", ret); - continue; - } - - if ((irq_src & P9221R7_STAT_OVC) == 0) { - print_current_samples(iout_val, i + 1); - CPRINTS("OVER condition %04x cleared after %d tries", - irq_src, i); - return; - } - - CPRINTS("OVER status is still %04x, retry", irq_src); - } - - if (ovc_count < OVC_LIMIT) { - print_current_samples(iout_val, P9221R7_OVER_CHECK_NUM); - CPRINTS("ovc_threshold=%d, ovc_count=%d, ovc_limit=%d", - OVC_THRESHOLD, ovc_count, OVC_LIMIT); - return; - } - -send_eop: - CPRINTS("OVER is %04x, sending EOP %d", irq_src, reason); - - ret = p9221_send_eop(reason); - if (ret) - CPRINTS("Failed to send EOP %d: %d", reason, ret); -} - -static void p9221_abort_transfers(void) -{ - wpc->tx_busy = false; - wpc->tx_done = true; - wpc->rx_done = true; - wpc->rx_len = 0; -} - -/* Handler for r7 and R7 chips */ -static void p9221r7_irq_handler(uint16_t irq_src) -{ - int res; - - if (irq_src & P9221R7_STAT_LIMIT_MASK) - p9221_limit_handler_r7(irq_src); - - /* Receive complete */ - if (irq_src & P9221R7_STAT_CCDATARCVD) { - int rxlen = 0; - - res = p9221_read8(P9221R7_COM_CHAN_RECV_SIZE_REG, &rxlen); - if (res) - CPRINTS("Failed to read len: %d", res); - - if (rxlen) { - res = p9221_block_read(P9221R7_DATA_RECV_BUF_START, - wpc->rx_buf, rxlen); - if (res) { - CPRINTS("Failed to read CC data: %d", res); - rxlen = 0; - } - - wpc->rx_len = rxlen; - wpc->rx_done = true; - } - } - - /* Send complete */ - if (irq_src & P9221R7_STAT_CCSENDBUSY) { - wpc->tx_busy = false; - wpc->tx_done = true; - } - - /* Proprietary packet */ - if (irq_src & P9221R7_STAT_PPRCVD) { - res = p9221_block_read(P9221R7_DATA_RECV_BUF_START, - wpc->pp_buf, sizeof(wpc->pp_buf)); - if (res) { - CPRINTS("Failed to read PP: %d", res); - wpc->pp_buf_valid = false; - return; - } - - /* We only care about PP which come with 0x4F header */ - wpc->pp_buf_valid = (wpc->pp_buf[0] == 0x4F); - - hexdump(wpc->pp_buf, sizeof(wpc->pp_buf)); - } - - /* CC Reset complete */ - if (irq_src & P9221R7_STAT_CCRESET) - p9221_abort_transfers(); -} - -static int p9221_is_epp(void) -{ - int ret, reg; - uint32_t vout_uv; - - if (p9221_read8(P9221R7_SYSTEM_MODE_REG, ®) == EC_SUCCESS) - return reg & P9221R7_SYSTEM_MODE_EXTENDED_MASK; - - /* Check based on power supply voltage */ - ret = p9221_reg_read_converted(P9221R7_VOUT_ADC_REG, &vout_uv); - if (ret) { - CPRINTS("Failed to read VOUT_ADC: %d", ret); - return false; - } - - CPRINTS("Voltage is %duV", vout_uv); - if (vout_uv > P9221_EPP_THRESHOLD_UV) - return true; - - return false; -} - -static void p9221_config_fod(void) -{ - - int epp; - uint8_t *fod; - int fod_len; - int ret; - int retries = 3; - - CPRINTS("Config FOD"); - - epp = p9221_is_epp(); - fod_len = epp ? board_get_epp_fod(&fod) : board_get_fod(&fod); - if (!fod_len || !fod) { - CPRINTS("FOD data not found"); - return; - } - - while (retries) { - uint8_t fod_read[fod_len]; - - CPRINTS("Writing %s FOD (n=%d try=%d)", - epp ? "EPP" : "BPP", fod_len, retries); - - ret = p9221_block_write(P9221R7_FOD_REG, fod, fod_len); - if (ret) - goto no_fod; - - /* Verify the FOD has been written properly */ - ret = p9221_block_read(P9221R7_FOD_REG, fod_read, fod_len); - if (ret) - goto no_fod; - - if (memcmp(fod, fod_read, fod_len) == 0) - return; - - hexdump(fod_read, fod_len); - - retries--; - msleep(100); - } - -no_fod: - CPRINTS("Failed to set FOD. retries:%d ret:%d", retries, ret); -} - -static void p9221_set_online(void) -{ - int ret; - - CPRINTS("Set online"); - - wpc->online = true; - - wpc->tx_busy = false; - wpc->tx_done = true; - wpc->rx_done = false; - wpc->charge_supplier = CHARGE_SUPPLIER_WPC_BPP; - - ret = p9221_enable_interrupts_r7(); - if (ret) - CPRINTS("Failed to enable INT: %d", ret); - - /* NOTE: depends on _is_epp() which is not valid until DC_IN */ - p9221_config_fod(); -} - -static void p9221_vbus_check_timeout(void) -{ - CPRINTS("Timeout VBUS, online=%d", wpc->online); - if (wpc->online) - p9221_set_offline(); - -} -DECLARE_DEFERRED(p9221_vbus_check_timeout); - -static void p9221_set_offline(void) -{ - CPRINTS("Set offline"); - - wpc->online = false; - /* Reset PP buf so we can get a new serial number next time around */ - wpc->pp_buf_valid = false; - - p9221_abort_transfers(); - - hook_call_deferred(&p9221_vbus_check_timeout_data, -1); -} - -/* P9221_NOTIFIER_DELAY_MS from VRECTON */ -static int p9221_notifier_check_det(void) -{ - if (wpc->online) - goto done; - - /* send out a FOD but is_epp() is still invalid */ - p9221_set_online(); - - /* Give the vbus 2 seconds to come up. */ - CPRINTS("Waiting VBUS"); - hook_call_deferred(&p9221_vbus_check_timeout_data, -1); - hook_call_deferred(&p9221_vbus_check_timeout_data, - P9221_DCIN_TIMEOUT_MS); - -done: - wpc->p9221_check_det = false; - return 0; -} - -static int p9221_get_charge_supplier(void) -{ - if (!wpc->online) - return EC_ERROR_UNKNOWN; - - if (p9221_is_epp()) { - uint32_t tx_id; - int txmf_id; - int ret; - - wpc->charge_supplier = CHARGE_SUPPLIER_WPC_EPP; - - ret = p9221_read16(P9221R7_EPP_TX_MFG_CODE_REG, &txmf_id); - if (ret || txmf_id != P9221_GPP_TX_MF_ID) - return ret; - - ret = p9221_block_read(P9221R7_PROP_TX_ID_REG, - (uint8_t *) &tx_id, - P9221R7_PROP_TX_ID_SIZE); - if (ret) - return ret; - - if (tx_id & P9221R7_PROP_TX_ID_GPP_MASK) - wpc->charge_supplier = CHARGE_SUPPLIER_WPC_GPP; - - CPRINTS("txmf_id=0x%04x tx_id=0x%08x supplier=%d", - txmf_id, tx_id, wpc->charge_supplier); - } else { - wpc->charge_supplier = CHARGE_SUPPLIER_WPC_BPP; - CPRINTS("supplier=%d", wpc->charge_supplier); - } - - return EC_SUCCESS; -} - -static int p9221_get_icl(int charge_supplier) -{ - switch (charge_supplier) { - case CHARGE_SUPPLIER_WPC_EPP: - case CHARGE_SUPPLIER_WPC_GPP: - return P9221_DC_ICL_EPP_MA; - case CHARGE_SUPPLIER_WPC_BPP: - default: - return P9221_DC_ICL_BPP_MA; - } -} - -static int p9221_get_ivl(int charge_supplier) -{ - switch (charge_supplier) { - case CHARGE_SUPPLIER_WPC_EPP: - case CHARGE_SUPPLIER_WPC_GPP: - return P9221_DC_IVL_EPP_MV; - case CHARGE_SUPPLIER_WPC_BPP: - default: - return P9221_DC_IVL_BPP_MV; - } -} - -static void p9221_update_charger(int type, struct charge_port_info *chg) -{ - if (!chg) - charge_manager_update_dualrole(0, CAP_UNKNOWN); - else - charge_manager_update_dualrole(0, CAP_DEDICATED); - - charge_manager_update_charge(type, 0, chg); -} - -static int p9221_reg_write_converted_r7(uint16_t reg, uint32_t val) -{ - int ret = 0; - uint16_t data; - int i; - /* Do the appropriate conversion */ - switch (reg) { - case P9221R7_ILIM_SET_REG: - /* uA -> 0.1A, offset 0.2A */ - if ((val < 200000) || (val > 1600000)) - return -EC_ERROR_INVAL; - data = (val / (100 * 1000)) - 2; - break; - case P9221R7_VOUT_SET_REG: - /* uV -> 0.1V */ - val /= 1000; - if (val < 3500 || val > 9000) - return -EC_ERROR_INVAL; - data = val / 100; - break; - case P9221R7_OVSET_REG: - /* uV */ - for (i = 0; i < ARRAY_SIZE(p9221_ov_set_lut); i++) { - if (val == p9221_ov_set_lut[i]) - break; - } - if (i == ARRAY_SIZE(p9221_ov_set_lut)) - return -EC_ERROR_INVAL; - data = i; - break; - default: - return -EC_ERROR_INVAL; - } - if (p9221_reg_is_8_bit(reg)) - ret = p9221_write8(reg, data); - else - ret = p9221_write16(reg, data); - return ret; -} - -static int p9221_set_dc_icl(void) -{ - /* Increase the IOUT limit */ - if (p9221_reg_write_converted_r7(P9221R7_ILIM_SET_REG, - P9221R7_ILIM_MAX_UA)) - CPRINTS("%s set rx_iout limit fail.", __func__); - - return EC_SUCCESS; -} - - -static void p9221_notifier_check_vbus(void) -{ - struct charge_port_info chg; - - wpc->p9221_check_vbus = false; - - CPRINTS("%s online:%d vbus:%d", __func__, wpc->online, - wpc->vbus_status); - - /* - * We now have confirmation from DC_IN, kill the timer, p9221_online - * will be set by this function. - */ - hook_call_deferred(&p9221_vbus_check_timeout_data, -1); - - if (wpc->vbus_status) { - /* WPC VBUS on ,Always write FOD, check dc_icl, send CSP */ - p9221_set_dc_icl(); - p9221_config_fod(); - - p9221_send_csp(1); - - /* when wpc vbus attached after 2s, set wpc online */ - if (!wpc->online) - p9221_set_online(); - - /* WPC VBUS on , update charge voltage and current */ - p9221_get_charge_supplier(); - chg.voltage = p9221_get_ivl(wpc->charge_supplier); - chg.current = p9221_get_icl(wpc->charge_supplier); - - p9221_update_charger(wpc->charge_supplier, &chg); - } else { - /* - * Vbus detached, set wpc offline and update wpc charge voltage - * and current to zero. - */ - if (wpc->online) { - p9221_set_offline(); - p9221_update_charger(wpc->charge_supplier, NULL); - } - } - - CPRINTS("check_vbus changed on:%d vbus:%d", wpc->online, - wpc->vbus_status); - -} - -static void p9221_detect_work(void) -{ - - CPRINTS("%s online:%d check_vbus:%d check_det:%d vbus:%d", __func__, - wpc->online, wpc->p9221_check_vbus, wpc->p9221_check_det, - wpc->vbus_status); - - /* Step 1 */ - if (wpc->p9221_check_det) - p9221_notifier_check_det(); - - /* Step 2 */ - if (wpc->p9221_check_vbus) - p9221_notifier_check_vbus(); - -} -DECLARE_DEFERRED(p9221_detect_work); - -void p9221_notify_vbus_change(int vbus) -{ - wpc->p9221_check_vbus = true; - wpc->vbus_status = vbus; - hook_call_deferred(&p9221_detect_work_data, P9221_NOTIFIER_DELAY_MS); -} - -void wireless_power_charger_task(void *u) -{ - while (1) { - int ret, irq_src; - task_wait_event(-1); - - ret = p9221_read16(P9221_INT_REG, &irq_src); - if (ret) { - CPRINTS("Failed to read INT REG"); - continue; - } - - CPRINTS("INT SRC 0x%04x", irq_src); - - if (p9221r7_clear_interrupts(irq_src)) - continue; - - if (irq_src & P9221_STAT_VRECT) { - CPRINTS("VRECTON, online=%d", wpc->online); - if (!wpc->online) { - wpc->p9221_check_det = true; - hook_call_deferred(&p9221_detect_work_data, - P9221_NOTIFIER_DELAY_MS); - } - } - - p9221r7_irq_handler(irq_src); - } -} diff --git a/driver/wpc/p9221.h b/driver/wpc/p9221.h index 0bb0571b38..53dcc57aa7 100644 --- a/driver/wpc/p9221.h +++ b/driver/wpc/p9221.h @@ -1,9 +1,8 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. +/* Copyright 2018 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ - /* * IDT P9221-R7 Wireless Power Receiver driver definitions. */ @@ -16,248 +15,243 @@ #include "charge_manager.h" #include "task.h" - /* ========== Variant-specific configuration ============ */ -#define P9221_R7_ADDR_FLAGS 0x61 +#define P9221_R7_ADDR_FLAGS 0x61 /* * P9221 common registers */ -#define P9221_CHIP_ID_REG 0x00 -#define P9221_CHIP_ID 0x9220 -#define P9221_CHIP_REVISION_REG 0x02 -#define P9221_CUSTOMER_ID_REG 0x03 -#define P9221R7_CUSTOMER_ID_VAL 0x05 -#define P9221_OTP_FW_MAJOR_REV_REG 0x04 -#define P9221_OTP_FW_MINOR_REV_REG 0x06 -#define P9221_OTP_FW_DATE_REG 0x08 -#define P9221_OTP_FW_DATE_SIZE 12 -#define P9221_OTP_FW_TIME_REG 0x14 -#define P9221_OTP_FW_TIME_SIZE 8 -#define P9221_SRAM_FW_MAJOR_REV_REG 0x1C -#define P9221_SRAM_FW_MINOR_REV_REG 0x1E -#define P9221_SRAM_FW_DATE_REG 0x20 -#define P9221_SRAM_FW_DATE_SIZE 12 -#define P9221_SRAM_FW_TIME_REG 0x2C -#define P9221_SRAM_FW_TIME_SIZE 8 -#define P9221_STATUS_REG 0x34 -#define P9221_INT_REG 0x36 -#define P9221_INT_MASK 0xF7 -#define P9221_INT_ENABLE_REG 0x38 -#define P9221_GPP_TX_MF_ID 0x0072 +#define P9221_CHIP_ID_REG 0x00 +#define P9221_CHIP_ID 0x9220 +#define P9221_CHIP_REVISION_REG 0x02 +#define P9221_CUSTOMER_ID_REG 0x03 +#define P9221R7_CUSTOMER_ID_VAL 0x05 +#define P9221_OTP_FW_MAJOR_REV_REG 0x04 +#define P9221_OTP_FW_MINOR_REV_REG 0x06 +#define P9221_OTP_FW_DATE_REG 0x08 +#define P9221_OTP_FW_DATE_SIZE 12 +#define P9221_OTP_FW_TIME_REG 0x14 +#define P9221_OTP_FW_TIME_SIZE 8 +#define P9221_SRAM_FW_MAJOR_REV_REG 0x1C +#define P9221_SRAM_FW_MINOR_REV_REG 0x1E +#define P9221_SRAM_FW_DATE_REG 0x20 +#define P9221_SRAM_FW_DATE_SIZE 12 +#define P9221_SRAM_FW_TIME_REG 0x2C +#define P9221_SRAM_FW_TIME_SIZE 8 +#define P9221_STATUS_REG 0x34 +#define P9221_INT_REG 0x36 +#define P9221_INT_MASK 0xF7 +#define P9221_INT_ENABLE_REG 0x38 +#define P9221_GPP_TX_MF_ID 0x0072 /* * P9221 Rx registers (x != 5) */ -#define P9221_CHARGE_STAT_REG 0x3A -#define P9221_EPT_REG 0x3B -#define P9221_VOUT_ADC_REG 0x3C -#define P9221_VOUT_ADC_MASK 0x0FFF -#define P9221_VOUT_SET_REG 0x3E -#define P9221_MAX_VOUT_SET_MV_DEFAULT 9000 -#define P9221_VRECT_ADC_REG 0x40 -#define P9221_VRECT_ADC_MASK 0x0FFF -#define P9221_OVSET_REG 0x42 -#define P9221_OVSET_MASK 0x70 -#define P9221_OVSET_SHIFT 4 -#define P9221_RX_IOUT_REG 0x44 -#define P9221_DIE_TEMP_ADC_REG 0x46 -#define P9221_DIE_TEMP_ADC_MASK 0x0FFF -#define P9221_OP_FREQ_REG 0x48 -#define P9221_ILIM_SET_REG 0x4A -#define P9221_ALIGN_X_ADC_REG 0x4B -#define P9221_ALIGN_Y_ADC_REG 0x4C -#define P9221_OP_MODE_REG 0x4D -#define P9221_COM_REG 0x4E -#define P9221_FW_SWITCH_KEY_REG 0x4F -#define P9221_INT_CLEAR_REG 0x56 -#define P9221_RXID_REG 0x5C -#define P9221_RXID_LEN 6 -#define P9221_MPREQ_REG 0x5C -#define P9221_MPREQ_LEN 6 -#define P9221_FOD_REG 0x68 -#define P9221_NUM_FOD 16 -#define P9221_RX_RAWIOUT_REG 0x7A -#define P9221_RX_RAWIOUT_MASK 0xFFF -#define P9221_PMA_AD_REG 0x7C -#define P9221_RX_PINGFREQ_REG 0xFC -#define P9221_RX_PINGFREQ_MASK 0xFFF -#define P9221_LAST_REG 0xFF +#define P9221_CHARGE_STAT_REG 0x3A +#define P9221_EPT_REG 0x3B +#define P9221_VOUT_ADC_REG 0x3C +#define P9221_VOUT_ADC_MASK 0x0FFF +#define P9221_VOUT_SET_REG 0x3E +#define P9221_MAX_VOUT_SET_MV_DEFAULT 9000 +#define P9221_VRECT_ADC_REG 0x40 +#define P9221_VRECT_ADC_MASK 0x0FFF +#define P9221_OVSET_REG 0x42 +#define P9221_OVSET_MASK 0x70 +#define P9221_OVSET_SHIFT 4 +#define P9221_RX_IOUT_REG 0x44 +#define P9221_DIE_TEMP_ADC_REG 0x46 +#define P9221_DIE_TEMP_ADC_MASK 0x0FFF +#define P9221_OP_FREQ_REG 0x48 +#define P9221_ILIM_SET_REG 0x4A +#define P9221_ALIGN_X_ADC_REG 0x4B +#define P9221_ALIGN_Y_ADC_REG 0x4C +#define P9221_OP_MODE_REG 0x4D +#define P9221_COM_REG 0x4E +#define P9221_FW_SWITCH_KEY_REG 0x4F +#define P9221_INT_CLEAR_REG 0x56 +#define P9221_RXID_REG 0x5C +#define P9221_RXID_LEN 6 +#define P9221_MPREQ_REG 0x5C +#define P9221_MPREQ_LEN 6 +#define P9221_FOD_REG 0x68 +#define P9221_NUM_FOD 16 +#define P9221_RX_RAWIOUT_REG 0x7A +#define P9221_RX_RAWIOUT_MASK 0xFFF +#define P9221_PMA_AD_REG 0x7C +#define P9221_RX_PINGFREQ_REG 0xFC +#define P9221_RX_PINGFREQ_MASK 0xFFF +#define P9221_LAST_REG 0xFF /* * P9221R7 unique registers */ -#define P9221R7_INT_CLEAR_REG 0x3A -#define P9221R7_VOUT_SET_REG 0x3C -#define P9221R7_ILIM_SET_REG 0x3D -#define P9221R7_ILIM_SET_MAX 0x0E /* 0x0E = 1.6A */ -#define P9221R7_CHARGE_STAT_REG 0x3E -#define P9221R7_EPT_REG 0x3F -#define P9221R7_VRECT_REG 0x40 -#define P9221R7_VOUT_REG 0x42 -#define P9221R7_IOUT_REG 0x44 -#define P9221R7_OP_FREQ_REG 0x48 -#define P9221R7_SYSTEM_MODE_REG 0x4C -#define P9221R7_COM_CHAN_RESET_REG 0x50 -#define P9221R7_COM_CHAN_SEND_SIZE_REG 0x58 -#define P9221R7_COM_CHAN_SEND_IDX_REG 0x59 -#define P9221R7_COM_CHAN_RECV_SIZE_REG 0x5A -#define P9221R7_COM_CHAN_RECV_IDX_REG 0x5B -#define P9221R7_VRECT_ADC_REG 0x60 -#define P9221R7_VOUT_ADC_REG 0x62 -#define P9221R7_VOUT_ADC_MASK 0xFFF -#define P9221R7_IOUT_ADC_REG 0x64 -#define P9221R7_IOUT_ADC_MASK 0xFFF -#define P9221R7_DIE_TEMP_ADC_REG 0x66 -#define P9221R7_DIE_TEMP_ADC_MASK 0xFFF -#define P9221R7_AC_PERIOD_REG 0x68 -#define P9221R7_TX_PINGFREQ_REG 0x6A -#define P9221R7_EXT_TEMP_REG 0x6C -#define P9221R7_EXT_TEMP_MASK 0xFFF -#define P9221R7_FOD_REG 0x70 -#define P9221R7_NUM_FOD 16 -#define P9221R7_DEBUG_REG 0x80 -#define P9221R7_EPP_Q_FACTOR_REG 0x83 -#define P9221R7_EPP_TX_GUARANTEED_POWER_REG 0x84 -#define P9221R7_EPP_TX_POTENTIAL_POWER_REG 0x85 -#define P9221R7_EPP_TX_CAPABILITY_FLAGS_REG 0x86 -#define P9221R7_EPP_RENEGOTIATION_REG 0x87 -#define P9221R7_EPP_CUR_RPP_HEADER_REG 0x88 -#define P9221R7_EPP_CUR_NEGOTIATED_POWER_REG 0x89 -#define P9221R7_EPP_CUR_MAXIMUM_POWER_REG 0x8A -#define P9221R7_EPP_CUR_FSK_MODULATION_REG 0x8B -#define P9221R7_EPP_REQ_RPP_HEADER_REG 0x8C -#define P9221R7_EPP_REQ_NEGOTIATED_POWER_REG 0x8D -#define P9221R7_EPP_REQ_MAXIMUM_POWER_REG 0x8E -#define P9221R7_EPP_REQ_FSK_MODULATION_REG 0x8F -#define P9221R7_VRECT_TARGET_REG 0x90 -#define P9221R7_VRECT_KNEE_REG 0x92 -#define P9221R7_VRECT_CORRECTION_FACTOR_REG 0x93 -#define P9221R7_VRECT_MAX_CORRECTION_FACTOR_REG 0x94 -#define P9221R7_VRECT_MIN_CORRECTION_FACTOR_REG 0x96 -#define P9221R7_FOD_SECTION_REG 0x99 -#define P9221R7_VRECT_ADJ_REG 0x9E -#define P9221R7_ALIGN_X_ADC_REG 0xA0 -#define P9221R7_ALIGN_Y_ADC_REG 0xA1 -#define P9221R7_ASK_MODULATION_DEPTH_REG 0xA2 -#define P9221R7_OVSET_REG 0xA3 -#define P9221R7_OVSET_MASK 0x7 -#define P9221R7_EPP_TX_SPEC_REV_REG 0xA9 -#define P9221R7_EPP_TX_MFG_CODE_REG 0xAA -#define P9221R7_GP0_RESET_VOLT_REG 0xAC -#define P9221R7_GP1_RESET_VOLT_REG 0xAE -#define P9221R7_GP2_RESET_VOLT_REG 0xB0 -#define P9221R7_GP3_RESET_VOLT_REG 0xB2 -#define P9221R7_PROP_TX_ID_REG 0xB4 -#define P9221R7_PROP_TX_ID_SIZE 4 -#define P9221R7_DATA_SEND_BUF_START 0x100 -#define P9221R7_DATA_SEND_BUF_SIZE 0x80 -#define P9221R7_DATA_RECV_BUF_START 0x180 -#define P9221R7_DATA_RECV_BUF_SIZE 0x80 -#define P9221R7_MAX_PP_BUF_SIZE 16 -#define P9221R7_LAST_REG 0x1FF +#define P9221R7_INT_CLEAR_REG 0x3A +#define P9221R7_VOUT_SET_REG 0x3C +#define P9221R7_ILIM_SET_REG 0x3D +#define P9221R7_ILIM_SET_MAX 0x0E /* 0x0E = 1.6A */ +#define P9221R7_CHARGE_STAT_REG 0x3E +#define P9221R7_EPT_REG 0x3F +#define P9221R7_VRECT_REG 0x40 +#define P9221R7_VOUT_REG 0x42 +#define P9221R7_IOUT_REG 0x44 +#define P9221R7_OP_FREQ_REG 0x48 +#define P9221R7_SYSTEM_MODE_REG 0x4C +#define P9221R7_COM_CHAN_RESET_REG 0x50 +#define P9221R7_COM_CHAN_SEND_SIZE_REG 0x58 +#define P9221R7_COM_CHAN_SEND_IDX_REG 0x59 +#define P9221R7_COM_CHAN_RECV_SIZE_REG 0x5A +#define P9221R7_COM_CHAN_RECV_IDX_REG 0x5B +#define P9221R7_VRECT_ADC_REG 0x60 +#define P9221R7_VOUT_ADC_REG 0x62 +#define P9221R7_VOUT_ADC_MASK 0xFFF +#define P9221R7_IOUT_ADC_REG 0x64 +#define P9221R7_IOUT_ADC_MASK 0xFFF +#define P9221R7_DIE_TEMP_ADC_REG 0x66 +#define P9221R7_DIE_TEMP_ADC_MASK 0xFFF +#define P9221R7_AC_PERIOD_REG 0x68 +#define P9221R7_TX_PINGFREQ_REG 0x6A +#define P9221R7_EXT_TEMP_REG 0x6C +#define P9221R7_EXT_TEMP_MASK 0xFFF +#define P9221R7_FOD_REG 0x70 +#define P9221R7_NUM_FOD 16 +#define P9221R7_DEBUG_REG 0x80 +#define P9221R7_EPP_Q_FACTOR_REG 0x83 +#define P9221R7_EPP_TX_GUARANTEED_POWER_REG 0x84 +#define P9221R7_EPP_TX_POTENTIAL_POWER_REG 0x85 +#define P9221R7_EPP_TX_CAPABILITY_FLAGS_REG 0x86 +#define P9221R7_EPP_RENEGOTIATION_REG 0x87 +#define P9221R7_EPP_CUR_RPP_HEADER_REG 0x88 +#define P9221R7_EPP_CUR_NEGOTIATED_POWER_REG 0x89 +#define P9221R7_EPP_CUR_MAXIMUM_POWER_REG 0x8A +#define P9221R7_EPP_CUR_FSK_MODULATION_REG 0x8B +#define P9221R7_EPP_REQ_RPP_HEADER_REG 0x8C +#define P9221R7_EPP_REQ_NEGOTIATED_POWER_REG 0x8D +#define P9221R7_EPP_REQ_MAXIMUM_POWER_REG 0x8E +#define P9221R7_EPP_REQ_FSK_MODULATION_REG 0x8F +#define P9221R7_VRECT_TARGET_REG 0x90 +#define P9221R7_VRECT_KNEE_REG 0x92 +#define P9221R7_VRECT_CORRECTION_FACTOR_REG 0x93 +#define P9221R7_VRECT_MAX_CORRECTION_FACTOR_REG 0x94 +#define P9221R7_VRECT_MIN_CORRECTION_FACTOR_REG 0x96 +#define P9221R7_FOD_SECTION_REG 0x99 +#define P9221R7_VRECT_ADJ_REG 0x9E +#define P9221R7_ALIGN_X_ADC_REG 0xA0 +#define P9221R7_ALIGN_Y_ADC_REG 0xA1 +#define P9221R7_ASK_MODULATION_DEPTH_REG 0xA2 +#define P9221R7_OVSET_REG 0xA3 +#define P9221R7_OVSET_MASK 0x7 +#define P9221R7_EPP_TX_SPEC_REV_REG 0xA9 +#define P9221R7_EPP_TX_MFG_CODE_REG 0xAA +#define P9221R7_GP0_RESET_VOLT_REG 0xAC +#define P9221R7_GP1_RESET_VOLT_REG 0xAE +#define P9221R7_GP2_RESET_VOLT_REG 0xB0 +#define P9221R7_GP3_RESET_VOLT_REG 0xB2 +#define P9221R7_PROP_TX_ID_REG 0xB4 +#define P9221R7_PROP_TX_ID_SIZE 4 +#define P9221R7_DATA_SEND_BUF_START 0x100 +#define P9221R7_DATA_SEND_BUF_SIZE 0x80 +#define P9221R7_DATA_RECV_BUF_START 0x180 +#define P9221R7_DATA_RECV_BUF_SIZE 0x80 +#define P9221R7_MAX_PP_BUF_SIZE 16 +#define P9221R7_LAST_REG 0x1FF /* * System Mode Mask (r7+/0x4C) */ -#define P9221R7_SYSTEM_MODE_EXTENDED_MASK (1 << 3) +#define P9221R7_SYSTEM_MODE_EXTENDED_MASK (1 << 3) /* * TX ID GPP Mask (r7+/0xB4->0xB7) */ -#define P9221R7_PROP_TX_ID_GPP_MASK (1 << 29) +#define P9221R7_PROP_TX_ID_GPP_MASK (1 << 29) /* * Com Channel Commands */ -#define P9221R7_COM_CHAN_CCRESET BIT(7) -#define P9221_COM_CHAN_RETRIES 5 +#define P9221R7_COM_CHAN_CCRESET BIT(7) +#define P9221_COM_CHAN_RETRIES 5 /* * End of Power packet types */ -#define P9221_EOP_UNKNOWN 0x00 -#define P9221_EOP_EOC 0x01 -#define P9221_EOP_INTERNAL_FAULT 0x02 -#define P9221_EOP_OVER_TEMP 0x03 -#define P9221_EOP_OVER_VOLT 0x04 -#define P9221_EOP_OVER_CURRENT 0x05 -#define P9221_EOP_BATT_FAIL 0x06 -#define P9221_EOP_RECONFIG 0x07 -#define P9221_EOP_NO_RESPONSE 0x08 -#define P9221_EOP_NEGOTIATION_FAIL 0x0A -#define P9221_EOP_RESTART_POWER 0x0B +#define P9221_EOP_UNKNOWN 0x00 +#define P9221_EOP_EOC 0x01 +#define P9221_EOP_INTERNAL_FAULT 0x02 +#define P9221_EOP_OVER_TEMP 0x03 +#define P9221_EOP_OVER_VOLT 0x04 +#define P9221_EOP_OVER_CURRENT 0x05 +#define P9221_EOP_BATT_FAIL 0x06 +#define P9221_EOP_RECONFIG 0x07 +#define P9221_EOP_NO_RESPONSE 0x08 +#define P9221_EOP_NEGOTIATION_FAIL 0x0A +#define P9221_EOP_RESTART_POWER 0x0B /* * Command flags */ -#define P9221R7_COM_RENEGOTIATE P9221_COM_RENEGOTIATE -#define P9221R7_COM_SWITCH2RAM P9221_COM_SWITCH_TO_RAM_MASK -#define P9221R7_COM_CLRINT P9221_COM_CLEAR_INT_MASK -#define P9221R7_COM_SENDCSP P9221_COM_SEND_CHG_STAT_MASK -#define P9221R7_COM_SENDEPT P9221_COM_SEND_EOP_MASK -#define P9221R7_COM_LDOTGL P9221_COM_LDO_TOGGLE -#define P9221R7_COM_CCACTIVATE BIT(0) +#define P9221R7_COM_RENEGOTIATE P9221_COM_RENEGOTIATE +#define P9221R7_COM_SWITCH2RAM P9221_COM_SWITCH_TO_RAM_MASK +#define P9221R7_COM_CLRINT P9221_COM_CLEAR_INT_MASK +#define P9221R7_COM_SENDCSP P9221_COM_SEND_CHG_STAT_MASK +#define P9221R7_COM_SENDEPT P9221_COM_SEND_EOP_MASK +#define P9221R7_COM_LDOTGL P9221_COM_LDO_TOGGLE +#define P9221R7_COM_CCACTIVATE BIT(0) -#define P9221_COM_RENEGOTIATE BIT(7) -#define P9221_COM_SWITCH_TO_RAM_MASK BIT(6) -#define P9221_COM_CLEAR_INT_MASK BIT(5) -#define P9221_COM_SEND_CHG_STAT_MASK BIT(4) -#define P9221_COM_SEND_EOP_MASK BIT(3) -#define P9221_COM_LDO_TOGGLE BIT(1) +#define P9221_COM_RENEGOTIATE BIT(7) +#define P9221_COM_SWITCH_TO_RAM_MASK BIT(6) +#define P9221_COM_CLEAR_INT_MASK BIT(5) +#define P9221_COM_SEND_CHG_STAT_MASK BIT(4) +#define P9221_COM_SEND_EOP_MASK BIT(3) +#define P9221_COM_LDO_TOGGLE BIT(1) /* * Interrupt/Status flags for P9221 */ -#define P9221_STAT_VOUT BIT(7) -#define P9221_STAT_VRECT BIT(6) -#define P9221_STAT_ACMISSING BIT(5) -#define P9221_STAT_OV_TEMP BIT(2) -#define P9221_STAT_OV_VOLT BIT(1) -#define P9221_STAT_OV_CURRENT BIT(0) -#define P9221_STAT_LIMIT_MASK (P9221_STAT_OV_TEMP | \ - P9221_STAT_OV_VOLT | \ - P9221_STAT_OV_CURRENT) +#define P9221_STAT_VOUT BIT(7) +#define P9221_STAT_VRECT BIT(6) +#define P9221_STAT_ACMISSING BIT(5) +#define P9221_STAT_OV_TEMP BIT(2) +#define P9221_STAT_OV_VOLT BIT(1) +#define P9221_STAT_OV_CURRENT BIT(0) +#define P9221_STAT_LIMIT_MASK \ + (P9221_STAT_OV_TEMP | P9221_STAT_OV_VOLT | P9221_STAT_OV_CURRENT) /* * Interrupt/Status flags for P9221R7 */ -#define P9221R7_STAT_CCRESET BIT(12) -#define P9221R7_STAT_CCERROR BIT(11) -#define P9221R7_STAT_PPRCVD BIT(10) -#define P9221R7_STAT_CCDATARCVD BIT(9) -#define P9221R7_STAT_CCSENDBUSY BIT(8) -#define P9221R7_STAT_VOUTCHANGED BIT(7) -#define P9221R7_STAT_VRECTON BIT(6) -#define P9221R7_STAT_MODECHANGED BIT(5) -#define P9221R7_STAT_UV BIT(3) -#define P9221R7_STAT_OVT BIT(2) -#define P9221R7_STAT_OVV BIT(1) -#define P9221R7_STAT_OVC BIT(0) -#define P9221R7_STAT_MASK 0x1FFF -#define P9221R7_STAT_CC_MASK (P9221R7_STAT_CCRESET | \ - P9221R7_STAT_PPRCVD | \ - P9221R7_STAT_CCERROR | \ - P9221R7_STAT_CCDATARCVD | \ - P9221R7_STAT_CCSENDBUSY) -#define P9221R7_STAT_LIMIT_MASK (P9221R7_STAT_UV | \ - P9221R7_STAT_OVV | \ - P9221R7_STAT_OVT | \ - P9221R7_STAT_OVC) +#define P9221R7_STAT_CCRESET BIT(12) +#define P9221R7_STAT_CCERROR BIT(11) +#define P9221R7_STAT_PPRCVD BIT(10) +#define P9221R7_STAT_CCDATARCVD BIT(9) +#define P9221R7_STAT_CCSENDBUSY BIT(8) +#define P9221R7_STAT_VOUTCHANGED BIT(7) +#define P9221R7_STAT_VRECTON BIT(6) +#define P9221R7_STAT_MODECHANGED BIT(5) +#define P9221R7_STAT_UV BIT(3) +#define P9221R7_STAT_OVT BIT(2) +#define P9221R7_STAT_OVV BIT(1) +#define P9221R7_STAT_OVC BIT(0) +#define P9221R7_STAT_MASK 0x1FFF +#define P9221R7_STAT_CC_MASK \ + (P9221R7_STAT_CCRESET | P9221R7_STAT_PPRCVD | P9221R7_STAT_CCERROR | \ + P9221R7_STAT_CCDATARCVD | P9221R7_STAT_CCSENDBUSY) +#define P9221R7_STAT_LIMIT_MASK \ + (P9221R7_STAT_UV | P9221R7_STAT_OVV | P9221R7_STAT_OVT | \ + P9221R7_STAT_OVC) -#define P9221_DC_ICL_BPP_MA 1000 -#define P9221_DC_ICL_EPP_MA 1100 -#define P9221_DC_IVL_BPP_MV 5000 -#define P9221_DC_IVL_EPP_MV 9000 -#define P9221_EPP_THRESHOLD_UV 7000000 +#define P9221_DC_ICL_BPP_MA 1000 +#define P9221_DC_ICL_EPP_MA 1100 +#define P9221_DC_IVL_BPP_MV 5000 +#define P9221_DC_IVL_EPP_MV 9000 +#define P9221_EPP_THRESHOLD_UV 7000000 -#define true 1 -#define false 0 +#define true 1 +#define false 0 struct wpc_charger_info { - uint8_t online; /* wpc is online */ - uint8_t cust_id; /* customer id */ - uint8_t i2c_port; /* i2c port */ + uint8_t online; /* wpc is online */ + uint8_t cust_id; /* customer id */ + uint8_t i2c_port; /* i2c port */ /* Proprietary Packets receive buffer, to get Proprietary data from TX*/ uint8_t pp_buf[P9221R7_MAX_PP_BUF_SIZE]; uint8_t pp_buf_valid; @@ -267,8 +261,8 @@ struct wpc_charger_info { uint8_t rx_done; /* Message packets send buffer, used when send messages from RX to TX*/ uint8_t tx_buf[P9221R7_DATA_SEND_BUF_SIZE]; - uint8_t tx_id; /* TX device id */ - uint8_t tx_len; /* The data size need send to TX */ + uint8_t tx_id; /* TX device id */ + uint8_t tx_len; /* The data size need send to TX */ uint8_t tx_done; /* TX data send has done */ uint8_t tx_busy; /* when tx_busy=1, can't transfer data from RX to TX */ /* p9221_check_vbus=1 when VBUS has changed, need update charge state */ |