From patchwork Wed Jan 27 09:54:29 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Raja Mani X-Patchwork-Id: 8131911 Return-Path: X-Original-To: patchwork-ath10k@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 413439F1C0 for ; Wed, 27 Jan 2016 09:58:53 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 3BC6120270 for ; Wed, 27 Jan 2016 09:58:52 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 2E02C201F4 for ; Wed, 27 Jan 2016 09:58:51 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1aOMs9-0004gN-UB; Wed, 27 Jan 2016 09:58:45 +0000 Received: from sabertooth01.qualcomm.com ([65.197.215.72]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1aOMs6-0004Ox-F0 for ath10k@lists.infradead.org; Wed, 27 Jan 2016 09:58:44 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=qti.qualcomm.com; i=@qti.qualcomm.com; q=dns/txt; s=qcdkim; t=1453888722; x=1485424722; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version; bh=hy9qG5jxeY+Oi7KknvLtYrLFOdNHVCnj4YkKTNXbo5c=; b=qzNQsU1rVx5z2DxwTeVK5NOwmwy8THaRDzQ4ju/n+mJiFnGwNg1BxG5D V1hwB4fu2zgjYqUMFHFwlqOySUyRLoeHx0uoKzgfFy1G6W/g+zKYWN2JQ JyTZG5oftfWm9q8F+2CA8oyaHJtLb6l/i6TVLGxMH2x52Sf4S2VJWmDTD Y=; X-IronPort-AV: E=Sophos;i="5.22,354,1449561600"; d="scan'208";a="106397882" Received: from ironmsg04-r-new.qualcomm.com (HELO Ironmsg04-R.qualcomm.com) ([10.53.140.108]) by sabertooth01.qualcomm.com with ESMTP/TLS/DHE-RSA-AES256-SHA; 27 Jan 2016 01:58:21 -0800 X-IronPort-AV: E=McAfee;i="5700,7163,8056"; a="1127798704" Received: from nasanexm02a.na.qualcomm.com ([10.85.0.41]) by Ironmsg04-R.qualcomm.com with ESMTP/TLS/RC4-SHA; 27 Jan 2016 01:58:21 -0800 Received: from aphydexm01a.ap.qualcomm.com (10.252.127.10) by nasanexm02a.na.qualcomm.com (10.85.0.41) with Microsoft SMTP Server (TLS) id 15.0.1130.7; Wed, 27 Jan 2016 01:58:20 -0800 Received: from 10.80.81.91 (10.80.80.8) by aphydexm01a.ap.qualcomm.com (10.252.127.10) with Microsoft SMTP Server (TLS) id 15.0.1130.7; Wed, 27 Jan 2016 15:28:11 +0530 Received: by 10.80.81.91 (sSMTP sendmail emulation); Wed, 27 Jan 2016 15:28:00 +0530 From: Raja Mani To: Subject: [PATCH 08/12] ath10k: add reset ctrl related functions in ahb Date: Wed, 27 Jan 2016 15:24:29 +0530 Message-ID: <1453888473-2879-9-git-send-email-rmani@qti.qualcomm.com> X-Mailer: git-send-email 1.8.1.2 In-Reply-To: <1453888473-2879-1-git-send-email-rmani@qti.qualcomm.com> References: <1453888473-2879-1-git-send-email-rmani@qti.qualcomm.com> MIME-Version: 1.0 X-Originating-IP: [10.80.80.8] X-ClientProxiedBy: NASANEXM01F.na.qualcomm.com (10.85.0.32) To aphydexm01a.ap.qualcomm.com (10.252.127.10) X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20160127_015842_694888_DD6F19B7 X-CRM114-Status: GOOD ( 13.59 ) X-Spam-Score: -5.4 (-----) X-BeenThere: ath10k@lists.infradead.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: linux-wireless@vger.kernel.org, Raja Mani Sender: "ath10k" Errors-To: ath10k-bounces+patchwork-ath10k=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-4.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_MED,RP_MATCHES_RCVD,T_DKIM_INVALID,UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP To perform reset on qca4019 wifi, multiple reset lines needs to be toggled in a sequence with help of reset controller support in the kernel. This patch adds functions to reset control init/deinit and release reset. Signed-off-by: Raja Mani --- drivers/net/wireless/ath/ath10k/Kconfig | 2 +- drivers/net/wireless/ath/ath10k/ahb.c | 138 ++++++++++++++++++++++++++++++++ drivers/net/wireless/ath/ath10k/ahb.h | 6 ++ 3 files changed, 145 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath10k/Kconfig b/drivers/net/wireless/ath/ath10k/Kconfig index d7f207a..db1ca62 100644 --- a/drivers/net/wireless/ath/ath10k/Kconfig +++ b/drivers/net/wireless/ath/ath10k/Kconfig @@ -17,7 +17,7 @@ config ATH10K_PCI config ATH10K_AHB bool "Atheros ath10k AHB support" - depends on ATH10K_PCI && OF + depends on ATH10K_PCI && OF && RESET_CONTROLLER ---help--- This module adds support for AHB bus diff --git a/drivers/net/wireless/ath/ath10k/ahb.c b/drivers/net/wireless/ath/ath10k/ahb.c index 11185c0..d1f1972 100644 --- a/drivers/net/wireless/ath/ath10k/ahb.c +++ b/drivers/net/wireless/ath/ath10k/ahb.c @@ -16,6 +16,7 @@ */ #include #include +#include #include "core.h" #include "debug.h" #include "pci.h" @@ -207,6 +208,143 @@ static void ath10k_ahb_clock_disable(struct ath10k *ar) clk_disable_unprepare(ar_ahb->rtc_clk); } +static int ath10k_ahb_rst_ctrl_init(struct ath10k *ar) +{ + struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar); + struct device *dev; + int ret; + + dev = &ar_ahb->pdev->dev; + + ar_ahb->core_cold_rst = reset_control_get(dev, "wifi_core_cold"); + if (IS_ERR_OR_NULL(ar_ahb->core_cold_rst)) { + ath10k_err(ar, "failed to get core cold rst ctrl: %ld\n", + PTR_ERR(ar_ahb->core_cold_rst)); + ret = ar_ahb->core_cold_rst ? + PTR_ERR(ar_ahb->core_cold_rst) : -ENODEV; + goto out; + } + + ar_ahb->radio_cold_rst = reset_control_get(dev, "wifi_radio_cold"); + if (IS_ERR_OR_NULL(ar_ahb->radio_cold_rst)) { + ath10k_err(ar, "failed to get radio cold rst ctrl: %ld\n", + PTR_ERR(ar_ahb->radio_cold_rst)); + ret = ar_ahb->radio_cold_rst ? + PTR_ERR(ar_ahb->radio_cold_rst) : -ENODEV; + goto err_core_cold_rst_put; + } + + ar_ahb->radio_warm_rst = reset_control_get(dev, "wifi_radio_warm"); + if (IS_ERR_OR_NULL(ar_ahb->radio_warm_rst)) { + ath10k_err(ar, "failed to get radio warm rst ctrl: %ld\n", + PTR_ERR(ar_ahb->radio_warm_rst)); + ret = ar_ahb->radio_warm_rst ? + PTR_ERR(ar_ahb->radio_warm_rst) : -ENODEV; + goto err_radio_cold_rst_put; + } + + ar_ahb->radio_srif_rst = reset_control_get(dev, "wifi_radio_srif"); + if (IS_ERR_OR_NULL(ar_ahb->radio_srif_rst)) { + ath10k_err(ar, "failed to get radio srif rst ctrl: %ld\n", + PTR_ERR(ar_ahb->radio_srif_rst)); + ret = ar_ahb->radio_srif_rst ? + PTR_ERR(ar_ahb->radio_srif_rst) : -ENODEV; + goto err_radio_warm_rst_put; + } + + ar_ahb->cpu_init_rst = reset_control_get(dev, "wifi_cpu_init"); + if (IS_ERR_OR_NULL(ar_ahb->cpu_init_rst)) { + ath10k_err(ar, "failed to get cpu init rst ctrl: %ld\n", + PTR_ERR(ar_ahb->cpu_init_rst)); + ret = ar_ahb->cpu_init_rst ? + PTR_ERR(ar_ahb->cpu_init_rst) : -ENODEV; + goto err_radio_srif_rst_put; + } + + return 0; + +err_radio_srif_rst_put: + reset_control_put(ar_ahb->radio_srif_rst); + +err_radio_warm_rst_put: + reset_control_put(ar_ahb->radio_warm_rst); + +err_radio_cold_rst_put: + reset_control_put(ar_ahb->radio_cold_rst); + +err_core_cold_rst_put: + reset_control_put(ar_ahb->core_cold_rst); + +out: + return ret; +} + +static void ath10k_ahb_rst_ctrl_deinit(struct ath10k *ar) +{ + struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar); + + if (!IS_ERR_OR_NULL(ar_ahb->core_cold_rst)) + reset_control_put(ar_ahb->core_cold_rst); + + if (!IS_ERR_OR_NULL(ar_ahb->radio_cold_rst)) + reset_control_put(ar_ahb->radio_cold_rst); + + if (!IS_ERR_OR_NULL(ar_ahb->radio_warm_rst)) + reset_control_put(ar_ahb->radio_warm_rst); + + if (!IS_ERR_OR_NULL(ar_ahb->radio_srif_rst)) + reset_control_put(ar_ahb->radio_srif_rst); + + if (!IS_ERR_OR_NULL(ar_ahb->cpu_init_rst)) + reset_control_put(ar_ahb->cpu_init_rst); + + ar_ahb->core_cold_rst = NULL; + ar_ahb->radio_cold_rst = NULL; + ar_ahb->radio_warm_rst = NULL; + ar_ahb->radio_srif_rst = NULL; + ar_ahb->cpu_init_rst = NULL; +} + +static int ath10k_ahb_release_reset(struct ath10k *ar) +{ + struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar); + int ret; + + if (IS_ERR_OR_NULL(ar_ahb->radio_cold_rst) || + IS_ERR_OR_NULL(ar_ahb->radio_warm_rst) || + IS_ERR_OR_NULL(ar_ahb->radio_srif_rst) || + IS_ERR_OR_NULL(ar_ahb->cpu_init_rst)) { + ath10k_err(ar, "rst ctrl(s) is/are not initialized\n"); + return -EINVAL; + } + + ret = reset_control_deassert(ar_ahb->radio_cold_rst); + if (ret) { + ath10k_err(ar, "failed to deassert radio cold rst: %d\n", ret); + return ret; + } + + ret = reset_control_deassert(ar_ahb->radio_warm_rst); + if (ret) { + ath10k_err(ar, "failed to deassert radio warm rst: %d\n", ret); + return ret; + } + + ret = reset_control_deassert(ar_ahb->radio_srif_rst); + if (ret) { + ath10k_err(ar, "failed to deassert radio srif rst: %d\n", ret); + return ret; + } + + ret = reset_control_deassert(ar_ahb->cpu_init_rst); + if (ret) { + ath10k_err(ar, "failed to deassert cpu init rst: %d\n", ret); + return ret; + } + + return 0; +} + static int ath10k_ahb_probe(struct platform_device *pdev) { return 0; diff --git a/drivers/net/wireless/ath/ath10k/ahb.h b/drivers/net/wireless/ath/ath10k/ahb.h index 753b433..2904b7b 100644 --- a/drivers/net/wireless/ath/ath10k/ahb.h +++ b/drivers/net/wireless/ath/ath10k/ahb.h @@ -29,6 +29,12 @@ struct ath10k_ahb { struct clk *cmd_clk; struct clk *ref_clk; struct clk *rtc_clk; + + struct reset_control *core_cold_rst; + struct reset_control *radio_cold_rst; + struct reset_control *radio_warm_rst; + struct reset_control *radio_srif_rst; + struct reset_control *cpu_init_rst; }; #ifdef CONFIG_ATH10K_AHB