summaryrefslogtreecommitdiff
path: root/zephyr/emul
diff options
context:
space:
mode:
authorEric Yilun Lin <yllin@chromium.org>2023-04-27 16:52:08 +0800
committerChromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com>2023-05-02 03:42:31 +0000
commit6adc4456c723f61c83e3e3c643a0974a99829ce9 (patch)
tree83887c78a103494e1ea53accdbc37e4d92606b6e /zephyr/emul
parent1f30cdabd0e26bc3e2079719c05277559491b014 (diff)
downloadchrome-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.c88
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)