Re: [PATCH v7 6/6] typec: tcpm: Add support for sink PPS related messages

2018-03-25 Thread Guenter Roeck

On 03/23/2018 03:12 AM, Adam Thomson wrote:

This commit adds sink side support for Get_Status, Status,
Get_PPS_Status and PPS_Status handling. As there's the
potential for a partner to respond with Not_Supported,
handling of this message is also added. Sending of
Not_Supported is added to handle messagescreceived but not
yet handled.

Signed-off-by: Adam Thomson 
Acked-by: Heikki Krogerus 


Reviewed-by: Guenter Roeck 


---
  drivers/usb/typec/tcpm.c | 143 ---
  1 file changed, 134 insertions(+), 9 deletions(-)

diff --git a/drivers/usb/typec/tcpm.c b/drivers/usb/typec/tcpm.c
index 57a7d1a..7025a16 100644
--- a/drivers/usb/typec/tcpm.c
+++ b/drivers/usb/typec/tcpm.c
@@ -19,7 +19,9 @@
  #include 
  #include 
  #include 
+#include 
  #include 
+#include 
  #include 
  #include 
  #include 
@@ -113,6 +115,11 @@
S(SNK_TRYWAIT_VBUS),\
S(BIST_RX), \
\
+   S(GET_STATUS_SEND), \
+   S(GET_STATUS_SEND_TIMEOUT), \
+   S(GET_PPS_STATUS_SEND), \
+   S(GET_PPS_STATUS_SEND_TIMEOUT), \
+   \
S(ERROR_RECOVERY),  \
S(PORT_RESET),  \
S(PORT_RESET_WAIT_OFF)
@@ -143,6 +150,7 @@ enum pd_msg_request {
PD_MSG_NONE = 0,
PD_MSG_CTRL_REJECT,
PD_MSG_CTRL_WAIT,
+   PD_MSG_CTRL_NOT_SUPP,
PD_MSG_DATA_SINK_CAP,
PD_MSG_DATA_SOURCE_CAP,
  };
