From patchwork Sun Aug 29 13:12:54 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Baryshkov X-Patchwork-Id: 504196 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-18.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 02383C432BE for ; Sun, 29 Aug 2021 13:14:49 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id DCC8E6023E for ; Sun, 29 Aug 2021 13:14:48 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235408AbhH2NPe (ORCPT ); Sun, 29 Aug 2021 09:15:34 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46986 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235405AbhH2NOF (ORCPT ); Sun, 29 Aug 2021 09:14:05 -0400 Received: from mail-lf1-x132.google.com (mail-lf1-x132.google.com [IPv6:2a00:1450:4864:20::132]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 61386C0617AE for ; Sun, 29 Aug 2021 06:13:13 -0700 (PDT) Received: by mail-lf1-x132.google.com with SMTP id y34so25251861lfa.8 for ; Sun, 29 Aug 2021 06:13:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=77LQWfyVKMoi73qcXWTeFPSwjbiChQAfjnB164skbi4=; b=F7nJu+GO+HQuwgLZrS62N16GEljKer+Oo3YGlCAQjsSE/Njj5LzzFwhPbEzCxP94JK rOzm+jfZ3hLXWiuqetSAH6DRo4SvVTYna5jJWTOe2hZ+pK97+6UXfiWQWKJtOMMKa8sH oYIRj91RsdGMPzqg/7mDoJTOd08wNwidKyQ4LJekn8RgxrIk4w964ropQCCa+H8rscWa ex2ZlZQTyDxMh1l2Ke2b/DT5CLwEAbySyK8E1TNL/skfx07zCT62fxsScRQGFCcgU/z4 sARKhGpeGRBH6hnmWThr+wbnFMpPbz11vNgfV0NcVucpt3QUB4Y34CICIF1IYLr/AnQh rvwQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=77LQWfyVKMoi73qcXWTeFPSwjbiChQAfjnB164skbi4=; b=WQ3kQgMy+JnlYzJbBFymF87ItB4ZdyaFyMgDxP3H+GW5A5YycoOVlRLm/4W2WMyub4 MYP7qlBj4kNswNSl9oOL7+5epHGy35Q6WkXIen7tf4xRXWaotjAfswLoo/fTB13nnhEM lufZiu2BWEEoR2Sg7J5898kFDsiEaZW0ogxVNNzZEzgzB79Z97Fs+7OLYMdBhzGMn/Ac pJw7/jqztLz9dztHGEdpm6gS6ifJDREIcBBELI8svEeTfm1Wlnxsdc6wBt8z3Hfsfq8Z rk0J/D3ZtsExCRS5OqzvrxAr624UO9R8zQ65a/FRpgMH5CbbAeeaUQ4gCTgF8RYJ+G1H 7GRA== X-Gm-Message-State: AOAM530XgcQUglA9loR05s9M53lMjJh7+xtA2AK72hAPro2WSW+/tQQm TvHwDD/n8BSjDhu2Fq4NfxQ6PQ== X-Google-Smtp-Source: ABdhPJybr5Jaw2i5q9no+zvN/s79iVW44buANCnoNX4NFJsLVg6o1dmQ13pW9bFnNi3dN4y2amXkEA== X-Received: by 2002:a05:6512:11e9:: with SMTP id p9mr14218015lfs.372.1630242791547; Sun, 29 Aug 2021 06:13:11 -0700 (PDT) Received: from eriador.lan ([37.153.55.125]) by smtp.gmail.com with ESMTPSA id x13sm712503lfq.262.2021.08.29.06.13.10 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 29 Aug 2021 06:13:11 -0700 (PDT) From: Dmitry Baryshkov To: Andy Gross , Bjorn Andersson , Ulf Hansson , Marcel Holtmann , Johan Hedberg , Luiz Augusto von Dentz , Kalle Valo , "David S. Miller" , Jakub Kicinski , Stanimir Varbanov Cc: linux-arm-msm@vger.kernel.org, linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-bluetooth@vger.kernel.org, ath10k@lists.infradead.org, linux-wireless@vger.kernel.org, netdev@vger.kernel.org Subject: [RFC v2 02/13] pwrseq: port MMC's pwrseq drivers to new pwrseq subsystem Date: Sun, 29 Aug 2021 16:12:54 +0300 Message-Id: <20210829131305.534417-3-dmitry.baryshkov@linaro.org> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20210829131305.534417-1-dmitry.baryshkov@linaro.org> References: <20210829131305.534417-1-dmitry.baryshkov@linaro.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org Port MMC's all pwrseq drivers to new pwrseq subsystem. Signed-off-by: Dmitry Baryshkov --- .../pwrseq}/mmc-pwrseq-emmc.yaml | 0 .../pwrseq}/mmc-pwrseq-sd8787.yaml | 0 .../pwrseq}/mmc-pwrseq-simple.yaml | 0 drivers/mmc/core/Kconfig | 32 ---- drivers/mmc/core/Makefile | 3 - drivers/mmc/core/pwrseq_emmc.c | 120 ------------- drivers/mmc/core/pwrseq_sd8787.c | 107 ------------ drivers/mmc/core/pwrseq_simple.c | 164 ------------------ drivers/power/pwrseq/Kconfig | 32 ++++ drivers/power/pwrseq/Makefile | 4 + drivers/power/pwrseq/pwrseq_emmc.c | 119 +++++++++++++ drivers/power/pwrseq/pwrseq_sd8787.c | 98 +++++++++++ drivers/power/pwrseq/pwrseq_simple.c | 160 +++++++++++++++++ 13 files changed, 413 insertions(+), 426 deletions(-) rename Documentation/devicetree/bindings/{mmc => power/pwrseq}/mmc-pwrseq-emmc.yaml (100%) rename Documentation/devicetree/bindings/{mmc => power/pwrseq}/mmc-pwrseq-sd8787.yaml (100%) rename Documentation/devicetree/bindings/{mmc => power/pwrseq}/mmc-pwrseq-simple.yaml (100%) delete mode 100644 drivers/mmc/core/pwrseq_emmc.c delete mode 100644 drivers/mmc/core/pwrseq_sd8787.c delete mode 100644 drivers/mmc/core/pwrseq_simple.c create mode 100644 drivers/power/pwrseq/pwrseq_emmc.c create mode 100644 drivers/power/pwrseq/pwrseq_sd8787.c create mode 100644 drivers/power/pwrseq/pwrseq_simple.c diff --git a/Documentation/devicetree/bindings/mmc/mmc-pwrseq-emmc.yaml b/Documentation/devicetree/bindings/power/pwrseq/mmc-pwrseq-emmc.yaml similarity index 100% rename from Documentation/devicetree/bindings/mmc/mmc-pwrseq-emmc.yaml rename to Documentation/devicetree/bindings/power/pwrseq/mmc-pwrseq-emmc.yaml diff --git a/Documentation/devicetree/bindings/mmc/mmc-pwrseq-sd8787.yaml b/Documentation/devicetree/bindings/power/pwrseq/mmc-pwrseq-sd8787.yaml similarity index 100% rename from Documentation/devicetree/bindings/mmc/mmc-pwrseq-sd8787.yaml rename to Documentation/devicetree/bindings/power/pwrseq/mmc-pwrseq-sd8787.yaml diff --git a/Documentation/devicetree/bindings/mmc/mmc-pwrseq-simple.yaml b/Documentation/devicetree/bindings/power/pwrseq/mmc-pwrseq-simple.yaml similarity index 100% rename from Documentation/devicetree/bindings/mmc/mmc-pwrseq-simple.yaml rename to Documentation/devicetree/bindings/power/pwrseq/mmc-pwrseq-simple.yaml diff --git a/drivers/mmc/core/Kconfig b/drivers/mmc/core/Kconfig index ae8b69aee619..cf7df64ce009 100644 --- a/drivers/mmc/core/Kconfig +++ b/drivers/mmc/core/Kconfig @@ -2,38 +2,6 @@ # # MMC core configuration # -config PWRSEQ_EMMC - tristate "HW reset support for eMMC" - default y - depends on OF - help - This selects Hardware reset support aka pwrseq-emmc for eMMC - devices. By default this option is set to y. - - This driver can also be built as a module. If so, the module - will be called pwrseq_emmc. - -config PWRSEQ_SD8787 - tristate "HW reset support for SD8787 BT + Wifi module" - depends on OF && (MWIFIEX || BT_MRVL_SDIO || LIBERTAS_SDIO) - help - This selects hardware reset support for the SD8787 BT + Wifi - module. By default this option is set to n. - - This driver can also be built as a module. If so, the module - will be called pwrseq_sd8787. - -config PWRSEQ_SIMPLE - tristate "Simple HW reset support for MMC" - default y - depends on OF - help - This selects simple hardware reset support aka pwrseq-simple for MMC - devices. By default this option is set to y. - - This driver can also be built as a module. If so, the module - will be called pwrseq_simple. - config MMC_BLOCK tristate "MMC block device driver" depends on BLOCK diff --git a/drivers/mmc/core/Makefile b/drivers/mmc/core/Makefile index 6a907736cd7a..322eb69bd00e 100644 --- a/drivers/mmc/core/Makefile +++ b/drivers/mmc/core/Makefile @@ -10,9 +10,6 @@ mmc_core-y := core.o bus.o host.o \ sdio_cis.o sdio_io.o sdio_irq.o \ slot-gpio.o regulator.o mmc_core-$(CONFIG_OF) += pwrseq.o -obj-$(CONFIG_PWRSEQ_SIMPLE) += pwrseq_simple.o -obj-$(CONFIG_PWRSEQ_SD8787) += pwrseq_sd8787.o -obj-$(CONFIG_PWRSEQ_EMMC) += pwrseq_emmc.o mmc_core-$(CONFIG_DEBUG_FS) += debugfs.o obj-$(CONFIG_MMC_BLOCK) += mmc_block.o mmc_block-objs := block.o queue.o diff --git a/drivers/mmc/core/pwrseq_emmc.c b/drivers/mmc/core/pwrseq_emmc.c deleted file mode 100644 index f6dde9edd7a3..000000000000 --- a/drivers/mmc/core/pwrseq_emmc.c +++ /dev/null @@ -1,120 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (C) 2015, Samsung Electronics Co., Ltd. - * - * Author: Marek Szyprowski - * - * Simple eMMC hardware reset provider - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "pwrseq.h" - -struct mmc_pwrseq_emmc { - struct mmc_pwrseq pwrseq; - struct notifier_block reset_nb; - struct gpio_desc *reset_gpio; -}; - -#define to_pwrseq_emmc(p) container_of(p, struct mmc_pwrseq_emmc, pwrseq) - -static void mmc_pwrseq_emmc_reset(struct mmc_host *host) -{ - struct mmc_pwrseq_emmc *pwrseq = to_pwrseq_emmc(host->pwrseq); - - gpiod_set_value_cansleep(pwrseq->reset_gpio, 1); - udelay(1); - gpiod_set_value_cansleep(pwrseq->reset_gpio, 0); - udelay(200); -} - -static int mmc_pwrseq_emmc_reset_nb(struct notifier_block *this, - unsigned long mode, void *cmd) -{ - struct mmc_pwrseq_emmc *pwrseq = container_of(this, - struct mmc_pwrseq_emmc, reset_nb); - gpiod_set_value(pwrseq->reset_gpio, 1); - udelay(1); - gpiod_set_value(pwrseq->reset_gpio, 0); - udelay(200); - - return NOTIFY_DONE; -} - -static const struct mmc_pwrseq_ops mmc_pwrseq_emmc_ops = { - .reset = mmc_pwrseq_emmc_reset, -}; - -static int mmc_pwrseq_emmc_probe(struct platform_device *pdev) -{ - struct mmc_pwrseq_emmc *pwrseq; - struct device *dev = &pdev->dev; - - pwrseq = devm_kzalloc(dev, sizeof(*pwrseq), GFP_KERNEL); - if (!pwrseq) - return -ENOMEM; - - pwrseq->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); - if (IS_ERR(pwrseq->reset_gpio)) - return PTR_ERR(pwrseq->reset_gpio); - - if (!gpiod_cansleep(pwrseq->reset_gpio)) { - /* - * register reset handler to ensure emmc reset also from - * emergency_reboot(), priority 255 is the highest priority - * so it will be executed before any system reboot handler. - */ - pwrseq->reset_nb.notifier_call = mmc_pwrseq_emmc_reset_nb; - pwrseq->reset_nb.priority = 255; - register_restart_handler(&pwrseq->reset_nb); - } else { - dev_notice(dev, "EMMC reset pin tied to a sleepy GPIO driver; reset on emergency-reboot disabled\n"); - } - - pwrseq->pwrseq.ops = &mmc_pwrseq_emmc_ops; - pwrseq->pwrseq.dev = dev; - pwrseq->pwrseq.owner = THIS_MODULE; - platform_set_drvdata(pdev, pwrseq); - - return mmc_pwrseq_register(&pwrseq->pwrseq); -} - -static int mmc_pwrseq_emmc_remove(struct platform_device *pdev) -{ - struct mmc_pwrseq_emmc *pwrseq = platform_get_drvdata(pdev); - - unregister_restart_handler(&pwrseq->reset_nb); - mmc_pwrseq_unregister(&pwrseq->pwrseq); - - return 0; -} - -static const struct of_device_id mmc_pwrseq_emmc_of_match[] = { - { .compatible = "mmc-pwrseq-emmc",}, - {/* sentinel */}, -}; - -MODULE_DEVICE_TABLE(of, mmc_pwrseq_emmc_of_match); - -static struct platform_driver mmc_pwrseq_emmc_driver = { - .probe = mmc_pwrseq_emmc_probe, - .remove = mmc_pwrseq_emmc_remove, - .driver = { - .name = "pwrseq_emmc", - .of_match_table = mmc_pwrseq_emmc_of_match, - }, -}; - -module_platform_driver(mmc_pwrseq_emmc_driver); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/mmc/core/pwrseq_sd8787.c b/drivers/mmc/core/pwrseq_sd8787.c deleted file mode 100644 index 68a826f1c0a1..000000000000 --- a/drivers/mmc/core/pwrseq_sd8787.c +++ /dev/null @@ -1,107 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * pwrseq_sd8787.c - power sequence support for Marvell SD8787 BT + Wifi chip - * - * Copyright (C) 2016 Matt Ranostay - * - * Based on the original work pwrseq_simple.c - * Copyright (C) 2014 Linaro Ltd - * Author: Ulf Hansson - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "pwrseq.h" - -struct mmc_pwrseq_sd8787 { - struct mmc_pwrseq pwrseq; - struct gpio_desc *reset_gpio; - struct gpio_desc *pwrdn_gpio; -}; - -#define to_pwrseq_sd8787(p) container_of(p, struct mmc_pwrseq_sd8787, pwrseq) - -static void mmc_pwrseq_sd8787_pre_power_on(struct mmc_host *host) -{ - struct mmc_pwrseq_sd8787 *pwrseq = to_pwrseq_sd8787(host->pwrseq); - - gpiod_set_value_cansleep(pwrseq->reset_gpio, 1); - - msleep(300); - gpiod_set_value_cansleep(pwrseq->pwrdn_gpio, 1); -} - -static void mmc_pwrseq_sd8787_power_off(struct mmc_host *host) -{ - struct mmc_pwrseq_sd8787 *pwrseq = to_pwrseq_sd8787(host->pwrseq); - - gpiod_set_value_cansleep(pwrseq->pwrdn_gpio, 0); - gpiod_set_value_cansleep(pwrseq->reset_gpio, 0); -} - -static const struct mmc_pwrseq_ops mmc_pwrseq_sd8787_ops = { - .pre_power_on = mmc_pwrseq_sd8787_pre_power_on, - .power_off = mmc_pwrseq_sd8787_power_off, -}; - -static const struct of_device_id mmc_pwrseq_sd8787_of_match[] = { - { .compatible = "mmc-pwrseq-sd8787",}, - {/* sentinel */}, -}; -MODULE_DEVICE_TABLE(of, mmc_pwrseq_sd8787_of_match); - -static int mmc_pwrseq_sd8787_probe(struct platform_device *pdev) -{ - struct mmc_pwrseq_sd8787 *pwrseq; - struct device *dev = &pdev->dev; - - pwrseq = devm_kzalloc(dev, sizeof(*pwrseq), GFP_KERNEL); - if (!pwrseq) - return -ENOMEM; - - pwrseq->pwrdn_gpio = devm_gpiod_get(dev, "powerdown", GPIOD_OUT_LOW); - if (IS_ERR(pwrseq->pwrdn_gpio)) - return PTR_ERR(pwrseq->pwrdn_gpio); - - pwrseq->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); - if (IS_ERR(pwrseq->reset_gpio)) - return PTR_ERR(pwrseq->reset_gpio); - - pwrseq->pwrseq.dev = dev; - pwrseq->pwrseq.ops = &mmc_pwrseq_sd8787_ops; - pwrseq->pwrseq.owner = THIS_MODULE; - platform_set_drvdata(pdev, pwrseq); - - return mmc_pwrseq_register(&pwrseq->pwrseq); -} - -static int mmc_pwrseq_sd8787_remove(struct platform_device *pdev) -{ - struct mmc_pwrseq_sd8787 *pwrseq = platform_get_drvdata(pdev); - - mmc_pwrseq_unregister(&pwrseq->pwrseq); - - return 0; -} - -static struct platform_driver mmc_pwrseq_sd8787_driver = { - .probe = mmc_pwrseq_sd8787_probe, - .remove = mmc_pwrseq_sd8787_remove, - .driver = { - .name = "pwrseq_sd8787", - .of_match_table = mmc_pwrseq_sd8787_of_match, - }, -}; - -module_platform_driver(mmc_pwrseq_sd8787_driver); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/mmc/core/pwrseq_simple.c b/drivers/mmc/core/pwrseq_simple.c deleted file mode 100644 index ea4d3670560e..000000000000 --- a/drivers/mmc/core/pwrseq_simple.c +++ /dev/null @@ -1,164 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (C) 2014 Linaro Ltd - * - * Author: Ulf Hansson - * - * Simple MMC power sequence management - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "pwrseq.h" - -struct mmc_pwrseq_simple { - struct mmc_pwrseq pwrseq; - bool clk_enabled; - u32 post_power_on_delay_ms; - u32 power_off_delay_us; - struct clk *ext_clk; - struct gpio_descs *reset_gpios; -}; - -#define to_pwrseq_simple(p) container_of(p, struct mmc_pwrseq_simple, pwrseq) - -static void mmc_pwrseq_simple_set_gpios_value(struct mmc_pwrseq_simple *pwrseq, - int value) -{ - struct gpio_descs *reset_gpios = pwrseq->reset_gpios; - - if (!IS_ERR(reset_gpios)) { - unsigned long *values; - int nvalues = reset_gpios->ndescs; - - values = bitmap_alloc(nvalues, GFP_KERNEL); - if (!values) - return; - - if (value) - bitmap_fill(values, nvalues); - else - bitmap_zero(values, nvalues); - - gpiod_set_array_value_cansleep(nvalues, reset_gpios->desc, - reset_gpios->info, values); - - kfree(values); - } -} - -static void mmc_pwrseq_simple_pre_power_on(struct mmc_host *host) -{ - struct mmc_pwrseq_simple *pwrseq = to_pwrseq_simple(host->pwrseq); - - if (!IS_ERR(pwrseq->ext_clk) && !pwrseq->clk_enabled) { - clk_prepare_enable(pwrseq->ext_clk); - pwrseq->clk_enabled = true; - } - - mmc_pwrseq_simple_set_gpios_value(pwrseq, 1); -} - -static void mmc_pwrseq_simple_post_power_on(struct mmc_host *host) -{ - struct mmc_pwrseq_simple *pwrseq = to_pwrseq_simple(host->pwrseq); - - mmc_pwrseq_simple_set_gpios_value(pwrseq, 0); - - if (pwrseq->post_power_on_delay_ms) - msleep(pwrseq->post_power_on_delay_ms); -} - -static void mmc_pwrseq_simple_power_off(struct mmc_host *host) -{ - struct mmc_pwrseq_simple *pwrseq = to_pwrseq_simple(host->pwrseq); - - mmc_pwrseq_simple_set_gpios_value(pwrseq, 1); - - if (pwrseq->power_off_delay_us) - usleep_range(pwrseq->power_off_delay_us, - 2 * pwrseq->power_off_delay_us); - - if (!IS_ERR(pwrseq->ext_clk) && pwrseq->clk_enabled) { - clk_disable_unprepare(pwrseq->ext_clk); - pwrseq->clk_enabled = false; - } -} - -static const struct mmc_pwrseq_ops mmc_pwrseq_simple_ops = { - .pre_power_on = mmc_pwrseq_simple_pre_power_on, - .post_power_on = mmc_pwrseq_simple_post_power_on, - .power_off = mmc_pwrseq_simple_power_off, -}; - -static const struct of_device_id mmc_pwrseq_simple_of_match[] = { - { .compatible = "mmc-pwrseq-simple",}, - {/* sentinel */}, -}; -MODULE_DEVICE_TABLE(of, mmc_pwrseq_simple_of_match); - -static int mmc_pwrseq_simple_probe(struct platform_device *pdev) -{ - struct mmc_pwrseq_simple *pwrseq; - struct device *dev = &pdev->dev; - - pwrseq = devm_kzalloc(dev, sizeof(*pwrseq), GFP_KERNEL); - if (!pwrseq) - return -ENOMEM; - - pwrseq->ext_clk = devm_clk_get(dev, "ext_clock"); - if (IS_ERR(pwrseq->ext_clk) && PTR_ERR(pwrseq->ext_clk) != -ENOENT) - return PTR_ERR(pwrseq->ext_clk); - - pwrseq->reset_gpios = devm_gpiod_get_array(dev, "reset", - GPIOD_OUT_HIGH); - if (IS_ERR(pwrseq->reset_gpios) && - PTR_ERR(pwrseq->reset_gpios) != -ENOENT && - PTR_ERR(pwrseq->reset_gpios) != -ENOSYS) { - return PTR_ERR(pwrseq->reset_gpios); - } - - device_property_read_u32(dev, "post-power-on-delay-ms", - &pwrseq->post_power_on_delay_ms); - device_property_read_u32(dev, "power-off-delay-us", - &pwrseq->power_off_delay_us); - - pwrseq->pwrseq.dev = dev; - pwrseq->pwrseq.ops = &mmc_pwrseq_simple_ops; - pwrseq->pwrseq.owner = THIS_MODULE; - platform_set_drvdata(pdev, pwrseq); - - return mmc_pwrseq_register(&pwrseq->pwrseq); -} - -static int mmc_pwrseq_simple_remove(struct platform_device *pdev) -{ - struct mmc_pwrseq_simple *pwrseq = platform_get_drvdata(pdev); - - mmc_pwrseq_unregister(&pwrseq->pwrseq); - - return 0; -} - -static struct platform_driver mmc_pwrseq_simple_driver = { - .probe = mmc_pwrseq_simple_probe, - .remove = mmc_pwrseq_simple_remove, - .driver = { - .name = "pwrseq_simple", - .of_match_table = mmc_pwrseq_simple_of_match, - }, -}; - -module_platform_driver(mmc_pwrseq_simple_driver); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/power/pwrseq/Kconfig b/drivers/power/pwrseq/Kconfig index 8904ec9ed541..36339a456b03 100644 --- a/drivers/power/pwrseq/Kconfig +++ b/drivers/power/pwrseq/Kconfig @@ -8,4 +8,36 @@ menuconfig PWRSEQ if PWRSEQ +config PWRSEQ_EMMC + tristate "HW reset support for eMMC" + default y + depends on OF + help + This selects Hardware reset support aka pwrseq-emmc for eMMC + devices. By default this option is set to y. + + This driver can also be built as a module. If so, the module + will be called pwrseq_emmc. + +config PWRSEQ_SD8787 + tristate "HW reset support for SD8787 BT + Wifi module" + depends on OF + help + This selects hardware reset support for the SD8787 BT + Wifi + module. By default this option is set to n. + + This driver can also be built as a module. If so, the module + will be called pwrseq_sd8787. + +config PWRSEQ_SIMPLE + tristate "Simple HW reset support" + default y + depends on OF + help + This selects simple hardware reset support aka pwrseq-simple. + By default this option is set to y. + + This driver can also be built as a module. If so, the module + will be called pwrseq_simple. + endif diff --git a/drivers/power/pwrseq/Makefile b/drivers/power/pwrseq/Makefile index 108429ff6445..6f359d228843 100644 --- a/drivers/power/pwrseq/Makefile +++ b/drivers/power/pwrseq/Makefile @@ -4,3 +4,7 @@ # obj-$(CONFIG_PWRSEQ) += core.o + +obj-$(CONFIG_PWRSEQ_EMMC) += pwrseq_emmc.o +obj-$(CONFIG_PWRSEQ_SD8787) += pwrseq_sd8787.o +obj-$(CONFIG_PWRSEQ_SIMPLE) += pwrseq_simple.o diff --git a/drivers/power/pwrseq/pwrseq_emmc.c b/drivers/power/pwrseq/pwrseq_emmc.c new file mode 100644 index 000000000000..4a2da837efd0 --- /dev/null +++ b/drivers/power/pwrseq/pwrseq_emmc.c @@ -0,0 +1,119 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2015, Samsung Electronics Co., Ltd. + * + * Author: Marek Szyprowski + * + * Simple eMMC hardware reset provider + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct pwrseq_emmc { + struct notifier_block reset_nb; + struct gpio_desc *reset_gpio; +}; + +static void pwrseq_ereset(struct pwrseq *pwrseq) +{ + struct pwrseq_emmc *pwrseq_emmc = pwrseq_get_data(pwrseq); + + gpiod_set_value_cansleep(pwrseq_emmc->reset_gpio, 1); + udelay(1); + gpiod_set_value_cansleep(pwrseq_emmc->reset_gpio, 0); + udelay(200); +} + +static int pwrseq_ereset_nb(struct notifier_block *this, + unsigned long mode, void *cmd) +{ + struct pwrseq_emmc *pwrseq_emmc = container_of(this, + struct pwrseq_emmc, reset_nb); + gpiod_set_value(pwrseq_emmc->reset_gpio, 1); + udelay(1); + gpiod_set_value(pwrseq_emmc->reset_gpio, 0); + udelay(200); + + return NOTIFY_DONE; +} + +static const struct pwrseq_ops pwrseq_eops = { + .reset = pwrseq_ereset, +}; + +static int pwrseq_eprobe(struct platform_device *pdev) +{ + struct pwrseq_emmc *pwrseq_emmc; + struct pwrseq *pwrseq; + struct pwrseq_provider *provider; + struct device *dev = &pdev->dev; + + pwrseq_emmc = devm_kzalloc(dev, sizeof(*pwrseq_emmc), GFP_KERNEL); + if (!pwrseq_emmc) + return -ENOMEM; + + pwrseq_emmc->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); + if (IS_ERR(pwrseq_emmc->reset_gpio)) + return PTR_ERR(pwrseq_emmc->reset_gpio); + + if (!gpiod_cansleep(pwrseq_emmc->reset_gpio)) { + /* + * register reset handler to ensure emmc reset also from + * emergency_reboot(), priority 255 is the highest priority + * so it will be executed before any system reboot handler. + */ + pwrseq_emmc->reset_nb.notifier_call = pwrseq_ereset_nb; + pwrseq_emmc->reset_nb.priority = 255; + register_restart_handler(&pwrseq_emmc->reset_nb); + } else { + dev_notice(dev, "EMMC reset pin tied to a sleepy GPIO driver; reset on emergency-reboot disabled\n"); + } + + platform_set_drvdata(pdev, pwrseq_emmc); + + pwrseq = devm_pwrseq_create(dev, &pwrseq_eops, pwrseq_emmc); + if (IS_ERR(pwrseq)) + return PTR_ERR(pwrseq); + + provider = devm_of_pwrseq_provider_register(dev, of_pwrseq_xlate_single, pwrseq); + + return PTR_ERR_OR_ZERO(provider); +} + +static int pwrseq_eremove(struct platform_device *pdev) +{ + struct pwrseq_emmc *pwrseq_emmc = platform_get_drvdata(pdev); + + unregister_restart_handler(&pwrseq_emmc->reset_nb); + + return 0; +} + +static const struct of_device_id pwrseq_eof_match[] = { + { .compatible = "mmc-pwrseq-emmc",}, + {/* sentinel */}, +}; + +MODULE_DEVICE_TABLE(of, pwrseq_eof_match); + +static struct platform_driver pwrseq_edriver = { + .probe = pwrseq_eprobe, + .remove = pwrseq_eremove, + .driver = { + .name = "pwrseq_emmc", + .of_match_table = pwrseq_eof_match, + }, +}; + +module_platform_driver(pwrseq_edriver); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/power/pwrseq/pwrseq_sd8787.c b/drivers/power/pwrseq/pwrseq_sd8787.c new file mode 100644 index 000000000000..c5d6c639380f --- /dev/null +++ b/drivers/power/pwrseq/pwrseq_sd8787.c @@ -0,0 +1,98 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * pwrseq_sd8787.c - power sequence support for Marvell SD8787 BT + Wifi chip + * + * Copyright (C) 2016 Matt Ranostay + * + * Based on the original work pwrseq_sd8787.c + * Copyright (C) 2014 Linaro Ltd + * Author: Ulf Hansson + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +struct pwrseq_sd8787 { + struct gpio_desc *reset_gpio; + struct gpio_desc *pwrdn_gpio; +}; + +static int pwrseq_sd8787_pre_power_on(struct pwrseq *pwrseq) +{ + struct pwrseq_sd8787 *pwrseq_sd8787 = pwrseq_get_data(pwrseq); + + gpiod_set_value_cansleep(pwrseq_sd8787->reset_gpio, 1); + + msleep(300); + gpiod_set_value_cansleep(pwrseq_sd8787->pwrdn_gpio, 1); + + return 0; +} + +static void pwrseq_sd8787_power_off(struct pwrseq *pwrseq) +{ + struct pwrseq_sd8787 *pwrseq_sd8787 = pwrseq_get_data(pwrseq); + + gpiod_set_value_cansleep(pwrseq_sd8787->pwrdn_gpio, 0); + gpiod_set_value_cansleep(pwrseq_sd8787->reset_gpio, 0); +} + +static const struct pwrseq_ops pwrseq_sd8787_ops = { + .pre_power_on = pwrseq_sd8787_pre_power_on, + .power_off = pwrseq_sd8787_power_off, +}; + +static const struct of_device_id pwrseq_sd8787_of_match[] = { + { .compatible = "mmc-pwrseq-sd8787",}, + {/* sentinel */}, +}; +MODULE_DEVICE_TABLE(of, pwrseq_sd8787_of_match); + +static int pwrseq_sd8787_probe(struct platform_device *pdev) +{ + struct pwrseq_sd8787 *pwrseq_sd8787; + struct pwrseq *pwrseq; + struct pwrseq_provider *provider; + struct device *dev = &pdev->dev; + + pwrseq_sd8787 = devm_kzalloc(dev, sizeof(*pwrseq_sd8787), GFP_KERNEL); + if (!pwrseq_sd8787) + return -ENOMEM; + + pwrseq_sd8787->pwrdn_gpio = devm_gpiod_get(dev, "powerdown", GPIOD_OUT_LOW); + if (IS_ERR(pwrseq_sd8787->pwrdn_gpio)) + return PTR_ERR(pwrseq_sd8787->pwrdn_gpio); + + pwrseq_sd8787->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); + if (IS_ERR(pwrseq_sd8787->reset_gpio)) + return PTR_ERR(pwrseq_sd8787->reset_gpio); + + pwrseq = devm_pwrseq_create(dev, &pwrseq_sd8787_ops, pwrseq_sd8787); + if (IS_ERR(pwrseq)) + return PTR_ERR(pwrseq); + + provider = devm_of_pwrseq_provider_register(dev, of_pwrseq_xlate_single, pwrseq); + + return PTR_ERR_OR_ZERO(provider); +} + +static struct platform_driver pwrseq_sd8787_driver = { + .probe = pwrseq_sd8787_probe, + .driver = { + .name = "pwrseq_sd8787", + .of_match_table = pwrseq_sd8787_of_match, + }, +}; + +module_platform_driver(pwrseq_sd8787_driver); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/power/pwrseq/pwrseq_simple.c b/drivers/power/pwrseq/pwrseq_simple.c new file mode 100644 index 000000000000..f8d6e6e077df --- /dev/null +++ b/drivers/power/pwrseq/pwrseq_simple.c @@ -0,0 +1,160 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2014 Linaro Ltd + * + * Author: Ulf Hansson + * + * Simple MMC power sequence management + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct pwrseq_simple { + bool clk_enabled; + u32 post_power_on_delay_ms; + u32 power_off_delay_us; + struct clk *ext_clk; + struct gpio_descs *reset_gpios; +}; + +static int pwrseq_simple_set_gpios_value(struct pwrseq_simple *pwrseq_simple, + int value) +{ + struct gpio_descs *reset_gpios = pwrseq_simple->reset_gpios; + unsigned long *values; + int nvalues; + int ret; + + if (IS_ERR(reset_gpios)) + return PTR_ERR(reset_gpios); + + nvalues = reset_gpios->ndescs; + + values = bitmap_alloc(nvalues, GFP_KERNEL); + if (!values) + return -ENOMEM; + + if (value) + bitmap_fill(values, nvalues); + else + bitmap_zero(values, nvalues); + + ret = gpiod_set_array_value_cansleep(nvalues, reset_gpios->desc, + reset_gpios->info, values); + kfree(values); + + return ret; +} + +static int pwrseq_simple_pre_power_on(struct pwrseq *pwrseq) +{ + struct pwrseq_simple *pwrseq_simple = pwrseq_get_data(pwrseq); + + if (!IS_ERR(pwrseq_simple->ext_clk) && !pwrseq_simple->clk_enabled) { + clk_prepare_enable(pwrseq_simple->ext_clk); + pwrseq_simple->clk_enabled = true; + } + + return pwrseq_simple_set_gpios_value(pwrseq_simple, 1); +} + +static int pwrseq_simple_power_on(struct pwrseq *pwrseq) +{ + struct pwrseq_simple *pwrseq_simple = pwrseq_get_data(pwrseq); + int ret; + + ret = pwrseq_simple_set_gpios_value(pwrseq_simple, 0); + if (ret) + return ret; + + if (pwrseq_simple->post_power_on_delay_ms) + msleep(pwrseq_simple->post_power_on_delay_ms); + + return 0; +} + +static void pwrseq_simple_power_off(struct pwrseq *pwrseq) +{ + struct pwrseq_simple *pwrseq_simple = pwrseq_get_data(pwrseq); + + pwrseq_simple_set_gpios_value(pwrseq_simple, 1); + + if (pwrseq_simple->power_off_delay_us) + usleep_range(pwrseq_simple->power_off_delay_us, + 2 * pwrseq_simple->power_off_delay_us); + + if (!IS_ERR(pwrseq_simple->ext_clk) && pwrseq_simple->clk_enabled) { + clk_disable_unprepare(pwrseq_simple->ext_clk); + pwrseq_simple->clk_enabled = false; + } +} + +static const struct pwrseq_ops pwrseq_simple_ops = { + .pre_power_on = pwrseq_simple_pre_power_on, + .power_on = pwrseq_simple_power_on, + .power_off = pwrseq_simple_power_off, +}; + +static const struct of_device_id pwrseq_simple_of_match[] = { + { .compatible = "mmc-pwrseq-simple",}, /* MMC-specific compatible */ + {/* sentinel */}, +}; +MODULE_DEVICE_TABLE(of, pwrseq_simple_of_match); + +static int pwrseq_simple_probe(struct platform_device *pdev) +{ + struct pwrseq_simple *pwrseq_simple; + struct pwrseq *pwrseq; + struct pwrseq_provider *provider; + struct device *dev = &pdev->dev; + + pwrseq_simple = devm_kzalloc(dev, sizeof(*pwrseq_simple), GFP_KERNEL); + if (!pwrseq_simple) + return -ENOMEM; + + pwrseq_simple->ext_clk = devm_clk_get(dev, "ext_clock"); + if (IS_ERR(pwrseq_simple->ext_clk) && PTR_ERR(pwrseq_simple->ext_clk) != -ENOENT) + return PTR_ERR(pwrseq_simple->ext_clk); + + pwrseq_simple->reset_gpios = devm_gpiod_get_array(dev, "reset", + GPIOD_OUT_HIGH); + if (IS_ERR(pwrseq_simple->reset_gpios) && + PTR_ERR(pwrseq_simple->reset_gpios) != -ENOENT && + PTR_ERR(pwrseq_simple->reset_gpios) != -ENOSYS) { + return PTR_ERR(pwrseq_simple->reset_gpios); + } + + device_property_read_u32(dev, "post-power-on-delay-ms", + &pwrseq_simple->post_power_on_delay_ms); + device_property_read_u32(dev, "power-off-delay-us", + &pwrseq_simple->power_off_delay_us); + + pwrseq = devm_pwrseq_create(dev, &pwrseq_simple_ops, pwrseq_simple); + if (IS_ERR(pwrseq)) + return PTR_ERR(pwrseq); + + provider = devm_of_pwrseq_provider_register(dev, of_pwrseq_xlate_single, pwrseq); + + return PTR_ERR_OR_ZERO(provider); +} + +static struct platform_driver pwrseq_simple_driver = { + .probe = pwrseq_simple_probe, + .driver = { + .name = "pwrseq_simple", + .of_match_table = pwrseq_simple_of_match, + }, +}; + +module_platform_driver(pwrseq_simple_driver); +MODULE_LICENSE("GPL v2"); From patchwork Sun Aug 29 13:12:56 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Baryshkov X-Patchwork-Id: 504047 Delivered-To: patch@linaro.org Received: by 2002:a02:8629:0:0:0:0:0 with SMTP id e38csp926701jai; Sun, 29 Aug 2021 06:13:26 -0700 (PDT) X-Google-Smtp-Source: ABdhPJz/2hDMvvep5cvDuWTJ/GmCobLpx52vlPnTxyXT9eSP1wQTin0WRgoOvSCYzl/5G/fM/OUS X-Received: by 2002:a50:998c:: with SMTP id m12mr14361696edb.327.1630242806749; Sun, 29 Aug 2021 06:13:26 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1630242806; cv=none; d=google.com; s=arc-20160816; b=KnDo1B8bfbUxI87w5zjUmh3vibxx1O64GMgknYHqv+ssskoS/E6uTsr9EmbhXt6mr3 IC93+NKPKq4mUC+EHatt5edY+1tQ3LOkFPWKJ5+QFcTEA8kNLfkwHi9jWZuRI27XPRTw vj/5PE3NcRC9D1OzoCpa0a47YwAuKT0c+S/N6EW4iSaVJVssC2yI6MAmDIPspNbDmi37 xbwLVi63vwqqOsqwX/qme6E2faFcEUey57wV0Bdolb4R7YJC948kxhQ08tva1zFTTfFk 3yvQi7VHTHgyjdIgz5wfQLE4YmtbE1bYHjjhhC+oMdyALyRaAznYoNBGW4INmhfxgfpK Kgcg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=WshXke/adPD/p+WKmajaeRbUAwrviqR8m0vly4QQtAM=; b=bOAlszaoIPLULsnyHYdXr3zHK5dxYmNpR5LlhuIpS+029Bc4rQP6xLFo7R4jKtAnhr UEB9sZyAlkDF4dhQcdURElSNFPi/3m49aLKoqZuTG1numwz4BV7aBLsL+mLdLT8z0Oo8 1PJ/OqqH5basTxs7NglJdOxZNHzXlMbgspamAskBtqyshgMu/28WU2WezslD5nuVoDeJ 6H/SyLhSQBdKgN2VjoL7jn6BtXAgEA2ctB8NE+Lbh6SsO6VFhUZmNqIB0Mb6dulQT5Gy F0DBiYF1+LHtGnOX62VN1s5/bXDQXUoiyirChSmtF2xR5S3flmBh+sB65YvTUoVvgeoa 87VQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=yv1wY8n3; spf=pass (google.com: domain of linux-mmc-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-mmc-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id q21si12161065eds.318.2021.08.29.06.13.26; Sun, 29 Aug 2021 06:13:26 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-mmc-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=yv1wY8n3; spf=pass (google.com: domain of linux-mmc-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-mmc-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235514AbhH2NOL (ORCPT + 3 others); Sun, 29 Aug 2021 09:14:11 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46996 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235442AbhH2NOH (ORCPT ); Sun, 29 Aug 2021 09:14:07 -0400 Received: from mail-lj1-x230.google.com (mail-lj1-x230.google.com [IPv6:2a00:1450:4864:20::230]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B80C0C061292 for ; Sun, 29 Aug 2021 06:13:14 -0700 (PDT) Received: by mail-lj1-x230.google.com with SMTP id l18so20659738lji.12 for ; Sun, 29 Aug 2021 06:13:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=WshXke/adPD/p+WKmajaeRbUAwrviqR8m0vly4QQtAM=; b=yv1wY8n36L7V0jXuL/RKTDHsagrZcjl+Y3stnEv9CTKMwNlicXHVJzd0NMJpPVINaX kxotUF62kz6pCbV9QbgS+FeTD3Po1u0hf1mHzrYzMwXmMIqo1o+Q3ooBSSJd140yKen1 Z1NegLFxPuefY6PGj78zz2BTSQ/DV6e3Fzwn0ShuqI9yDU8Kky5kJAhm8+kRESN2dn/b NrTvmw6qCSQBglnbxk7mP0T27UonyLZrzgIRDKkyfBqa0WZ2jSemgAE5bN5rnpMffj+K UwJukwuHNrjkaOwn5ppNbkREg+qs6s5bnUNdRQmT3FfiKdyK/JVjJMLBUlSE83k0fZFZ u0PQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=WshXke/adPD/p+WKmajaeRbUAwrviqR8m0vly4QQtAM=; b=MdL/IGOoAoug72EjVypKAQmWIMZV1fmAYuNdO2RTY+Ouoth29NsXUn4evoBvjBXy99 mwAyreBeU5TmaLFwYGsKce2a41GWNyW1Vq817R+fRLbWEjRVB6Gv9Myqes+OBtl3FpTq 9FM86va7yYB0W1JXoX9Ua/EO6k1EWIhgvcxhbMKTJCNKWCqah4/M3LEcJymqhKYqWeR4 rVkTFdtitfhAVPNinp6okuYtxlb75U9f3mY0tONvZv0XP0WI17SqXN7mr7keG2Zt7lfI vi3P6dwbcqJh1PTBdCfOGETHBSPOlr7ZTuwOdfag9Uuz0U52dvucp8sRWe4bw4XjTidM XJSg== X-Gm-Message-State: AOAM531xrIBeUwGIUAPwkoMMcSxUWqFEEWORXU+djprLaT8twplG8Y9t 3635w78ihutSze2kGKEm3T9mdw== X-Received: by 2002:a2e:9b0e:: with SMTP id u14mr16309564lji.447.1630242793010; Sun, 29 Aug 2021 06:13:13 -0700 (PDT) Received: from eriador.lan ([37.153.55.125]) by smtp.gmail.com with ESMTPSA id x13sm712503lfq.262.2021.08.29.06.13.12 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 29 Aug 2021 06:13:12 -0700 (PDT) From: Dmitry Baryshkov To: Andy Gross , Bjorn Andersson , Ulf Hansson , Marcel Holtmann , Johan Hedberg , Luiz Augusto von Dentz , Kalle Valo , "David S. Miller" , Jakub Kicinski , Stanimir Varbanov Cc: linux-arm-msm@vger.kernel.org, linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-bluetooth@vger.kernel.org, ath10k@lists.infradead.org, linux-wireless@vger.kernel.org, netdev@vger.kernel.org Subject: [RFC v2 04/13] pwrseq: add support for QCA BT+WiFi power sequencer Date: Sun, 29 Aug 2021 16:12:56 +0300 Message-Id: <20210829131305.534417-5-dmitry.baryshkov@linaro.org> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20210829131305.534417-1-dmitry.baryshkov@linaro.org> References: <20210829131305.534417-1-dmitry.baryshkov@linaro.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org Add support for power sequencer used in the Qualcomm BT+WiFi SoCs. They require several external volate regulators and some of them use separate BT and WiFi enable GPIO pins. This code is mostly extracted from the hci_qca.c bluetooth driver and ath10k WiFi driver. Instead of having each of them manage pins, different requirements, regulator types, move this knowledge to the common power sequencer driver. Currently original drivers are not stripped from the regulator code, this will be done later (to keep compatibility with the old device trees). Signed-off-by: Dmitry Baryshkov --- drivers/power/pwrseq/Kconfig | 14 ++ drivers/power/pwrseq/Makefile | 1 + drivers/power/pwrseq/pwrseq_qca.c | 371 ++++++++++++++++++++++++++++++ 3 files changed, 386 insertions(+) create mode 100644 drivers/power/pwrseq/pwrseq_qca.c -- 2.33.0 diff --git a/drivers/power/pwrseq/Kconfig b/drivers/power/pwrseq/Kconfig index 36339a456b03..990c3164144e 100644 --- a/drivers/power/pwrseq/Kconfig +++ b/drivers/power/pwrseq/Kconfig @@ -19,6 +19,20 @@ config PWRSEQ_EMMC This driver can also be built as a module. If so, the module will be called pwrseq_emmc. +config PWRSEQ_QCA + tristate "Power Sequencer for Qualcomm WiFi + BT SoCs" + depends on OF + help + If you say yes to this option, support will be included for Qualcomm + WCN399x,QCA639x,QCA67xx families of hybrid WiFi and Bluetooth SoCs. + Note, this driver supports only power control for these SoC, you + still have to enable individual Bluetooth and WiFi drivers. This + driver is only necessary on ARM platforms with these chips. PCIe + cards handle power sequencing on their own. + + Say M here if you want to include support for Qualcomm WiFi+BT SoCs + as a module. This will build a module called "pwrseq_qca". + config PWRSEQ_SD8787 tristate "HW reset support for SD8787 BT + Wifi module" depends on OF diff --git a/drivers/power/pwrseq/Makefile b/drivers/power/pwrseq/Makefile index 6f359d228843..556bf5582d47 100644 --- a/drivers/power/pwrseq/Makefile +++ b/drivers/power/pwrseq/Makefile @@ -6,5 +6,6 @@ obj-$(CONFIG_PWRSEQ) += core.o obj-$(CONFIG_PWRSEQ_EMMC) += pwrseq_emmc.o +obj-$(CONFIG_PWRSEQ_QCA) += pwrseq_qca.o obj-$(CONFIG_PWRSEQ_SD8787) += pwrseq_sd8787.o obj-$(CONFIG_PWRSEQ_SIMPLE) += pwrseq_simple.o diff --git a/drivers/power/pwrseq/pwrseq_qca.c b/drivers/power/pwrseq/pwrseq_qca.c new file mode 100644 index 000000000000..7aa5f2d94039 --- /dev/null +++ b/drivers/power/pwrseq/pwrseq_qca.c @@ -0,0 +1,371 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2021, Linaro Ltd. + * + * Author: Dmitry Baryshkov + * + * Power Sequencer for Qualcomm WiFi + BT SoCs + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* susclk rate */ +#define SUSCLK_RATE_32KHZ 32768 + +/* + * Voltage regulator information required for configuring the + * QCA WiFi+Bluetooth chipset + */ +struct qca_vreg { + const char *name; + unsigned int load_uA; +}; + +struct qca_device_data { + bool has_enable_gpios; + + /* + * VDDIO has to be enabled before the rest of regulators, so we treat + * it separately + */ + struct qca_vreg vddio; + + size_t num_vregs; + struct qca_vreg vregs[]; +}; + +struct pwrseq_qca_common { + struct gpio_desc *sw_ctrl; + struct clk *susclk; + + /* + * Again vddio is separate so that it can be enabled before enabling + * other regulators. + */ + struct regulator *vddio; + int num_vregs; + struct regulator_bulk_data vregs[]; +}; + +struct pwrseq_qca_one { + struct pwrseq_qca_common *common; + struct gpio_desc *enable; +}; + +#define PWRSEQ_QCA_WIFI 0 +#define PWRSEQ_QCA_BT 1 + +#define PWRSEQ_QCA_MAX 2 + +struct pwrseq_qca { + struct pwrseq_qca_one pwrseq_qcas[PWRSEQ_QCA_MAX]; + struct pwrseq_qca_common common; +}; + +static int pwrseq_qca_pre_power_on(struct pwrseq *pwrseq) +{ + struct pwrseq_qca_one *qca_one = pwrseq_get_data(pwrseq); + + if (qca_one->enable) { + gpiod_set_value_cansleep(qca_one->enable, 0); + msleep(50); + } + + return 0; +} + +static int pwrseq_qca_power_on(struct pwrseq *pwrseq) +{ + struct pwrseq_qca_one *qca_one = pwrseq_get_data(pwrseq); + int ret; + + if (qca_one->common->vddio) { + ret = regulator_enable(qca_one->common->vddio); + if (ret) + return ret; + } + + ret = regulator_bulk_enable(qca_one->common->num_vregs, qca_one->common->vregs); + if (ret) + goto err_bulk; + + ret = clk_prepare_enable(qca_one->common->susclk); + if (ret) + goto err_clk; + + if (qca_one->enable) { + gpiod_set_value_cansleep(qca_one->enable, 1); + msleep(150); + } + + if (qca_one->common->sw_ctrl) { + bool sw_ctrl_state = gpiod_get_value_cansleep(qca_one->common->sw_ctrl); + dev_dbg(&pwrseq->dev, "SW_CTRL is %d", sw_ctrl_state); + } + + return 0; + +err_clk: + regulator_bulk_disable(qca_one->common->num_vregs, qca_one->common->vregs); +err_bulk: + regulator_disable(qca_one->common->vddio); + + return ret; +} + +static void pwrseq_qca_power_off(struct pwrseq *pwrseq) +{ + struct pwrseq_qca_one *qca_one = pwrseq_get_data(pwrseq); + + if (qca_one->enable) { + gpiod_set_value_cansleep(qca_one->enable, 0); + msleep(50); + } + + clk_disable_unprepare(qca_one->common->susclk); + + regulator_bulk_disable(qca_one->common->num_vregs, qca_one->common->vregs); + regulator_disable(qca_one->common->vddio); + + if (qca_one->common->sw_ctrl) { + bool sw_ctrl_state = gpiod_get_value_cansleep(qca_one->common->sw_ctrl); + dev_dbg(&pwrseq->dev, "SW_CTRL is %d", sw_ctrl_state); + } +} + +static const struct pwrseq_ops pwrseq_qca_ops = { + .pre_power_on = pwrseq_qca_pre_power_on, + .power_on = pwrseq_qca_power_on, + .power_off = pwrseq_qca_power_off, +}; + +static int pwrseq_qca_common_init(struct device *dev, struct pwrseq_qca_common *qca_common, + const struct qca_device_data *data) +{ + int ret, i; + + if (data->vddio.name) { + qca_common->vddio = devm_regulator_get(dev, data->vddio.name); + if (IS_ERR(qca_common->vddio)) + return PTR_ERR(qca_common->vddio); + + ret = regulator_set_load(qca_common->vddio, data->vddio.load_uA); + if (ret) + return ret; + } + + qca_common->num_vregs = data->num_vregs; + + for (i = 0; i < qca_common->num_vregs; i++) + qca_common->vregs[i].supply = data->vregs[i].name; + + ret = devm_regulator_bulk_get(dev, qca_common->num_vregs, qca_common->vregs); + if (ret) + return ret; + + for (i = 0; i < qca_common->num_vregs; i++) { + if (!data->vregs[i].load_uA) + continue; + + ret = regulator_set_load(qca_common->vregs[i].consumer, data->vregs[i].load_uA); + if (ret) + return ret; + } + + qca_common->susclk = devm_clk_get_optional(dev, NULL); + if (IS_ERR(qca_common->susclk)) { + dev_err(dev, "failed to acquire clk\n"); + return PTR_ERR(qca_common->susclk); + } + + qca_common->sw_ctrl = devm_gpiod_get_optional(dev, "swctrl", GPIOD_IN); + if (IS_ERR(qca_common->sw_ctrl)) { + return dev_err_probe(dev, PTR_ERR(qca_common->sw_ctrl), + "failed to acquire SW_CTRL gpio\n"); + } else if (!qca_common->sw_ctrl) + dev_info(dev, "No SW_CTRL gpio\n"); + + return 0; +} + +static void pwrseq_qca_unprepare_susclk(void *data) +{ + struct pwrseq_qca_common *qca_common = data; + + clk_disable_unprepare(qca_common->susclk); +} + +static const struct qca_device_data qca_soc_data_default = { + .num_vregs = 0, + .has_enable_gpios = true, +}; + +static int pwrseq_qca_probe(struct platform_device *pdev) +{ + struct pwrseq_qca *pwrseq_qca; + struct pwrseq *pwrseq; + struct pwrseq_provider *provider; + struct device *dev = &pdev->dev; + struct pwrseq_onecell_data *onecell; + const struct qca_device_data *data; + int ret, i; + + data = device_get_match_data(dev); + if (!data) + data = &qca_soc_data_default; + + pwrseq_qca = devm_kzalloc(dev, struct_size(pwrseq_qca, common.vregs, data->num_vregs), GFP_KERNEL); + if (!pwrseq_qca) + return -ENOMEM; + + onecell = devm_kzalloc(dev, struct_size(onecell, pwrseqs, PWRSEQ_QCA_MAX), GFP_KERNEL); + if (!onecell) + return -ENOMEM; + + ret = pwrseq_qca_common_init(dev, &pwrseq_qca->common, data); + if (ret) + return ret; + + if (data->has_enable_gpios) { + struct gpio_desc *gpiod; + + gpiod = devm_gpiod_get_optional(dev, "wifi-enable", GPIOD_OUT_LOW); + if (IS_ERR(gpiod)) + return dev_err_probe(dev, PTR_ERR(gpiod), "failed to acquire WIFI enable GPIO\n"); + else if (!gpiod) + dev_warn(dev, "No WiFi enable GPIO declared\n"); + + pwrseq_qca->pwrseq_qcas[PWRSEQ_QCA_WIFI].enable = gpiod; + + gpiod = devm_gpiod_get_optional(dev, "bt-enable", GPIOD_OUT_LOW); + if (IS_ERR(gpiod)) + return dev_err_probe(dev, PTR_ERR(gpiod), "failed to acquire BT enable GPIO\n"); + else if (!gpiod) + dev_warn(dev, "No BT enable GPIO declared\n"); + + pwrseq_qca->pwrseq_qcas[PWRSEQ_QCA_BT].enable = gpiod; + } + + /* If we have no control over device's enablement, make sure that sleep clock is always running */ + if (!pwrseq_qca->common.vddio || + !pwrseq_qca->common.num_vregs || + !(pwrseq_qca->pwrseq_qcas[PWRSEQ_QCA_BT].enable && + pwrseq_qca->pwrseq_qcas[PWRSEQ_QCA_WIFI].enable)) { + ret = clk_set_rate(pwrseq_qca->common.susclk, SUSCLK_RATE_32KHZ); + if (ret) + return ret; + + ret = clk_prepare_enable(pwrseq_qca->common.susclk); + if (ret) + return ret; + + ret = devm_add_action_or_reset(dev, pwrseq_qca_unprepare_susclk, &pwrseq_qca->common); + if (ret) + return ret; + } + + for (i = 0; i < PWRSEQ_QCA_MAX; i++) { + pwrseq_qca->pwrseq_qcas[i].common = &pwrseq_qca->common; + + pwrseq = devm_pwrseq_create(dev, &pwrseq_qca_ops, &pwrseq_qca->pwrseq_qcas[i]); + if (IS_ERR(pwrseq)) + return PTR_ERR(pwrseq); + + onecell->pwrseqs[i] = pwrseq; + } + + onecell->num = PWRSEQ_QCA_MAX; + + provider = devm_of_pwrseq_provider_register(dev, of_pwrseq_xlate_onecell, onecell); + + return PTR_ERR_OR_ZERO(provider); +} + +static const struct qca_device_data qca_soc_data_qca6390 = { + .vddio = { "vddio", 20000 }, + .vregs = { + /* 2.0 V */ + { "vddpcie2", 15000 }, + { "vddrfa3", 400000 }, + + /* 0.95 V */ + { "vddaon", 100000 }, + { "vddpmu", 1250000 }, + { "vddrfa1", 200000 }, + + /* 1.35 V */ + { "vddrfa2", 400000 }, + { "vddpcie1", 35000 }, + }, + .num_vregs = 7, + .has_enable_gpios = true, +}; + +/* Shared between wcn3990 and wcn3991 */ +static const struct qca_device_data qca_soc_data_wcn3990 = { + .vddio = { "vddio", 15000 }, + .vregs = { + { "vddxo", 80000 }, + { "vddrf", 300000 }, + { "vddch0", 450000 }, + { "vddch1", 450000 }, + }, + .num_vregs = 4, +}; + +static const struct qca_device_data qca_soc_data_wcn3998 = { + .vddio = { "vddio", 10000 }, + .vregs = { + { "vddxo", 80000 }, + { "vddrf", 300000 }, + { "vddch0", 450000 }, + { "vddch1", 450000 }, + }, + .num_vregs = 4, +}; + +static const struct qca_device_data qca_soc_data_wcn6750 = { + .vddio = { "vddio", 5000 }, + .vregs = { + { "vddaon", 26000 }, + { "vddbtcxmx", 126000 }, + { "vddrfacmn", 12500 }, + { "vddrfa0p8", 102000 }, + { "vddrfa1p7", 302000 }, + { "vddrfa1p2", 257000 }, + { "vddrfa2p2", 1700000 }, + { "vddasd", 200 }, + }, + .num_vregs = 8, + .has_enable_gpios = true, +}; + +static const struct of_device_id pwrseq_qca_of_match[] = { + { .compatible = "qcom,qca6174-pwrseq", }, + { .compatible = "qcom,qca6390-pwrseq", .data = &qca_soc_data_qca6390 }, + { .compatible = "qcom,qca9377-pwrseq" }, + { .compatible = "qcom,wcn3990-pwrseq", .data = &qca_soc_data_wcn3990 }, + { .compatible = "qcom,wcn3991-pwrseq", .data = &qca_soc_data_wcn3990 }, + { .compatible = "qcom,wcn3998-pwrseq", .data = &qca_soc_data_wcn3998 }, + { .compatible = "qcom,wcn6750-pwrseq", .data = &qca_soc_data_wcn6750 }, + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(of, pwrseq_qca_of_match); + +static struct platform_driver pwrseq_qca_driver = { + .probe = pwrseq_qca_probe, + .driver = { + .name = "pwrseq_qca", + .of_match_table = pwrseq_qca_of_match, + }, +}; + +module_platform_driver(pwrseq_qca_driver); +MODULE_LICENSE("GPL v2"); From patchwork Sun Aug 29 13:12:57 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Baryshkov X-Patchwork-Id: 504197 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-18.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2BE42C4320E for ; Sun, 29 Aug 2021 13:14:35 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 11CB760F3A for ; Sun, 29 Aug 2021 13:14:35 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235390AbhH2NPO (ORCPT ); Sun, 29 Aug 2021 09:15:14 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47020 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235386AbhH2NOH (ORCPT ); Sun, 29 Aug 2021 09:14:07 -0400 Received: from mail-lj1-x233.google.com (mail-lj1-x233.google.com [IPv6:2a00:1450:4864:20::233]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7043EC0617A8 for ; Sun, 29 Aug 2021 06:13:15 -0700 (PDT) Received: by mail-lj1-x233.google.com with SMTP id p15so20718713ljn.3 for ; Sun, 29 Aug 2021 06:13:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=kOLT9BadebYXeYAB7hIlHQlCOenxQnkUWJLGubnr1rE=; b=eXVXijIbP24TAYlaMs97dBBt/U2QEctczDjX6jgLsE/+39va8+QbJ3d1g8XTXECnBR jv6X0xYRx9wzh/XMYRccym81uwwlP1jFN8rRs09+hCFR8XDGQIziptoimz2J+G7aLEaz FTtdWGwnHtqnZjm0iR28gqPWjQAuubYJqIOpV7vnxuaPL7VjxcsNHgFyF0fTSofSCdas Cgw2hcG2ClQJs90DhbGMyDD99/nx+UG1XBOk81n9nEJ0fl8A0U1kzLYNfn+S1U/pQxnD /Zm2R7qAggMiYEVrF7HsMShfDo9q+JHJr160fzacnq4ORh+tPTYT+DbxpGZNP19azS01 JQag== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=kOLT9BadebYXeYAB7hIlHQlCOenxQnkUWJLGubnr1rE=; b=ZcHpZP3BD1/F1Ut7X5dG4BAXMTfY0FqNIK2EjVTtsRBol6zP6BYczx3Ve4G0WLMPIz 1c52CmXFSjHN6dYR4qDmgFxhw7cZcweCI8Awp/P6I4GwRaJ06QEdhF5PfTvXaZ3AkBlo MTjXMm8MYuEtqoApvKTUEAR6A1rq0+/nErmSPasHJtZwl9GBxXD+u/NgXX9Vi4esDH2j yeVO4g7s7Rf1H/be7iigY+IsHENFTTiwfH+o+GR/IcEjKFFmsfx2qYqUkjeeoV0uha8U 4clPEB2Rj8aKFSIXxzvEIgwEQsZlCfP96B8M0s9yYIM+2EUulp4dnJv4fAUE63+rVi/F 7fkg== X-Gm-Message-State: AOAM533QJclM3EN/goWhbEL+19Qty+kM9P2fTT1O/plXi5uuJ3XMYDeY 2lY6Nygx4IQTXg03sMNQZLXT9mcH+G2k4Q== X-Google-Smtp-Source: ABdhPJz8h3Dug/hv7iINEs/urnSJJdflsvlIbTNNoxvsJmsBCzWXK5+pypfAp26PxquIGMP1uLb1AQ== X-Received: by 2002:a2e:2417:: with SMTP id k23mr16282098ljk.256.1630242793832; Sun, 29 Aug 2021 06:13:13 -0700 (PDT) Received: from eriador.lan ([37.153.55.125]) by smtp.gmail.com with ESMTPSA id x13sm712503lfq.262.2021.08.29.06.13.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 29 Aug 2021 06:13:13 -0700 (PDT) From: Dmitry Baryshkov To: Andy Gross , Bjorn Andersson , Ulf Hansson , Marcel Holtmann , Johan Hedberg , Luiz Augusto von Dentz , Kalle Valo , "David S. Miller" , Jakub Kicinski , Stanimir Varbanov Cc: linux-arm-msm@vger.kernel.org, linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-bluetooth@vger.kernel.org, ath10k@lists.infradead.org, linux-wireless@vger.kernel.org, netdev@vger.kernel.org Subject: [RFC v2 05/13] pwrseq: add fallback support Date: Sun, 29 Aug 2021 16:12:57 +0300 Message-Id: <20210829131305.534417-6-dmitry.baryshkov@linaro.org> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20210829131305.534417-1-dmitry.baryshkov@linaro.org> References: <20210829131305.534417-1-dmitry.baryshkov@linaro.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org Power sequencer support requires changing device tree. To ease migration to pwrseq, add support for pwrseq 'fallback': let the power sequencer driver register special handler that if matched will create pwrseq instance basing on the consumer device tree data. Signed-off-by: Dmitry Baryshkov --- drivers/power/pwrseq/Makefile | 2 +- drivers/power/pwrseq/core.c | 3 ++ drivers/power/pwrseq/fallback.c | 75 +++++++++++++++++++++++++++++++++ include/linux/pwrseq/fallback.h | 36 ++++++++++++++++ 4 files changed, 115 insertions(+), 1 deletion(-) create mode 100644 drivers/power/pwrseq/fallback.c create mode 100644 include/linux/pwrseq/fallback.h diff --git a/drivers/power/pwrseq/Makefile b/drivers/power/pwrseq/Makefile index 556bf5582d47..949ec848cf00 100644 --- a/drivers/power/pwrseq/Makefile +++ b/drivers/power/pwrseq/Makefile @@ -3,7 +3,7 @@ # Makefile for power sequencer drivers. # -obj-$(CONFIG_PWRSEQ) += core.o +obj-$(CONFIG_PWRSEQ) += core.o fallback.o obj-$(CONFIG_PWRSEQ_EMMC) += pwrseq_emmc.o obj-$(CONFIG_PWRSEQ_QCA) += pwrseq_qca.o diff --git a/drivers/power/pwrseq/core.c b/drivers/power/pwrseq/core.c index 2e4e9d123e60..a43977a0eed8 100644 --- a/drivers/power/pwrseq/core.c +++ b/drivers/power/pwrseq/core.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #define to_pwrseq(a) (container_of((a), struct pwrseq, dev)) @@ -108,6 +109,8 @@ struct pwrseq * __pwrseq_get(struct device *dev, const char *id, bool optional) struct device_link *link; pwrseq = _of_pwrseq_get(dev, id); + if (pwrseq == NULL) + pwrseq = pwrseq_fallback_get(dev, id); if (pwrseq == NULL) return optional ? NULL : ERR_PTR(-ENODEV); else if (IS_ERR(pwrseq)) diff --git a/drivers/power/pwrseq/fallback.c b/drivers/power/pwrseq/fallback.c new file mode 100644 index 000000000000..6ecf24dd8f29 --- /dev/null +++ b/drivers/power/pwrseq/fallback.c @@ -0,0 +1,75 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright 2021 (c) Linaro Ltd. + * Author: Dmitry Baryshkov + */ + +#include +#include +#include +#include +#include +#include + +static DEFINE_MUTEX(pwrseq_fallback_mutex); +static LIST_HEAD(pwrseq_fallback_list); + +int __pwrseq_fallback_register(struct pwrseq_fallback *fallback, struct module *owner) +{ + if (!try_module_get(owner)) + return -EPROBE_DEFER; + + fallback->owner = owner; + + mutex_lock(&pwrseq_fallback_mutex); + list_add_tail(&fallback->list, &pwrseq_fallback_list); + mutex_unlock(&pwrseq_fallback_mutex); + + return 0; +} +EXPORT_SYMBOL_GPL(__pwrseq_fallback_register); + +void pwrseq_fallback_unregister(struct pwrseq_fallback *fallback) +{ + mutex_lock(&pwrseq_fallback_mutex); + list_del(&fallback->list); + mutex_unlock(&pwrseq_fallback_mutex); + + module_put(fallback->owner); + + kfree(fallback); +} +EXPORT_SYMBOL_GPL(pwrseq_fallback_unregister); + +static bool pwrseq_fallback_match(struct device *dev, struct pwrseq_fallback *fallback) +{ + if (of_match_device(fallback->of_match_table, dev) != NULL) + return true; + + /* We might add support for other matching options later */ + + return false; +} + +struct pwrseq *pwrseq_fallback_get(struct device *dev, const char *id) +{ + struct pwrseq_fallback *fallback; + struct pwrseq *pwrseq = ERR_PTR(-ENODEV); + + mutex_lock(&pwrseq_fallback_mutex); + + list_for_each_entry(fallback, &pwrseq_fallback_list, list) { + if (!pwrseq_fallback_match(dev, fallback)) + continue; + + pwrseq = fallback->get(dev, id); + break; + } + + mutex_unlock(&pwrseq_fallback_mutex); + + if (!IS_ERR_OR_NULL(pwrseq)) + dev_warn(dev, "legacy pwrseq support used for the device\n"); + + return pwrseq; +} diff --git a/include/linux/pwrseq/fallback.h b/include/linux/pwrseq/fallback.h new file mode 100644 index 000000000000..616049df179f --- /dev/null +++ b/include/linux/pwrseq/fallback.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (c) 2021 Linaro Ltd. + */ + +#ifndef __LINUX_PWRSEQ_FALLBACK_H__ +#define __LINUX_PWRSEQ_FALLBACK_H__ + +#include + +struct pwrseq; + +struct device; +struct module; +struct of_device_id; + +struct pwrseq_fallback { + struct list_head list; + struct module *owner; + + const struct of_device_id *of_match_table; + + struct pwrseq *(*get)(struct device *dev, const char *id); +}; + +/* provider interface */ + +int __pwrseq_fallback_register(struct pwrseq_fallback *fallback, struct module *owner); +#define pwrseq_fallback_register(fallback) __pwrseq_fallback_register(fallback, THIS_MODULE) + +void pwrseq_fallback_unregister(struct pwrseq_fallback *fallback); + +/* internal interface */ +struct pwrseq *pwrseq_fallback_get(struct device *dev, const char *id); + +#endif /* __LINUX_PWRSEQ_DRIVER_H__ */ From patchwork Sun Aug 29 13:12:58 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Baryshkov X-Patchwork-Id: 504198 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-18.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 742F6C432BE for ; Sun, 29 Aug 2021 13:14:23 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 60FB36023E for ; Sun, 29 Aug 2021 13:14:23 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235548AbhH2NPN (ORCPT ); Sun, 29 Aug 2021 09:15:13 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47008 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235467AbhH2NOI (ORCPT ); Sun, 29 Aug 2021 09:14:08 -0400 Received: from mail-lf1-x134.google.com (mail-lf1-x134.google.com [IPv6:2a00:1450:4864:20::134]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2A525C06175F for ; Sun, 29 Aug 2021 06:13:16 -0700 (PDT) Received: by mail-lf1-x134.google.com with SMTP id s10so424850lfr.11 for ; Sun, 29 Aug 2021 06:13:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=W90zCRw/gyIjKh5bN6AdA5a45jbpL+6W+rmSnj/xdRc=; b=MGtT4oebKOHyJUzHFk/GStnDRBlucvXQUdsvl3KqvG83GLCtg/sscD7aUZINgsWWxR mry9SHUjRz6j/EVknFswB9UJeqJc+HnyQYofSptX+47CH9Ql58haBaYJs90uxm4l2ATF HZVJLqaBdi40E8oRdmm2DKIQwzwImyoA5skuvtj15Bv9dhyyYqaJ9LbM8Eh6md+hckVJ ktYNRzdmui0t6n855ydf+ooRalLokWct1cGpCbqeYE3xHBu6sbMZC+6WmTmouvLOH/DQ VsHIFmJZWcKV4tYEZ1LMdwxFFSQaDPf3/4zqG4nB9OBSNwV1dkGh3RLs9xXTAFUsHS79 Styg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=W90zCRw/gyIjKh5bN6AdA5a45jbpL+6W+rmSnj/xdRc=; b=KJzFUoQ87y6m3pdEwry9LKWzt3n3A5FS3GKf9lxCxkqtd82wv7Wq6TFwL8GVJptpT4 73iac41Sd0wLgcvR9vDrpIQTxE1OltwcBDRpAUtD5w8bUvqP0b58M54dnUqmxa9OWAH1 EJr8P9qSSXslJjJwkW3ozB41SSOhwPZGe7Fqq7E51kny4/WUeGkdC6MtK8uqeRoJHOWS nNO0DwnGucDSypOezcFt/YUL9XICGuvY1HpL5jp0bLtvQi7xbYM9deXJSiUhNf2K7v0+ 8MWDHvl/aDo4jR5xtdSQjz+cW569j/0t/5V2emXHY+/0uNSD8MwWE5HF5GjRQ8w1N6ID hj+A== X-Gm-Message-State: AOAM530g2xp/XjGL8IfOmoFBDmxMDoXqOar/OnZDoXFQAmPnsnqcnuW+ N4egObuXLgRfmYG157W6u4QdVw== X-Google-Smtp-Source: ABdhPJz8ss1hZf/h7XEdWNe+VXrVLZ8dFiYzYa9JHOoN8i2WkbHCSfq9a7aQ5moet2JaOib5Pq53hA== X-Received: by 2002:a05:6512:21d1:: with SMTP id d17mr14594374lft.588.1630242794541; Sun, 29 Aug 2021 06:13:14 -0700 (PDT) Received: from eriador.lan ([37.153.55.125]) by smtp.gmail.com with ESMTPSA id x13sm712503lfq.262.2021.08.29.06.13.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 29 Aug 2021 06:13:14 -0700 (PDT) From: Dmitry Baryshkov To: Andy Gross , Bjorn Andersson , Ulf Hansson , Marcel Holtmann , Johan Hedberg , Luiz Augusto von Dentz , Kalle Valo , "David S. Miller" , Jakub Kicinski , Stanimir Varbanov Cc: linux-arm-msm@vger.kernel.org, linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-bluetooth@vger.kernel.org, ath10k@lists.infradead.org, linux-wireless@vger.kernel.org, netdev@vger.kernel.org Subject: [RFC v2 06/13] pwrseq: pwrseq_qca: implement fallback support Date: Sun, 29 Aug 2021 16:12:58 +0300 Message-Id: <20210829131305.534417-7-dmitry.baryshkov@linaro.org> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20210829131305.534417-1-dmitry.baryshkov@linaro.org> References: <20210829131305.534417-1-dmitry.baryshkov@linaro.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org While we are waiting for all users of wcn399x-bt to be converted to the pwrseq declaration in the device tree, provide support for the pwrseq fallback: if the regulators are declared in the device itself, create pwrseq instance. This way the hci_qca driver doesn't have to cope with old and new dts bindings. Signed-off-by: Dmitry Baryshkov --- drivers/power/pwrseq/pwrseq_qca.c | 148 +++++++++++++++++++++++++++++- 1 file changed, 147 insertions(+), 1 deletion(-) diff --git a/drivers/power/pwrseq/pwrseq_qca.c b/drivers/power/pwrseq/pwrseq_qca.c index 7aa5f2d94039..d01f1ef4626b 100644 --- a/drivers/power/pwrseq/pwrseq_qca.c +++ b/drivers/power/pwrseq/pwrseq_qca.c @@ -11,9 +11,11 @@ #include #include #include +#include #include #include #include +#include #include /* susclk rate */ @@ -367,5 +369,149 @@ static struct platform_driver pwrseq_qca_driver = { }, }; -module_platform_driver(pwrseq_qca_driver); +struct pwrseq_qca_fallback { + struct pwrseq_qca_one qca_one; + struct pwrseq_qca_common common; +}; + +static const struct of_device_id pwrseq_qca_bt_of_match[] = { + { .compatible = "qcom,qca6174-bt" }, + { .compatible = "qcom,qca6390-bt", .data = &qca_soc_data_qca6390}, + { .compatible = "qcom,qca9377-bt" }, + { .compatible = "qcom,wcn3990-bt", .data = &qca_soc_data_wcn3990 }, + { .compatible = "qcom,wcn3991-bt", .data = &qca_soc_data_wcn3990 }, + { .compatible = "qcom,wcn3998-bt", .data = &qca_soc_data_wcn3998 }, + { .compatible = "qcom,wcn6750-bt", .data = &qca_soc_data_wcn6750 }, + { /* sentinel */ }, +}; + +static const struct qca_device_data qca_soc_data_wifi = { + .vregs = { + { "vdd-1.8-xo", 80000 }, + { "vdd-1.3-rfa", 300000 }, + { "vdd-3.3-ch0", 450000 }, + { "vdd-3.3-ch1", 450000 }, + }, + .num_vregs = 4, +}; + +static const struct of_device_id pwrseq_qca_wifi_of_match[] = { + { .compatible = "qcom,wcn3990-wifi", .data = &qca_soc_data_wifi }, + { /* sentinel */ } +}; + +static struct pwrseq * pwrseq_qca_fallback_get(struct device *dev) +{ + struct pwrseq_qca_fallback *fallback; + const struct of_device_id *match; + const struct qca_device_data *data; + struct gpio_desc *gpiod; + int ret; + + match = of_match_device(pwrseq_qca_bt_of_match, dev); + if (!match) + return ERR_PTR(-ENODEV); + + data = match->data; + if (!data) + data = &qca_soc_data_default; + + fallback = devm_kzalloc(dev, struct_size(fallback, common.vregs, data->num_vregs), GFP_KERNEL); + if (!data) + return ERR_PTR(-ENOMEM); + + fallback->qca_one.common = &fallback->common; + + ret = pwrseq_qca_common_init(dev, &fallback->common, data); + if (ret) + return ERR_PTR(ret); + + if (data->has_enable_gpios) { + gpiod = devm_gpiod_get(dev, "enable", GPIOD_OUT_LOW); + if (IS_ERR(gpiod)) + return ERR_PTR(dev_err_probe(dev, PTR_ERR(gpiod), "failed to acquire enable GPIO\n")); + fallback->qca_one.enable = gpiod; + } + + /* If we have no control over device's enablement, make sure that sleep clock is always running */ + if (!fallback->common.vddio || + !fallback->common.num_vregs || + !fallback->qca_one.enable) { + ret = clk_set_rate(fallback->common.susclk, SUSCLK_RATE_32KHZ); + if (ret) + return ERR_PTR(ret); + + ret = clk_prepare_enable(fallback->common.susclk); + if (ret) + return ERR_PTR(ret); + + ret = devm_add_action_or_reset(dev, pwrseq_qca_unprepare_susclk, &fallback->common); + if (ret) + return ERR_PTR(ret); + } + + return devm_pwrseq_create(dev, &pwrseq_qca_ops, &fallback->qca_one); +} + +static struct pwrseq * pwrseq_qca_fallback_get_bt(struct device *dev, const char *id) +{ + if (strcmp(id, "bt")) + return ERR_PTR(-ENODEV); + + return pwrseq_qca_fallback_get(dev); +} + +static struct pwrseq * pwrseq_qca_fallback_get_wifi(struct device *dev, const char *id) +{ + if (strcmp(id, "wifi")) + return ERR_PTR(-ENODEV); + + return pwrseq_qca_fallback_get(dev); +} + +static struct pwrseq_fallback pwrseq_qca_fallback_bt = { + .get = pwrseq_qca_fallback_get_bt, + .of_match_table = pwrseq_qca_bt_of_match, +}; + +static struct pwrseq_fallback pwrseq_qca_fallback_wifi = { + .get = pwrseq_qca_fallback_get_wifi, + .of_match_table = pwrseq_qca_wifi_of_match, +}; + +static int __init pwrseq_qca_init(void) +{ + int ret; + + ret = platform_driver_register(&pwrseq_qca_driver); + if (ret) + return ret; + + ret = pwrseq_fallback_register(&pwrseq_qca_fallback_bt); + if (ret) + goto err_bt; + + ret = pwrseq_fallback_register(&pwrseq_qca_fallback_wifi); + if (ret) + goto err_wifi; + + return 0; + +err_wifi: + pwrseq_fallback_unregister(&pwrseq_qca_fallback_bt); +err_bt: + platform_driver_unregister(&pwrseq_qca_driver); + + return ret; +} +module_init(pwrseq_qca_init); + +static void __exit pwrseq_qca_exit(void) +{ + pwrseq_fallback_unregister(&pwrseq_qca_fallback_wifi); + pwrseq_fallback_unregister(&pwrseq_qca_fallback_bt); + platform_driver_unregister(&pwrseq_qca_driver); +} +module_exit(pwrseq_qca_exit); + MODULE_LICENSE("GPL v2"); From patchwork Sun Aug 29 13:12:59 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Baryshkov X-Patchwork-Id: 504056 Delivered-To: patch@linaro.org Received: by 2002:a02:8629:0:0:0:0:0 with SMTP id e38csp927366jai; Sun, 29 Aug 2021 06:14:19 -0700 (PDT) X-Google-Smtp-Source: ABdhPJzoJ2lqWL0cd0YYQeDuCJ8sekg5mlTAMlWo2uWg2fsZQClorpeq0Mp5IMsJww1W60HgKoso X-Received: by 2002:a92:ce03:: with SMTP id b3mr12968886ilo.267.1630242859813; Sun, 29 Aug 2021 06:14:19 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1630242859; cv=none; d=google.com; s=arc-20160816; b=o9/o/d7FGsDN3If3g1vOLASNSTIvOvIchspfbdKhmhau6Tg4g6bODr9z5saS832PUj JhsaFpRsmI57JG6evZ3P1iBg3cdMdnPbCduAS/DE7q9KoU0hzCYntCCEKwq1LipTHcnN SYmTbUJnSmrYGroeVyfXPxpsfgeLWAMp9pNC6tCAIX+BuG1wKys6NBEvPLEv0qJ9IPLt UY6bcfcJYPmXQKKRuJv3K79eygbVUWS6Hig0+Lrc7vzWECUJv1FxSk4efjhlULIB4qqy RG2rKMMtyEZbsP54vgUtbTa5s6nE2KcaLuR8p2HzZKoSWac0zxEPeLSNLHnvHm9eeM2V kX/A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=gdZGnwzEHVfU1lQviDSHFvhmNm98xNMbizrp42xP5ec=; b=1EWwAab2+MTlUKhDpoxFCMp0NcxhQ831C60Lb9c6pzvPCBGHe6/ag8x7/ziuaaTHIZ sR4NNfIjNfXUV4+wUcCETvVMn4k0OS6+eYZ0dryzZPwUBMeZVKXT+UJsxmOSuy78yuj/ f4bJLdynh+lXqzaFzEejfnu1epGXK/rUczzO8f9bCK/xlI3Gfonwy+ruUb98fPOGvjcI AWOtfPgSIwCGMY/4v3nD+auK6aaCEKAjzP0n7XePJjMLCcLuXWcXpzhqqXfe9XY8yZPe LdQy7biqD8GK3d4NM3jvsdbcg9ovLFaluVSGSt9DlWx/rg92dEo//+opYRtfjarLdb1m EWzA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=UokfyIpM; spf=pass (google.com: domain of linux-mmc-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-mmc-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id n3si12867009ioh.98.2021.08.29.06.14.18; Sun, 29 Aug 2021 06:14:19 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-mmc-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=UokfyIpM; spf=pass (google.com: domain of linux-mmc-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-mmc-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235676AbhH2NPJ (ORCPT + 3 others); Sun, 29 Aug 2021 09:15:09 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47028 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235474AbhH2NOJ (ORCPT ); Sun, 29 Aug 2021 09:14:09 -0400 Received: from mail-lj1-x22d.google.com (mail-lj1-x22d.google.com [IPv6:2a00:1450:4864:20::22d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0F54DC061292 for ; Sun, 29 Aug 2021 06:13:17 -0700 (PDT) Received: by mail-lj1-x22d.google.com with SMTP id c12so20745665ljr.5 for ; Sun, 29 Aug 2021 06:13:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=gdZGnwzEHVfU1lQviDSHFvhmNm98xNMbizrp42xP5ec=; b=UokfyIpM+vjrkS6Rz5X3836JY8QaZc8srNRwNGsKSzrkJxRSLfQiiK0TvOQaGTC599 R7niZ/jIWguW0cMTLNDguWkDkFSaHGHNRwnFk8pGrnzbsYhbDcnWIHBztBxpfZrr5P6i 3KJBfAJNUz0o8GptHt6piSYNBPOEBrAngYh5h+U2HtvGi/zlO4FkmOFFZq/aZuWDhA5f SEUJB7NjfnGs8CMK/EWh1aVL/HplOSVrVK1UMnNmvOLRXfWIVTuveeKjX18VUovqbwdX otHxBpuo0xDwXASLSxeiHR8PXJj4z9yHNQw2wGbk571v6REiXYo4b7TOBpMkfq5H6csd 2wow== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=gdZGnwzEHVfU1lQviDSHFvhmNm98xNMbizrp42xP5ec=; b=Rxd0lhDcq2KTNiFc+hI6hHs4c1MRZS1vRTbRPHkxpg302hP7C4XLaT8jCtwK9kBll3 of4nLzSeqJR+IOiyhl1h8wkFmARHIa4ZmHs3HYPjDKE9NR+4TOFJ87/grKY4vuyXb9yi N3et8DkQg2DyocObVfqK578QZ+HC5eJzJDakPhjo4kMAW5p7CI1y2VV9fdpuqBhIGSOa YYfmGLXYl75HZASQcabl+reYmBYr9UIEngm9BCGYg60Tnpyfts5L97zg3S8VtBuS4leQ leTdnlZwiZA+2Xb/R5H8lZuBJtmD5j3Gl6RlVMDtMYvmpVEwymhPwcEmw8uQCnuL+3az Lh0Q== X-Gm-Message-State: AOAM532ZdkU5CoT6U8ZTYsxIwl7EmHq3xMFDKv4yaVaqRoB6mdZZCDFV jPTdGLkB9DrGlu9L35uelVlcGw== X-Received: by 2002:a2e:a30d:: with SMTP id l13mr16482973lje.193.1630242795389; Sun, 29 Aug 2021 06:13:15 -0700 (PDT) Received: from eriador.lan ([37.153.55.125]) by smtp.gmail.com with ESMTPSA id x13sm712503lfq.262.2021.08.29.06.13.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 29 Aug 2021 06:13:15 -0700 (PDT) From: Dmitry Baryshkov To: Andy Gross , Bjorn Andersson , Ulf Hansson , Marcel Holtmann , Johan Hedberg , Luiz Augusto von Dentz , Kalle Valo , "David S. Miller" , Jakub Kicinski , Stanimir Varbanov Cc: linux-arm-msm@vger.kernel.org, linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-bluetooth@vger.kernel.org, ath10k@lists.infradead.org, linux-wireless@vger.kernel.org, netdev@vger.kernel.org Subject: [RFC v2 07/13] Bluetooth: hci_qca: switch to using pwrseq Date: Sun, 29 Aug 2021 16:12:59 +0300 Message-Id: <20210829131305.534417-8-dmitry.baryshkov@linaro.org> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20210829131305.534417-1-dmitry.baryshkov@linaro.org> References: <20210829131305.534417-1-dmitry.baryshkov@linaro.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org Signed-off-by: Dmitry Baryshkov --- drivers/bluetooth/hci_qca.c | 260 +++++------------------------------- 1 file changed, 37 insertions(+), 223 deletions(-) -- 2.33.0 diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index 53deea2eb7b4..1e4416916533 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c @@ -16,19 +16,17 @@ */ #include -#include #include #include #include #include #include -#include #include #include #include #include #include -#include +#include #include #include #include @@ -54,9 +52,6 @@ (MEMDUMP_TIMEOUT_MS + FW_DOWNLOAD_TIMEOUT_MS) #define FW_DOWNLOAD_TIMEOUT_MS 3000 -/* susclk rate */ -#define SUSCLK_RATE_32KHZ 32768 - /* Controller debug log header */ #define QCA_DEBUG_HANDLE 0x2EDC @@ -200,28 +195,17 @@ struct qca_vreg { struct qca_device_data { enum qca_btsoc_type soc_type; - struct qca_vreg *vregs; - size_t num_vregs; uint32_t capabilities; }; /* * Platform data for the QCA Bluetooth power driver. */ -struct qca_power { - struct device *dev; - struct regulator_bulk_data *vreg_bulk; - int num_vregs; - bool vregs_on; -}; - struct qca_serdev { struct hci_uart serdev_hu; - struct gpio_desc *bt_en; - struct gpio_desc *sw_ctrl; - struct clk *susclk; enum qca_btsoc_type btsoc_type; - struct qca_power *bt_power; + struct pwrseq *pwrseq; + bool vregs_on; u32 init_speed; u32 oper_speed; const char *firmware_name; @@ -1596,13 +1580,12 @@ static int qca_regulator_init(struct hci_uart *hu) enum qca_btsoc_type soc_type = qca_soc_type(hu); struct qca_serdev *qcadev; int ret; - bool sw_ctrl_state; /* Check for vregs status, may be hci down has turned * off the voltage regulator. */ qcadev = serdev_device_get_drvdata(hu->serdev); - if (!qcadev->bt_power->vregs_on) { + if (!qcadev->vregs_on) { serdev_device_close(hu->serdev); ret = qca_regulator_enable(qcadev); if (ret) @@ -1623,19 +1606,9 @@ static int qca_regulator_init(struct hci_uart *hu) return ret; } - /* For wcn6750 need to enable gpio bt_en */ - if (qcadev->bt_en) { - gpiod_set_value_cansleep(qcadev->bt_en, 0); - msleep(50); - gpiod_set_value_cansleep(qcadev->bt_en, 1); - msleep(50); - if (qcadev->sw_ctrl) { - sw_ctrl_state = gpiod_get_value_cansleep(qcadev->sw_ctrl); - bt_dev_dbg(hu->hdev, "SW_CTRL is %d", sw_ctrl_state); - } - } - - qca_set_speed(hu, QCA_INIT_SPEED); + if (qca_is_wcn399x(soc_type) || + qca_is_wcn6750(soc_type)) + qca_set_speed(hu, QCA_INIT_SPEED); if (qca_is_wcn399x(soc_type)) { ret = qca_send_power_pulse(hu, true); @@ -1655,7 +1628,9 @@ static int qca_regulator_init(struct hci_uart *hu) return ret; } - hci_uart_set_flow_control(hu, false); + if (qca_is_wcn399x(soc_type) || + qca_is_wcn6750(soc_type)) + hci_uart_set_flow_control(hu, false); return 0; } @@ -1663,8 +1638,6 @@ static int qca_regulator_init(struct hci_uart *hu) static int qca_power_on(struct hci_dev *hdev) { struct hci_uart *hu = hci_get_drvdata(hdev); - enum qca_btsoc_type soc_type = qca_soc_type(hu); - struct qca_serdev *qcadev; struct qca_data *qca = hu->priv; int ret = 0; @@ -1674,17 +1647,7 @@ static int qca_power_on(struct hci_dev *hdev) if (!hu->serdev) return 0; - if (qca_is_wcn399x(soc_type) || - qca_is_wcn6750(soc_type)) { - ret = qca_regulator_init(hu); - } else { - qcadev = serdev_device_get_drvdata(hu->serdev); - if (qcadev->bt_en) { - gpiod_set_value_cansleep(qcadev->bt_en, 1); - /* Controller needs time to bootup. */ - msleep(150); - } - } + ret = qca_regulator_init(hu); clear_bit(QCA_BT_OFF, &qca->flags); return ret; @@ -1820,57 +1783,23 @@ static const struct hci_uart_proto qca_proto = { static const struct qca_device_data qca_soc_data_wcn3990 = { .soc_type = QCA_WCN3990, - .vregs = (struct qca_vreg []) { - { "vddio", 15000 }, - { "vddxo", 80000 }, - { "vddrf", 300000 }, - { "vddch0", 450000 }, - }, - .num_vregs = 4, }; static const struct qca_device_data qca_soc_data_wcn3991 = { .soc_type = QCA_WCN3991, - .vregs = (struct qca_vreg []) { - { "vddio", 15000 }, - { "vddxo", 80000 }, - { "vddrf", 300000 }, - { "vddch0", 450000 }, - }, - .num_vregs = 4, .capabilities = QCA_CAP_WIDEBAND_SPEECH | QCA_CAP_VALID_LE_STATES, }; static const struct qca_device_data qca_soc_data_wcn3998 = { .soc_type = QCA_WCN3998, - .vregs = (struct qca_vreg []) { - { "vddio", 10000 }, - { "vddxo", 80000 }, - { "vddrf", 300000 }, - { "vddch0", 450000 }, - }, - .num_vregs = 4, }; static const struct qca_device_data qca_soc_data_qca6390 = { .soc_type = QCA_QCA6390, - .num_vregs = 0, }; static const struct qca_device_data qca_soc_data_wcn6750 = { .soc_type = QCA_WCN6750, - .vregs = (struct qca_vreg []) { - { "vddio", 5000 }, - { "vddaon", 26000 }, - { "vddbtcxmx", 126000 }, - { "vddrfacmn", 12500 }, - { "vddrfa0p8", 102000 }, - { "vddrfa1p7", 302000 }, - { "vddrfa1p2", 257000 }, - { "vddrfa2p2", 1700000 }, - { "vddasd", 200 }, - }, - .num_vregs = 9, .capabilities = QCA_CAP_WIDEBAND_SPEECH | QCA_CAP_VALID_LE_STATES, }; @@ -1880,7 +1809,6 @@ static void qca_power_shutdown(struct hci_uart *hu) struct qca_data *qca = hu->priv; unsigned long flags; enum qca_btsoc_type soc_type = qca_soc_type(hu); - bool sw_ctrl_state; /* From this point we go into power off state. But serial port is * still open, stop queueing the IBS data and flush all the buffered @@ -1902,19 +1830,10 @@ static void qca_power_shutdown(struct hci_uart *hu) if (qca_is_wcn399x(soc_type)) { host_set_baudrate(hu, 2400); qca_send_power_pulse(hu, false); - qca_regulator_disable(qcadev); - } else if (soc_type == QCA_WCN6750) { - gpiod_set_value_cansleep(qcadev->bt_en, 0); - msleep(100); - qca_regulator_disable(qcadev); - if (qcadev->sw_ctrl) { - sw_ctrl_state = gpiod_get_value_cansleep(qcadev->sw_ctrl); - bt_dev_dbg(hu->hdev, "SW_CTRL is %d", sw_ctrl_state); - } - } else if (qcadev->bt_en) { - gpiod_set_value_cansleep(qcadev->bt_en, 0); } + qca_regulator_disable(qcadev); + set_bit(QCA_BT_OFF, &qca->flags); } @@ -1940,75 +1859,34 @@ static int qca_power_off(struct hci_dev *hdev) static int qca_regulator_enable(struct qca_serdev *qcadev) { - struct qca_power *power = qcadev->bt_power; int ret; /* Already enabled */ - if (power->vregs_on) + if (qcadev->vregs_on) return 0; - BT_DBG("enabling %d regulators)", power->num_vregs); + BT_DBG("enabling regulators)"); - ret = regulator_bulk_enable(power->num_vregs, power->vreg_bulk); + ret = pwrseq_full_power_on(qcadev->pwrseq); if (ret) return ret; - power->vregs_on = true; - - ret = clk_prepare_enable(qcadev->susclk); - if (ret) - qca_regulator_disable(qcadev); + qcadev->vregs_on = true; return ret; } static void qca_regulator_disable(struct qca_serdev *qcadev) { - struct qca_power *power; - if (!qcadev) return; - power = qcadev->bt_power; - /* Already disabled? */ - if (!power->vregs_on) + if (!qcadev->vregs_on) return; - regulator_bulk_disable(power->num_vregs, power->vreg_bulk); - power->vregs_on = false; - - clk_disable_unprepare(qcadev->susclk); -} - -static int qca_init_regulators(struct qca_power *qca, - const struct qca_vreg *vregs, size_t num_vregs) -{ - struct regulator_bulk_data *bulk; - int ret; - int i; - - bulk = devm_kcalloc(qca->dev, num_vregs, sizeof(*bulk), GFP_KERNEL); - if (!bulk) - return -ENOMEM; - - for (i = 0; i < num_vregs; i++) - bulk[i].supply = vregs[i].name; - - ret = devm_regulator_bulk_get(qca->dev, num_vregs, bulk); - if (ret < 0) - return ret; - - for (i = 0; i < num_vregs; i++) { - ret = regulator_set_load(bulk[i].consumer, vregs[i].load_uA); - if (ret) - return ret; - } - - qca->vreg_bulk = bulk; - qca->num_vregs = num_vregs; - - return 0; + pwrseq_power_off(qcadev->pwrseq); + qcadev->vregs_on = false; } static int qca_serdev_probe(struct serdev_device *serdev) @@ -2017,7 +1895,6 @@ static int qca_serdev_probe(struct serdev_device *serdev) struct hci_dev *hdev; const struct qca_device_data *data; int err; - bool power_ctrl_enabled = true; qcadev = devm_kzalloc(&serdev->dev, sizeof(*qcadev), GFP_KERNEL); if (!qcadev) @@ -2033,89 +1910,29 @@ static int qca_serdev_probe(struct serdev_device *serdev) if (!qcadev->oper_speed) BT_DBG("UART will pick default operating speed"); - if (data && - (qca_is_wcn399x(data->soc_type) || - qca_is_wcn6750(data->soc_type))) { - qcadev->btsoc_type = data->soc_type; - qcadev->bt_power = devm_kzalloc(&serdev->dev, - sizeof(struct qca_power), - GFP_KERNEL); - if (!qcadev->bt_power) - return -ENOMEM; - - qcadev->bt_power->dev = &serdev->dev; - err = qca_init_regulators(qcadev->bt_power, data->vregs, - data->num_vregs); - if (err) { - BT_ERR("Failed to init regulators:%d", err); - return err; - } - - qcadev->bt_power->vregs_on = false; - - qcadev->bt_en = devm_gpiod_get_optional(&serdev->dev, "enable", - GPIOD_OUT_LOW); - if (!qcadev->bt_en && data->soc_type == QCA_WCN6750) { - dev_err(&serdev->dev, "failed to acquire BT_EN gpio\n"); - power_ctrl_enabled = false; - } - qcadev->sw_ctrl = devm_gpiod_get_optional(&serdev->dev, "swctrl", - GPIOD_IN); - if (!qcadev->sw_ctrl && data->soc_type == QCA_WCN6750) - dev_warn(&serdev->dev, "failed to acquire SW_CTRL gpio\n"); - - qcadev->susclk = devm_clk_get_optional(&serdev->dev, NULL); - if (IS_ERR(qcadev->susclk)) { - dev_err(&serdev->dev, "failed to acquire clk\n"); - return PTR_ERR(qcadev->susclk); - } - - err = hci_uart_register_device(&qcadev->serdev_hu, &qca_proto); - if (err) { - BT_ERR("wcn3990 serdev registration failed"); - return err; - } - } else { - if (data) - qcadev->btsoc_type = data->soc_type; - else - qcadev->btsoc_type = QCA_ROME; + if (data) + qcadev->btsoc_type = data->soc_type; + else + qcadev->btsoc_type = QCA_ROME; - qcadev->bt_en = devm_gpiod_get_optional(&serdev->dev, "enable", - GPIOD_OUT_LOW); - if (!qcadev->bt_en) { - dev_warn(&serdev->dev, "failed to acquire enable gpio\n"); - power_ctrl_enabled = false; - } + qcadev->pwrseq = devm_pwrseq_get(&serdev->dev, "bt"); + if (IS_ERR(qcadev->pwrseq)) { + dev_err(&serdev->dev, "failed to acquire pwrseq\n"); + return PTR_ERR(qcadev->pwrseq); + } + qcadev->vregs_on = false; - qcadev->susclk = devm_clk_get_optional(&serdev->dev, NULL); - if (IS_ERR(qcadev->susclk)) { - dev_warn(&serdev->dev, "failed to acquire clk\n"); - return PTR_ERR(qcadev->susclk); - } - err = clk_set_rate(qcadev->susclk, SUSCLK_RATE_32KHZ); - if (err) - return err; - - err = clk_prepare_enable(qcadev->susclk); - if (err) - return err; - - err = hci_uart_register_device(&qcadev->serdev_hu, &qca_proto); - if (err) { - BT_ERR("Rome serdev registration failed"); - clk_disable_unprepare(qcadev->susclk); - return err; - } + err = hci_uart_register_device(&qcadev->serdev_hu, &qca_proto); + if (err) { + BT_ERR("wcn3990 serdev registration failed"); + return err; } hdev = qcadev->serdev_hu.hdev; - if (power_ctrl_enabled) { - set_bit(HCI_QUIRK_NON_PERSISTENT_SETUP, &hdev->quirks); - hdev->shutdown = qca_power_off; - } + set_bit(HCI_QUIRK_NON_PERSISTENT_SETUP, &hdev->quirks); + hdev->shutdown = qca_power_off; if (data) { /* Wideband speech support must be set per driver since it can't @@ -2135,14 +1952,11 @@ static int qca_serdev_probe(struct serdev_device *serdev) static void qca_serdev_remove(struct serdev_device *serdev) { struct qca_serdev *qcadev = serdev_device_get_drvdata(serdev); - struct qca_power *power = qcadev->bt_power; if ((qca_is_wcn399x(qcadev->btsoc_type) || qca_is_wcn6750(qcadev->btsoc_type)) && - power->vregs_on) + qcadev->vregs_on) qca_power_shutdown(&qcadev->serdev_hu); - else if (qcadev->susclk) - clk_disable_unprepare(qcadev->susclk); hci_uart_unregister_device(&qcadev->serdev_hu); } From patchwork Sun Aug 29 13:13:01 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Baryshkov X-Patchwork-Id: 504200 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-18.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 04A00C4320E for ; Sun, 29 Aug 2021 13:14:02 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id E245460F44 for ; Sun, 29 Aug 2021 13:14:01 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235529AbhH2NOw (ORCPT ); Sun, 29 Aug 2021 09:14:52 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47048 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235511AbhH2NOL (ORCPT ); Sun, 29 Aug 2021 09:14:11 -0400 Received: from mail-lf1-x132.google.com (mail-lf1-x132.google.com [IPv6:2a00:1450:4864:20::132]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9052EC0612AF for ; Sun, 29 Aug 2021 06:13:18 -0700 (PDT) Received: by mail-lf1-x132.google.com with SMTP id bq28so25247976lfb.7 for ; Sun, 29 Aug 2021 06:13:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=L38kgQv//emLd4ZPZWGNBDSkLJU2AA0/25feolL0iIY=; b=PKOPo4eo6O7r2pbSVyV6dlmRizAKPHv8Gsi1JEwGmBrBuRsuag0tYpek2/JgmUOwQI eVFwhDETUXPLgR8sqFRnl1Q/NXsfBaalYtozrjVt1zSW4vhaaLwkiOkdqVy7n4hNzstj 4Kr8V+J00IjPN7i9vl4uwT7qwydvj33nnjbnDXSIVf2runmfYgKiJ5rbl7rGo4kWgT8/ QARJ+34wCmWZT3/MmpDRYMF8tOsKV8N5bV8r1nh60A0q4JBOwdzpM7PkX0YVIWfwTzIS cu/p6/61SkR9cLiDvx36/rJC00sTqlp+HtOapdQaMvI53wVJlbTYPoF/YZz5nllo64ET MjmQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=L38kgQv//emLd4ZPZWGNBDSkLJU2AA0/25feolL0iIY=; b=Z5PFpS0+Y+IBW2+qdMOewwySEwTUqVkMHFOcFgWNPy34lQvvP3Z+jh+oTDehgqDy61 mcBW5SiQ6PX1tor8md/TwlVl0NUf0+3t1nfB2sT995s1vzCHrVymI8mzOpolI+8jiBcA mOnVs1mI+Uc5F+OHFttyznFLtmwZPLMDzQp29tCPQCbARA1Euxoi51TkLqfzgd8Wo6Re wUlQ6kkPdjR1shi6dsdjEB1n8u2Oc8t6mrxhCF1rlhYUWHtMDWN+eF+83NKpdqT9MnKv R0DSs4YI8k2baL06mc5laHoUQWO97pSi2C1d0BHYboDehb50/nhlpoww9qOFu1+1mvWm fh1A== X-Gm-Message-State: AOAM531nLoelhwVZqE+nAQsoFNRvOn1LDYMNNitS2CJ3ZaRmNmiK6s5o EO5KHbBm7yqVE/ZtgwxBeKB07g== X-Google-Smtp-Source: ABdhPJzdn7I12oW46O5UIXj/wovt7fy2VV2ahAwxWW+a4IFWY/AUt0BBSKGBtjDcX3VqOkSXoXKlaQ== X-Received: by 2002:ac2:4c41:: with SMTP id o1mr10394337lfk.52.1630242796938; Sun, 29 Aug 2021 06:13:16 -0700 (PDT) Received: from eriador.lan ([37.153.55.125]) by smtp.gmail.com with ESMTPSA id x13sm712503lfq.262.2021.08.29.06.13.16 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 29 Aug 2021 06:13:16 -0700 (PDT) From: Dmitry Baryshkov To: Andy Gross , Bjorn Andersson , Ulf Hansson , Marcel Holtmann , Johan Hedberg , Luiz Augusto von Dentz , Kalle Valo , "David S. Miller" , Jakub Kicinski , Stanimir Varbanov Cc: linux-arm-msm@vger.kernel.org, linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-bluetooth@vger.kernel.org, ath10k@lists.infradead.org, linux-wireless@vger.kernel.org, netdev@vger.kernel.org Subject: [RFC v2 09/13] arm64: dts: qcom: sdm845-db845c: switch bt+wifi to qca power sequencer Date: Sun, 29 Aug 2021 16:13:01 +0300 Message-Id: <20210829131305.534417-10-dmitry.baryshkov@linaro.org> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20210829131305.534417-1-dmitry.baryshkov@linaro.org> References: <20210829131305.534417-1-dmitry.baryshkov@linaro.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org Switch sdm845-db845c device tree to use new power sequencer driver rather than separate regulators. Signed-off-by: Dmitry Baryshkov --- arch/arm64/boot/dts/qcom/sdm845-db845c.dts | 21 ++++++++++++++------- arch/arm64/boot/dts/qcom/sdm845.dtsi | 6 ++++++ 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/sdm845-db845c.dts b/arch/arm64/boot/dts/qcom/sdm845-db845c.dts index 2d5533dd4ec2..a6a34a959a91 100644 --- a/arch/arm64/boot/dts/qcom/sdm845-db845c.dts +++ b/arch/arm64/boot/dts/qcom/sdm845-db845c.dts @@ -629,6 +629,16 @@ &qupv3_id_1 { status = "okay"; }; +&qca_pwrseq { + status = "okay"; + + vddio-supply = <&vreg_s4a_1p8>; + + vddxo-supply = <&vreg_l7a_1p8>; + vddrf-supply = <&vreg_l17a_1p3>; + vddch0-supply = <&vreg_l25a_3p3>; +}; + &sdhc_2 { status = "okay"; @@ -916,10 +926,8 @@ &uart6 { bluetooth { compatible = "qcom,wcn3990-bt"; - vddio-supply = <&vreg_s4a_1p8>; - vddxo-supply = <&vreg_l7a_1p8>; - vddrf-supply = <&vreg_l17a_1p3>; - vddch0-supply = <&vreg_l25a_3p3>; + bt-pwrseq = <&qca_pwrseq 1>; + max-speed = <3200000>; }; }; @@ -1036,9 +1044,8 @@ &wifi { status = "okay"; vdd-0.8-cx-mx-supply = <&vreg_l5a_0p8>; - vdd-1.8-xo-supply = <&vreg_l7a_1p8>; - vdd-1.3-rfa-supply = <&vreg_l17a_1p3>; - vdd-3.3-ch0-supply = <&vreg_l25a_3p3>; + + wifi-pwrseq = <&qca_pwrseq 0>; qcom,snoc-host-cap-8bit-quirk; }; diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi index 0a86fe71a66d..78e889b2c8dd 100644 --- a/arch/arm64/boot/dts/qcom/sdm845.dtsi +++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi @@ -1051,6 +1051,12 @@ psci { method = "smc"; }; + qca_pwrseq: qca-pwrseq { + compatible = "qcom,wcn3990-pwrseq"; + #pwrseq-cells = <1>; + status = "disabled"; + }; + soc: soc@0 { #address-cells = <2>; #size-cells = <2>; From patchwork Sun Aug 29 13:13:05 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Baryshkov X-Patchwork-Id: 504201 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-18.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id BC7C2C432BE for ; Sun, 29 Aug 2021 13:13:34 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id A44C260F4B for ; Sun, 29 Aug 2021 13:13:34 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235620AbhH2NOX (ORCPT ); Sun, 29 Aug 2021 09:14:23 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47036 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235575AbhH2NOO (ORCPT ); Sun, 29 Aug 2021 09:14:14 -0400 Received: from mail-lj1-x22e.google.com (mail-lj1-x22e.google.com [IPv6:2a00:1450:4864:20::22e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C2E8CC0612A4 for ; Sun, 29 Aug 2021 06:13:21 -0700 (PDT) Received: by mail-lj1-x22e.google.com with SMTP id m4so20683490ljq.8 for ; Sun, 29 Aug 2021 06:13:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=DZOpdA3eYjpudg4OpQFFkH8jLHw3BxsNdxzTMff7kgw=; b=JYgvhRh/XMbWSmh2hHQ6low2HT/EK5Db15j4xEn196MVYAmhicQUPTkqK33Ygf5yJV rIzHsKI+Z3ckWJRnIUe8dzDewGj8MNiCcN3JIyjVk8xGm0jTD/fexByf4nfLDCRojILy /oSMgUZwtgSQTDfCyHKl3j2WvWHGMsledNkCtgxqqMzm9IvPQvg4CFrG2Jlfglgj36iX PooxcxfGHTuPO6c6gyEHfNmzBVsimJZLJTGHu6co+MuRlWDTVLxi4vVmD0a2oxg5N+8h 2NOSABtA1NVG0Xv+u7omjq/8kK4obaak3LZh0U+Pdzi6pCOqwezV15LMpV08KYXIqDFE T49A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=DZOpdA3eYjpudg4OpQFFkH8jLHw3BxsNdxzTMff7kgw=; b=ZTenmZZVXFxBbuLNEJwOJh3AYAULL121ICNJkurjo4MBqHHL8B1lu6Sk9Qunri0VR4 Dx+C6faqQ+EQDB9fA5wn8ZFaFlwdZnT6SaB5Bd0bwbP03p3t0zThegnuuFndPAjZWUuo XIxp33o1Gg+xzp+Wnl/rY9qstjcCMyY7TyWrv7ZN/9ShVQW02WDvMfiVBFok4kPUKQ3q 7gcnV+nnemRbyM0EYmflVhgMDT3pMZ1bX11AY8nr7LC4049n1aNOvn/r8j9PquqQhglD C5LSpdZ4/Jz/cxV+Lkj9Xu6ZsGyaldkT9AymcDYIB3Aa2MuyNVoui9dp5MhkyjvUyVYw MTHw== X-Gm-Message-State: AOAM5323Vgc25El14ahTW2UA0VsYINcj35yJhIe80WrJpaw0OZimQzYc lyyEVQO2zkUGN91WrYCVyoTcag== X-Google-Smtp-Source: ABdhPJwN0RnHneAiBvwIuepF2POuNFYC+7soqzPBkiEXgB5t1sLpCiFezga+nEjbYoWJ71ExIPe4Iw== X-Received: by 2002:a2e:b605:: with SMTP id r5mr16548450ljn.283.1630242800140; Sun, 29 Aug 2021 06:13:20 -0700 (PDT) Received: from eriador.lan ([37.153.55.125]) by smtp.gmail.com with ESMTPSA id x13sm712503lfq.262.2021.08.29.06.13.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 29 Aug 2021 06:13:19 -0700 (PDT) From: Dmitry Baryshkov To: Andy Gross , Bjorn Andersson , Ulf Hansson , Marcel Holtmann , Johan Hedberg , Luiz Augusto von Dentz , Kalle Valo , "David S. Miller" , Jakub Kicinski , Stanimir Varbanov Cc: linux-arm-msm@vger.kernel.org, linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-bluetooth@vger.kernel.org, ath10k@lists.infradead.org, linux-wireless@vger.kernel.org, netdev@vger.kernel.org Subject: [RFC v2 13/13] WIP: arm64: dts: qcom: qrb5165-rb5: add bus-pwrseq property to pcie0 Date: Sun, 29 Aug 2021 16:13:05 +0300 Message-Id: <20210829131305.534417-14-dmitry.baryshkov@linaro.org> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20210829131305.534417-1-dmitry.baryshkov@linaro.org> References: <20210829131305.534417-1-dmitry.baryshkov@linaro.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org Signed-off-by: Dmitry Baryshkov --- arch/arm64/boot/dts/qcom/qrb5165-rb5.dts | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/boot/dts/qcom/qrb5165-rb5.dts b/arch/arm64/boot/dts/qcom/qrb5165-rb5.dts index 326330f528fc..0c347cb6f8e0 100644 --- a/arch/arm64/boot/dts/qcom/qrb5165-rb5.dts +++ b/arch/arm64/boot/dts/qcom/qrb5165-rb5.dts @@ -689,6 +689,7 @@ wifi-therm@1 { &pcie0 { status = "okay"; + bus-pwrseq = <&qca_pwrseq 0>; }; &pcie0_phy {