From patchwork Wed Oct 6 03:53:53 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Baryshkov X-Patchwork-Id: 12538505 X-Patchwork-Delegate: johannes@sipsolutions.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id E2807C4332F for ; Wed, 6 Oct 2021 03:55:16 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id C53F161248 for ; Wed, 6 Oct 2021 03:55:16 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237325AbhJFD4I (ORCPT ); Tue, 5 Oct 2021 23:56:08 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:32928 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237268AbhJFD4G (ORCPT ); Tue, 5 Oct 2021 23:56:06 -0400 Received: from mail-lf1-x135.google.com (mail-lf1-x135.google.com [IPv6:2a00:1450:4864:20::135]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0C460C061764 for ; Tue, 5 Oct 2021 20:54:14 -0700 (PDT) Received: by mail-lf1-x135.google.com with SMTP id n8so4531853lfk.6 for ; Tue, 05 Oct 2021 20:54: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=0QbCWpC0YUHd4oM8ALhGkUXV2GRwREBEvhvGaNVxQyo=; b=he2kT439AhNtxiuqDLrNaZpNYt38+4H16zAkk/pYeKvytO6jQI9YrfDulq+/ku2ae6 QcjskLIWgJBzMoIQi0R91D2cctBB27lEMBdcuYBNl1HRLoyuq5WQRO/M8fZI0e/eaEWd sINOv6L6kKh0sh5q3Gj4F1V2jcH1vNu7KSKbOJFm7UG2hdj6vvWkvE73ie0jGA+nIM0Y t6Z1V4bddNVkkWhw8u7pOiI2jhSPajejhaCgdcxmdmpZkHfz35vCMKx36LYu5awMpEY2 nVj9Hb4/4m9nCEHG9DRzBH3FEma/IlB2fgdRMh3xMWOJE1+ti3mLeKUTppV80/OiPgZ5 eS1w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=0QbCWpC0YUHd4oM8ALhGkUXV2GRwREBEvhvGaNVxQyo=; b=7wYQFqJhPkdQBPPAJAZmsAukbgXNg5oi2PK8laIUfzDYo3Ui74eA+LX5ttDHNc2LE5 WxzPazaa+9DhdXviVLZsGMM1DLrQ/DvOU7bBWA9Bikmyz3oCe/Iv+B0xB5aZSVos+FLS Gsx3YF+M3tSb2c9SeTlICRpGF9Ak5+2JSb2WFv7EJ7iaydD2PZ8bJWACVpWPsMqkBqhm Fso2Su8JaIFn3etpsYIHFFy8baCWJ3zaXIYt1eWwjaC1XV9dufIdlj9i8Rfs6x6/TDVI ahqCEXzBxkpYV9CRxPc+ZOTYC2VJSqDmpW3UYuKEMqopSHdJF+C1tPlOE9bCaU6AAItf byaw== X-Gm-Message-State: AOAM531el/NIRt47abXydwXi6mwA6a4yAp/Bc0TOljNhwvIYeK0CrZPP 9pvVAKI5ihWIEmZgyGEyowfaGg== X-Google-Smtp-Source: ABdhPJzUyTSbGQqEZmbXX4rYk8Wj34+52wMw1vr6OKUpbP6w62OKwylW2IUSus9+fPfMVxbFfNEITg== X-Received: by 2002:a2e:550:: with SMTP id 77mr27560874ljf.478.1633492452244; Tue, 05 Oct 2021 20:54:12 -0700 (PDT) Received: from eriador.lan ([37.153.55.125]) by smtp.gmail.com with ESMTPSA id s4sm2142967lfd.103.2021.10.05.20.54.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 05 Oct 2021 20:54: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: [PATCH v1 01/15] dt-bindings: add pwrseq device tree bindings Date: Wed, 6 Oct 2021 06:53:53 +0300 Message-Id: <20211006035407.1147909-2-dmitry.baryshkov@linaro.org> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20211006035407.1147909-1-dmitry.baryshkov@linaro.org> References: <20211006035407.1147909-1-dmitry.baryshkov@linaro.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org Add device tree bindings for the new power sequencer subsystem. Consumers would reference pwrseq nodes using "foo-pwrseq" properties. Providers would use '#pwrseq-cells' property to declare the amount of cells in the pwrseq specifier. Signed-off-by: Dmitry Baryshkov --- .../bindings/power/pwrseq/pwrseq.yaml | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 Documentation/devicetree/bindings/power/pwrseq/pwrseq.yaml diff --git a/Documentation/devicetree/bindings/power/pwrseq/pwrseq.yaml b/Documentation/devicetree/bindings/power/pwrseq/pwrseq.yaml new file mode 100644 index 000000000000..4a8f6c0218bf --- /dev/null +++ b/Documentation/devicetree/bindings/power/pwrseq/pwrseq.yaml @@ -0,0 +1,32 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/power/pwrseq/pwrseq.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Power Sequencer devices + +maintainers: + - Dmitry Baryshkov + +properties: + "#powerseq-cells": + description: + Number of cells in a pwrseq specifier. + +patternProperties: + ".*-pwrseq$": + description: Power sequencer supply phandle(s) for this node + +additionalProperties: true + +examples: + - | + qca_pwrseq: qca-pwrseq { + #pwrseq-cells = <1>; + }; + + bluetooth { + bt-pwrseq = <&qca_pwrseq 1>; + }; +... From patchwork Wed Oct 6 03:53: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: 12538515 X-Patchwork-Delegate: johannes@sipsolutions.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 19A70C4332F for ; Wed, 6 Oct 2021 03:55:31 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 019C861248 for ; Wed, 6 Oct 2021 03:55:30 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237896AbhJFD5P (ORCPT ); Tue, 5 Oct 2021 23:57:15 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:32952 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237284AbhJFD4G (ORCPT ); Tue, 5 Oct 2021 23:56:06 -0400 Received: from mail-lf1-x12b.google.com (mail-lf1-x12b.google.com [IPv6:2a00:1450:4864:20::12b]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 093AAC061749 for ; Tue, 5 Oct 2021 20:54:15 -0700 (PDT) Received: by mail-lf1-x12b.google.com with SMTP id j5so4511469lfg.8 for ; Tue, 05 Oct 2021 20:54: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=00n7CaYRtB/oPVPJyhNLQU99dusIfQvK/8kpoba23hk=; b=zX40LljGN0ujw8Ut02so9lFStCBV0UifqUNXL0ScIn+t056lOtA+NXl2HUma6WEbyT iHzvQr0fA86NTJ4WX5zvV5ZnwjUSwpP/AwO/AwfBrPb1A8whPKrmDYhypIwS4dCm5FoD bmfAAvbSh4JeEKf64NBq1URR/KeBWwDXLtCFaQynpl06NivcC6ju2RPI7kY1Ob5KKcVz bXnsCjZCPmcAj2ljhIDXY54cOk34otVfOdrOChtE0ZWY/q5NJ/7iIwEdU9+ZHTzTOkmu qwOnrOaBCTqAqiCzzhD7u6T0KPw3Q0+yWQ4cJRx0JymQl+BaZAaA7vUcHz3TvNhFsiX3 uNMA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=00n7CaYRtB/oPVPJyhNLQU99dusIfQvK/8kpoba23hk=; b=WXR154g18xzFU2z9uTyULHgr0aRV808KiWbPjWIw+Z5rJRgl7GRl4PbX23tCiu7MkZ 6Dl1OdceQbxqww2a1Q/rQ1Qjo46ljYDjAwNCXbmryfj7qKsy2hxnxmGbxxQzn7nGiNWU dTFFztFZv1ZOvQSeJQ7AKQm3vryFv1YkmI1oItb1O2w+HMf+DEq2KPuG+GKJTJk2oH2X /RG6v/+BiUAKuJZH5lpy/+t2Nk2c3bfxhZEeJpD4emp/RVGjE436JiPPG7bpdn6Lqytd /uurC3trYuw1BYMftfzkWFQqfX7JD+yuSkAjr6I9NEUydFtvG16l1ZwWD0xGf2ApPoZh gTHA== X-Gm-Message-State: AOAM531mctrzzhm2Ii23Fly4PNtN6SwFjVI3CpLBuhkV8/8nrOVUKhix +Fk0Ti6vUZTmGP9t6XGm7aV5sQ== X-Google-Smtp-Source: ABdhPJy3e+mVycCeMiNKlisUqhg9bBIUp1+fzuK3w4Wx3UkS+S2PGMaTnxZyiwjLhZdx7FUZNywDSw== X-Received: by 2002:a05:6512:2614:: with SMTP id bt20mr7043195lfb.506.1633492453152; Tue, 05 Oct 2021 20:54:13 -0700 (PDT) Received: from eriador.lan ([37.153.55.125]) by smtp.gmail.com with ESMTPSA id s4sm2142967lfd.103.2021.10.05.20.54.12 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 05 Oct 2021 20:54: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: [PATCH v1 02/15] power: add power sequencer subsystem Date: Wed, 6 Oct 2021 06:53:54 +0300 Message-Id: <20211006035407.1147909-3-dmitry.baryshkov@linaro.org> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20211006035407.1147909-1-dmitry.baryshkov@linaro.org> References: <20211006035407.1147909-1-dmitry.baryshkov@linaro.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org Basing on MMC's pwrseq support code, add separate power sequencer subsystem. It will be used by other drivers to handle device power up requirements. Signed-off-by: Dmitry Baryshkov --- Documentation/driver-api/index.rst | 1 + Documentation/driver-api/pwrseq.rst | 77 +++++ drivers/power/Kconfig | 1 + drivers/power/Makefile | 1 + drivers/power/pwrseq/Kconfig | 14 + drivers/power/pwrseq/Makefile | 6 + drivers/power/pwrseq/core.c | 448 ++++++++++++++++++++++++++++ include/linux/pwrseq/consumer.h | 82 +++++ include/linux/pwrseq/driver.h | 160 ++++++++++ 9 files changed, 790 insertions(+) create mode 100644 Documentation/driver-api/pwrseq.rst create mode 100644 drivers/power/pwrseq/Kconfig create mode 100644 drivers/power/pwrseq/Makefile create mode 100644 drivers/power/pwrseq/core.c create mode 100644 include/linux/pwrseq/consumer.h create mode 100644 include/linux/pwrseq/driver.h diff --git a/Documentation/driver-api/index.rst b/Documentation/driver-api/index.rst index c57c609ad2eb..15f51c08db1f 100644 --- a/Documentation/driver-api/index.rst +++ b/Documentation/driver-api/index.rst @@ -94,6 +94,7 @@ available subsections can be seen below. ptp phy/index pwm + pwrseq pldmfw/index rfkill serial/index diff --git a/Documentation/driver-api/pwrseq.rst b/Documentation/driver-api/pwrseq.rst new file mode 100644 index 000000000000..df7cfce0f792 --- /dev/null +++ b/Documentation/driver-api/pwrseq.rst @@ -0,0 +1,77 @@ +.. Copyright 2021 Linaro Ltd. + +.. This documentation is free software; you can redistribute +.. it and/or modify it under the terms of the GNU General Public +.. License version 2 as published by the Free Software Foundation. + +==================== +Power Sequencing API +==================== + +:Author: Dmitry Baryshkov +:Author: Ulf Hansson (original MMC pwrseq) + +Introduction +============ + +This framework is designed to provide a standard kernel interface to +handle power sequencing requirements for different devices. + +The intention is to provide a generic way to handle power sequencing of complex +devices sitting on a variety of busses. First implementation comes from MMC +SDIO/eMMC code, not generified to support other kinds of devices. + +Glossary +-------- + +The pwrseq API uses a number of terms which may not be familiar: + +Power sequencer + + Electronic device (or part of it) that supplies power to other devices. + Unlike regulators (which typically handle single voltage), power sequencer + handles several voltage inputs. Also it does not provide an exact voltage + output. Instead it makes sure that the consumers (see below) are powered on + when required. + +Consumer + + Electronic device which consumes power provided by a power sequencer. + +Consumer driver interface +========================= + +This offers a similar API to the kernel clock or regulator framework. Consumer +drivers use `get <#API-pwrseq-get>`__ and +`put <#API-pwrseq-put>`__ operations to acquire and release +power sequencers. Functions are provided to `power on +<#API-pwrseq-full-power-on>`__ and `power off <#API-pwrseq-power-off>`__ the +power sequencer. + +A stub version of this API is provided when the power sequencer framework is +not in use in order to minimise the need to use ifdefs. + +Power sequencer driver interface +================================ + +Drivers for power sequencers register the sequencer within the pwrseq +core, providing operations structures to the core. + +API reference +============= + +Due to limitations of the kernel documentation framework and the +existing layout of the source code the entire regulator API is +documented here. + +.. kernel-doc:: include/linux/pwrseq/consumer.h + :internal: + +.. kernel-doc:: include/linux/pwrseq/driver.h + :internal: + +.. kernel-doc:: include/linux/pwrseq/fallback.h + :internal: + +.. kernel-doc:: drivers/power/pwrseq/core.c + :export: diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig index 696bf77a7042..c87cd2240a74 100644 --- a/drivers/power/Kconfig +++ b/drivers/power/Kconfig @@ -1,3 +1,4 @@ # SPDX-License-Identifier: GPL-2.0-only +source "drivers/power/pwrseq/Kconfig" source "drivers/power/reset/Kconfig" source "drivers/power/supply/Kconfig" diff --git a/drivers/power/Makefile b/drivers/power/Makefile index effbf0377f32..1dbce454a8c4 100644 --- a/drivers/power/Makefile +++ b/drivers/power/Makefile @@ -1,3 +1,4 @@ # SPDX-License-Identifier: GPL-2.0-only obj-$(CONFIG_POWER_RESET) += reset/ obj-$(CONFIG_POWER_SUPPLY) += supply/ +obj-$(CONFIG_PWRSEQ) += pwrseq/ diff --git a/drivers/power/pwrseq/Kconfig b/drivers/power/pwrseq/Kconfig new file mode 100644 index 000000000000..dab8f4d860fe --- /dev/null +++ b/drivers/power/pwrseq/Kconfig @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: GPL-2.0-only +menuconfig PWRSEQ + bool "Power Sequencer drivers" + help + Provides support for special power sequencing drivers. Power + sequencer is an entity providing abstraced power on/power off/reset + operations for the connected devices. Possible usages include MMC + SDIO devices, some complex WiFi/BT chips, controlled USB hubs, etc. + + Say Y here to enable support for such devices. + +if PWRSEQ + +endif diff --git a/drivers/power/pwrseq/Makefile b/drivers/power/pwrseq/Makefile new file mode 100644 index 000000000000..108429ff6445 --- /dev/null +++ b/drivers/power/pwrseq/Makefile @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# Makefile for power sequencer drivers. +# + +obj-$(CONFIG_PWRSEQ) += core.o diff --git a/drivers/power/pwrseq/core.c b/drivers/power/pwrseq/core.c new file mode 100644 index 000000000000..d29b4b97b95c --- /dev/null +++ b/drivers/power/pwrseq/core.c @@ -0,0 +1,448 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright 2021 (c) Linaro Ltd. + * Author: Dmitry Baryshkov + * + * Based on phy-core.c: + * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define to_pwrseq(a) (container_of((a), struct pwrseq, dev)) + +static DEFINE_IDA(pwrseq_ida); +static DEFINE_MUTEX(pwrseq_provider_mutex); +static LIST_HEAD(pwrseq_provider_list); + +/** + * struct pwrseq_provider - a + */ +struct pwrseq_provider { + struct device *dev; + struct module *owner; + struct list_head list; + void *data; + struct pwrseq * (*of_xlate)(void *data, struct of_phandle_args *args); +}; + +/** + * pwrseq_put() - release the pwrseq + * @pwrseq: the pwrseq returned by pwrseq_get() + * + * Releases a refcount on the pwrseq instance received from pwrseq_get(). + */ +void pwrseq_put(struct pwrseq *pwrseq) +{ + module_put(pwrseq->owner); + put_device(&pwrseq->dev); +} +EXPORT_SYMBOL_GPL(pwrseq_put); + +static struct pwrseq_provider *of_pwrseq_provider_lookup(struct device_node *node) +{ + struct pwrseq_provider *pwrseq_provider; + + list_for_each_entry(pwrseq_provider, &pwrseq_provider_list, list) { + if (pwrseq_provider->dev->of_node == node) + return pwrseq_provider; + } + + return ERR_PTR(-EPROBE_DEFER); +} + +static struct pwrseq *_of_pwrseq_get(struct device *dev, const char *id) +{ + struct pwrseq_provider *pwrseq_provider; + struct pwrseq *pwrseq; + struct of_phandle_args args; + char prop_name[64]; /* 64 is max size of property name */ + int ret; + + snprintf(prop_name, sizeof(prop_name), "%s-pwrseq", id); + ret = of_parse_phandle_with_args(dev->of_node, prop_name, "#pwrseq-cells", 0, &args); + if (ret == -ENOENT) + return NULL; + else if (ret < 0) + return ERR_PTR(ret); + + mutex_lock(&pwrseq_provider_mutex); + pwrseq_provider = of_pwrseq_provider_lookup(args.np); + if (IS_ERR(pwrseq_provider) || !try_module_get(pwrseq_provider->owner)) { + pwrseq = ERR_PTR(-EPROBE_DEFER); + goto out_unlock; + } + + if (!of_device_is_available(args.np)) { + dev_warn(pwrseq_provider->dev, "Requested pwrseq is disabled\n"); + pwrseq = ERR_PTR(-ENODEV); + goto out_put_module; + } + + pwrseq = pwrseq_provider->of_xlate(pwrseq_provider->data, &args); + +out_put_module: + module_put(pwrseq_provider->owner); + +out_unlock: + mutex_unlock(&pwrseq_provider_mutex); + of_node_put(args.np); + + return pwrseq; +} + +/** + * pwrseq_get() - lookup and obtain a reference to a pwrseq + * @dev: device for which to get the pwrseq + * @id: name of the pwrseq from device's point of view + * + * Returns the pwrseq instance, after getting a refcount to it; or + * NULL if there is no such pwrseq. The caller is responsible for + * calling pwrseq_put() to release that count. + */ +struct pwrseq * pwrseq_get(struct device *dev, const char *id) +{ + struct pwrseq *pwrseq; + + pwrseq = _of_pwrseq_get(dev, id); + if (IS_ERR_OR_NULL(pwrseq)) + return pwrseq; + + if (!try_module_get(pwrseq->owner)) + return ERR_PTR(-EPROBE_DEFER); + + get_device(&pwrseq->dev); + + return pwrseq; +} +EXPORT_SYMBOL_GPL(pwrseq_get); + +static void devm_pwrseq_release(struct device *dev, void *res) +{ + struct pwrseq *pwrseq = *(struct pwrseq **)res; + + pwrseq_put(pwrseq); +} + +/** + * devm_pwrseq_get() - lookup and obtain a reference to a pwrseq + * @dev: device for which to get the pwrseq + * @id: name of the pwrseq from device's point of view + * + * Devres-managed variant of pwrseq_get(). + * Returns the pwrseq instance, after getting a refcount to it; or + * NULL if there is no such pwrseq. Gets the pwrseq using pwrseq_get(), and + * associates it with the a device using devres. On driver detach, returned + * pwrseq is automatically put using pwrseq_put(), removing the need to call it + * manually. + */ +struct pwrseq * devm_pwrseq_get(struct device *dev, const char *id) +{ + struct pwrseq **ptr, *pwrseq; + + ptr = devres_alloc(devm_pwrseq_release, sizeof(*ptr), GFP_KERNEL); + if (!ptr) + return ERR_PTR(-ENOMEM); + + pwrseq = pwrseq_get(dev, id); + if (!IS_ERR_OR_NULL(pwrseq)) { + *ptr = pwrseq; + devres_add(dev, ptr); + } else { + devres_free(ptr); + } + + return pwrseq; +} +EXPORT_SYMBOL_GPL(devm_pwrseq_get); + +/** + * pwrseq_pre_power_on() - perform pre-power on actions + * @pwrseq: pwrseq instance + * + * Perform pre-powering on actions, like pulling reset pin. This function + * should be called before device is being powered on. Typical usage would + * include MMC cards, where pwrseq subsystem is combined with the MMC power + * controls. + * In most cases there is no need to call it directly, use + * @pwrseq_full_power_on() instead. + */ +int pwrseq_pre_power_on(struct pwrseq *pwrseq) +{ + if (pwrseq && pwrseq->ops->pre_power_on) + return pwrseq->ops->pre_power_on(pwrseq); + + return 0; +} +EXPORT_SYMBOL_GPL(pwrseq_pre_power_on); + +/** + * pwrseq_power_on() - power on the device + * @pwrseq: pwrseq instance + * + * Power on the device and perform post-power on actions, like pulling reset + * or enable pin. In most cases there is no need to call it directly, use + * @pwrseq_full_power_on() instead. + */ +int pwrseq_power_on(struct pwrseq *pwrseq) +{ + if (pwrseq && pwrseq->ops->power_on) + return pwrseq->ops->power_on(pwrseq); + + return 0; +} +EXPORT_SYMBOL_GPL(pwrseq_power_on); + +/** + * pwrseq_power_off() - power off the device + * @pwrseq: pwrseq instance + * + * Power off the device clearly. + */ +void pwrseq_power_off(struct pwrseq *pwrseq) +{ + if (pwrseq && pwrseq->ops->power_off) + pwrseq->ops->power_off(pwrseq); +} +EXPORT_SYMBOL_GPL(pwrseq_power_off); + +/** + * pwrseq_reset() - reset powered device + * @pwrseq: pwrseq instance + * + * Reset the device controlled by the power sequencer. + */ +void pwrseq_reset(struct pwrseq *pwrseq) +{ + if (pwrseq && pwrseq->ops->reset) + pwrseq->ops->reset(pwrseq); +} +EXPORT_SYMBOL_GPL(pwrseq_reset); + +static void pwrseq_dev_release(struct device *dev) +{ + struct pwrseq *pwrseq = to_pwrseq(dev); + + ida_free(&pwrseq_ida, pwrseq->id); + of_node_put(dev->of_node); + kfree(pwrseq); +} + +static struct class pwrseq_class = { + .name = "pwrseq", + .dev_release = pwrseq_dev_release, +}; + +/** + * __pwrseq_create() - internal helper for pwrseq_create + * @dev: parent device + * @owner: the module providing callbacks. + * @ops: pwrseq device callbacks + * + * This is an internal helper for pwrseq_create which should not be called + * directly. + * + * Return: created instance or the wrapped error code. + */ +struct pwrseq *__pwrseq_create(struct device *dev, struct module *owner, const struct pwrseq_ops *ops) +{ + struct pwrseq *pwrseq; + int ret; + + if (WARN_ON(!dev)) + return ERR_PTR(-EINVAL); + + pwrseq = kzalloc(sizeof(*pwrseq), GFP_KERNEL); + if (!pwrseq) + return ERR_PTR(-ENOMEM); + + ret = ida_alloc(&pwrseq_ida, GFP_KERNEL); + if (ret < 0) + goto free_pwrseq; + + pwrseq->id = ret; + + device_initialize(&pwrseq->dev); + + pwrseq->dev.class = &pwrseq_class; + pwrseq->dev.parent = dev; + pwrseq->dev.of_node = of_node_get(dev->of_node); + pwrseq->ops = ops; + pwrseq->owner = owner; + + ret = dev_set_name(&pwrseq->dev, "pwrseq-%s.%u", dev_name(dev), pwrseq->id); + if (ret) + goto put_dev; + + ret = device_add(&pwrseq->dev); + if (ret) + goto put_dev; + + return pwrseq; + +put_dev: + /* will call pwrseq_dev_release() to free resources */ + put_device(&pwrseq->dev); + + return ERR_PTR(ret); + +free_pwrseq: + kfree(pwrseq); + + return ERR_PTR(ret); +} +EXPORT_SYMBOL_GPL(__pwrseq_create); + +void pwrseq_destroy(struct pwrseq *pwrseq) +{ + device_unregister(&pwrseq->dev); +} +EXPORT_SYMBOL_GPL(pwrseq_destroy); + +static void devm_pwrseq_destroy(struct device *dev, void *res) +{ + struct pwrseq *pwrseq = *(struct pwrseq **)res; + + pwrseq_destroy(pwrseq); +} + +/** + * __devm_pwrseq_create() - devres-managed version of __pwrseq_create + * @dev: parent device + * @owner: the module providing callbacks. + * @ops: pwrseq device callbacks + * + * This is the devres-managed version of __pwrseq_create(). It is an internal + * helper which should not be called directly. + * + * Return: created instance or the wrapped error code. + */ +struct pwrseq *__devm_pwrseq_create(struct device *dev, struct module *owner, const struct pwrseq_ops *ops) +{ + struct pwrseq **ptr, *pwrseq; + + ptr = devres_alloc(devm_pwrseq_destroy, sizeof(*ptr), GFP_KERNEL); + if (!ptr) + return ERR_PTR(-ENOMEM); + + pwrseq = __pwrseq_create(dev, owner, ops); + if (!IS_ERR(pwrseq)) { + *ptr = pwrseq; + devres_add(dev, ptr); + } else { + devres_free(ptr); + } + + return pwrseq; +} +EXPORT_SYMBOL_GPL(__devm_pwrseq_create); + +/** + * __of_pwrseq_provider_register - internal version of of_pwrseq_provider_register + * @dev: handling device + * @owner: the module providing callbacks. + * @xlate: xlate function returning pwrseq instance corresponding to OF args + * @data: provider-specific data to be passed to xlate function + * + * This is an internal helper of of_pwrseq_provider_register, it should not be + * called directly. + */ +struct pwrseq_provider *__of_pwrseq_provider_register(struct device *dev, + struct module *owner, + struct pwrseq * (*of_xlate)(void *data, + struct of_phandle_args *args), + void *data) +{ + struct pwrseq_provider *pwrseq_provider; + + pwrseq_provider = kzalloc(sizeof(*pwrseq_provider), GFP_KERNEL); + if (!pwrseq_provider) + return ERR_PTR(-ENOMEM); + + if (!fwnode_property_present(dev->fwnode, "#pwrseq-cells")) + dev_warn(dev, "no #pwrseq-cells property found, please add the property to the provider\n"); + + pwrseq_provider->dev = dev; + pwrseq_provider->owner = owner; + pwrseq_provider->of_xlate = of_xlate; + pwrseq_provider->data = data; + + mutex_lock(&pwrseq_provider_mutex); + list_add_tail(&pwrseq_provider->list, &pwrseq_provider_list); + mutex_unlock(&pwrseq_provider_mutex); + + return pwrseq_provider; +} +EXPORT_SYMBOL_GPL(__of_pwrseq_provider_register); + +/** + * of_pwrseq_provider_unregister() - unregister pwrseq provider + * @pwrseq_provider: pwrseq provider to unregister + * + * Unregister pwrseq provider previously registered by of_pwrseq_provider_register(). + */ +void of_pwrseq_provider_unregister(struct pwrseq_provider *pwrseq_provider) +{ + if (IS_ERR(pwrseq_provider)) + return; + + mutex_lock(&pwrseq_provider_mutex); + list_del(&pwrseq_provider->list); + kfree(pwrseq_provider); + mutex_unlock(&pwrseq_provider_mutex); +} +EXPORT_SYMBOL_GPL(of_pwrseq_provider_unregister); + +static void devm_pwrseq_provider_unregister(struct device *dev, void *res) +{ + struct pwrseq_provider *pwrseq_provider = *(struct pwrseq_provider **)res; + + of_pwrseq_provider_unregister(pwrseq_provider); +} + +/** + * __devm_of_pwrseq_provider_register - internal version of devm_of_pwrseq_provider_register + * @dev: handling device + * @owner: the module providing callbacks. + * @xlate: xlate function returning pwrseq instance corresponding to OF args + * @data: provider-specific data to be passed to xlate function + * + * This is an internal helper of devm_of_pwrseq_provider_register, it should + * not be called directly. + */ +struct pwrseq_provider *__devm_of_pwrseq_provider_register(struct device *dev, + struct module *owner, + struct pwrseq * (*of_xlate)(void *data, + struct of_phandle_args *args), + void *data) +{ + struct pwrseq_provider **ptr, *pwrseq_provider; + + ptr = devres_alloc(devm_pwrseq_provider_unregister, sizeof(*ptr), GFP_KERNEL); + if (!ptr) + return ERR_PTR(-ENOMEM); + + pwrseq_provider = __of_pwrseq_provider_register(dev, owner, of_xlate, data); + if (!IS_ERR(pwrseq_provider)) { + *ptr = pwrseq_provider; + devres_add(dev, ptr); + } else { + devres_free(ptr); + } + + return pwrseq_provider; +} +EXPORT_SYMBOL_GPL(__devm_of_pwrseq_provider_register); + +static int __init pwrseq_core_init(void) +{ + return class_register(&pwrseq_class); +} +device_initcall(pwrseq_core_init); diff --git a/include/linux/pwrseq/consumer.h b/include/linux/pwrseq/consumer.h new file mode 100644 index 000000000000..7c8efefd3184 --- /dev/null +++ b/include/linux/pwrseq/consumer.h @@ -0,0 +1,82 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (c) 2021 Linaro Ltd. + */ + +#ifndef __LINUX_PWRSEQ_CONSUMER_H__ +#define __LINUX_PWRSEQ_CONSUMER_H__ + +struct pwrseq; +struct device; + +#if defined(CONFIG_PWRSEQ) + +struct pwrseq *__must_check pwrseq_get(struct device *dev, const char *id); +struct pwrseq *__must_check devm_pwrseq_get(struct device *dev, const char *id); + +void pwrseq_put(struct pwrseq *pwrseq); + +int pwrseq_pre_power_on(struct pwrseq *pwrseq); +int pwrseq_power_on(struct pwrseq *pwrseq); +void pwrseq_power_off(struct pwrseq *pwrseq); +void pwrseq_reset(struct pwrseq *pwrseq); + +#else + +static inline struct pwrseq *__must_check +pwrseq_get(struct device *dev, const char *id) +{ + return NULL; +} + +static inline struct pwrseq *__must_check +devm_pwrseq_get(struct device *dev, const char *id) +{ + return NULL; +} + +static inline void pwrseq_put(struct pwrseq *pwrseq) +{ +} + +static inline int pwrseq_pre_power_on(struct pwrseq *pwrseq) +{ + return -ENOSYS; +} + +static inline int pwrseq_power_on(struct pwrseq *pwrseq) +{ + return -ENOSYS; +} + +static inline void pwrseq_power_off(struct pwrseq *pwrseq) +{ +} + +static inline void pwrseq_reset(struct pwrseq *pwrseq) +{ +} + +#endif + +/** + * pwrseq_full_power_on() - Perform full power on of the sequencer + * @pwrseq: the power sequencer to power on + * + * Perform full power on of the sequencer, including pre power on and + * power on steps. + * + * Return: 0 upon no error; -error upon error. + */ +static inline int pwrseq_full_power_on(struct pwrseq *pwrseq) +{ + int ret; + + ret = pwrseq_pre_power_on(pwrseq); + if (ret) + return ret; + + return pwrseq_power_on(pwrseq); +} + +#endif /* __LINUX_PWRSEQ_CONSUMER_H__ */ diff --git a/include/linux/pwrseq/driver.h b/include/linux/pwrseq/driver.h new file mode 100644 index 000000000000..bdb8a25a8504 --- /dev/null +++ b/include/linux/pwrseq/driver.h @@ -0,0 +1,160 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (c) 2021 Linaro Ltd. + */ + +#ifndef __LINUX_PWRSEQ_DRIVER_H__ +#define __LINUX_PWRSEQ_DRIVER_H__ + +#include + +struct pwrseq; + +/** + * struct pwrseq_ops - power sequencer operations. + * + * @pre_power_on: Perform pre powering operations (like ensuring that the + * device will be held in the reset) + * @power_on: Power on the sequencer, making sure that the consumer + * devices can be operated + * @power_off: Power off the sequencer, removing power from the comsumer + * device (if possible) + * @reset: Reset the consumer device + */ +struct pwrseq_ops { + int (*pre_power_on)(struct pwrseq *pwrseq); + int (*power_on)(struct pwrseq *pwrseq); + void (*power_off)(struct pwrseq *pwrseq); + void (*reset)(struct pwrseq *pwrseq); +}; + +struct module; + +/** + * struct pwrseq - private pwrseq data + * + * Power sequencer device, one for each power sequencer. + * + * This should *not* be used directly by anything except the pwrseq core. + */ +struct pwrseq { + struct device dev; + const struct pwrseq_ops *ops; + unsigned int id; + struct module *owner; +}; + +struct pwrseq *__pwrseq_create(struct device *dev, struct module *owner, const struct pwrseq_ops *ops); +struct pwrseq *__devm_pwrseq_create(struct device *dev, struct module *owner, const struct pwrseq_ops *ops); + +/** + * pwrseq_create() - create pwrseq instance + * @dev: parent device + * @ops: pwrseq device callbacks + * + * Create new pwrseq instance parenting with @dev using provided @ops set of + * callbacks. Create instance should be destroyed using @pwrseq_destroy(). + * + * Return: created instance or the wrapped error code. + */ +#define pwrseq_create(dev, ops, data) __pwrseq_create((dev), THIS_MODULE, (ops)) + +/** + * devm_pwrseq_create() - devres-managed version of pwrseq_create + * @dev: parent device + * @ops: pwrseq device callbacks + * + * This is the devres-managed version of pwrseq_create(). It creates new + * pwrseq instance parenting with @dev using provided @ops set of + * callbacks. Returned object is destroyed automatically, one must not call + * pwrseq_destroy(). + * + * Return: created instance or the wrapped error code. + */ +#define devm_pwrseq_create(dev, ops, data) __devm_pwrseq_create((dev), THIS_MODULE, (ops)) + +void pwrseq_destroy(struct pwrseq *pwrseq); + +/** + * pwrseq_set_data() - get drv-specific data for the pwrseq + * @pwrseq: the pwrseq to get driver data for + * @data: the data to set + * + * Sets the driver-specific data for the provided powrseq instance. + */ +static inline void pwrseq_set_drvdata(struct pwrseq *pwrseq, void *data) +{ + dev_set_drvdata(&pwrseq->dev, data); +} + +/** + * pwrseq_get_data() - get drv-specific data for the pwrseq + * @pwrseq: the pwrseq to get driver data for + * + * Returns driver-specific data for the provided powrseq instance. + */ +static inline void *pwrseq_get_drvdata(struct pwrseq *pwrseq) +{ + return dev_get_drvdata(&pwrseq->dev); +} + +/** + * of_pwrseq_provider_register() - register OF pwrseq provider + * @dev: handling device + * @xlate: xlate function returning pwrseq instance corresponding to OF args + * @data: provider-specific data to be passed to xlate function + * + * This macros registers OF-specific pwrseq provider. Pwrseq core will call + * specified @xlate function to retrieve pwrseq instance corresponding to + * device tree arguments. Returned pwrseq provider should be unregistered using + * of_pwrseq_provider_unregister(). + */ +#define of_pwrseq_provider_register(dev, xlate, data) \ + __of_pwrseq_provider_register((dev), THIS_MODULE, (xlate), (data)) + +/** + * devm_of_pwrseq_provider_register() - devres-managed version of of_pwrseq_provider_register + * @dev: handling device + * @xlate: xlate function returning pwrseq instance corresponding to OF args + * @data: provider-specific data to be passed to xlate function + * + * This is a devres-managed version of of_pwrseq_provider_register(). + * This macros registers OF-specific pwrseq provider. Pwrseq core will call + * specified @xlate function to retrieve pwrseq instance corresponding to + * device tree arguments. Returned pwrseq provider is automatically + * unregistered, without the need to call of_pwrseq_provider_unregister(). + */ +#define devm_of_pwrseq_provider_register(dev, xlate, data) \ + __devm_of_pwrseq_provider_register((dev), THIS_MODULE, (xlate), (data)) + +struct of_phandle_args; + +struct pwrseq_provider *__of_pwrseq_provider_register(struct device *dev, + struct module *owner, + struct pwrseq * (*of_xlate)(void *data, + struct of_phandle_args *args), + void *data); +struct pwrseq_provider *__devm_of_pwrseq_provider_register(struct device *dev, + struct module *owner, + struct pwrseq * (*of_xlate)(void *data, + struct of_phandle_args *args), + void *data); +void of_pwrseq_provider_unregister(struct pwrseq_provider *pwrseq_provider); + +/** + * of_pwrseq_xlate_single() - returns the pwrseq instance from pwrseq provider + * @data: the pwrseq provider data + * @args: of_phandle_args (not used here) + * + * Intended to be used by pwrseq provider for the common case where + * #pwrseq-cells is 0. For other cases where #pwrseq-cells is greater than '0', + * the pwrseq provider should provide a custom of_xlate function that reads the + * *args* and returns the appropriate pwrseq. + */ +static inline struct pwrseq *of_pwrseq_xlate_single(void *data, + struct of_phandle_args *args) +{ + return data; +} + +#endif /* __LINUX_PWRSEQ_DRIVER_H__ */ From patchwork Wed Oct 6 03:53:55 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Baryshkov X-Patchwork-Id: 12538511 X-Patchwork-Delegate: johannes@sipsolutions.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 42205C433F5 for ; Wed, 6 Oct 2021 03:55:23 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 2A5E7611C1 for ; Wed, 6 Oct 2021 03:55:23 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237856AbhJFD5L (ORCPT ); Tue, 5 Oct 2021 23:57:11 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:32962 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237296AbhJFD4H (ORCPT ); Tue, 5 Oct 2021 23:56:07 -0400 Received: from mail-lf1-x130.google.com (mail-lf1-x130.google.com [IPv6:2a00:1450:4864:20::130]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id BAFB3C061764 for ; Tue, 5 Oct 2021 20:54:15 -0700 (PDT) Received: by mail-lf1-x130.google.com with SMTP id u18so4429647lfd.12 for ; Tue, 05 Oct 2021 20:54: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=rbD+BS0NcNaczpvYu66j0XoKIa1SV+z+K/gWdXPxBUk=; b=KykwizkLmvDe9V3ztSXHrMUbEtG+5O9apjwceX15mSAxfOGddjZBn9DvzqFQm8al+v EAnxZ4OCvL47ljwDebZl06eRDP+igYzAFrsJJ+opFdIsw1yb/jto3oBjuKWhwchmzFZk mzy0kAh+LD6tz+hN8sGOY125bt6SsnhGXQMAcV3SbFx/KPE+6HAg9GcKn4rXy+OHW9a9 EJqd/8q7d+PsNvrrx65/+T9ur6agPadWkmCQTbQ3U/B/stGNNXhj/8ogUfAi8CGTLy7Q Pzj9M/b0zsb5GzGml+qQ1rPPUbEVQyDD+9ZVBLd8fsMeGmeWr/I8emBgFrsG/NavD70P tDlQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=rbD+BS0NcNaczpvYu66j0XoKIa1SV+z+K/gWdXPxBUk=; b=rxOijXkT+oQzjf3zpmlNZEXejSrVTYghr2GnwdeFeMTn3lyKmBG/1K0Vb8y22GNB8Z GEYCSQURtNQv8TOtrYag52WPc6tRVNXNMJ4ZPA4hrBO4yscdPb5ezqxoLrvN5uSqwjBh pSVRAcQ6vKbBqTDyipW8VZoXoLjR1kSc8iKnUPtRxs/q6dih4wfNsfPI7vizi172I0y7 U/b/i+JlViCb27sisGiDo+P6mrDtVe5PI2T0Qzgzt4Q8pzSaZYiqOmoiScUaZpecNexU 18SxGqCOB6w5Rd3dbM/giKK54N3U5caeU7KKpmT+s/lztcQPXNMi7M3dcP7yNiK/iWQG UW8w== X-Gm-Message-State: AOAM532/KTFf/JeG+q/bV/5Amck0uX1DpSPxYHVImUOfnSYBQSu3GsNH WYCbSvvxlRwbgtndW9cjjZ15lw== X-Google-Smtp-Source: ABdhPJyHOYUrhGd9ENG3ERRSBh4fXx2/aUNfIRp3OWEd/bpQIfbGu6lhQiSaVH9XY6NpQ7K+CSnSLg== X-Received: by 2002:a05:6512:ea2:: with SMTP id bi34mr6935938lfb.638.1633492453860; Tue, 05 Oct 2021 20:54:13 -0700 (PDT) Received: from eriador.lan ([37.153.55.125]) by smtp.gmail.com with ESMTPSA id s4sm2142967lfd.103.2021.10.05.20.54.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 05 Oct 2021 20:54: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: [PATCH v1 03/15] pwrseq: port MMC's pwrseq drivers to new pwrseq subsystem Date: Wed, 6 Oct 2021 06:53:55 +0300 Message-Id: <20211006035407.1147909-4-dmitry.baryshkov@linaro.org> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20211006035407.1147909-1-dmitry.baryshkov@linaro.org> References: <20211006035407.1147909-1-dmitry.baryshkov@linaro.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org Port MMC's all pwrseq drivers to new pwrseq subsystem. Signed-off-by: Dmitry Baryshkov --- .../pwrseq}/mmc-pwrseq-emmc.yaml | 6 +- .../pwrseq}/mmc-pwrseq-sd8787.yaml | 6 +- .../pwrseq}/mmc-pwrseq-simple.yaml | 6 +- drivers/mmc/core/Kconfig | 32 ---- drivers/mmc/core/Makefile | 3 - drivers/mmc/core/pwrseq_emmc.c | 120 ------------- drivers/mmc/core/pwrseq_sd8787.c | 117 ------------- drivers/mmc/core/pwrseq_simple.c | 164 ------------------ drivers/power/pwrseq/Kconfig | 32 ++++ drivers/power/pwrseq/Makefile | 4 + drivers/power/pwrseq/pwrseq_emmc.c | 121 +++++++++++++ drivers/power/pwrseq/pwrseq_sd8787.c | 108 ++++++++++++ drivers/power/pwrseq/pwrseq_simple.c | 162 +++++++++++++++++ include/linux/pwrseq/driver.h | 4 +- 14 files changed, 444 insertions(+), 441 deletions(-) rename Documentation/devicetree/bindings/{mmc => power/pwrseq}/mmc-pwrseq-emmc.yaml (91%) rename Documentation/devicetree/bindings/{mmc => power/pwrseq}/mmc-pwrseq-sd8787.yaml (86%) rename Documentation/devicetree/bindings/{mmc => power/pwrseq}/mmc-pwrseq-simple.yaml (92%) 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 91% rename from Documentation/devicetree/bindings/mmc/mmc-pwrseq-emmc.yaml rename to Documentation/devicetree/bindings/power/pwrseq/mmc-pwrseq-emmc.yaml index 1fc7e620f328..a5e14e4a19b3 100644 --- a/Documentation/devicetree/bindings/mmc/mmc-pwrseq-emmc.yaml +++ b/Documentation/devicetree/bindings/power/pwrseq/mmc-pwrseq-emmc.yaml @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 %YAML 1.2 --- -$id: http://devicetree.org/schemas/mmc/mmc-pwrseq-emmc.yaml# +$id: http://devicetree.org/schemas/power/pwrseq/mmc-pwrseq-emmc.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# title: Simple eMMC hardware reset provider binding @@ -32,6 +32,9 @@ properties: reset procedure as described in Jedec 4.4 specification, the gpio line should be defined as GPIO_ACTIVE_LOW. + "#pwrseq-cells": + const: 0 + required: - compatible - reset-gpios @@ -43,6 +46,7 @@ examples: #include sdhci0_pwrseq { compatible = "mmc-pwrseq-emmc"; + #pwrseq-cells = <0>; reset-gpios = <&gpio1 12 GPIO_ACTIVE_LOW>; }; ... diff --git a/Documentation/devicetree/bindings/mmc/mmc-pwrseq-sd8787.yaml b/Documentation/devicetree/bindings/power/pwrseq/mmc-pwrseq-sd8787.yaml similarity index 86% rename from Documentation/devicetree/bindings/mmc/mmc-pwrseq-sd8787.yaml rename to Documentation/devicetree/bindings/power/pwrseq/mmc-pwrseq-sd8787.yaml index 9e2396751030..7876be05573d 100644 --- a/Documentation/devicetree/bindings/mmc/mmc-pwrseq-sd8787.yaml +++ b/Documentation/devicetree/bindings/power/pwrseq/mmc-pwrseq-sd8787.yaml @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 %YAML 1.2 --- -$id: http://devicetree.org/schemas/mmc/mmc-pwrseq-sd8787.yaml# +$id: http://devicetree.org/schemas/power/pwrseq/mmc-pwrseq-sd8787.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# title: Marvell SD8787 power sequence provider binding @@ -25,6 +25,9 @@ properties: description: contains a reset GPIO specifier with the default active state + "#pwrseq-cells": + const: 0 + required: - compatible - powerdown-gpios @@ -37,6 +40,7 @@ examples: #include wifi_pwrseq: wifi_pwrseq { compatible = "mmc-pwrseq-sd8787"; + #pwrseq-cells = <0>; powerdown-gpios = <&twl_gpio 0 GPIO_ACTIVE_LOW>; reset-gpios = <&twl_gpio 1 GPIO_ACTIVE_LOW>; }; diff --git a/Documentation/devicetree/bindings/mmc/mmc-pwrseq-simple.yaml b/Documentation/devicetree/bindings/power/pwrseq/mmc-pwrseq-simple.yaml similarity index 92% rename from Documentation/devicetree/bindings/mmc/mmc-pwrseq-simple.yaml rename to Documentation/devicetree/bindings/power/pwrseq/mmc-pwrseq-simple.yaml index 226fb191913d..3eff40fd347e 100644 --- a/Documentation/devicetree/bindings/mmc/mmc-pwrseq-simple.yaml +++ b/Documentation/devicetree/bindings/power/pwrseq/mmc-pwrseq-simple.yaml @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 %YAML 1.2 --- -$id: http://devicetree.org/schemas/mmc/mmc-pwrseq-simple.yaml# +$id: http://devicetree.org/schemas/power/pwrseq/mmc-pwrseq-simple.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# title: Simple MMC power sequence provider binding @@ -47,6 +47,9 @@ properties: Delay in us after asserting the reset-gpios (if any) during power off of the card. + "#pwrseq-cells": + const: 0 + required: - compatible @@ -57,6 +60,7 @@ examples: #include sdhci0_pwrseq { compatible = "mmc-pwrseq-simple"; + #pwrseq-cells = <0>; reset-gpios = <&gpio1 12 GPIO_ACTIVE_LOW>; clocks = <&clk_32768_ck>; clock-names = "ext_clock"; diff --git a/drivers/mmc/core/Kconfig b/drivers/mmc/core/Kconfig index 6f25c34e4fec..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 || WILC1000_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 2e120ad83020..000000000000 --- a/drivers/mmc/core/pwrseq_sd8787.c +++ /dev/null @@ -1,117 +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 - -#include "pwrseq.h" - -struct mmc_pwrseq_sd8787 { - struct mmc_pwrseq pwrseq; - struct gpio_desc *reset_gpio; - struct gpio_desc *pwrdn_gpio; - u32 reset_pwrdwn_delay_ms; -}; - -#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(pwrseq->reset_pwrdwn_delay_ms); - 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 u32 sd8787_delay_ms = 300; -static const u32 wilc1000_delay_ms = 5; - -static const struct of_device_id mmc_pwrseq_sd8787_of_match[] = { - { .compatible = "mmc-pwrseq-sd8787", .data = &sd8787_delay_ms }, - { .compatible = "mmc-pwrseq-wilc1000", .data = &wilc1000_delay_ms }, - {/* 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; - const struct of_device_id *match; - - pwrseq = devm_kzalloc(dev, sizeof(*pwrseq), GFP_KERNEL); - if (!pwrseq) - return -ENOMEM; - - match = of_match_node(mmc_pwrseq_sd8787_of_match, pdev->dev.of_node); - pwrseq->reset_pwrdwn_delay_ms = *(u32 *)match->data; - - 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 dab8f4d860fe..1985f13d9193 100644 --- a/drivers/power/pwrseq/Kconfig +++ b/drivers/power/pwrseq/Kconfig @@ -11,4 +11,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..954bbb44979d --- /dev/null +++ b/drivers/power/pwrseq/pwrseq_emmc.c @@ -0,0 +1,121 @@ +// 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_drvdata(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); + if (IS_ERR(pwrseq)) + return PTR_ERR(pwrseq); + + pwrseq_set_drvdata(pwrseq, pwrseq_emmc); + + 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..aeb80327f40d --- /dev/null +++ b/drivers/power/pwrseq/pwrseq_sd8787.c @@ -0,0 +1,108 @@ +// 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 + +#include + +struct pwrseq_sd8787 { + struct gpio_desc *reset_gpio; + struct gpio_desc *pwrdn_gpio; + u32 reset_pwrdwn_delay_ms; +}; + +static int pwrseq_sd8787_pre_power_on(struct pwrseq *pwrseq) +{ + struct pwrseq_sd8787 *pwrseq_sd8787 = pwrseq_get_drvdata(pwrseq); + + gpiod_set_value_cansleep(pwrseq_sd8787->reset_gpio, 1); + + msleep(pwrseq_sd8787->reset_pwrdwn_delay_ms); + 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_drvdata(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 u32 sd8787_delay_ms = 300; +static const u32 wilc1000_delay_ms = 5; + +static const struct of_device_id pwrseq_sd8787_of_match[] = { + { .compatible = "mmc-pwrseq-sd8787", .data = &sd8787_delay_ms }, + { .compatible = "mmc-pwrseq-wilc1000", .data = &wilc1000_delay_ms }, + {/* 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->reset_pwrdwn_delay_ms = *(u32 *)of_device_get_match_data(dev); + + 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); + if (IS_ERR(pwrseq)) + return PTR_ERR(pwrseq); + + pwrseq_set_drvdata(pwrseq, pwrseq_sd8787); + + 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..4889fd5a11e0 --- /dev/null +++ b/drivers/power/pwrseq/pwrseq_simple.c @@ -0,0 +1,162 @@ +// 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_drvdata(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_drvdata(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_drvdata(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); + if (IS_ERR(pwrseq)) + return PTR_ERR(pwrseq); + + pwrseq_set_drvdata(pwrseq, pwrseq_simple); + + 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"); diff --git a/include/linux/pwrseq/driver.h b/include/linux/pwrseq/driver.h index bdb8a25a8504..0ca1d0311ab6 100644 --- a/include/linux/pwrseq/driver.h +++ b/include/linux/pwrseq/driver.h @@ -57,7 +57,7 @@ struct pwrseq *__devm_pwrseq_create(struct device *dev, struct module *owner, co * * Return: created instance or the wrapped error code. */ -#define pwrseq_create(dev, ops, data) __pwrseq_create((dev), THIS_MODULE, (ops)) +#define pwrseq_create(dev, ops) __pwrseq_create((dev), THIS_MODULE, (ops)) /** * devm_pwrseq_create() - devres-managed version of pwrseq_create @@ -71,7 +71,7 @@ struct pwrseq *__devm_pwrseq_create(struct device *dev, struct module *owner, co * * Return: created instance or the wrapped error code. */ -#define devm_pwrseq_create(dev, ops, data) __devm_pwrseq_create((dev), THIS_MODULE, (ops)) +#define devm_pwrseq_create(dev, ops) __devm_pwrseq_create((dev), THIS_MODULE, (ops)) void pwrseq_destroy(struct pwrseq *pwrseq); From patchwork Wed Oct 6 03:53: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: 12538507 X-Patchwork-Delegate: johannes@sipsolutions.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 63BF0C433F5 for ; Wed, 6 Oct 2021 03:55:19 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 4EFE1611C1 for ; Wed, 6 Oct 2021 03:55:19 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237820AbhJFD5H (ORCPT ); Tue, 5 Oct 2021 23:57:07 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:32958 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237324AbhJFD4I (ORCPT ); Tue, 5 Oct 2021 23:56:08 -0400 Received: from mail-lf1-x133.google.com (mail-lf1-x133.google.com [IPv6:2a00:1450:4864:20::133]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 57FA1C06178A for ; Tue, 5 Oct 2021 20:54:16 -0700 (PDT) Received: by mail-lf1-x133.google.com with SMTP id y26so4461359lfa.11 for ; Tue, 05 Oct 2021 20:54: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=9lmj4z2XmvtgOeyuCcLAR8+/FQoqDUZMLX1DvXWCDtk=; b=cMeYaNyTbMR8bGLWrM98suMs6L0Yshkz2dJCZMFbLzamLV+tOYwNg1q0EFd9rZZwzK s8gV/uthkE5+RN9/bQV52t78R7tU+hMwu5HPOWsXPtkNGO7hLm/LNVw8Hp2TBYl00uzz iymzZ1siy3Li2jScYl44aSSBG9jSWzs9v/KmkCDSZz9zzaaglKVqTaly7cIpwImQleY3 Jt4e6dBAOpLzYca9ka7Px/snHAZI4r9SdZ+9YGAvn14Rplfp5SBZVVELE7D81vuDlhfm aT8G1R+idv20rIeIr63bDBletPmiwDxaQNaFYqFaWNUbKY54EfayHITiwHWGc7opOUh9 we0A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=9lmj4z2XmvtgOeyuCcLAR8+/FQoqDUZMLX1DvXWCDtk=; b=T+aTE4Vza08SCFLRvl0W449G/rv2FXFx0H96wJU3KeZdMuNEY8IJCIQGpGvoHf0tGz YRlKLhUb0c3sVgg9vayo1KbsbqjBx1aNjtxceAKX5tSI+kHkVANHelSb+/PfXQ9B9//t kKvp+ZOPFssgfpqfBTXHz45IrAQUSTI4RNPjmUsXBnFRzUkE5ZzMbH8tCKun913REUDd 2QIrlvR+wPYCMuLJYoC4Bama+zSvu2Mtn7JsXeh2v8tORKyf0Kej+6wfu+IB48f9sRC6 /6TS1/k/aGt2DkuurYjCUbpPR1Yr3aywaYfXD3OejLN8qGFPZ0DJi8PIm11hDjdSN9FJ WBvA== X-Gm-Message-State: AOAM532jnNndVz6gXXnaxac/V7/lSK+hqdYabdPDXQKAKYfvrBJ2ncd3 e0m0nEtg8l8zT/uMQh/LBa14Hg== X-Google-Smtp-Source: ABdhPJzaab7eXLdHwpE+7i1SfolFjAbanjbGoslkWp1x8IKRGRFcoRzPguB7/mw2H4Kzt92jpXGVqA== X-Received: by 2002:a2e:7f14:: with SMTP id a20mr27460466ljd.259.1633492454543; Tue, 05 Oct 2021 20:54:14 -0700 (PDT) Received: from eriador.lan ([37.153.55.125]) by smtp.gmail.com with ESMTPSA id s4sm2142967lfd.103.2021.10.05.20.54.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 05 Oct 2021 20:54: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: [PATCH v1 04/15] mmc: core: switch to new pwrseq subsystem Date: Wed, 6 Oct 2021 06:53:56 +0300 Message-Id: <20211006035407.1147909-5-dmitry.baryshkov@linaro.org> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20211006035407.1147909-1-dmitry.baryshkov@linaro.org> References: <20211006035407.1147909-1-dmitry.baryshkov@linaro.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org Drop old MMC pwrseq code and use new pwrseq subsystem instead. Individual drivers are already ported to new subsystem. Signed-off-by: Dmitry Baryshkov --- drivers/mmc/core/Makefile | 1 - drivers/mmc/core/core.c | 9 ++- drivers/mmc/core/host.c | 8 ++- drivers/mmc/core/mmc.c | 3 +- drivers/mmc/core/pwrseq.c | 117 ------------------------------------ drivers/mmc/core/pwrseq.h | 58 ------------------ drivers/power/pwrseq/core.c | 8 +++ include/linux/mmc/host.h | 4 +- 8 files changed, 20 insertions(+), 188 deletions(-) delete mode 100644 drivers/mmc/core/pwrseq.c delete mode 100644 drivers/mmc/core/pwrseq.h diff --git a/drivers/mmc/core/Makefile b/drivers/mmc/core/Makefile index 322eb69bd00e..a504d873cf8e 100644 --- a/drivers/mmc/core/Makefile +++ b/drivers/mmc/core/Makefile @@ -9,7 +9,6 @@ mmc_core-y := core.o bus.o host.o \ sdio.o sdio_ops.o sdio_bus.o \ sdio_cis.o sdio_io.o sdio_irq.o \ slot-gpio.o regulator.o -mmc_core-$(CONFIG_OF) += pwrseq.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/core.c b/drivers/mmc/core/core.c index 240c5af793dc..c4b08067ab9f 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -41,7 +41,6 @@ #include "bus.h" #include "host.h" #include "sdio_bus.h" -#include "pwrseq.h" #include "mmc_ops.h" #include "sd_ops.h" @@ -1322,7 +1321,7 @@ void mmc_power_up(struct mmc_host *host, u32 ocr) if (host->ios.power_mode == MMC_POWER_ON) return; - mmc_pwrseq_pre_power_on(host); + pwrseq_pre_power_on(host->pwrseq); host->ios.vdd = fls(ocr) - 1; host->ios.power_mode = MMC_POWER_UP; @@ -1337,7 +1336,7 @@ void mmc_power_up(struct mmc_host *host, u32 ocr) */ mmc_delay(host->ios.power_delay_ms); - mmc_pwrseq_post_power_on(host); + pwrseq_power_on(host->pwrseq); host->ios.clock = host->f_init; @@ -1356,7 +1355,7 @@ void mmc_power_off(struct mmc_host *host) if (host->ios.power_mode == MMC_POWER_OFF) return; - mmc_pwrseq_power_off(host); + pwrseq_power_off(host->pwrseq); host->ios.clock = 0; host->ios.vdd = 0; @@ -1986,7 +1985,7 @@ EXPORT_SYMBOL(mmc_set_blocklen); static void mmc_hw_reset_for_init(struct mmc_host *host) { - mmc_pwrseq_reset(host); + pwrseq_reset(host->pwrseq); if (!(host->caps & MMC_CAP_HW_RESET) || !host->ops->hw_reset) return; diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c index d4683b1d263f..aa5326db7c60 100644 --- a/drivers/mmc/core/host.c +++ b/drivers/mmc/core/host.c @@ -28,7 +28,6 @@ #include "crypto.h" #include "host.h" #include "slot-gpio.h" -#include "pwrseq.h" #include "sdio_ops.h" #define cls_dev_to_mmc_host(d) container_of(d, struct mmc_host, class_dev) @@ -422,7 +421,11 @@ int mmc_of_parse(struct mmc_host *host) device_property_read_u32(dev, "post-power-on-delay-ms", &host->ios.power_delay_ms); - return mmc_pwrseq_alloc(host); + host->pwrseq = devm_pwrseq_get(dev, "mmc"); + if (IS_ERR(host->pwrseq)) + return PTR_ERR(host->pwrseq); + + return 0; } EXPORT_SYMBOL(mmc_of_parse); @@ -641,7 +644,6 @@ EXPORT_SYMBOL(mmc_remove_host); */ void mmc_free_host(struct mmc_host *host) { - mmc_pwrseq_free(host); put_device(&host->class_dev); } diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 29e58ffae379..d7e1c083fa12 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -24,7 +24,6 @@ #include "mmc_ops.h" #include "quirks.h" #include "sd_ops.h" -#include "pwrseq.h" #define DEFAULT_CMD6_TIMEOUT_MS 500 #define MIN_CACHE_EN_TIMEOUT_MS 1600 @@ -2222,7 +2221,7 @@ static int _mmc_hw_reset(struct mmc_host *host) } else { /* Do a brute force power cycle */ mmc_power_cycle(host, card->ocr); - mmc_pwrseq_reset(host); + pwrseq_reset(host->pwrseq); } return mmc_init_card(host, card->ocr, card); } diff --git a/drivers/mmc/core/pwrseq.c b/drivers/mmc/core/pwrseq.c deleted file mode 100644 index ef675f364bf0..000000000000 --- a/drivers/mmc/core/pwrseq.c +++ /dev/null @@ -1,117 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (C) 2014 Linaro Ltd - * - * Author: Ulf Hansson - * - * MMC power sequence management - */ -#include -#include -#include -#include - -#include - -#include "pwrseq.h" - -static DEFINE_MUTEX(pwrseq_list_mutex); -static LIST_HEAD(pwrseq_list); - -int mmc_pwrseq_alloc(struct mmc_host *host) -{ - struct device_node *np; - struct mmc_pwrseq *p; - - np = of_parse_phandle(host->parent->of_node, "mmc-pwrseq", 0); - if (!np) - return 0; - - mutex_lock(&pwrseq_list_mutex); - list_for_each_entry(p, &pwrseq_list, pwrseq_node) { - if (p->dev->of_node == np) { - if (!try_module_get(p->owner)) - dev_err(host->parent, - "increasing module refcount failed\n"); - else - host->pwrseq = p; - - break; - } - } - - of_node_put(np); - mutex_unlock(&pwrseq_list_mutex); - - if (!host->pwrseq) - return -EPROBE_DEFER; - - dev_info(host->parent, "allocated mmc-pwrseq\n"); - - return 0; -} - -void mmc_pwrseq_pre_power_on(struct mmc_host *host) -{ - struct mmc_pwrseq *pwrseq = host->pwrseq; - - if (pwrseq && pwrseq->ops->pre_power_on) - pwrseq->ops->pre_power_on(host); -} - -void mmc_pwrseq_post_power_on(struct mmc_host *host) -{ - struct mmc_pwrseq *pwrseq = host->pwrseq; - - if (pwrseq && pwrseq->ops->post_power_on) - pwrseq->ops->post_power_on(host); -} - -void mmc_pwrseq_power_off(struct mmc_host *host) -{ - struct mmc_pwrseq *pwrseq = host->pwrseq; - - if (pwrseq && pwrseq->ops->power_off) - pwrseq->ops->power_off(host); -} - -void mmc_pwrseq_reset(struct mmc_host *host) -{ - struct mmc_pwrseq *pwrseq = host->pwrseq; - - if (pwrseq && pwrseq->ops->reset) - pwrseq->ops->reset(host); -} - -void mmc_pwrseq_free(struct mmc_host *host) -{ - struct mmc_pwrseq *pwrseq = host->pwrseq; - - if (pwrseq) { - module_put(pwrseq->owner); - host->pwrseq = NULL; - } -} - -int mmc_pwrseq_register(struct mmc_pwrseq *pwrseq) -{ - if (!pwrseq || !pwrseq->ops || !pwrseq->dev) - return -EINVAL; - - mutex_lock(&pwrseq_list_mutex); - list_add(&pwrseq->pwrseq_node, &pwrseq_list); - mutex_unlock(&pwrseq_list_mutex); - - return 0; -} -EXPORT_SYMBOL_GPL(mmc_pwrseq_register); - -void mmc_pwrseq_unregister(struct mmc_pwrseq *pwrseq) -{ - if (pwrseq) { - mutex_lock(&pwrseq_list_mutex); - list_del(&pwrseq->pwrseq_node); - mutex_unlock(&pwrseq_list_mutex); - } -} -EXPORT_SYMBOL_GPL(mmc_pwrseq_unregister); diff --git a/drivers/mmc/core/pwrseq.h b/drivers/mmc/core/pwrseq.h deleted file mode 100644 index f3bb103db9ad..000000000000 --- a/drivers/mmc/core/pwrseq.h +++ /dev/null @@ -1,58 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (C) 2014 Linaro Ltd - * - * Author: Ulf Hansson - */ -#ifndef _MMC_CORE_PWRSEQ_H -#define _MMC_CORE_PWRSEQ_H - -#include - -struct mmc_host; -struct device; -struct module; - -struct mmc_pwrseq_ops { - void (*pre_power_on)(struct mmc_host *host); - void (*post_power_on)(struct mmc_host *host); - void (*power_off)(struct mmc_host *host); - void (*reset)(struct mmc_host *host); -}; - -struct mmc_pwrseq { - const struct mmc_pwrseq_ops *ops; - struct device *dev; - struct list_head pwrseq_node; - struct module *owner; -}; - -#ifdef CONFIG_OF - -int mmc_pwrseq_register(struct mmc_pwrseq *pwrseq); -void mmc_pwrseq_unregister(struct mmc_pwrseq *pwrseq); - -int mmc_pwrseq_alloc(struct mmc_host *host); -void mmc_pwrseq_pre_power_on(struct mmc_host *host); -void mmc_pwrseq_post_power_on(struct mmc_host *host); -void mmc_pwrseq_power_off(struct mmc_host *host); -void mmc_pwrseq_reset(struct mmc_host *host); -void mmc_pwrseq_free(struct mmc_host *host); - -#else - -static inline int mmc_pwrseq_register(struct mmc_pwrseq *pwrseq) -{ - return -ENOSYS; -} -static inline void mmc_pwrseq_unregister(struct mmc_pwrseq *pwrseq) {} -static inline int mmc_pwrseq_alloc(struct mmc_host *host) { return 0; } -static inline void mmc_pwrseq_pre_power_on(struct mmc_host *host) {} -static inline void mmc_pwrseq_post_power_on(struct mmc_host *host) {} -static inline void mmc_pwrseq_power_off(struct mmc_host *host) {} -static inline void mmc_pwrseq_reset(struct mmc_host *host) {} -static inline void mmc_pwrseq_free(struct mmc_host *host) {} - -#endif - -#endif diff --git a/drivers/power/pwrseq/core.c b/drivers/power/pwrseq/core.c index d29b4b97b95c..0aaba4e79a44 100644 --- a/drivers/power/pwrseq/core.c +++ b/drivers/power/pwrseq/core.c @@ -68,6 +68,14 @@ static struct pwrseq *_of_pwrseq_get(struct device *dev, const char *id) snprintf(prop_name, sizeof(prop_name), "%s-pwrseq", id); ret = of_parse_phandle_with_args(dev->of_node, prop_name, "#pwrseq-cells", 0, &args); + + /* + * Parsing failed. Try locating old bindings for mmc-pwrseq, which did + * not use #pwrseq-cells. + */ + if (ret == -EINVAL && !strcmp(id, "mmc")) + ret = of_parse_phandle_with_args(dev->of_node, prop_name, NULL, 0, &args); + if (ret == -ENOENT) return NULL; else if (ret < 0) diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index 0c0c9a0fdf57..f5daee6c1d7b 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -16,6 +16,7 @@ #include #include #include +#include struct mmc_ios { unsigned int clock; /* clock rate */ @@ -278,7 +279,6 @@ struct mmc_context_info { }; struct regulator; -struct mmc_pwrseq; struct mmc_supply { struct regulator *vmmc; /* Card power supply */ @@ -294,7 +294,7 @@ struct mmc_host { struct device class_dev; int index; const struct mmc_host_ops *ops; - struct mmc_pwrseq *pwrseq; + struct pwrseq *pwrseq; unsigned int f_min; unsigned int f_max; unsigned int f_init; From patchwork Wed Oct 6 03:53: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: 12538495 X-Patchwork-Delegate: johannes@sipsolutions.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 42F96C433EF for ; Wed, 6 Oct 2021 03:54:25 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 2DE156137C for ; Wed, 6 Oct 2021 03:54:25 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237425AbhJFD4N (ORCPT ); Tue, 5 Oct 2021 23:56:13 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:32962 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237346AbhJFD4J (ORCPT ); Tue, 5 Oct 2021 23:56:09 -0400 Received: from mail-lf1-x130.google.com (mail-lf1-x130.google.com [IPv6:2a00:1450:4864:20::130]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5938FC061760 for ; Tue, 5 Oct 2021 20:54:17 -0700 (PDT) Received: by mail-lf1-x130.google.com with SMTP id x27so4575274lfu.5 for ; Tue, 05 Oct 2021 20:54:17 -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=xiLuOKz2kvk1cz4G50uNXXciKxmoQzaWMMylpBwCLy8=; b=polX0w89CVBCN2mcuowNKfbRPyuzDIzwQxcUMvp3pSgIs1y7JVQpWtngRvq+waMU7b YNbLlO3w4Xb2/8f6XEubs/qJUOtQznrQBL7S2ecUcLV70S99fUjf2ZLGhnphtztogFJD w2ISSBLMGCOuMxGu1HjknOvyTtLj1b6S+cTqqBQr2EFtcwZaBnukHF8D0cMZM0tnx0nI uCV3MQ398im1coHH4Usy3IV2fXVi0Fbt1Xaj7AZyBH+aVkmKGsxd3nbtmF9TFr7DYgvV K4jnBP31CLG9cegrjQl9fWMYbNN4TUdiby8W9Rl0yr8BmdtlXAb9MIJWsfalRQ0iUxqQ XBfQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=xiLuOKz2kvk1cz4G50uNXXciKxmoQzaWMMylpBwCLy8=; b=QW2D544Gb/Hwn+O8hpayde3NfwMUiZALDcN7VkVRgkLr9YZWWDip12kIOTNu1JdHGJ ggHDiZMUO1sI60SX07XBFBsLRGOIrbNj+xXxJxmBUdWsV5fsQhlKaFuRvrIVlatpZHMf J1ycypGRm/ETtuTz1HDkxXDZqRScpATZaSAhIla00qRxTCOSnhez55NCzE4uQQ6+Vhc6 lVbJJ0qddEeoSZM8VRmDJBOewfdBA59vCUa5wgWrXsIwErvGFCZyjtkaYa9ia4cEZfIb Dl0XExIRw/h38ZXnR/NRhT8bJfzZxSLFpYo15eRJ/z621c9ZmIj3/9sLCjlgzJoq4mJK 67jw== X-Gm-Message-State: AOAM531l4is+7NVOQNBRPqSyiTqq5XlmdlOAbrI9Qrx1y9I3fphNnEeI os0Zkwe8Lz6nogCwaYv0KZMDQQ== X-Google-Smtp-Source: ABdhPJzlegaIltE1SIs8lAxvicfs57o+JcqU51cspIdlK5w/V62EiVjwgLcERznirqVXN7f7frEROg== X-Received: by 2002:ac2:4e0d:: with SMTP id e13mr7012924lfr.560.1633492455635; Tue, 05 Oct 2021 20:54:15 -0700 (PDT) Received: from eriador.lan ([37.153.55.125]) by smtp.gmail.com with ESMTPSA id s4sm2142967lfd.103.2021.10.05.20.54.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 05 Oct 2021 20:54: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: [PATCH v1 05/15] pwrseq: implement onecell helper Date: Wed, 6 Oct 2021 06:53:57 +0300 Message-Id: <20211006035407.1147909-6-dmitry.baryshkov@linaro.org> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20211006035407.1147909-1-dmitry.baryshkov@linaro.org> References: <20211006035407.1147909-1-dmitry.baryshkov@linaro.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org Provide of_pwrseq_xlate_onecell() - a helper easing implementation of power sequencers using one cell to determine pwrseq instance to return. Signed-off-by: Dmitry Baryshkov --- drivers/power/pwrseq/core.c | 26 ++++++++++++++++++++++++++ include/linux/pwrseq/driver.h | 12 ++++++++++++ 2 files changed, 38 insertions(+) diff --git a/drivers/power/pwrseq/core.c b/drivers/power/pwrseq/core.c index 0aaba4e79a44..3dffa52f65ee 100644 --- a/drivers/power/pwrseq/core.c +++ b/drivers/power/pwrseq/core.c @@ -449,6 +449,32 @@ struct pwrseq_provider *__devm_of_pwrseq_provider_register(struct device *dev, } EXPORT_SYMBOL_GPL(__devm_of_pwrseq_provider_register); +/** + * of_pwrseq_xlate_single() - returns the pwrseq instance from pwrseq provider using single index + * @data: the pwrseq provider data, struct pwrseq_onecell_data + * @args: of_phandle_args containing single integer index + * + * Intended to be used by pwrseq provider for the common case where + * #pwrseq-cells is 1. It will return corresponding pwrseq instance. + */ +struct pwrseq *of_pwrseq_xlate_onecell(void *data, struct of_phandle_args *args) +{ + struct pwrseq_onecell_data *pwrseq_data = data; + unsigned int idx; + + if (args->args_count != 1) + return ERR_PTR(-EINVAL); + + idx = args->args[0]; + if (idx >= pwrseq_data->num) { + pr_err("%s: invalid index %u\n", __func__, idx); + return ERR_PTR(-EINVAL); + } + + return pwrseq_data->pwrseqs[idx]; +} +EXPORT_SYMBOL_GPL(of_pwrseq_xlate_onecell); + static int __init pwrseq_core_init(void) { return class_register(&pwrseq_class); diff --git a/include/linux/pwrseq/driver.h b/include/linux/pwrseq/driver.h index 0ca1d0311ab6..8d46940981bf 100644 --- a/include/linux/pwrseq/driver.h +++ b/include/linux/pwrseq/driver.h @@ -157,4 +157,16 @@ static inline struct pwrseq *of_pwrseq_xlate_single(void *data, return data; } +/** + * struct pwrseq_onecell_data - pwrseq data for of_pwrseq_xlate_onecell + * @num: amount of instances in @owrseqs + * @pwrseqs: array of pwrseq instances + */ +struct pwrseq_onecell_data { + unsigned int num; + struct pwrseq *pwrseqs[]; +}; + +struct pwrseq *of_pwrseq_xlate_onecell(void *data, struct of_phandle_args *args); + #endif /* __LINUX_PWRSEQ_DRIVER_H__ */ From patchwork Wed Oct 6 03:53: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: 12538497 X-Patchwork-Delegate: johannes@sipsolutions.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 16C72C433EF for ; Wed, 6 Oct 2021 03:54:35 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id F3335613AC for ; Wed, 6 Oct 2021 03:54:34 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230409AbhJFD4Y (ORCPT ); Tue, 5 Oct 2021 23:56:24 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:32980 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237362AbhJFD4K (ORCPT ); Tue, 5 Oct 2021 23:56:10 -0400 Received: from mail-lf1-x12e.google.com (mail-lf1-x12e.google.com [IPv6:2a00:1450:4864:20::12e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6A7D4C061794 for ; Tue, 5 Oct 2021 20:54:18 -0700 (PDT) Received: by mail-lf1-x12e.google.com with SMTP id i24so4407498lfj.13 for ; Tue, 05 Oct 2021 20:54: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=mcNit0g6jUmmUjsU7FAtIRduJRJ7wpPHtyysZeeAHFY=; b=Xh2nneBb/87+tArNL4Ub5gViAzfXJDIt0nN7Bymb9OpZLb9P/imlrckWJlA/M+3cTt 7c8eGMzP7lXSIDLkTnIlfWXLR6Xt8rclJjKYOUk4e73SzYY5wYBvp2wpcbGuRMrQRVAv pNJ0hBoGw9uU0TfZASPIBvt36O//ykJfspidjcIBqyIqYOZBX/QzyrooyiirypL/kuXu 8tdfTQXThfx9NQsFJCPxqhgIjTpcA6bKlxLAp0JTBCeEwhnvOiswNRfaC3Rhbx2jvg2N enaYRfssXa/hK05/CkZxpLji7C7cni+x1/ooPHyZAFJhfzZw6eKLiuxEBSKAx79g7fSf cqyA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=mcNit0g6jUmmUjsU7FAtIRduJRJ7wpPHtyysZeeAHFY=; b=jx0sSbfLXu7+2buTMhw+9aXMNfQRkjC8d0GnZlXDkgJ+XZAbsHDJEjESBG6iCmqUDX tJl8ODhKybDN4zW/M4TY2Zry54E6sURI0F84FhBiRibIe8IU2+K0ctmz4KslIlB2Qvc+ NptsZvfaxwNFv7hUqeoEa2TNxIUxH2ZKVjKMAk5fqk+aF3GPinsWzMbp2y1WCPWEHV4+ iTk5imCZ3co8nsmhQYv+PnQT5t4GHZKlmIdyDWdv9xi/J6737cWjGUo2QTTXpxo7jS6i 422DhJOi0cNjyFC6YoUrpPzsTKNYD1FaUTvD0p9rgAjEJ5IntK0pEC4gtc7gQL+V1IDw uCkw== X-Gm-Message-State: AOAM532C1Q0HTJOCXqB4xtZWQQwo51iz9Pzha3kLcdnzSwVxm6La3509 +8s3leEserC42u3hf+BZdn3yQQ== X-Google-Smtp-Source: ABdhPJz1kFyKYOWjo2k7SexA6deiKwcYASU6DfLmY4tB7DuImqXPFUkuj8BoRxRFiJxUQoWHk0T4Xg== X-Received: by 2002:a05:651c:1615:: with SMTP id f21mr11860995ljq.318.1633492456613; Tue, 05 Oct 2021 20:54:16 -0700 (PDT) Received: from eriador.lan ([37.153.55.125]) by smtp.gmail.com with ESMTPSA id s4sm2142967lfd.103.2021.10.05.20.54.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 05 Oct 2021 20:54: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: [PATCH v1 06/15] pwrseq: add support for QCA BT+WiFi power sequencer Date: Wed, 6 Oct 2021 06:53:58 +0300 Message-Id: <20211006035407.1147909-7-dmitry.baryshkov@linaro.org> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20211006035407.1147909-1-dmitry.baryshkov@linaro.org> References: <20211006035407.1147909-1-dmitry.baryshkov@linaro.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-wireless@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 | 373 ++++++++++++++++++++++++++++++ 3 files changed, 388 insertions(+) create mode 100644 drivers/power/pwrseq/pwrseq_qca.c diff --git a/drivers/power/pwrseq/Kconfig b/drivers/power/pwrseq/Kconfig index 1985f13d9193..7983e37c7855 100644 --- a/drivers/power/pwrseq/Kconfig +++ b/drivers/power/pwrseq/Kconfig @@ -22,6 +22,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..c15508cc80d2 --- /dev/null +++ b/drivers/power/pwrseq/pwrseq_qca.c @@ -0,0 +1,373 @@ +// 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_drvdata(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_drvdata(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_drvdata(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); + if (IS_ERR(pwrseq)) + return PTR_ERR(pwrseq); + + pwrseq_set_drvdata(pwrseq, &pwrseq_qca->pwrseq_qcas[i]); + + 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 Wed Oct 6 03:53: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: 12538499 X-Patchwork-Delegate: johannes@sipsolutions.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3DCFDC43217 for ; Wed, 6 Oct 2021 03:54:40 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 253F5611C1 for ; Wed, 6 Oct 2021 03:54:40 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237360AbhJFD4Z (ORCPT ); Tue, 5 Oct 2021 23:56:25 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:32970 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237376AbhJFD4L (ORCPT ); Tue, 5 Oct 2021 23:56:11 -0400 Received: from mail-lf1-x133.google.com (mail-lf1-x133.google.com [IPv6:2a00:1450:4864:20::133]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 437F4C061783 for ; Tue, 5 Oct 2021 20:54:19 -0700 (PDT) Received: by mail-lf1-x133.google.com with SMTP id x27so4496361lfa.9 for ; Tue, 05 Oct 2021 20:54:19 -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=NeHIhsZMUr5ykJB6Caqyp6Vh5XIKp8x7h5mO8Gk2lJA=; b=JUxbS46H6NBi4pyhUO9ZGHUxljkmmFsu0pJ1MztZTmIx0lOvzlLsrza/qzXhdcfkqA tzHNBu7cho4Ik8BtD9OCsxGoTX0Zhkwq7V+9F31Nt/K4XnLL1j9MSWzoIl+BfwAi2zvB cnoAJpYHzi8Km7qVHJnTMsUttYGJWKqH5V5h3gMpzb4xJ14mpDQrGrl7RvE2hInpCSoP MSAkuk5ii1PH1RSLcCglGm7JDtaOdzA5caqSLHHPViXNkIbGS7xeO+YNFWkqoYHM5IAS MMI7xXBA/oj04pXU6xndAQjW3s2+1gueXHAu78GYMaidhyyqvCgOyGi6JYaoeHC87Xo2 bLQw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=NeHIhsZMUr5ykJB6Caqyp6Vh5XIKp8x7h5mO8Gk2lJA=; b=zZ3+Hh3FoZLM2M8YBhzgRfEpdMYNIsPz9UIMtTg7dMCgu29SOUexEovusxgshMfwem CHvpCJhAp9pSQMpI8DLCoq7+k/k6NJRWRXq62ThsTFVFnfKj8PJWoQkm8i9U8PEioccm dhfJzDABoZKYOIpfUGDCvFw65o12EPCrp/rR02um0j9jYDRcWW3uTFkzRD2x+Qgyn6d0 czm8XfVTETwgJ+tojJka48U0sRffj0rZHpTx+8IrwEI9+ONcxzdbHaGK/GlQe59QwlTh C3uimODJPa1JR1trxfe/12jUaOMpF5e4FgcabpVEpjwSYktoF7ihMv02MOL92ruJWaQy ssFQ== X-Gm-Message-State: AOAM533zZqzWo70oWDXSf3tUs6WEEz2kek2W/P9VfUuTw8B7wR9BfQsD Fw3zRR7YQeeBuVO7/ux84/cnpg== X-Google-Smtp-Source: ABdhPJyK9tu7tnCJm/AWi0OyoXXi8YhLObOtc76v0sfowxgHmlXe9CSRMktSA+i8KUxBsBoAP8bIPg== X-Received: by 2002:a19:7109:: with SMTP id m9mr7621114lfc.112.1633492457604; Tue, 05 Oct 2021 20:54:17 -0700 (PDT) Received: from eriador.lan ([37.153.55.125]) by smtp.gmail.com with ESMTPSA id s4sm2142967lfd.103.2021.10.05.20.54.16 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 05 Oct 2021 20:54: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: [PATCH v1 07/15] pwrseq: add fallback support Date: Wed, 6 Oct 2021 06:53:59 +0300 Message-Id: <20211006035407.1147909-8-dmitry.baryshkov@linaro.org> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20211006035407.1147909-1-dmitry.baryshkov@linaro.org> References: <20211006035407.1147909-1-dmitry.baryshkov@linaro.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-wireless@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 | 88 +++++++++++++++++++++++++++++++++ include/linux/pwrseq/fallback.h | 60 ++++++++++++++++++++++ 4 files changed, 152 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 3dffa52f65ee..30380ca6159a 100644 --- a/drivers/power/pwrseq/core.c +++ b/drivers/power/pwrseq/core.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #define to_pwrseq(a) (container_of((a), struct pwrseq, dev)) @@ -120,6 +121,8 @@ struct pwrseq * pwrseq_get(struct device *dev, const char *id) struct pwrseq *pwrseq; pwrseq = _of_pwrseq_get(dev, id); + if (pwrseq == NULL) + pwrseq = pwrseq_fallback_get(dev, id); if (IS_ERR_OR_NULL(pwrseq)) return pwrseq; diff --git a/drivers/power/pwrseq/fallback.c b/drivers/power/pwrseq/fallback.c new file mode 100644 index 000000000000..b83bd5795ccb --- /dev/null +++ b/drivers/power/pwrseq/fallback.c @@ -0,0 +1,88 @@ +// 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); + +/** + * __pwrseq_fallback_register - internal helper for pwrseq_fallback_register + * @fallback - struct pwrseq_fallback to be registered + * @owner: module containing fallback callback + * + * Internal helper for pwrseq_fallback_register. It should not be called directly. + */ +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); + +/** + * pwrseq_fallback_unregister() - unregister fallback helper + * @fallback - struct pwrseq_fallback to unregister + * + * Unregister pwrseq fallback handler registered by pwrseq_fallback_handler. + */ +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..14f9aa527692 --- /dev/null +++ b/include/linux/pwrseq/fallback.h @@ -0,0 +1,60 @@ +/* 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 - structure providing fallback data/ + * @list: a list node for the fallback handlers + * @owner: module containing fallback callback + * @of_match_table: match table for this fallback + * + * Pwrseq fallback is a mechanism for handling backwards compatibility in the + * case device tree was not updated to use proper pwrseq providers. + * + * In case the pwrseq instance is not registered, core will automatically try + * locating and calling fallback getter. If the requesting device matches + * against @of_match_table, the @get callback will be called to retrieve pwrseq + * instance. + * + * The driver should fill of_match_table and @get fields only. @list and @owner + * will be filled by the core code. + */ +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); + +/** + * pwrseq_fallback_register() - register fallback helper + * @fallback - struct pwrseq_fallback to be registered + * + * Register pwrseq fallback handler to assist pwrseq core. + */ +#define pwrseq_fallback_register(fallback) __pwrseq_fallback_register(fallback, THIS_MODULE) + +void pwrseq_fallback_unregister(struct pwrseq_fallback *fallback); + +/* internal interface to be used by pwrseq core */ +struct pwrseq *pwrseq_fallback_get(struct device *dev, const char *id); + +#endif /* __LINUX_PWRSEQ_DRIVER_H__ */ From patchwork Wed Oct 6 03:54:00 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Baryshkov X-Patchwork-Id: 12538503 X-Patchwork-Delegate: johannes@sipsolutions.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id EFE99C433EF for ; Wed, 6 Oct 2021 03:55:10 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id DC9A36120F for ; Wed, 6 Oct 2021 03:55:10 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237755AbhJFD45 (ORCPT ); Tue, 5 Oct 2021 23:56:57 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:33008 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237394AbhJFD4L (ORCPT ); Tue, 5 Oct 2021 23:56: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 20408C061788 for ; Tue, 5 Oct 2021 20:54:20 -0700 (PDT) Received: by mail-lf1-x132.google.com with SMTP id b20so4612625lfv.3 for ; Tue, 05 Oct 2021 20:54:19 -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=20pfiPj2Llz4cGLyPgKlOrfQmUN7w2lzAc5IpSkv3GI=; b=IXkrOb5Iz/JfPhzwI6v3Kgqqknyi/+bInvUv07kFzlxnKMk7JFNeHghZz54DiHXAIs Zhuj6VbGzDcX16B0S3Gf44y4VWWpqDq/uN3SHSd9RXjCx7bMgdiLf0skAmQj5ibRB+SP bMr8EDVuYCvdaAVEvrY6+z63Q/Vdb+mAL5YNkN+e0Ef7X0Y+psZvfNO2+41l1qiCx9MW wZlre7qC58F/fnFMGA+c/nzKZ7BjHhtKSDPzsID+876qdzyc2jcb7OokLuxaaEDGi/Up NIfEoUCeX3eCvIRWnv6ylatWevkMaY+xdMXtmguz5z6yj5/eZe6cDBzSIi8MUReYCyIj /aaw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=20pfiPj2Llz4cGLyPgKlOrfQmUN7w2lzAc5IpSkv3GI=; b=Yh3YJ0YuIjf8cEpIAfcSH70WH/26pM1W+PcugyrBljETRMNiBWv4yu9r/D0P4VC7oG EKxUyXqi8AtgYOPe0ZveJriTm8MZGnJw+4nFu5X39qE8J3w5qZpJQ5Wu7iqUEaLGzTmc XiI5GmIYbFMrYQL3mVqpHv1qzqinI0x8k/8qPdoyWaP3F9X9jDoklz9otV3/RQdCqOVC nBNZgoBNT052ynAFmSGUy+xrWdw8y9N6rENR2ORaUNUEbLwh4TRmb89a15LRgBZizeO/ deZhRbzXTQvi9CpxF5g76+8RAznq+IKcg7WFNPRlY8t4i7TcUJH8+gHnsJBBfk0MYeVR 9RXA== X-Gm-Message-State: AOAM530WbpBL5A7WX3vhzMt9VG7rA94L+5ju+9UuDPCxkUcIC2ot7CFZ TEXNqEW7hjF7ggZRDTq6f4GjHg== X-Google-Smtp-Source: ABdhPJx2PiFO+bVt8FwHx7jFT762AVaMkoQ2aY0tZJ1LZSdXu3KJP7oFaqeQQPTPuEqluhV/4Q2+3A== X-Received: by 2002:a05:6512:1293:: with SMTP id u19mr7205262lfs.218.1633492458405; Tue, 05 Oct 2021 20:54:18 -0700 (PDT) Received: from eriador.lan ([37.153.55.125]) by smtp.gmail.com with ESMTPSA id s4sm2142967lfd.103.2021.10.05.20.54.17 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 05 Oct 2021 20:54:17 -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: [PATCH v1 08/15] pwrseq: pwrseq_qca: implement fallback support Date: Wed, 6 Oct 2021 06:54:00 +0300 Message-Id: <20211006035407.1147909-9-dmitry.baryshkov@linaro.org> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20211006035407.1147909-1-dmitry.baryshkov@linaro.org> References: <20211006035407.1147909-1-dmitry.baryshkov@linaro.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-wireless@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 | 155 +++++++++++++++++++++++++++++- 1 file changed, 154 insertions(+), 1 deletion(-) diff --git a/drivers/power/pwrseq/pwrseq_qca.c b/drivers/power/pwrseq/pwrseq_qca.c index c15508cc80d2..f237cf2f1880 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 */ @@ -369,5 +371,156 @@ 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; + struct pwrseq *pwrseq; + 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); + } + + pwrseq = devm_pwrseq_create(dev, &pwrseq_qca_ops); + if (IS_ERR(pwrseq)) + return pwrseq; + + pwrseq_set_drvdata(pwrseq, &fallback->qca_one); + + return pwrseq; +} + +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 Wed Oct 6 03:54: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: 12538501 X-Patchwork-Delegate: johannes@sipsolutions.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 15B18C433EF for ; Wed, 6 Oct 2021 03:54:56 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id F0DCC611C1 for ; Wed, 6 Oct 2021 03:54:55 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237664AbhJFD4m (ORCPT ); Tue, 5 Oct 2021 23:56:42 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:32974 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237408AbhJFD4M (ORCPT ); Tue, 5 Oct 2021 23:56:12 -0400 Received: from mail-lf1-x135.google.com (mail-lf1-x135.google.com [IPv6:2a00:1450:4864:20::135]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4B074C061764 for ; Tue, 5 Oct 2021 20:54:21 -0700 (PDT) Received: by mail-lf1-x135.google.com with SMTP id y15so4540227lfk.7 for ; Tue, 05 Oct 2021 20:54: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=gdZGnwzEHVfU1lQviDSHFvhmNm98xNMbizrp42xP5ec=; b=ZIA3rODl2Ki9rPwRisOcBTnXWSqii6n74k4f+ncNlaH1T5a6RLVb1Ss1eRKXh1Up17 vx1n0JKLCUIn38lw/DBB535C0HaXoslYGo2N8KvPyMaRNdVBmkiHim6wtwusIKmxob1X 6lK5aeZYKBTOkgvd9sld6YmfOhvBIRX/9fKZRJCYRd04ZDVZyl3VWZYLO2QdFBXpzuTG nWlk1Ypn7QiipOPhGTPOWTMQ2rg6vxpBLe9IO3kYHkjOow/3p92OwKgpc28HBAzn0cZj v9fXFMuq3kKIc7lLX6iaDfi9m+fulgjvi1TOPZAXSmkr/0UxSKB3ctedYtGMDb3X852e 5+SA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=gdZGnwzEHVfU1lQviDSHFvhmNm98xNMbizrp42xP5ec=; b=fOaSsmdDuEz3TsECQzfba/9fF4Lyyo3+wXQZhnlnaANPYQetTfgeo5Ul98OZprdQtR WdXCjZz5GreDRyhxVrgALxNbN2h6nQZBaCZzTB7pJjynhZVB1J9jwZFArxvTlnTYaFY9 bxC/zm8ak/S/K7TzRRGlsW9s2XbP9JfsrSHMFHLWljqqOTJm715v6YN64nFIhVPiGRaw uFLkz3vpkl7CcsShYbfljiB33sZ425S5g5yuRJ2IxIpY9/OZuJNVNIfijNXhnE3RNKSb Xyktp99lAZBvMm5YlNzSQF9i/AqfvLMsz+i1OGbxQuwS4FJAbo505+lDKA1AWs9VnjWJ n48w== X-Gm-Message-State: AOAM531sv6G2Er1EpnyqNhVOl8W50N8LFCO6wMw6zL31n4wti8pPUbKH MH4Xdk7wRRMYXqSEWVLhFwmtPw== X-Google-Smtp-Source: ABdhPJxzhMHB0ZOu4M1vx77IDO1IB+dljeAqv68Ezgyq9e5/Vs1iyNXOSiVStQ9mZbpCrgO/IVZWkQ== X-Received: by 2002:a2e:9c4b:: with SMTP id t11mr26711712ljj.376.1633492459533; Tue, 05 Oct 2021 20:54:19 -0700 (PDT) Received: from eriador.lan ([37.153.55.125]) by smtp.gmail.com with ESMTPSA id s4sm2142967lfd.103.2021.10.05.20.54.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 05 Oct 2021 20:54:18 -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: [PATCH v1 09/15] Bluetooth: hci_qca: switch to using pwrseq Date: Wed, 6 Oct 2021 06:54:01 +0300 Message-Id: <20211006035407.1147909-10-dmitry.baryshkov@linaro.org> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20211006035407.1147909-1-dmitry.baryshkov@linaro.org> References: <20211006035407.1147909-1-dmitry.baryshkov@linaro.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org Signed-off-by: Dmitry Baryshkov --- drivers/bluetooth/hci_qca.c | 260 +++++------------------------------- 1 file changed, 37 insertions(+), 223 deletions(-) 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 Wed Oct 6 03:54:02 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Baryshkov X-Patchwork-Id: 12538513 X-Patchwork-Delegate: kvalo@adurom.com Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2D331C433EF for ; Wed, 6 Oct 2021 03:55:31 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 176D9611C1 for ; Wed, 6 Oct 2021 03:55:31 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237841AbhJFD5K (ORCPT ); Tue, 5 Oct 2021 23:57:10 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:32986 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237489AbhJFD4W (ORCPT ); Tue, 5 Oct 2021 23:56:22 -0400 Received: from mail-lf1-x12d.google.com (mail-lf1-x12d.google.com [IPv6:2a00:1450:4864:20::12d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 42964C06178C for ; Tue, 5 Oct 2021 20:54:22 -0700 (PDT) Received: by mail-lf1-x12d.google.com with SMTP id u18so4430424lfd.12 for ; Tue, 05 Oct 2021 20:54:22 -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=gLxBTtcfVl4dtJ5J9RXz2IWihrIE1icg8208P8LI768=; b=o7/Ze/q0htXc3MD9r6CcG3LU411fiLFkjclIYt5gxydc/GKQKyTk+c7fhvbcoYtnXY 7/e9Y6P+WvNC7PaRnuR6Fs8f/HGSu4cm8HPQMOPF+D42Ao70Z9MCpH+fqsIDFK5zJkDR R6gWSvzoe/3HsUDPDcO1qFwjWV7xhaNAeaxJGZ4Ca0smcF2WjV7pCfl0Im0ofCDBFxmf ZqpC8OxUr+Gjxy55TUUZGalgayt6UEOiDNBvCOqr7z2uJPL94ZyCRoG6wWTIlDvMj9/F Fom9EcqTv3xJHX1Gutf93jM/YB4tttS/qRFlfCz1mTrwIXBMkWVUSeIxW/9VKgUMzgNQ ExTA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=gLxBTtcfVl4dtJ5J9RXz2IWihrIE1icg8208P8LI768=; b=DV5xIRnbYiOJnris/0w8t5Fgh9eTc6rl7IxuTFKeW5OE26DImh8E2GPQy5042D5W3W pCQMgOoAVMlprenHlaI8UZm45x7snsqBonsUDLF/04EylVfvhqIKmDqXmfzRzncevBQ8 N0LxdyL4lSqBcAQWHe1Rv27M6cw+cLW9laOLu7cQIpJM/O/dH63qAEanyckaeWMSThzP h9S+euT8Smy09L3y9ZFu/2oVXDWKbBIg6JCtjtRb192J7hUIQ4rcLqtb146Iorf1Xidq v3TMYUU10N9lJw+6FDWs2BwTF48NPaewM4I7cYYa+IRc2eJ8/wE6oeAAA9k2BQ1eFFkd SnUg== X-Gm-Message-State: AOAM532J3NIfIDBjg0e1KhWE2oJcMqWKtzFd6eh4246AAM4ngPgRmy1R Ycy7U6nDE5c4Y15BcR+HZ5fwcA== X-Google-Smtp-Source: ABdhPJy89+pMq9hJpLFoCh7hciqRs5MkSybaUyFLo80FMybatgUVnxZf/pBhBn/cocZ6nF3Qd4LzIg== X-Received: by 2002:ac2:4c51:: with SMTP id o17mr7353777lfk.457.1633492460649; Tue, 05 Oct 2021 20:54:20 -0700 (PDT) Received: from eriador.lan ([37.153.55.125]) by smtp.gmail.com with ESMTPSA id s4sm2142967lfd.103.2021.10.05.20.54.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 05 Oct 2021 20:54: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: [PATCH v1 10/15] ath10k: add support for pwrseq sequencing Date: Wed, 6 Oct 2021 06:54:02 +0300 Message-Id: <20211006035407.1147909-11-dmitry.baryshkov@linaro.org> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20211006035407.1147909-1-dmitry.baryshkov@linaro.org> References: <20211006035407.1147909-1-dmitry.baryshkov@linaro.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org Power sequencing for Qualcomm WiFi+BT chipsets are being reworked to use pwrseq rather than individually handling all the regulators. Add support for pwrseq to ath10k SNOC driver. Signed-off-by: Dmitry Baryshkov Acked-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/snoc.c | 45 +++++++++++++------------- drivers/net/wireless/ath/ath10k/snoc.h | 4 +-- 2 files changed, 25 insertions(+), 24 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/snoc.c b/drivers/net/wireless/ath/ath10k/snoc.c index ea00fbb15601..8578c56982df 100644 --- a/drivers/net/wireless/ath/ath10k/snoc.c +++ b/drivers/net/wireless/ath/ath10k/snoc.c @@ -14,6 +14,7 @@ #include #include #include +#include #include "ce.h" #include "coredump.h" @@ -41,14 +42,6 @@ static char *const ce_name[] = { "WLAN_CE_11", }; -static const char * const ath10k_regulators[] = { - "vdd-0.8-cx-mx", - "vdd-1.8-xo", - "vdd-1.3-rfa", - "vdd-3.3-ch0", - "vdd-3.3-ch1", -}; - static const char * const ath10k_clocks[] = { "cxo_ref_clk_pin", "qdss", }; @@ -1010,10 +1003,14 @@ static int ath10k_hw_power_on(struct ath10k *ar) ath10k_dbg(ar, ATH10K_DBG_SNOC, "soc power on\n"); - ret = regulator_bulk_enable(ar_snoc->num_vregs, ar_snoc->vregs); + ret = pwrseq_full_power_on(ar_snoc->pwrseq); if (ret) return ret; + ret = regulator_enable(ar_snoc->vreg_cx_mx); + if (ret) + goto vreg_pwrseq_off; + ret = clk_bulk_prepare_enable(ar_snoc->num_clks, ar_snoc->clks); if (ret) goto vreg_off; @@ -1021,11 +1018,14 @@ static int ath10k_hw_power_on(struct ath10k *ar) return ret; vreg_off: - regulator_bulk_disable(ar_snoc->num_vregs, ar_snoc->vregs); + regulator_disable(ar_snoc->vreg_cx_mx); +vreg_pwrseq_off: + pwrseq_power_off(ar_snoc->pwrseq); + return ret; } -static int ath10k_hw_power_off(struct ath10k *ar) +static void ath10k_hw_power_off(struct ath10k *ar) { struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar); @@ -1033,7 +1033,9 @@ static int ath10k_hw_power_off(struct ath10k *ar) clk_bulk_disable_unprepare(ar_snoc->num_clks, ar_snoc->clks); - return regulator_bulk_disable(ar_snoc->num_vregs, ar_snoc->vregs); + regulator_disable(ar_snoc->vreg_cx_mx); + + pwrseq_power_off(ar_snoc->pwrseq); } static void ath10k_snoc_wlan_disable(struct ath10k *ar) @@ -1691,20 +1693,19 @@ static int ath10k_snoc_probe(struct platform_device *pdev) goto err_release_resource; } - ar_snoc->num_vregs = ARRAY_SIZE(ath10k_regulators); - ar_snoc->vregs = devm_kcalloc(&pdev->dev, ar_snoc->num_vregs, - sizeof(*ar_snoc->vregs), GFP_KERNEL); - if (!ar_snoc->vregs) { - ret = -ENOMEM; + ar_snoc->pwrseq = devm_pwrseq_get(&pdev->dev, "wifi"); + if (IS_ERR(ar_snoc->pwrseq)) { + ret = PTR_ERR(ar_snoc->pwrseq); + if (ret != -EPROBE_DEFER) + ath10k_warn(ar, "failed to acquire pwrseq: %d\n", ret); goto err_free_irq; } - for (i = 0; i < ar_snoc->num_vregs; i++) - ar_snoc->vregs[i].supply = ath10k_regulators[i]; - ret = devm_regulator_bulk_get(&pdev->dev, ar_snoc->num_vregs, - ar_snoc->vregs); - if (ret < 0) + ar_snoc->vreg_cx_mx = devm_regulator_get(&pdev->dev, "vdd-0.8-cx-mx"); + if (IS_ERR(ar_snoc->vreg_cx_mx)) { + ret = PTR_ERR(ar_snoc->vreg_cx_mx); goto err_free_irq; + } ar_snoc->num_clks = ARRAY_SIZE(ath10k_clocks); ar_snoc->clks = devm_kcalloc(&pdev->dev, ar_snoc->num_clks, diff --git a/drivers/net/wireless/ath/ath10k/snoc.h b/drivers/net/wireless/ath/ath10k/snoc.h index 5095d1893681..5188d6f6f850 100644 --- a/drivers/net/wireless/ath/ath10k/snoc.h +++ b/drivers/net/wireless/ath/ath10k/snoc.h @@ -70,10 +70,10 @@ struct ath10k_snoc { struct ath10k_snoc_ce_irq ce_irqs[CE_COUNT_MAX]; struct ath10k_ce ce; struct timer_list rx_post_retry; - struct regulator_bulk_data *vregs; - size_t num_vregs; + struct regulator *vreg_cx_mx; struct clk_bulk_data *clks; size_t num_clks; + struct pwrseq *pwrseq; struct ath10k_qmi *qmi; unsigned long flags; bool xo_cal_supported; From patchwork Wed Oct 6 03:54:03 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Baryshkov X-Patchwork-Id: 12538509 X-Patchwork-Delegate: johannes@sipsolutions.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2080FC433FE for ; Wed, 6 Oct 2021 03:55:24 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 0FF9B611C1 for ; Wed, 6 Oct 2021 03:55:24 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237659AbhJFD5N (ORCPT ); Tue, 5 Oct 2021 23:57:13 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:32988 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237508AbhJFD4X (ORCPT ); Tue, 5 Oct 2021 23:56:23 -0400 Received: from mail-lf1-x135.google.com (mail-lf1-x135.google.com [IPv6:2a00:1450:4864:20::135]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4E9F2C0617A4 for ; Tue, 5 Oct 2021 20:54:23 -0700 (PDT) Received: by mail-lf1-x135.google.com with SMTP id y23so4777026lfb.0 for ; Tue, 05 Oct 2021 20:54:23 -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=/yFX2Zi7N+6O7NNekyBMBaaX61kWJ67YZ/rDfO9/pCo=; b=wbt/SYeVTpGchHAcroGs65Of1AQiUTTG33akfUx79AzYY7nm6RIYq5RhUXp+c9Jys4 nXiObPAc9jCzAYIZ1poh6hdKRe+bj0bgMbS88p28gO6wqFmeLTYm4zuoD4+T3MhC6yjW ZepDlWf6ARy8vZhxqA1b3B0t0KcRz9417nhNZY94WNepBe4GPa6KVt65f7s9X/t4aZDk shoOxtV8sXrBvfORX2E4aaC1h8l1zuhYA8z4UiPS3Eu3WEKvzDt2tSUCWnrG0Jrlo5AG Qcx1rElX2rZ8uflS2LqYwzGzlTy4ej8i4J3tGxc/Gc0S07QUgsx8cN9arN3kElLOU6aF ypyg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=/yFX2Zi7N+6O7NNekyBMBaaX61kWJ67YZ/rDfO9/pCo=; b=v3A9AYPr+/+k8/5jDP1/4/6qj3LV/Rk07bpiAZvWwF4IlbP4H5XWjrncGeWNQZlDLx cxqc7cpdlE53Gk8cmKX3eu1jLi9BVouq0V2UT82cbLdWJdTCJ1EVf6DP6yuCwxzIb9Ku GT4TEXJTS13cZyX4TlbEjUteYqQcp+V2P5fiOnIDtzPAdkzj9dKIQ52BAT0yBAylZ1MA v7+gLLCK35Ua63tGzPmGAc73mXuJSpcddOqJ9e2xM9k8//Hi6R7wv7WZsZ7ZKEzEMtCD 6EWnVmXmgb2QR5BkEdo3k16A2J7GxuLPnNs9x5wxbIzQoBaId8fRmkn7KtLxSZgey4Mn lQtQ== X-Gm-Message-State: AOAM531X1EbyqHOfrCyivufESotqK2ZokAiVa+POIOnLHHuIAJQ6EjGw FOsOLvn4bi2Sj4F1tMF/ZTjueg== X-Google-Smtp-Source: ABdhPJwT5ag+B+NF1iSiO5FkQOo/yXhp0aFso0y+wwdL536y1fd1PVtCEaOvxXhyUrfGhnEPv5FIjg== X-Received: by 2002:a05:6512:2341:: with SMTP id p1mr7186976lfu.204.1633492461726; Tue, 05 Oct 2021 20:54:21 -0700 (PDT) Received: from eriador.lan ([37.153.55.125]) by smtp.gmail.com with ESMTPSA id s4sm2142967lfd.103.2021.10.05.20.54.20 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 05 Oct 2021 20:54:21 -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: [PATCH v1 11/15] arm64: dts: qcom: sdm845-db845c: switch bt+wifi to qca power sequencer Date: Wed, 6 Oct 2021 06:54:03 +0300 Message-Id: <20211006035407.1147909-12-dmitry.baryshkov@linaro.org> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20211006035407.1147909-1-dmitry.baryshkov@linaro.org> References: <20211006035407.1147909-1-dmitry.baryshkov@linaro.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-wireless@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 6d7172e6f4c3..99117eaf617f 100644 --- a/arch/arm64/boot/dts/qcom/sdm845.dtsi +++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi @@ -1046,6 +1046,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 Wed Oct 6 03:54:04 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Baryshkov X-Patchwork-Id: 12538517 X-Patchwork-Delegate: johannes@sipsolutions.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id C0BC2C4332F for ; Wed, 6 Oct 2021 03:55:46 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id AE2F961381 for ; Wed, 6 Oct 2021 03:55:46 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237980AbhJFD5g (ORCPT ); Tue, 5 Oct 2021 23:57:36 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:33016 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237602AbhJFD4c (ORCPT ); Tue, 5 Oct 2021 23:56:32 -0400 Received: from mail-lf1-x12a.google.com (mail-lf1-x12a.google.com [IPv6:2a00:1450:4864:20::12a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 35CF9C0617B1 for ; Tue, 5 Oct 2021 20:54:24 -0700 (PDT) Received: by mail-lf1-x12a.google.com with SMTP id y26so4462365lfa.11 for ; Tue, 05 Oct 2021 20:54:24 -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=fc0GoKyWHbaDUKZRwzSCHWvKPWvkUL1O7EIfFaZFJjw=; b=ek+UBm52N/dNF84c5mtTjMTJvJ5oGZ0lbXTAAjAyV1XvQDUOFH0l/tTMhfVzJAVy1s 5A9IIqqQjiddD6Xxi2TTAaGdSgVqpk0Rmqtk98pIDkXppBKhslgFJvZPuN4VYjg8Kh/k NvN7a6TOOxfaYoA9A7SJwXWmEtuPXBVt4gb8badGbZhlGOA620Gyxh4R+YbZd6q49MOv 2Qi1wfxZ+XCc8YcurEshmk0YU/rcgY4765nt9Wx5F406K53k2YpQJYrDUJTkWqNBikGf xKtKknzKdnRkKPLuVnIzXFOf+W03r/taVjHXCFr1DlAWSxc5MKil96Ym1SLsZZZJqpo+ ufLA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=fc0GoKyWHbaDUKZRwzSCHWvKPWvkUL1O7EIfFaZFJjw=; b=lVnaby22IS3rgKQfFhN0t5N0arTB3xGqqr6B1sQh+TYZGbVSptBya6J/oM0/v7HQWM iA8azpTGGPShcxq0F6FW9hKmq/2JuFTYaSPXP22m3a0QQlxzqhdqongtSVFqd6+eQISw wa7iOl8PvxYzV0omglvw4TTHGVZL8PLPSsl4fJn2O4hZgYBcDMh9KBw1iL5UdPTFgmP7 V930KEYFKgwfmHvfihE6puVHQvJrrphcrCdF1nkDexH1AGkXdsYQ8zzag6hopK9I+iqZ mbE2J6ihKKDwI1lEFF18H/ywsbG0WzpVaCwAQXqGQss7e8bCs8WPESTokwvZnPzISDPE qRlw== X-Gm-Message-State: AOAM532BtwTsLNwiJC9Tt1/GcYyS7H3nvTRG1KJyKg9vA4gmXfPngeWC A0o2oauzq1E9kjb2g4UERDxPSA== X-Google-Smtp-Source: ABdhPJwsKWl3H1d1iLra8+QrQS59nd54fvK9Etapf6nvAyz9n7l6E+sLHM/FZUi8R5GtNZVbuy881Q== X-Received: by 2002:a2e:9893:: with SMTP id b19mr26949222ljj.112.1633492462601; Tue, 05 Oct 2021 20:54:22 -0700 (PDT) Received: from eriador.lan ([37.153.55.125]) by smtp.gmail.com with ESMTPSA id s4sm2142967lfd.103.2021.10.05.20.54.21 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 05 Oct 2021 20:54:22 -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: [PATCH v1 12/15] arm64: dts: qcom: qrb5165-rb5: add bluetooth support Date: Wed, 6 Oct 2021 06:54:04 +0300 Message-Id: <20211006035407.1147909-13-dmitry.baryshkov@linaro.org> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20211006035407.1147909-1-dmitry.baryshkov@linaro.org> References: <20211006035407.1147909-1-dmitry.baryshkov@linaro.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org Add support for the bluetooth part of the QCA6391 BT+WiFi chip present on the RB5 board. WiFi is not supported yet, as it requires separate handling of the PCIe device power. Signed-off-by: Dmitry Baryshkov --- arch/arm64/boot/dts/qcom/qrb5165-rb5.dts | 50 ++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/qrb5165-rb5.dts b/arch/arm64/boot/dts/qcom/qrb5165-rb5.dts index 8ac96f8e79d4..326330f528fc 100644 --- a/arch/arm64/boot/dts/qcom/qrb5165-rb5.dts +++ b/arch/arm64/boot/dts/qcom/qrb5165-rb5.dts @@ -19,6 +19,7 @@ / { aliases { serial0 = &uart12; + serial1 = &uart6; sdhc2 = &sdhc_2; }; @@ -98,6 +99,25 @@ lt9611_3v3: lt9611-3v3 { regulator-always-on; }; + qca_pwrseq: qca-pwrseq { + compatible = "qcom,qca6390-pwrseq"; + + #pwrseq-cells = <1>; + + vddaon-supply = <&vreg_s6a_0p95>; + vddpmu-supply = <&vreg_s2f_0p95>; + vddrfa1-supply = <&vreg_s2f_0p95>; + vddrfa2-supply = <&vreg_s8c_1p3>; + vddrfa3-supply = <&vreg_s5a_1p9>; + vddpcie1-supply = <&vreg_s8c_1p3>; + vddpcie2-supply = <&vreg_s5a_1p9>; + vddio-supply = <&vreg_s4a_1p8>; + + bt-enable-gpios = <&tlmm 21 GPIO_ACTIVE_HIGH>; + wifi-enable-gpios = <&tlmm 20 GPIO_ACTIVE_HIGH>; + swctrl-gpios = <&tlmm 124 GPIO_ACTIVE_HIGH>; + }; + thermal-zones { conn-thermal { polling-delay-passive = <0>; @@ -804,6 +824,26 @@ lt9611_rst_pin: lt9611-rst-pin { }; }; +&qup_uart6_default { + ctsrx { + pins = "gpio16", "gpio19"; + drive-strength = <2>; + bias-disable; + }; + + rts { + pins = "gpio17"; + drive-strength = <2>; + bias-disable; + }; + + tx { + pins = "gpio18"; + drive-strength = <2>; + bias-pull-up; + }; +}; + &qupv3_id_0 { status = "okay"; }; @@ -1193,6 +1233,16 @@ sdc2_card_det_n: sd-card-det-n { }; }; +&uart6 { + status = "okay"; + bluetooth { + compatible = "qcom,qca6390-bt"; + clocks = <&sleep_clk>; + + bt-pwrseq = <&qca_pwrseq 1>; + }; +}; + &uart12 { status = "okay"; }; From patchwork Wed Oct 6 03:54: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: 12538519 X-Patchwork-Delegate: johannes@sipsolutions.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 61A54C433EF for ; Wed, 6 Oct 2021 03:56:22 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 3F61F6120F for ; Wed, 6 Oct 2021 03:56:22 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237597AbhJFD6M (ORCPT ); Tue, 5 Oct 2021 23:58:12 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:32986 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237388AbhJFD5B (ORCPT ); Tue, 5 Oct 2021 23:57:01 -0400 Received: from mail-lf1-x135.google.com (mail-lf1-x135.google.com [IPv6:2a00:1450:4864:20::135]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1CDD9C06139D for ; Tue, 5 Oct 2021 20:54:25 -0700 (PDT) Received: by mail-lf1-x135.google.com with SMTP id t9so4633218lfd.1 for ; Tue, 05 Oct 2021 20:54:25 -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=lOnAyrBq8epXVQrN/WDXQeiKNCDBNkNLvVnOhj3ua+A=; b=EXdBcPTCi9Pbs0BZua/dU4gI91si5Iub0rrfb+BVmheSvGSqXRSQ1kTj9Kqk/o+YSw Sp1PzSb7XxDE6ZWrp4WTBqXtYUK5/iu+ZIPqibNy9cycqyaln2LWVHuzozAYV3rtzlq5 9JDIe22v3Rl6vzgtu8z/JAtQVwEN+sxrE1TnWj64YrQE2kjXFEYtiB6BN+wWrm+JRh2z 9/9v8A1FYXQ/r87Ky9Q+TyRfQMzrhSFQ1bsbzanHx72oRBfaCXppxWib6kYzeC6exCA9 QhKWbm+NHDc5HuI/TPTVgPnlLzD9VM/8PG/YDbKoHhCMtKa7spNdHPUdjZwN94pYp1e4 Xn7w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=lOnAyrBq8epXVQrN/WDXQeiKNCDBNkNLvVnOhj3ua+A=; b=MNaTngTTHp/fIeTGNyOKz3YIQvh9oTFtlkCA1EHtTOOIdlOpzsGMedfX8NH7o/QBW0 fEj/OFJ5VKVy+j0YwaIuqwzmT5SLJdo4kxAgkxoyEf4AGVy0nKwo8sRIMiAiSkmZiG3y V+mU8OeDZfdc1joiuvTvuiyhEvNxlK3VOL8Y8J808xxmE9Vrk8+RdtFyV+UbP5PY1Xg1 xT0Tbt4+YmOHLaMF6k7G44QzdtvrWOCfhpuY93S0xOqubVWV+9yUAKkrSrp/XzIKidD3 AVLaBNC5ckp5drU1dn4ZKqKr5kvKhd7SK3M0Kdz6VhB3sb4I8zUn/BBHEEERfqwQjk+u oqGA== X-Gm-Message-State: AOAM532ahglh5pvMmB5GdoQZ9CnSm7i5+wMaG/SSK8GcQtotrZFT4rTu 8PfxxEVi170WRy8CLl0inVwM7A== X-Google-Smtp-Source: ABdhPJytJDOF+lgU658ts6E88pAfppSJZDYauPQN5bzLfv3wFMtv/ZGbgZCMTKCWUMBONI7iO1qyjQ== X-Received: by 2002:a2e:812:: with SMTP id 18mr26729407lji.497.1633492463509; Tue, 05 Oct 2021 20:54:23 -0700 (PDT) Received: from eriador.lan ([37.153.55.125]) by smtp.gmail.com with ESMTPSA id s4sm2142967lfd.103.2021.10.05.20.54.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 05 Oct 2021 20:54:23 -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: [PATCH v1 13/15] arm64: dts: qcom: sdm845-db845c: add second channel to qca power sequencer Date: Wed, 6 Oct 2021 06:54:05 +0300 Message-Id: <20211006035407.1147909-14-dmitry.baryshkov@linaro.org> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20211006035407.1147909-1-dmitry.baryshkov@linaro.org> References: <20211006035407.1147909-1-dmitry.baryshkov@linaro.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org On DB845c board WiFi/BT chip can use both RF channels/antennas, so add vddch1-supply property. Signed-off-by: Dmitry Baryshkov --- arch/arm64/boot/dts/qcom/sdm845-db845c.dts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sdm845-db845c.dts b/arch/arm64/boot/dts/qcom/sdm845-db845c.dts index a6a34a959a91..0f3214c60980 100644 --- a/arch/arm64/boot/dts/qcom/sdm845-db845c.dts +++ b/arch/arm64/boot/dts/qcom/sdm845-db845c.dts @@ -342,6 +342,12 @@ vreg_l21a_2p95: ldo21 { regulator-initial-mode = ; }; + vreg_l23a_3p3: ldo23 { + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3312000>; + regulator-initial-mode = ; + }; + vreg_l24a_3p075: ldo24 { regulator-min-microvolt = <3088000>; regulator-max-microvolt = <3088000>; @@ -637,6 +643,7 @@ &qca_pwrseq { vddxo-supply = <&vreg_l7a_1p8>; vddrf-supply = <&vreg_l17a_1p3>; vddch0-supply = <&vreg_l25a_3p3>; + vddch1-supply = <&vreg_l23a_3p3>; }; &sdhc_2 { From patchwork Wed Oct 6 03:54:06 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Baryshkov X-Patchwork-Id: 12538523 X-Patchwork-Delegate: johannes@sipsolutions.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 23445C433F5 for ; Wed, 6 Oct 2021 03:57:17 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 0A57D61166 for ; Wed, 6 Oct 2021 03:57:16 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237461AbhJFD7G (ORCPT ); Tue, 5 Oct 2021 23:59:06 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:33008 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237832AbhJFD5I (ORCPT ); Tue, 5 Oct 2021 23:57:08 -0400 Received: from mail-lf1-x12b.google.com (mail-lf1-x12b.google.com [IPv6:2a00:1450:4864:20::12b]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C3C80C0613A4 for ; Tue, 5 Oct 2021 20:54:25 -0700 (PDT) Received: by mail-lf1-x12b.google.com with SMTP id u18so4430689lfd.12 for ; Tue, 05 Oct 2021 20:54:25 -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=cntTQV+8xT1gaPRWwmEttMqurpErGQCflfEN/t0ShBw=; b=nI8QFgOb018OHBusf4YC2JeMjW54+ysmQEB8kR7Xsem1gHesZm4WMMnTqiCIMiIJic WI7/wxQI+UPOYHBu3IM8HVi9QtbP9cW2z7Dw6JKWTuCV4ApU9PGZzJrmoVoO8ohQJUx2 ofFLe3i5sE2uwNgAtXM+eSdn8y8WAry7pokGo4W4zYARZ5um+aTBPwVaXMYetwnPHqnt EukYtJv6K7yZzw+gQsNKLblw67yWlUpB+YUL310GiTZMoiBbS2CMLfTpElLBXjmOdr5n Qg+qq3q8Cw/VMVHNvozcdAKgFGZYFF40fyNeJ64thfSGSgOSto4way/p2ww9JO/ImxaM 5Lww== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=cntTQV+8xT1gaPRWwmEttMqurpErGQCflfEN/t0ShBw=; b=QhjNcAWLtzf0/WV7q0NlUTPybn24dqTdyanzQJ099ddnBACqpGVlbswLNx8h3vu+dy AJXLyR+nkG8O+gtFV8UCmYTZvgiaZAMJad970o7gc5clRUp5iMR+qgUQH5a2OAmevXyW fTfmfKPY/N7qjECuXbfs4evWX2J2qBuqJrlmBOMGPLxmISVJvnisZApmqpF97DkXkl/1 Z2/aEuMUijazAPmr/o5Ao0Rfe5gaxtKsg9pDuy1DKawEY2/OErT5SJ0MnBq6dADG9Ohf sw1NcuK+6UHzqWDuxESQdqb+qW4gOospad4yGK+8MmmifQR3rnU86edUfm+kaQ1WDU/W HtnA== X-Gm-Message-State: AOAM531Ml3zQzE48A32/3BPt1cEqjhQ5VQI9Le0Bur77qmJ2XHtdQbWe 5/mcjX9hq7OK5+/+fiMlErq02w== X-Google-Smtp-Source: ABdhPJxsUvRGDiX/+G1NjVUXp066qhnPQIzeN7/ovvdbZrBswOTRoBoS6GwOzADjXLYmhRy7xOhHcw== X-Received: by 2002:ac2:59d0:: with SMTP id x16mr7310130lfn.107.1633492464220; Tue, 05 Oct 2021 20:54:24 -0700 (PDT) Received: from eriador.lan ([37.153.55.125]) by smtp.gmail.com with ESMTPSA id s4sm2142967lfd.103.2021.10.05.20.54.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 05 Oct 2021 20:54:23 -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: [PATCH v1 14/15] WIP: PCI: qcom: use pwrseq to power up bus devices Date: Wed, 6 Oct 2021 06:54:06 +0300 Message-Id: <20211006035407.1147909-15-dmitry.baryshkov@linaro.org> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20211006035407.1147909-1-dmitry.baryshkov@linaro.org> References: <20211006035407.1147909-1-dmitry.baryshkov@linaro.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org Use bus-pwrseq device tree node to power up the devices on the bus. This is to be rewritten with the proper code parsing the device tree and powering up individual devices. Signed-off-by: Dmitry Baryshkov --- drivers/pci/controller/dwc/pcie-qcom.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/pci/controller/dwc/pcie-qcom.c b/drivers/pci/controller/dwc/pcie-qcom.c index 8a7a300163e5..f398283912c7 100644 --- a/drivers/pci/controller/dwc/pcie-qcom.c +++ b/drivers/pci/controller/dwc/pcie-qcom.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -1467,6 +1468,7 @@ static int qcom_pcie_probe(struct platform_device *pdev) struct pcie_port *pp; struct dw_pcie *pci; struct qcom_pcie *pcie; + struct pwrseq *pwrseq; int ret; pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL); @@ -1520,6 +1522,17 @@ static int qcom_pcie_probe(struct platform_device *pdev) pp->ops = &qcom_pcie_dw_ops; + pwrseq = devm_pwrseq_get(dev, "bus"); + if (IS_ERR(pwrseq)) { + ret = PTR_ERR(pwrseq); + goto err_pm_runtime_put; + } + if (pwrseq) { + ret = pwrseq_full_power_on(pwrseq); + if (ret) + goto err_pm_runtime_put; + } + ret = phy_init(pcie->phy); if (ret) { pm_runtime_disable(&pdev->dev); From patchwork Wed Oct 6 03:54:07 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Baryshkov X-Patchwork-Id: 12538521 X-Patchwork-Delegate: johannes@sipsolutions.net Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 35CE3C4332F for ; Wed, 6 Oct 2021 03:56:35 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 1D42E61166 for ; Wed, 6 Oct 2021 03:56:35 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237389AbhJFD6Y (ORCPT ); Tue, 5 Oct 2021 23:58:24 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:32928 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237766AbhJFD5O (ORCPT ); Tue, 5 Oct 2021 23:57:14 -0400 Received: from mail-lf1-x135.google.com (mail-lf1-x135.google.com [IPv6:2a00:1450:4864:20::135]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id AD9BBC0613AA for ; Tue, 5 Oct 2021 20:54:26 -0700 (PDT) Received: by mail-lf1-x135.google.com with SMTP id x27so4576415lfu.5 for ; Tue, 05 Oct 2021 20:54:26 -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=Vqowca4UgiaC+fBXqBcu/uY1PBquzcLUSNLvI4m85X7UrokO3SMSU2VjgjwlLvMQmh qsx0PVYwuS97nctSczbW0/EPVJ0QBpI8npXxHwrFMaNxAVtaIlRSrtfDr/01lMkJFIzk NeLaREUo2x9NAHKctYTeKFJdcbLKG3DGrW4TE6vnxKsvxVRzGpwnzWZPAhbV6qTOP1TZ 8albRcafCq9VIoNGF5i1EtEgCzTR7YeJxiTMPsw8rZxBFCSGpBQwXD+jrBjbyyQnVjnb ujZ8iI+IoHoh/d/5ZhPx+FNiAsGnS4MzGWDOWNQ3qbBfyZhavzipupkGO+MkveylWsCR B8HA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=DZOpdA3eYjpudg4OpQFFkH8jLHw3BxsNdxzTMff7kgw=; b=H9aDS3yKoW2cdgr8FW68yaQe/U3CR1E+uoq51Mip1lijMoqCWBzmRSM3Objy0bwqfr nH9qv4E+VruVFsDN4389pog1xiLhM7xX+UgeV0tXtHiCmbrnEVXHpwRFNTqAIz9WkBuq XaknsPrd+GALeXobDKbhR5jLawUQdCxnna37neTwXiwH2Tm4JXPsO5tiYQmH5eO24OKD dXsruUxjYo3mSd/y/0NmFDuslMG6STftNGj4jkfD8DWdyP5ckUH9DDHbEAGaz55ImtjW sgjNhlZFs3QIYPNi9BozN9+2jRdK+sdqbR+kuq48mrGYYR/C+EcgPVV27gfm2dgz+yym axWg== X-Gm-Message-State: AOAM533osxqHUjxEMTWj5ofgSalPC29yg+qinIO+qp6yQTNWAYqkxJm6 sZzurrTiaZVgGsdELjL7y4hiYQ== X-Google-Smtp-Source: ABdhPJzAuciR0Bs89UsVK2ICmqc78PA7gPD8wfVqylDag0DqJdI3Y1HguWHKaOEbTu8SD0HZCDgojQ== X-Received: by 2002:a2e:480a:: with SMTP id v10mr25910067lja.268.1633492465108; Tue, 05 Oct 2021 20:54:25 -0700 (PDT) Received: from eriador.lan ([37.153.55.125]) by smtp.gmail.com with ESMTPSA id s4sm2142967lfd.103.2021.10.05.20.54.24 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 05 Oct 2021 20:54:24 -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: [PATCH v1 15/15] WIP: arm64: dts: qcom: qrb5165-rb5: add bus-pwrseq property to pcie0 Date: Wed, 6 Oct 2021 06:54:07 +0300 Message-Id: <20211006035407.1147909-16-dmitry.baryshkov@linaro.org> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20211006035407.1147909-1-dmitry.baryshkov@linaro.org> References: <20211006035407.1147909-1-dmitry.baryshkov@linaro.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-wireless@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 {