@@ -185,7 +185,8 @@
S(UNSTRUCTURED_VDMS), \
S(STRUCTURED_VDMS), \
S(COUNTRY_INFO), \
- S(COUNTRY_CODES)
+ S(COUNTRY_CODES), \
+ S(REVISION_INFORMATION)
#define GENERATE_ENUM(e) e
#define GENERATE_STRING(s) #s
@@ -225,6 +226,7 @@ enum pd_msg_request {
PD_MSG_CTRL_NOT_SUPP,
PD_MSG_DATA_SINK_CAP,
PD_MSG_DATA_SOURCE_CAP,
+ PD_MSG_DATA_REV,
};
enum adev_actions {
@@ -1244,6 +1246,24 @@ static u32 tcpm_forge_legacy_pdo(struct tcpm_port *port, u32 pdo, enum typec_rol
}
}
+static int tcpm_pd_send_revision(struct tcpm_port *port)
+{
+ struct pd_message msg;
+ u32 rmdo;
+
+ memset(&msg, 0, sizeof(msg));
+ rmdo = RMDO(port->pd_rev.rev_major, port->pd_rev.rev_minor,
+ port->pd_rev.ver_major, port->pd_rev.ver_minor);
+ msg.payload[0] = cpu_to_le32(rmdo);
+ msg.header = PD_HEADER_LE(PD_DATA_REVISION,
+ port->pwr_role,
+ port->data_role,
+ port->negotiated_rev,
+ port->message_id,
+ 1);
+ return tcpm_pd_transmit(port, TCPC_TX_SOP, &msg);
+}
+
static int tcpm_pd_send_source_caps(struct tcpm_port *port)
{
struct pd_message msg;
@@ -3547,6 +3567,17 @@ static void tcpm_pd_ctrl_request(struct tcpm_port *port,
PD_MSG_CTRL_NOT_SUPP,
NONE_AMS);
break;
+ case PD_CTRL_GET_REVISION:
+ if (port->negotiated_rev >= PD_REV30 && port->pd_rev.rev_major)
+ tcpm_pd_handle_msg(port, PD_MSG_DATA_REV,
+ REVISION_INFORMATION);
+ else
+ tcpm_pd_handle_msg(port,
+ port->negotiated_rev < PD_REV30 ?
+ PD_MSG_CTRL_REJECT :
+ PD_MSG_CTRL_NOT_SUPP,
+ NONE_AMS);
+ break;
default:
tcpm_pd_handle_msg(port,
port->negotiated_rev < PD_REV30 ?
@@ -3791,6 +3822,14 @@ static bool tcpm_send_queued_message(struct tcpm_port *port)
tcpm_ams_finish(port);
}
break;
+ case PD_MSG_DATA_REV:
+ ret = tcpm_pd_send_revision(port);
+ if (ret)
+ tcpm_log(port,
+ "Unable to send revision msg, ret=%d",
+ ret);
+ tcpm_ams_finish(port);
+ break;
default:
break;
}
@@ -33,7 +33,9 @@ enum pd_ctrl_msg_type {
PD_CTRL_FR_SWAP = 19,
PD_CTRL_GET_PPS_STATUS = 20,
PD_CTRL_GET_COUNTRY_CODES = 21,
- /* 22-31 Reserved */
+ /* 22-23 Reserved */
+ PD_CTRL_GET_REVISION = 24,
+ /* 25-31 Reserved */
};
enum pd_data_msg_type {
@@ -46,7 +48,9 @@ enum pd_data_msg_type {
PD_DATA_ALERT = 6,
PD_DATA_GET_COUNTRY_INFO = 7,
PD_DATA_ENTER_USB = 8,
- /* 9-14 Reserved */
+ /* 9-11 Reserved */
+ PD_DATA_REVISION = 12,
+ /* 13-14 Reserved */
PD_DATA_VENDOR_DEF = 15,
/* 16-31 Reserved */
};
@@ -453,6 +457,20 @@ static inline unsigned int rdo_max_power(u32 rdo)
#define EUDO_TBT_SUPPORT BIT(14)
#define EUDO_HOST_PRESENT BIT(13)
+/*
+ * Request Message Data Object (PD Revision 3.1+ only)
+ * --------
+ * <31:28> :: Revision Major
+ * <27:24> :: Revision Minor
+ * <23:20> :: Version Major
+ * <19:16> :: Version Minor
+ * <15:0> :: Reserved, Shall be set to zero
+ */
+
+#define RMDO(rev_maj, rev_min, ver_maj, ver_min) \
+ (((rev_maj) & 0xf) << 28 | ((rev_min) & 0xf) << 24 | \
+ ((ver_maj) & 0xf) << 20 | ((ver_min) & 0xf) << 16)
+
/* USB PD timers and counters */
#define PD_T_NO_RESPONSE 5000 /* 4.5 - 5.5 seconds */
#define PD_T_DB_DETECT 10000 /* 10 - 15 seconds */