drivers: usb_c: tcpc: stm32: Add VCONN functionality
Add VCONN discharge functionality to TCPC and driver Signed-off-by: Sam Hurst <sbh1187@gmail.com>
This commit is contained in:
parent
a19cf99aa3
commit
77e1638c3c
4 changed files with 130 additions and 2 deletions
|
@ -156,10 +156,15 @@ static uint32_t ucpd_get_cc_enable_mask(const struct device *dev)
|
|||
const struct tcpc_config *const config = dev->config;
|
||||
uint32_t mask = UCPD_CR_CCENABLE_Msk;
|
||||
|
||||
/*
|
||||
* When VCONN is enabled, it is supplied on the CC line that's
|
||||
* not being used for Power Delivery messages.
|
||||
*/
|
||||
if (data->ucpd_vconn_enable) {
|
||||
uint32_t cr = LL_UCPD_ReadReg(config->ucpd_port, CR);
|
||||
int pol = (cr & UCPD_CR_PHYCCSEL);
|
||||
|
||||
/* Dissable CC line that's used for VCONN */
|
||||
mask &= ~BIT(UCPD_CR_CCENABLE_Pos + !pol);
|
||||
}
|
||||
|
||||
|
@ -281,12 +286,52 @@ static int ucpd_set_vconn(const struct device *dev, bool enable)
|
|||
update_stm32g0x_cc_line(config->ucpd_port);
|
||||
#endif
|
||||
|
||||
/* Get CC line that VCONN is active on */
|
||||
data->ucpd_vconn_cc = (cr & UCPD_CR_CCENABLE_0) ?
|
||||
TC_POLARITY_CC2 : TC_POLARITY_CC1;
|
||||
|
||||
/* Call user supplied callback to set vconn */
|
||||
ret = data->vconn_cb(dev, enable);
|
||||
ret = data->vconn_cb(dev, data->ucpd_vconn_cc, enable);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Discharge VCONN
|
||||
*
|
||||
* @retval 0 on success
|
||||
* @retval -EIO on failure
|
||||
* @retval -ENOTSUP if not supported
|
||||
*/
|
||||
static int ucpd_vconn_discharge(const struct device *dev, bool enable)
|
||||
{
|
||||
struct tcpc_data *data = dev->data;
|
||||
const struct tcpc_config *const config = dev->config;
|
||||
|
||||
/* VCONN should not be discharged while it's enabled */
|
||||
if (data->ucpd_vconn_enable) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (data->vconn_discharge_cb) {
|
||||
/* Use DPM supplied VCONN Discharge */
|
||||
return data->vconn_discharge_cb(dev, data->ucpd_vconn_cc, enable);
|
||||
}
|
||||
|
||||
/* Use TCPC VCONN Discharge */
|
||||
if (enable) {
|
||||
LL_UCPD_VconnDischargeEnable(config->ucpd_port);
|
||||
} else {
|
||||
LL_UCPD_VconnDischargeDisable(config->ucpd_port);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SOC_SERIES_STM32G0X
|
||||
update_stm32g0x_cc_line(config->ucpd_port);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the value of the CC pull up resistor used when operating as a Source
|
||||
*
|
||||
|
@ -1236,6 +1281,20 @@ static void ucpd_set_vconn_cb(const struct device *dev,
|
|||
data->vconn_cb = vconn_cb;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets a callback that can discharge VCONN if the TCPC is
|
||||
* unable to or the system is configured in a way that does not use
|
||||
* the VCONN discharge capabilities of the TCPC
|
||||
*
|
||||
*/
|
||||
static void ucpd_set_vconn_discharge_cb(const struct device *dev,
|
||||
tcpc_vconn_discharge_cb_t cb)
|
||||
{
|
||||
struct tcpc_data *data = dev->data;
|
||||
|
||||
data->vconn_discharge_cb = cb;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief UCPD interrupt init
|
||||
*/
|
||||
|
@ -1344,7 +1403,9 @@ static const struct tcpc_driver_api driver_api = {
|
|||
.set_cc = ucpd_set_cc,
|
||||
.set_roles = ucpd_set_roles,
|
||||
.set_vconn_cb = ucpd_set_vconn_cb,
|
||||
.set_vconn_discharge_cb = ucpd_set_vconn_discharge_cb,
|
||||
.set_vconn = ucpd_set_vconn,
|
||||
.vconn_discharge = ucpd_vconn_discharge,
|
||||
.set_cc_polarity = ucpd_cc_set_polarity,
|
||||
.dump_std_reg = ucpd_dump_std_reg,
|
||||
.set_bist_test_mode = ucpd_set_bist_test_mode,
|
||||
|
|
|
@ -267,6 +267,8 @@ struct tcpc_config {
|
|||
struct tcpc_data {
|
||||
/* VCONN callback function */
|
||||
tcpc_vconn_control_cb_t vconn_cb;
|
||||
/* VCONN Discharge callback function */
|
||||
tcpc_vconn_discharge_cb_t vconn_discharge_cb;
|
||||
/* Alert information */
|
||||
struct alert_info alert_info;
|
||||
|
||||
|
@ -309,6 +311,8 @@ struct tcpc_data {
|
|||
struct msg_header_info msg_header;
|
||||
/* Track VCONN on/off state */
|
||||
bool ucpd_vconn_enable;
|
||||
/* Track CC line that VCONN was active on */
|
||||
enum tc_cc_polarity ucpd_vconn_cc;
|
||||
|
||||
/* Timer for amount of time to wait for receiving a GoodCRC */
|
||||
struct k_timer goodcrc_rx_timer;
|
||||
|
|
|
@ -116,7 +116,10 @@ struct tcpc_chip_info {
|
|||
};
|
||||
};
|
||||
|
||||
typedef int (*tcpc_vconn_control_cb_t)(const struct device *dev, bool enable);
|
||||
typedef int (*tcpc_vconn_control_cb_t)(const struct device *dev,
|
||||
enum tc_cc_polarity pol, bool enable);
|
||||
typedef int (*tcpc_vconn_discharge_cb_t)(const struct device *dev,
|
||||
enum tc_cc_polarity pol, bool enable);
|
||||
typedef void (*tcpc_alert_handler_cb_t)(const struct device *dev, void *data,
|
||||
enum tcpc_alert alert);
|
||||
|
||||
|
@ -127,7 +130,9 @@ __subsystem struct tcpc_driver_api {
|
|||
int (*select_rp_value)(const struct device *dev, enum tc_rp_value rp);
|
||||
int (*get_rp_value)(const struct device *dev, enum tc_rp_value *rp);
|
||||
int (*set_cc)(const struct device *dev, enum tc_cc_pull pull);
|
||||
void (*set_vconn_discharge_cb)(const struct device *dev, tcpc_vconn_discharge_cb_t cb);
|
||||
void (*set_vconn_cb)(const struct device *dev, tcpc_vconn_control_cb_t vconn_cb);
|
||||
int (*vconn_discharge)(const struct device *dev, bool enable);
|
||||
int (*set_vconn)(const struct device *dev, bool enable);
|
||||
int (*set_roles)(const struct device *dev, enum tc_power_role power_role,
|
||||
enum tc_data_role data_role);
|
||||
|
@ -350,6 +355,53 @@ static inline void tcpc_set_vconn_cb(const struct device *dev,
|
|||
return api->set_vconn_cb(dev, vconn_cb);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets a callback that can enable or discharge VCONN if the TCPC is
|
||||
* unable to or the system is configured in a way that does not use
|
||||
* the VCONN control capabilities of the TCPC
|
||||
*
|
||||
* The callback is called in the tcpc_vconn_discharge function if cb isn't NULL
|
||||
*
|
||||
* @param dev Runtime device structure
|
||||
* @param cb pointer to the callback function that discharges vconn
|
||||
*/
|
||||
static inline void tcpc_set_vconn_discharge_cb(const struct device *dev,
|
||||
tcpc_vconn_discharge_cb_t cb)
|
||||
{
|
||||
const struct tcpc_driver_api *api =
|
||||
(const struct tcpc_driver_api *)dev->api;
|
||||
|
||||
__ASSERT(api->set_vconn_discharge_cb != NULL,
|
||||
"Callback pointer should not be NULL");
|
||||
|
||||
return api->set_vconn_discharge_cb(dev, cb);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Discharges VCONN
|
||||
*
|
||||
* This function uses the TCPC to discharge VCONN if possible or calls the
|
||||
* callback function set by tcpc_set_vconn_cb
|
||||
*
|
||||
* @param dev Runtime device structure
|
||||
* @param enable VCONN discharge is enabled when true, it's disabled
|
||||
*
|
||||
* @retval 0 on success
|
||||
* @retval -EIO on failure
|
||||
* @retval -ENOSYS if not implemented
|
||||
*/
|
||||
static inline int tcpc_vconn_discharge(const struct device *dev, bool enable)
|
||||
{
|
||||
const struct tcpc_driver_api *api =
|
||||
(const struct tcpc_driver_api *)dev->api;
|
||||
|
||||
if (api->vconn_discharge == NULL) {
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
return api->vconn_discharge(dev, enable);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enables or disables VCONN
|
||||
*
|
||||
|
|
|
@ -123,6 +123,8 @@ enum usbc_policy_check_t {
|
|||
CHECK_DATA_ROLE_SWAP_TO_UFP,
|
||||
/** Check if Sink is at default level */
|
||||
CHECK_SNK_AT_DEFAULT_LEVEL,
|
||||
/** Check if should control VCONN */
|
||||
CHECK_VCONN_CONTROL,
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -213,6 +215,15 @@ void *usbc_get_dpm_data(const struct device *dev);
|
|||
void usbc_set_vconn_control_cb(const struct device *dev,
|
||||
const tcpc_vconn_control_cb_t cb);
|
||||
|
||||
/**
|
||||
* @brief Set the callback used to discharge VCONN
|
||||
*
|
||||
* @param dev Runtime device structure
|
||||
* @param cb VCONN discharge callback
|
||||
*/
|
||||
void usbc_set_vconn_discharge_cb(const struct device *dev,
|
||||
const tcpc_vconn_discharge_cb_t cb);
|
||||
|
||||
/**
|
||||
* @brief Set the callback used to check a policy
|
||||
*
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue