diff options
author | Eric Yilun Lin <yllin@chromium.org> | 2023-04-27 16:52:08 +0800 |
---|---|---|
committer | Chromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com> | 2023-05-02 03:42:31 +0000 |
commit | 6adc4456c723f61c83e3e3c643a0974a99829ce9 (patch) | |
tree | 83887c78a103494e1ea53accdbc37e4d92606b6e /zephyr/emul | |
parent | 1f30cdabd0e26bc3e2079719c05277559491b014 (diff) | |
download | chrome-ec-6adc4456c723f61c83e3e3c643a0974a99829ce9.tar.gz |
emul_nx20p348x: use TCPC power_status as TCPC GPIO config
On NX20P3483, it needs 2 dedicated TCPC GPIO to reflect the
VBUS sink and source control. There's no such binding now,
so we checked the TCPC POWER_STATUS instead, and it should have
the same functionality for the VBUS status checking.
BUG=b:272664811
TEST=./twister -ci -T zephyr/test
BRANCH=none
Change-Id: I05e73e16a4ddb1d22b812e672dbaaa366704f984
Signed-off-by: Eric Yilun Lin <yllin@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/4483239
Commit-Queue: Eric Yilun Lin <yllin@google.com>
Reviewed-by: Diana Z <dzigterman@chromium.org>
Tested-by: Eric Yilun Lin <yllin@google.com>
Diffstat (limited to 'zephyr/emul')
-rw-r--r-- | zephyr/emul/emul_nx20p348x.c | 88 |
1 files changed, 77 insertions, 11 deletions
diff --git a/zephyr/emul/emul_nx20p348x.c b/zephyr/emul/emul_nx20p348x.c index 8d654f42ce..3e4b4d7b2d 100644 --- a/zephyr/emul/emul_nx20p348x.c +++ b/zephyr/emul/emul_nx20p348x.c @@ -4,8 +4,12 @@ */ #include "driver/ppc/nx20p348x.h" +#include "driver/tcpm/tcpci.h" #include "emul/emul_common_i2c.h" +#include "emul/emul_nx20p348x.h" #include "emul/emul_stub_device.h" +#include "emul/tcpc/emul_tcpci.h" +#include "emul/utils.h" #include "usbc/ppc_nx20p348x.h" #include "usbc_ppc.h" #include "util.h" @@ -30,7 +34,9 @@ LOG_MODULE_REGISTER(emul_nx20p348x); struct nx20p348x_emul_data { struct i2c_common_emul_data common; struct gpio_dt_spec irq_gpio; + const struct emul *tcpc_emul; uint8_t regs[NX20P348X_MAX_REG + 1]; + bool tcpc_interact; }; struct nx20p348x_reg_default { @@ -69,6 +75,7 @@ void nx20p348x_emul_reset_regs(const struct emul *emul) data->regs[def.offset] = def.val; } nx20p348x_emul_interrupt_set(emul, 1); + nx20p348x_emul_set_tcpc_interact(emul, true); } uint8_t nx20p348x_emul_peek(const struct emul *emul, int reg) @@ -81,6 +88,13 @@ uint8_t nx20p348x_emul_peek(const struct emul *emul, int reg) return data->regs[reg]; } +void nx20p348x_emul_set_tcpc_interact(const struct emul *emul, bool en) +{ + struct nx20p348x_emul_data *data = + (struct nx20p348x_emul_data *)emul->data; + data->tcpc_interact = en; +} + void nx20p348x_emul_set_interrupt1(const struct emul *emul, uint8_t val) { struct nx20p348x_emul_data *data = @@ -103,6 +117,55 @@ static int nx20p348x_emul_read(const struct emul *emul, int reg, uint8_t *val, if (bytes != 0) return -EINVAL; + if (IS_ENABLED(CONFIG_PLATFORM_EC_USBC_PPC_NX20P3483) && + data->tcpc_interact) { + uint16_t pwr_status; + bool src_en, snk_en; + + tcpci_emul_get_reg(data->tcpc_emul, TCPC_REG_POWER_STATUS, + &pwr_status); + src_en = pwr_status & TCPC_REG_POWER_STATUS_SOURCING_VBUS; + snk_en = pwr_status & TCPC_REG_POWER_STATUS_SINKING_VBUS; + + if (reg == NX20P348X_SWITCH_STATUS_REG) { + if (src_en) { + data->regs[reg] |= + NX20P348X_SWITCH_STATUS_5VSRC; + } else { + data->regs[reg] &= + ~(NX20P348X_SWITCH_STATUS_5VSRC | + NX20P348X_SWITCH_STATUS_HVSRC); + } + if (snk_en) { + data->regs[reg] |= + NX20P348X_SWITCH_STATUS_HVSNK; + } else { + data->regs[reg] &= + (~NX20P348X_SWITCH_STATUS_HVSNK); + } + } else if (reg == NX20P348X_DEVICE_STATUS_REG) { + int mode = data->regs[reg] & + (~NX20P3483_DEVICE_MODE_MASK); + bool db_exit = + !!(data->regs[NX20P348X_DEVICE_CONTROL_REG] & + NX20P348X_CTRL_DB_EXIT); + + if (snk_en) { + mode = NX20P3483_MODE_HV_SNK; + } else if (src_en) { + mode = NX20P3483_MODE_5V_SRC; + } else if (data->regs[NX20P348X_SWITCH_STATUS_REG] & + NX20P348X_SWITCH_STATUS_HVSRC) { + mode = NX20P3483_MODE_HV_SRC; + } else if (!db_exit) { + mode = NX20P348X_MODE_DEAD_BATTERY; + } + data->regs[reg] = (data->regs[reg] & + ~NX20P3483_DEVICE_MODE_MASK) | + mode; + } + } + *val = data->regs[reg]; /* Interrupt registers are clear on read and de-assert when serviced */ @@ -173,17 +236,20 @@ static int nx20p348x_emul_init(const struct emul *emul, return 0; } -#define INIT_NX20P348X_EMUL(n) \ - static struct nx20p348x_emul_data nx20p348x_emul_data_##n; \ - static struct i2c_common_emul_cfg common_cfg_##n = { \ - .dev_label = DT_NODE_FULL_NAME(DT_DRV_INST(n)), \ - .data = &nx20p348x_emul_data_##n.common, \ - .addr = DT_INST_REG_ADDR(n) \ - }; \ - static struct nx20p348x_emul_data nx20p348x_emul_data_##n = { \ - .irq_gpio = GPIO_DT_SPEC_INST_GET_OR(n, irq_gpios, {}), \ - }; \ - EMUL_DT_INST_DEFINE(n, nx20p348x_emul_init, &nx20p348x_emul_data_##n, \ +#define INIT_NX20P348X_EMUL(n) \ + static struct nx20p348x_emul_data nx20p348x_emul_data_##n; \ + static struct i2c_common_emul_cfg common_cfg_##n = { \ + .dev_label = DT_NODE_FULL_NAME(DT_DRV_INST(n)), \ + .data = &nx20p348x_emul_data_##n.common, \ + .addr = DT_INST_REG_ADDR(n) \ + }; \ + static struct nx20p348x_emul_data nx20p348x_emul_data_##n = { \ + .irq_gpio = GPIO_DT_SPEC_INST_GET_OR(n, irq_gpios, {}), \ + .tcpc_emul = \ + EMUL_GET_USBC_PROP_BINDING(ppc, DT_DRV_INST(n), tcpc), \ + .tcpc_interact = true, \ + }; \ + EMUL_DT_INST_DEFINE(n, nx20p348x_emul_init, &nx20p348x_emul_data_##n, \ &common_cfg_##n, &i2c_common_emul_api, NULL) DT_INST_FOREACH_STATUS_OKAY(INIT_NX20P348X_EMUL) |