/*
|
* Copyright (c) 2016, Fuzhou Rockchip Electronics Co., Ltd
|
* Author: Zain Wang <zain.wang@rock-chips.com>
|
*
|
* This program is free software; you can redistribute it and/or modify it
|
* under the terms and conditions of the GNU General Public License,
|
* version 2, as published by the Free Software Foundation.
|
*
|
* Some ideas are from chrome ec and fairchild GPL fusb302 driver.
|
*/
|
|
#ifndef FUSB302_H
|
#define FUSB302_H
|
|
#include <linux/i2c.h>
|
#include <linux/hrtimer.h>
|
#include <linux/input.h>
|
|
const char *FUSB_DT_INTERRUPT_INTN = "fsc_interrupt_int_n";
|
#define FUSB_DT_GPIO_INTN "fairchild,int_n"
|
#define FUSB_DT_GPIO_VBUS_5V "fairchild,vbus5v"
|
#define FUSB_DT_GPIO_VBUS_OTHER "fairchild,vbusOther"
|
|
#define FUSB30X_I2C_DRIVER_NAME "fusb302"
|
#define FUSB30X_I2C_DEVICETREE_NAME "fairchild,fusb302"
|
|
/* FUSB300 Register Addresses */
|
#define FUSB_REG_DEVICEID 0x01
|
#define FUSB_REG_SWITCHES0 0x02
|
#define FUSB_REG_SWITCHES1 0x03
|
#define FUSB_REG_MEASURE 0x04
|
#define FUSB_REG_SLICE 0x05
|
#define FUSB_REG_CONTROL0 0x06
|
#define FUSB_REG_CONTROL1 0x07
|
#define FUSB_REG_CONTROL2 0x08
|
#define FUSB_REG_CONTROL3 0x09
|
#define FUSB_REG_MASK 0x0A
|
#define FUSB_REG_POWER 0x0B
|
#define FUSB_REG_RESET 0x0C
|
#define FUSB_REG_OCPREG 0x0D
|
#define FUSB_REG_MASKA 0x0E
|
#define FUSB_REG_MASKB 0x0F
|
#define FUSB_REG_CONTROL4 0x10
|
#define FUSB_REG_STATUS0A 0x3C
|
#define FUSB_REG_STATUS1A 0x3D
|
#define FUSB_REG_INTERRUPTA 0x3E
|
#define FUSB_REG_INTERRUPTB 0x3F
|
#define FUSB_REG_STATUS0 0x40
|
#define FUSB_REG_STATUS1 0x41
|
#define FUSB_REG_INTERRUPT 0x42
|
#define FUSB_REG_FIFO 0x43
|
|
enum connection_state {
|
disabled = 0,
|
error_recovery,
|
unattached,
|
attach_wait_sink,
|
attach_wait_source,
|
attached_source,
|
attached_sink,
|
|
policy_src_startup,
|
policy_src_send_caps,
|
policy_src_discovery,
|
policy_src_negotiate_cap,
|
policy_src_cap_response,
|
policy_src_transition_supply,
|
policy_src_transition_default,
|
|
policy_src_ready,
|
policy_src_get_sink_caps,
|
|
policy_src_send_softrst,
|
policy_src_softrst,
|
policy_src_send_hardrst,
|
|
policy_snk_startup,
|
policy_snk_discovery,
|
policy_snk_wait_caps,
|
policy_snk_evaluate_caps,
|
policy_snk_select_cap,
|
policy_snk_transition_sink,
|
policy_snk_ready,
|
|
policy_snk_send_softrst,
|
policy_snk_softrst,
|
policy_snk_send_hardrst,
|
|
policy_snk_transition_default,
|
|
/* PR SWAP */
|
policy_src_prs_evaluate,
|
policy_src_prs_accept,
|
policy_src_prs_transition_to_off,
|
policy_src_prs_source_off,
|
policy_src_prs_assert_rd,
|
policy_src_prs_reject,
|
policy_src_prs_send_swap,
|
|
policy_snk_prs_evaluate,
|
policy_snk_prs_accept,
|
policy_snk_prs_transition_to_off,
|
policy_snk_prs_source_on,
|
policy_snk_prs_assert_rp,
|
policy_snk_prs_reject,
|
policy_snk_prs_send_swap,
|
|
/* VC SWAP */
|
policy_vcs_dfp_send_swap,
|
policy_vcs_dfp_wait_for_ufp_vconn,
|
policy_vcs_dfp_turn_off_vconn,
|
policy_vcs_dfp_turn_on_vconn,
|
policy_vcs_dfp_send_ps_rdy,
|
|
policy_vcs_ufp_evaluate_swap,
|
policy_vcs_ufp_reject,
|
policy_vcs_ufp_accept,
|
policy_vcs_ufp_wait_for_dfp_vconn,
|
policy_vcs_ufp_turn_off_vconn,
|
policy_vcs_ufp_turn_on_vconn,
|
policy_vcs_ufp_send_ps_rdy,
|
|
policy_drs_ufp_evaluate,
|
policy_drs_ufp_accept,
|
policy_drs_ufp_reject,
|
policy_drs_ufp_change,
|
policy_drs_ufp_send_swap,
|
|
policy_drs_dfp_evaluate,
|
policy_drs_dfp_accept,
|
policy_drs_dfp_reject,
|
policy_drs_dfp_change,
|
policy_drs_dfp_send_swap,
|
|
attach_try_src,
|
attach_try_snk,
|
|
attach_wait_audio_acc,
|
attached_audio_acc,
|
};
|
|
enum vdm_state {
|
VDM_STATE_DISCOVERY_ID,
|
VDM_STATE_DISCOVERY_SVID,
|
VDM_STATE_DISCOVERY_MODES,
|
VDM_STATE_ENTER_MODE,
|
VDM_STATE_UPDATE_STATUS,
|
VDM_STATE_DP_CONFIG,
|
VDM_STATE_NOTIFY,
|
VDM_STATE_READY,
|
VDM_STATE_ERR,
|
};
|
|
enum tcpm_rp_value {
|
TYPEC_RP_USB = 0,
|
TYPEC_RP_1A5 = 1,
|
TYPEC_RP_3A0 = 2,
|
TYPEC_RP_RESERVED = 3,
|
};
|
|
enum role_mode {
|
ROLE_MODE_NONE,
|
ROLE_MODE_DRP,
|
ROLE_MODE_UFP,
|
ROLE_MODE_DFP,
|
ROLE_MODE_ASS,
|
};
|
|
#define SBF(s, v) ((s) << (v))
|
#define SWITCHES0_PDWN1 SBF(1, 0)
|
#define SWITCHES0_PDWN2 SBF(1, 1)
|
#define SWITCHES0_MEAS_CC1 SBF(1, 2)
|
#define SWITCHES0_MEAS_CC2 SBF(1, 3)
|
#define SWITCHES0_VCONN_CC1 SBF(1, 4)
|
#define SWITCHES0_VCONN_CC2 SBF(1, 5)
|
#define SWITCHES0_PU_EN1 SBF(1, 6)
|
#define SWITCHES0_PU_EN2 SBF(1, 7)
|
|
#define SWITCHES1_TXCC1 SBF(1, 0)
|
#define SWITCHES1_TXCC2 SBF(1, 1)
|
#define SWITCHES1_AUTO_CRC SBF(1, 2)
|
#define SWITCHES1_DATAROLE SBF(1, 4)
|
#define SWITCHES1_SPECREV SBF(3, 5)
|
#define SWITCHES1_POWERROLE SBF(1, 7)
|
|
#define MEASURE_MDAC SBF(0x3f, 0)
|
#define MEASURE_VBUS SBF(1, 6)
|
|
#define SLICE_SDAC SBF(0x3f, 0)
|
#define SLICE_SDAC_HYS SBF(3, 6)
|
|
#define CONTROL0_TX_START SBF(1, 0)
|
#define CONTROL0_AUTO_PRE SBF(1, 1)
|
#define CONTROL0_HOST_CUR SBF(3, 2)
|
#define CONTROL0_HOST_CUR_USB SBF(1, 2)
|
#define CONTROL0_HOST_CUR_1A5 SBF(2, 2)
|
#define CONTROL0_HOST_CUR_3A0 SBF(3, 2)
|
#define CONTROL0_INT_MASK SBF(1, 5)
|
#define CONTROL0_TX_FLUSH SBF(1, 6)
|
|
#define CONTROL1_ENSOP1 SBF(1, 0)
|
#define CONTROL1_ENSOP2 SBF(1, 1)
|
#define CONTROL1_RX_FLUSH SBF(1, 2)
|
#define CONTROL1_BIST_MODE2 SBF(1, 4)
|
#define CONTROL1_ENSOP1DB SBF(1, 5)
|
#define CONTROL1_ENSOP2DB SBF(1, 6)
|
|
#define CONTROL2_TOGGLE SBF(1, 0)
|
#define CONTROL2_MODE SBF(3, 1)
|
#define CONTROL2_MODE_NONE 0
|
#define CONTROL2_MODE_DFP SBF(3, 1)
|
#define CONTROL2_MODE_UFP SBF(2, 1)
|
#define CONTROL2_MODE_DRP SBF(1, 1)
|
#define CONTROL2_WAKE_EN SBF(1, 3)
|
#define CONTROL2_TOG_RD_ONLY SBF(1, 5)
|
#define CONTROL2_TOG_SAVE_PWR1 SBF(1, 6)
|
#define CONTROL2_TOG_SAVE_PWR2 SBF(1, 7)
|
|
#define CONTROL3_AUTO_RETRY SBF(1, 0)
|
#define CONTROL3_N_RETRIES SBF(3, 1)
|
#define CONTROL3_AUTO_SOFTRESET SBF(1, 3)
|
#define CONTROL3_AUTO_HARDRESET SBF(1, 4)
|
#define CONTROL3_SEND_HARDRESET SBF(1, 6)
|
|
#define MASK_M_BC_LVL SBF(1, 0)
|
#define MASK_M_COLLISION SBF(1, 1)
|
#define MASK_M_WAKE SBF(1, 2)
|
#define MASK_M_ALERT SBF(1, 3)
|
#define MASK_M_CRC_CHK SBF(1, 4)
|
#define MASK_M_COMP_CHNG SBF(1, 5)
|
#define MASK_M_ACTIVITY SBF(1, 6)
|
#define MASK_M_VBUSOK SBF(1, 7)
|
|
#define POWER_PWR SBF(0xf, 0)
|
|
#define RESET_SW_RESET SBF(1, 0)
|
#define RESET_PD_RESET SBF(1, 1)
|
|
#define MASKA_M_HARDRST SBF(1, 0)
|
#define MASKA_M_SOFTRST SBF(1, 1)
|
#define MASKA_M_TXSENT SBF(1, 2)
|
#define MASKA_M_HARDSENT SBF(1, 3)
|
#define MASKA_M_RETRYFAIL SBF(1, 4)
|
#define MASKA_M_SOFTFAIL SBF(1, 5)
|
#define MASKA_M_TOGDONE SBF(1, 6)
|
#define MASKA_M_OCP_TEMP SBF(1, 7)
|
|
#define MASKB_M_GCRCSEND SBF(1, 0)
|
|
#define CONTROL4_TOG_USRC_EXIT SBF(1, 0)
|
|
#define MDAC_1P6V 0x26
|
|
#define STATUS0A_HARDRST SBF(1, 0)
|
#define STATUS0A_SOFTRST SBF(1, 1)
|
#define STATUS0A_POWER23 SBF(3, 2)
|
#define STATUS0A_RETRYFAIL SBF(1, 4)
|
#define STATUS0A_SOFTFAIL SBF(1, 5)
|
#define STATUS0A_TOGDONE SBF(1, 6)
|
#define STATUS0A_M_OCP_TEMP SBF(1, 7)
|
|
#define STATUS1A_RXSOP SBF(1, 0)
|
#define STATUS1A_RXSOP1DB SBF(1, 1)
|
#define STATUS1A_RXSOP2DB SBF(1, 2)
|
#define STATUS1A_TOGSS SBF(7, 3)
|
#define CC_STATE_TOGSS_CC1 SBF(1, 0)
|
#define CC_STATE_TOGSS_CC2 SBF(1, 1)
|
#define CC_STATE_TOGSS_IS_UFP SBF(1, 2)
|
|
#define CC_STATE_TOGSS_IS_DFP SBF(2, 2)
|
#define CC_STATE_TOGSS_IS_ACC SBF(3, 2)
|
#define CC_STATE_TOGSS_ROLE SBF(3, 2)
|
|
#define INTERRUPTA_HARDRST SBF(1, 0)
|
#define INTERRUPTA_SOFTRST SBF(1, 1)
|
#define INTERRUPTA_TXSENT SBF(1, 2)
|
#define INTERRUPTA_HARDSENT SBF(1, 3)
|
#define INTERRUPTA_RETRYFAIL SBF(1, 4)
|
#define INTERRUPTA_SOFTFAIL SBF(1, 5)
|
#define INTERRUPTA_TOGDONE SBF(1, 6)
|
#define INTERRUPTA_OCP_TEMP SBF(1, 7)
|
|
#define INTERRUPTB_GCRCSENT SBF(1, 0)
|
|
#define STATUS0_BC_LVL SBF(3, 0)
|
#define STATUS0_WAKE SBF(1, 2)
|
#define STATUS0_ALERT SBF(1, 3)
|
#define STATUS0_CRC_CHK SBF(1, 4)
|
#define STATUS0_COMP SBF(1, 5)
|
#define STATUS0_ACTIVITY SBF(1, 6)
|
#define STATUS0_VBUSOK SBF(1, 7)
|
|
#define STATUS1_OCP SBF(1, 0)
|
#define STATUS1_OVRTEMP SBF(1, 1)
|
#define STATUS1_TX_FULL SBF(1, 2)
|
#define STATUS1_TX_EMPTY SBF(1, 3)
|
#define STATUS1_RX_FULL SBF(1, 4)
|
#define STATUS1_RX_EMPTY SBF(1, 5)
|
#define STATUS1_RXSOP1 SBF(1, 6)
|
#define STATUS1_RXSOP2 SBF(1, 7)
|
|
#define INTERRUPT_BC_LVL SBF(1, 0)
|
#define INTERRUPT_COLLISION SBF(1, 1)
|
#define INTERRUPT_WAKE SBF(1, 2)
|
#define INTERRUPT_ALERT SBF(1, 3)
|
#define INTERRUPT_CRC_CHK SBF(1, 4)
|
#define INTERRUPT_COMP_CHNG SBF(1, 5)
|
#define INTERRUPT_ACTIVITY SBF(1, 6)
|
#define INTERRUPT_VBUSOK SBF(1, 7)
|
|
#define FUSB_TKN_TXON 0xa1
|
#define FUSB_TKN_SYNC1 0x12
|
#define FUSB_TKN_SYNC2 0x13
|
#define FUSB_TKN_SYNC3 0x1b
|
#define FUSB_TKN_RST1 0x15
|
#define FUSB_TKN_RST2 0x16
|
#define FUSB_TKN_PACKSYM 0x80
|
#define FUSB_TKN_JAMCRC 0xff
|
#define FUSB_TKN_EOP 0x14
|
#define FUSB_TKN_TXOFF 0xfe
|
|
/* USB PD Control Message Types */
|
#define CONTROLMESSAGE 0
|
#define CMT_GOODCRC 1
|
#define CMT_GOTOMIN 2
|
#define CMT_ACCEPT 3
|
#define CMT_REJECT 4
|
#define CMT_PING 5
|
#define CMT_PS_RDY 6
|
#define CMT_GETSOURCECAP 7
|
#define CMT_GETSINKCAP 8
|
#define CMT_DR_SWAP 9
|
#define CMT_PR_SWAP 10
|
#define CMT_VCONN_SWAP 11
|
#define CMT_WAIT 12
|
#define CMT_SOFTRESET 13
|
|
/* USB PD Data Message Types */
|
#define DATAMESSAGE 1
|
#define DMT_SOURCECAPABILITIES 1
|
#define DMT_REQUEST 2
|
#define DMT_BIST 3
|
#define DMT_SINKCAPABILITIES 4
|
#define DMT_VENDERDEFINED 15
|
|
/* VDM Command Types */
|
#define VDM_DISCOVERY_ID 0X01
|
#define VDM_DISCOVERY_SVIDS 0X02
|
#define VDM_DISCOVERY_MODES 0X03
|
#define VDM_ENTER_MODE 0X04
|
#define VDM_EXIT_MODE 0X05
|
#define VDM_ATTENTION 0X06
|
#define VDM_DP_STATUS_UPDATE 0X10
|
#define VDM_DP_CONFIG 0X11
|
|
#define VDM_TYPE_INIT 0
|
#define VDM_TYPE_ACK 1
|
#define VDM_TYPE_NACK 2
|
#define VDM_TYPE_BUSY 3
|
|
/* 200ms at least, 1 cycle about 6ms */
|
#define N_DEBOUNCE_CNT 33
|
#define N_CAPS_COUNT 50
|
#define N_HARDRESET_COUNT 0
|
|
#define T_NO_RESPONSE 5000
|
#define T_SRC_RECOVER 830
|
#define T_TYPEC_SEND_SOURCECAP 100
|
#define T_SENDER_RESPONSE 30
|
#define T_SRC_TRANSITION 30
|
#define T_TYPEC_SINK_WAIT_CAP 500
|
#define T_PS_TRANSITION 500
|
#define T_BMC_TIMEOUT 5
|
#define T_PS_HARD_RESET_MAX 35
|
#define T_SAFE_0V 650
|
#define T_SRC_TURN_ON 275
|
#define T_SRC_RECOVER_MAX 1000
|
#define T_PD_SOURCE_OFF 920
|
#define T_PD_SOURCE_ON 480
|
#define T_PD_SWAP_SOURCE_START 20
|
#define T_PD_VCONN_SRC_ON 100
|
#define T_PD_TRY_DRP 75
|
|
#define T_NO_TRIGGER 500
|
#define T_DISABLED 0xffff
|
|
#define PD_HEADER_CNT(header) (((header) >> 12) & 7)
|
#define PD_HEADER_TYPE(header) ((header) & 0xF)
|
#define PD_HEADER_ID(header) (((header) >> 9) & 7)
|
|
#define VDM_HEADER_TYPE(header) (((header) >> 6) & 3)
|
#define VDMHEAD_CMD_TYPE_MASK (3 << 6)
|
#define VDMHEAD_CMD_MASK (0x1f << 0)
|
#define VDMHEAD_STRUCT_TYPE_MASK BIT(15)
|
|
#define GET_VDMHEAD_CMD_TYPE(head) ((head & VDMHEAD_CMD_TYPE_MASK) >> 6)
|
#define GET_VDMHEAD_CMD(head) (head & VDMHEAD_CMD_MASK)
|
#define GET_VDMHEAD_STRUCT_TYPE(head) ((head & VDMHEAD_STRUCT_TYPE_MASK) >> 15)
|
|
#define DP_STATUS_MASK 0x000000ff
|
#define DP_STATUS_HPD_STATE BIT(7)
|
|
#define GET_DP_STATUS(status) (status & DP_STATUS_MASK)
|
#define GET_DP_STATUS_HPD(status) ((status & DP_STATUS_HPD_STATE) >> 7)
|
|
#define VDM_IDHEAD_USBVID_MASK (0xffff << 0)
|
#define VDM_IDHEAD_MODALSUPPORT_MASK BIT(26)
|
#define VDM_IDHEAD_PRODUCTTYPE (7 << 27)
|
#define VDM_IDHEAD_USBDEVICE BIT(30)
|
#define VDM_IDHEAD_USBHOST BIT(30)
|
|
#define CAP_POWER_TYPE(PDO) ((PDO >> 30) & 3)
|
#define CAP_FPDO_VOLTAGE(PDO) ((PDO >> 10) & 0x3ff)
|
#define CAP_VPDO_VOLTAGE(PDO) ((PDO >> 20) & 0x3ff)
|
#define CAP_FPDO_CURRENT(PDO) ((PDO >> 0) & 0x3ff)
|
#define CAP_VPDO_CURRENT(PDO) ((PDO >> 0) & 0x3ff)
|
|
enum CC_ORIENTATION {
|
TYPEC_ORIENTATION_NONE,
|
TYPEC_ORIENTATION_CC1,
|
TYPEC_ORIENTATION_CC2,
|
};
|
|
enum typec_cc_polarity {
|
TYPEC_POLARITY_CC1,
|
TYPEC_POLARITY_CC2,
|
};
|
|
enum CC_MODE {
|
CC_PULL_UP,
|
CC_PULL_DOWN,
|
CC_PULL_NONE,
|
};
|
|
enum typec_power_role {
|
POWER_ROLE_SINK = 0,
|
POWER_ROLE_SOURCE,
|
};
|
|
enum typec_data_role {
|
DATA_ROLE_UFP = 0,
|
DATA_ROLE_DFP,
|
};
|
|
struct notify_info {
|
enum CC_ORIENTATION orientation;
|
/* 0 UFP : 1 DFP */
|
enum typec_power_role power_role;
|
enum typec_data_role data_role;
|
|
bool is_cc_connected;
|
bool is_pd_connected;
|
|
bool is_enter_mode;
|
int pin_assignment_support;
|
int pin_assignment_def;
|
bool attention;
|
u32 dp_status;
|
u32 dp_caps;
|
};
|
|
enum tx_state {
|
tx_idle,
|
tx_busy,
|
tx_failed,
|
tx_success
|
};
|
|
struct PD_CAP_INFO {
|
u32 peak_current;
|
u32 specification_revision;
|
u32 externally_powered;
|
u32 usb_suspend_support;
|
u32 usb_communications_cap;
|
u32 dual_role_power;
|
u32 data_role_swap;
|
u32 supply_type;
|
};
|
|
struct fusb30x_chip {
|
struct i2c_client *client;
|
struct device *dev;
|
struct regmap *regmap;
|
struct work_struct work;
|
struct workqueue_struct *fusb30x_wq;
|
struct hrtimer timer_state_machine;
|
struct hrtimer timer_mux_machine;
|
struct PD_CAP_INFO pd_cap_info;
|
struct notify_info notify;
|
struct notify_info notify_cmp;
|
struct extcon_dev *extcon;
|
enum connection_state conn_state;
|
struct gpio_desc *gpio_vbus_5v;
|
struct gpio_desc *gpio_vbus_other;
|
struct gpio_desc *gpio_int;
|
struct gpio_desc *gpio_discharge;
|
int timer_state;
|
int timer_mux;
|
int port_num;
|
u32 work_continue;
|
spinlock_t irq_lock;
|
int gpio_int_irq;
|
int enable_irq;
|
|
/*
|
* ---------------------------------
|
* | role 0x03 << 2, | cc_use 0x03 |
|
* | src 1 << 2, | cc1 1 |
|
* | snk 2 << 2, | cc2 2 |
|
* ---------------------------------
|
*/
|
u8 cc_state;
|
int cc1;
|
int cc2;
|
enum typec_cc_polarity cc_polarity;
|
u8 val_tmp;
|
u8 debounce_cnt;
|
int sub_state;
|
int caps_counter;
|
u32 send_load[7];
|
u32 rec_load[7];
|
u16 send_head;
|
u16 rec_head;
|
int msg_id;
|
enum tx_state tx_state;
|
int hardrst_count;
|
u32 source_power_supply[7];
|
/* 50mv unit */
|
u32 source_max_current[7];
|
/* 10ma uint*/
|
int pos_power;
|
/*
|
* if PartnerCap[0] == 0xffffffff
|
* show Partner Device do not support supply
|
*/
|
u32 partner_cap[7];
|
int n_caps_used;
|
int vdm_state;
|
int vdm_substate;
|
int vdm_send_state;
|
u16 vdm_svid[12];
|
int vdm_svid_num;
|
u32 vdm_id;
|
u8 chip_id;
|
bool vconn_enabled;
|
bool is_pd_support;
|
int pd_output_vol;
|
int pd_output_cur;
|
int cc_meas_high;
|
int cc_meas_low;
|
bool vbus_begin;
|
|
enum role_mode role;
|
bool vconn_supported;
|
bool try_role_complete;
|
enum role_mode try_role;
|
struct input_dev *input;
|
bool suspended;
|
};
|
|
#endif /* FUSB302_H */
|