From patchwork Mon Nov 23 00:15:46 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steve deRosier X-Patchwork-Id: 7677181 X-Patchwork-Delegate: kvalo@adurom.com Return-Path: X-Original-To: patchwork-linux-wireless@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 AD8EE9F1D3 for ; Mon, 23 Nov 2015 00:17:52 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id CA91B206EA for ; Mon, 23 Nov 2015 00:17:51 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id D5107206E9 for ; Mon, 23 Nov 2015 00:17:50 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752879AbbKWARq (ORCPT ); Sun, 22 Nov 2015 19:17:46 -0500 Received: from mail-qg0-f52.google.com ([209.85.192.52]:33061 "EHLO mail-qg0-f52.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752840AbbKWARo (ORCPT ); Sun, 22 Nov 2015 19:17:44 -0500 Received: by qgea14 with SMTP id a14so105744606qge.0 for ; Sun, 22 Nov 2015 16:17:43 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=aEFVTvVG++s9oWAogGKPllTFkkdGmai3fXUJnqkxTAc=; b=mfC05PJBDEoOf9N9x/WVbeB8GzDKpGEKnsumkChT/jTVULkQWsoLH77SjX/9wn+aKw ZPNUpt3EnbdWs/qK2Yk6o/HYgizz6i5ormlb4lrwdcqZNrSUYOrQ4lmQGwDHz1ayH+Ll zU+gw6JhKHbmDNVJav5MfODHSGH9DsbY5EohTIbZKJL6dBjpIlo1Sg3VIDqZ28seQ6u2 6qeDQSTTq32ySFvgt5u6Gl94VbZW//21pdt1uSFdZA8Q/iPWaQQ+fq1rhz7GA1X/4zG/ Ga74n1RtYjpTs+VO16z4UM++icci38HmkbcoePn3u+LHrmnjzndYIw5exztiPtmxmgGT XlfQ== X-Received: by 10.140.32.4 with SMTP id g4mr24359660qgg.79.1448237863400; Sun, 22 Nov 2015 16:17:43 -0800 (PST) Received: from elmer.corp.lairdtech.com (c-50-184-185-234.hsd1.ca.comcast.net. [50.184.185.234]) by smtp.gmail.com with ESMTPSA id q133sm2376767qhq.20.2015.11.22.16.17.42 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Sun, 22 Nov 2015 16:17:43 -0800 (PST) From: Steve deRosier X-Google-Original-From: Steve deRosier To: Kalle Valo Cc: ath6kl@lists.infradead.org, linux-wireless@vger.kernel.org, Julian Calaby , Steve deRosier Subject: [PATCH v3 1/2] ath6kl_sdio: Add reset gpio module parameter for CHIP_PWD_L pin Date: Sun, 22 Nov 2015 16:15:46 -0800 Message-Id: <1448237747-20037-2-git-send-email-steve.derosier@lairdtech.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1448237747-20037-1-git-send-email-steve.derosier@lairdtech.com> References: <1448237747-20037-1-git-send-email-steve.derosier@lairdtech.com> Sender: linux-wireless-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org X-Spam-Status: No, score=-7.4 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, T_DKIM_INVALID, UNPARSEABLE_RELAY autolearn=ham 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 Many ath6k chips have a reset pin, usually labeled CHIP_PWD_L. This pin can be pulled low by the host processor to hold the wifi chip in reset. By holding the chip in reset, the lowest power consumption available can be achieved. This adds a module parameter so the ath6kl_sdio driver can control the CHIP_PWD_L pin if the implementer so desires. This code is only available if GPIOLIB is configured. Signed-off-by: Steve deRosier --- drivers/net/wireless/ath/ath6kl/sdio.c | 70 +++++++++++++++++++++++++++++++++- 1 file changed, 69 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath6kl/sdio.c b/drivers/net/wireless/ath/ath6kl/sdio.c index eab0ab9..d06aa41 100644 --- a/drivers/net/wireless/ath/ath6kl/sdio.c +++ b/drivers/net/wireless/ath/ath6kl/sdio.c @@ -23,6 +23,7 @@ #include #include #include +#include #include "hif.h" #include "hif-ops.h" #include "target.h" @@ -69,6 +70,20 @@ struct ath6kl_sdio { spinlock_t wr_async_lock; }; +/* Delay to avoid the mmc driver calling the probe on the prior notice of + * the chip, which we just killed. If this is missing, it results in a + * spurious warning: + * "ath6kl_sdio: probe of mmc0:0001:1 failed with error -110" + * + * Time chosen experimentally, with padding + */ +#define ATH6KL_MMC_PROBE_DELAY 150 +static unsigned int reset_pwd_gpio = ARCH_NR_GPIOS; +#ifdef CONFIG_GPIOLIB +module_param(reset_pwd_gpio, uint, 0644); +MODULE_PARM_DESC(reset_pwd_gpio, "WIFI CHIP_PWD reset pin GPIO"); +#endif + #define CMD53_ARG_READ 0 #define CMD53_ARG_WRITE 1 #define CMD53_ARG_BLOCK_BASIS 1 @@ -1414,20 +1429,73 @@ static struct sdio_driver ath6kl_sdio_driver = { .drv.pm = ATH6KL_SDIO_PM_OPS, }; +static int ath6kl_sdio_init_gpio(void) +{ + int ret = 0; + + if (gpio_is_valid(reset_pwd_gpio)) { + /* Request the reset GPIO, and assert it to make sure we get a + * clean boot in-case we had a floating input or other issue. + */ + ret = gpio_request_one(reset_pwd_gpio, + GPIOF_OUT_INIT_LOW | + GPIOF_EXPORT_DIR_FIXED, + "WIFI_RESET"); + if (ret) { + ath6kl_err("Unable to get WIFI power gpio: %d\n", ret); + return ret; + } + + ath6kl_dbg(ATH6KL_DBG_SUSPEND, "Setup wifi gpio #%d\n", + reset_pwd_gpio); + usleep_range(20, 50); /* Pin must be asserted at least 5 usec */ + gpio_set_value(reset_pwd_gpio, 1); /* De-assert the pin */ + + msleep(ATH6KL_MMC_PROBE_DELAY); + } + + return 0; +} + +static void ath6kl_sdio_release_gpio(void) +{ + if (gpio_is_valid(reset_pwd_gpio)) { + /* Be sure we leave the chip in reset when we unload and also + * release the GPIO + */ + gpio_set_value(reset_pwd_gpio, 0); + gpio_free(reset_pwd_gpio); + } +} + static int __init ath6kl_sdio_init(void) { int ret; - ret = sdio_register_driver(&ath6kl_sdio_driver); + ret = ath6kl_sdio_init_gpio(); if (ret) + goto err_gpio; + + ret = sdio_register_driver(&ath6kl_sdio_driver); + if (ret) { ath6kl_err("sdio driver registration failed: %d\n", ret); + goto err_register; + } return ret; + +err_register: + ath6kl_sdio_release_gpio(); + +err_gpio: + return ret; } static void __exit ath6kl_sdio_exit(void) { sdio_unregister_driver(&ath6kl_sdio_driver); + + ath6kl_sdio_release_gpio(); } module_init(ath6kl_sdio_init);