From patchwork Mon Mar 11 10:48:11 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: 10847275 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 2C64617EF for ; Mon, 11 Mar 2019 10:48:26 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 183C628EE3 for ; Mon, 11 Mar 2019 10:48:26 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 0C4F728F30; Mon, 11 Mar 2019 10:48: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 90CC028EE3 for ; Mon, 11 Mar 2019 10:48:25 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726997AbfCKKsY (ORCPT ); Mon, 11 Mar 2019 06:48:24 -0400 Received: from mx1.redhat.com ([209.132.183.28]:48462 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726074AbfCKKsY (ORCPT ); Mon, 11 Mar 2019 06:48:24 -0400 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id AA8B9308425A; Mon, 11 Mar 2019 10:48:23 +0000 (UTC) Received: from shalem.localdomain.com (ovpn-117-37.ams2.redhat.com [10.36.117.37]) by smtp.corp.redhat.com (Postfix) with ESMTP id 937185DA62; Mon, 11 Mar 2019 10:48:22 +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 v3 1/8] usb: typec: fusb302: Make fusb302_set_cc_polarity also set pull ups / downs Date: Mon, 11 Mar 2019 11:48:11 +0100 Message-Id: <20190311104818.30216-2-hdegoede@redhat.com> In-Reply-To: <20190311104818.30216-1-hdegoede@redhat.com> References: <20190311104818.30216-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.40]); Mon, 11 Mar 2019 10:48: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 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 the 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. Reviewed-by: Guenter Roeck Signed-off-by: Hans de Goede --- 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 45b8b75080cf..50ba978a46e4 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; } @@ -1232,38 +1230,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, @@ -1284,16 +1280,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); @@ -1360,16 +1350,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 Mon Mar 11 10:48:12 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: 10847277 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 9F14617EF for ; Mon, 11 Mar 2019 10:48:27 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 8BA9C28EE3 for ; Mon, 11 Mar 2019 10:48:27 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 7FD1F28F30; Mon, 11 Mar 2019 10:48:27 +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 04FA528EE3 for ; Mon, 11 Mar 2019 10:48:26 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727013AbfCKKs0 (ORCPT ); Mon, 11 Mar 2019 06:48:26 -0400 Received: from mx1.redhat.com ([209.132.183.28]:55280 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726074AbfCKKsZ (ORCPT ); Mon, 11 Mar 2019 06:48:25 -0400 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 1582381F31; Mon, 11 Mar 2019 10:48:25 +0000 (UTC) Received: from shalem.localdomain.com (ovpn-117-37.ams2.redhat.com [10.36.117.37]) by smtp.corp.redhat.com (Postfix) with ESMTP id EF8B55DAAF; Mon, 11 Mar 2019 10:48: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 v3 2/8] usb: typec: fusb302: Refactor / simplify tcpm_set_cc() Date: Mon, 11 Mar 2019 11:48:12 +0100 Message-Id: <20190311104818.30216-3-hdegoede@redhat.com> In-Reply-To: <20190311104818.30216-1-hdegoede@redhat.com> References: <20190311104818.30216-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.27]); Mon, 11 Mar 2019 10:48:25 +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. Reviewed-by: Guenter Roeck Signed-off-by: Hans de Goede --- 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 50ba978a46e4..605fbbb92e39 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 Mon Mar 11 10:48:13 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: 10847279 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 62BA317EF for ; Mon, 11 Mar 2019 10:48:28 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 4F10028EE3 for ; Mon, 11 Mar 2019 10:48:28 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 4307A28F30; Mon, 11 Mar 2019 10:48:28 +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 D9D1928EE3 for ; Mon, 11 Mar 2019 10:48:27 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727026AbfCKKs1 (ORCPT ); Mon, 11 Mar 2019 06:48:27 -0400 Received: from mx1.redhat.com ([209.132.183.28]:48262 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726074AbfCKKs0 (ORCPT ); Mon, 11 Mar 2019 06:48:26 -0400 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 72384C057F4A; Mon, 11 Mar 2019 10:48:26 +0000 (UTC) Received: from shalem.localdomain.com (ovpn-117-37.ams2.redhat.com [10.36.117.37]) by smtp.corp.redhat.com (Postfix) with ESMTP id 598645DA62; Mon, 11 Mar 2019 10:48:25 +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 v3 3/8] usb: typec: fusb302: Fold fusb302_set_cc_pull into tcpm_set_cc Date: Mon, 11 Mar 2019 11:48:13 +0100 Message-Id: <20190311104818.30216-4-hdegoede@redhat.com> In-Reply-To: <20190311104818.30216-1-hdegoede@redhat.com> References: <20190311104818.30216-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.32]); Mon, 11 Mar 2019 10:48:26 +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. Reviewed-by: Guenter Roeck Signed-off-by: Hans de Goede --- 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 605fbbb92e39..c947d18cdc0f 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 Mon Mar 11 10:48:14 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: 10847281 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 5EEE81823 for ; Mon, 11 Mar 2019 10:48:29 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 4B33328EE3 for ; Mon, 11 Mar 2019 10:48:29 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 3F90628F30; Mon, 11 Mar 2019 10:48:29 +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 D0BFC28EE3 for ; Mon, 11 Mar 2019 10:48:28 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727107AbfCKKs2 (ORCPT ); Mon, 11 Mar 2019 06:48:28 -0400 Received: from mx1.redhat.com ([209.132.183.28]:48504 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726074AbfCKKs1 (ORCPT ); Mon, 11 Mar 2019 06:48:27 -0400 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id C98683084029; Mon, 11 Mar 2019 10:48:27 +0000 (UTC) Received: from shalem.localdomain.com (ovpn-117-37.ams2.redhat.com [10.36.117.37]) by smtp.corp.redhat.com (Postfix) with ESMTP id B3B8E5DD6B; Mon, 11 Mar 2019 10:48:26 +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 v3 4/8] usb: typec: fusb302: Check vconn is off when we start toggling Date: Mon, 11 Mar 2019 11:48:14 +0100 Message-Id: <20190311104818.30216-5-hdegoede@redhat.com> In-Reply-To: <20190311104818.30216-1-hdegoede@redhat.com> References: <20190311104818.30216-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.40]); Mon, 11 Mar 2019 10:48:27 +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 to catch any cases where vconn is not off for some reason. Signed-off-by: Hans de Goede Reviewed-by: Guenter Roeck --- Changes in v3: -Use WARN with a message describing the problem, instead of WARN_ON --- 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 c947d18cdc0f..a1256855eaa0 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(chip->vconn_on, "Vconn is on during toggle start"); /* unmask TOGDONE interrupt */ ret = fusb302_i2c_clear_bits(chip, FUSB_REG_MASKA, FUSB_REG_MASKA_TOGDONE); From patchwork Mon Mar 11 10:48:15 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: 10847283 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 8A3941823 for ; Mon, 11 Mar 2019 10:48:31 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 74FAB28EE3 for ; Mon, 11 Mar 2019 10:48:31 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 6988728F30; Mon, 11 Mar 2019 10:48:31 +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 A894828EE3 for ; Mon, 11 Mar 2019 10:48:30 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727109AbfCKKsa (ORCPT ); Mon, 11 Mar 2019 06:48:30 -0400 Received: from mx1.redhat.com ([209.132.183.28]:48522 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726074AbfCKKs3 (ORCPT ); Mon, 11 Mar 2019 06:48:29 -0400 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 315DE3084293; Mon, 11 Mar 2019 10:48:29 +0000 (UTC) Received: from shalem.localdomain.com (ovpn-117-37.ams2.redhat.com [10.36.117.37]) by smtp.corp.redhat.com (Postfix) with ESMTP id 1A9A75DA62; Mon, 11 Mar 2019 10:48:27 +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 v3 5/8] usb: typec: fusb302: Fix fusb302_handle_togdone_src Ra handling Date: Mon, 11 Mar 2019 11:48:15 +0100 Message-Id: <20190311104818.30216-6-hdegoede@redhat.com> In-Reply-To: <20190311104818.30216-1-hdegoede@redhat.com> References: <20190311104818.30216-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.40]); Mon, 11 Mar 2019 10:48:29 +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 Reviewed-by: Guenter Roeck --- Changes in v3 -Keep the delays for measuring Rd / Ra the same as before instead of multiplying them by a factor 100 --- 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 a1256855eaa0..a4387ce5ac85 100644 --- a/drivers/usb/typec/tcpm/fusb302.c +++ b/drivers/usb/typec/tcpm/fusb302.c @@ -1255,6 +1255,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(50, 100); + 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(50, 100); + 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) { @@ -1265,71 +1321,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) @@ -1515,10 +1562,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 Mon Mar 11 10:48:16 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: 10847285 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 1843717EF for ; Mon, 11 Mar 2019 10:48:32 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 04AAE28EE3 for ; Mon, 11 Mar 2019 10:48:32 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id ED50728F30; Mon, 11 Mar 2019 10:48:31 +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 97B6228EE3 for ; Mon, 11 Mar 2019 10:48:31 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727154AbfCKKsb (ORCPT ); Mon, 11 Mar 2019 06:48:31 -0400 Received: from mx1.redhat.com ([209.132.183.28]:51650 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726074AbfCKKsa (ORCPT ); Mon, 11 Mar 2019 06:48:30 -0400 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 8D11A59468; Mon, 11 Mar 2019 10:48:30 +0000 (UTC) Received: from shalem.localdomain.com (ovpn-117-37.ams2.redhat.com [10.36.117.37]) by smtp.corp.redhat.com (Postfix) with ESMTP id 7453E5DD6B; Mon, 11 Mar 2019 10:48:29 +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 v3 6/8] usb: typec: fusb302: 2 small misc. fixes Date: Mon, 11 Mar 2019 11:48:16 +0100 Message-Id: <20190311104818.30216-7-hdegoede@redhat.com> In-Reply-To: <20190311104818.30216-1-hdegoede@redhat.com> References: <20190311104818.30216-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.39]); Mon, 11 Mar 2019 10:48:30 +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. Reviewed-by: Guenter Roeck Signed-off-by: Hans de Goede --- 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 a4387ce5ac85..4bb10564082a 100644 --- a/drivers/usb/typec/tcpm/fusb302.c +++ b/drivers/usb/typec/tcpm/fusb302.c @@ -1386,7 +1386,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; @@ -1561,7 +1561,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 Mon Mar 11 10:48:17 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: 10847287 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 26EDB1823 for ; Mon, 11 Mar 2019 10:48:34 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 1371228F17 for ; Mon, 11 Mar 2019 10:48:34 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 082CA28F3C; Mon, 11 Mar 2019 10:48:34 +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 52A6F28F17 for ; Mon, 11 Mar 2019 10:48:33 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727167AbfCKKsc (ORCPT ); Mon, 11 Mar 2019 06:48:32 -0400 Received: from mx1.redhat.com ([209.132.183.28]:50238 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726074AbfCKKsc (ORCPT ); Mon, 11 Mar 2019 06:48:32 -0400 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id E7025368B1; Mon, 11 Mar 2019 10:48:31 +0000 (UTC) Received: from shalem.localdomain.com (ovpn-117-37.ams2.redhat.com [10.36.117.37]) by smtp.corp.redhat.com (Postfix) with ESMTP id CFE105DD6B; Mon, 11 Mar 2019 10:48:30 +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 v3 7/8] usb: typec: fusb302: Improve suspend/resume handling Date: Mon, 11 Mar 2019 11:48:17 +0100 Message-Id: <20190311104818.30216-8-hdegoede@redhat.com> In-Reply-To: <20190311104818.30216-1-hdegoede@redhat.com> References: <20190311104818.30216-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.30]); Mon, 11 Mar 2019 10:48:32 +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-enabling 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. This commit also changes the devm_request_irq to a regular request_irq + free_irq, so that the work can be properly stopped. While at it also properly disable the wake setting on the irq and also properly stop the delayed work for bcl handling. Reviewed-by: Guenter Roeck Signed-off-by: Hans de Goede --- Changes in v3: -Change devm_request_irq to a regular request_irq free_irq, so that the work can be properly stopped Changes in v2: -Use a work_queue item which gets delayed during suspend, rather then disabling the interrupts entirely during suspend --- drivers/usb/typec/tcpm/fusb302.c | 112 +++++++++++++------------------ 1 file changed, 48 insertions(+), 64 deletions(-) diff --git a/drivers/usb/typec/tcpm/fusb302.c b/drivers/usb/typec/tcpm/fusb302.c index 4bb10564082a..f3b66dc71c33 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; } @@ -1491,6 +1442,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; @@ -1619,8 +1589,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) @@ -1736,6 +1705,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); @@ -1755,10 +1726,9 @@ 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 = request_irq(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; @@ -1781,6 +1751,10 @@ static int fusb302_remove(struct i2c_client *client) { struct fusb302_chip *chip = i2c_get_clientdata(client); + disable_irq_wake(chip->gpio_int_n_irq); + free_irq(chip->gpio_int_n_irq, chip); + cancel_work_sync(&chip->irq_work); + cancel_delayed_work_sync(&chip->bc_lvl_handler); tcpm_unregister_port(chip->tcpm_port); destroy_workqueue(chip->wq); fusb302_debugfs_exit(chip); @@ -1791,19 +1765,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 Mon Mar 11 10:48:18 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: 10847289 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 9927A1823 for ; Mon, 11 Mar 2019 10:48:36 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 86BF228F17 for ; Mon, 11 Mar 2019 10:48:36 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 7B65928F3C; Mon, 11 Mar 2019 10:48:36 +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 3386F28F17 for ; Mon, 11 Mar 2019 10:48:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727182AbfCKKsf (ORCPT ); Mon, 11 Mar 2019 06:48:35 -0400 Received: from mx1.redhat.com ([209.132.183.28]:55346 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726074AbfCKKsf (ORCPT ); Mon, 11 Mar 2019 06:48:35 -0400 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 73E1283F45; Mon, 11 Mar 2019 10:48:35 +0000 (UTC) Received: from shalem.localdomain.com (ovpn-117-37.ams2.redhat.com [10.36.117.37]) by smtp.corp.redhat.com (Postfix) with ESMTP id 362495DA62; Mon, 11 Mar 2019 10:48:32 +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 v3 8/8] usb: typec: fusb302: Add __printf attribute to fusb302_log function Date: Mon, 11 Mar 2019 11:48:18 +0100 Message-Id: <20190311104818.30216-9-hdegoede@redhat.com> In-Reply-To: <20190311104818.30216-1-hdegoede@redhat.com> References: <20190311104818.30216-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.27]); Mon, 11 Mar 2019 10:48:35 +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. Reviewed-by: Guenter Roeck Signed-off-by: Hans de Goede --- 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 f3b66dc71c33..6ea6199caafa 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) {