UPSTREAM: usb: typec: tcpm: Add new AMS for Get_Revision response
This commit adds a new AMS for responding to a "Get_Revision" request.
Revision message consists of the following fields:
+----------------------------------------------------+
| Header | RMDO |
| No. of data objects = 1 | |
+----------------------------------------------------+
While RMDO consists of:
* B31..28 Revision Major
* B27..24 Revision Minor
* B23..20 Version Major
* B19..16 Version Minor
* B15..0 Reserved, shall be set to zero.
As per the PD spec ("8.3.3.16.2.1 PR_Give_Revision State"), a request is
only expected when an explicit contract is established and the port is
in ready state. This AMS is only supported for PD >= 3.0.
Signed-off-by: Amit Sunil Dhamne <amitsd@google.com>
Reviewed-by: Badhri Jagan Sridharan <badhri@google.com>
Link: https://lore.kernel.org/r/20241210-get_rev_upstream-v2-3-d0094e52d48f@google.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Amit Sunil Dhamne <amitsd@google.com>
Bug: 317129663
(cherry picked from commit 8cda395b79d90709fde3a9963c667d849cc5718f)
Change-Id: I1f25dae338908ce9191a24bdf29ad2a19c08767f
Signed-off-by: Amit Sunil Dhamne <amitsd@google.com>
diff --git a/android/abi_gki_aarch64.stg b/android/abi_gki_aarch64.stg
index bac2bdd..2e3fb78 100644
--- a/android/abi_gki_aarch64.stg
+++ b/android/abi_gki_aarch64.stg
@@ -151044,6 +151044,12 @@
offset: 768
}
member {
+ id: 0xf4dec516
+ name: "pd_rev"
+ type_id: 0xb86bbd27
+ offset: 34336
+}
+member {
id: 0x148dd054
name: "pd_revision"
type_id: 0x914dbfdc
@@ -171709,6 +171715,17 @@
offset: 32
}
member {
+ id: 0x5a462436
+ name: "rev_major"
+ type_id: 0x295c7202
+}
+member {
+ id: 0xffd8baff
+ name: "rev_minor"
+ type_id: 0x295c7202
+ offset: 8
+}
+member {
id: 0x006556c8
name: "revents"
type_id: 0xb0312d5a
@@ -208491,6 +208508,18 @@
type_id: 0xc9082b19
}
member {
+ id: 0x550a2434
+ name: "ver_major"
+ type_id: 0x295c7202
+ offset: 16
+}
+member {
+ id: 0x7aec6bc4
+ name: "ver_minor"
+ type_id: 0x295c7202
+ offset: 24
+}
+member {
id: 0x816935ff
name: "verification_time"
type_id: 0x92233392
@@ -253798,6 +253827,18 @@
}
}
struct_union {
+ id: 0xb86bbd27
+ kind: STRUCT
+ name: "pd_revision_info"
+ definition {
+ bytesize: 4
+ member_id: 0x5a462436
+ member_id: 0xffd8baff
+ member_id: 0x550a2434
+ member_id: 0x7aec6bc4
+ }
+}
+struct_union {
id: 0x308c0299
kind: STRUCT
name: "pdev_archdata"
@@ -267540,6 +267581,7 @@
member_id: 0x0161008f
member_id: 0x3e93273a
member_id: 0x5016a2b8
+ member_id: 0xf4dec516
member_id: 0xf3efe442
member_id: 0x6339ac5e
member_id: 0x2a721ab3
@@ -290571,6 +290613,10 @@
name: "PD_MSG_DATA_SOURCE_CAP"
value: 5
}
+ enumerator {
+ name: "PD_MSG_DATA_REV"
+ value: 6
+ }
}
}
enumeration {
@@ -293953,6 +293999,10 @@
name: "COUNTRY_CODES"
value: 33
}
+ enumerator {
+ name: "REVISION_INFORMATION"
+ value: 34
+ }
}
}
enumeration {
diff --git a/android/abi_gki_aarch64.stg.allowed_breaks b/android/abi_gki_aarch64.stg.allowed_breaks
index 42e5c02..b65a8ae 100644
--- a/android/abi_gki_aarch64.stg.allowed_breaks
+++ b/android/abi_gki_aarch64.stg.allowed_breaks
@@ -187,3 +187,12 @@
member 'u64 android_kabi_reserved1' was removed
member 'union { struct { u16 hw_timestamp_max_peers; u16 android_kabi_reserve1; }; struct { u64 android_kabi_reserved1; }; union { }; }' was added
+type 'struct tcpm_port' changed
+ member 'struct pd_revision_info pd_rev' was added
+
+type 'enum pd_msg_request' changed
+ enumerator 'PD_MSG_DATA_REV' (6) was added
+
+type 'enum tcpm_ams' changed
+ enumerator 'REVISION_INFORMATION' (34) was added
+
diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c
index 4f10c89..03db084 100644
--- a/drivers/usb/typec/tcpm/tcpm.c
+++ b/drivers/usb/typec/tcpm/tcpm.c
@@ -182,7 +182,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
@@ -222,6 +223,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 {
@@ -1158,6 +1160,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;
@@ -2939,6 +2959,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 ?
@@ -3139,6 +3170,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;
}
diff --git a/include/linux/usb/pd.h b/include/linux/usb/pd.h
index c59fb79..24fd328 100644
--- a/include/linux/usb/pd.h
+++ b/include/linux/usb/pd.h
@@ -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 */
};
@@ -452,6 +456,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 */