blob: df5817f32bfbe5e122b587e8d0cbfa4a4a1e1845 [file]
/* 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.
*/
/**
* @file drivers/pdc.h
* @brief Public APIs for Power Delivery Controller Chip drivers.
*
*/
#ifndef ZEPHYR_INCLUDE_DRIVERS_PDC_H_
#define ZEPHYR_INCLUDE_DRIVERS_PDC_H_
#include "ec_commands.h"
#include "power.h"
#include "ucsi_v3.h"
#include "usb_pd.h"
#include "usbc/utils.h"
#include <errno.h>
#include <zephyr/device.h>
#include <zephyr/drivers/i2c.h>
#include <zephyr/sys/slist.h>
#include <zephyr/types.h>
#ifdef __cplusplus
extern "C" {
#endif
#define PDC_VID_INVALID (0x0000)
#define PDC_PID_INVALID (0x0000)
/**
* Compare PDC versions
*/
#define PDC_FWVER_AT_LEAST(ver_in, major, minor) \
(PDC_FWVER_GET_MAJOR(ver_in) > (major) || \
(PDC_FWVER_GET_MAJOR(ver_in) == (major) && \
PDC_FWVER_GET_MINOR(ver_in) >= (minor)))
/**
* Extract the major, minor, and patch elements from a 32-bit version in
* `struct pdc_info_t`
*/
#define PDC_FWVER_GET_MAJOR(fwver) (((fwver) >> 16) & 0xFF)
#define PDC_FWVER_GET_MINOR(fwver) (((fwver) >> 8) & 0xFF)
#define PDC_FWVER_GET_PATCH(fwver) ((fwver) & 0xFF)
#define PDC_FWVER_INVALID (0xFFFFFFFF)
#define NODE_MATCHES(node1, node2) IS_EQ(DT_DEP_ORD(node1), DT_DEP_ORD(node2))
#define COMPARE_PDC_ARRAY_MEMBER(usbc_id, prop, idx, target) \
COND_CODE_1(NODE_MATCHES(DT_PROP_BY_IDX(usbc_id, prop, idx), target), \
(USBC_PORT_NEW(usbc_id)), ())
#define GET_USBC_PORT_IF_PDC_IN_LIST(usbc_id, target) \
DT_FOREACH_PROP_ELEM_VARGS(usbc_id, pdc, COMPARE_PDC_ARRAY_MEMBER, \
target)
/**
* @brief Given a devicetree node, return the USB-C port number that references
* the devicetree node.
*
* Usage:
* usbc_port0: port0@0 {
* compatible = "named-usbc-port";
* reg = < 0x0 >;
* chg = < &charger >;
* pdc = < &pdc_power_p0 >;
* };
* usbc_port1: port1@1 {
* compatible = "named-usbc-port";
* reg = < 0x1 >;
* pdc = < &pdc_power_p1 >;
* };
* &i2c{
* pdc_power_p1: driver@88 {
* compatible = "my-driver";
* }
* };
*
*
* @param target Devicetree node to search for
* @param prop named-usbc-port property to check
* @returns USB-C port number
*/
#define USBC_PORT_FROM_PDC_DRIVER_NODE(target) \
DT_FOREACH_STATUS_OKAY_VARGS(named_usbc_port, \
GET_USBC_PORT_IF_PDC_IN_LIST, target)
/**
* @brief Power Delivery Controller Information
*/
struct pdc_info_t {
/** Firmware version running on the PDC */
uint32_t fw_version;
/** Power Delivery Revision supported by the PDC */
uint16_t pd_revision;
/** Power Delivery Version supported by the PDC */
uint16_t pd_version;
/** VID of the PDC (optional) */
uint16_t vid;
/** PID of the PDC (optional) */
uint16_t pid;
/** Set to 1 if running from flash code (optional) */
uint8_t is_running_flash_code;
/** Set to the currently used flash bank (optional) */
uint8_t running_in_flash_bank;
/** 12-byte program name string plus NUL terminator */
char project_name[USB_PD_CHIP_INFO_PROJECT_NAME_LEN + 1];
/** Compat string of driver */
char driver_name[USB_PD_CHIP_INFO_DRIVER_NAME_LEN + 1];
/** If true, do not apply PDC FW updates to this port */
bool no_fw_update;
/** True if the PDC hardware supports FRS */
bool frs_supported;
/** True if the USB-C port is capable of USB communication as a device
*/
bool usb_comm_capable_as_device;
/** Extra information (optional) */
uint16_t extra;
};
/**
* Connector status changes that PDCs can report through vendor defined
* interfaces. These events are not supported by GET_CONNECTOR_STATUS.
*/
union vendor_status_change_bits_t {
struct {
/* Set to 1 when PDC reports receiving a PD Alert message */
uint32_t alert_received : 1;
uint32_t reserved : 31;
};
uint32_t raw_value;
};
/**
* The type of interface used to access the PDC
*/
enum pdc_bus_type {
PDC_BUS_TYPE_NONE = 0,
PDC_BUS_TYPE_I2C,
PDC_BUS_TYPE_MAX,
};
/**
* @brief Bus info for PDC chip. This gets exposed via host command to enable
* passthrough access to the PDC from AP during firmware updates.
*/
struct pdc_hw_config_t {
enum pdc_bus_type bus_type;
union {
struct i2c_dt_spec i2c;
};
bool ccd;
};
/**
* @brief Used for building CMD_PDC_GET_PDOS
*/
struct get_pdo_t {
enum pdo_type_t pdo_type;
enum pdo_source_t pdo_source;
uint8_t num_pdos;
enum pdo_offset_t pdo_offset;
/** flag to indicate retrieving pdo from PDC */
bool updating;
};
/**
* Used with pdc_get_sbu_mux_mode() / pdc_set_sbu_mux_mode()
*/
enum pdc_sbu_mux_mode {
/** SBU mux mode is invalid or unknown */
PDC_SBU_MUX_MODE_INVALID = -1,
/** The SBU mux behaves normally (switches to debug path when a debug
* accessory is attached, or connected to AP for alternate modes) */
PDC_SBU_MUX_MODE_NORMAL = 0,
/** The SBU mux is forced into the debug path unconditionally. Used when
* CCD must be kept alive. This is not cleared unless explicitly set
* back to PDC_SBU_MUX_MODE_NORMAL or the PDC reboots. */
PDC_SBU_MUX_MODE_FORCE_DBG,
PDC_SBU_MUX_MODE_MAX,
};
/**
* Used with pdc_set_pdr to describe the desired power policy / behavior
*/
enum pdc_power_policy {
/** Transition to or remain in the sink role, and allow external power
role swap requests */
PDC_POWER_POLICY_SINK_ALLOW_SWAP,
/** Transition to or remain in the sink role, and block external power
role swap requests */
PDC_POWER_POLICY_SINK_DISALLOW_SWAP,
/** Transition to or remain in the source role, and allow external power
role swap requests */
PDC_POWER_POLICY_SOURCE_ALLOW_SWAP,
/** Transition to or remain in the source role, and block external power
role swap requests */
PDC_POWER_POLICY_SOURCE_DISALLOW_SWAP,
};
/**
* Used to define device maximum source PDP
*/
enum max_pdp_t {
MAX_PDP_7_5W,
MAX_PDP_15W,
};
/** Helper macro to set the policy to sink and allow or disallow external swaps
* based on a boolean argument.
*/
#define PDC_POWER_POLICY_SINK(external_swap) \
((external_swap) ? PDC_POWER_POLICY_SINK_ALLOW_SWAP : \
PDC_POWER_POLICY_SINK_DISALLOW_SWAP)
/** Helper macro to set the policy to source and allow or disallow external
* swaps based on a boolean argument.
*/
#define PDC_POWER_POLICY_SOURCE(external_swap) \
((external_swap) ? PDC_POWER_POLICY_SOURCE_ALLOW_SWAP : \
PDC_POWER_POLICY_SOURCE_DISALLOW_SWAP)
struct pdc_callback;
/**
* @typedef
* @brief These are the API function types
*/
typedef void (*pdc_start_thread_t)(const struct device *dev);
typedef int (*pdc_get_ucsi_version_t)(const struct device *dev,
uint16_t *version);
typedef int (*pdc_reset_t)(const struct device *dev);
typedef int (*pdc_connector_reset_t)(const struct device *dev,
union connector_reset_t reset);
typedef int (*pdc_get_capability_t)(const struct device *dev,
struct capability_t *caps);
typedef int (*pdc_get_connector_capability_t)(
const struct device *dev, union connector_capability_t *caps);
typedef int (*pdc_set_ccom_t)(const struct device *dev, enum ccom_t ccom);
typedef int (*pdc_set_drp_mode_t)(const struct device *dev, enum drp_mode_t dm);
typedef int (*pdc_get_drp_mode_t)(const struct device *dev,
enum drp_mode_t *dm);
typedef int (*pdc_set_uor_t)(const struct device *dev, union uor_t uor);
typedef int (*pdc_set_pdr_t)(const struct device *dev, union pdr_t pdr);
typedef int (*pdc_set_sink_path_t)(const struct device *dev, bool en);
typedef int (*pdc_get_connector_status_t)(
const struct device *dev, union connector_status_t *connector_status);
typedef int (*pdc_get_error_status_t)(const struct device *dev,
union error_status_t *es);
typedef int (*pdc_set_handler_cb_t)(const struct device *dev,
struct pdc_callback *callback);
typedef void (*pdc_cci_cb_t)(const struct device *dev,
const struct pdc_callback *callback,
union cci_event_t cci_event);
typedef int (*pdc_get_vbus_t)(const struct device *dev, uint16_t *vbus);
typedef int (*pdc_get_pdos_t)(const struct device *dev,
enum pdo_type_t pdo_type,
enum pdo_offset_t pdo_offset, uint8_t num_pdos,
enum pdo_source_t source, uint32_t *pdos);
typedef int (*pdc_get_rdo_t)(const struct device *dev, uint32_t *rdo);
typedef int (*pdc_set_rdo_t)(const struct device *dev, uint32_t rdo);
typedef int (*pdc_get_info_t)(const struct device *dev, struct pdc_info_t *info,
bool live);
typedef int (*pdc_get_hw_config_t)(const struct device *dev,
struct pdc_hw_config_t *config);
typedef bool (*pdc_get_hw_frs_support_t)(const struct device *dev);
typedef int (*pdc_get_current_pdo_t)(const struct device *dev, uint32_t *pdo);
typedef int (*pdc_read_power_level_t)(const struct device *dev);
typedef int (*pdc_set_power_level_t)(const struct device *dev,
enum usb_typec_current_t tcc);
typedef int (*pdc_reconnect_t)(const struct device *dev);
typedef int (*pdc_update_retimer_fw_t)(const struct device *dev, bool enable);
typedef bool (*pdc_is_init_done_t)(const struct device *dev);
typedef int (*pdc_get_cable_property_t)(const struct device *dev,
union cable_property_t *cable_prop);
typedef int (*pdc_get_vdo_t)(const struct device *dev, union get_vdo_t req,
uint8_t *req_list, uint32_t *vdo);
typedef int (*pdc_get_identity_discovery_t)(const struct device *dev,
bool *disc_state);
typedef int (*pdc_set_comms_state_t)(const struct device *dev, bool active);
typedef int (*pdc_is_vconn_sourcing_t)(const struct device *dev,
bool *vconn_sourcing);
typedef int (*pdc_set_pdos_t)(const struct device *dev, enum pdo_type_t type,
uint32_t *pdo, int count);
typedef int (*pdc_get_pch_data_status_t)(const struct device *dev,
uint8_t port_num, uint8_t *status_reg);
typedef int (*pdc_execute_ucsi_cmd_t)(const struct device *dev,
uint8_t ucsi_command, uint8_t data_size,
uint8_t *command_specific,
uint8_t *lpm_data_out,
struct pdc_callback *callback);
typedef int (*pdc_manage_callback_t)(const struct device *dev,
struct pdc_callback *callback, bool set);
typedef int (*pdc_ack_cc_ci_t)(const struct device *dev,
union conn_status_change_bits_t ci, bool cc,
uint16_t vendor_defined);
typedef int (*pdc_get_lpm_ppm_info_t)(const struct device *dev,
struct lpm_ppm_info_t *info);
typedef int (*pdc_set_frs_t)(const struct device *dev, bool enable);
typedef int (*pdc_get_attention_vdo_t)(const struct device *dev,
union get_attention_vdo_t *vdo);
typedef int (*pdc_get_sbu_mux_mode_t)(const struct device *dev,
enum pdc_sbu_mux_mode *mode);
typedef int (*pdc_set_sbu_mux_mode_t)(const struct device *dev,
enum pdc_sbu_mux_mode mode);
typedef int (*pdc_set_ap_power_state_t)(const struct device *dev,
enum power_state state);
typedef int (*pdc_set_battery_capability_t)(const struct device *dev,
union battery_capability_t *bcap);
typedef int (*pdc_set_battery_status_t)(const struct device *dev,
union battery_status_t *bstat);
typedef int (*pdc_set_bbr_cts_t)(const struct device *dev, bool enable);
typedef int (*pdc_get_vendor_status_t)(
const struct device *dev,
union vendor_status_change_bits_t *vendor_status);
typedef int (*pdc_get_alert_t)(const struct device *dev, uint32_t *ado);
typedef int (*pdc_set_max_pdp_t)(const struct device *dev,
enum max_pdp_t max_pdp);
/**
* @cond INTERNAL_HIDDEN
*
* These are for internal use only, so skip these in public documentation.
*/
__subsystem struct pdc_driver_api {
pdc_start_thread_t start_thread;
pdc_is_init_done_t is_init_done;
pdc_get_ucsi_version_t get_ucsi_version;
pdc_reset_t reset;
pdc_connector_reset_t connector_reset;
pdc_get_capability_t get_capability;
pdc_get_connector_capability_t get_connector_capability;
pdc_set_ccom_t set_ccom;
pdc_set_drp_mode_t set_drp_mode;
pdc_get_drp_mode_t get_drp_mode;
pdc_set_uor_t set_uor;
pdc_set_pdr_t set_pdr;
pdc_set_sink_path_t set_sink_path;
pdc_get_connector_status_t get_connector_status;
pdc_get_error_status_t get_error_status;
pdc_set_handler_cb_t set_handler_cb;
pdc_get_vbus_t get_vbus_voltage;
pdc_get_current_pdo_t get_current_pdo;
pdc_get_pdos_t get_pdos;
pdc_get_rdo_t get_rdo;
pdc_set_rdo_t set_rdo;
pdc_read_power_level_t read_power_level;
pdc_get_info_t get_info;
pdc_get_hw_config_t get_hw_config;
pdc_get_hw_frs_support_t get_hw_frs_support;
pdc_set_power_level_t set_power_level;
pdc_reconnect_t reconnect;
pdc_update_retimer_fw_t update_retimer;
pdc_get_cable_property_t get_cable_property;
pdc_get_vdo_t get_vdo;
pdc_get_identity_discovery_t get_identity_discovery;
pdc_set_comms_state_t set_comms_state;
pdc_is_vconn_sourcing_t is_vconn_sourcing;
pdc_set_pdos_t set_pdos;
pdc_get_pch_data_status_t get_pch_data_status;
pdc_execute_ucsi_cmd_t execute_ucsi_cmd;
pdc_manage_callback_t manage_callback;
pdc_ack_cc_ci_t ack_cc_ci;
pdc_get_lpm_ppm_info_t get_lpm_ppm_info;
pdc_set_frs_t set_frs;
pdc_get_attention_vdo_t get_attention_vdo;
pdc_get_sbu_mux_mode_t get_sbu_mux_mode;
pdc_set_sbu_mux_mode_t set_sbu_mux_mode;
pdc_set_ap_power_state_t set_ap_power_state;
pdc_set_battery_capability_t set_battery_capability;
pdc_set_battery_status_t set_battery_status;
pdc_set_bbr_cts_t set_bbr_cts;
pdc_get_vendor_status_t get_vendor_status;
pdc_get_alert_t get_alert;
pdc_set_max_pdp_t set_max_pdp;
};
/**
* @endcond
*/
/**
* @brief Starts the PDC driver thread
*
* @param dev PDC device structure pointer
*/
static inline void pdc_start_thread(const struct device *dev)
{
__ASSERT(DEVICE_API_GET(pdc, dev)->start_thread != NULL,
"START_THREAD is not optional");
return DEVICE_API_GET(pdc, dev)->start_thread(dev);
}
/**
* @brief Tests if the PDC driver init process is complete
*
* @param dev PDC device structure pointer
*
* @retval true if PDC driver init process is complete, else false
*/
static inline bool pdc_is_init_done(const struct device *dev)
{
__ASSERT(DEVICE_API_GET(pdc, dev)->is_init_done != NULL,
"IS_INIT_DONE is not optional");
return DEVICE_API_GET(pdc, dev)->is_init_done(dev);
}
/**
* @brief Trigger the PDC to read the power level when in Source mode.
* @note CCI Events set
* busy: If PDC is Busy
* error: If the connector is in Sink Mode or is disconnected
* command_completed: power level in source mode ready
*
* @param dev PDC device structure pointer
*
* @retval 0 on API call success
* @retval -EBUSY if not ready to execute the command
*/
static inline int pdc_read_power_level(const struct device *dev)
{
__ASSERT(DEVICE_API_GET(pdc, dev)->read_power_level != NULL,
"READ_POWER_LEVEL is not optional");
return DEVICE_API_GET(pdc, dev)->read_power_level(dev);
}
/**
* @brief Read the version of the UCSI supported by the PDC. The version is
* read and cached during PDC initialization, so this call is
* synchronous and the version information is returned immediately
* to caller.
* @note CCI Events set
* <none>
*
* @param dev PDC device structure pointer
*
* @retval PDC Version number in BCD as an uint16. Format is JJMN, where (JJ –
* major version number, M – minor version number, N – sub-minor
* version number)
* @retval -EINVAL if caps is NULL
*/
static inline int pdc_get_ucsi_version(const struct device *dev,
uint16_t *version)
{
__ASSERT(DEVICE_API_GET(pdc, dev)->get_ucsi_version != NULL,
"GET_UCSI_VERSION is not optional");
return DEVICE_API_GET(pdc, dev)->get_ucsi_version(dev, version);
}
/**
* @brief Resets the PDC
* @note CCI Events set
* reset_completed: PDC has been reset
*
* @param dev PDC device structure pointer
*
* @retval 0 on API call success
* @retval -EBUSY if not ready to execute the command
*/
static inline int pdc_reset(const struct device *dev)
{
__ASSERT(DEVICE_API_GET(pdc, dev)->reset != NULL,
"RESET is not optional");
return DEVICE_API_GET(pdc, dev)->reset(dev);
}
/**
* @brief Resets a PDC connector
* @note CCI Events set
* busy: if PDC is busy
* error: command was unsuccessful
* command_commpleted: connector was reset
*
* @param dev PDC device structure pointer
*
* @retval 0 on success
* @retval -EBUSY if not ready to execute the command
*/
static inline int pdc_connector_reset(const struct device *dev,
union connector_reset_t reset)
{
__ASSERT(DEVICE_API_GET(pdc, dev)->connector_reset != NULL,
"CONNECTOR_RESET is not optional");
return DEVICE_API_GET(pdc, dev)->connector_reset(dev, reset);
}
/**
* @brief Set the Sink FET state while in the Attached Sink State
* @note CCI Events set
* busy: if PDC is busy
* error: command was unsuccessful
* command_commpleted: sink path was set
*
* @param dev PDC device structure pointer
* @param en true to enable the Sink FET or false to disable it
*
* @retval 0 on success
* @retval -EBUSY if not ready to execute the command
*/
static inline int pdc_set_sink_path(const struct device *dev, bool en)
{
__ASSERT(DEVICE_API_GET(pdc, dev)->set_sink_path != NULL,
"SET_SINK_PATH is not optional");
return DEVICE_API_GET(pdc, dev)->set_sink_path(dev, en);
}
/**
* @brief Gets the PDC device capabilities.
* @note CCI Events set
* busy: if PDC is busy
* error: command was unsuccessful
* command_commpleted: capability was retrieved
*
* @param dev PDC device structure pointer
* @param caps pointer where the device capabilities are stored.
*
* @retval 0 on success
* @retval -EBUSY if not ready to execute the command
* @retval -EINVAL if caps is NULL
*/
static inline int pdc_get_capability(const struct device *dev,
struct capability_t *caps)
{
__ASSERT(DEVICE_API_GET(pdc, dev)->get_capability != NULL,
"GET_CAPABILITY is not optional");
return DEVICE_API_GET(pdc, dev)->get_capability(dev, caps);
}
/**
* @brief Gets the PDC connector status.
* @note CCI Events set
* busy: if PDC is busy
* error: command was unsuccessful
* command_commpleted: connector status was retrieved
* @note cci_event.command_completed_indicator is set when the UCSI command
* completes.
* @note cci_event.error_indicator is set if the UCSI command was
* unsuccessful.
*
* @param dev PDC device structure pointer
* @param cs pointer where the connector status is stored.
*
* @retval 0 on success
* @retval -EBUSY if not ready to execute the command
* @retval -EINVAL if cs is NULL
*/
static inline int
pdc_get_connector_status(const struct device *dev,
union connector_status_t *connector_status)
{
__ASSERT(DEVICE_API_GET(pdc, dev)->get_connector_status != NULL,
"GET_CONNECTOR_STATUS is not optional");
return DEVICE_API_GET(pdc, dev)->get_connector_status(dev,
connector_status);
}
/**
* @brief Gets the details about an error, if the cci_event.error_indicator is
* set.
* @note CCI Events set
* busy: if PDC is busy
* error: command was unsuccessful
* command_commpleted: error status was retrieved
*
* @param dev PDC device structure pointer
* @param es pointer where the error status is stored.
*
* @retval 0 on success
* @retval -EBUSY if not ready to execute the command
* @retval -EINVAL if es is NULL
*/
static inline int pdc_get_error_status(const struct device *dev,
union error_status_t *es)
{
__ASSERT(DEVICE_API_GET(pdc, dev)->get_error_status != NULL,
"GET_ERROR_STATUS is not optional");
return DEVICE_API_GET(pdc, dev)->get_error_status(dev, es);
}
/**
* @brief Gets capabilities of a connector
* @note CCI Events set
* busy: if PDC is busy
* error: command was unsuccessful
* command_commpleted: connector caps were retrieved
*
* @param dev PDC device structure pointer
* @param caps pointer where the connector capabilities are stored.
*
* @retval 0 on success
* @retval -EBUSY if not ready to execute the command
* @retval -EINVAL if caps is NULL
*/
static inline int
pdc_get_connector_capability(const struct device *dev,
union connector_capability_t *caps)
{
__ASSERT(DEVICE_API_GET(pdc, dev)->get_connector_capability != NULL,
"GET_CONNECTOR_CAPABILITY is not optional");
return DEVICE_API_GET(pdc, dev)->get_connector_capability(dev, caps);
}
/**
* @brief Sets the CC operation mode of the PDC
* @note CCI Events set
* busy: if PDC is busy
* error: command was unsuccessful
* command_commpleted: CCOM was set
*
* @param dev PDC device structure pointer
* @param ccom CC operation mode
*
* @retval 0 on success
* @retval -EBUSY if not ready to execute the command
* @retval -ENOSYS if not implemented
*/
static inline int pdc_set_ccom(const struct device *dev, enum ccom_t ccom)
{
/* This is an optional feature, so it might not be implemented */
if (DEVICE_API_GET(pdc, dev)->set_ccom == NULL) {
return -ENOSYS;
}
return DEVICE_API_GET(pdc, dev)->set_ccom(dev, ccom);
}
/**
* @brief Sets the DRP mode of the PDC
* @note CCI Events set
* busy: if PDC is busy
* error: command was unsuccessful
* command_commpleted: DRP mode was set
*
* @param dev PDC device structure pointer
* @param dm DRP mode
*
* @retval 0 on success
* @retval -EBUSY if not ready to execute the command
* @retval -ENOSYS if not implemented
*/
static inline int pdc_set_drp_mode(const struct device *dev, enum drp_mode_t dm)
{
/* This is an optional feature, so it might not be implemented */
if (DEVICE_API_GET(pdc, dev)->set_drp_mode == NULL) {
return -ENOSYS;
}
return DEVICE_API_GET(pdc, dev)->set_drp_mode(dev, dm);
}
static inline int pdc_get_drp_mode(const struct device *dev,
enum drp_mode_t *dm)
{
/* This is an optional feature, so it might not be implemented */
if (DEVICE_API_GET(pdc, dev)->get_drp_mode == NULL) {
return -ENOSYS;
}
return DEVICE_API_GET(pdc, dev)->get_drp_mode(dev, dm);
}
/**
* @brief Sets the USB operation role of the PDC
* @note CCI Events set
* busy: if the PDC is busy
* error: command was unsuccessful
* command_commpleted: UOR was set
*
* @param dev PDC device structure pointer
* @param uor USB operation role
*
* @retval 0 on success
* @retval -EBUSY if not ready to execute the command
*/
static inline int pdc_set_uor(const struct device *dev, union uor_t uor)
{
__ASSERT(DEVICE_API_GET(pdc, dev)->set_uor != NULL,
"SET_UOR is not optional");
return DEVICE_API_GET(pdc, dev)->set_uor(dev, uor);
}
/**
* @brief Sets the Power direction role of the PDC
* @note CCI Events set
* busy: if PDC is busy
* error: command was unsuccessful
* command_commpleted: PDR was set
*
* @param dev PDC device structure pointer
* @param pdr Power direction role
*
* @retval 0 on success
* @retval -EBUSY if not ready to execute the command
* @retval -EINVAL if \p policy is invalid
*/
static inline int pdc_set_pdr(const struct device *dev,
enum pdc_power_policy policy)
{
union pdr_t pdr = { 0 };
__ASSERT(DEVICE_API_GET(pdc, dev)->set_pdr != NULL,
"SET_PDR is not optional");
switch (policy) {
case PDC_POWER_POLICY_SINK_ALLOW_SWAP:
pdr.swap_to_src = 0;
pdr.swap_to_snk = 1;
pdr.accept_pr_swap = 1;
break;
case PDC_POWER_POLICY_SINK_DISALLOW_SWAP:
pdr.swap_to_src = 0;
pdr.swap_to_snk = 1;
pdr.accept_pr_swap = 0;
break;
case PDC_POWER_POLICY_SOURCE_ALLOW_SWAP:
pdr.swap_to_src = 1;
pdr.swap_to_snk = 0;
pdr.accept_pr_swap = 1;
break;
case PDC_POWER_POLICY_SOURCE_DISALLOW_SWAP:
pdr.swap_to_src = 1;
pdr.swap_to_snk = 0;
pdr.accept_pr_swap = 0;
break;
default:
return -EINVAL;
}
return DEVICE_API_GET(pdc, dev)->set_pdr(dev, pdr);
}
/**
* @brief Sets the callback the driver uses to communicate CC events to the
* TCPM.
* @note CCI Events set
* <none>
*
* @param dev PDC device structure pointer
* @param callback Pointer to callback
*/
static inline void pdc_set_cc_callback(const struct device *dev,
struct pdc_callback *callback)
{
__ASSERT(DEVICE_API_GET(pdc, dev)->set_handler_cb != NULL,
"SET_HANDLER_CB is not optional");
DEVICE_API_GET(pdc, dev)->set_handler_cb(dev, callback);
}
/**
* @brief Reads the VBUS voltage
* @note CCI Events set
* busy: if PDC is busy
* error: if port isn't connected
* command_commpleted: VBUS voltage was read
*
* @param dev PDC device structure pointer
* @param voltage pointer to where the voltage is stored
*
* @retval 0 on success
* @retval -EBUSY if not ready to execute the command
* @retval -EINVAL if voltage pointer is NULL
*/
static inline int pdc_get_vbus_voltage(const struct device *dev,
uint16_t *voltage)
{
__ASSERT(DEVICE_API_GET(pdc, dev)->get_vbus_voltage != NULL,
"GET_VBUS_VOLTAGE is not optional");
return DEVICE_API_GET(pdc, dev)->get_vbus_voltage(dev, voltage);
}
/**
* @brief Gets the Sink or Source PDOs associated with the connector
* @note CCI Events set
* busy: if the PDC is busy
* error: the Port is not PD connected
* command_commpleted: PDOs have been retrieved
*
* @param dev PDC device structure pointer
* @param pdo_type Whether to retrieve source or sink PDOs
* @param pdo_offset starting offset of the first PDO to be returned. Valid
* values are 0 to 7.
* @param num_pdos number of PDOs to return starting from the PDO offset. NOTE:
* the number of PDOs returned is num + 1. Max is UCSI_GET_PDOS_MAX_NUM.
* @param source Whether to retrieve the LPM's (PDC) or port partner's PDOs.
* @param pdos pointer to where the PDOs are outputted to.
*
* @retval 0 on success
* @retval -EBUSY if not ready to execute the command
* @retval -EINVAL if pdos is NULL
* @retval -ENOSYS if not implemented
*/
static inline int pdc_get_pdos(const struct device *dev,
enum pdo_type_t pdo_type,
enum pdo_offset_t pdo_offset, uint8_t num_pdos,
enum pdo_source_t source, uint32_t *pdos)
{
/* This is an optional feature, so it might not be implemented */
if (DEVICE_API_GET(pdc, dev)->get_pdos == NULL) {
return -ENOSYS;
}
__ASSERT(num_pdos <= UCSI_GET_PDOS_MAX_NUM,
"GET_PDOS supports a maximum count of " STRINGIFY(
UCSI_GET_PDOS_MAX_NUM) " PDOs");
return DEVICE_API_GET(pdc, dev)->get_pdos(dev, pdo_type, pdo_offset,
num_pdos, source, pdos);
}
/**
* @brief Get information about the PDC
* @note CCI Events set
* busy: if PDC is busy
* error: if the the info could not be retrieved
* command_completed: if the info was received
*
* @param dev PDC device structure pointer
* @param info pointer to where the PDC information is stored
* @param live If true, force a read from chip. Else used cached version.
*
* @retval 0 on success
* @retval -EBUSY if not ready to execute the command
* @retval -EINVAL if fw_version pointers is NULL
*/
static inline int pdc_get_info(const struct device *dev,
struct pdc_info_t *info, bool live)
{
__ASSERT(DEVICE_API_GET(pdc, dev)->get_info != NULL,
"GET_INFO is not optional");
return DEVICE_API_GET(pdc, dev)->get_info(dev, info, live);
}
/**
* @brief Get bus interface hw config about the PDC
*
* @param dev PDC device structure pointer
* @param config Output struct for hw config
*
* @retval 0 on success
* @retval -EINVAL if info pointer is NULL
*/
static inline int pdc_get_hw_config(const struct device *dev,
struct pdc_hw_config_t *config)
{
__ASSERT(DEVICE_API_GET(pdc, dev)->get_hw_config != NULL,
"GET_HW_CONFIG is not optional");
return DEVICE_API_GET(pdc, dev)->get_hw_config(dev, config);
}
/**
* @brief Get the Requested Data Object sent to the Source
* @note CCI Events set
* busy: if PDC is busy
* error: if the port partner is a Sink
* command_commpleted: if the RDO was retrieved
*
* @param dev PDC device structure pointer
* @param rdo pointer to where the RDO is stored
*
* @retval 0 on success
* @retval -EBUSY if not ready to execute the command
* @retval -EINVAL if rdo pointer is NULL
*/
static inline int pdc_get_rdo(const struct device *dev, uint32_t *rdo)
{
__ASSERT(DEVICE_API_GET(pdc, dev)->get_rdo != NULL,
"GET_RDO is not optional");
return DEVICE_API_GET(pdc, dev)->get_rdo(dev, rdo);
}
/**
* @brief Sends a Requested Data Object to the attached Source
* @note CCI Events set
* busy: if the PDC is busy
* error: if the port partner is a Sink
* command_commpleted: RDO was sent to port partner
*
* @param dev PDC device structure pointer
* @param rdo RDO to send to the Source
*
* @retval 0 on success
* @retval -EBUSY if not ready to execute the command
*/
static inline int pdc_set_rdo(const struct device *dev, uint32_t rdo)
{
__ASSERT(DEVICE_API_GET(pdc, dev)->set_rdo != NULL,
"SET_RDO is not optional");
return DEVICE_API_GET(pdc, dev)->set_rdo(dev, rdo);
}
/**
* @brief Get the currently selected PDO that was requested from the Source
* @note CCI Events set
* busy: if the PDC is busy
* error: if the port isn't PD connected, or port partner is a Sink
* command_commpleted: PDO has been retrieved
*
* @param dev PDC device structure pointer
* @param pdo pointer to where the PDO is stored
*
* @retval 0 on success
* @retval -EBUSY if not ready to execute the command
* @retval -EINVAL if pdo pointer is NULL
* @retval -ENOSYS if not implemented
*/
static inline int pdc_get_current_pdo(const struct device *dev, uint32_t *pdo)
{
/* This is an optional feature, so it might not be implemented */
if (DEVICE_API_GET(pdc, dev)->get_current_pdo == NULL) {
return -ENOSYS;
}
return DEVICE_API_GET(pdc, dev)->get_current_pdo(dev, pdo);
}
/**
* @brief Sets the TypeC Rp current resistor.
* @note This command isn't compliant with the UCSI spec
* @note CCI Events set
* busy: if the PDC is busy
* error: if the command couldn't be executed
* command_commpleted: the Rp was set
*
* @retval 0 on success
* @retval -EBUSY if not ready to execute the command
* @retval -EINVAL if tcc is set to TC_CURRENT_PPM_DEFINED
* @retval -ENOSYS if not implemented
*/
static inline int pdc_set_power_level(const struct device *dev,
enum usb_typec_current_t tcc)
{
/* This is an optional feature, so it might not be implemented */
if (DEVICE_API_GET(pdc, dev)->set_power_level == NULL) {
return -ENOSYS;
}
return DEVICE_API_GET(pdc, dev)->set_power_level(dev, tcc);
}
/**
* @brief Perform a Type-C reconnect
* @note CCI Events set
* busy: if PDC is busy
* error: if port isn't connected
* command_commpleted: if the port has reconnected
*
* @param dev PDC device structure pointer
*
* @retval 0 on API call success
* @retval -EIO on failure
* @retval -ENOSYS if not implemented
*/
static inline int pdc_reconnect(const struct device *dev)
{
/* This is an optional feature, so it might not be implemented */
if (DEVICE_API_GET(pdc, dev)->reconnect == NULL) {
return -ENOSYS;
}
return DEVICE_API_GET(pdc, dev)->reconnect(dev);
}
/**
* @brief Command PD chip to enter retimer firmware update mode.
*
* @param enable True->enter, False->exit retimer firmware update mode.
*
* @retval 0 if success or I2C error.
* @retval -EIO if input/output error.
* @retval -ENOSYS if API not implemented.
*/
static inline int pdc_update_retimer_fw(const struct device *dev, bool enable)
{
/* Temporarily optional feature, so it might not be implemented */
if (DEVICE_API_GET(pdc, dev)->update_retimer == NULL) {
return -ENOSYS;
}
return DEVICE_API_GET(pdc, dev)->update_retimer(dev, enable);
}
/**
* @brief Command to get the PDC PCH DATA STATUS REG value.
*
* @param enable True->enter, False->exit get pch data status.
*
* @retval 0 if success.
* @retval -EIO if input/output error.
* @retval -ENOSYS if API not implemented.
*/
static inline int pdc_get_pch_data_status(const struct device *dev,
uint8_t port_num, uint8_t *status_reg)
{
/* Temporarily optional feature, so it might not be implemented */
if (DEVICE_API_GET(pdc, dev)->get_pch_data_status == NULL) {
return -ENOSYS;
}
return DEVICE_API_GET(pdc, dev)->get_pch_data_status(dev, port_num,
status_reg);
}
/**
* @brief Gets the attached cable properties
* @note CCI Events set
* busy: if PDC is busy
* error: treated as non-emarker cable
* command_commpleted: capability was retrieved
*
* @param dev PDC device structure pointer
* @param cable_prop pointer where the cable properties are stored
*
* @retval 0 on success
* @retval -EBUSY if not ready to execute the command
* @retval -EINVAL if caps is NULL
*/
static inline int pdc_get_cable_property(const struct device *dev,
union cable_property_t *cable_prop)
{
__ASSERT(DEVICE_API_GET(pdc, dev)->get_cable_property != NULL,
"GET_CABLE_PROPERTY is not optional");
return DEVICE_API_GET(pdc, dev)->get_cable_property(dev, cable_prop);
}
/**
* @brief Get the Requested VDO objects
* @note CCI Events set
* busy: if PDC is busy
* error:
* command_commpleted: if the VDOs were retrieved
*
* @param dev PDC device structure pointer
* @param vdo pointer to where the VDOs are stored
*
* @retval 0 on success
* @retval -EBUSY if not ready to execute the command
* @retval -EINVAL if vdo pointer is NULL
*/
static inline int pdc_get_vdo(const struct device *dev, union get_vdo_t vdo_req,
uint8_t *vdo_list, uint32_t *vdo)
{
__ASSERT(DEVICE_API_GET(pdc, dev)->get_vdo != NULL,
"GET_VDO is not optional");
return DEVICE_API_GET(pdc, dev)->get_vdo(dev, vdo_req, vdo_list, vdo);
}
/**
* @brief get the state of the discovery process
*
* @param dev PDC device structure pointer
* @param disc_state pointer where the discovery state is stored. True if
* discovery is complete, else False
*
* @retval 0 on success
* @retval -ENOSYS if not implemented
* @retval -EINVAL if disc_state is NULL
*/
static inline int pdc_get_identity_discovery(const struct device *dev,
bool *disc_state)
{
if (DEVICE_API_GET(pdc, dev)->get_identity_discovery == NULL) {
return -ENOSYS;
}
return DEVICE_API_GET(pdc, dev)->get_identity_discovery(dev,
disc_state);
}
/**
* @brief Control if the driver can communicate with the PDC.
*
* @param dev PDC device structure pointer
* @param comms_active True to allow PDC communication, false to end
* communication
*
* @retval 0 if success
*/
static inline int pdc_set_comms_state(const struct device *dev,
bool comms_active)
{
__ASSERT(DEVICE_API_GET(pdc, dev)->set_comms_state != NULL,
"set_comms_state is not optional");
return DEVICE_API_GET(pdc, dev)->set_comms_state(dev, comms_active);
}
/**
* @brief Sends a Power Data Object to the PDC
* @note CCI Events set
* busy: if the PDC is busy
* command_commpleted: PDO was sent to LPM or port partner
*
* @param dev PDC device structure pointer
* @param type SINK_PDO or SOURCE_PDO
* @param pdo Pointer to PDO array
* @param count Number of PDOs to send
*
* @retval 0 on success
* @retval -EBUSY if not ready to execute the command
* @retval -ERANGE if the count is not supported
* @retval -EINVAL if \p pdo is NULL
*/
static inline int pdc_set_pdos(const struct device *dev, enum pdo_type_t type,
uint32_t *pdo, int count)
{
if (DEVICE_API_GET(pdc, dev)->set_pdos == NULL) {
return -ENOSYS;
}
return DEVICE_API_GET(pdc, dev)->set_pdos(dev, type, pdo, count);
}
/**
* @brief Checks if the port is sourcing VCONN
*
* @param dev PDC device structure pointer
* @param vconn_sourcing True if the port is sourcing VCONN, else false
*
* @retval 0 if success
* @retval -ENOSYS if not implemented
* @retval -EINVAL if vconn_sourcing is NULL
*/
static inline int pdc_is_vconn_sourcing(const struct device *dev,
bool *vconn_sourcing)
{
if (DEVICE_API_GET(pdc, dev)->is_vconn_sourcing == NULL) {
return -ENOSYS;
}
return DEVICE_API_GET(pdc, dev)->is_vconn_sourcing(dev, vconn_sourcing);
}
/**
* @brief Acknowledge command complete (cc) or change indicator (ci)
* @note CCI Events set
* busy: if the PDC is busy
* error: if command fails
* command_commpleted: ack_cc_ci write successful
*
* @param dev PDC device structure pointer
* @param ci Change Indicator bits
* @param cc Complete complete bit
* @param vendor_defined Vendor specified change indicator bits
*
* @retval 0 on success
* @retval -EBUSY if not ready to execute the command
*/
static inline int pdc_ack_cc_ci(const struct device *dev,
union conn_status_change_bits_t ci, bool cc,
uint16_t vendor_defined)
{
if (DEVICE_API_GET(pdc, dev)->ack_cc_ci == NULL) {
return -ENOSYS;
}
return DEVICE_API_GET(pdc, dev)->ack_cc_ci(dev, ci, cc, vendor_defined);
}
/**
* @brief PDC message type or chip type identifiers. These are 8-bit
* values.
*/
enum pdc_trace_chip_type {
PDC_TRACE_CHIP_TYPE_UNSPEC = 0,
PDC_TRACE_CHIP_TYPE_RTS54XX = 0x54,
};
/**
* @brief Log outgoing PDC message for tracing
*
* @param port Type-C port number
* @param msg_type Message type (hint how to interpret message)
* @param buf Message to log
* @param count Message length
*
* @retval true IFF pushed into FIFO
*/
bool pdc_trace_msg_req(int port, enum pdc_trace_chip_type msg_type,
const uint8_t *buf, const int count);
/**
* @brief Log incoming PDC message for tracing
*
* @param port Type-C port number
* @param msg_type Message type (hint how to interpret message)
* @param buf Message to log
* @param count Message length
*
* @retval true IFF pushed into FIFO
*/
bool pdc_trace_msg_resp(int port, enum pdc_trace_chip_type msg_type,
const uint8_t *buf, const int count);
/**
* @brief Execute UCSI command synchronously
*
* @param dev PDC device structure pointer
* @param ucsi_command UCSI command
* @param data_size Size of the command specific data.
* @param command_specific Command specific data to be sent
* @param lpm_data_out Buffer to receive data returned from a PDC
*
* @return 0 on success
* @return -EBUSY if PDC is busy with serving another request.
* @return -ECONNREFUSED if PDC is suspended.
* @retval -ENOSYS if not implemented
* @return -ETIMEDOUT if timer expires while waiting for write or read operation
* to finish.
*/
static inline int pdc_execute_ucsi_cmd(const struct device *dev,
uint8_t ucsi_command, uint8_t data_size,
uint8_t *command_specific,
uint8_t *lpm_data_out,
struct pdc_callback *callback)
{
if (DEVICE_API_GET(pdc, dev)->execute_ucsi_cmd == NULL) {
return -ENOSYS;
}
return DEVICE_API_GET(pdc, dev)->execute_ucsi_cmd(
dev, ucsi_command, data_size, command_specific, lpm_data_out,
callback);
}
/**
* @brief Add callback for connector change events.
*
* @param dev PDC device structure pointer
* @param callback Callback handler and data
*
* @return 0 on success
* @return -ENOSYS if not implemented
* @return -EINVAL for other errors
*/
static inline int pdc_add_ci_callback(const struct device *dev,
struct pdc_callback *callback)
{
if (DEVICE_API_GET(pdc, dev)->manage_callback == NULL) {
return -ENOSYS;
}
return DEVICE_API_GET(pdc, dev)->manage_callback(dev, callback, true);
}
/**
* @brief Query UCSI LPM PPM info
*
* @param dev PDC device structure pointer
* @param info Caller-provided output struct for received data
*
* @return 0 on success
* @return -ENOSYS if not implemented
* @return -EINVAL for other errors
*/
static inline int pdc_get_lpm_ppm_info(const struct device *dev,
struct lpm_ppm_info_t *info)
{
if (DEVICE_API_GET(pdc, dev)->get_lpm_ppm_info == NULL) {
return -ENOSYS;
}
return DEVICE_API_GET(pdc, dev)->get_lpm_ppm_info(dev, info);
}
/**
* @typedef pdc_callback_handler_t
* @brief Define the application callback handler function signature
*
* @param port Device struct for the PDC device.
* @param cb Original struct pdc_callback owning this handler
* @param pins Mask of pins that triggers the callback handler
*
* Note: cb pointer can be used to retrieve private data through
* CONTAINER_OF() if original struct pdc_callback is stored in
* another private structure.
*/
typedef void (*pdc_callback_handler_t)(const struct device *port,
struct pdc_callback *cb,
union cci_event_t cci_event);
/**
* @brief PDC callback structure
*
* Used to register a callback in the driver instance callback list.
* As many callbacks as needed can be added as long as each of them
* are unique pointers of struct pdc_callback.
* Beware such structure should not be allocated on stack.
*/
struct pdc_callback {
/** This is meant to be used in the driver and the user should not
* mess with it.
*/
sys_snode_t node;
/** Actual callback function being called when relevant. */
pdc_cci_cb_t handler;
};
/**
* @brief Generic function to append or remove a callback from a callback list
* @note This should only be called by PDC drivers and not the user.
*
* @param callbacks A pointer to the original list of callbacks (can be NULL)
* @param callback A pointer of the callback to append or remove from the list
* @param set A boolean indicating insertion or removal of the callback
*
* @return 0 on success, negative errno otherwise.
*/
static inline int pdc_manage_callbacks(sys_slist_t *callbacks,
struct pdc_callback *callback, bool set)
{
__ASSERT(callback, "No callback!");
__ASSERT(callback->handler, "No callback handler!");
if (!sys_slist_is_empty(callbacks)) {
if (!sys_slist_find_and_remove(callbacks, &callback->node)) {
if (!set) {
return -EINVAL;
}
}
} else if (!set) {
return -EINVAL;
}
if (set) {
sys_slist_append(callbacks, &callback->node);
}
return 0;
}
/**
* @brief Generic function to go through and fire callback from a callback list
* @note This should only be called by PDC drivers and not the user.
*
* @param list A pointer on the gpio callback list
* @param dev A pointer to the PDC device instance
* @param cci_event The actual CCI event mask that triggered the interrupt
*/
static inline void pdc_fire_callbacks(sys_slist_t *list,
const struct device *dev,
union cci_event_t cci_event)
{
struct pdc_callback *cb, *tmp;
SYS_SLIST_FOR_EACH_CONTAINER_SAFE(list, cb, tmp, node)
{
__ASSERT(cb->handler, "No callback handler!");
cb->handler(dev, cb, cci_event);
}
}
/**
* @brief Enable or disable fast role swap (FRS).
*
* @param dev Pointer to the PDC device instance
* @param enable Set to true to enable FRS, set to false to disable FRS
* @return 0 on success, negative errno otherwise
*/
static inline int pdc_set_frs(const struct device *dev, bool enable)
{
if (DEVICE_API_GET(pdc, dev)->set_frs == NULL) {
return -ENOSYS;
}
return DEVICE_API_GET(pdc, dev)->set_frs(dev, enable);
}
/**
* @brief Get whether or not the PDC supports FRS.
*
* @param dev Pointer to the PDC device instance
* @param config Pointer to the PDC hardware configuration structure
* @return true if the PDC supports FRS, false otherwise.
*/
static inline bool pdc_get_frs_supported(const struct device *dev)
{
__ASSERT(DEVICE_API_GET(pdc, dev)->get_hw_frs_support != NULL,
"GET_FRS_SUPPORTED is not optional");
return DEVICE_API_GET(pdc, dev)->get_hw_frs_support(dev);
}
/**
* @brief UCSI command to request an Attention VDO received from the partner
* @param dev PDC device structure pointer
* @param get_attention_vdo_t pointer where the GET_ATTENTION_VDO response is
* stored.
* @return 0 on success, negative errno otherwise
*/
static inline int pdc_get_attention_vdo(const struct device *dev,
union get_attention_vdo_t *vdo)
{
if (DEVICE_API_GET(pdc, dev)->get_attention_vdo == NULL) {
return -ENOSYS;
}
return DEVICE_API_GET(pdc, dev)->get_attention_vdo(dev, vdo);
}
/**
* @brief Vendor command to query current SBU mux operational mode
* @param dev PDC device structure pointer
* @param mode Output pointer for current mode to be written to
* @return 0 on success, or negative error code
*/
static inline int pdc_get_sbu_mux_mode(const struct device *dev,
enum pdc_sbu_mux_mode *mode)
{
if (DEVICE_API_GET(pdc, dev)->get_sbu_mux_mode == NULL) {
return -ENOSYS;
}
return DEVICE_API_GET(pdc, dev)->get_sbu_mux_mode(dev, mode);
}
/**
* @brief Vendor command to set the SBU mux operational mode
* @param dev PDC device structure pointer
* @param mode Mode to set the SBU mux to
* @return 0 on success, or negative error code
*/
static inline int pdc_set_sbu_mux_mode(const struct device *dev,
enum pdc_sbu_mux_mode mode)
{
if (mode < 0 || mode >= PDC_SBU_MUX_MODE_MAX) {
return -EINVAL;
}
if (DEVICE_API_GET(pdc, dev)->set_sbu_mux_mode == NULL) {
return -ENOSYS;
}
return DEVICE_API_GET(pdc, dev)->set_sbu_mux_mode(dev, mode);
}
/**
* @brief Notify the PDC of the current AP power state
*
* @param dev Pointer to the PDC device instance
* @param power_state New AP power state
* @return 0 on success, negative errno otherwise
*/
static inline int pdc_set_ap_power_state(const struct device *dev,
enum power_state state)
{
if (DEVICE_API_GET(pdc, dev)->set_ap_power_state == NULL) {
return -ENOSYS;
}
return DEVICE_API_GET(pdc, dev)->set_ap_power_state(dev, state);
}
/**
* @brief Set the battery capability response on PDC.
*
* @param dev Pointer to the PDC device instance
* @param bcap Battery capability
* @return 0 on success, negative errno otherwise
*/
static inline int pdc_set_battery_capability(const struct device *dev,
union battery_capability_t *bcap)
{
if (DEVICE_API_GET(pdc, dev)->set_battery_capability == NULL) {
return -ENOSYS;
}
return DEVICE_API_GET(pdc, dev)->set_battery_capability(dev, bcap);
}
/**
* @brief Set the battery status response on PDC.
*
* @param dev Pointer to the PDC device instance
* @param bstat Battery status
* @return 0 on success, negative errno otherwise
*/
static inline int pdc_set_battery_status(const struct device *dev,
union battery_status_t *bstat)
{
if (DEVICE_API_GET(pdc, dev)->set_battery_status == NULL) {
return -ENOSYS;
}
return DEVICE_API_GET(pdc, dev)->set_battery_status(dev, bstat);
}
/**
* @brief Configure PDC for BBR compliance test
*
* @param dev PDC device structure pointer
* @param enable Enable or disable BBR test mode
*
* @retval 0 on success
* @retval -ENOSYS if not implemented
*/
static inline int pdc_set_bbr_cts(const struct device *dev, bool enable)
{
if (DEVICE_API_GET(pdc, dev)->set_bbr_cts == NULL) {
return -ENOSYS;
}
return DEVICE_API_GET(pdc, dev)->set_bbr_cts(dev, enable);
}
static inline int
pdc_get_vendor_status(const struct device *dev,
union vendor_status_change_bits_t *vendor_status)
{
/* This is an optional feature, so it might not be implemented */
if (DEVICE_API_GET(pdc, dev)->get_vendor_status == NULL) {
return -ENOSYS;
}
return DEVICE_API_GET(pdc, dev)->get_vendor_status(dev, vendor_status);
}
static inline int pdc_get_alert(const struct device *dev, uint32_t *ado)
{
/* This is an optional feature, so it might not be implemented */
if (DEVICE_API_GET(pdc, dev)->get_alert == NULL) {
return -ENOSYS;
}
return DEVICE_API_GET(pdc, dev)->get_alert(dev, ado);
}
static inline int pdc_set_max_pdp(const struct device *dev,
enum max_pdp_t max_pdp)
{
const struct pdc_driver_api *api =
(const struct pdc_driver_api *)dev->api;
if (api->set_max_pdp == NULL) {
return -ENOSYS;
}
return api->set_max_pdp(dev, max_pdp);
}
#ifdef __cplusplus
}
#endif
/**
* @}
*/
#endif /* ZEPHYR_INCLUDE_DRIVERS_PDC_H_ */