stm32: Add STM32 USB TCPC Driver

This commit adds a USB Type-C Port Controller Driver for
the STM32 USB Type-C / USB Power Delivery (UCPD) peripheral

Signed-off-by: Sam Hurst <sbh1187@gmail.com>
This commit is contained in:
Sam Hurst 2022-01-16 14:30:43 -08:00 committed by Carles Cufí
commit 6458649137
10 changed files with 1853 additions and 0 deletions

View file

@ -0,0 +1,3 @@
# SPDX-License-Identifier: Apache-2.0
add_subdirectory_ifdef(CONFIG_USBC_TCPC_DRIVER tcpc)

6
drivers/usbc/Kconfig Normal file
View file

@ -0,0 +1,6 @@
# USBC configuration options
# Copyright 2022 The Chromium OS Authors
# SPDX-License-Identifier: Apache-2.0
source "drivers/usbc/tcpc/Kconfig"

View file

@ -0,0 +1,5 @@
# SPDX-License-Identifier: Apache-2.0
zephyr_library()
zephyr_library_sources_ifdef(CONFIG_USBC_TCPC_STM32 ucpd_stm32.c)

28
drivers/usbc/tcpc/Kconfig Normal file
View file

@ -0,0 +1,28 @@
# USBC TCPC configuration options
# Copyright 2022 The Chromium OS Authors
# SPDX-License-Identifier: Apache-2.0
menuconfig USBC_TCPC_DRIVER
bool "USBC TCPC drivers"
help
Enable USBC TypeC Port Controller (TCPC) drivers
if USBC_TCPC_DRIVER
config USBC_INIT_PRIORITY
int "USBC driver init priority"
default 80
help
USBC device driver initialization priority.
Do not mess with it unless you know what you are doing.
Note that the priority needs to be lower than the USBC stack
so that it can start before the USBC sub-system.
source "drivers/usbc/tcpc/Kconfig.tcpc_stm32"
endif # USBC_TCPC_DRIVER
module = USBC
module-str = usbc
source "subsys/logging/Kconfig.template.log_config"

View file