@@ -1398,10 +1406,42 @@ static int tcpm_validate_caps(struct tcpm_port *port, 
const u32 *pdo,
  /*
   * PD (data, control) command handling functions
   */
+static inline enum tcpm_state ready_state(struct tcpm_port *port)
+{
+   if (port->pwr_role == TYPEC_SOURCE)
+   return SRC_READY;
+   else
+   return SNK_READY;
+}
  
  static int tcpm_pd_send_control(struct tcpm_port *port,

enum pd_ctrl_msg_type type);
  
+static void tcpm_handle_alert(struct tcpm_port *port, const __le32 *payload,

+ int cnt)
+{
+   u32 p0 = le32_to_cpu(payload[0]);
+   unsigned int type = usb_pd_ado_type(p0);
+
+   if (!type) {
+   tcpm_log(port, "Alert message received with no type");
+   return;
+   }
+
+   /* Just handling non-battery alerts for now */
+   if (!(type & USB_PD_ADO_TYPE_BATT_STATUS_CHANGE)) {
+   switch (port->state) {
+   case SRC_READY:
+   case SNK_READY:
+   tcpm_set_state(port, GET_STATUS_SEND, 0);
+   break;
+   default:
+   tcpm_queue_message(port, PD_MSG_CTRL_WAIT);
+   break;
+   }
+   }
+}
+
  static void tcpm_pd_data_request(struct tcpm_port *port,
 const struct pd_message *msg)
  {
@@ -1489,6 +1529,14 @@ static void tcpm_pd_data_request(struct tcpm_port *port,
tcpm_set_state(port, BIST_RX, 0);
}
break;
+   case PD_DATA_ALERT:
+   tcpm_handle_alert(port, msg->payload, cnt);
+   break;
+   case PD_DATA_BATT_STATUS:
+   case PD_DATA_GET_COUNTRY_INFO:
+   /* Currently unsupported */
+   tcpm_queue_message(port, PD_MSG_CTRL_NOT_SUPP);
+   break;
default:
tcpm_log(port, "Unhandled data message type %#x", type);
break;
@@ -1571,6 +1619,7 @@ static void tcpm_pd_ctrl_request(struct tcpm_port *port,
break;
case PD_CTRL_REJECT:
case PD_CTRL_WAIT:
+   case PD_CTRL_NOT_SUPP:
switch (port->state) {
case SNK_NEGOTIATE_CAPABILITIES:
/* USB PD specification, Figure 8-43 */
@@ -1690,12 +1739,75 @@ static void tcpm_pd_ctrl_request(struct tcpm_port *port,
break;
}
break;
+   case PD_CTRL_GET_SOURCE_CAP_EXT:
+   case PD_CTRL_GET_STATUS:
+   case PD_CTRL_FR_SWAP:
+   case PD_CTRL_GET_PPS_STATUS:
+   case PD_CTRL_GET_COUNTRY_CODES:
+   /* Currently not supported */
+   tcpm_queue_message(port, PD_MSG_CTRL_NOT_SUPP);
+   break;
default:
tcpm_log(port, "Unhandled ctrl message type %#x", type);
break;
}
  }
  
+static void tcpm_pd_ext_msg_request(struct tcpm_port *port,

+   const struct pd_message *msg)
+{
+   enum pd_ext_msg_type type = pd_header_type_le(msg->header);
+   unsigned int data_size = 
pd_ext_header_data_size_le(msg->ext_msg.header);
+
+   if (!(msg->ext_msg.header && 

Re: [PATCH v7 6/6] typec: tcpm: Add support for sink PPS related messages

2018-03-25 Thread Guenter Roeck

On 03/23/2018 03:12 AM, Adam Thomson wrote:

This commit adds sink side support for Get_Status, Status,
Get_PPS_Status and PPS_Status handling. As there's the
potential for a partner to respond with Not_Supported,
handling of this message is also added. Sending of
Not_Supported is added to handle messagescreceived but not
yet handled.

Signed-off-by: Adam Thomson 
Acked-by: Heikki Krogerus 


Reviewed-by: Guenter Roeck 


---
  drivers/usb/typec/tcpm.c | 143 ---
  1 file changed, 134 insertions(+), 9 deletions(-)

diff --git a/drivers/usb/typec/tcpm.c b/drivers/usb/typec/tcpm.c
index 57a7d1a..7025a16 100644
--- a/drivers/usb/typec/tcpm.c
+++ b/drivers/usb/typec/tcpm.c
@@ -19,7 +19,9 @@
  #include 
  #include 
  #include 
+#include 
  #include 
+#include 
  #include 
  #include 
  #include 
@@ -113,6 +115,11 @@
S(SNK_TRYWAIT_VBUS),\
S(BIST_RX), \
\
+   S(GET_STATUS_SEND), \
+   S(GET_STATUS_SEND_TIMEOUT), \
+   S(GET_PPS_STATUS_SEND), \
+   S(GET_PPS_STATUS_SEND_TIMEOUT), \
+   \
S(ERROR_RECOVERY),  \
S(PORT_RESET),  \
S(PORT_RESET_WAIT_OFF)
@@ -143,6 +150,7 @@ enum pd_msg_request {
PD_MSG_NONE = 0,
PD_MSG_CTRL_REJECT,
PD_MSG_CTRL_WAIT,
+   PD_MSG_CTRL_NOT_SUPP,
PD_MSG_DATA_SINK_CAP,
PD_MSG_DATA_SOURCE_CAP,
  };
@@ -1398,10 +1406,42 @@ static int tcpm_validate_caps(struct tcpm_port *port, 
const u32 *pdo,
  /*
   * PD (data, control) command handling functions
   */
+static inline enum tcpm_state ready_state(struct tcpm_port *port)
+{
+   if (port->pwr_role == TYPEC_SOURCE)
+   return SRC_READY;
+   else
+   return SNK_READY;
+}
  
  static int tcpm_pd_send_control(struct tcpm_port *port,

enum pd_ctrl_msg_type type);
  
+static void tcpm_handle_alert(struct tcpm_port *port, const __le32 *payload,

+ int cnt)
+{
+   u32 p0 = le32_to_cpu(payload[0]);
+   unsigned int type = usb_pd_ado_type(p0);
+
+   if (!type) {
+   tcpm_log(port, "Alert message received with no type");
+   return;
+   }
+
+   /* Just handling non-battery alerts for now */
+   if (!(type & USB_PD_ADO_TYPE_BATT_STATUS_CHANGE)) {
+   switch (port->state) {
+   case SRC_READY:
+   case SNK_READY:
+   tcpm_set_state(port, GET_STATUS_SEND, 0);
+   break;
+   default:
+   tcpm_queue_message(port, PD_MSG_CTRL_WAIT);
+   break;
+   }
+   }
+}
+
  static void tcpm_pd_data_request(struct tcpm_port *port,
 const struct pd_message *msg)
  {
@@ -1489,6 +1529,14 @@ static void tcpm_pd_data_request(struct tcpm_port *port,
tcpm_set_state(port, BIST_RX, 0);
}
break;
+   case PD_DATA_ALERT:
+   tcpm_handle_alert(port, msg->payload, cnt);
+   break;
+   case PD_DATA_BATT_STATUS:
+   case PD_DATA_GET_COUNTRY_INFO:
+   /* Currently unsupported */
+   tcpm_queue_message(port, PD_MSG_CTRL_NOT_SUPP);
+   break;
default:
tcpm_log(port, "Unhandled data message type %#x", type);
break;
@@ -1571,6 +1619,7 @@ static void tcpm_pd_ctrl_request(struct tcpm_port *port,
break;
case PD_CTRL_REJECT:
case PD_CTRL_WAIT:
+   case PD_CTRL_NOT_SUPP:
switch (port->state) {
case SNK_NEGOTIATE_CAPABILITIES:
/* USB PD specification, Figure 8-43 */
@@ -1690,12 +1739,75 @@ static void tcpm_pd_ctrl_request(struct tcpm_port *port,
break;
}
break;
+   case PD_CTRL_GET_SOURCE_CAP_EXT:
+   case PD_CTRL_GET_STATUS:
+   case PD_CTRL_FR_SWAP:
+   case PD_CTRL_GET_PPS_STATUS:
+   case PD_CTRL_GET_COUNTRY_CODES:
+   /* Currently not supported */
+   tcpm_queue_message(port, PD_MSG_CTRL_NOT_SUPP);
+   break;
default:
tcpm_log(port, "Unhandled ctrl message type %#x", type);
break;
}
  }
  
+static void tcpm_pd_ext_msg_request(struct tcpm_port *port,

+   const struct pd_message *msg)
+{
+   enum pd_ext_msg_type type = pd_header_type_le(msg->header);
+   unsigned int data_size = 
pd_ext_header_data_size_le(msg->ext_msg.header);
+
+   if (!(msg->ext_msg.header && PD_EXT_HDR_CHUNKED)) {
+   tcpm_log(port, "Unchunked extended messages 

[PATCH v7 6/6] typec: tcpm: Add support for sink PPS related messages

2018-03-23 Thread Adam Thomson
This commit adds sink side support for Get_Status, Status,
Get_PPS_Status and PPS_Status handling. As there's the
potential for a partner to respond with Not_Supported,
handling of this message is also added. Sending of
Not_Supported is added to handle messagescreceived but not
yet handled.

Signed-off-by: Adam Thomson 
Acked-by: Heikki Krogerus 
---
 drivers/usb/typec/tcpm.c | 143 ---
 1 file changed, 134 insertions(+), 9 deletions(-)

diff --git a/drivers/usb/typec/tcpm.c b/drivers/usb/typec/tcpm.c
index 57a7d1a..7025a16 100644
--- a/drivers/usb/typec/tcpm.c
+++ b/drivers/usb/typec/tcpm.c
@@ -19,7 +19,9 @@
 #include 
 #include 
 #include 
+#include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -113,6 +115,11 @@
S(SNK_TRYWAIT_VBUS),\
S(BIST_RX), \
\
+   S(GET_STATUS_SEND), \
+   S(GET_STATUS_SEND_TIMEOUT), \
+   S(GET_PPS_STATUS_SEND), \
+   S(GET_PPS_STATUS_SEND_TIMEOUT), \
+   \
S(ERROR_RECOVERY),  \
S(PORT_RESET),  \
S(PORT_RESET_WAIT_OFF)
@@ -143,6 +150,7 @@ enum pd_msg_request {
PD_MSG_NONE = 0,
PD_MSG_CTRL_REJECT,
PD_MSG_CTRL_WAIT,
+   PD_MSG_CTRL_NOT_SUPP,
PD_MSG_DATA_SINK_CAP,
PD_MSG_DATA_SOURCE_CAP,
 };
@@ -1398,10 +1406,42 @@ static int tcpm_validate_caps(struct tcpm_port *port, 
const u32 *pdo,
 /*
  * PD (data, control) command handling functions
  */
+static inline enum tcpm_state ready_state(struct tcpm_port *port)
+{
+   if (port->pwr_role == TYPEC_SOURCE)
+   return SRC_READY;
+   else
+   return SNK_READY;
+}
 
 static int tcpm_pd_send_control(struct tcpm_port *port,
enum pd_ctrl_msg_type type);
 
+static void tcpm_handle_alert(struct tcpm_port *port, const __le32 *payload,
+ int cnt)
+{
+   u32 p0 = le32_to_cpu(payload[0]);
+   unsigned int type = usb_pd_ado_type(p0);
+
+   if (!type) {
+   tcpm_log(port, "Alert message received with no type");
+   return;
+   }
+
+   /* Just handling non-battery alerts for now */
+   if (!(type & USB_PD_ADO_TYPE_BATT_STATUS_CHANGE)) {
+   switch (port->state) {
+   case SRC_READY:
+   case SNK_READY:
+   tcpm_set_state(port, GET_STATUS_SEND, 0);
+   break;
+   default:
+   tcpm_queue_message(port, PD_MSG_CTRL_WAIT);
+   break;
+   }
+   }
+}
+
 static void tcpm_pd_data_request(struct tcpm_port *port,
 const struct pd_message *msg)
 {
@@ -1489,6 +1529,14 @@ static void tcpm_pd_data_request(struct tcpm_port *port,
tcpm_set_state(port, BIST_RX, 0);
}
break;
+   case PD_DATA_ALERT:
+   tcpm_handle_alert(port, msg->payload, cnt);
+   break;
+   case PD_DATA_BATT_STATUS:
+   case PD_DATA_GET_COUNTRY_INFO:
+   /* Currently unsupported */
+   tcpm_queue_message(port, PD_MSG_CTRL_NOT_SUPP);
+   break;
default:
tcpm_log(port, "Unhandled data message type %#x", type);
break;
@@ -1571,6 +1619,7 @@ static void tcpm_pd_ctrl_request(struct tcpm_port *port,
break;
case PD_CTRL_REJECT:
case PD_CTRL_WAIT:
+   case PD_CTRL_NOT_SUPP:
switch (port->state) {
case SNK_NEGOTIATE_CAPABILITIES:
/* USB PD specification, Figure 8-43 */
@@ -1690,12 +1739,75 @@ static void tcpm_pd_ctrl_request(struct tcpm_port *port,
break;
}
break;
+   case PD_CTRL_GET_SOURCE_CAP_EXT:
+   case PD_CTRL_GET_STATUS:
+   case PD_CTRL_FR_SWAP:
+   case PD_CTRL_GET_PPS_STATUS:
+   case PD_CTRL_GET_COUNTRY_CODES:
+   /* Currently not supported */
+   tcpm_queue_message(port, PD_MSG_CTRL_NOT_SUPP);
+   break;
default:
tcpm_log(port, "Unhandled ctrl message type %#x", type);
break;
}
 }
 
+static void tcpm_pd_ext_msg_request(struct tcpm_port *port,
+   const struct pd_message *msg)
+{
+   enum pd_ext_msg_type type = pd_header_type_le(msg->header);
+   unsigned int data_size = 
pd_ext_header_data_size_le(msg->ext_msg.header);
+
+   if (!(msg->ext_msg.header && PD_EXT_HDR_CHUNKED)) {
+   tcpm_log(port, "Unchunked extended messages unsupported");
+   return;
+

[PATCH v7 6/6] typec: tcpm: Add support for sink PPS related messages

2018-03-23 Thread Adam Thomson
This commit adds sink side support for Get_Status, Status,
Get_PPS_Status and PPS_Status handling. As there's the
potential for a partner to respond with Not_Supported,
handling of this message is also added. Sending of
Not_Supported is added to handle messagescreceived but not
yet handled.

Signed-off-by: Adam Thomson 
Acked-by: Heikki Krogerus 
---
 drivers/usb/typec/tcpm.c | 143 ---
 1 file changed, 134 insertions(+), 9 deletions(-)

diff --git a/drivers/usb/typec/tcpm.c b/drivers/usb/typec/tcpm.c
index 57a7d1a..7025a16 100644
--- a/drivers/usb/typec/tcpm.c
+++ b/drivers/usb/typec/tcpm.c
@@ -19,7 +19,9 @@
 #include 
 #include 
 #include 
+#include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -113,6 +115,11 @@
S(SNK_TRYWAIT_VBUS),\
S(BIST_RX), \
\
+   S(GET_STATUS_SEND), \
+   S(GET_STATUS_SEND_TIMEOUT), \
+   S(GET_PPS_STATUS_SEND), \
+   S(GET_PPS_STATUS_SEND_TIMEOUT), \
+   \
S(ERROR_RECOVERY),  \
S(PORT_RESET),  \
S(PORT_RESET_WAIT_OFF)
@@ -143,6 +150,7 @@ enum pd_msg_request {
PD_MSG_NONE = 0,
PD_MSG_CTRL_REJECT,
PD_MSG_CTRL_WAIT,
+   PD_MSG_CTRL_NOT_SUPP,
PD_MSG_DATA_SINK_CAP,
PD_MSG_DATA_SOURCE_CAP,
 };
@@ -1398,10 +1406,42 @@ static int tcpm_validate_caps(struct tcpm_port *port, 
const u32 *pdo,
 /*
  * PD (data, control) command handling functions
  */
+static inline enum tcpm_state ready_state(struct tcpm_port *port)
+{
+   if (port->pwr_role == TYPEC_SOURCE)
+   return SRC_READY;
+   else
+   return SNK_READY;
+}
 
 static int tcpm_pd_send_control(struct tcpm_port *port,
enum pd_ctrl_msg_type type);
 
+static void tcpm_handle_alert(struct tcpm_port *port, const __le32 *payload,
+ int cnt)
+{
+   u32 p0 = le32_to_cpu(payload[0]);
+   unsigned int type = usb_pd_ado_type(p0);
+
+   if (!type) {
+   tcpm_log(port, "Alert message received with no type");
+   return;
+   }
+
+   /* Just handling non-battery alerts for now */
+   if (!(type & USB_PD_ADO_TYPE_BATT_STATUS_CHANGE)) {
+   switch (port->state) {
+   case SRC_READY:
+   case SNK_READY:
+   tcpm_set_state(port, GET_STATUS_SEND, 0);
+   break;
+   default:
+   tcpm_queue_message(port, PD_MSG_CTRL_WAIT);
+   break;
+   }
+   }
+}
+
 static void tcpm_pd_data_request(struct tcpm_port *port,
 const struct pd_message *msg)
 {
@@ -1489,6 +1529,14 @@ static void tcpm_pd_data_request(struct tcpm_port *port,
tcpm_set_state(port, BIST_RX, 0);
}
break;
+   case PD_DATA_ALERT:
+   tcpm_handle_alert(port, msg->payload, cnt);
+   break;
+   case PD_DATA_BATT_STATUS:
+   case PD_DATA_GET_COUNTRY_INFO:
+   /* Currently unsupported */
+   tcpm_queue_message(port, PD_MSG_CTRL_NOT_SUPP);
+   break;
default:
tcpm_log(port, "Unhandled data message type %#x", type);
break;
@@ -1571,6 +1619,7 @@ static void tcpm_pd_ctrl_request(struct tcpm_port *port,
break;
case PD_CTRL_REJECT:
case PD_CTRL_WAIT:
+   case PD_CTRL_NOT_SUPP:
switch (port->state) {
case SNK_NEGOTIATE_CAPABILITIES:
/* USB PD specification, Figure 8-43 */
@@ -1690,12 +1739,75 @@ static void tcpm_pd_ctrl_request(struct tcpm_port *port,
break;
}
break;
+   case PD_CTRL_GET_SOURCE_CAP_EXT:
+   case PD_CTRL_GET_STATUS:
+   case PD_CTRL_FR_SWAP:
+   case PD_CTRL_GET_PPS_STATUS:
+   case PD_CTRL_GET_COUNTRY_CODES:
+   /* Currently not supported */
+   tcpm_queue_message(port, PD_MSG_CTRL_NOT_SUPP);
+   break;
default:
tcpm_log(port, "Unhandled ctrl message type %#x", type);
break;
}
 }
 
+static void tcpm_pd_ext_msg_request(struct tcpm_port *port,
+   const struct pd_message *msg)
+{
+   enum pd_ext_msg_type type = pd_header_type_le(msg->header);
+   unsigned int data_size = 
pd_ext_header_data_size_le(msg->ext_msg.header);
+
+   if (!(msg->ext_msg.header && PD_EXT_HDR_CHUNKED)) {
+   tcpm_log(port, "Unchunked extended messages unsupported");
+   return;
+   }
+
+   if (data_size > PD_EXT_MAX_CHUNK_DATA) {
+