#include <linux/completion.h>
#include <linux/debugfs.h>
#include <linux/device.h>
#include <linux/hrtimer.h>
#include <linux/jiffies.h>
#include <linux/kernel.h>
#include <linux/kthread.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/power_supply.h>
#include <linux/proc_fs.h>
#include <linux/property.h>
#include <linux/sched/clock.h>
#include <linux/seq_file.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/usb.h>
#include <linux/usb/pd.h>
#include <linux/usb/pd_ado.h>
#include <linux/usb/pd_bdo.h>
#include <linux/usb/pd_ext_sdb.h>
#include <linux/usb/pd_vdo.h>
#include <linux/usb/role.h>
#include <linux/usb/tcpm.h>
#include <linux/usb/typec_altmode.h>
#include <uapi/linux/sched/types.h>
#define FOREACH_STATE(S) …
#define FOREACH_AMS(S) …
#define GENERATE_ENUM(e) …
#define GENERATE_STRING(s) …
enum tcpm_state { … };
static const char * const tcpm_states[] = …;
enum tcpm_ams { … };
static const char * const tcpm_ams_str[] = …;
enum vdm_states { … };
enum pd_msg_request { … };
enum adev_actions { … };
enum frs_typec_current { … };
#define TCPM_CC_EVENT …
#define TCPM_VBUS_EVENT …
#define TCPM_RESET_EVENT …
#define TCPM_FRS_EVENT …
#define TCPM_SOURCING_VBUS …
#define TCPM_PORT_CLEAN …
#define TCPM_PORT_ERROR …
#define LOG_BUFFER_ENTRIES …
#define LOG_BUFFER_ENTRY_SIZE …
#define SVID_DISCOVERY_MAX …
#define ALTMODE_DISCOVERY_MAX …
#define GET_SINK_CAP_RETRY_MS …
#define SEND_DISCOVER_RETRY_MS …
struct pd_mode_data { … };
struct pd_pps_data { … };
struct pd_data { … };
struct tcpm_port { … };
struct pd_rx_event { … };
static const char * const pd_rev[] = …;
#define tcpm_cc_is_sink(cc) …
#define tcpm_port_is_sink(port) …
#define tcpm_cc_is_source(cc) …
#define tcpm_cc_is_audio(cc) …
#define tcpm_cc_is_open(cc) …
#define tcpm_port_is_source(port) …
#define tcpm_port_is_debug(port) …
#define tcpm_port_is_audio(port) …
#define tcpm_port_is_audio_detached(port) …
#define tcpm_try_snk(port) …
#define tcpm_try_src(port) …
#define tcpm_data_role_for_source(port) …
#define tcpm_data_role_for_sink(port) …
#define tcpm_sink_tx_ok(port) …
#define tcpm_wait_for_discharge(port) …
static enum tcpm_state tcpm_default_state(struct tcpm_port *port)
{ … }
static bool tcpm_port_is_disconnected(struct tcpm_port *port)
{ … }
#ifdef CONFIG_DEBUG_FS
static bool tcpm_log_full(struct tcpm_port *port)
{ … }
__printf(2, 0)
static void _tcpm_log(struct tcpm_port *port, const char *fmt, va_list args)
{ … }
__printf(2, 3)
static void tcpm_log(struct tcpm_port *port, const char *fmt, ...)
{ … }
__printf(2, 3)
static void tcpm_log_force(struct tcpm_port *port, const char *fmt, ...)
{ … }
static void tcpm_log_source_caps(struct tcpm_port *port)
{ … }
static int tcpm_debug_show(struct seq_file *s, void *v)
{ … }
DEFINE_SHOW_ATTRIBUTE(…);
static void tcpm_debugfs_init(struct tcpm_port *port)
{ … }
static void tcpm_debugfs_exit(struct tcpm_port *port)
{ … }
#else
__printf(2, 3)
static void tcpm_log(const struct tcpm_port *port, const char *fmt, ...) { }
__printf(2, 3)
static void tcpm_log_force(struct tcpm_port *port, const char *fmt, ...) { }
static void tcpm_log_source_caps(struct tcpm_port *port) { }
static void tcpm_debugfs_init(const struct tcpm_port *port) { }
static void tcpm_debugfs_exit(const struct tcpm_port *port) { }
#endif
static void tcpm_set_cc(struct tcpm_port *port, enum typec_cc_status cc)
{ … }
static int tcpm_enable_auto_vbus_discharge(struct tcpm_port *port, bool enable)
{ … }
static void tcpm_apply_rc(struct tcpm_port *port)
{ … }
static enum typec_cc_status tcpm_rp_cc(struct tcpm_port *port)
{ … }
static void tcpm_ams_finish(struct tcpm_port *port)
{ … }
static int tcpm_pd_transmit(struct tcpm_port *port,
enum tcpm_transmit_type tx_sop_type,
const struct pd_message *msg)
{ … }
void tcpm_pd_transmit_complete(struct tcpm_port *port,
enum tcpm_transmit_status status)
{ … }
EXPORT_SYMBOL_GPL(…);
static int tcpm_mux_set(struct tcpm_port *port, int state,
enum usb_role usb_role,
enum typec_orientation orientation)
{ … }
static int tcpm_set_polarity(struct tcpm_port *port,
enum typec_cc_polarity polarity)
{ … }
static int tcpm_set_vconn(struct tcpm_port *port, bool enable)
{ … }
static u32 tcpm_get_current_limit(struct tcpm_port *port)
{ … }
static int tcpm_set_current_limit(struct tcpm_port *port, u32 max_ma, u32 mv)
{ … }
static int tcpm_set_attached_state(struct tcpm_port *port, bool attached)
{ … }
static int tcpm_set_roles(struct tcpm_port *port, bool attached,
enum typec_role role, enum typec_data_role data)
{ … }
static int tcpm_set_pwr_role(struct tcpm_port *port, enum typec_role role)
{ … }
static u32 tcpm_forge_legacy_pdo(struct tcpm_port *port, u32 pdo, enum typec_role role)
{ … }
static int tcpm_pd_send_source_caps(struct tcpm_port *port)
{ … }
static int tcpm_pd_send_sink_caps(struct tcpm_port *port)
{ … }
static void mod_tcpm_delayed_work(struct tcpm_port *port, unsigned int delay_ms)
{ … }
static void mod_vdm_delayed_work(struct tcpm_port *port, unsigned int delay_ms)
{ … }
static void mod_enable_frs_delayed_work(struct tcpm_port *port, unsigned int delay_ms)
{ … }
static void mod_send_discover_delayed_work(struct tcpm_port *port, unsigned int delay_ms)
{ … }
static void tcpm_set_state(struct tcpm_port *port, enum tcpm_state state,
unsigned int delay_ms)
{ … }
static void tcpm_set_state_cond(struct tcpm_port *port, enum tcpm_state state,
unsigned int delay_ms)
{ … }
static void tcpm_queue_message(struct tcpm_port *port,
enum pd_msg_request message)
{ … }
static bool tcpm_vdm_ams(struct tcpm_port *port)
{ … }
static bool tcpm_ams_interruptible(struct tcpm_port *port)
{ … }
static int tcpm_ams_start(struct tcpm_port *port, enum tcpm_ams ams)
{ … }
static void tcpm_queue_vdm(struct tcpm_port *port, const u32 header,
const u32 *data, int cnt, enum tcpm_transmit_type tx_sop_type)
{ … }
static void tcpm_queue_vdm_unlocked(struct tcpm_port *port, const u32 header,
const u32 *data, int cnt, enum tcpm_transmit_type tx_sop_type)
{ … }
static void svdm_consume_identity(struct tcpm_port *port, const u32 *p, int cnt)
{ … }
static void svdm_consume_identity_sop_prime(struct tcpm_port *port, const u32 *p, int cnt)
{ … }
static bool svdm_consume_svids(struct tcpm_port *port, const u32 *p, int cnt,
enum tcpm_transmit_type rx_sop_type)
{ … }
static void svdm_consume_modes(struct tcpm_port *port, const u32 *p, int cnt,
enum tcpm_transmit_type rx_sop_type)
{ … }
static void tcpm_register_partner_altmodes(struct tcpm_port *port)
{ … }
static void tcpm_register_plug_altmodes(struct tcpm_port *port)
{ … }
#define supports_modal(port) …
#define supports_modal_cable(port) …
#define supports_host(port) …
static bool tcpm_can_communicate_sop_prime(struct tcpm_port *port)
{ … }
static bool tcpm_attempt_vconn_swap_discovery(struct tcpm_port *port)
{ … }
static bool tcpm_cable_vdm_supported(struct tcpm_port *port)
{ … }
static int tcpm_pd_svdm(struct tcpm_port *port, struct typec_altmode *adev,
const u32 *p, int cnt, u32 *response,
enum adev_actions *adev_action,
enum tcpm_transmit_type rx_sop_type,
enum tcpm_transmit_type *response_tx_sop_type)
{ … }
static void tcpm_pd_handle_msg(struct tcpm_port *port,
enum pd_msg_request message,
enum tcpm_ams ams);
static void tcpm_handle_vdm_request(struct tcpm_port *port,
const __le32 *payload, int cnt,
enum tcpm_transmit_type rx_sop_type)
{ … }
static void tcpm_send_vdm(struct tcpm_port *port, u32 vid, int cmd,
const u32 *data, int count, enum tcpm_transmit_type tx_sop_type)
{ … }
static unsigned int vdm_ready_timeout(u32 vdm_hdr)
{ … }
static void vdm_run_state_machine(struct tcpm_port *port)
{ … }
static void vdm_state_machine_work(struct kthread_work *work)
{ … }
enum pdo_err { … };
static const char * const pdo_err_msg[] = …;
static enum pdo_err tcpm_caps_err(struct tcpm_port *port, const u32 *pdo,
unsigned int nr_pdo)
{ … }
static int tcpm_validate_caps(struct tcpm_port *port, const u32 *pdo,
unsigned int nr_pdo)
{ … }
static int tcpm_altmode_enter(struct typec_altmode *altmode, u32 *vdo)
{ … }
static int tcpm_altmode_exit(struct typec_altmode *altmode)
{ … }
static int tcpm_altmode_vdm(struct typec_altmode *altmode,
u32 header, const u32 *data, int count)
{ … }
static const struct typec_altmode_ops tcpm_altmode_ops = …;
static int tcpm_cable_altmode_enter(struct typec_altmode *altmode, enum typec_plug_index sop,
u32 *vdo)
{ … }
static int tcpm_cable_altmode_exit(struct typec_altmode *altmode, enum typec_plug_index sop)
{ … }
static int tcpm_cable_altmode_vdm(struct typec_altmode *altmode, enum typec_plug_index sop,
u32 header, const u32 *data, int count)
{ … }
static const struct typec_cable_ops tcpm_cable_ops = …;
static inline enum tcpm_state ready_state(struct tcpm_port *port)
{ … }
static int tcpm_pd_send_control(struct tcpm_port *port,
enum pd_ctrl_msg_type type,
enum tcpm_transmit_type tx_sop_type);
static void tcpm_handle_alert(struct tcpm_port *port, const __le32 *payload,
int cnt)
{ … }
static int tcpm_set_auto_vbus_discharge_threshold(struct tcpm_port *port,
enum typec_pwr_opmode mode, bool pps_active,
u32 requested_vbus_voltage)
{ … }
static void tcpm_pd_handle_state(struct tcpm_port *port,
enum tcpm_state state,
enum tcpm_ams ams,
unsigned int delay_ms)
{ … }
static void tcpm_pd_handle_msg(struct tcpm_port *port,
enum pd_msg_request message,
enum tcpm_ams ams)
{ … }
static int tcpm_register_source_caps(struct tcpm_port *port)
{ … }
static int tcpm_register_sink_caps(struct tcpm_port *port)
{ … }
static void tcpm_pd_data_request(struct tcpm_port *port,
const struct pd_message *msg,
enum tcpm_transmit_type rx_sop_type)
{ … }
static void tcpm_pps_complete(struct tcpm_port *port, int result)
{ … }
static void tcpm_pd_ctrl_request(struct tcpm_port *port,
const struct pd_message *msg,
enum tcpm_transmit_type rx_sop_type)
{ … }
static void tcpm_pd_ext_msg_request(struct tcpm_port *port,
const struct pd_message *msg)
{ … }
static void tcpm_pd_rx_handler(struct kthread_work *work)
{ … }
void tcpm_pd_receive(struct tcpm_port *port, const struct pd_message *msg,
enum tcpm_transmit_type rx_sop_type)
{ … }
EXPORT_SYMBOL_GPL(…);
static int tcpm_pd_send_control(struct tcpm_port *port,
enum pd_ctrl_msg_type type,
enum tcpm_transmit_type tx_sop_type)
{ … }
static bool tcpm_send_queued_message(struct tcpm_port *port)
{ … }
static int tcpm_pd_check_request(struct tcpm_port *port)
{ … }
#define min_power(x, y) …
#define min_current(x, y) …
static int tcpm_pd_select_pdo(struct tcpm_port *port, int *sink_pdo,
int *src_pdo)
{ … }
static unsigned int tcpm_pd_select_pps_apdo(struct tcpm_port *port)
{ … }
static int tcpm_pd_build_request(struct tcpm_port *port, u32 *rdo)
{ … }
static int tcpm_pd_send_request(struct tcpm_port *port)
{ … }
static int tcpm_pd_build_pps_request(struct tcpm_port *port, u32 *rdo)
{ … }
static int tcpm_pd_send_pps_request(struct tcpm_port *port)
{ … }
static int tcpm_set_vbus(struct tcpm_port *port, bool enable)
{ … }
static int tcpm_set_charge(struct tcpm_port *port, bool charge)
{ … }
static bool tcpm_start_toggling(struct tcpm_port *port, enum typec_cc_status cc)
{ … }
static int tcpm_init_vbus(struct tcpm_port *port)
{ … }
static int tcpm_init_vconn(struct tcpm_port *port)
{ … }
static void tcpm_typec_connect(struct tcpm_port *port)
{ … }
static int tcpm_src_attach(struct tcpm_port *port)
{ … }
static void tcpm_typec_disconnect(struct tcpm_port *port)
{ … }
static void tcpm_unregister_altmodes(struct tcpm_port *port)
{ … }
static void tcpm_set_partner_usb_comm_capable(struct tcpm_port *port, bool capable)
{ … }
static void tcpm_reset_port(struct tcpm_port *port)
{ … }
static void tcpm_detach(struct tcpm_port *port)
{ … }
static void tcpm_src_detach(struct tcpm_port *port)
{ … }
static int tcpm_snk_attach(struct tcpm_port *port)
{ … }
static void tcpm_snk_detach(struct tcpm_port *port)
{ … }
static int tcpm_acc_attach(struct tcpm_port *port)
{ … }
static void tcpm_acc_detach(struct tcpm_port *port)
{ … }
static inline enum tcpm_state hard_reset_state(struct tcpm_port *port)
{ … }
static inline enum tcpm_state unattached_state(struct tcpm_port *port)
{ … }
static void tcpm_swap_complete(struct tcpm_port *port, int result)
{ … }
static enum typec_pwr_opmode tcpm_get_pwr_opmode(enum typec_cc_status cc)
{ … }
static enum typec_cc_status tcpm_pwr_opmode_to_rp(enum typec_pwr_opmode opmode)
{ … }
static void tcpm_set_initial_svdm_version(struct tcpm_port *port)
{ … }
static void run_state_machine(struct tcpm_port *port)
{ … }
static void tcpm_state_machine_work(struct kthread_work *work)
{ … }
static void _tcpm_cc_change(struct tcpm_port *port, enum typec_cc_status cc1,
enum typec_cc_status cc2)
{ … }
static void _tcpm_pd_vbus_on(struct tcpm_port *port)
{ … }
static void _tcpm_pd_vbus_off(struct tcpm_port *port)
{ … }
static void _tcpm_pd_vbus_vsafe0v(struct tcpm_port *port)
{ … }
static void _tcpm_pd_hard_reset(struct tcpm_port *port)
{ … }
static void tcpm_pd_event_handler(struct kthread_work *work)
{ … }
void tcpm_cc_change(struct tcpm_port *port)
{ … }
EXPORT_SYMBOL_GPL(…);
void tcpm_vbus_change(struct tcpm_port *port)
{ … }
EXPORT_SYMBOL_GPL(…);
void tcpm_pd_hard_reset(struct tcpm_port *port)
{ … }
EXPORT_SYMBOL_GPL(…);
void tcpm_sink_frs(struct tcpm_port *port)
{ … }
EXPORT_SYMBOL_GPL(…);
void tcpm_sourcing_vbus(struct tcpm_port *port)
{ … }
EXPORT_SYMBOL_GPL(…);
void tcpm_port_clean(struct tcpm_port *port)
{ … }
EXPORT_SYMBOL_GPL(…);
bool tcpm_port_is_toggling(struct tcpm_port *port)
{ … }
EXPORT_SYMBOL_GPL(…);
void tcpm_port_error_recovery(struct tcpm_port *port)
{ … }
EXPORT_SYMBOL_GPL(…);
static void tcpm_enable_frs_work(struct kthread_work *work)
{ … }
static void tcpm_send_discover_work(struct kthread_work *work)
{ … }
static int tcpm_dr_set(struct typec_port *p, enum typec_data_role data)
{ … }
static int tcpm_pr_set(struct typec_port *p, enum typec_role role)
{ … }
static int tcpm_vconn_set(struct typec_port *p, enum typec_role role)
{ … }
static int tcpm_try_role(struct typec_port *p, int role)
{ … }
static int tcpm_pps_set_op_curr(struct tcpm_port *port, u16 req_op_curr)
{ … }
static int tcpm_pps_set_out_volt(struct tcpm_port *port, u16 req_out_volt)
{ … }
static int tcpm_pps_activate(struct tcpm_port *port, bool activate)
{ … }
static void tcpm_init(struct tcpm_port *port)
{ … }
static int tcpm_port_type_set(struct typec_port *p, enum typec_port_type type)
{ … }
static struct pd_data *tcpm_find_pd_data(struct tcpm_port *port, struct usb_power_delivery *pd)
{ … }
static struct usb_power_delivery **tcpm_pd_get(struct typec_port *p)
{ … }
static int tcpm_pd_set(struct typec_port *p, struct usb_power_delivery *pd)
{ … }
static const struct typec_operations tcpm_ops = …;
void tcpm_tcpc_reset(struct tcpm_port *port)
{ … }
EXPORT_SYMBOL_GPL(…);
static void tcpm_port_unregister_pd(struct tcpm_port *port)
{ … }
static int tcpm_port_register_pd(struct tcpm_port *port)
{ … }
static int tcpm_fw_get_caps(struct tcpm_port *port, struct fwnode_handle *fwnode)
{ … }
static int tcpm_fw_get_snk_vdos(struct tcpm_port *port, struct fwnode_handle *fwnode)
{ … }
enum tcpm_psy_online_states { … };
static enum power_supply_property tcpm_psy_props[] = …;
static int tcpm_psy_get_online(struct tcpm_port *port,
union power_supply_propval *val)
{ … }
static int tcpm_psy_get_voltage_min(struct tcpm_port *port,
union power_supply_propval *val)
{ … }
static int tcpm_psy_get_voltage_max(struct tcpm_port *port,
union power_supply_propval *val)
{ … }
static int tcpm_psy_get_voltage_now(struct tcpm_port *port,
union power_supply_propval *val)
{ … }
static int tcpm_psy_get_current_max(struct tcpm_port *port,
union power_supply_propval *val)
{ … }
static int tcpm_psy_get_current_now(struct tcpm_port *port,
union power_supply_propval *val)
{ … }
static int tcpm_psy_get_input_power_limit(struct tcpm_port *port,
union power_supply_propval *val)
{ … }
static int tcpm_psy_get_prop(struct power_supply *psy,
enum power_supply_property psp,
union power_supply_propval *val)
{ … }
static int tcpm_psy_set_online(struct tcpm_port *port,
const union power_supply_propval *val)
{ … }
static int tcpm_psy_set_prop(struct power_supply *psy,
enum power_supply_property psp,
const union power_supply_propval *val)
{ … }
static int tcpm_psy_prop_writeable(struct power_supply *psy,
enum power_supply_property psp)
{ … }
static enum power_supply_usb_type tcpm_psy_usb_types[] = …;
static const char *tcpm_psy_name_prefix = …;
static int devm_tcpm_psy_register(struct tcpm_port *port)
{ … }
static enum hrtimer_restart state_machine_timer_handler(struct hrtimer *timer)
{ … }
static enum hrtimer_restart vdm_state_machine_timer_handler(struct hrtimer *timer)
{ … }
static enum hrtimer_restart enable_frs_timer_handler(struct hrtimer *timer)
{ … }
static enum hrtimer_restart send_discover_timer_handler(struct hrtimer *timer)
{ … }
struct tcpm_port *tcpm_register_port(struct device *dev, struct tcpc_dev *tcpc)
{ … }
EXPORT_SYMBOL_GPL(…);
void tcpm_unregister_port(struct tcpm_port *port)
{ … }
EXPORT_SYMBOL_GPL(…);
MODULE_AUTHOR(…) …;
MODULE_DESCRIPTION(…) …;
MODULE_LICENSE(…) …;