From patchwork Tue Jan 10 05:54:39 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rajendra Nayak X-Patchwork-Id: 9506399 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 549F760231 for ; Tue, 10 Jan 2017 05:55:01 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 43A8F28487 for ; Tue, 10 Jan 2017 05:55:01 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 341622845E; Tue, 10 Jan 2017 05:55:01 +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=-6.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,T_DKIM_INVALID 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 9F5392845E for ; Tue, 10 Jan 2017 05:55:00 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753313AbdAJFzA (ORCPT ); Tue, 10 Jan 2017 00:55:00 -0500 Received: from smtp.codeaurora.org ([198.145.29.96]:53160 "EHLO smtp.codeaurora.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750879AbdAJFy5 (ORCPT ); Tue, 10 Jan 2017 00:54:57 -0500 Received: by smtp.codeaurora.org (Postfix, from userid 1000) id CE210613D3; Tue, 10 Jan 2017 05:54:56 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1484027696; bh=cBXV9z9G/OmFG3l+nBhZpyWNZsuDup7u/ERro2jS2lU=; h=From:To:Cc:Subject:Date:From; b=WVZCVBcOPqcgQ4skgNqt4kLQGszxJ4RnEb6A7sZv9k8FXHVnGt7z5QgIrcMi7e2wb 9V/3e8wcI1ZXb8YNukshgkUYziKIiDPCxZF3jIAIxixMvP3nPa+K1c/0NAPKJY6oW5 6jeRvpL2Y+HsSB8IPzHDZnBRZzPMspqg79t/nwMw= Received: from blr-ubuntu-34.ap.qualcomm.com (unknown [202.46.23.61]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) (Authenticated sender: rnayak@smtp.codeaurora.org) by smtp.codeaurora.org (Postfix) with ESMTPSA id A67C0613AB; Tue, 10 Jan 2017 05:54:52 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1484027696; bh=cBXV9z9G/OmFG3l+nBhZpyWNZsuDup7u/ERro2jS2lU=; h=From:To:Cc:Subject:Date:From; b=WVZCVBcOPqcgQ4skgNqt4kLQGszxJ4RnEb6A7sZv9k8FXHVnGt7z5QgIrcMi7e2wb 9V/3e8wcI1ZXb8YNukshgkUYziKIiDPCxZF3jIAIxixMvP3nPa+K1c/0NAPKJY6oW5 6jeRvpL2Y+HsSB8IPzHDZnBRZzPMspqg79t/nwMw= DMARC-Filter: OpenDMARC Filter v1.3.1 smtp.codeaurora.org A67C0613AB Authentication-Results: pdx-caf-mail.web.codeaurora.org; dmarc=none header.from=codeaurora.org Authentication-Results: pdx-caf-mail.web.codeaurora.org; spf=pass smtp.mailfrom=rnayak@codeaurora.org From: Rajendra Nayak To: sboyd@codeaurora.org, mturquette@baylibre.com Cc: linux-clk@vger.kernel.org, linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org, stanimir.varbanov@linaro.org, sricharan@codeaurora.org, Rajendra Nayak Subject: [PATCH] clk: qcom: gdsc: Fix handling of hw control enable/disable Date: Tue, 10 Jan 2017 11:24:39 +0530 Message-Id: <1484027679-18397-1-git-send-email-rnayak@codeaurora.org> X-Mailer: git-send-email 1.8.2.1 Sender: linux-clk-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-clk@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Once a gdsc is brought in and out of HW control, there is a power down and up cycle which can take upto 1us. Polling on the gdsc status immediately after the hw control enable/disable can mislead software/firmware to belive the gdsc is already either on or off, while its yet to complete the power cycle. To avoid this add a 1us delay post a enable/disable of HW control mode. Also after the HW control mode is disabled, poll on the status to check gdsc status reflects its 'on' before force disabling it in software. Reported-by: Stanimir Varbanov Signed-off-by: Rajendra Nayak --- Stan, If there was a specific issue you saw with venus because of the missing delay and poll, can you check if this fixes any of that. drivers/clk/qcom/gdsc.c | 58 ++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 45 insertions(+), 13 deletions(-) diff --git a/drivers/clk/qcom/gdsc.c b/drivers/clk/qcom/gdsc.c index 288186c..6fbd6df 100644 --- a/drivers/clk/qcom/gdsc.c +++ b/drivers/clk/qcom/gdsc.c @@ -63,11 +63,26 @@ static int gdsc_hwctrl(struct gdsc *sc, bool en) return regmap_update_bits(sc->regmap, sc->gdscr, HW_CONTROL_MASK, val); } +static int gdsc_poll_status(struct gdsc *sc, unsigned int reg, bool val) +{ + ktime_t start; + + start = ktime_get(); + do { + if (gdsc_is_enabled(sc, reg) == val) + return 0; + } while (ktime_us_delta(ktime_get(), start) < TIMEOUT_US); + + if (gdsc_is_enabled(sc, reg) == val) + return 0; + + return -ETIMEDOUT; +} + static int gdsc_toggle_logic(struct gdsc *sc, bool en) { int ret; u32 val = en ? 0 : SW_COLLAPSE_MASK; - ktime_t start; unsigned int status_reg = sc->gdscr; ret = regmap_update_bits(sc->regmap, sc->gdscr, SW_COLLAPSE_MASK, val); @@ -100,16 +115,7 @@ static int gdsc_toggle_logic(struct gdsc *sc, bool en) udelay(1); } - start = ktime_get(); - do { - if (gdsc_is_enabled(sc, status_reg) == en) - return 0; - } while (ktime_us_delta(ktime_get(), start) < TIMEOUT_US); - - if (gdsc_is_enabled(sc, status_reg) == en) - return 0; - - return -ETIMEDOUT; + return gdsc_poll_status(sc, status_reg, en); } static inline int gdsc_deassert_reset(struct gdsc *sc) @@ -188,8 +194,19 @@ static int gdsc_enable(struct generic_pm_domain *domain) udelay(1); /* Turn on HW trigger mode if supported */ - if (sc->flags & HW_CTRL) - return gdsc_hwctrl(sc, true); + if (sc->flags & HW_CTRL) { + ret = gdsc_hwctrl(sc, true); + /* + * Wait for the GDSC to go through a power down and + * up cycle. In case a firmware ends up polling status + * bits for the gdsc, it might read an 'on' status before + * the GDSC can finish the power cycle. + * We wait 1us before returning to ensure the firmware + * can't immediately poll the status bits. + */ + mb(); + udelay(1); + } return 0; } @@ -204,9 +221,24 @@ static int gdsc_disable(struct generic_pm_domain *domain) /* Turn off HW trigger mode if supported */ if (sc->flags & HW_CTRL) { + unsigned int reg; + ret = gdsc_hwctrl(sc, false); if (ret < 0) return ret; + /* + * Wait for the GDSC to go through a power down and + * up cycle. In case we end up polling status + * bits for the gdsc before the power cycle is completed + * it might read an 'on' status wrongly. + */ + mb(); + udelay(1); + + reg = sc->gds_hw_ctrl ? sc->gds_hw_ctrl : sc->gdscr; + ret = gdsc_poll_status(sc, reg, 0); + if (ret) + return ret; } if (sc->pwrsts & PWRSTS_OFF)