summaryrefslogtreecommitdiff
path: root/zephyr/include/emul/tcpc/emul_tcpci.h
diff options
context:
space:
mode:
Diffstat (limited to 'zephyr/include/emul/tcpc/emul_tcpci.h')
-rw-r--r--zephyr/include/emul/tcpc/emul_tcpci.h278
1 files changed, 163 insertions, 115 deletions
diff --git a/zephyr/include/emul/tcpc/emul_tcpci.h b/zephyr/include/emul/tcpc/emul_tcpci.h
index dd225c5f6e..8175b9ce96 100644
--- a/zephyr/include/emul/tcpc/emul_tcpci.h
+++ b/zephyr/include/emul/tcpc/emul_tcpci.h
@@ -1,4 +1,4 @@
-/* Copyright 2021 The Chromium OS Authors. All rights reserved.
+/* Copyright 2021 The ChromiumOS Authors
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
@@ -17,27 +17,13 @@
#include <zephyr/drivers/i2c_emul.h>
#include <usb_pd_tcpm.h>
+#include "emul/emul_common_i2c.h"
+
/**
- * @brief TCPCI emulator backend API
- * @defgroup tcpci_emul TCPCI emulator
- * @{
- *
- * TCPCI emulator supports access to its registers using I2C messages.
- * It follows Type-C Port Controller Interface Specification. It is possible
- * to use this emulator as base for implementation of specific TCPC emulator
- * which follows TCPCI specification. Emulator allows to set callbacks
- * on change of CC status or transmitting message to implement partner emulator.
- * There is also callback used to inform about alert line state change.
- * Application may alter emulator state:
- *
- * - call @ref tcpci_emul_set_reg and @ref tcpci_emul_get_reg to set and get
- * value of TCPCI registers
- * - call functions from emul_common_i2c.h to setup custom handlers for I2C
- * messages
- * - call @ref tcpci_emul_add_rx_msg to setup received SOP messages
- * - call @ref tcpci_emul_get_tx_msg to examine sended message
- * - call @ref tcpci_emul_set_rev to set revision of emulated TCPCI
+ * Number of emulated register. This include vendor registers defined in TCPCI
+ * specification
*/
+#define TCPCI_EMUL_REG_COUNT 0x100
/** SOP message structure */
struct tcpci_emul_msg {
@@ -46,7 +32,7 @@ struct tcpci_emul_msg {
/** Number of bytes in buf */
int cnt;
/** Type of message (SOP, SOP', etc) */
- uint8_t type;
+ uint8_t sop_type;
/** Index used to mark accessed byte */
int idx;
/** Pointer to optional second message */
@@ -64,6 +50,80 @@ struct tcpci_emul_msg {
typedef void (*tcpci_emul_alert_state_func)(const struct emul *emul, bool alert,
void *data);
+/** Run-time data used by the emulator */
+struct tcpci_ctx {
+ /** Common I2C data for TCPC */
+ struct i2c_common_emul_data common;
+
+ /** Current state of all emulated TCPCI registers */
+ uint8_t reg[TCPCI_EMUL_REG_COUNT];
+
+ /** Structures representing TX and RX buffers */
+ struct tcpci_emul_msg *rx_msg;
+ struct tcpci_emul_msg *tx_msg;
+
+ /** Data that should be written to register (except TX_BUFFER) */
+ uint16_t write_data;
+
+ /** Return error when trying to write to RO register */
+ bool error_on_ro_write;
+ /** Return error when trying to write 1 to reserved bit */
+ bool error_on_rsvd_write;
+
+ /** User function called when alert line could change */
+ tcpci_emul_alert_state_func alert_callback;
+ /** Data passed to alert_callback */
+ void *alert_callback_data;
+
+ /** Callbacks for TCPCI partner */
+ const struct tcpci_emul_partner_ops *partner;
+
+ /** Reference to Alert# GPIO emulator. */
+ const struct device *alert_gpio_port;
+ gpio_pin_t alert_gpio_pin;
+};
+
+/** Run-time data used by the emulator */
+struct tcpc_emul_data {
+ /** Pointer to the common TCPCI emulator context */
+ struct tcpci_ctx *tcpci_ctx;
+
+ /** Pointer to chip specific data */
+ void *chip_data;
+
+ const struct i2c_common_emul_cfg i2c_cfg;
+};
+
+#define TCPCI_EMUL_DEFINE(n, init, cfg_ptr, chip_data_ptr, bus_api) \
+ static uint8_t tcpci_emul_tx_buf_##n[128]; \
+ static struct tcpci_emul_msg tcpci_emul_tx_msg_##n = { \
+ .buf = tcpci_emul_tx_buf_##n, \
+ }; \
+ static struct tcpci_ctx tcpci_ctx##n = { \
+ .tx_msg = &tcpci_emul_tx_msg_##n, \
+ .error_on_ro_write = true, \
+ .error_on_rsvd_write = true, \
+ .alert_gpio_port = COND_CODE_1( \
+ DT_INST_NODE_HAS_PROP(n, alert_gpio), \
+ (DEVICE_DT_GET(DT_GPIO_CTLR( \
+ DT_INST_PROP(n, alert_gpio), gpios))), \
+ (NULL)), \
+ .alert_gpio_pin = COND_CODE_1( \
+ DT_INST_NODE_HAS_PROP(n, alert_gpio), \
+ (DT_GPIO_PIN(DT_INST_PROP(n, alert_gpio), gpios)), \
+ (0)), \
+ }; \
+ static struct tcpc_emul_data tcpc_emul_data_##n = { \
+ .tcpci_ctx = &tcpci_ctx##n, \
+ .chip_data = chip_data_ptr, \
+ .i2c_cfg = { \
+ .dev_label = DT_NODE_FULL_NAME(DT_DRV_INST(n)), \
+ .data = &tcpci_ctx##n.common, \
+ .addr = DT_INST_REG_ADDR(n), \
+ }, \
+ }; \
+ EMUL_DT_INST_DEFINE(n, init, &tcpc_emul_data_##n, cfg_ptr, bus_api)
+
/** Response from TCPCI specific device operations */
enum tcpci_emul_ops_resp {
TCPCI_EMUL_CONTINUE = 0,
@@ -72,10 +132,7 @@ enum tcpci_emul_ops_resp {
};
/** Revisions supported by TCPCI emaluator */
-enum tcpci_emul_rev {
- TCPCI_EMUL_REV1_0_VER1_0 = 0,
- TCPCI_EMUL_REV2_0_VER1_1
-};
+enum tcpci_emul_rev { TCPCI_EMUL_REV1_0_VER1_0 = 0, TCPCI_EMUL_REV2_0_VER1_1 };
/** Status of TX message send to TCPCI emulator partner */
enum tcpci_emul_tx_status {
@@ -90,67 +147,6 @@ enum tcpci_emul_tx_status {
TCPCI_EMUL_TX_UNKNOWN
};
-/** TCPCI specific device operations. Not all of them need to be implemented. */
-struct tcpci_emul_dev_ops {
- /**
- * @brief Function called for each byte of read message
- *
- * @param emul Pointer to TCPCI emulator
- * @param ops Pointer to device operations structure
- * @param reg First byte of last write message
- * @param val Pointer where byte to read should be stored
- * @param bytes Number of bytes already readded
- *
- * @return TCPCI_EMUL_CONTINUE to continue with default handler
- * @return TCPCI_EMUL_DONE to immedietly return success
- * @return TCPCI_EMUL_ERROR to immedietly return error
- */
- enum tcpci_emul_ops_resp (*read_byte)(const struct emul *emul,
- const struct tcpci_emul_dev_ops *ops,
- int reg, uint8_t *val, int bytes);
-
- /**
- * @brief Function called for each byte of write message
- *
- * @param emul Pointer to TCPCI emulator
- * @param ops Pointer to device operations structure
- * @param reg First byte of write message
- * @param val Received byte of write message
- * @param bytes Number of bytes already received
- *
- * @return TCPCI_EMUL_CONTINUE to continue with default handler
- * @return TCPCI_EMUL_DONE to immedietly return success
- * @return TCPCI_EMUL_ERROR to immedietly return error
- */
- enum tcpci_emul_ops_resp (*write_byte)(const struct emul *emul,
- const struct tcpci_emul_dev_ops *ops,
- int reg, uint8_t val, int bytes);
-
- /**
- * @brief Function called on the end of write message
- *
- * @param emul Pointer to TCPCI emulator
- * @param ops Pointer to device operations structure
- * @param reg Register which is written
- * @param msg_len Length of handled I2C message
- *
- * @return TCPCI_EMUL_CONTINUE to continue with default handler
- * @return TCPCI_EMUL_DONE to immedietly return success
- * @return TCPCI_EMUL_ERROR to immedietly return error
- */
- enum tcpci_emul_ops_resp (*handle_write)(const struct emul *emul,
- const struct tcpci_emul_dev_ops *ops,
- int reg, int msg_len);
-
- /**
- * @brief Function called on reset
- *
- * @param emul Pointer to TCPCI emulator
- * @param ops Pointer to device operations structure
- */
- void (*reset)(const struct emul *emul, struct tcpci_emul_dev_ops *ops);
-};
-
/** TCPCI partner operations. Not all of them need to be implemented. */
struct tcpci_emul_partner_ops {
/**
@@ -166,8 +162,7 @@ struct tcpci_emul_partner_ops {
void (*transmit)(const struct emul *emul,
const struct tcpci_emul_partner_ops *ops,
const struct tcpci_emul_msg *tx_msg,
- enum tcpci_msg_type type,
- int retry);
+ enum tcpci_msg_type type, int retry);
/**
* @brief Function called when control settings change to allow partner
@@ -201,18 +196,9 @@ struct tcpci_emul_partner_ops {
};
/**
- * @brief Get i2c_emul for TCPCI emulator
- *
- * @param emul Pointer to TCPCI emulator
- *
- * @return Pointer to I2C TCPCI emulator
- */
-struct i2c_emul *tcpci_emul_get_i2c_emul(const struct emul *emul);
-
-/**
* @brief Set value of given register of TCPCI
*
- * @param emul Pointer to TCPCI emulator
+ * @param emul Pointer to TCPC emulator
* @param reg Register address which value will be changed
* @param val New value of the register
*
@@ -222,6 +208,68 @@ struct i2c_emul *tcpci_emul_get_i2c_emul(const struct emul *emul);
int tcpci_emul_set_reg(const struct emul *emul, int reg, uint16_t val);
/**
+ * @brief Function called for each byte of read message from TCPCI
+ *
+ * @param emul Pointer to TCPC emulator
+ * @param reg First byte of last write message
+ * @param val Pointer where byte to read should be stored
+ * @param bytes Number of bytes already readded
+ *
+ * @return 0 on success
+ */
+int tcpci_emul_read_byte(const struct emul *emul, int reg, uint8_t *val,
+ int bytes);
+
+/**
+ * @brief Function called for each byte of write message from TCPCI.
+ * Data are stored in write_data field of tcpci_emul_data or in tx_msg
+ * in case of writing to TX buffer.
+ *
+ * @param emul Pointer to TCPC emulator
+ * @param reg First byte of write message
+ * @param val Received byte of write message
+ * @param bytes Number of bytes already received
+ *
+ * @return 0 on success
+ * @return -EIO on invalid write to TX buffer
+ */
+int tcpci_emul_write_byte(const struct emul *emul, int reg, uint8_t val,
+ int bytes);
+
+/**
+ * @brief Handle I2C write message. It is checked if accessed register isn't RO
+ * and reserved bits are set to 0.
+ *
+ * @param emul Pointer to TCPC emulator
+ * @param reg Register which is written
+ * @param msg_len Length of handled I2C message
+ *
+ * @return 0 on success
+ * @return -EIO on error
+ */
+int tcpci_emul_handle_write(const struct emul *emul, int reg, int msg_len);
+
+/**
+ * @brief Set up a new TCPCI emulator
+ *
+ * This should be called for each TCPC device that needs to be
+ * registered on the I2C bus.
+ *
+ * @param emul Pointer to TCPC emulator
+ * @param parent Pointer to emulated I2C bus
+ */
+void tcpci_emul_i2c_init(const struct emul *emul, const struct device *i2c_dev);
+
+/**
+ * @brief Reset registers to default values. Vendor and reserved registers
+ * are not changed.
+ *
+ * @param emul Pointer to TCPC emulator
+ * @return 0 if successful
+ */
+int tcpci_emul_reset(const struct emul *emul);
+
+/**
* @brief Get value of given register of TCPCI
*
* @param emul Pointer to TCPCI emulator
@@ -237,7 +285,7 @@ int tcpci_emul_get_reg(const struct emul *emul, int reg, uint16_t *val);
/**
* @brief Add up to two SOP RX messages
*
- * @param emul Pointer to TCPCI emulator
+ * @param emul Pointer to TCPC emulator
* @param rx_msg Pointer to message that is added
* @param alert Select if alert register should be updated
*
@@ -255,7 +303,7 @@ int tcpci_emul_add_rx_msg(const struct emul *emul,
/**
* @brief Get SOP TX message to examine what was sended by TCPM
*
- * @param emul Pointer to TCPCI emulator
+ * @param emul Pointer to TCPC emulator
*
* @return Pointer to TX message
*/
@@ -264,24 +312,15 @@ struct tcpci_emul_msg *tcpci_emul_get_tx_msg(const struct emul *emul);
/**
* @brief Set TCPCI revision in PD_INT_REV register
*
- * @param emul Pointer to TCPCI emulator
+ * @param emul Pointer to TCPC emulator
* @param rev Requested revision
*/
void tcpci_emul_set_rev(const struct emul *emul, enum tcpci_emul_rev rev);
/**
- * @brief Set callbacks for specific TCPC device emulator
- *
- * @param emul Pointer to TCPCI emulator
- * @param dev_ops Pointer to callbacks
- */
-void tcpci_emul_set_dev_ops(const struct emul *emul,
- struct tcpci_emul_dev_ops *dev_ops);
-
-/**
* @brief Set callback which is called when alert register is changed
*
- * @param emul Pointer to TCPCI emulator
+ * @param emul Pointer to TCPC emulator
* @param alert_callback Pointer to callback
* @param alert_callback_data Pointer to data passed to callback as an argument
*/
@@ -292,7 +331,7 @@ void tcpci_emul_set_alert_callback(const struct emul *emul,
/**
* @brief Set callbacks for port partner device emulator
*
- * @param emul Pointer to TCPCI emulator
+ * @param emul Pointer to TCPC emulator
* @param partner Pointer to callbacks
*/
void tcpci_emul_set_partner_ops(const struct emul *emul,
@@ -301,7 +340,7 @@ void tcpci_emul_set_partner_ops(const struct emul *emul,
/**
* @brief Emulate connection of specific device to emulated TCPCI
*
- * @param emul Pointer to TCPCI emulator
+ * @param emul Pointer to TCPC emulator
* @param partner_power_role Power role of connected partner (sink or source)
* @param partner_cc1 Voltage on partner CC1 line (usually Rd or Rp)
* @param partner_cc2 Voltage on partner CC2 line (usually open or Ra if active
@@ -321,7 +360,7 @@ int tcpci_emul_connect_partner(const struct emul *emul,
/** @brief Emulate the disconnection of the partner device to emulated TCPCI
*
- * @param emul Pointer to TCPCI emulator
+ * @param emul Pointer to TCPC emulator
*
* @return 0 on success
*/
@@ -330,13 +369,22 @@ int tcpci_emul_disconnect_partner(const struct emul *emul);
/**
* @brief Allows port partner to select if message was received correctly
*
- * @param emul Pointer to TCPCI emulator
+ * @param emul Pointer to TCPC emulator
* @param status Status of sended message
*/
void tcpci_emul_partner_msg_status(const struct emul *emul,
enum tcpci_emul_tx_status status);
/**
+ * @brief Gets the common data associated with the tcpci chip overall
+ *
+ * @param emul Pointer to TCPC emulator
+ * @return Pointer to struct i2c_common_emul_data
+ */
+struct i2c_common_emul_data *
+emul_tcpci_generic_get_i2c_common_data(const struct emul *emul);
+
+/**
* @}
*/