Skip to content

Commit

Permalink
usb: typec: tcpm: Add new AMS for Get_Revision response
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Amit Sunil Dhamne authored and Greg Kroah-Hartman committed Dec 24, 2024
1 parent 8ecf60c commit 8cda395
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 3 deletions.
41 changes: 40 additions & 1 deletion drivers/usb/typec/tcpm/tcpm.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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 ?
Expand Down Expand Up @@ -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;
}
Expand Down
22 changes: 20 additions & 2 deletions include/linux/usb/pd.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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 */
};
Expand Down Expand Up @@ -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 */
Expand Down

0 comments on commit 8cda395

Please sign in to comment.