From patchwork Thu Jan 28 17:52:21 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Baryshkov X-Patchwork-Id: 372615 Delivered-To: patch@linaro.org Received: by 2002:a02:a60d:0:0:0:0:0 with SMTP id c13csp1484390jam; Thu, 28 Jan 2021 09:54:15 -0800 (PST) X-Google-Smtp-Source: ABdhPJzGW3WocpQvEvo8THFVjDfXcy0afK6xU+F5bDm2dZ+ephbMhlyFFtv8UIkChFEUz3rFC80Z X-Received: by 2002:a05:6402:c87:: with SMTP id cm7mr800724edb.69.1611856455849; Thu, 28 Jan 2021 09:54:15 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1611856455; cv=none; d=google.com; s=arc-20160816; b=ZTD9TXgoWt5vQ1B+779Ln+N4unSlZ5+QiosNoDTzN6pl26xVcW4w4DiuxyNw2ywAbb 4143q9pXa17V3VegIyo+C2ztAXfYXg6vSiEB2IdzqHIfaNXMvB9Qh29TuwrJJNioq3Oz SeWnfj1g+JBJ/2hTgll2OK7W/zp4lykrdGH3HGJ1bY7oiW72Istup8uZfff4ZwvAc0LP HHgnSRkxrLKl14egRlqMWXuD+/RZQWzSAxzwaFBKddH2+ovEto4xqy3nIiyuQ++Oc9/Q kN2VerSTmbBzswXVdABN8yqQgqsBRxqRr7VVXrJZ0UhTUCVwIw4UvBT5VrXdH4Reze+u IXfA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=dk89QtY9XlOJ4lSbFodbDfjmlfoZzf3XCi+vMFHgHok=; b=JaSsbdsqp6H+luFiHnPknTcoxLIy5tqf5FkA7hLjk/ThaVaDzllSJH/DkwAcwgzVSx 10taCy69FWXuvFLzRZDgTObUsvZyl5aBXU3bTxGGJzTlDX5PYv0JZqX8PCHT+z7PVDuz A6OwqnMZY/E1wxznFSFhPqBArrhF4tWXdwxkHdLtzx0BmBxeUpoRbAmLagNNk1aPKG51 Dh32q/Ywx2xOoaNH99UY0Aa8OUeWp4lh53F81aMhVOPtEWMds/YhHl/3ofe+IqQ42qEl N4GwuR150rofGM4Dz7wI6i076TEkxWMgSu7t7FoktLbIuSkhT5k/UH3G3/DOAFG4G8P6 NECQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=s1b6iFGc; spf=pass (google.com: domain of linux-arm-msm-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-arm-msm-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id bs19si3370475edb.212.2021.01.28.09.54.15; Thu, 28 Jan 2021 09:54:15 -0800 (PST) Received-SPF: pass (google.com: domain of linux-arm-msm-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=s1b6iFGc; spf=pass (google.com: domain of linux-arm-msm-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-arm-msm-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231152AbhA1Rx2 (ORCPT + 15 others); Thu, 28 Jan 2021 12:53:28 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:58614 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231146AbhA1RxZ (ORCPT ); Thu, 28 Jan 2021 12:53:25 -0500 Received: from mail-lf1-x12f.google.com (mail-lf1-x12f.google.com [IPv6:2a00:1450:4864:20::12f]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C6327C061788 for ; Thu, 28 Jan 2021 09:52:33 -0800 (PST) Received: by mail-lf1-x12f.google.com with SMTP id e2so5111725lfj.13 for ; Thu, 28 Jan 2021 09:52:33 -0800 (PST) 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=dk89QtY9XlOJ4lSbFodbDfjmlfoZzf3XCi+vMFHgHok=; b=s1b6iFGc1xAsquj/ntFQobMHzwwE5meOTZQpJqhMvbTul/jkfDwEK1qrboPMa+Fkm5 RZQd+TtVuZkdOBzfNuxrgdHp52dMKrhN4Yi8ZVzliMmYIsV5spFEakHA60kpuzlrK9Rh q+xU/xtzlYnKTjkvBHqssnAaCtRwOhTVPwL3am6aWD9NykDw6bq2lLpDE5Vrwcmv1/YL Wa3+d+aP6zu6Un/C4A3OQvO3r8JyhZV3vmNSNgScl6zoeuRQ+wkK26o215Vm0JEff3eR kaeA3Sg8dhp1Unrcx7PlZ2RFw3rLkVcLG+ptM23QANVF/beHNCCQoUANZP3gp3QJsfX6 7bqg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=dk89QtY9XlOJ4lSbFodbDfjmlfoZzf3XCi+vMFHgHok=; b=eIG9QFQMCAqjiXfsWN5HFQ2hMAWDKoqKdWR0dPIjxaF9XEspKXWyhe6zkELFIODJf1 lBzM7GU/+qy0srKFrk/5DkMPWxsycbpEbtnugzpwo/qtmSk9NbLl9bLElD0Uw/gazNNa 0Lnbu1/hxE8ASvCxPcW5TMsZqcB8W5adKs3vtTN9/kQ+Y6N2sSaRVNB5Dq6mXqceLDPS 8mvOtNMHqo4/u6caEM1Yxa1W8OrrK2PzCiyQ1f1x/TRH0H3lc7Zg3ilMTzjWjbhzv4Zr KS1z56fQ5gDQ75wWiSGheANuKSTf98310zCJLt1BQtVMQvmduYfUB/jDAinP/8ZXXeIa 5zKw== X-Gm-Message-State: AOAM531lgi6fprPuxq37BHQ+aYdGK+uAKgWT6XTYoeGl9PY3gN+MJRKk 722+FDubIwChVQo/FpJpnEB6VA== X-Received: by 2002:a19:6555:: with SMTP id c21mr90981lfj.563.1611856352300; Thu, 28 Jan 2021 09:52:32 -0800 (PST) Received: from eriador.lan ([94.25.229.83]) by smtp.gmail.com with ESMTPSA id w10sm2216119ljj.37.2021.01.28.09.52.30 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 28 Jan 2021 09:52:31 -0800 (PST) From: Dmitry Baryshkov To: Andy Gross , Bjorn Andersson , Rob Herring , Arnd Bergmann , Greg Kroah-Hartman , Stanimir Varbanov , Lorenzo Pieralisi , Bjorn Helgaas Cc: linux-arm-msm@vger.kernel.org, Manivannan Sadhasivam , devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-pci@vger.kernel.org Subject: [PATCH v2 1/5] misc: qca639x: add support for QCA639x powerup sequence Date: Thu, 28 Jan 2021 20:52:21 +0300 Message-Id: <20210128175225.3102958-2-dmitry.baryshkov@linaro.org> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210128175225.3102958-1-dmitry.baryshkov@linaro.org> References: <20210128175225.3102958-1-dmitry.baryshkov@linaro.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-arm-msm@vger.kernel.org Qualcomm QCA639x is a family of WiFi + Bluetooth SoCs, with BT part being controlled through the UART and WiFi being present on PCIe bus. Both blocks share common power sources. Add device driver handling power sequencing of QCA6390/1. Signed-off-by: Dmitry Baryshkov --- drivers/misc/Kconfig | 12 +++ drivers/misc/Makefile | 1 + drivers/misc/qcom-qca639x.c | 164 ++++++++++++++++++++++++++++++++++++ 3 files changed, 177 insertions(+) create mode 100644 drivers/misc/qcom-qca639x.c -- 2.29.2 diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index e90c2524e46c..a14f67ab476c 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -255,6 +255,18 @@ config QCOM_FASTRPC applications DSP processor. Say M if you want to enable this module. +config QCOM_QCA639X + tristate "Qualcomm QCA639x WiFi/Bluetooth module support" + depends on REGULATOR && PM_GENERIC_DOMAINS + help + If you say yes to this option, support will be included for Qualcomm + QCA639x family of WiFi and Bluetooth SoCs. Note, this driver supports + only power control for this SoC, you still have to enable individual + Bluetooth and WiFi drivers. + + Say M here if you want to include support for QCA639x chips as a + module. This will build a module called "qcom-qca639x". + config SGI_GRU tristate "SGI GRU driver" depends on X86_UV && SMP diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index f65e8b18ecd8..bf21d5b1189f 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -18,6 +18,7 @@ obj-$(CONFIG_TIFM_7XX1) += tifm_7xx1.o obj-$(CONFIG_PHANTOM) += phantom.o obj-$(CONFIG_QCOM_COINCELL) += qcom-coincell.o obj-$(CONFIG_QCOM_FASTRPC) += fastrpc.o +obj-$(CONFIG_QCOM_QCA639X) += qcom-qca639x.o obj-$(CONFIG_SENSORS_BH1770) += bh1770glc.o obj-$(CONFIG_SENSORS_APDS990X) += apds990x.o obj-$(CONFIG_ENCLOSURE_SERVICES) += enclosure.o diff --git a/drivers/misc/qcom-qca639x.c b/drivers/misc/qcom-qca639x.c new file mode 100644 index 000000000000..b34e08ff4a88 --- /dev/null +++ b/drivers/misc/qcom-qca639x.c @@ -0,0 +1,164 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2020, Linaro Limited + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_NUM_REGULATORS 8 + +static struct vreg { + const char *name; + unsigned int load_uA; +} vregs[MAX_NUM_REGULATORS] = { + /* 2.0 V */ + { "vddpcie2", 15000 }, + { "vddrfa3", 400000 }, + + /* 0.95 V */ + { "vddaon", 100000 }, + { "vddpmu", 1250000 }, + { "vddrfa1", 200000 }, + + /* 1.35 V */ + { "vddrfa2", 400000 }, + { "vddpcie1", 35000 }, + + /* 1.8 V */ + { "vddio", 20000 }, +}; + +struct qca639x_data { + struct regulator_bulk_data regulators[MAX_NUM_REGULATORS]; + size_t num_vregs; + struct device *dev; + struct pinctrl_state *active_state; + struct generic_pm_domain pd; +}; + +#define domain_to_data(domain) container_of(domain, struct qca639x_data, pd) + +static int qca639x_power_on(struct generic_pm_domain *domain) +{ + struct qca639x_data *data = domain_to_data(domain); + int ret; + + ret = regulator_bulk_enable(data->num_vregs, data->regulators); + if (ret) { + dev_err(data->dev, "Failed to enable regulators"); + return ret; + } + + /* Wait for 1ms before toggling enable pins. */ + usleep_range(1000, 2000); + + ret = pinctrl_select_state(data->dev->pins->p, data->active_state); + if (ret) { + dev_err(data->dev, "Failed to select active state"); + return ret; + } + + /* Wait for all power levels to stabilize */ + usleep_range(6000, 7000); + + return 0; +} + +static int qca639x_power_off(struct generic_pm_domain *domain) +{ + struct qca639x_data *data = domain_to_data(domain); + + pinctrl_select_default_state(data->dev); + regulator_bulk_disable(data->num_vregs, data->regulators); + + return 0; +} + +static int qca639x_probe(struct platform_device *pdev) +{ + struct qca639x_data *data; + struct device *dev = &pdev->dev; + int i, ret; + + if (!dev->pins || IS_ERR_OR_NULL(dev->pins->default_state)) + return -EINVAL; + + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + data->dev = dev; + data->num_vregs = ARRAY_SIZE(vregs); + + data->active_state = pinctrl_lookup_state(dev->pins->p, "active"); + if (IS_ERR(data->active_state)) { + ret = PTR_ERR(data->active_state); + dev_err(dev, "Failed to get active_state: %d\n", ret); + return ret; + } + + for (i = 0; i < data->num_vregs; i++) + data->regulators[i].supply = vregs[i].name; + ret = devm_regulator_bulk_get(dev, data->num_vregs, data->regulators); + if (ret < 0) + return ret; + + for (i = 0; i < data->num_vregs; i++) { + ret = regulator_set_load(data->regulators[i].consumer, vregs[i].load_uA); + if (ret) + return ret; + } + + data->pd.name = dev_name(dev); + data->pd.power_on = qca639x_power_on; + data->pd.power_off = qca639x_power_off; + + ret = pm_genpd_init(&data->pd, NULL, true); + if (ret < 0) + return ret; + + ret = of_genpd_add_provider_simple(dev->of_node, &data->pd); + if (ret < 0) { + pm_genpd_remove(&data->pd); + return ret; + } + + platform_set_drvdata(pdev, data); + + return 0; +} + +static int qca639x_remove(struct platform_device *pdev) +{ + struct qca639x_data *data = platform_get_drvdata(pdev); + + pm_genpd_remove(&data->pd); + + return 0; +} + +static const struct of_device_id qca639x_of_match[] = { + { .compatible = "qcom,qca6390" }, +}; + +static struct platform_driver qca639x_driver = { + .probe = qca639x_probe, + .remove = qca639x_remove, + .driver = { + .name = "qca639x", + .of_match_table = qca639x_of_match, + }, +}; + +module_platform_driver(qca639x_driver); +MODULE_AUTHOR("Dmitry Baryshkov "); +MODULE_DESCRIPTION("Power control for Qualcomm QCA639x BT/WiFi chip"); +MODULE_LICENSE("GPL v2");