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: 12538463 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 3D4D6C433F5 for ; Wed, 6 Oct 2021 03:54:17 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 267A36120F for ; Wed, 6 Oct 2021 03:54:17 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230363AbhJFD4G (ORCPT ); Tue, 5 Oct 2021 23:56:06 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:32932 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231985AbhJFD4F (ORCPT ); Tue, 5 Oct 2021 23:56:05 -0400 Received: from mail-lf1-x131.google.com (mail-lf1-x131.google.com [IPv6:2a00:1450:4864:20::131]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E7FB3C06174E for ; Tue, 5 Oct 2021 20:54:13 -0700 (PDT) Received: by mail-lf1-x131.google.com with SMTP id x27so4495659lfa.9 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=iOEMsX7NBqEQeZiTKzyHz6xfnM0jk9jZn0MolGt10FJqmula4PDzTCDRGwlPbED2Vi K9W9qtEpyviw9Pcoaebh8UougCDDpB2XVQ7MqQvQG6N9lNdUnEbUTBLf0RxKGQHnOWDG HLyTHcTXn/s0M2/XY75c+cE1oC/4HZ550GifOyzOJ6f8qV1q8oJSSONYpd4FR2mFl2zt UVtZ8SgTz0wNuTK2mO3NQ4DRdPFEvXK/c6w/PXQpzOd8KqdACokY/ujaOgwChpjxe39+ pyuS+Eb1fzTajWVjqysiG8+THm0N8+XB3wNgAWznPdoak0rUytF7ZFBei9FKoxhZvE+h qygg== X-Gm-Message-State: AOAM531Os9qXpbssvlcvJWs7Q9tQqKX5EdNNgsceXu5hHaZSF7fW6BMp GNMBsYtQruLKE76SmwIHtxKy0A== 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-mmc@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: 12538465 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 98653C433F5 for ; Wed, 6 Oct 2021 03:54:20 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 7FE9361371 for ; Wed, 6 Oct 2021 03:54:20 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237335AbhJFD4J (ORCPT ); Tue, 5 Oct 2021 23:56:09 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:32950 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237278AbhJFD4G (ORCPT ); Tue, 5 Oct 2021 23:56:06 -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 F2E50C061753 for ; Tue, 5 Oct 2021 20:54:14 -0700 (PDT) Received: by mail-lf1-x12e.google.com with SMTP id m3so4627822lfu.2 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=mMR7UcpeeTKuH2aWyzSbsU5ybngLzvUznXeCtySYioBSlV5LE8QnQRBGSLA2Y5mqn/ T9RP2ZMrzcTWTreMLGSjXm3+dkexr5Ksh8zcPOp1hzaSM6SnAMp9TV58efdNWCIWR9uQ BHzDW5GUQJJQJ9bg0cUjm3iHBs3ZdU9Fe0AzPqj06tpKp1gzg1RPaugj489KQX7QGB/1 lDCXIixFuUUFE7UI6pZub6qugC0wn3KcV7B3K+vSSkTybRIXNoQEKShAH6h7sdfbwd7Z t0gkHyUsyY2WKWFta1uNCgRwPS2CIYi5IxsLbzHF9FecE3M9GzwBTLwebCemsgcSKtY8 HEAQ== X-Gm-Message-State: AOAM531R4w7fWyb3z9rOkitw4Iu+DGr31YpUdbCJqgaTZ2b0wfKxnHcx Afxd2MLhZ1PqNOHpugorc6+F7w== 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-mmc@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: 12538479 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 843C1C433EF 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 6D7CE611C1 for ; Wed, 6 Oct 2021 03:55:19 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237817AbhJFD5H (ORCPT ); Tue, 5 Oct 2021 23:57:07 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:32968 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237300AbhJFD4H (ORCPT ); Tue, 5 Oct 2021 23:56:07 -0400 Received: from mail-lf1-x134.google.com (mail-lf1-x134.google.com [IPv6:2a00:1450:4864:20::134]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C6833C061768 for ; Tue, 5 Oct 2021 20:54:15 -0700 (PDT) Received: by mail-lf1-x134.google.com with SMTP id r19so4458775lfe.10 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=NDTdw8Ma7SzDLxiECFWREpofw+238z6wz98Yy1XWtL28ZqHONqkGlg1t+npvkC7qMx 2ncwnOivh/JN1QqiKs3/wGQw6s5HIGFLgVUVg8xouy0RI5r1/Qnyz4moQC3Xpc1ju0KX 1g9KDiuTocAZ1Xbztiupk5snlbTPPfWZVpKqM5El8KYOypg8pcpCry4JVAONdlj5vzX/ Dv95Y6F0+uW74/eyCpjfhc2orY3ntGDGN1WcWfLYccuNiNUSAlGm9AUVkpmdNxPpJmdE 8beQVlgpuMw7F62Ucqjcx27eTvBliZXMZwDfpRy+4BYw9r8Wdh792TrCVDXERXndMNOU 1RaQ== X-Gm-Message-State: AOAM531dzh+F2ZslRsBGGyvb7gt+SUGFC81jFTPrIPGIy71GlbAMOwGd 7nHdL6QGgRHBiK+9Vb2zZ51SuQ== 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-mmc@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: 12538481 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 2DA1AC433FE for ; Wed, 6 Oct 2021 03:55:20 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 0E2FE61260 for ; Wed, 6 Oct 2021 03:55:20 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237834AbhJFD5J (ORCPT ); Tue, 5 Oct 2021 23:57:09 -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 S237309AbhJFD4I (ORCPT ); Tue, 5 Oct 2021 23:56:08 -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 3AD50C061783 for ; Tue, 5 Oct 2021 20:54:16 -0700 (PDT) Received: by mail-lf1-x135.google.com with SMTP id r19so4458810lfe.10 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=kMnyX0zxeA9zQ6W1+nNPtdumMm2U1B1JJVEYDUHfcWZDkjV4RCoUeVoKjpKxJsywP/ el3spL2TsTYX5LG8wqG4z2YmXCYjHZGZiPHMpflOvf3z+7/BhYcOvmtyBC4R209ZthGs B4x7Bhf+h54wuuZFHpZ6NemmvORMr3/u0Ip8DhB7EzhASaGu4Z6ff0PBB3pCvtqJMAbX I90w6Bim3zq1lecsyrSVpyalYTfUsRSVoQc4sRWf7L8N7l/5k3BpJyCEALCZBXRncC5t qM49qOl1HgRUs1S2YY9o0VLpG4rzw5uu0hqG9W3S1n0iDtqVlwwk6RSXtjiDGpne5qXD lFmA== X-Gm-Message-State: AOAM531pTlSUvaKRtegpkVx7laqnluz3GvcruA/fI7rK932u3212AFZG DQhf7qINnQle/etxvxhjN0/deg== 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-mmc@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: 12538475 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 24075C433EF for ; Wed, 6 Oct 2021 03:55:09 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 0F7D561248 for ; Wed, 6 Oct 2021 03:55:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237742AbhJFD4y (ORCPT ); Tue, 5 Oct 2021 23:56:54 -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 S237343AbhJFD4J (ORCPT ); Tue, 5 Oct 2021 23:56:09 -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 4283AC061762 for ; Tue, 5 Oct 2021 20:54:17 -0700 (PDT) Received: by mail-lf1-x12d.google.com with SMTP id r19so4458967lfe.10 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=b+9zUA9FQRAOejxhL1Y+ONpmbcAaHRN4irPQxFt75msBpvEaBGo5CSBhVui0pbWMN7 pPhoW6r1+cgbFLxLftrcPSvqfJPngd6thwwYEqmsJFVrkML6L+G1a1scjM7bhi19CM37 xUS8RhYVNC6tDIkkASHaS5vEzvk7n2CNMfWTkZZuMe6Ov0hQmZXGX0bAalnvg1+Jrbc8 +BgiVg34bhZNTZR5RM+XqMk48U59y3aq1vFa/PQSfTZxUTA6CoPH2RkB95W+pwB+7FG8 552tqC1J68R5UD0lrycrnNNmiSzQ3jJMyg5T6cvme1gaReSFk96fIuO3SbvP72Yjx2Q2 v/LA== X-Gm-Message-State: AOAM5315CwBssSNTfYv/lWBCSCi4enpVPmJnFnliogB9SBbZAO0j/eso 4SLRJ53rNdqNZRq4j0qVn7Enr6OFEO6NPg== 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-mmc@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: 12538467 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 92D9BC433FE for ; Wed, 6 Oct 2021 03:54:33 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 8068861248 for ; Wed, 6 Oct 2021 03:54:33 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237498AbhJFD4W (ORCPT ); Tue, 5 Oct 2021 23:56:22 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:32972 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230409AbhJFD4K (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 4D8ECC061766 for ; Tue, 5 Oct 2021 20:54:18 -0700 (PDT) Received: by mail-lf1-x12e.google.com with SMTP id i4so4605117lfv.4 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=gg5MHZ4pGACmxYHA5nCWOhTyE8bkuMpYyaXS2zVCzm7eSbwoMPTc89+71jA11QthSE YJmASUlWaJz9augq0klvCu7ZZGvsCjn1gVxtzhDhuTFUxbeGYBym1uxLDJuCotBoptxR 7q1h88U690CY6YmlTjQFVbhWdWKnCArgpX0fzysyjAINH5OITAi13Q/9XWQq2R5GSM6U zHAiCDSvNCB3QN6AMpC/2oTBPy04+RP3mSFitZ0RLB6hTpJ1KnWWQbRrfiuh7K1T/T0w s65yEYoWNf/NPi53Jji6a9Kfi/G/hEq3yLtsgqDztkKWGX1GSPydx5weVzdmaqBccrjB l6XA== X-Gm-Message-State: AOAM533K3mwYV51WMGX46F4w7sMas3Y4dggp0Mj7lqfv/YPDy5ImAptg lNThxFqQ/Mn9WbqlAIZnsx4nnA== 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-mmc@vger.kernel.org Add support for power sequencer used in the Qualcomm BT+WiFi SoCs. They require several external volate regulators and some of them use separate BT and WiFi enable GPIO pins. This code is mostly extracted from the hci_qca.c bluetooth driver and ath10k WiFi driver. Instead of having each of them manage pins, different requirements, regulator types, move this knowledge to the common power sequencer driver. Currently original drivers are not stripped from the regulator code, this will be done later (to keep compatibility with the old device trees). Signed-off-by: Dmitry Baryshkov --- drivers/power/pwrseq/Kconfig | 14 ++ drivers/power/pwrseq/Makefile | 1 + drivers/power/pwrseq/pwrseq_qca.c | 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: 12538469 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 1C9EDC4332F for ; Wed, 6 Oct 2021 03:54:39 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 08EF761423 for ; Wed, 6 Oct 2021 03:54:39 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237570AbhJFD41 (ORCPT ); Tue, 5 Oct 2021 23:56:27 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:32966 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237371AbhJFD4L (ORCPT ); Tue, 5 Oct 2021 23:56:11 -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 41684C06174E for ; Tue, 5 Oct 2021 20:54:19 -0700 (PDT) Received: by mail-lf1-x130.google.com with SMTP id m3so4628334lfu.2 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=02DBAXl89AwOVPM4aCjm3WqvrE0c/WafFVKYhPAmSl0GnyzXQjLfRkYjTFgVkO9Xkx stQN3YGPo31aQ6mYvRolHxmjOz4rOQ3jpXAiLHzEH+W1Pb8V85B72aYBQ0TTbjQXgV2f v93OzMKoi1v/KeiDI+mZEZavGu8uF/vtL2UWA1UXq0b66Aee+r+j5M56tBsH/GBkMYLV AXZ+VKXdfwEAiB8acSAUdG2z+y6GD9o0vALeygEIu5WyWQ2Gj0pYXYC7BtJ4UimjVZBR rf4o0QFLf2FonTCRQtWbV0mOCT6ZNpZVujZGYcfXXuvEiREPnDBxBIQWaL0XoqlpXDQs h1uA== X-Gm-Message-State: AOAM530O9Figff4aAAA3ZWeP8CnLXLCeirDYWuZcmdgBlmmbVTbLhJsF lgqV1tRVBOkA8jvxqHLhMqeLSg== 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-mmc@vger.kernel.org Power sequencer support requires changing device tree. To ease migration to pwrseq, add support for pwrseq 'fallback': let the power sequencer driver register special handler that if matched will create pwrseq instance basing on the consumer device tree data. Signed-off-by: Dmitry Baryshkov --- drivers/power/pwrseq/Makefile | 2 +- drivers/power/pwrseq/core.c | 3 ++ drivers/power/pwrseq/fallback.c | 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: 12538477 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 9F864C43217 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 8D67A6120F for ; Wed, 6 Oct 2021 03:55:10 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237343AbhJFD45 (ORCPT ); Tue, 5 Oct 2021 23:56:57 -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 S237388AbhJFD4L (ORCPT ); Tue, 5 Oct 2021 23:56:11 -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 0B815C061753 for ; Tue, 5 Oct 2021 20:54:20 -0700 (PDT) Received: by mail-lf1-x12b.google.com with SMTP id y23so4776676lfb.0 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=5Fd0Qlxc3gQPDZHbvN7rsA52cnNWj2DL/IQ/kVViQuXRgj1BXMuaADbS6L7wBPC4g1 5lB2yI7f88NtD4dEgIps7O0xHFQm9sdFdoYgcTxCsQ3JEORc1QuUKMlvCkiIp80W3emE eUl8zzie5Ewd85OzfBAp45dh2O4okiGSAbHrdkw6YkyColfhL3X7q/yt3hfKq7wocZSf PbIw8Jx9nOMg0Qhnk6kXPwjmrMUFso36bDsbgeAMTyRoSGg7oCX1Y0F1ja661AROrcd+ MsP4/tuUxCohVwCH+t5BF+7m2HAedv+xTDuD7So8V33anrSjnjLT+pRubQiQmpAvi0H3 9FGw== X-Gm-Message-State: AOAM531j9cUEwXic0yiF20iPe5H/CNYVHwyufcRxbMseMLPsD1br4uBI fjk3jfPgoHKoReUH/cHXQj+jCA== 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-mmc@vger.kernel.org While we are waiting for all users of wcn399x-bt to be converted to the pwrseq declaration in the device tree, provide support for the pwrseq fallback: if the regulators are declared in the device itself, create pwrseq instance. This way the hci_qca driver doesn't have to cope with old and new dts bindings. Signed-off-by: Dmitry Baryshkov --- drivers/power/pwrseq/pwrseq_qca.c | 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: 12538471 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 58065C4332F for ; Wed, 6 Oct 2021 03:54:53 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 4022461248 for ; Wed, 6 Oct 2021 03:54:53 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237632AbhJFD4i (ORCPT ); Tue, 5 Oct 2021 23:56:38 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:32972 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237409AbhJFD4N (ORCPT ); Tue, 5 Oct 2021 23:56:13 -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 38F34C061762 for ; Tue, 5 Oct 2021 20:54:21 -0700 (PDT) Received: by mail-lf1-x132.google.com with SMTP id r19so4459404lfe.10 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=57RKClTAUkya4en7o65gjj6/oF0FUMuyzv8Jp9ayXBCRSuZD8iAXCh0fT28TsfFCf7 t5/wrBNhTXaDwOU9/JcmL4yVGyiouU4rM4MzCm+OW+4DR0Z4hRLAQE07F44amMQ0Bu5c yVGGLV3qYeLW3HU58MnWAp9rTJ8SO/SZqJQ6NTx68EtqASkimzNsWRy0rBjjlCcfemRw dnbaJjargr3E8ZVHJ0X+Gcuxds6Nm+RZaS3WLnzbqKFdobr5a4Y7xBHjp4axLGoF/AYH 8akl9QJJHh5WmFK0GxP5i0UO46GyaYCAfgnG6U3oWfO15oEzYEioGuMKrNRfuRsYy33H 5/Iw== X-Gm-Message-State: AOAM531XQxWd3wb291/UJTmF5TJ5cnVqd9sj60h9T0qTVGNHSw9xLPF0 JamNcQqSNBXLKFT9qJcYktau0w== 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-mmc@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: 12538473 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 385ACC433EF for ; Wed, 6 Oct 2021 03:55:01 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 25AE061260 for ; Wed, 6 Oct 2021 03:55:01 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237484AbhJFD4s (ORCPT ); Tue, 5 Oct 2021 23:56:48 -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 S237487AbhJFD4W (ORCPT ); Tue, 5 Oct 2021 23:56:22 -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 444A7C061798 for ; Tue, 5 Oct 2021 20:54:22 -0700 (PDT) Received: by mail-lf1-x12b.google.com with SMTP id t9so4632917lfd.1 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=hIslI2+9rMs3Cf1Wels6HaODtPdzv+veTqE/4mJX5vGG2EDhV6RfknP75TzXUbbn8Q bYCY5O5ZKgETjxJfE6MHkTU9D8C+MVQM60FRaGrEt4KgVqZYevLnJohL72DaaQIgtLFf nnjWZPUPyIRVbF9M6ON5kNXWI9aVe7FhXEY09mHEoyPH2xVj6/rvDGkSAUsDqzNj8agk r2R0qZnQm3iwx5RHVe4hyg5KpxDmDgtyheWY9Ddn7vBfx35G8WOkxKAGzGrdJFz+JfiW RMEnhn+9HEd8sozD1jQ+wkm6Xf0AouDNxdUkDAnOW+k0Md+gPcelqXsmjtgE1HgCv3Nm rrCw== X-Gm-Message-State: AOAM5325IrfWXIKH1AyxwmbShR1eHbJyCH1GpM9lL0r5QWH71bm6rwvS JVtmDlvSOEoOycszbH970STVCg== 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-mmc@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: 12538483 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 EAB82C433EF for ; Wed, 6 Oct 2021 03:55:43 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id D6690611C1 for ; Wed, 6 Oct 2021 03:55:43 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237531AbhJFD53 (ORCPT ); Tue, 5 Oct 2021 23:57:29 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:33004 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237523AbhJFD4Y (ORCPT ); Tue, 5 Oct 2021 23:56:24 -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 4EBEBC0617A6 for ; Tue, 5 Oct 2021 20:54:23 -0700 (PDT) Received: by mail-lf1-x130.google.com with SMTP id j5so4512454lfg.8 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=fP5CwgiN9AaPcbjkBftDGp6n9idr/6oxrSJqn9v5UMN5QNmBCq64vZKmXT53HkeUEA xdPMZyS1orHK0MgBR4MuG546ViTh/LjzZ3JKgGCv+df6fIetIocki64L4AJk8z66LyWS 3RAfdkxSNs71Zsr8RWFiUJYavMAgJdBwERTNroA3GfurorJtBji8DgTVne1vj7c6h77l BWJIJ968qdFtxOvJjkNXuE6lV2hynisSSGf0hVU491CZA0MJnuQx+CpHZCp0e38jw9ix sRAkb2lFa8QwRouz7ShpNoqrGW3Vy/BG8A5odl/OqL9mOGsciqPGmZsH20WJoRGxLaKU Nyhg== X-Gm-Message-State: AOAM531Fe+kFx0gkMywS2fe/lMjzN1O48Fa0ukHmHTDn4U6AsiqT7+4B rUss01W2lxihrsrBd/Ivlasvkg== 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-mmc@vger.kernel.org Switch sdm845-db845c device tree to use new power sequencer driver rather than separate regulators. Signed-off-by: Dmitry Baryshkov --- arch/arm64/boot/dts/qcom/sdm845-db845c.dts | 21 ++++++++++++++------- arch/arm64/boot/dts/qcom/sdm845.dtsi | 6 ++++++ 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/sdm845-db845c.dts b/arch/arm64/boot/dts/qcom/sdm845-db845c.dts index 2d5533dd4ec2..a6a34a959a91 100644 --- a/arch/arm64/boot/dts/qcom/sdm845-db845c.dts +++ b/arch/arm64/boot/dts/qcom/sdm845-db845c.dts @@ -629,6 +629,16 @@ &qupv3_id_1 { status = "okay"; }; +&qca_pwrseq { + status = "okay"; + + vddio-supply = <&vreg_s4a_1p8>; + + vddxo-supply = <&vreg_l7a_1p8>; + vddrf-supply = <&vreg_l17a_1p3>; + vddch0-supply = <&vreg_l25a_3p3>; +}; + &sdhc_2 { status = "okay"; @@ -916,10 +926,8 @@ &uart6 { bluetooth { compatible = "qcom,wcn3990-bt"; - vddio-supply = <&vreg_s4a_1p8>; - vddxo-supply = <&vreg_l7a_1p8>; - vddrf-supply = <&vreg_l17a_1p3>; - vddch0-supply = <&vreg_l25a_3p3>; + bt-pwrseq = <&qca_pwrseq 1>; + max-speed = <3200000>; }; }; @@ -1036,9 +1044,8 @@ &wifi { status = "okay"; vdd-0.8-cx-mx-supply = <&vreg_l5a_0p8>; - vdd-1.8-xo-supply = <&vreg_l7a_1p8>; - vdd-1.3-rfa-supply = <&vreg_l17a_1p3>; - vdd-3.3-ch0-supply = <&vreg_l25a_3p3>; + + wifi-pwrseq = <&qca_pwrseq 0>; qcom,snoc-host-cap-8bit-quirk; }; diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi index 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: 12538485 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 AEB53C433F5 for ; Wed, 6 Oct 2021 03:56:08 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 996206120F for ; Wed, 6 Oct 2021 03:56:08 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237646AbhJFD57 (ORCPT ); Tue, 5 Oct 2021 23:57:59 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:32966 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237667AbhJFD4n (ORCPT ); Tue, 5 Oct 2021 23:56:43 -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 391E5C0617BA for ; Tue, 5 Oct 2021 20:54:24 -0700 (PDT) Received: by mail-lf1-x135.google.com with SMTP id x27so4497014lfa.9 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=HO7hPj8/txiOOwkfl5c/bA3oHF1W5uN4kHsvW6zkGoHoGY+nbRb2SJdGS9M5NB+a7z +5iPD7wFarb9coWmTZlHGyqWO6sSBhQIlBESnBXxsdtPnbuiwRmaINHaxnoItgy5fGqx EzDb6RfbvDw4luqgJnuz5iyt4/QcFOuoWxbTErZSXa6puUfGF6OCrJxu74YS4XO63Abo I57t4cI5tTrafnG0g1Cz9KgN/FCr/bhisBEUvKPG0YBwqbGsVron4Rh9GzKNY9SOtaEg OEMDRpdGh6hEpgLc+9qzuqbfbRkZuYOuRdhZeWrAMcLHM2EKBUi2eyMzdKfYkWwM6nlT 8GKQ== X-Gm-Message-State: AOAM531bNIq/gFrjS2tL7LPgvACrACsiTS2fLgtg8Bxol9RIsW3k+wOH yEW3CSvw4j2WZMITpc/ovzTwoA== 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-mmc@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: 12538487 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 7E576C433F5 for ; Wed, 6 Oct 2021 03:56:26 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 655D26120F for ; Wed, 6 Oct 2021 03:56:26 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237719AbhJFD6P (ORCPT ); Tue, 5 Oct 2021 23:58:15 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:33002 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237824AbhJFD5H (ORCPT ); Tue, 5 Oct 2021 23:57:07 -0400 Received: from mail-lf1-x134.google.com (mail-lf1-x134.google.com [IPv6:2a00:1450:4864:20::134]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 38839C0613A2 for ; Tue, 5 Oct 2021 20:54:25 -0700 (PDT) Received: by mail-lf1-x134.google.com with SMTP id r19so4459910lfe.10 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=hhzQZwb+0qfl5okjLUrXMWu80M+grFyxp83E+yXPmoH1s4iJ1bVyqdCSSdgLeZgJoB u2cD66TBJ8v5Spc3pu+nKD/hTzgI6gp2/Lfe+mJ/me8HQi9Sl7xIjJLvcx2+RbC/UZuY AOGO7KX9AK7dqxTX2kofOF8EaFzS/NMfXpI5nwAT6uEMgCqRzLdczSfhOPxjF191bzxK KTr1in96IYFH8uXBSuIGsr/CI2T21Fj4kPYkAv6ltpTdaYf38YyvnppPAtTtCZM44Kn3 CAaJiIBqdNv1Ho5ERn6jcyOmL3RRN7JTR7X2RWhmTHcrAFi3uLnFsOIP8cBEJB1C/z8b ZYDA== X-Gm-Message-State: AOAM531p4o5Q4eTkHz5qzGZbSKS6hst+7ryyDJjgZJpfGxN4/7Wo3jNk gHzw4CePysd6UTkPpvIaECVQWw== 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-mmc@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: 12538489 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 D8F1BC433EF for ; Wed, 6 Oct 2021 03:56:33 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id C2A8E6120F for ; Wed, 6 Oct 2021 03:56:33 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237625AbhJFD6T (ORCPT ); Tue, 5 Oct 2021 23:58:19 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:32972 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237884AbhJFD5O (ORCPT ); Tue, 5 Oct 2021 23:57:14 -0400 Received: from mail-lf1-x131.google.com (mail-lf1-x131.google.com [IPv6:2a00:1450:4864:20::131]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D41B9C0613A9 for ; Tue, 5 Oct 2021 20:54:25 -0700 (PDT) Received: by mail-lf1-x131.google.com with SMTP id b20so4613211lfv.3 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=rvYvEDBTZqFyoVf2T91hjT0mqlkdVCgpyADg1IkazkFrlGosQQQ3bYaKS2LGXHlkv8 r3R3cXeaTb2QgRKyISh9aeszD8RhUjxH+BJ40SC5S908BXtJcVOSeyiylnmcBJxb6Fid mpEhy2U6/3Dn1q3eUN0Cy9+D1Retzf96Z+OyENnSLHipXi8Fj0CgoaVIP2i9nMGn2DsC 6kw1sjpyXMAeR+6TW6JiFTbHmbxI3hNeqpmANOpJGptYy4/8e+wGjQ71gX3qm4VNPBu1 rQweCC5RMUohYFpeAg848Lp6jQgwMJhcARicB6lMIF+1PUEZL4EXN8uOjEpdLvf92kdZ CEKw== X-Gm-Message-State: AOAM530/6iUHmFzblq7l/S/omO3YNbsUXZ1L74r9PQ4qpa/Qw9N3WnQc uL0vG48ngGbsLoeUoyS+T9Treg== 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-mmc@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: 12538491 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 D7629C433FE for ; Wed, 6 Oct 2021 03:57:00 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id C0011611C1 for ; Wed, 6 Oct 2021 03:57:00 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237352AbhJFD6v (ORCPT ); Tue, 5 Oct 2021 23:58:51 -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 S237964AbhJFD5e (ORCPT ); Tue, 5 Oct 2021 23:57:34 -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 B02A7C0613AE for ; Tue, 5 Oct 2021 20:54:26 -0700 (PDT) Received: by mail-lf1-x12a.google.com with SMTP id y23so4777479lfb.0 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=J115y31RrxZMal7f1W93cji7CaEdEUxw/TCSRp04RKdaXm7Y5ezDrWbwepu1ABg9OB E4Bp7hdphKdidzM3Mf4WaXmZdW+OLidmNlkpvsRyLe/tFBvB9COfP1BtKyySsDj5VJqH xawTf2Q2j0ho/+MNvIj0pG+E2Hbwe54rzQEkP2cycxW211/AgDRZRdtVtxk2EUYZT1J2 24UiroV2g8Aoyrh0k3bnJsZt7H7ID3iQsTNT8yXoiUB/bkzMQ9tEzhNgVm2JwB/WTQI4 n7vPJNpMfntM+w8mYJlO397d4APkQcEl/LHITy8mEy2Lho9tbuVGvQcpsXhfi718AANx l5lw== X-Gm-Message-State: AOAM5330Qmd+1YU56CPngtd/jq7AmLf+cVu+aN5xls1ydykFbQB9nsrv cUqWCtAswGJMaANcZEptxYSgAA== 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-mmc@vger.kernel.org Signed-off-by: Dmitry Baryshkov --- arch/arm64/boot/dts/qcom/qrb5165-rb5.dts | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/boot/dts/qcom/qrb5165-rb5.dts b/arch/arm64/boot/dts/qcom/qrb5165-rb5.dts index 326330f528fc..0c347cb6f8e0 100644 --- a/arch/arm64/boot/dts/qcom/qrb5165-rb5.dts +++ b/arch/arm64/boot/dts/qcom/qrb5165-rb5.dts @@ -689,6 +689,7 @@ wifi-therm@1 { &pcie0 { status = "okay"; + bus-pwrseq = <&qca_pwrseq 0>; }; &pcie0_phy {