From patchwork Thu Apr 23 13:20:53 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Heikki Krogerus X-Patchwork-Id: 11505673 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id AAF0F81 for ; Thu, 23 Apr 2020 13:21:07 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 9350120857 for ; Thu, 23 Apr 2020 13:21:07 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728354AbgDWNVG (ORCPT ); Thu, 23 Apr 2020 09:21:06 -0400 Received: from mga07.intel.com ([134.134.136.100]:16372 "EHLO mga07.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726753AbgDWNVF (ORCPT ); Thu, 23 Apr 2020 09:21:05 -0400 IronPort-SDR: wbNwn4+NxFf/q4Jlcu/2rNctBsvIiggkUTMDpBJ4rbn04J+7FQi0V7/g5AsG3gu2lgBk2EFQqa aIrpnRpOT7JQ== X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by orsmga105.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 23 Apr 2020 06:21:04 -0700 IronPort-SDR: Yyi1QSm4rSCWOF9thmWOVSkQMCtMLQbd3i7l8OMEPofFkEmSyQgTPEkePispkWB4oNDIuqt2N4 pS+mzMzJx54Q== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.73,307,1583222400"; d="scan'208";a="366001010" Received: from black.fi.intel.com (HELO black.fi.intel.com.) ([10.237.72.28]) by fmsmga001.fm.intel.com with ESMTP; 23 Apr 2020 06:21:03 -0700 From: Heikki Krogerus To: Greg Kroah-Hartman Cc: linux-usb@vger.kernel.org, "K V, Abhilash" , Mayank Rana Subject: [PATCH 1/6] usb: typec: ucsi: set USB data role when partner type is power cable/ufp Date: Thu, 23 Apr 2020 16:20:53 +0300 Message-Id: <20200423132058.6972-2-heikki.krogerus@linux.intel.com> X-Mailer: git-send-email 2.26.1 In-Reply-To: <20200423132058.6972-1-heikki.krogerus@linux.intel.com> References: <20200423132058.6972-1-heikki.krogerus@linux.intel.com> MIME-Version: 1.0 Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org From: Mayank Rana Currently UCSI framework doesn't update USB data role when partner type is reported as power cable or power cable with ufp connected. This results into no USB host mode functionality. This is valid usecase where user wants to use legacy type c power cable with type a female connector to attach different USB devices like mouse, thumb drive etc. Hence update USB data role as host when partner type is reported as power cable or power cable with ufp connected. Signed-off-by: Mayank Rana Signed-off-by: Heikki Krogerus --- drivers/usb/typec/ucsi/ucsi.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c index ddf2ad3752de..e9baa9a749e5 100644 --- a/drivers/usb/typec/ucsi/ucsi.c +++ b/drivers/usb/typec/ucsi/ucsi.c @@ -566,6 +566,8 @@ static void ucsi_partner_change(struct ucsi_connector *con) switch (UCSI_CONSTAT_PARTNER_TYPE(con->status.flags)) { case UCSI_CONSTAT_PARTNER_TYPE_UFP: + case UCSI_CONSTAT_PARTNER_TYPE_CABLE: + case UCSI_CONSTAT_PARTNER_TYPE_CABLE_AND_UFP: typec_set_data_role(con->port, TYPEC_HOST); break; case UCSI_CONSTAT_PARTNER_TYPE_DFP: @@ -627,6 +629,8 @@ static void ucsi_handle_connector_change(struct work_struct *work) switch (UCSI_CONSTAT_PARTNER_TYPE(con->status.flags)) { case UCSI_CONSTAT_PARTNER_TYPE_UFP: + case UCSI_CONSTAT_PARTNER_TYPE_CABLE: + case UCSI_CONSTAT_PARTNER_TYPE_CABLE_AND_UFP: typec_set_data_role(con->port, TYPEC_HOST); break; case UCSI_CONSTAT_PARTNER_TYPE_DFP: @@ -927,6 +931,8 @@ static int ucsi_register_port(struct ucsi *ucsi, int index) switch (UCSI_CONSTAT_PARTNER_TYPE(con->status.flags)) { case UCSI_CONSTAT_PARTNER_TYPE_UFP: + case UCSI_CONSTAT_PARTNER_TYPE_CABLE: + case UCSI_CONSTAT_PARTNER_TYPE_CABLE_AND_UFP: typec_set_data_role(con->port, TYPEC_HOST); break; case UCSI_CONSTAT_PARTNER_TYPE_DFP: From patchwork Thu Apr 23 13:20:54 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Heikki Krogerus X-Patchwork-Id: 11505675 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id CFAF192C for ; Thu, 23 Apr 2020 13:21:08 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id B7AF52084D for ; Thu, 23 Apr 2020 13:21:08 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728363AbgDWNVI (ORCPT ); Thu, 23 Apr 2020 09:21:08 -0400 Received: from mga07.intel.com ([134.134.136.100]:16372 "EHLO mga07.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726753AbgDWNVG (ORCPT ); Thu, 23 Apr 2020 09:21:06 -0400 IronPort-SDR: EanpjvNyjjo/aGxi7E05OQcVe+ytmZoUJwZEvCn7U6iPiF5uygrk0dte0t2oTvpHmiTwm1oOE6 V322gs44d21A== X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by orsmga105.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 23 Apr 2020 06:21:06 -0700 IronPort-SDR: I5vWWZrq746FAM6pYRJkVjxu3E+673kU6t9/wNDyPTkoOAkIvdjmrl6pK9nwgW6xdYwKrI0eJv DtmbgCeNYk9w== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.73,307,1583222400"; d="scan'208";a="366001015" Received: from black.fi.intel.com (HELO black.fi.intel.com.) ([10.237.72.28]) by fmsmga001.fm.intel.com with ESMTP; 23 Apr 2020 06:21:04 -0700 From: Heikki Krogerus To: Greg Kroah-Hartman Cc: linux-usb@vger.kernel.org, "K V, Abhilash" Subject: [PATCH 2/6] usb: typec: ucsi: Workaround for missed op_mode change Date: Thu, 23 Apr 2020 16:20:54 +0300 Message-Id: <20200423132058.6972-3-heikki.krogerus@linux.intel.com> X-Mailer: git-send-email 2.26.1 In-Reply-To: <20200423132058.6972-1-heikki.krogerus@linux.intel.com> References: <20200423132058.6972-1-heikki.krogerus@linux.intel.com> MIME-Version: 1.0 Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org From: "K V, Abhilash" EC firmware on Dell XPS & Latitude series does not set "Power Operation Mode Change" bit in "Connector Status change" field of MESSAGE IN Data while transitioning from type-C current to PD mode. Instead the "Negotiated Power Level Change" bit is set when the "Power Operation Mode" field shows the correct mode (i.e. PD). This patch adds a check for this bit also, to trigger an update of power operation mode in class driver, while handling GET_CONNECTOR_STATUS command. Signed-off-by: K V, Abhilash Signed-off-by: Heikki Krogerus --- drivers/usb/typec/ucsi/ucsi.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c index e9baa9a749e5..0c7c3f9b1b50 100644 --- a/drivers/usb/typec/ucsi/ucsi.c +++ b/drivers/usb/typec/ucsi/ucsi.c @@ -613,7 +613,8 @@ static void ucsi_handle_connector_change(struct work_struct *work) role = !!(con->status.flags & UCSI_CONSTAT_PWR_DIR); - if (con->status.change & UCSI_CONSTAT_POWER_OPMODE_CHANGE) + if (con->status.change & UCSI_CONSTAT_POWER_OPMODE_CHANGE || + con->status.change & UCSI_CONSTAT_POWER_LEVEL_CHANGE) ucsi_pwr_opmode_change(con); if (con->status.change & UCSI_CONSTAT_POWER_DIR_CHANGE) { From patchwork Thu Apr 23 13:20:55 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Heikki Krogerus X-Patchwork-Id: 11505677 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 6EF0F15AB for ; Thu, 23 Apr 2020 13:21:09 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 5654621473 for ; Thu, 23 Apr 2020 13:21:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728370AbgDWNVI (ORCPT ); Thu, 23 Apr 2020 09:21:08 -0400 Received: from mga07.intel.com ([134.134.136.100]:16372 "EHLO mga07.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728367AbgDWNVI (ORCPT ); Thu, 23 Apr 2020 09:21:08 -0400 IronPort-SDR: MxYnLxjTo7QI3HZpLW7aWwhxtJ6vz2k3tdixot8SiAQsK3C7ZjTjP5SL9NNWVXeXQmAEJClbR1 Vf4rRVXZ6QGQ== X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by orsmga105.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 23 Apr 2020 06:21:07 -0700 IronPort-SDR: IFD5K60FNvydQX6sLWtq/zsY10Gr3Vv0O1dB7JRI/6S7/TDxZ2YVTCCNaZ6gK2lYYtH3aIrEVw boojj/oib4Mg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.73,307,1583222400"; d="scan'208";a="366001019" Received: from black.fi.intel.com (HELO black.fi.intel.com.) ([10.237.72.28]) by fmsmga001.fm.intel.com with ESMTP; 23 Apr 2020 06:21:06 -0700 From: Heikki Krogerus To: Greg Kroah-Hartman Cc: linux-usb@vger.kernel.org, "K V, Abhilash" Subject: [PATCH 3/6] usb: typec: ucsi: replace magic numbers Date: Thu, 23 Apr 2020 16:20:55 +0300 Message-Id: <20200423132058.6972-4-heikki.krogerus@linux.intel.com> X-Mailer: git-send-email 2.26.1 In-Reply-To: <20200423132058.6972-1-heikki.krogerus@linux.intel.com> References: <20200423132058.6972-1-heikki.krogerus@linux.intel.com> MIME-Version: 1.0 Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org From: "K V, Abhilash" Replace magic numbers with macros in trace.h. Signed-off-by: K V, Abhilash Signed-off-by: Heikki Krogerus --- drivers/usb/typec/ucsi/trace.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/usb/typec/ucsi/trace.c b/drivers/usb/typec/ucsi/trace.c index 48ad1dc1b1b2..cb62ad835761 100644 --- a/drivers/usb/typec/ucsi/trace.c +++ b/drivers/usb/typec/ucsi/trace.c @@ -35,16 +35,16 @@ const char *ucsi_cmd_str(u64 raw_cmd) const char *ucsi_cci_str(u32 cci) { - if (cci & GENMASK(7, 0)) { - if (cci & BIT(29)) + if (UCSI_CCI_CONNECTOR(cci)) { + if (cci & UCSI_CCI_ACK_COMPLETE) return "Event pending (ACK completed)"; - if (cci & BIT(31)) + if (cci & UCSI_CCI_COMMAND_COMPLETE) return "Event pending (command completed)"; return "Connector Change"; } - if (cci & BIT(29)) + if (cci & UCSI_CCI_ACK_COMPLETE) return "ACK completed"; - if (cci & BIT(31)) + if (cci & UCSI_CCI_COMMAND_COMPLETE) return "Command completed"; return ""; From patchwork Thu Apr 23 13:20:56 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Heikki Krogerus X-Patchwork-Id: 11505679 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 0D7F281 for ; Thu, 23 Apr 2020 13:21:11 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id E9BE92098B for ; Thu, 23 Apr 2020 13:21:10 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728379AbgDWNVK (ORCPT ); Thu, 23 Apr 2020 09:21:10 -0400 Received: from mga07.intel.com ([134.134.136.100]:16372 "EHLO mga07.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728367AbgDWNVJ (ORCPT ); Thu, 23 Apr 2020 09:21:09 -0400 IronPort-SDR: kiUl0ClO+binPNAg2Tyyd6tr6G24RgiBS4sQRQaXV4I0jwF2TrL08MzuZ2XCi4u5hH22D44f3Q mxCuGyORb7sg== X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by orsmga105.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 23 Apr 2020 06:21:09 -0700 IronPort-SDR: A4NQImD/Go5aqOj9Ea5nSJd+dcRJucX6NhF3eKssQmP9byFj8xObRDxONIsJi3b1jQptX2ZLNE 6ojZDNYgN5Kw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.73,307,1583222400"; d="scan'208";a="366001027" Received: from black.fi.intel.com (HELO black.fi.intel.com.) ([10.237.72.28]) by fmsmga001.fm.intel.com with ESMTP; 23 Apr 2020 06:21:07 -0700 From: Heikki Krogerus To: Greg Kroah-Hartman Cc: linux-usb@vger.kernel.org, "K V, Abhilash" Subject: [PATCH 4/6] usb: typec: ucsi: Correct bit-mask for CCI Date: Thu, 23 Apr 2020 16:20:56 +0300 Message-Id: <20200423132058.6972-5-heikki.krogerus@linux.intel.com> X-Mailer: git-send-email 2.26.1 In-Reply-To: <20200423132058.6972-1-heikki.krogerus@linux.intel.com> References: <20200423132058.6972-1-heikki.krogerus@linux.intel.com> MIME-Version: 1.0 Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org From: "K V, Abhilash" Bit 0 is reserved in CCI (Command Status & Connector Change Indicator) register. So, change bit-mask for connector number field to 7..1 instead of 7..0. There would be no functional change since we were anyways right-shifing by 1 bit. Signed-off-by: K V, Abhilash Signed-off-by: Heikki Krogerus --- drivers/usb/typec/ucsi/ucsi.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/typec/ucsi/ucsi.h b/drivers/usb/typec/ucsi/ucsi.h index 8e831108f481..f068356cc325 100644 --- a/drivers/usb/typec/ucsi/ucsi.h +++ b/drivers/usb/typec/ucsi/ucsi.h @@ -21,7 +21,7 @@ struct ucsi_altmode; #define UCSI_MESSAGE_OUT 32 /* Command Status and Connector Change Indication (CCI) bits */ -#define UCSI_CCI_CONNECTOR(_c_) (((_c_) & GENMASK(7, 0)) >> 1) +#define UCSI_CCI_CONNECTOR(_c_) (((_c_) & GENMASK(7, 1)) >> 1) #define UCSI_CCI_LENGTH(_c_) (((_c_) & GENMASK(15, 8)) >> 8) #define UCSI_CCI_NOT_SUPPORTED BIT(25) #define UCSI_CCI_CANCEL_COMPLETE BIT(26) From patchwork Thu Apr 23 13:20:57 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Heikki Krogerus X-Patchwork-Id: 11505681 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id B65BD81 for ; Thu, 23 Apr 2020 13:21:12 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id A86942098B for ; Thu, 23 Apr 2020 13:21:12 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728402AbgDWNVM (ORCPT ); Thu, 23 Apr 2020 09:21:12 -0400 Received: from mga07.intel.com ([134.134.136.100]:16372 "EHLO mga07.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728367AbgDWNVL (ORCPT ); Thu, 23 Apr 2020 09:21:11 -0400 IronPort-SDR: ym0Rd/9cqKpXCvFPb12WmSgkMdoDi68INWSDNpI7sqUPNTI8UUK9oBltNmWZ2Ipg9nGggnADs2 /Ryh/4Jpis6A== X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by orsmga105.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 23 Apr 2020 06:21:10 -0700 IronPort-SDR: YO1fB/Y8scBTqAFUiHpW7WA78eSdm7xZHWVKgb+vvyBJjobn1WaII8TXxs3Y8uIrCKHNp+R3XS M5ouLS8MCmCw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.73,307,1583222400"; d="scan'208";a="366001033" Received: from black.fi.intel.com (HELO black.fi.intel.com.) ([10.237.72.28]) by fmsmga001.fm.intel.com with ESMTP; 23 Apr 2020 06:21:09 -0700 From: Heikki Krogerus To: Greg Kroah-Hartman Cc: linux-usb@vger.kernel.org, "K V, Abhilash" Subject: [PATCH 5/6] usb: typec: ucsi: save power data objects in PD mode Date: Thu, 23 Apr 2020 16:20:57 +0300 Message-Id: <20200423132058.6972-6-heikki.krogerus@linux.intel.com> X-Mailer: git-send-email 2.26.1 In-Reply-To: <20200423132058.6972-1-heikki.krogerus@linux.intel.com> References: <20200423132058.6972-1-heikki.krogerus@linux.intel.com> MIME-Version: 1.0 Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org From: "K V, Abhilash" When connected to a PD-capable power-source, read & save all partner power data objects (PDOs) by using GET_PDOS UCSI command. Also, save the current power contract in request data object (RDO) for that connector. Signed-off-by: K V, Abhilash Signed-off-by: Heikki Krogerus --- drivers/usb/typec/ucsi/ucsi.c | 26 ++++++++++++++++++++++++++ drivers/usb/typec/ucsi/ucsi.h | 9 +++++++++ 2 files changed, 35 insertions(+) diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c index 0c7c3f9b1b50..ffea795da815 100644 --- a/drivers/usb/typec/ucsi/ucsi.c +++ b/drivers/usb/typec/ucsi/ucsi.c @@ -492,19 +492,45 @@ static void ucsi_unregister_altmodes(struct ucsi_connector *con, u8 recipient) } } +static void ucsi_get_pdos(struct ucsi_connector *con, int is_partner) +{ + struct ucsi *ucsi = con->ucsi; + u64 command; + int ret; + + command = UCSI_COMMAND(UCSI_GET_PDOS) | UCSI_CONNECTOR_NUMBER(con->num); + command |= UCSI_GET_PDOS_PARTNER_PDO(is_partner); + command |= UCSI_GET_PDOS_NUM_PDOS(UCSI_MAX_PDOS - 1); + command |= UCSI_GET_PDOS_SRC_PDOS; + ret = ucsi_run_command(ucsi, command, con->src_pdos, + sizeof(con->src_pdos)); + if (ret < 0) { + dev_err(ucsi->dev, "UCSI_GET_PDOS failed (%d)\n", ret); + return; + } + con->num_pdos = ret / sizeof(u32); /* number of bytes to 32-bit PDOs */ + if (ret == 0) + dev_warn(ucsi->dev, "UCSI_GET_PDOS returned 0 bytes\n"); +} + static void ucsi_pwr_opmode_change(struct ucsi_connector *con) { switch (UCSI_CONSTAT_PWR_OPMODE(con->status.flags)) { case UCSI_CONSTAT_PWR_OPMODE_PD: + con->rdo = con->status.request_data_obj; typec_set_pwr_opmode(con->port, TYPEC_PWR_MODE_PD); + ucsi_get_pdos(con, 1); break; case UCSI_CONSTAT_PWR_OPMODE_TYPEC1_5: + con->rdo = 0; typec_set_pwr_opmode(con->port, TYPEC_PWR_MODE_1_5A); break; case UCSI_CONSTAT_PWR_OPMODE_TYPEC3_0: + con->rdo = 0; typec_set_pwr_opmode(con->port, TYPEC_PWR_MODE_3_0A); break; default: + con->rdo = 0; typec_set_pwr_opmode(con->port, TYPEC_PWR_MODE_USB); break; } diff --git a/drivers/usb/typec/ucsi/ucsi.h b/drivers/usb/typec/ucsi/ucsi.h index f068356cc325..28e21a1e6b61 100644 --- a/drivers/usb/typec/ucsi/ucsi.h +++ b/drivers/usb/typec/ucsi/ucsi.h @@ -130,6 +130,11 @@ void ucsi_connector_change(struct ucsi *ucsi, u8 num); #define UCSI_GET_ALTMODE_OFFSET(_r_) ((u64)(_r_) << 32) #define UCSI_GET_ALTMODE_NUM_ALTMODES(_r_) ((u64)(_r_) << 40) +/* GET_PDOS command bits */ +#define UCSI_GET_PDOS_PARTNER_PDO(_r_) ((u64)(_r_) << 23) +#define UCSI_GET_PDOS_NUM_PDOS(_r_) ((u64)(_r_) << 32) +#define UCSI_GET_PDOS_SRC_PDOS ((u64)1 << 34) + /* -------------------------------------------------------------------------- */ /* Error information returned by PPM in response to GET_ERROR_STATUS command. */ @@ -294,6 +299,7 @@ struct ucsi { #define UCSI_MAX_SVID 5 #define UCSI_MAX_ALTMODES (UCSI_MAX_SVID * 6) +#define UCSI_MAX_PDOS (4) struct ucsi_connector { int num; @@ -313,6 +319,9 @@ struct ucsi_connector { struct ucsi_connector_status status; struct ucsi_connector_capability cap; + u32 rdo; + u32 src_pdos[UCSI_MAX_PDOS]; + int num_pdos; }; int ucsi_send_command(struct ucsi *ucsi, u64 command, From patchwork Thu Apr 23 13:20:58 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Heikki Krogerus X-Patchwork-Id: 11505683 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 5893592C for ; Thu, 23 Apr 2020 13:21:15 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 41E1420857 for ; Thu, 23 Apr 2020 13:21:15 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728413AbgDWNVO (ORCPT ); Thu, 23 Apr 2020 09:21:14 -0400 Received: from mga07.intel.com ([134.134.136.100]:16372 "EHLO mga07.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728367AbgDWNVN (ORCPT ); Thu, 23 Apr 2020 09:21:13 -0400 IronPort-SDR: 28Ggxv1PAp2Cfi+o3FHJpHAie+Q28kHFBEiWjZxZwsfdh4AlOBmwr/Ml0xy9OuRCKimDexIipE w5hAy91EON1w== X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by orsmga105.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 23 Apr 2020 06:21:12 -0700 IronPort-SDR: R5BOH4lLyTSvidrVMB0qtVpqpd/xpl6pusWzYmHDsdDiwTn76KTlo/d1zPYh5ZQBqFOznf3def cvaNhKSd3jmw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.73,307,1583222400"; d="scan'208";a="366001040" Received: from black.fi.intel.com (HELO black.fi.intel.com.) ([10.237.72.28]) by fmsmga001.fm.intel.com with ESMTP; 23 Apr 2020 06:21:11 -0700 From: Heikki Krogerus To: Greg Kroah-Hartman Cc: linux-usb@vger.kernel.org, "K V, Abhilash" Subject: [PATCH 6/6] usb: typec: ucsi: register with power_supply class Date: Thu, 23 Apr 2020 16:20:58 +0300 Message-Id: <20200423132058.6972-7-heikki.krogerus@linux.intel.com> X-Mailer: git-send-email 2.26.1 In-Reply-To: <20200423132058.6972-1-heikki.krogerus@linux.intel.com> References: <20200423132058.6972-1-heikki.krogerus@linux.intel.com> MIME-Version: 1.0 Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org From: "K V, Abhilash" With this change the UCSI device will show up in /sys/class/power_supply/. The following values are exported: - online - usb_type - voltage_min - voltage_max - voltage_now - current_max - current_now Once a PD-capable type-C power source is connected to the system, GET_PDOS UCSI command is used to query all source capabilities. Request data object (RDO) is used to get current values. Signed-off-by: K V, Abhilash Signed-off-by: Heikki Krogerus --- drivers/usb/typec/ucsi/Makefile | 4 + drivers/usb/typec/ucsi/psy.c | 241 ++++++++++++++++++++++++++++++++ drivers/usb/typec/ucsi/ucsi.c | 6 + drivers/usb/typec/ucsi/ucsi.h | 15 ++ 4 files changed, 266 insertions(+) create mode 100644 drivers/usb/typec/ucsi/psy.c diff --git a/drivers/usb/typec/ucsi/Makefile b/drivers/usb/typec/ucsi/Makefile index b35e15a1f02c..8a8eb5cb8e0f 100644 --- a/drivers/usb/typec/ucsi/Makefile +++ b/drivers/usb/typec/ucsi/Makefile @@ -7,6 +7,10 @@ typec_ucsi-y := ucsi.o typec_ucsi-$(CONFIG_TRACING) += trace.o +ifneq ($(CONFIG_POWER_SUPPLY),) + typec_ucsi-y += psy.o +endif + ifneq ($(CONFIG_TYPEC_DP_ALTMODE),) typec_ucsi-y += displayport.o endif diff --git a/drivers/usb/typec/ucsi/psy.c b/drivers/usb/typec/ucsi/psy.c new file mode 100644 index 000000000000..26ed0b520749 --- /dev/null +++ b/drivers/usb/typec/ucsi/psy.c @@ -0,0 +1,241 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Power Supply for UCSI + * + * Copyright (C) 2020, Intel Corporation + * Author: K V, Abhilash + * Author: Heikki Krogerus + */ + +#include +#include + +#include "ucsi.h" + +/* Power Supply access to expose source power information */ +enum ucsi_psy_online_states { + UCSI_PSY_OFFLINE = 0, + UCSI_PSY_FIXED_ONLINE, + UCSI_PSY_PROG_ONLINE, +}; + +static enum power_supply_property ucsi_psy_props[] = { + POWER_SUPPLY_PROP_USB_TYPE, + POWER_SUPPLY_PROP_ONLINE, + POWER_SUPPLY_PROP_VOLTAGE_MIN, + POWER_SUPPLY_PROP_VOLTAGE_MAX, + POWER_SUPPLY_PROP_VOLTAGE_NOW, + POWER_SUPPLY_PROP_CURRENT_MAX, + POWER_SUPPLY_PROP_CURRENT_NOW, +}; + +static int ucsi_psy_get_online(struct ucsi_connector *con, + union power_supply_propval *val) +{ + val->intval = UCSI_PSY_OFFLINE; + if (con->status.flags & UCSI_CONSTAT_CONNECTED && + (con->status.flags & UCSI_CONSTAT_PWR_DIR) == TYPEC_SINK) + val->intval = UCSI_PSY_FIXED_ONLINE; + return 0; +} + +static int ucsi_psy_get_voltage_min(struct ucsi_connector *con, + union power_supply_propval *val) +{ + u32 pdo; + + switch (UCSI_CONSTAT_PWR_OPMODE(con->status.flags)) { + case UCSI_CONSTAT_PWR_OPMODE_PD: + pdo = con->src_pdos[0]; + val->intval = pdo_fixed_voltage(pdo) * 1000; + break; + case UCSI_CONSTAT_PWR_OPMODE_TYPEC3_0: + case UCSI_CONSTAT_PWR_OPMODE_TYPEC1_5: + case UCSI_CONSTAT_PWR_OPMODE_BC: + case UCSI_CONSTAT_PWR_OPMODE_DEFAULT: + val->intval = UCSI_TYPEC_VSAFE5V * 1000; + break; + default: + val->intval = 0; + break; + } + return 0; +} + +static int ucsi_psy_get_voltage_max(struct ucsi_connector *con, + union power_supply_propval *val) +{ + u32 pdo; + + switch (UCSI_CONSTAT_PWR_OPMODE(con->status.flags)) { + case UCSI_CONSTAT_PWR_OPMODE_PD: + if (con->num_pdos > 0) { + pdo = con->src_pdos[con->num_pdos - 1]; + val->intval = pdo_fixed_voltage(pdo) * 1000; + } else { + val->intval = 0; + } + break; + case UCSI_CONSTAT_PWR_OPMODE_TYPEC3_0: + case UCSI_CONSTAT_PWR_OPMODE_TYPEC1_5: + case UCSI_CONSTAT_PWR_OPMODE_BC: + case UCSI_CONSTAT_PWR_OPMODE_DEFAULT: + val->intval = UCSI_TYPEC_VSAFE5V * 1000; + break; + default: + val->intval = 0; + break; + } + return 0; +} + +static int ucsi_psy_get_voltage_now(struct ucsi_connector *con, + union power_supply_propval *val) +{ + int index; + u32 pdo; + + switch (UCSI_CONSTAT_PWR_OPMODE(con->status.flags)) { + case UCSI_CONSTAT_PWR_OPMODE_PD: + index = rdo_index(con->rdo); + if (index > 0) { + pdo = con->src_pdos[index - 1]; + val->intval = pdo_fixed_voltage(pdo) * 1000; + } else { + val->intval = 0; + } + break; + case UCSI_CONSTAT_PWR_OPMODE_TYPEC3_0: + case UCSI_CONSTAT_PWR_OPMODE_TYPEC1_5: + case UCSI_CONSTAT_PWR_OPMODE_BC: + case UCSI_CONSTAT_PWR_OPMODE_DEFAULT: + val->intval = UCSI_TYPEC_VSAFE5V * 1000; + break; + default: + val->intval = 0; + break; + } + return 0; +} + +static int ucsi_psy_get_current_max(struct ucsi_connector *con, + union power_supply_propval *val) +{ + u32 pdo; + + switch (UCSI_CONSTAT_PWR_OPMODE(con->status.flags)) { + case UCSI_CONSTAT_PWR_OPMODE_PD: + if (con->num_pdos > 0) { + pdo = con->src_pdos[con->num_pdos - 1]; + val->intval = pdo_max_current(pdo) * 1000; + } else { + val->intval = 0; + } + break; + case UCSI_CONSTAT_PWR_OPMODE_TYPEC1_5: + val->intval = UCSI_TYPEC_1_5_CURRENT * 1000; + break; + case UCSI_CONSTAT_PWR_OPMODE_TYPEC3_0: + val->intval = UCSI_TYPEC_3_0_CURRENT * 1000; + break; + case UCSI_CONSTAT_PWR_OPMODE_BC: + case UCSI_CONSTAT_PWR_OPMODE_DEFAULT: + /* UCSI can't tell b/w DCP/CDP or USB2/3x1/3x2 SDP chargers */ + default: + val->intval = 0; + break; + } + return 0; +} + +static int ucsi_psy_get_current_now(struct ucsi_connector *con, + union power_supply_propval *val) +{ + u16 flags = con->status.flags; + + if (UCSI_CONSTAT_PWR_OPMODE(flags) == UCSI_CONSTAT_PWR_OPMODE_PD) + val->intval = rdo_op_current(con->rdo) * 1000; + else + val->intval = 0; + return 0; +} + +static int ucsi_psy_get_usb_type(struct ucsi_connector *con, + union power_supply_propval *val) +{ + u16 flags = con->status.flags; + + val->intval = POWER_SUPPLY_USB_TYPE_C; + if (flags & UCSI_CONSTAT_CONNECTED && + UCSI_CONSTAT_PWR_OPMODE(flags) == UCSI_CONSTAT_PWR_OPMODE_PD) + val->intval = POWER_SUPPLY_USB_TYPE_PD; + + return 0; +} + +static int ucsi_psy_get_prop(struct power_supply *psy, + enum power_supply_property psp, + union power_supply_propval *val) +{ + struct ucsi_connector *con = power_supply_get_drvdata(psy); + + switch (psp) { + case POWER_SUPPLY_PROP_USB_TYPE: + return ucsi_psy_get_usb_type(con, val); + case POWER_SUPPLY_PROP_ONLINE: + return ucsi_psy_get_online(con, val); + case POWER_SUPPLY_PROP_VOLTAGE_MIN: + return ucsi_psy_get_voltage_min(con, val); + case POWER_SUPPLY_PROP_VOLTAGE_MAX: + return ucsi_psy_get_voltage_max(con, val); + case POWER_SUPPLY_PROP_VOLTAGE_NOW: + return ucsi_psy_get_voltage_now(con, val); + case POWER_SUPPLY_PROP_CURRENT_MAX: + return ucsi_psy_get_current_max(con, val); + case POWER_SUPPLY_PROP_CURRENT_NOW: + return ucsi_psy_get_current_now(con, val); + default: + return -EINVAL; + } +} + +static enum power_supply_usb_type ucsi_psy_usb_types[] = { + POWER_SUPPLY_USB_TYPE_C, + POWER_SUPPLY_USB_TYPE_PD, + POWER_SUPPLY_USB_TYPE_PD_PPS, +}; + +int ucsi_register_port_psy(struct ucsi_connector *con) +{ + struct power_supply_config psy_cfg = {}; + struct device *dev = con->ucsi->dev; + char *psy_name; + + psy_cfg.drv_data = con; + psy_cfg.fwnode = dev_fwnode(dev); + + psy_name = devm_kasprintf(dev, GFP_KERNEL, "ucsi-source-psy-%s%d", + dev_name(dev), con->num); + if (!psy_name) + return -ENOMEM; + + con->psy_desc.name = psy_name; + con->psy_desc.type = POWER_SUPPLY_TYPE_USB, + con->psy_desc.usb_types = ucsi_psy_usb_types; + con->psy_desc.num_usb_types = ARRAY_SIZE(ucsi_psy_usb_types); + con->psy_desc.properties = ucsi_psy_props, + con->psy_desc.num_properties = ARRAY_SIZE(ucsi_psy_props), + con->psy_desc.get_property = ucsi_psy_get_prop; + + con->psy = power_supply_register(dev, &con->psy_desc, &psy_cfg); + + return PTR_ERR_OR_ZERO(con->psy); +} + +void ucsi_unregister_port_psy(struct ucsi_connector *con) +{ + if (IS_ERR_OR_NULL(con->psy)) + return; + + power_supply_unregister(con->psy); +} diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c index ffea795da815..d0c63afaf345 100644 --- a/drivers/usb/typec/ucsi/ucsi.c +++ b/drivers/usb/typec/ucsi/ucsi.c @@ -936,6 +936,10 @@ static int ucsi_register_port(struct ucsi *ucsi, int index) cap->driver_data = con; cap->ops = &ucsi_ops; + ret = ucsi_register_port_psy(con); + if (ret) + return ret; + /* Register the connector */ con->port = typec_register_port(ucsi->dev, cap); if (IS_ERR(con->port)) @@ -1062,6 +1066,7 @@ int ucsi_init(struct ucsi *ucsi) for (con = ucsi->connector; con->port; con++) { ucsi_unregister_partner(con); ucsi_unregister_altmodes(con, UCSI_RECIPIENT_CON); + ucsi_unregister_port_psy(con); typec_unregister_port(con->port); con->port = NULL; } @@ -1185,6 +1190,7 @@ void ucsi_unregister(struct ucsi *ucsi) ucsi_unregister_partner(&ucsi->connector[i]); ucsi_unregister_altmodes(&ucsi->connector[i], UCSI_RECIPIENT_CON); + ucsi_unregister_port_psy(&ucsi->connector[i]); typec_unregister_port(ucsi->connector[i].port); } diff --git a/drivers/usb/typec/ucsi/ucsi.h b/drivers/usb/typec/ucsi/ucsi.h index 28e21a1e6b61..e52b5540b254 100644 --- a/drivers/usb/typec/ucsi/ucsi.h +++ b/drivers/usb/typec/ucsi/ucsi.h @@ -5,6 +5,7 @@ #include #include +#include #include #include @@ -301,6 +302,10 @@ struct ucsi { #define UCSI_MAX_ALTMODES (UCSI_MAX_SVID * 6) #define UCSI_MAX_PDOS (4) +#define UCSI_TYPEC_VSAFE5V 5000 +#define UCSI_TYPEC_1_5_CURRENT 1500 +#define UCSI_TYPEC_3_0_CURRENT 3000 + struct ucsi_connector { int num; @@ -319,6 +324,8 @@ struct ucsi_connector { struct ucsi_connector_status status; struct ucsi_connector_capability cap; + struct power_supply *psy; + struct power_supply_desc psy_desc; u32 rdo; u32 src_pdos[UCSI_MAX_PDOS]; int num_pdos; @@ -330,6 +337,14 @@ int ucsi_send_command(struct ucsi *ucsi, u64 command, void ucsi_altmode_update_active(struct ucsi_connector *con); int ucsi_resume(struct ucsi *ucsi); +#if IS_ENABLED(CONFIG_POWER_SUPPLY) +int ucsi_register_port_psy(struct ucsi_connector *con); +void ucsi_unregister_port_psy(struct ucsi_connector *con); +#else +static inline int ucsi_register_port(struct ucsi_connector *con) { return 0; } +static inline void ucsi_unregister_port_psy(struct ucsi_connector *con) { } +#endif /* CONFIG_POWER_SUPPLY */ + #if IS_ENABLED(CONFIG_TYPEC_DP_ALTMODE) struct typec_altmode * ucsi_register_displayport(struct ucsi_connector *con,