diff options
Diffstat (limited to 'include/linux/hisi/usb/pd/richtek/pd_core.h')
-rw-r--r-- | include/linux/hisi/usb/pd/richtek/pd_core.h | 1218 |
1 files changed, 1218 insertions, 0 deletions
diff --git a/include/linux/hisi/usb/pd/richtek/pd_core.h b/include/linux/hisi/usb/pd/richtek/pd_core.h new file mode 100644 index 000000000000..8675f835fd52 --- /dev/null +++ b/include/linux/hisi/usb/pd/richtek/pd_core.h @@ -0,0 +1,1218 @@ +/* + * Copyright (C) 2016 Richtek Technology Corp. + * + * Author: TH <tsunghan_tsai@richtek.com> + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef PD_CORE_H_ +#define PD_CORE_H_ +#include <linux/module.h> +#include <linux/hisi/usb/pd/richtek/tcpci_timer.h> +#include <linux/hisi/usb/pd/richtek/tcpci_event.h> +#include <linux/hisi/usb/pd/richtek/tcpci_config.h> + +#ifdef CONFIG_USB_PD_SRC_STARTUP_DISCOVER_ID +#define CONFIG_PD_DISCOVER_CABLE_ID +#endif /* CONFIG_USB_PD_SRC_STARTUP_DISCOVER_ID */ + +#ifdef CONFIG_USB_PD_DFP_READY_DISCOVER_ID +#undef CONFIG_PD_DISCOVER_CABLE_ID +#define CONFIG_PD_DISCOVER_CABLE_ID +#endif /* CONFIG_USB_PD_DFP_READY_DISCOVER_ID */ + +#define PD_SOP_NR 3 + +#ifndef BIT +#define BIT(x) (1 << (x)) +#endif + +/* Default retry count for transmitting */ +#define PD_RETRY_COUNT 3 + +#if PD_RETRY_COUNT > 3 +#error "PD_RETRY_COUNT Max = 3" +#endif + +/* --- PD data message helpers --- */ +#define PDO_MAX_OBJECTS 7 +#define PDO_MODES (PDO_MAX_OBJECTS - 1) + +/* PDO : Power Data Object */ +/* + * 1. The vSafe5V Fixed Supply Object shall always be the first object. + * 2. The remaining Fixed Supply Objects, + * if present, shall be sent in voltage order; lowest to highest. + * 3. The Battery Supply Objects, + * if present shall be sent in Minimum Voltage order; lowest to highest. + * 4. The Variable Supply (non battery) Objects, + * if present, shall be sent in Minimum Voltage order; lowest to highest. + */ +#define PDO_TYPE_FIXED (0 << 30) +#define PDO_TYPE_BATTERY BIT(30) +#define PDO_TYPE_VARIABLE (2 << 30) +#define PDO_TYPE_MASK (3 << 30) + +#define PDO_FIXED_DUAL_ROLE BIT(29) /* Dual role device */ +#define PDO_FIXED_SUSPEND BIT(28) /* USB Suspend supported (SRC)*/ +#define PDO_FIXED_HIGH_CAP BIT(28) /* Higher Capability (SNK )*/ +#define PDO_FIXED_EXTERNAL BIT(27) /* Externally powered */ +#define PDO_FIXED_COMM_CAP BIT(26) /* USB Communications Capable */ +#define PDO_FIXED_DATA_SWAP BIT(25) /* Data role swap command supported */ + +#define PDO_FIXED_PEAK_CURR(i) \ + (((i) & 0x03) << 20) /* [21..20] Peak current */ +#define PDO_FIXED_VOLT(mv) \ + ((((mv) / 50) & 0x3fff) << 10) /* Voltage in 50mV units */ +#define PDO_FIXED_CURR(ma) \ + ((((ma) / 10) & 0x3fff) << 0) /* Max current in 10mA units */ + +#define PDO_TYPE(raw) ((raw) & PDO_TYPE_MASK) + +#define PDO_FIXED_EXTRACT_VOLT_RAW(raw) (((raw) >> 10) & 0x3ff) +#define PDO_FIXED_EXTRACT_CURR_RAW(raw) (((raw) >> 0) & 0x3ff) +#define PDO_FIXED_EXTRACT_VOLT(raw) (PDO_FIXED_EXTRACT_VOLT_RAW(raw) * 50) +#define PDO_FIXED_EXTRACT_CURR(raw) (PDO_FIXED_EXTRACT_CURR_RAW(raw) * 10) +#define PDO_FIXED_RESET_CURR(raw, ma) \ + (((raw) & ~0x3ff) | PDO_FIXED_CURR(ma)) + +#define PDO_FIXED(mv, ma, flags) (PDO_FIXED_VOLT(mv) |\ + PDO_FIXED_CURR(ma) | (flags)) + +#define PDO_VAR_MAX_VOLT(mv) ((((mv) / 50) & 0x3FF) << 20) +#define PDO_VAR_MIN_VOLT(mv) ((((mv) / 50) & 0x3FF) << 10) +#define PDO_VAR_OP_CURR(ma) ((((ma) / 10) & 0x3FF) << 0) + +#define PDO_VAR_EXTRACT_MAX_VOLT_RAW(raw) (((raw) >> 20) & 0x3ff) +#define PDO_VAR_EXTRACT_MIN_VOLT_RAW(raw) (((raw) >> 10) & 0x3ff) +#define PDO_VAR_EXTRACT_CURR_RAW(raw) (((raw) >> 0) & 0x3ff) + +#define PDO_VAR_EXTRACT_MAX_VOLT(raw) (PDO_VAR_EXTRACT_MAX_VOLT_RAW(raw) * 50) +#define PDO_VAR_EXTRACT_MIN_VOLT(raw) (PDO_VAR_EXTRACT_MIN_VOLT_RAW(raw) * 50) +#define PDO_VAR_EXTRACT_CURR(raw) (PDO_VAR_EXTRACT_CURR_RAW(raw) * 10) + +#define PDO_VAR_RESET_CURR(raw, ma) \ + (((raw) & ~0x3ff) | PDO_VAR_OP_CURR(ma)) + +#define PDO_VAR(min_mv, max_mv, op_ma) \ + (PDO_VAR_MIN_VOLT(min_mv) | \ + PDO_VAR_MAX_VOLT(max_mv) | \ + PDO_VAR_OP_CURR(op_ma) | \ + PDO_TYPE_VARIABLE) + +#define PDO_BATT_MAX_VOLT(mv) ((((mv) / 50) & 0x3FF) << 20) +#define PDO_BATT_MIN_VOLT(mv) ((((mv) / 50) & 0x3FF) << 10) +#define PDO_BATT_OP_POWER(mw) ((((mw) / 250) & 0x3FF) << 0) + +#define PDO_BATT_EXTRACT_MAX_VOLT_RAW(raw) (((raw) >> 20) & 0x3ff) +#define PDO_BATT_EXTRACT_MIN_VOLT_RAW(raw) (((raw) >> 10) & 0x3ff) +#define PDO_BATT_EXTRACT_OP_POWER_RAW(raw) (((raw) >> 0) & 0x3ff) + +#define PDO_BATT_EXTRACT_MAX_VOLT(raw) \ + (PDO_BATT_EXTRACT_MAX_VOLT_RAW(raw) * 50) +#define PDO_BATT_EXTRACT_MIN_VOLT(raw) \ + (PDO_BATT_EXTRACT_MIN_VOLT_RAW(raw) * 50) +#define PDO_BATT_EXTRACT_OP_POWER(raw) \ + (PDO_BATT_EXTRACT_OP_POWER_RAW(raw) * 250) + +#define PDO_BATT(min_mv, max_mv, op_mw) \ + (PDO_BATT_MIN_VOLT(min_mv) | \ + PDO_BATT_MAX_VOLT(max_mv) | \ + PDO_BATT_OP_POWER(op_mw) | \ + PDO_TYPE_BATTERY) + +/* RDO : Request Data Object */ +#define RDO_OBJ_POS(n) (((n) & 0x7) << 28) +#define RDO_POS(rdo) (((rdo) >> 28) & 0x7) +#define RDO_GIVE_BACK BIT(27) +#define RDO_CAP_MISMATCH BIT(26) +#define RDO_COMM_CAP BIT(25) +#define RDO_NO_SUSPEND BIT(24) +#define RDO_FIXED_VAR_OP_CURR(ma) ((((ma) / 10) & 0x3FF) << 10) +#define RDO_FIXED_VAR_MAX_CURR(ma) ((((ma) / 10) & 0x3FF) << 0) + +#define RDO_FIXED_VAR_EXTRACT_OP_CURR(raw) ((((raw) >> 10 & 0x3ff)) * 10) +#define RDO_FIXED_VAR_EXTRACT_MAX_CURR(raw) ((((raw) >> 0 & 0x3ff)) * 10) + +#define RDO_BATT_OP_POWER(mw) ((((mw) / 250) & 0x3FF) << 10) +#define RDO_BATT_MAX_POWER(mw) ((((mw) / 250) & 0x3FF) << 0) + +#define RDO_BATT_EXTRACT_OP_POWER(raw) ((((raw) >> 10 & 0x3ff)) * 250) +#define RDO_BATT_EXTRACT_MAX_POWER(raw) ((((raw) >> 0 & 0x3ff)) * 250) + +#define RDO_FIXED(n, op_ma, max_ma, flags) \ + (RDO_OBJ_POS(n) | (flags) | \ + RDO_FIXED_VAR_OP_CURR(op_ma) | \ + RDO_FIXED_VAR_MAX_CURR(max_ma)) + +#define RDO_BATT(n, op_mw, max_mw, flags) \ + (RDO_OBJ_POS(n) | (flags) | \ + RDO_BATT_OP_POWER(op_mw) | \ + RDO_BATT_MAX_POWER(max_mw)) + +/* BDO : BIST Data Object */ +#define BDO_MODE_RECV (0 << 28) +#define BDO_MODE_TRANSMIT BIT(28) +#define BDO_MODE_COUNTERS (2 << 28) +#define BDO_MODE_CARRIER0 (3 << 28) +#define BDO_MODE_CARRIER1 (4 << 28) +#define BDO_MODE_CARRIER2 (5 << 28) +#define BDO_MODE_CARRIER3 (6 << 28) +#define BDO_MODE_EYE (7 << 28) +#define BDO_MODE_TEST_DATA (8 << 28) + +#define BDO_MODE(obj) ((obj) & (0xf << 28)) +#define BDO(mode, cnt) ((mode) | ((cnt) & 0xFFFF)) + +#define SVID_DISCOVERY_MAX 16 + +/* Protocol revision */ +#define PD_REV10 0 +#define PD_REV20 1 + +/* build message header */ + +#define PD_HEADER_SOP(msg_type, prole, drole, id, cnt) \ + ((msg_type) | (PD_REV20 << 6) | \ + ((drole) << 5) | ((prole) << 8) | \ + ((id) << 9) | ((cnt) << 12)) + +#define PD_HEADER_SOP_PRIME(msg_type, cable_plug, id, cnt) \ + ((msg_type) | (PD_REV20 << 6) | \ + ((cable_plug) << 8) | \ + ((id) << 9) | ((cnt) << 12)) + +#define PD_HEADER_CNT(header) (((header) >> 12) & 7) +#define PD_HEADER_TYPE(header) ((header) & 0xF) +#define PD_HEADER_ID(header) (((header) >> 9) & 7) +#define PD_HEADER_PR(header) (((header) >> 8) & 1) +#define PD_HEADER_DR(header) (((header) >> 5) & 1) + +/* + * VDO : Vendor Defined Message Object + * VDM object is minimum of VDM header + 6 additional data objects. + */ + +/* + * VDM header + * ---------- + * <31:16> :: SVID + * <15> :: VDM type ( 1b == structured, 0b == unstructured ) + * <14:13> :: Structured VDM version (can only be 00 == 1.0 currently) + * <12:11> :: reserved + * <10:8> :: object position (1-7 valid ... used for enter/exit mode only) + * <7:6> :: command type (SVDM only?) + * <5> :: reserved (SVDM), command type (UVDM) + * <4:0> :: command + */ +#define VDO_MAX_SIZE (7) +#define VDO_MAX_DATA_SIZE (VDO_MAX_SIZE - 1) +#define VDO_MAX_SVID_SIZE (VDO_MAX_DATA_SIZE * 2) + +#define VDO(vid, type, custom) \ + (((vid) << 16) | \ + ((type) << 15) | \ + ((custom) & 0x7FFF)) + +#define VDO_S(svid, cmd_type, cmd, obj) \ + VDO(svid, 1, VDO_CMDT(cmd_type) | VDO_OPOS(obj) | (cmd)) + +#define VDO_SVDM_TYPE BIT(15) +#define VDO_SVDM_VERS(x) ((x) << 13) +#define VDO_OPOS(x) ((x) << 8) +#define VDO_CMDT(x) ((x) << 6) +#define VDO_OPOS_MASK VDO_OPOS(0x7) +#define VDO_CMDT_MASK VDO_CMDT(0x3) + +#define CMDT_INIT 0 +#define CMDT_RSP_ACK 1 +#define CMDT_RSP_NAK 2 +#define CMDT_RSP_BUSY 3 + +/* reserved for SVDM ... for Google UVDM */ +#define VDO_SRC_INITIATOR (0 << 5) +#define VDO_SRC_RESPONDER BIT(5) + +#define CMD_DISCOVER_IDENT 1 +#define CMD_DISCOVER_SVID 2 +#define CMD_DISCOVER_MODES 3 +#define CMD_ENTER_MODE 4 +#define CMD_EXIT_MODE 5 +#define CMD_ATTENTION 6 +#define CMD_DP_STATUS 16 +#define CMD_DP_CONFIG 17 + +#define VDO_CMD_VENDOR(x) (((10 + (x)) & 0x1f)) + +/* ChromeOS specific commands */ +#define VDO_CMD_VERSION VDO_CMD_VENDOR(0) +#define VDO_CMD_SEND_INFO VDO_CMD_VENDOR(1) +#define VDO_CMD_READ_INFO VDO_CMD_VENDOR(2) +#define VDO_CMD_REBOOT VDO_CMD_VENDOR(5) +#define VDO_CMD_FLASH_ERASE VDO_CMD_VENDOR(6) +#define VDO_CMD_FLASH_WRITE VDO_CMD_VENDOR(7) +#define VDO_CMD_ERASE_SIG VDO_CMD_VENDOR(8) +#define VDO_CMD_PING_ENABLE VDO_CMD_VENDOR(10) +#define VDO_CMD_CURRENT VDO_CMD_VENDOR(11) +#define VDO_CMD_FLIP VDO_CMD_VENDOR(12) +#define VDO_CMD_GET_LOG VDO_CMD_VENDOR(13) +#define VDO_CMD_CCD_EN VDO_CMD_VENDOR(14) + +#define PD_VDO_VID(vdo) ((vdo) >> 16) +#define PD_VDO_SVDM(vdo) (((vdo) >> 15) & 1) +#define PD_VDO_OPOS(vdo) (((vdo) >> 8) & 0x7) +#define PD_VDO_CMD(vdo) ((vdo) & 0x1f) +#define PD_VDO_CMDT(vdo) (((vdo) >> 6) & 0x3) + +/* + * SVDM Identity request -> response + * + * Request is simply properly formatted SVDM header + * + * Response is 4 data objects: + * [0] :: SVDM header + * [1] :: Identitiy header + * [2] :: Cert Stat VDO + * [3] :: (Product | Cable) VDO + * [4] :: AMA VDO + * + */ +#define VDO_INDEX_HDR 0 +#define VDO_INDEX_IDH 1 +#define VDO_INDEX_CSTAT 2 +#define VDO_INDEX_CABLE 3 +#define VDO_INDEX_PRODUCT 3 +#define VDO_INDEX_AMA 4 +#define VDO_I(name) VDO_INDEX_##name + +/* + * SVDM Identity Header + * -------------------- + * <31> :: data capable as a USB host + * <30> :: data capable as a USB device + * <29:27> :: product type + * <26> :: modal operation supported (1b == yes) + * <25:16> :: SBZ + * <15:0> :: USB-IF assigned VID for this cable vendor + */ +#define IDH_PTYPE_UNDEF 0 +#define IDH_PTYPE_HUB 1 +#define IDH_PTYPE_PERIPH 2 +#define IDH_PTYPE_PCABLE 3 +#define IDH_PTYPE_ACABLE 4 +#define IDH_PTYPE_AMA 5 + +#define VDO_IDH(usbh, usbd, ptype, is_modal, vid) \ + ((usbh) << 31 | (usbd) << 30 | ((ptype) & 0x7) << 27 \ + | (is_modal) << 26 | ((vid) & 0xffff)) + +#define PD_IDH_PTYPE(vdo) (((vdo) >> 27) & 0x7) +#define PD_IDH_VID(vdo) ((vdo) & 0xffff) + +#define PD_IDH_MODAL_SUPPORT BIT(26) + +/* + * Cert Stat VDO + * ------------- + * <31:20> : SBZ + * <19:0> : USB-IF assigned TID for this cable + */ +#define VDO_CSTAT(tid) ((tid) & 0xfffff) +#define PD_CSTAT_TID(vdo) ((vdo) & 0xfffff) + +/* + * Product VDO + * ----------- + * <31:16> : USB Product ID + * <15:0> : USB bcdDevice + */ +#define VDO_PRODUCT(pid, bcd) (((pid) & 0xffff) << 16 | ((bcd) & 0xffff)) +#define PD_PRODUCT_PID(vdo) (((vdo) >> 16) & 0xffff) + +/* + * Cable VDO + * --------- + * <31:28> :: Cable HW version + * <27:24> :: Cable FW version + * <23:20> :: SBZ + * <19:18> :: type-C to Type-A/B/C (00b == A, 01 == B, 10 == C) + * <17> :: Type-C to Plug/Receptacle (0b == plug, 1b == receptacle) + * <16:13> :: cable latency (0001 == <10ns(~1m length)) + * <12:11> :: cable termination type (11b == both ends active VCONN req) + * <10> :: SSTX1 Directionality support (0b == fixed, 1b == cfgable) + * <9> :: SSTX2 Directionality support + * <8> :: SSRX1 Directionality support + * <7> :: SSRX2 Directionality support + * <6:5> :: Vbus current handling capability + * <4> :: Vbus through cable (0b == no, 1b == yes) + * <3> :: SOP" controller present? (0b == no, 1b == yes) + * <2:0> :: USB SS Signaling support + */ +#define CABLE_ATYPE 0 +#define CABLE_BTYPE 1 +#define CABLE_CTYPE 2 +#define CABLE_PLUG 0 +#define CABLE_RECEPTACLE 1 +#define CABLE_CURR_1A5 0 +#define CABLE_CURR_3A 1 +#define CABLE_CURR_5A 2 +#define CABLE_USBSS_U2_ONLY 0 +#define CABLE_USBSS_U31_GEN1 1 +#define CABLE_USBSS_U31_GEN2 2 +#define VDO_CABLE(hw, fw, cbl, gdr, lat, term, tx1d,\ + tx2d, rx1d, rx2d, cur, vps, sopp, usbss) \ + (((hw) & 0x7) << 28 | ((fw) & 0x7) << 24 | ((cbl) & 0x3) << 18 \ + | (gdr) << 17 | ((lat) & 0x7) << 13 | ((term) & 0x3) << 11 \ + | (tx1d) << 10 | (tx2d) << 9 | (rx1d) << 8 | (rx2d) << 7 \ + | ((cur) & 0x3) << 5 | (vps) << 4 | (sopp) << 3 \ + | ((usbss) & 0x7)) + +#define PD_VDO_CABLE_CURR(x) (((x) >> 5) & 0x03) + +/* + * AMA VDO + * --------- + * <31:28> :: Cable HW version + * <27:24> :: Cable FW version + * <23:12> :: SBZ + * <11> :: SSTX1 Directionality support (0b == fixed, 1b == cfgable) + * <10> :: SSTX2 Directionality support + * <9> :: SSRX1 Directionality support + * <8> :: SSRX2 Directionality support + * <7:5> :: Vconn power + * <4> :: Vconn power required + * <3> :: Vbus power required + * <2:0> :: USB SS Signaling support + */ +#define VDO_AMA(hw, fw, tx1d, tx2d, rx1d, rx2d, vcpwr, vcr, vbr, usbss) \ + (((hw) & 0x7) << 28 | ((fw) & 0x7) << 24 \ + | (tx1d) << 11 | (tx2d) << 10 | (rx1d) << 9 | (rx2d) << 8 \ + | ((vcpwr) & 0x3) << 5 | (vcr) << 4 | (vbr) << 3 \ + | ((usbss) & 0x7)) + +#define PD_VDO_AMA_VCONN_REQ(vdo) (((vdo) >> 4) & 1) +#define PD_VDO_AMA_VBUS_REQ(vdo) (((vdo) >> 3) & 1) + +#define AMA_VCONN_PWR_1W 0 +#define AMA_VCONN_PWR_1W5 1 +#define AMA_VCONN_PWR_2W 2 +#define AMA_VCONN_PWR_3W 3 +#define AMA_VCONN_PWR_4W 4 +#define AMA_VCONN_PWR_5W 5 +#define AMA_VCONN_PWR_6W 6 +#define AMA_USBSS_U2_ONLY 0 +#define AMA_USBSS_U31_GEN1 1 +#define AMA_USBSS_U31_GEN2 2 +#define AMA_USBSS_BBONLY 3 + +/* + * SVDM Discover SVIDs request -> response + * + * Request is properly formatted VDM Header with discover SVIDs command. + * Response is a set of SVIDs of all all supported SVIDs with all zero's to + * mark the end of SVIDs. If more than 12 SVIDs are supported command SHOULD be + * repeated. + */ +#define VDO_SVID(svid0, svid1) (((svid0) & 0xffff) << 16 | ((svid1) & 0xffff)) +#define PD_VDO_SVID_SVID0(vdo) ((vdo) >> 16) +#define PD_VDO_SVID_SVID1(vdo) ((vdo) & 0xffff) + +/* + * Google modes capabilities + * <31:8> : reserved + * <7:0> : mode + */ +#define VDO_MODE_GOOGLE(mode) ((mode) & 0xff) + +#define MODE_GOOGLE_FU 1 /* Firmware Update mode */ + +/* + * Mode Capabilities + * + * Number of VDOs supplied is SID dependent (but <= 6 VDOS?) + */ +#define VDO_MODE_CNT_DISPLAYPORT 1 + +/* + * DisplayPort modes capabilities + * ------------------------------- + * <31:24> : SBZ + * <23:16> : UFP_D pin assignment supported + * <15:8> : DFP_D pin assignment supported + * <7> : USB 2.0 signaling (0b=yes, 1b=no) + * <6> : Plug | Receptacle (0b == plug, 1b == receptacle) + * <5:2> : xxx1: Supports DPv1.3, xx1x Supports USB Gen 2 signaling + * Other bits are reserved. + * <1:0> : signal direction ( 00b=rsv, 01b=sink, 10b=src 11b=both ) + */ +#define VDO_MODE_DP(snkp, srcp, usb, gdr, sign, sdir) \ + (((snkp) & 0xff) << 16 | ((srcp) & 0xff) << 8 \ + | ((usb) & 1) << 7 | ((gdr) & 1) << 6 | ((sign) & 0xF) << 2 \ + | ((sdir) & 0x3)) +#define PD_DP_PIN_CAPS(x) ((((x) >> 6) & 0x1) ? (((x) >> 16) & 0x3f) \ + : (((x) >> 8) & 0x3f)) + +#define MODE_DP_PIN_A 0x01 +#define MODE_DP_PIN_B 0x02 +#define MODE_DP_PIN_C 0x04 +#define MODE_DP_PIN_D 0x08 +#define MODE_DP_PIN_E 0x10 +#define MODE_DP_PIN_F 0x20 + +/* Pin configs B/D/F support multi-function */ +#define MODE_DP_PIN_MF_MASK 0x2a +/* Pin configs A/B support BR2 signaling levels */ +#define MODE_DP_PIN_BR2_MASK 0x3 +/* Pin configs C/D/E/F support DP signaling levels */ +#define MODE_DP_PIN_DP_MASK 0x3c + +#define MODE_DP_V13 0x1 +#define MODE_DP_GEN2 0x2 + +#define MODE_DP_SNK 0x1 +#define MODE_DP_SRC 0x2 +#define MODE_DP_BOTH 0x3 + +#define MODE_DP_PORT_CAP(raw) ((raw) & 0x03) +#define MODE_DP_SIGNAL_SUPPORT(raw) (((raw) >> 2) & 0x0f) +#define MODE_DP_RECEPT(mode) (((mode) >> 6) & 0x01) + +#define MODE_DP_PIN_DFP(mode) (((mode) >> 8) & 0xff) +#define MODE_DP_PIN_UFP(mode) (((mode) >> 16) & 0xff) + +#define PD_DP_DFP_D_PIN_CAPS(x) (MODE_DP_RECEPT(x) ? \ + MODE_DP_PIN_DFP(x) : MODE_DP_PIN_UFP(x)) + +#define PD_DP_UFP_D_PIN_CAPS(x) (MODE_DP_RECEPT(x) ? \ + MODE_DP_PIN_UFP(x) : MODE_DP_PIN_DFP(x)) + +/* + * DisplayPort Status VDO + * ---------------------- + * <31:9> : SBZ + * <8> : IRQ_HPD : 1 == irq arrived since last message otherwise 0. + * <7> : HPD state : 0 = HPD_LOW, 1 == HPD_HIGH + * <6> : Exit DP Alt mode: 0 == maintain, 1 == exit + * <5> : USB config : 0 == maintain current, 1 == switch to USB from DP + * <4> : Multi-function preference : 0 == no pref, 1 == MF preferred. + * <3> : enabled : is DPout on/off. + * <2> : power low : 0 == normal or LPM disabled, 1 == DP disabled for LPM + * <1:0> : connect status : 00b == no (DFP|UFP)_D is connected or disabled. + * 01b == DFP_D connected, 10b == UFP_D connected, 11b == both. + */ + +#define VDO_DP_STATUS(irq, lvl, amode, usbc, mf, en, lp, conn) \ + (((irq) & 1) << 8 | ((lvl) & 1) << 7 | ((amode) & 1) << 6 \ + | ((usbc) & 1) << 5 | ((mf) & 1) << 4 | ((en) & 1) << 3 \ + | ((lp) & 1) << 2 | (((conn) & 0x3) << 0)) + +#define PD_VDO_DPSTS_HPD_IRQ(x) (((x) >> 8) & 1) +#define PD_VDO_DPSTS_HPD_LVL(x) (((x) >> 7) & 1) +#define PD_VDO_DPSTS_MF_PREF(x) (((x) >> 4) & 1) + +#define PD_VDO_DPSTS_CONNECT(x) (((x) >> 0) & 0x03) + +#define DPSTS_DISCONNECT 0 + +#define DPSTS_DFP_D_CONNECTED BIT(0) +#define DPSTS_UFP_D_CONNECTED BIT(1) +#define DPSTS_BOTH_CONNECTED (DPSTS_DFP_D_CONNECTED | DPSTS_UFP_D_CONNECTED) + +/* UFP_U only */ +#define DPSTS_DP_ENABLED BIT(3) +#define DPSTS_DP_MF_PREF BIT(4) +#define DPSTS_DP_USB_CONFIG BIT(5) +#define DPSTS_DP_EXIT_ALT_MODE BIT(6) + +/* UFP_D only */ +#define DPSTS_DP_HPD_STATUS BIT(7) +#define DPSTS_DP_HPD_IRQ BIT(8) + +/* Per DisplayPort Spec v1.3 Section 3.3 */ +#define HPD_USTREAM_DEBOUNCE_LVL (2 * MSEC) +#define HPD_USTREAM_DEBOUNCE_IRQ (250) +#define HPD_DSTREAM_DEBOUNCE_IRQ (750) /* between 500-1000us */ + +/* + * DisplayPort Configure VDO + * ------------------------- + * <31:24> : SBZ + * <23:16> : SBZ + * <15:8> : Pin assignment requested. Choose one from mode caps. + * <7:6> : SBZ + * <5:2> : signalling : 1h == DP v1.3, 2h == Gen 2 + * Oh is only for USB, remaining values are reserved + * <1:0> : cfg : 00 == USB, 01 == DFP_D, 10 == UFP_D, 11 == reserved + */ + +#define DP_CONFIG_USB 0 +#define DP_CONFIG_DFP_D 1 +#define DP_CONFIG_UFP_D 2 + +#define VDO_DP_CFG(pin, sig, cfg) \ + (((pin) & 0xff) << 8 | ((sig) & 0xf) << 2 | ((cfg) & 0x3)) + +#define VDO_DP_DFP_CFG(pin, sig) VDO_DP_CFG(pin, sig, DP_CONFIG_DFP_D) +#define VDO_DP_UFP_CFG(pin, sig) VDO_DP_CFG(pin, sig, DP_CONFIG_UFP_D) + +#define PD_DP_CFG_USB(x) (((x) & 0x3) == DP_CONFIG_USB) +#define PD_DP_CFG_DFP_D(x) (((x) & 0x3) == DP_CONFIG_DFP_D) +#define PD_DP_CFG_UFP_D(x) (((x) & 0x3) == DP_CONFIG_UFP_D) +#define PD_DP_CFG_DPON(x) (PD_DP_CFG_DFP_D(x) | PD_DP_CFG_UFP_D(x)) + +#define DP_SIG_DPV13 (0x01) +#define DP_SIG_GEN2 (0x02) + +#define DP_PIN_ASSIGN_SUPPORT_A BIT(0) +#define DP_PIN_ASSIGN_SUPPORT_B BIT(1) +#define DP_PIN_ASSIGN_SUPPORT_C BIT(2) +#define DP_PIN_ASSIGN_SUPPORT_D BIT(3) +#define DP_PIN_ASSIGN_SUPPORT_E BIT(4) +#define DP_PIN_ASSIGN_SUPPORT_F BIT(5) + +/* + * Get the pin assignment mask + * for backward compatibility, if it is null, + * get the former sink pin assignment we used to be in <23:16>. + */ + +#define PD_DP_CFG_PIN(x) (((x) >> 8) & 0xff) + +/* + * ChromeOS specific PD device Hardware IDs. Used to identify unique + * products and used in VDO_INFO. Note this field is 10 bits. + */ +#define USB_PD_HW_DEV_ID_RESERVED 0 +#define USB_PD_HW_DEV_ID_ZINGER 1 +#define USB_PD_HW_DEV_ID_MINIMUFFIN 2 +#define USB_PD_HW_DEV_ID_DINGDONG 3 +#define USB_PD_HW_DEV_ID_HOHO 4 +#define USB_PD_HW_DEV_ID_HONEYBUNS 5 + +/* + * ChromeOS specific VDO_CMD_READ_INFO responds with device info including: + * RW Hash: First 20 bytes of SHA-256 of RW (20 bytes) + * HW Device ID: unique descriptor for each ChromeOS model (2 bytes) + * top 6 bits are minor revision, bottom 10 bits are major + * SW Debug Version: Software version useful for debugging (15 bits) + * IS RW: True if currently in RW, False otherwise (1 bit) + */ +#define VDO_INFO(id, id_minor, ver, is_rw) ((id_minor) << 26 \ + | ((id) & 0x3ff) << 16 \ + | ((ver) & 0x7fff) << 1 \ + | ((is_rw) & 1)) +#define VDO_INFO_HW_DEV_ID(x) ((x) >> 16) +#define VDO_INFO_SW_DBG_VER(x) (((x) >> 1) & 0x7fff) +#define VDO_INFO_IS_RW(x) ((x) & 1) + +#define HW_DEV_ID_MAJ(x) ((x) & 0x3ff) +#define HW_DEV_ID_MIN(x) ((x) >> 10) + +/* USB-IF SIDs */ +#define USB_SID_PD 0xff00 /* power delivery */ +#define USB_SID_DISPLAYPORT 0xff01 /* display port */ +#define USB_SID_RICHTEK 0x29cf /* demo uvdm */ +#define USB_SID_DIRECTCHARGE 0x29cf /* direct charge */ + +/* DPM Flags */ + +#define DPM_FLAGS_PARTNER_DR_POWER BIT(0) +#define DPM_FLAGS_PARTNER_DR_DATA BIT(1) +#define DPM_FLAGS_PARTNER_EXTPOWER BIT(2) +#define DPM_FLAGS_PARTNER_USB_COMM BIT(3) +#define DPM_FLAGS_PARTNER_USB_SUSPEND BIT(4) +#define DPM_FLAGS_PARTNER_HIGH_CAP BIT(5) + +#define DPM_FLAGS_PARTNER_MISMATCH BIT(7) +#define DPM_FLAGS_PARTNER_GIVE_BACK BIT(8) +#define DPM_FLAGS_PARTNER_NO_SUSPEND BIT(9) + +#define DPM_FLAGS_RESET_PARTNER_MASK \ + (DPM_FLAGS_PARTNER_DR_POWER | DPM_FLAGS_PARTNER_DR_DATA | \ + DPM_FLAGS_PARTNER_EXTPOWER | DPM_FLAGS_PARTNER_USB_COMM) + +#define DPM_FLAGS_CHECK_DC_MODE BIT(20) +#define DPM_FLAGS_CHECK_UFP_SVID BIT(21) +#define DPM_FLAGS_CHECK_EXT_POWER BIT(22) +#define DPM_FLAGS_CHECK_DP_MODE BIT(23) +#define DPM_FLAGS_CHECK_SINK_CAP BIT(24) +#define DPM_FLAGS_CHECK_SOURCE_CAP BIT(25) +#define DPM_FLAGS_CHECK_UFP_ID BIT(26) +#define DPM_FLAGS_CHECK_CABLE_ID BIT(27) +#define DPM_FLAGS_CHECK_CABLE_ID_DFP BIT(28) +#define DPM_FLAGS_CHECK_PR_ROLE BIT(29) +#define DPM_FLAGS_CHECK_DR_ROLE BIT(30) + +/* DPM_CAPS */ + +#define DPM_CAP_LOCAL_DR_POWER BIT(0) +#define DPM_CAP_LOCAL_DR_DATA BIT(1) +#define DPM_CAP_LOCAL_EXT_POWER BIT(2) +#define DPM_CAP_LOCAL_USB_COMM BIT(3) +#define DPM_CAP_LOCAL_USB_SUSPEND BIT(4) +#define DPM_CAP_LOCAL_HIGH_CAP BIT(5) +#define DPM_CAP_LOCAL_GIVE_BACK BIT(6) +#define DPM_CAP_LOCAL_NO_SUSPEND BIT(7) +#define DPM_CAP_LOCAL_VCONN_SUPPLY BIT(8) + +#define DPM_CAP_ATTEMP_ENTER_DC_MODE BIT(11) +#define DPM_CAP_ATTEMP_DISCOVER_CABLE_DFP BIT(12) +#define DPM_CAP_ATTEMP_ENTER_DP_MODE BIT(13) +#define DPM_CAP_ATTEMP_DISCOVER_CABLE BIT(14) +#define DPM_CAP_ATTEMP_DISCOVER_ID BIT(15) + +enum dpm_cap_pr_check_prefer { + DPM_CAP_PR_CHECK_DISABLE = 0, + DPM_CAP_PR_CHECK_PREFER_SNK = 1, + DPM_CAP_PR_CHECK_PREFER_SRC = 2, +}; + +#define DPM_CAP_PR_CHECK_PROP(cap) (((cap) & 0x03) << 16) +#define DPM_CAP_EXTRACT_PR_CHECK(raw) (((raw) >> 16) & 0x03) +#define DPM_CAP_PR_SWAP_REJECT_AS_SRC BIT(18) +#define DPM_CAP_PR_SWAP_REJECT_AS_SNK BIT(19) +#define DPM_CAP_PR_SWAP_CHECK_GP_SRC BIT(20) +#define DPM_CAP_PR_SWAP_CHECK_GP_SNK BIT(21) +#define DPM_CAP_PR_SWAP_CHECK_GOOD_POWER \ + (DPM_CAP_PR_SWAP_CHECK_GP_SRC | DPM_CAP_PR_SWAP_CHECK_GP_SNK) + +enum dpm_cap_dr_check_prefer { + DPM_CAP_DR_CHECK_DISABLE = 0, + DPM_CAP_DR_CHECK_PREFER_UFP = 1, + DPM_CAP_DR_CHECK_PREFER_DFP = 2, +}; + +#define DPM_CAP_DR_CHECK_PROP(cap) (((cap) & 0x03) << 22) +#define DPM_CAP_EXTRACT_DR_CHECK(raw) (((raw) >> 22) & 0x03) +#define DPM_CAP_DR_SWAP_REJECT_AS_DFP BIT(24) +#define DPM_CAP_DR_SWAP_REJECT_AS_UFP BIT(25) + +#define DPM_CAP_DP_PREFER_MF BIT(29) +#define DPM_CAP_SNK_PREFER_LOW_VOLTAGE BIT(30) +#define DPM_CAP_SNK_IGNORE_MISMATCH_CURRENT BIT(31) + +/* PD counter definitions */ +#define PD_MESSAGE_ID_COUNT 7 +#define PD_HARD_RESET_COUNT 2 +#define PD_CAPS_COUNT 50 +#define PD_GET_SNK_CAP_RETRIES 3 +#define PD_GET_SRC_CAP_RETRIES 3 +#define PD_DISCOVER_ID_COUNT 3 /* max : 20 */ + +enum { + PD_WAIT_VBUS_DISABLE = 0, + PD_WAIT_VBUS_VALID_ONCE = 1, + PD_WAIT_VBUS_INVALID_ONCE = 2, + PD_WAIT_VBUS_SAFE0V_ONCE = 3, + PD_WAIT_VBUS_STABLE_ONCE = 4, +}; + +typedef struct __pd_port_power_cababilities { + u8 nr; + u32 pdos[7]; +} pd_port_power_caps; + +#define PD_SVID_DATA_NR 2 /* must < 11 */ + +typedef struct __svdm_mode { + u8 mode_cnt; + u32 mode_vdo[VDO_MAX_DATA_SIZE]; +} svdm_mode_t; + +struct __svdm_svid_ops; +typedef struct __svdm_svid_data { + bool exist; + u16 svid; + u8 active_mode; + svdm_mode_t local_mode; + svdm_mode_t remote_mode; + const struct __svdm_svid_ops *ops; +} svdm_svid_data_t; + +typedef struct __svdm_svid_list { + u8 cnt; + u16 svids[VDO_MAX_SVID_SIZE]; +} svdm_svid_list_t; + +typedef struct __pd_port { + struct tcpc_device *tcpc_dev; + struct mutex pd_lock; + + /* PD */ + bool explicit_contract; + bool invalid_contract; + bool vconn_source; + +#ifdef CONFIG_USB_PD_DFP_READY_DISCOVER_ID + bool vconn_return; +#endif /* CONFIG_USB_PD_DFP_READY_DISCOVER_ID */ + + bool pe_ready; + bool pd_connected; + bool pd_prev_connected; + bool msg_output_lock; + + u8 state_machine; + u8 pd_connect_state; + + bool reset_vdm_state; + u8 pe_pd_state; + u8 pe_vdm_state; + + u8 pe_state_next; + u8 pe_state_curr; + + u8 data_role; + u8 power_role; + + u8 cap_counter; + u8 discover_id_counter; + u8 hard_reset_counter; + u8 snk_cap_count; + u8 src_cap_count; + u8 get_snk_cap_count; + u8 get_src_cap_count; + + u8 msg_id_rx[PD_SOP_NR]; + u8 msg_id_rx_init[PD_SOP_NR]; + u8 msg_id_tx[PD_SOP_NR]; + + u32 last_rdo; + u32 cable_vdos[VDO_MAX_SIZE]; + bool power_cable_present; + + u8 id_vdo_nr; + u32 id_vdos[VDO_MAX_DATA_SIZE]; + +#ifdef CONFIG_USB_PD_KEEP_SVIDS + svdm_svid_list_t remote_svid_list; +#endif + + u8 svid_data_cnt; + svdm_svid_data_t svid_data[PD_SVID_DATA_NR]; + + bool during_swap; /* pr or dr swap */ + +/* DPM */ + int request_v; + int request_i; + int request_v_new; + int request_i_new; + int request_i_op; + int request_i_max; + + u8 local_selected_cap; + u8 remote_selected_cap; + pd_port_power_caps local_src_cap; + pd_port_power_caps local_snk_cap; + pd_port_power_caps local_src_cap_default; + pd_port_power_caps remote_src_cap; + pd_port_power_caps remote_snk_cap; + + u16 mode_svid; + u8 mode_obj_pos; + bool modal_operation; + bool dpm_ack_immediately; + + u32 dpm_flags; + u32 dpm_init_flags; + u32 dpm_caps; + u32 dpm_dfp_retry_cnt; + +#ifdef CONFIG_USB_PD_CUSTOM_DBGACC + bool custom_dbgacc; +#endif /* CONFIG_USB_PD_CUSTOM_DBGACC */ +} pd_port_t; + +int pd_core_init(struct tcpc_device *tcpc_dev); +int pd_alert_vbus_changed(pd_port_t *pd_port, int vbus_level); + +static inline int pd_is_auto_discover_cable_id(pd_port_t *pd_port) +{ + if (pd_port->dpm_flags & DPM_FLAGS_CHECK_CABLE_ID) { + if (pd_port->discover_id_counter < PD_DISCOVER_ID_COUNT) + return true; + + pd_port->dpm_flags &= ~DPM_FLAGS_CHECK_CABLE_ID; + return false; + } + + return false; +} + +static inline int pd_is_support_modal_operation(pd_port_t *pd_port) +{ + if (!(pd_port->id_vdos[0] & PD_IDH_MODAL_SUPPORT)) + return false; + + return (pd_port->svid_data_cnt > 0); +} + +/* new definitions*/ + +#define PD_RX_CAP_PE_IDLE (0) +#define PD_RX_CAP_PE_DISABLE (TCPC_RX_CAP_HARD_RESET) +#define PD_RX_CAP_PE_STARTUP (TCPC_RX_CAP_HARD_RESET) +#define PD_RX_CAP_PE_HARDRESET (0) +#define PD_RX_CAP_PE_SEND_WAIT_CAP \ + (TCPC_RX_CAP_HARD_RESET | TCPC_RX_CAP_SOP) +#define PD_RX_CAP_PE_DISCOVER_CABLE \ + (TCPC_RX_CAP_HARD_RESET | TCPC_RX_CAP_SOP_PRIME) +#define PD_RX_CAP_PE_READY_UFP \ + (TCPC_RX_CAP_HARD_RESET | TCPC_RX_CAP_SOP) + +#ifdef CONFIG_PD_DISCOVER_CABLE_ID +#define PD_RX_CAP_PE_READY_DFP \ + (TCPC_RX_CAP_HARD_RESET | TCPC_RX_CAP_SOP | TCPC_RX_CAP_SOP_PRIME) +#else +#define PD_RX_CAP_PE_READY_DFP (TCPC_RX_CAP_HARD_RESET | TCPC_RX_CAP_SOP) +#endif + +enum { + PD_BIST_MODE_DISABLE = 0, + PD_BIST_MODE_EVENT_PENDING, + PD_BIST_MODE_TEST_DATA, +}; + +void pd_reset_svid_data(pd_port_t *pd_port); +int pd_reset_protocol_layer(pd_port_t *pd_port); + +int pd_set_rx_enable(pd_port_t *pd_port, u8 enable); + +int pd_enable_vbus_valid_detection(pd_port_t *pd_port, bool wait_valid); +int pd_enable_vbus_safe0v_detection(pd_port_t *pd_port); +int pd_enable_vbus_stable_detection(pd_port_t *pd_port); + +u32 pd_reset_pdo_power(u32 pdo, u32 imax); + +void pd_extract_rdo_power( + u32 rdo, u32 pdo, u32 *op_curr, + u32 *max_curr); + +void pd_extract_pdo_power(u32 pdo, + u32 *vmin, u32 *vmax, u32 *ioper); + +u32 pd_extract_cable_curr(u32 vdo); + +int pd_set_data_role(pd_port_t *pd_port, u8 dr); +int pd_set_power_role(pd_port_t *pd_port, u8 pr); +int pd_init_role(pd_port_t *pd_port, u8 pr, u8 dr, bool vr); + +int pd_set_cc_res(pd_port_t *pd_port, int pull); +int pd_set_vconn(pd_port_t *pd_port, int enable); +int pd_reset_local_hw(pd_port_t *pd_port); + +int pd_enable_bist_test_mode(pd_port_t *pd_port, bool en); + +void pd_lock_msg_output(pd_port_t *pd_port); +void pd_unlock_msg_output(pd_port_t *pd_port); + +int pd_update_connect_state(pd_port_t *pd_port, u8 state); +void pd_update_dpm_request_state(pd_port_t *pd_port, u8 state); + +/* ---- PD notify TCPC Policy Engine State Changed ---- */ + +void pd_try_put_pe_idle_event(pd_port_t *pd_port); +void pd_notify_pe_transit_to_default(pd_port_t *pd_port); +void pd_notify_pe_hard_reset_completed(pd_port_t *pd_port); +void pd_notify_pe_send_hard_reset(pd_port_t *pd_port); +void pd_notify_pe_idle(pd_port_t *pd_port); +void pd_notify_pe_wait_vbus_once(pd_port_t *pd_port, int wait_evt); +void pd_notify_pe_error_recovery(pd_port_t *pd_port); +void pd_notify_pe_execute_pr_swap(pd_port_t *pd_port, bool start_swap); +void pd_notify_pe_cancel_pr_swap(pd_port_t *pd_port); +void pd_notify_pe_reset_protocol(pd_port_t *pd_port); +void pd_noitfy_pe_bist_mode(pd_port_t *pd_port, u8 mode); +void pd_notify_pe_pr_changed(pd_port_t *pd_port); +void pd_notify_pe_src_explicit_contract(pd_port_t *pd_port); +void pd_notify_pe_transmit_msg(pd_port_t *pd_port, u8 type); +void pd_notify_pe_recv_ping_event(pd_port_t *pd_port); + +/* ---- pd_timer ---- */ + +static inline void pd_restart_timer(pd_port_t *pd_port, u32 timer_id) +{ + return tcpc_restart_timer(pd_port->tcpc_dev, timer_id); +} + +static inline void pd_enable_timer(pd_port_t *pd_port, u32 timer_id) +{ + return tcpc_enable_timer(pd_port->tcpc_dev, timer_id); +} + +static inline void pd_disable_timer(pd_port_t *pd_port, u32 timer_id) +{ + return tcpc_disable_timer(pd_port->tcpc_dev, timer_id); +} + +static inline void pd_reset_pe_timer(pd_port_t *pd_port) +{ + tcpc_reset_pe_timer(pd_port->tcpc_dev); +} + +/* ---- pd_event ---- */ + +static inline void pd_free_pd_event(pd_port_t *pd_port, pd_event_t *pd_event) +{ + pd_free_event(pd_port->tcpc_dev, pd_event); +} + +static inline bool pd_put_pe_event(pd_port_t *pd_port, u8 pe_event) +{ + pd_event_t evt = { + .event_type = PD_EVT_PE_MSG, + .msg = pe_event, + .pd_msg = NULL, + }; + + return pd_put_event(pd_port->tcpc_dev, &evt, false); +} + +static inline bool pd_put_dpm_event(pd_port_t *pd_port, u8 event) +{ + pd_event_t evt = { + .event_type = PD_EVT_DPM_MSG, + .msg = event, + .pd_msg = NULL, + }; + + return pd_put_event(pd_port->tcpc_dev, &evt, false); +} + +static inline bool pd_put_dpm_pd_request_event( + pd_port_t *pd_port, u8 event) +{ + pd_event_t evt = { + .event_type = PD_EVT_DPM_MSG, + .msg = PD_DPM_PD_REQUEST, + .msg_sec = event, + .pd_msg = NULL, + }; + + return pd_put_event(pd_port->tcpc_dev, &evt, false); +} + +static inline bool vdm_put_dpm_vdm_request_event( + pd_port_t *pd_port, u8 event) +{ + bool ret; + pd_event_t evt = { + .event_type = PD_EVT_DPM_MSG, + .msg = PD_DPM_VDM_REQUEST, + .msg_sec = event, + .pd_msg = NULL, + }; + + ret = pd_put_vdm_event(pd_port->tcpc_dev, &evt, false); + + if (ret) { + pd_port->reset_vdm_state = true; + pd_port->pe_vdm_state = pd_port->pe_pd_state; + } + + return ret; +} + +static inline bool pd_put_dpm_notify_event(pd_port_t *pd_port, u8 notify) +{ + pd_event_t evt = { + .event_type = PD_EVT_DPM_MSG, + .msg = PD_DPM_NOTIFIED, + .msg_sec = notify, + .pd_msg = NULL, + }; + + return pd_put_event(pd_port->tcpc_dev, &evt, false); +} + +static inline bool pd_put_dpm_ack_event(pd_port_t *pd_port) +{ + pd_event_t evt = { + .event_type = PD_EVT_DPM_MSG, + .msg = PD_DPM_ACK, + .pd_msg = NULL, + }; + + return pd_put_event(pd_port->tcpc_dev, &evt, false); +} + +static inline bool pd_put_dpm_nak_event(pd_port_t *pd_port, u8 notify) +{ + pd_event_t evt = { + .event_type = PD_EVT_DPM_MSG, + .msg = PD_DPM_NAK, + .msg_sec = notify, + .pd_msg = NULL, + }; + + return pd_put_event(pd_port->tcpc_dev, &evt, false); +} + +static inline bool vdm_put_hw_event( + struct tcpc_device *tcpc_dev, u8 hw_event) +{ + pd_event_t evt = { + .event_type = PD_EVT_HW_MSG, + .msg = hw_event, + .pd_msg = NULL, + }; + + return pd_put_vdm_event(tcpc_dev, &evt, false); +} + +static inline bool vdm_put_dpm_event( + pd_port_t *pd_port, u8 dpm_event, pd_msg_t *pd_msg) +{ + pd_event_t evt = { + .event_type = PD_EVT_DPM_MSG, + .msg = dpm_event, + .pd_msg = pd_msg, + }; + + return pd_put_vdm_event(pd_port->tcpc_dev, &evt, false); +} + +static inline bool vdm_put_dpm_notified_event(pd_port_t *pd_port) +{ + return vdm_put_dpm_event(pd_port, PD_DPM_NOTIFIED, NULL); +} + +static inline bool vdm_put_dpm_discover_cable_event(pd_port_t *pd_port) +{ + pd_port->pe_vdm_state = pd_port->pe_pd_state; + return vdm_put_dpm_event(pd_port, PD_DPM_DISCOVER_CABLE_ID, NULL); +} + +static inline bool pd_put_hw_event( + struct tcpc_device *tcpc_dev, u8 hw_event) +{ + pd_event_t evt = { + .event_type = PD_EVT_HW_MSG, + .msg = hw_event, + .pd_msg = NULL, + }; + + return pd_put_event(tcpc_dev, &evt, false); +} + +static inline bool pd_put_cc_attached_event( + struct tcpc_device *tcpc_dev, u8 type) +{ + pd_event_t evt = { + .event_type = PD_EVT_HW_MSG, + .msg = PD_HW_CC_ATTACHED, + .msg_sec = type, + .pd_msg = NULL, + }; + + return pd_put_event(tcpc_dev, &evt, false); +} + +/* ---- Handle PD Message ----*/ + +int pd_handle_soft_reset(pd_port_t *pd_port, u8 state_machine); + +/* ---- Send PD Message ----*/ + +int pd_send_ctrl_msg( + pd_port_t *pd_port, u8 sop_type, u8 msg); + +int pd_send_data_msg(pd_port_t *pd_port, + u8 sop_type, u8 msg, u8 cnt, u32 *payload); + +int pd_send_soft_reset(pd_port_t *pd_port, u8 state_machine); +int pd_send_hard_reset(pd_port_t *pd_port); + +int pd_send_bist_mode2(pd_port_t *pd_port); +int pd_disable_bist_mode2(pd_port_t *pd_port); + +/* ---- Send / Reply SVDM Command ----*/ + +/* Auto enable pd_timer_vdm_response if success */ +int pd_send_svdm_request(pd_port_t *pd_port, + u8 sop_type, u16 svid, u8 vdm_cmd, + u8 obj_pos, u8 cnt, u32 *data_obj); + +int pd_reply_svdm_request(pd_port_t *pd_port, + pd_event_t *pd_event, u8 reply, + u8 cnt, u32 *data_obj); + +static inline int pd_send_vdm_discover_id( + pd_port_t *pd_port, u8 sop_type) +{ + return pd_send_svdm_request( + pd_port, sop_type, USB_SID_PD, CMD_DISCOVER_IDENT, 0, 0, NULL); +} + +static inline int pd_send_vdm_discover_svids( + pd_port_t *pd_port, u8 sop_type) +{ + return pd_send_svdm_request( + pd_port, sop_type, USB_SID_PD, CMD_DISCOVER_SVID, 0, 0, NULL); +} + +static inline int pd_send_vdm_discover_modes( + pd_port_t *pd_port, u8 sop_type, u16 svid) +{ + return pd_send_svdm_request( + pd_port, sop_type, svid, CMD_DISCOVER_MODES, 0, 0, NULL); +} + +static inline int pd_send_vdm_enter_mode( + pd_port_t *pd_port, u8 sop_type, u16 svid, u8 obj_pos) +{ + return pd_send_svdm_request( + pd_port, sop_type, svid, CMD_ENTER_MODE, obj_pos, 0, NULL); +} + +static inline int pd_send_vdm_exit_mode( + pd_port_t *pd_port, u8 sop_type, u16 svid, u8 obj_pos) +{ + return pd_send_svdm_request( + pd_port, sop_type, svid, CMD_EXIT_MODE, obj_pos, 0, NULL); +} + +static inline int pd_send_vdm_attention( + pd_port_t *pd_port, u8 sop_type, u16 svid, u8 obj_pos) +{ + return pd_send_svdm_request( + pd_port, sop_type, svid, CMD_ATTENTION, obj_pos, 0, NULL); +} + +static inline int pd_send_vdm_dp_attention(pd_port_t *pd_port, + u8 sop_type, u8 obj_pos, + u32 dp_status) +{ + return pd_send_svdm_request(pd_port, sop_type, + USB_SID_DISPLAYPORT, CMD_ATTENTION, obj_pos, 1, &dp_status); +} + +static inline int pd_send_vdm_dp_status(pd_port_t *pd_port, + u8 sop_type, u8 obj_pos, + u8 cnt, u32 *data_obj) +{ + return pd_send_svdm_request(pd_port, sop_type, + USB_SID_DISPLAYPORT, CMD_DP_STATUS, obj_pos, cnt, data_obj); +} + +static inline int pd_send_vdm_dp_config(pd_port_t *pd_port, + u8 sop_type, u8 obj_pos, + u8 cnt, u32 *data_obj) +{ + return pd_send_svdm_request(pd_port, sop_type, + USB_SID_DISPLAYPORT, CMD_DP_CONFIG, obj_pos, cnt, data_obj); +} + +static inline int pd_reply_svdm_request_simply( + pd_port_t *pd_port, pd_event_t *pd_event, u8 reply) +{ + return pd_reply_svdm_request(pd_port, pd_event, reply, 0, NULL); +} +#endif /* PD_CORE_H_ */ |