From patchwork Thu Mar 7 16:36:00 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 10843349 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 25881922 for ; Thu, 7 Mar 2019 16:36:15 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 11A1E2F5AE for ; Thu, 7 Mar 2019 16:36:15 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 05EAC2F5B6; Thu, 7 Mar 2019 16:36:15 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 8978A2F5BC for ; Thu, 7 Mar 2019 16:36:14 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726364AbfCGQgO (ORCPT ); Thu, 7 Mar 2019 11:36:14 -0500 Received: from mx1.redhat.com ([209.132.183.28]:58454 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726346AbfCGQgN (ORCPT ); Thu, 7 Mar 2019 11:36:13 -0500 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 26E23883BC; Thu, 7 Mar 2019 16:36:13 +0000 (UTC) Received: from shalem.localdomain.com (ovpn-116-59.ams2.redhat.com [10.36.116.59]) by smtp.corp.redhat.com (Postfix) with ESMTP id 0B94A608C1; Thu, 7 Mar 2019 16:36:10 +0000 (UTC) From: Hans de Goede To: Greg Kroah-Hartman , Guenter Roeck , Heikki Krogerus Cc: Hans de Goede , linux-usb@vger.kernel.org Subject: [PATCH v2 1/8] usb: typec: fusb302: Make fusb302_set_cc_polarity also set pull ups / downs Date: Thu, 7 Mar 2019 17:36:00 +0100 Message-Id: <20190307163607.24016-2-hdegoede@redhat.com> In-Reply-To: <20190307163607.24016-1-hdegoede@redhat.com> References: <20190307163607.24016-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.26]); Thu, 07 Mar 2019 16:36:13 +0000 (UTC) Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The 2 callers of fusb302_set_cc_polarity both call fusb302_set_cc_pull directly before calling fusb302_set_cc_polarity, this is not ideal for 2 reasons: 1) fusb302_set_cc_pull uses the cached polarity when applying pull-ups, which maybe changed immediately afterwards, to fix this set_cc_polarity already does the pull-up setting. 2) Both touch the SWITCHES0 register in a r-w-modify cycle, this leads to read reg, write reg, read reg, write reg. If we fold the setting of the pull-downs into fusb302_set_cc_polarity then not only can we avoid doing the reads / writes twice, at this point we set all bits, so we can skip the read, turning 4 (slowish) i2c-transfers into 1. Doing this also avoids the need to cache the pull_up state in struct fusb302_chip. Signed-off-by: Hans de Goede Reviewed-by: Guenter Roeck --- drivers/usb/typec/tcpm/fusb302.c | 48 +++++++++++--------------------- 1 file changed, 16 insertions(+), 32 deletions(-) diff --git a/drivers/usb/typec/tcpm/fusb302.c b/drivers/usb/typec/tcpm/fusb302.c index e9344997329c..d2cce67289d4 100644 --- a/drivers/usb/typec/tcpm/fusb302.c +++ b/drivers/usb/typec/tcpm/fusb302.c @@ -99,7 +99,6 @@ struct fusb302_chip { bool intr_comp_chng; /* port status */ - bool pull_up; bool vconn_on; bool vbus_on; bool charge_on; @@ -540,7 +539,6 @@ static int fusb302_set_cc_pull(struct fusb302_chip *chip, mask, data); if (ret < 0) return ret; - chip->pull_up = pull_up; return ret; } @@ -1226,38 +1224,36 @@ static const char * const cc_polarity_name[] = { [TYPEC_POLARITY_CC2] = "Polarity_CC2", }; -static int fusb302_set_cc_polarity(struct fusb302_chip *chip, - enum typec_cc_polarity cc_polarity) +static int fusb302_set_cc_polarity_and_pull(struct fusb302_chip *chip, + enum typec_cc_polarity cc_polarity, + bool pull_up, bool pull_down) { int ret = 0; - u8 switches0_mask = FUSB_REG_SWITCHES0_CC1_PU_EN | - FUSB_REG_SWITCHES0_CC2_PU_EN | - FUSB_REG_SWITCHES0_VCONN_CC1 | - FUSB_REG_SWITCHES0_VCONN_CC2 | - FUSB_REG_SWITCHES0_MEAS_CC1 | - FUSB_REG_SWITCHES0_MEAS_CC2; u8 switches0_data = 0x00; u8 switches1_mask = FUSB_REG_SWITCHES1_TXCC1_EN | FUSB_REG_SWITCHES1_TXCC2_EN; u8 switches1_data = 0x00; + if (pull_down) + switches0_data |= FUSB_REG_SWITCHES0_CC1_PD_EN | + FUSB_REG_SWITCHES0_CC2_PD_EN; + if (cc_polarity == TYPEC_POLARITY_CC1) { - switches0_data = FUSB_REG_SWITCHES0_MEAS_CC1; + switches0_data |= FUSB_REG_SWITCHES0_MEAS_CC1; if (chip->vconn_on) switches0_data |= FUSB_REG_SWITCHES0_VCONN_CC2; - if (chip->pull_up) + if (pull_up) switches0_data |= FUSB_REG_SWITCHES0_CC1_PU_EN; switches1_data = FUSB_REG_SWITCHES1_TXCC1_EN; } else { - switches0_data = FUSB_REG_SWITCHES0_MEAS_CC2; + switches0_data |= FUSB_REG_SWITCHES0_MEAS_CC2; if (chip->vconn_on) switches0_data |= FUSB_REG_SWITCHES0_VCONN_CC1; - if (chip->pull_up) + if (pull_up) switches0_data |= FUSB_REG_SWITCHES0_CC2_PU_EN; switches1_data = FUSB_REG_SWITCHES1_TXCC2_EN; } - ret = fusb302_i2c_mask_write(chip, FUSB_REG_SWITCHES0, - switches0_mask, switches0_data); + ret = fusb302_i2c_write(chip, FUSB_REG_SWITCHES0, switches0_data); if (ret < 0) return ret; ret = fusb302_i2c_mask_write(chip, FUSB_REG_SWITCHES1, @@ -1278,16 +1274,10 @@ static int fusb302_handle_togdone_snk(struct fusb302_chip *chip, enum typec_cc_polarity cc_polarity; enum typec_cc_status cc_status_active, cc1, cc2; - /* set pull_up, pull_down */ - ret = fusb302_set_cc_pull(chip, false, true); - if (ret < 0) { - fusb302_log(chip, "cannot set cc to pull down, ret=%d", ret); - return ret; - } - /* set polarity */ + /* set polarity and pull_up, pull_down */ cc_polarity = (togdone_result == FUSB_REG_STATUS1A_TOGSS_SNK1) ? TYPEC_POLARITY_CC1 : TYPEC_POLARITY_CC2; - ret = fusb302_set_cc_polarity(chip, cc_polarity); + ret = fusb302_set_cc_polarity_and_pull(chip, cc_polarity, false, true); if (ret < 0) { fusb302_log(chip, "cannot set cc polarity %s, ret=%d", cc_polarity_name[cc_polarity], ret); @@ -1354,16 +1344,10 @@ static int fusb302_handle_togdone_src(struct fusb302_chip *chip, enum typec_cc_polarity cc_polarity; enum typec_cc_status cc_status_active, cc1, cc2; - /* set pull_up, pull_down */ - ret = fusb302_set_cc_pull(chip, true, false); - if (ret < 0) { - fusb302_log(chip, "cannot set cc to pull up, ret=%d", ret); - return ret; - } - /* set polarity */ + /* set polarity and pull_up, pull_down */ cc_polarity = (togdone_result == FUSB_REG_STATUS1A_TOGSS_SRC1) ? TYPEC_POLARITY_CC1 : TYPEC_POLARITY_CC2; - ret = fusb302_set_cc_polarity(chip, cc_polarity); + ret = fusb302_set_cc_polarity_and_pull(chip, cc_polarity, true, false); if (ret < 0) { fusb302_log(chip, "cannot set cc polarity %s, ret=%d", cc_polarity_name[cc_polarity], ret); From patchwork Thu Mar 7 16:36:01 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 10843351 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 9887D922 for ; Thu, 7 Mar 2019 16:36:16 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 849622F528 for ; Thu, 7 Mar 2019 16:36:16 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 78FC62F579; Thu, 7 Mar 2019 16:36:16 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id EF6292F528 for ; Thu, 7 Mar 2019 16:36:15 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726375AbfCGQgP (ORCPT ); Thu, 7 Mar 2019 11:36:15 -0500 Received: from mx1.redhat.com ([209.132.183.28]:60666 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726346AbfCGQgP (ORCPT ); Thu, 7 Mar 2019 11:36:15 -0500 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 82FD8307EA96; Thu, 7 Mar 2019 16:36:14 +0000 (UTC) Received: from shalem.localdomain.com (ovpn-116-59.ams2.redhat.com [10.36.116.59]) by smtp.corp.redhat.com (Postfix) with ESMTP id 6BF9160856; Thu, 7 Mar 2019 16:36:13 +0000 (UTC) From: Hans de Goede To: Greg Kroah-Hartman , Guenter Roeck , Heikki Krogerus Cc: Hans de Goede , linux-usb@vger.kernel.org Subject: [PATCH v2 2/8] usb: typec: fusb302: Refactor / simplify tcpm_set_cc() Date: Thu, 7 Mar 2019 17:36:01 +0100 Message-Id: <20190307163607.24016-3-hdegoede@redhat.com> In-Reply-To: <20190307163607.24016-1-hdegoede@redhat.com> References: <20190307163607.24016-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.44]); Thu, 07 Mar 2019 16:36:14 +0000 (UTC) Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP After commit ea3b4d5523bc ("usb: typec: fusb302: Resolve fixed power role contract setup"), tcpm_set_cc always calls fusb302_set_toggling. Before this refactor tcpm_set_cc does the following: 1) fusb302_set_toggling(TOGGLING_MODE_OFF), this sets both FUSB_REG_MASK_BC_LVL and FUSB_REG_MASK_COMP_CHNG. 2) fusb302_set_cc_pull(...). 3) "reset cc status". 4) if pull-up fusb302_set_src_current(...). 5) if pull-up or pull-down enable bc-lvl resp comp-chng irq. 6) fusb302_set_toggling(new-toggling-mode), which again sets both FUSB_REG_MASK_BC_LVL and FUSB_REG_MASK_COMP_CHNG disabling the just enabled irq. fusb302_set_toggling is skipped when the new toggling mode is TOGGLING_MODE_OFF because this is already done in 1, note in this case 5) is a no-op. When we are toggling the bits set by fusb302_set_cc_pull will be ignored until we turn toggling off, so we can safely move the fusb302_set_cc_pull call to before setting TOGGLING_MODE_OFF. Either we are not toggling yet, or the src-current has already been set, so we can also safely set the src-current earlier, allowing us to do the fusb302_set_toggling(TOGGLING_MODE_OFF) call at the same time as we set the other toggling modes. Also setting the src-current is a no-op when not enabling pull-ups, so we can drop the if. And since the second fusb302_set_toggling undoes the effects of step 5, we can skip step 5, the bc-lvl resp comp-chng irq wil be enabled by fusb302_handle_togdone_snk resp. fusb302_handle_togdone_src when toggling is done. Together this allows us to simplify things to: 1) fusb302_set_cc_pull(...) 2) "reset cc status" 3) fusb302_set_src_current(...) 4) fusb302_set_toggling(new-toggling-mode) This commit does this, leading to a nice cleanup. Signed-off-by: Hans de Goede Reviewed-by: Guenter Roeck --- drivers/usb/typec/tcpm/fusb302.c | 85 ++++++-------------------------- 1 file changed, 15 insertions(+), 70 deletions(-) diff --git a/drivers/usb/typec/tcpm/fusb302.c b/drivers/usb/typec/tcpm/fusb302.c index d2cce67289d4..bcb38e397712 100644 --- a/drivers/usb/typec/tcpm/fusb302.c +++ b/drivers/usb/typec/tcpm/fusb302.c @@ -676,7 +676,6 @@ static int tcpm_set_cc(struct tcpc_dev *dev, enum typec_cc_status cc) tcpc_dev); int ret = 0; bool pull_up, pull_down; - u8 rd_mda; enum toggling_mode mode; mutex_lock(&chip->lock); @@ -684,16 +683,19 @@ static int tcpm_set_cc(struct tcpc_dev *dev, enum typec_cc_status cc) case TYPEC_CC_OPEN: pull_up = false; pull_down = false; + mode = TOGGLING_MODE_OFF; break; case TYPEC_CC_RD: pull_up = false; pull_down = true; + mode = TOGGLING_MODE_SNK; break; case TYPEC_CC_RP_DEF: case TYPEC_CC_RP_1_5: case TYPEC_CC_RP_3_0: pull_up = true; pull_down = false; + mode = TOGGLING_MODE_SRC; break; default: fusb302_log(chip, "unsupported cc value %s", @@ -701,11 +703,9 @@ static int tcpm_set_cc(struct tcpc_dev *dev, enum typec_cc_status cc) ret = -EINVAL; goto done; } - ret = fusb302_set_toggling(chip, TOGGLING_MODE_OFF); - if (ret < 0) { - fusb302_log(chip, "cannot stop toggling, ret=%d", ret); - goto done; - } + + fusb302_log(chip, "cc := %s", typec_cc_status_name[cc]); + ret = fusb302_set_cc_pull(chip, pull_up, pull_down); if (ret < 0) { fusb302_log(chip, @@ -718,74 +718,19 @@ static int tcpm_set_cc(struct tcpc_dev *dev, enum typec_cc_status cc) /* reset the cc status */ chip->cc1 = TYPEC_CC_OPEN; chip->cc2 = TYPEC_CC_OPEN; + /* adjust current for SRC */ - if (pull_up) { - ret = fusb302_set_src_current(chip, cc_src_current[cc]); - if (ret < 0) { - fusb302_log(chip, "cannot set src current %s, ret=%d", - typec_cc_status_name[cc], ret); - goto done; - } - } - /* enable/disable interrupts, BC_LVL for SNK and COMP_CHNG for SRC */ - if (pull_up) { - rd_mda = rd_mda_value[cc_src_current[cc]]; - ret = fusb302_i2c_write(chip, FUSB_REG_MEASURE, rd_mda); - if (ret < 0) { - fusb302_log(chip, - "cannot set SRC measure value, ret=%d", - ret); - goto done; - } - ret = fusb302_i2c_mask_write(chip, FUSB_REG_MASK, - FUSB_REG_MASK_BC_LVL | - FUSB_REG_MASK_COMP_CHNG, - FUSB_REG_MASK_COMP_CHNG); - if (ret < 0) { - fusb302_log(chip, "cannot set SRC interrupt, ret=%d", - ret); - goto done; - } - chip->intr_bc_lvl = false; - chip->intr_comp_chng = true; - } - if (pull_down) { - ret = fusb302_i2c_mask_write(chip, FUSB_REG_MASK, - FUSB_REG_MASK_BC_LVL | - FUSB_REG_MASK_COMP_CHNG, - FUSB_REG_MASK_BC_LVL); - if (ret < 0) { - fusb302_log(chip, "cannot set SRC interrupt, ret=%d", - ret); - goto done; - } - chip->intr_bc_lvl = true; - chip->intr_comp_chng = false; + ret = fusb302_set_src_current(chip, cc_src_current[cc]); + if (ret < 0) { + fusb302_log(chip, "cannot set src current %s, ret=%d", + typec_cc_status_name[cc], ret); + goto done; } - fusb302_log(chip, "cc := %s", typec_cc_status_name[cc]); - /* Enable detection for fixed SNK or SRC only roles */ - switch (cc) { - case TYPEC_CC_RD: - mode = TOGGLING_MODE_SNK; - break; - case TYPEC_CC_RP_DEF: - case TYPEC_CC_RP_1_5: - case TYPEC_CC_RP_3_0: - mode = TOGGLING_MODE_SRC; - break; - default: - mode = TOGGLING_MODE_OFF; - break; - } + ret = fusb302_set_toggling(chip, mode); + if (ret < 0) + fusb302_log(chip, "cannot set toggling mode, ret=%d", ret); - if (mode != TOGGLING_MODE_OFF) { - ret = fusb302_set_toggling(chip, mode); - if (ret < 0) - fusb302_log(chip, - "cannot set fixed role toggling mode, ret=%d", - ret); - } done: mutex_unlock(&chip->lock); From patchwork Thu Mar 7 16:36:02 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 10843353 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 77537139A for ; Thu, 7 Mar 2019 16:36:19 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 655EC2F528 for ; Thu, 7 Mar 2019 16:36:19 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 5978F2F579; Thu, 7 Mar 2019 16:36:19 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id F06FC2F528 for ; Thu, 7 Mar 2019 16:36:18 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726380AbfCGQgS (ORCPT ); Thu, 7 Mar 2019 11:36:18 -0500 Received: from mx1.redhat.com ([209.132.183.28]:55038 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726346AbfCGQgS (ORCPT ); Thu, 7 Mar 2019 11:36:18 -0500 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 926B5309E972; Thu, 7 Mar 2019 16:36:17 +0000 (UTC) Received: from shalem.localdomain.com (ovpn-116-59.ams2.redhat.com [10.36.116.59]) by smtp.corp.redhat.com (Postfix) with ESMTP id C4C5960856; Thu, 7 Mar 2019 16:36:14 +0000 (UTC) From: Hans de Goede To: Greg Kroah-Hartman , Guenter Roeck , Heikki Krogerus Cc: Hans de Goede , linux-usb@vger.kernel.org Subject: [PATCH v2 3/8] usb: typec: fusb302: Fold fusb302_set_cc_pull into tcpm_set_cc Date: Thu, 7 Mar 2019 17:36:02 +0100 Message-Id: <20190307163607.24016-4-hdegoede@redhat.com> In-Reply-To: <20190307163607.24016-1-hdegoede@redhat.com> References: <20190307163607.24016-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.49]); Thu, 07 Mar 2019 16:36:17 +0000 (UTC) Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP After the recent cleanups, tcpm_set_cc is the only caller of fusb302_set_cc_pull, fold fusb302_set_cc_pull directly into tcpm_set_cc for a nice cleanup. Signed-off-by: Hans de Goede Reviewed-by: Guenter Roeck --- drivers/usb/typec/tcpm/fusb302.c | 51 ++++++++------------------------ 1 file changed, 13 insertions(+), 38 deletions(-) diff --git a/drivers/usb/typec/tcpm/fusb302.c b/drivers/usb/typec/tcpm/fusb302.c index bcb38e397712..cb6637e82f32 100644 --- a/drivers/usb/typec/tcpm/fusb302.c +++ b/drivers/usb/typec/tcpm/fusb302.c @@ -518,31 +518,6 @@ static int tcpm_get_current_limit(struct tcpc_dev *dev) return current_limit; } -static int fusb302_set_cc_pull(struct fusb302_chip *chip, - bool pull_up, bool pull_down) -{ - int ret = 0; - u8 data = 0x00; - u8 mask = FUSB_REG_SWITCHES0_CC1_PU_EN | - FUSB_REG_SWITCHES0_CC2_PU_EN | - FUSB_REG_SWITCHES0_CC1_PD_EN | - FUSB_REG_SWITCHES0_CC2_PD_EN; - - if (pull_up) - data |= (chip->cc_polarity == TYPEC_POLARITY_CC1) ? - FUSB_REG_SWITCHES0_CC1_PU_EN : - FUSB_REG_SWITCHES0_CC2_PU_EN; - if (pull_down) - data |= FUSB_REG_SWITCHES0_CC1_PD_EN | - FUSB_REG_SWITCHES0_CC2_PD_EN; - ret = fusb302_i2c_mask_write(chip, FUSB_REG_SWITCHES0, - mask, data); - if (ret < 0) - return ret; - - return ret; -} - static int fusb302_set_src_current(struct fusb302_chip *chip, enum src_current_status status) { @@ -674,27 +649,30 @@ static int tcpm_set_cc(struct tcpc_dev *dev, enum typec_cc_status cc) { struct fusb302_chip *chip = container_of(dev, struct fusb302_chip, tcpc_dev); + u8 switches0_mask = FUSB_REG_SWITCHES0_CC1_PU_EN | + FUSB_REG_SWITCHES0_CC2_PU_EN | + FUSB_REG_SWITCHES0_CC1_PD_EN | + FUSB_REG_SWITCHES0_CC2_PD_EN; + u8 switches0_data = 0x00; int ret = 0; - bool pull_up, pull_down; enum toggling_mode mode; mutex_lock(&chip->lock); switch (cc) { case TYPEC_CC_OPEN: - pull_up = false; - pull_down = false; mode = TOGGLING_MODE_OFF; break; case TYPEC_CC_RD: - pull_up = false; - pull_down = true; + switches0_data |= FUSB_REG_SWITCHES0_CC1_PD_EN | + FUSB_REG_SWITCHES0_CC2_PD_EN; mode = TOGGLING_MODE_SNK; break; case TYPEC_CC_RP_DEF: case TYPEC_CC_RP_1_5: case TYPEC_CC_RP_3_0: - pull_up = true; - pull_down = false; + switches0_data |= (chip->cc_polarity == TYPEC_POLARITY_CC1) ? + FUSB_REG_SWITCHES0_CC1_PU_EN : + FUSB_REG_SWITCHES0_CC2_PU_EN; mode = TOGGLING_MODE_SRC; break; default: @@ -706,13 +684,10 @@ static int tcpm_set_cc(struct tcpc_dev *dev, enum typec_cc_status cc) fusb302_log(chip, "cc := %s", typec_cc_status_name[cc]); - ret = fusb302_set_cc_pull(chip, pull_up, pull_down); + ret = fusb302_i2c_mask_write(chip, FUSB_REG_SWITCHES0, + switches0_mask, switches0_data); if (ret < 0) { - fusb302_log(chip, - "cannot set cc pulling up %s, down %s, ret = %d", - pull_up ? "True" : "False", - pull_down ? "True" : "False", - ret); + fusb302_log(chip, "cannot set pull-up/-down, ret = %d", ret); goto done; } /* reset the cc status */ From patchwork Thu Mar 7 16:36:03 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 10843355 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 83AAC139A for ; Thu, 7 Mar 2019 16:36:20 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 719112F530 for ; Thu, 7 Mar 2019 16:36:20 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 65B852F5AB; Thu, 7 Mar 2019 16:36:20 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 1F7DA2F530 for ; Thu, 7 Mar 2019 16:36:20 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726384AbfCGQgT (ORCPT ); Thu, 7 Mar 2019 11:36:19 -0500 Received: from mx1.redhat.com ([209.132.183.28]:25764 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726346AbfCGQgT (ORCPT ); Thu, 7 Mar 2019 11:36:19 -0500 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id F16FD2CD7F9; Thu, 7 Mar 2019 16:36:18 +0000 (UTC) Received: from shalem.localdomain.com (ovpn-116-59.ams2.redhat.com [10.36.116.59]) by smtp.corp.redhat.com (Postfix) with ESMTP id D972960856; Thu, 7 Mar 2019 16:36:17 +0000 (UTC) From: Hans de Goede To: Greg Kroah-Hartman , Guenter Roeck , Heikki Krogerus Cc: Hans de Goede , linux-usb@vger.kernel.org Subject: [PATCH v2 4/8] usb: typec: fusb302: Check vconn is off when we start toggling Date: Thu, 7 Mar 2019 17:36:03 +0100 Message-Id: <20190307163607.24016-5-hdegoede@redhat.com> In-Reply-To: <20190307163607.24016-1-hdegoede@redhat.com> References: <20190307163607.24016-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.29]); Thu, 07 Mar 2019 16:36:19 +0000 (UTC) Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The datasheet says the vconn MUST be off when we start toggling. The tcpm.c state-machine is responsible to make sure vconn is off, but lets add a WARN_ON check to catch any cases where vconn is not off for some reason. Signed-off-by: Hans de Goede --- drivers/usb/typec/tcpm/fusb302.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/typec/tcpm/fusb302.c b/drivers/usb/typec/tcpm/fusb302.c index cb6637e82f32..f43fe34b7a73 100644 --- a/drivers/usb/typec/tcpm/fusb302.c +++ b/drivers/usb/typec/tcpm/fusb302.c @@ -607,6 +607,8 @@ static int fusb302_set_toggling(struct fusb302_chip *chip, return ret; chip->intr_togdone = false; } else { + /* Datasheet says vconn MUST be off when toggling */ + WARN_ON(chip->vconn_on); /* unmask TOGDONE interrupt */ ret = fusb302_i2c_clear_bits(chip, FUSB_REG_MASKA, FUSB_REG_MASKA_TOGDONE); From patchwork Thu Mar 7 16:36:04 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 10843357 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id C28CD922 for ; Thu, 7 Mar 2019 16:36:22 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id ADD7D2F528 for ; Thu, 7 Mar 2019 16:36:22 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id A1F8C2F579; Thu, 7 Mar 2019 16:36:22 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id ED8B92F528 for ; Thu, 7 Mar 2019 16:36:21 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726392AbfCGQgV (ORCPT ); Thu, 7 Mar 2019 11:36:21 -0500 Received: from mx1.redhat.com ([209.132.183.28]:53698 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726346AbfCGQgV (ORCPT ); Thu, 7 Mar 2019 11:36:21 -0500 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 533DE30718DE; Thu, 7 Mar 2019 16:36:20 +0000 (UTC) Received: from shalem.localdomain.com (ovpn-116-59.ams2.redhat.com [10.36.116.59]) by smtp.corp.redhat.com (Postfix) with ESMTP id 3F82860856; Thu, 7 Mar 2019 16:36:19 +0000 (UTC) From: Hans de Goede To: Greg Kroah-Hartman , Guenter Roeck , Heikki Krogerus Cc: Hans de Goede , linux-usb@vger.kernel.org Subject: [PATCH v2 5/8] usb: typec: fusb302: Fix fusb302_handle_togdone_src Ra handling Date: Thu, 7 Mar 2019 17:36:04 +0100 Message-Id: <20190307163607.24016-6-hdegoede@redhat.com> In-Reply-To: <20190307163607.24016-1-hdegoede@redhat.com> References: <20190307163607.24016-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.40]); Thu, 07 Mar 2019 16:36:20 +0000 (UTC) Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The FUSB302 will stop toggling with a FUSB_REG_STATUS1A_TOGSS_SRC? status, as soon as it sees either Ra or Rd on a CC pin. Before this commit fusb302_handle_togdone_src would assume that the toggle- engine always stopped at the CC pin indicating the polarity, IOW it assumed that it stopped at the pin connected to Rd. It did check the CC-status of that pin, but it did not expect to get a CC-status of Ra and therefore treated this as CC-open. This lead to the following 2 problems: 1) If a powered cable/adapter gets plugged in with Ra on CC1 and Rd on CC2 then 4 of 5 times when plugged in toggling will stop with a togdone_result of FUSB_REG_STATUS1A_TOGSS_SRC1. 3/5th of the time the toggle-engine is testing for being connected as a sink and after that it tests 1/5th of the time for connected as a src through CC1 before finally testing the last 1/5th of the time for being a src connected through CC2. This was a problem because we would only check the CC pin status for the pin on which the toggling stopped which in this polarity 4 out of 5 times would be the Ra pin. The code before this commit would treat Ra as CC-open and then restart toggling. Once toggling is restarted we are guaranteed to end with FUSB_REG_STATUS1A_TOGSS_SRC1 as CC1 is tested first, leading to a CC-status of Ra again and an infinite restart toggling loop. So 4 out of 5 times when plugged in in this polarity a powered adapter will not work. 2) Even if we happen to have the right polarity or 1/5th of the time in the polarity with problem 1), we would report the non Rd pin as CC-open rather then as Ra, resulting in the tcpm.c code not enabling Vconn which is a problem for some adapters. This commit fixes this by getting the CC-status of *both* pins and then determining the polarity based on that, rather then on where the toggling stopped. Signed-off-by: Hans de Goede --- drivers/usb/typec/tcpm/fusb302.c | 149 ++++++++++++++++++++----------- 1 file changed, 97 insertions(+), 52 deletions(-) diff --git a/drivers/usb/typec/tcpm/fusb302.c b/drivers/usb/typec/tcpm/fusb302.c index f43fe34b7a73..b74c6ff67aae 100644 --- a/drivers/usb/typec/tcpm/fusb302.c +++ b/drivers/usb/typec/tcpm/fusb302.c @@ -1249,6 +1249,62 @@ static int fusb302_handle_togdone_snk(struct fusb302_chip *chip, return ret; } +/* On error returns < 0, otherwise a typec_cc_status value */ +static int fusb302_get_src_cc_status(struct fusb302_chip *chip, + enum typec_cc_polarity cc_polarity, + enum typec_cc_status *cc) +{ + u8 ra_mda = ra_mda_value[chip->src_current_status]; + u8 rd_mda = rd_mda_value[chip->src_current_status]; + u8 switches0_data, status0; + int ret; + + /* Step 1: Set switches so that we measure the right CC pin */ + switches0_data = (cc_polarity == TYPEC_POLARITY_CC1) ? + FUSB_REG_SWITCHES0_CC1_PU_EN | FUSB_REG_SWITCHES0_MEAS_CC1 : + FUSB_REG_SWITCHES0_CC2_PU_EN | FUSB_REG_SWITCHES0_MEAS_CC2; + ret = fusb302_i2c_write(chip, FUSB_REG_SWITCHES0, switches0_data); + if (ret < 0) + return ret; + + fusb302_i2c_read(chip, FUSB_REG_SWITCHES0, &status0); + fusb302_log(chip, "get_src_cc_status switches: 0x%0x", status0); + + /* Step 2: Set compararator volt to differentiate between Open and Rd */ + ret = fusb302_i2c_write(chip, FUSB_REG_MEASURE, rd_mda); + if (ret < 0) + return ret; + + usleep_range(5000, 10000); + ret = fusb302_i2c_read(chip, FUSB_REG_STATUS0, &status0); + if (ret < 0) + return ret; + + fusb302_log(chip, "get_src_cc_status rd_mda status0: 0x%0x", status0); + if (status0 & FUSB_REG_STATUS0_COMP) { + *cc = TYPEC_CC_OPEN; + return 0; + } + + /* Step 3: Set compararator input to differentiate between Rd and Ra. */ + ret = fusb302_i2c_write(chip, FUSB_REG_MEASURE, ra_mda); + if (ret < 0) + return ret; + + usleep_range(5000, 10000); + ret = fusb302_i2c_read(chip, FUSB_REG_STATUS0, &status0); + if (ret < 0) + return ret; + + fusb302_log(chip, "get_src_cc_status ra_mda status0: 0x%0x", status0); + if (status0 & FUSB_REG_STATUS0_COMP) + *cc = TYPEC_CC_RD; + else + *cc = TYPEC_CC_RA; + + return 0; +} + static int fusb302_handle_togdone_src(struct fusb302_chip *chip, u8 togdone_result) { @@ -1259,71 +1315,62 @@ static int fusb302_handle_togdone_src(struct fusb302_chip *chip, * - set I_COMP interrupt on */ int ret = 0; - u8 status0; - u8 ra_mda = ra_mda_value[chip->src_current_status]; u8 rd_mda = rd_mda_value[chip->src_current_status]; - bool ra_comp, rd_comp; + enum toggling_mode toggling_mode = chip->toggling_mode; enum typec_cc_polarity cc_polarity; - enum typec_cc_status cc_status_active, cc1, cc2; + enum typec_cc_status cc1, cc2; - /* set polarity and pull_up, pull_down */ - cc_polarity = (togdone_result == FUSB_REG_STATUS1A_TOGSS_SRC1) ? - TYPEC_POLARITY_CC1 : TYPEC_POLARITY_CC2; - ret = fusb302_set_cc_polarity_and_pull(chip, cc_polarity, true, false); + /* + * The toggle-engine will stop in a src state if it sees either Ra or + * Rd. Determine the status for both CC pins, starting with the one + * where toggling stopped, as that is where the switches point now. + */ + if (togdone_result == FUSB_REG_STATUS1A_TOGSS_SRC1) + ret = fusb302_get_src_cc_status(chip, TYPEC_POLARITY_CC1, &cc1); + else + ret = fusb302_get_src_cc_status(chip, TYPEC_POLARITY_CC2, &cc2); + if (ret < 0) + return ret; + /* we must turn off toggling before we can measure the other pin */ + ret = fusb302_set_toggling(chip, TOGGLING_MODE_OFF); if (ret < 0) { - fusb302_log(chip, "cannot set cc polarity %s, ret=%d", - cc_polarity_name[cc_polarity], ret); + fusb302_log(chip, "cannot set toggling mode off, ret=%d", ret); return ret; } - /* fusb302_set_cc_polarity() has set the correct measure block */ - ret = fusb302_i2c_write(chip, FUSB_REG_MEASURE, rd_mda); - if (ret < 0) - return ret; - usleep_range(50, 100); - ret = fusb302_i2c_read(chip, FUSB_REG_STATUS0, &status0); + /* get the status of the other pin */ + if (togdone_result == FUSB_REG_STATUS1A_TOGSS_SRC1) + ret = fusb302_get_src_cc_status(chip, TYPEC_POLARITY_CC2, &cc2); + else + ret = fusb302_get_src_cc_status(chip, TYPEC_POLARITY_CC1, &cc1); if (ret < 0) return ret; - rd_comp = !!(status0 & FUSB_REG_STATUS0_COMP); - if (!rd_comp) { - ret = fusb302_i2c_write(chip, FUSB_REG_MEASURE, ra_mda); - if (ret < 0) - return ret; - usleep_range(50, 100); - ret = fusb302_i2c_read(chip, FUSB_REG_STATUS0, &status0); - if (ret < 0) - return ret; - ra_comp = !!(status0 & FUSB_REG_STATUS0_COMP); + + /* determine polarity based on the status of both pins */ + if (cc1 == TYPEC_CC_RD && + (cc2 == TYPEC_CC_OPEN || cc2 == TYPEC_CC_RA)) { + cc_polarity = TYPEC_POLARITY_CC1; + } else if (cc2 == TYPEC_CC_RD && + (cc1 == TYPEC_CC_OPEN || cc1 == TYPEC_CC_RA)) { + cc_polarity = TYPEC_POLARITY_CC2; + } else { + fusb302_log(chip, "unexpected CC status cc1=%s, cc2=%s, restarting toggling", + typec_cc_status_name[cc1], + typec_cc_status_name[cc2]); + return fusb302_set_toggling(chip, toggling_mode); } - if (rd_comp) - cc_status_active = TYPEC_CC_OPEN; - else if (ra_comp) - cc_status_active = TYPEC_CC_RD; - else - /* Ra is not supported, report as Open */ - cc_status_active = TYPEC_CC_OPEN; - /* restart toggling if the cc status on the active line is OPEN */ - if (cc_status_active == TYPEC_CC_OPEN) { - fusb302_log(chip, "restart toggling as CC_OPEN detected"); - ret = fusb302_set_toggling(chip, chip->toggling_mode); + /* set polarity and pull_up, pull_down */ + ret = fusb302_set_cc_polarity_and_pull(chip, cc_polarity, true, false); + if (ret < 0) { + fusb302_log(chip, "cannot set cc polarity %s, ret=%d", + cc_polarity_name[cc_polarity], ret); return ret; } /* update tcpm with the new cc value */ - cc1 = (cc_polarity == TYPEC_POLARITY_CC1) ? - cc_status_active : TYPEC_CC_OPEN; - cc2 = (cc_polarity == TYPEC_POLARITY_CC2) ? - cc_status_active : TYPEC_CC_OPEN; if ((chip->cc1 != cc1) || (chip->cc2 != cc2)) { chip->cc1 = cc1; chip->cc2 = cc2; tcpm_cc_change(chip->tcpm_port); } - /* turn off toggling */ - ret = fusb302_set_toggling(chip, TOGGLING_MODE_OFF); - if (ret < 0) { - fusb302_log(chip, - "cannot set toggling mode off, ret=%d", ret); - return ret; - } /* set MDAC to Rd threshold, and unmask I_COMP for unplug detection */ ret = fusb302_i2c_write(chip, FUSB_REG_MEASURE, rd_mda); if (ret < 0) @@ -1509,10 +1556,8 @@ static irqreturn_t fusb302_irq_intn(int irq, void *dev_id) comp_result ? "true" : "false"); if (comp_result) { /* cc level > Rd_threashold, detach */ - if (chip->cc_polarity == TYPEC_POLARITY_CC1) - chip->cc1 = TYPEC_CC_OPEN; - else - chip->cc2 = TYPEC_CC_OPEN; + chip->cc1 = TYPEC_CC_OPEN; + chip->cc2 = TYPEC_CC_OPEN; tcpm_cc_change(chip->tcpm_port); } } From patchwork Thu Mar 7 16:36:05 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 10843359 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 30D4B17E9 for ; Thu, 7 Mar 2019 16:36:23 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 1FC052F528 for ; Thu, 7 Mar 2019 16:36:23 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 13D982F530; Thu, 7 Mar 2019 16:36:23 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id BEFE72F5AB for ; Thu, 7 Mar 2019 16:36:22 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726395AbfCGQgW (ORCPT ); Thu, 7 Mar 2019 11:36:22 -0500 Received: from mx1.redhat.com ([209.132.183.28]:47780 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726346AbfCGQgV (ORCPT ); Thu, 7 Mar 2019 11:36:21 -0500 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id B11B3C04FFF7; Thu, 7 Mar 2019 16:36:21 +0000 (UTC) Received: from shalem.localdomain.com (ovpn-116-59.ams2.redhat.com [10.36.116.59]) by smtp.corp.redhat.com (Postfix) with ESMTP id 97DEE60856; Thu, 7 Mar 2019 16:36:20 +0000 (UTC) From: Hans de Goede To: Greg Kroah-Hartman , Guenter Roeck , Heikki Krogerus Cc: Hans de Goede , linux-usb@vger.kernel.org Subject: [PATCH v2 6/8] usb: typec: fusb302: 2 small misc. fixes Date: Thu, 7 Mar 2019 17:36:05 +0100 Message-Id: <20190307163607.24016-7-hdegoede@redhat.com> In-Reply-To: <20190307163607.24016-1-hdegoede@redhat.com> References: <20190307163607.24016-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.31]); Thu, 07 Mar 2019 16:36:21 +0000 (UTC) Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Fix a copy and paste error in an error message and a spelling error in a comment. Signed-off-by: Hans de Goede Reviewed-by: Guenter Roeck --- drivers/usb/typec/tcpm/fusb302.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/typec/tcpm/fusb302.c b/drivers/usb/typec/tcpm/fusb302.c index b74c6ff67aae..23f773d07514 100644 --- a/drivers/usb/typec/tcpm/fusb302.c +++ b/drivers/usb/typec/tcpm/fusb302.c @@ -1380,7 +1380,7 @@ static int fusb302_handle_togdone_src(struct fusb302_chip *chip, FUSB_REG_MASK_COMP_CHNG); if (ret < 0) { fusb302_log(chip, - "cannot unmask bc_lcl interrupt, ret=%d", ret); + "cannot unmask comp_chng interrupt, ret=%d", ret); return ret; } chip->intr_comp_chng = true; @@ -1555,7 +1555,7 @@ static irqreturn_t fusb302_irq_intn(int irq, void *dev_id) fusb302_log(chip, "IRQ: COMP_CHNG, comp=%s", comp_result ? "true" : "false"); if (comp_result) { - /* cc level > Rd_threashold, detach */ + /* cc level > Rd_threshold, detach */ chip->cc1 = TYPEC_CC_OPEN; chip->cc2 = TYPEC_CC_OPEN; tcpm_cc_change(chip->tcpm_port); From patchwork Thu Mar 7 16:36:06 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 10843361 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id AF099139A for ; Thu, 7 Mar 2019 16:36:25 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 9B4ED2F528 for ; Thu, 7 Mar 2019 16:36:25 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 8F5582F579; Thu, 7 Mar 2019 16:36:25 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E3E852F528 for ; Thu, 7 Mar 2019 16:36:24 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726409AbfCGQgY (ORCPT ); Thu, 7 Mar 2019 11:36:24 -0500 Received: from mx1.redhat.com ([209.132.183.28]:52366 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726346AbfCGQgY (ORCPT ); Thu, 7 Mar 2019 11:36:24 -0500 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 641D6318A5FC; Thu, 7 Mar 2019 16:36:23 +0000 (UTC) Received: from shalem.localdomain.com (ovpn-116-59.ams2.redhat.com [10.36.116.59]) by smtp.corp.redhat.com (Postfix) with ESMTP id 002A3608C1; Thu, 7 Mar 2019 16:36:21 +0000 (UTC) From: Hans de Goede To: Greg Kroah-Hartman , Guenter Roeck , Heikki Krogerus Cc: Hans de Goede , linux-usb@vger.kernel.org Subject: [PATCH v2 7/8] usb: typec: fusb302: Improve suspend/resume handling Date: Thu, 7 Mar 2019 17:36:06 +0100 Message-Id: <20190307163607.24016-8-hdegoede@redhat.com> In-Reply-To: <20190307163607.24016-1-hdegoede@redhat.com> References: <20190307163607.24016-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.41]); Thu, 07 Mar 2019 16:36:23 +0000 (UTC) Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Remove the code which avoids doing i2c-transfers while our parent i2c-adapter may be suspended by busy-waiting for our resume handler to be called. Instead move the interrupt handling from a threaded interrupt handler to a work-queue and install a non-threaded interrupt handler which normally queues the new interrupt handling work directly. When our suspend handler gets called we set a flag which makes the new non-threaded interrupt handler skip queueing the work before our parent i2c-adapter is ready, instead the new non-threaded handler will record an interrupt has happened during suspend and then our resume handler will queue the work (at which point our parent will be ready). Note normally i2c drivers solve the problem of not being able to access the i2c bus until the i2c-controller is resumed by simply disabling their irq from the suspend handler and re-enable it on resume. That is not possible with the fusb302 since the irq is a wakeup source (it must be a wakeup source so that we can do PD negotiation when a charger gets plugged in while suspended). Besides avoiding the ugly busy-wait, this also fixes the following errors which were logged by the busy-wait code when woken from suspend by plugging in a Type-C device: fusb302: i2c: pm suspend, retry 1 / 10 fusb302: i2c: pm suspend, retry 2 / 10 etc. Signed-off-by: Hans de Goede Reviewed-by: Guenter Roeck --- drivers/usb/typec/tcpm/fusb302.c | 109 +++++++++++++------------------ 1 file changed, 45 insertions(+), 64 deletions(-) diff --git a/drivers/usb/typec/tcpm/fusb302.c b/drivers/usb/typec/tcpm/fusb302.c index 23f773d07514..6cdc38b8da74 100644 --- a/drivers/usb/typec/tcpm/fusb302.c +++ b/drivers/usb/typec/tcpm/fusb302.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -78,6 +79,10 @@ struct fusb302_chip { struct regulator *vbus; + spinlock_t irq_lock; + struct work_struct irq_work; + bool irq_suspended; + bool irq_while_suspended; int gpio_int_n; int gpio_int_n_irq; struct extcon_dev *extcon; @@ -85,9 +90,6 @@ struct fusb302_chip { struct workqueue_struct *wq; struct delayed_work bc_lvl_handler; - atomic_t pm_suspend; - atomic_t i2c_busy; - /* lock for sharing chip states */ struct mutex lock; @@ -233,43 +235,15 @@ static void fusb302_debugfs_exit(const struct fusb302_chip *chip) { } #endif -#define FUSB302_RESUME_RETRY 10 -#define FUSB302_RESUME_RETRY_SLEEP 50 - -static bool fusb302_is_suspended(struct fusb302_chip *chip) -{ - int retry_cnt; - - for (retry_cnt = 0; retry_cnt < FUSB302_RESUME_RETRY; retry_cnt++) { - if (atomic_read(&chip->pm_suspend)) { - dev_err(chip->dev, "i2c: pm suspend, retry %d/%d\n", - retry_cnt + 1, FUSB302_RESUME_RETRY); - msleep(FUSB302_RESUME_RETRY_SLEEP); - } else { - return false; - } - } - - return true; -} - static int fusb302_i2c_write(struct fusb302_chip *chip, u8 address, u8 data) { int ret = 0; - atomic_set(&chip->i2c_busy, 1); - - if (fusb302_is_suspended(chip)) { - atomic_set(&chip->i2c_busy, 0); - return -ETIMEDOUT; - } - ret = i2c_smbus_write_byte_data(chip->i2c_client, address, data); if (ret < 0) fusb302_log(chip, "cannot write 0x%02x to 0x%02x, ret=%d", data, address, ret); - atomic_set(&chip->i2c_busy, 0); return ret; } @@ -281,19 +255,12 @@ static int fusb302_i2c_block_write(struct fusb302_chip *chip, u8 address, if (length <= 0) return ret; - atomic_set(&chip->i2c_busy, 1); - - if (fusb302_is_suspended(chip)) { - atomic_set(&chip->i2c_busy, 0); - return -ETIMEDOUT; - } ret = i2c_smbus_write_i2c_block_data(chip->i2c_client, address, length, data); if (ret < 0) fusb302_log(chip, "cannot block write 0x%02x, len=%d, ret=%d", address, length, ret); - atomic_set(&chip->i2c_busy, 0); return ret; } @@ -303,18 +270,10 @@ static int fusb302_i2c_read(struct fusb302_chip *chip, { int ret = 0; - atomic_set(&chip->i2c_busy, 1); - - if (fusb302_is_suspended(chip)) { - atomic_set(&chip->i2c_busy, 0); - return -ETIMEDOUT; - } - ret = i2c_smbus_read_byte_data(chip->i2c_client, address); *data = (u8)ret; if (ret < 0) fusb302_log(chip, "cannot read %02x, ret=%d", address, ret); - atomic_set(&chip->i2c_busy, 0); return ret; } @@ -326,12 +285,6 @@ static int fusb302_i2c_block_read(struct fusb302_chip *chip, u8 address, if (length <= 0) return ret; - atomic_set(&chip->i2c_busy, 1); - - if (fusb302_is_suspended(chip)) { - atomic_set(&chip->i2c_busy, 0); - return -ETIMEDOUT; - } ret = i2c_smbus_read_i2c_block_data(chip->i2c_client, address, length, data); @@ -347,8 +300,6 @@ static int fusb302_i2c_block_read(struct fusb302_chip *chip, u8 address, } done: - atomic_set(&chip->i2c_busy, 0); - return ret; } @@ -1485,6 +1436,25 @@ static int fusb302_pd_read_message(struct fusb302_chip *chip, static irqreturn_t fusb302_irq_intn(int irq, void *dev_id) { struct fusb302_chip *chip = dev_id; + unsigned long flags; + + /* Disable our level triggered IRQ until our irq_work has cleared it */ + disable_irq_nosync(chip->gpio_int_n_irq); + + spin_lock_irqsave(&chip->irq_lock, flags); + if (chip->irq_suspended) + chip->irq_while_suspended = true; + else + schedule_work(&chip->irq_work); + spin_unlock_irqrestore(&chip->irq_lock, flags); + + return IRQ_HANDLED; +} + +void fusb302_irq_work(struct work_struct *work) +{ + struct fusb302_chip *chip = container_of(work, struct fusb302_chip, + irq_work); int ret = 0; u8 interrupt; u8 interrupta; @@ -1613,8 +1583,7 @@ static irqreturn_t fusb302_irq_intn(int irq, void *dev_id) } done: mutex_unlock(&chip->lock); - - return IRQ_HANDLED; + enable_irq(chip->gpio_int_n_irq); } static int init_gpio(struct fusb302_chip *chip) @@ -1730,6 +1699,8 @@ static int fusb302_probe(struct i2c_client *client, if (!chip->wq) return -ENOMEM; + spin_lock_init(&chip->irq_lock); + INIT_WORK(&chip->irq_work, fusb302_irq_work); INIT_DELAYED_WORK(&chip->bc_lvl_handler, fusb302_bc_lvl_handler_work); init_tcpc_dev(&chip->tcpc_dev); @@ -1749,10 +1720,10 @@ static int fusb302_probe(struct i2c_client *client, goto destroy_workqueue; } - ret = devm_request_threaded_irq(chip->dev, chip->gpio_int_n_irq, - NULL, fusb302_irq_intn, - IRQF_ONESHOT | IRQF_TRIGGER_LOW, - "fsc_interrupt_int_n", chip); + ret = devm_request_irq(chip->dev, chip->gpio_int_n_irq, + fusb302_irq_intn, + IRQF_ONESHOT | IRQF_TRIGGER_LOW, + "fsc_interrupt_int_n", chip); if (ret < 0) { dev_err(dev, "cannot request IRQ for GPIO Int_N, ret=%d", ret); goto tcpm_unregister_port; @@ -1785,19 +1756,29 @@ static int fusb302_remove(struct i2c_client *client) static int fusb302_pm_suspend(struct device *dev) { struct fusb302_chip *chip = dev->driver_data; + unsigned long flags; - if (atomic_read(&chip->i2c_busy)) - return -EBUSY; - atomic_set(&chip->pm_suspend, 1); + spin_lock_irqsave(&chip->irq_lock, flags); + chip->irq_suspended = true; + spin_unlock_irqrestore(&chip->irq_lock, flags); + /* Make sure any pending irq_work is finished before the bus suspends */ + flush_work(&chip->irq_work); return 0; } static int fusb302_pm_resume(struct device *dev) { struct fusb302_chip *chip = dev->driver_data; + unsigned long flags; - atomic_set(&chip->pm_suspend, 0); + spin_lock_irqsave(&chip->irq_lock, flags); + if (chip->irq_while_suspended) { + schedule_work(&chip->irq_work); + chip->irq_while_suspended = false; + } + chip->irq_suspended = false; + spin_unlock_irqrestore(&chip->irq_lock, flags); return 0; } From patchwork Thu Mar 7 16:36:07 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 10843363 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id A2DAB139A for ; Thu, 7 Mar 2019 16:36:26 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 90D8C2F528 for ; Thu, 7 Mar 2019 16:36:26 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 851A42F579; Thu, 7 Mar 2019 16:36:26 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 409632F528 for ; Thu, 7 Mar 2019 16:36:26 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726414AbfCGQgZ (ORCPT ); Thu, 7 Mar 2019 11:36:25 -0500 Received: from mx1.redhat.com ([209.132.183.28]:43706 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726346AbfCGQgY (ORCPT ); Thu, 7 Mar 2019 11:36:24 -0500 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id BD71D30EBE73; Thu, 7 Mar 2019 16:36:24 +0000 (UTC) Received: from shalem.localdomain.com (ovpn-116-59.ams2.redhat.com [10.36.116.59]) by smtp.corp.redhat.com (Postfix) with ESMTP id A643A60856; Thu, 7 Mar 2019 16:36:23 +0000 (UTC) From: Hans de Goede To: Greg Kroah-Hartman , Guenter Roeck , Heikki Krogerus Cc: Hans de Goede , linux-usb@vger.kernel.org Subject: [PATCH v2 8/8] usb: typec: fusb302: Add __printf attribute to fusb302_log function Date: Thu, 7 Mar 2019 17:36:07 +0100 Message-Id: <20190307163607.24016-9-hdegoede@redhat.com> In-Reply-To: <20190307163607.24016-1-hdegoede@redhat.com> References: <20190307163607.24016-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.46]); Thu, 07 Mar 2019 16:36:24 +0000 (UTC) Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Add __printf attribute to fusb302_log function, so that we get compiler warnings when specifying wrong vararg parameters. Signed-off-by: Hans de Goede Reviewed-by: Guenter Roeck --- drivers/usb/typec/tcpm/fusb302.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/typec/tcpm/fusb302.c b/drivers/usb/typec/tcpm/fusb302.c index 6cdc38b8da74..ad1538c31dc8 100644 --- a/drivers/usb/typec/tcpm/fusb302.c +++ b/drivers/usb/typec/tcpm/fusb302.c @@ -125,13 +125,13 @@ struct fusb302_chip { */ #ifdef CONFIG_DEBUG_FS - static bool fusb302_log_full(struct fusb302_chip *chip) { return chip->logbuffer_tail == (chip->logbuffer_head + 1) % LOG_BUFFER_ENTRIES; } +__printf(2, 0) static void _fusb302_log(struct fusb302_chip *chip, const char *fmt, va_list args) {