@ -0,0 +1,15 @@
# USBC STM32 TCPC device configuration options
# Copyright 2022 The Chromium OS Authors
# SPDX-License-Identifier: Apache-2.0
DT_COMPAT_ST_STM32_UCPD := st,stm32-ucpd
config USBC_TCPC_STM32
bool "USBC TCPC device controller driver"
depends on SOC_FAMILY_STM32
default $(dt_compat_enabled,$(DT_COMPAT_ST_STM32_UCPD))
select USE_STM32_LL_UCPD
help
Enable USBC TCPC support on the STM32 G0, G4, L5, and U5 family of
processors.

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,314 @@
/*
* Copyright (c) 2022 The Chromium OS Authors
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ZEPHYR_DRIVERS_USBC_DEVICE_UCPD_STM32_PRIV_H_
#define ZEPHYR_DRIVERS_USBC_DEVICE_UCPD_STM32_PRIV_H_
#include <sys/util.h>
#include <drivers/usbc/usbc_tcpc.h>
#include <stm32_ll_ucpd.h>
/**
* @brief The packet type(SOP*) consists of 2-bytes
*/
#define PACKET_TYPE_SIZE 2
/**
* @brief The message header consists of 2-bytes
*/
#define MSG_HEADER_SIZE 2
/**
* @brief USB PD message buffer length.
*/
#define UCPD_BUF_LEN (PD_MAX_EXTENDED_MSG_LEN + \
PACKET_TYPE_SIZE + \
MSG_HEADER_SIZE)
/**
* @brief UCPD alert mask used for enabling alerts
* used to receive a message
*/
#define UCPD_IMR_RX_INT_MASK (UCPD_IMR_RXNEIE | \
UCPD_IMR_RXORDDETIE | \
UCPD_IMR_RXHRSTDETIE | \
UCPD_IMR_RXOVRIE | \
UCPD_IMR_RXMSGENDIE)
/**
* @brief UCPD alert mask used for clearing alerts
* used to receive a message
*/
#define UCPD_ICR_RX_INT_MASK (UCPD_ICR_RXORDDETCF | \
UCPD_ICR_RXHRSTDETCF | \
UCPD_ICR_RXOVRCF | \
UCPD_ICR_RXMSGENDCF)
/**
* @brief UCPD alert mask used for enabling alerts
* used to transmit a message
*/
#define UCPD_IMR_TX_INT_MASK (UCPD_IMR_TXISIE | \
UCPD_IMR_TXMSGDISCIE | \
UCPD_IMR_TXMSGSENTIE | \
UCPD_IMR_TXMSGABTIE | \
UCPD_IMR_TXUNDIE)
/**
* @brief UCPD alert mask used for clearing alerts
* used to transmit a message
*/
#define UCPD_ICR_TX_INT_MASK (UCPD_ICR_TXMSGDISCCF | \
UCPD_ICR_TXMSGSENTCF | \
UCPD_ICR_TXMSGABTCF | \
UCPD_ICR_TXUNDCF)
/**
* @brief UCPD alert mask for all alerts
*/
#define UCPD_ICR_ALL_INT_MASK (UCPD_ICR_FRSEVTCF | \
UCPD_ICR_TYPECEVT2CF | \
UCPD_ICR_TYPECEVT1CF | \
UCPD_ICR_RXMSGENDCF | \
UCPD_ICR_RXOVRCF | \
UCPD_ICR_RXHRSTDETCF | \
UCPD_ICR_RXORDDETCF | \
UCPD_ICR_TXUNDCF | \
UCPD_ICR_HRSTSENTCF | \
UCPD_ICR_HRSTDISCCF | \
UCPD_ICR_TXMSGABTCF | \
UCPD_ICR_TXMSGSENTCF | \
UCPD_ICR_TXMSGDISCCF)
/**
* @brief Map UCPD ANASUB value to TCPC RP value
*
* @param r UCPD ANASUB value
*/
#define UCPD_ANASUB_TO_RP(r) ((r - 1) & 0x3)
/**
* @brief Map TCPC RP value to UCPD ANASUB value
*
* @param r TCPC RP value
*/
#define UCPD_RP_TO_ANASUB(r) ((r + 1) & 0x3)
/**
* @brief Create value for writing to UCPD CR ANASUBMOD
*/
#define STM32_UCPD_CR_ANASUBMODE_VAL(x) ((x) << UCPD_CR_ANASUBMODE_Pos)
/**
* @brief UCPD VSTATE CCx open value when in source mode
*/
#define STM32_UCPD_SR_VSTATE_OPEN 3
/**
* @brief UCPD VSTATE CCx RA value when in source mode
*/
#define STM32_UCPD_SR_VSTATE_RA 0
/**
* @brief PD message send retry count for Rev 2.0
*/
#define UCPD_N_RETRY_COUNT_REV20 3
/**
* @brief PD message send retry count for Rev 3.0
*/
#define UCPD_N_RETRY_COUNT_REV30 2
/**
* @brief Events for ucpd_alert_handler
*/
enum {
/* Request to send a goodCRC message */
UCPD_EVT_GOOD_CRC_REQ,
/* Request to send a power delivery message */
UCPD_EVT_TCPM_MSG_REQ,
/* Request to send a Hard Reset message */
UCPD_EVT_HR_REQ,
/* Transmission of power delivery message failed */
UCPD_EVT_TX_MSG_FAIL,
/* Transmission of power delivery message was discarded */
UCPD_EVT_TX_MSG_DISC,
/* Transmission of power delivery message was successful */
UCPD_EVT_TX_MSG_SUCCESS,
/* Transmission of Hard Reset message was successful */
UCPD_EVT_HR_DONE,
/* Transmission of Hard Reset message failed */
UCPD_EVT_HR_FAIL,
/* A goodCRC message was received */
UCPD_EVT_RX_GOOD_CRC,
/* A power delivery message was received */
UCPD_EVT_RX_MSG,
/* A CC event occurred */
UCPD_EVT_EVENT_CC,
/* A Hard Reset message was received */
UCPD_EVT_HARD_RESET_RECEIVED,
};
/**
* @brief GoodCRC message header roles
*/
struct msg_header_info {
/* Power Role */
enum tc_power_role pr;
/* Data Role */
enum tc_data_role dr;
};
/**
* @brief States for managing TX messages
*/
enum ucpd_state {
/* Idle state */
STATE_IDLE,
/* Transmitting a message state */
STATE_ACTIVE_TCPM,
/* Transmitting a goodCRC message state */
STATE_ACTIVE_CRC,
/* Transmitting a Hard Reset message state */
STATE_HARD_RESET,
/* Waiting for a goodCRC message state */
STATE_WAIT_CRC_ACK
};
/**
* @brief Tx messages are initiated either by the application or from
* the driver when a GoodCRC ack message needs to be sent.
*/
enum ucpd_tx_msg {
/* Default value for not sending a message */
TX_MSG_NONE = -1,
/* Message initiated from the application */
TX_MSG_TCPM = 0,
/* Message initiated from the driver */
TX_MSG_GOOD_CRC = 1,
/* Total number sources that can initiate a message */
TX_MSG_TOTAL = 2
};
/**
* @brief Message from application mask
*/
#define MSG_TCPM_MASK BIT(TX_MSG_TCPM)
/**
* @brief Message from driver mask
*/
#define MSG_GOOD_CRC_MASK BIT(TX_MSG_GOOD_CRC)
/**
* @brief Buffer for holding the received message
*/
union pd_buffer {
/* Power Delivery message header */
uint16_t header;
/* Power Deliver message data including the message header */
uint8_t msg[UCPD_BUF_LEN];
};
/**
* @brief Struct used for transmitting a power delivery message
*/
struct ucpd_tx_desc {
/* Type of the message */
enum pd_packet_type type;
/* Length of the message */
int msg_len;
/* Index of the current byte to transmit */
int msg_index;
/* Power Delivery message to transmit */
union pd_buffer data;
};
/**
* @brief Alert handler information
*/
struct alert_info {
/* Runtime device structure */
const struct device *dev;
/* Application supplied data that's passed to the
* application's alert handler callback
**/
void *data;
/* Application's alert handler callback */
tcpc_alert_handler_cb_t handler;
/*
* Kernel worker used to call the application's
* alert handler callback
*/
struct k_work work;
/* Event flags used in the kernel worker */
atomic_t evt;
};
/**
* @brief Driver config
*/
struct tcpc_config {
/* STM32 UCPD port */
UCPD_TypeDef *ucpd_port;
/* STM32 UCPD parameters */
LL_UCPD_InitTypeDef ucpd_params;
};
/**
* @brief Driver data
*/
struct tcpc_data {
/* VBUS callback function */
tcpc_vbus_cb_t vbus_cb;
/* Discharge VBUS callback function */
tcpc_discharge_vbus_cb_t discharge_vbus_cb;
/* VCONN callback function */
tcpc_vconn_control_cb_t vconn_cb;
/* Alert information */
struct alert_info alert_info;
/* CC Rp value */
enum tc_rp_value rp;
/* PD Rx variables */
/* Number of RX bytes received */
int ucpd_rx_byte_count;
/* Buffer to hold the received bytes */
uint8_t ucpd_rx_buffer[UCPD_BUF_LEN];
/* GoodCRC message ID */
int ucpd_crc_id;
/* Flag to receive or ignore SOP Prime messages */
bool ucpd_rx_sop_prime_enabled;
/* Flag set to true when receiving a message */
bool ucpd_rx_msg_active;
/* Flag set to true when in RX BIST Mode */
bool ucpd_rx_bist_mode;
/* Tx message variables */
/* Buffers to hold messages ready for transmission */
struct ucpd_tx_desc ucpd_tx_buffers[TX_MSG_TOTAL];
/* Current buffer being transmitted */
struct ucpd_tx_desc *ucpd_tx_active_buffer;
/* Request to send a transmission message */
int ucpd_tx_request;
/* State of the TX state machine */
enum ucpd_state ucpd_tx_state;
/* Transmission message ID */
int msg_id_match;
/* Retry count on failure to transmit a message */
int tx_retry_count;
/* Max number of reties before giving up */
int tx_retry_max;
/* GoodCRC message Header */
struct msg_header_info msg_header;
/* Track VCONN on/off state */
bool ucpd_vconn_enable;
};
#endif /* ZEPHYR_DRIVERS_USBC_DEVICE_UCPD_STM32_PRIV_H_ */