From patchwork Fri Dec 1 17:02:24 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Georgi Djakov X-Patchwork-Id: 120364 Delivered-To: patch@linaro.org Received: by 10.140.22.227 with SMTP id 90csp1390264qgn; Fri, 1 Dec 2017 09:02:57 -0800 (PST) X-Google-Smtp-Source: AGs4zMadpeq8ewcvrQmmpeAs2B5ezgLjOOWf0ALTYtyeci/gMyPoIOiz89/+2GJDN0SnoeBTfces X-Received: by 10.84.178.129 with SMTP id z1mr6940630plb.365.1512147777123; Fri, 01 Dec 2017 09:02:57 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1512147777; cv=none; d=google.com; s=arc-20160816; b=mgTSvM9cHxD91rXuRNQ+poB7H/CNPSjtVEiwITtZE6Q3tz8vW7BIE1PRo4gBbH8uGa 6EuUcItRZ4v0EpikTTibKvirBtAnzesfL+4VQrdT0I89lViTpHU5miXK6bMn+nmqt0Ko kzwxD8ifRbVjZAvH2EgDsgh+tFACQc3knKay6WdSJcDlOIVGFHKVHJCAi4lBe5cLV0R2 OmwUP16Cc8pElOq+v3oOZttVouND+kCHlKTAP08/f75mGuxwId754b2xXqZWpmNfbdMp bg0reh648f98d1NWm+SHo9eLJFxrn+QQMjCK3uSo2eiJNrxSGbpDbaHK162x5qkqbbnU vGvQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=HI9rmaIgyT6RG8o/i83JOnoqIXlaX8aMssiZtiNHaP0=; b=rudmrTrF0MPiSxZYSURwLbgbLhbIBob33BrO47rQaOpdiCL4TRXiy844I1hErtmZmt fX3SLJpqHbOKWLgS++sdA6eHSs8EsfXfLM5n9E6GL6xTF/2RfVO5yCS2h6uIyQAR0UYi VVG7Wl4qhWaazGX1a/Y5krBNkKPBk7djcFVhMyUMhZBdGgV8dDD7R4fV/TxGXBSZtYzA pKz8zlC2+4GeH1WdmbBQhiDaUSqA2XmJJ2QmoFAkqQiPfLhMUVt97ftANSPSWqXvLLCL a2MKS+OUWOzeg6VF6rKfgs+BeyNMEpblwJHEW6D8muKlh2sBSyEYvS+vbCIo1GyYPKS1 ggkA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=WTHwUfch; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-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. [209.132.180.67]) by mx.google.com with ESMTP id d126si5006209pgc.821.2017.12.01.09.02.56; Fri, 01 Dec 2017 09:02:57 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=WTHwUfch; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-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 S1752025AbdLARCy (ORCPT + 28 others); Fri, 1 Dec 2017 12:02:54 -0500 Received: from mail-wr0-f195.google.com ([209.85.128.195]:34944 "EHLO mail-wr0-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751894AbdLARCg (ORCPT ); Fri, 1 Dec 2017 12:02:36 -0500 Received: by mail-wr0-f195.google.com with SMTP id g53so10833026wra.2 for ; Fri, 01 Dec 2017 09:02:36 -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; bh=HI9rmaIgyT6RG8o/i83JOnoqIXlaX8aMssiZtiNHaP0=; b=WTHwUfch3Grkx/GTRNzqhP2RPbhoNPuLwfje0+3np3ZVciIozg57jppfNv/356t0R/ /rGHzKVBKIVNtXGve8BTiyvhDIv4mFtb3H9ScQvOK/qmCip6Hy0JAbT9T8vpuXtb4I7V 4Ti2g3C1glPFUYEej8+6egvewph+vjztrxNt8= 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; bh=HI9rmaIgyT6RG8o/i83JOnoqIXlaX8aMssiZtiNHaP0=; b=SvnnOy5fH7Fy71KM3ZoCDxd2e4eqb8NXxjUjdF7WmrT9i0ZOfG1UOviQ69neOOSdgO o97CiNcBNqWi8VVFcSHPMHfBo1NjeboD63iqM6uxHw9hejoM2TM4n8ZYWZslmEV5V6kO Vuo/dMuWNngZnD3lHL4v+HZHigncKGqQPWcBDkb1fHr9FWzpmP14/1FBoYeL4cfov89L XEu82SmBQ4j7jDj5OoVFBYDJfN/OD4Ow8ZfNq5oxKsgsjo83NcgXoaDmKOyaT63mjnDl J09/jRsm8eu+nfSHJkTg1NB9F94be82gE2xwSYijyRJZIRGb/TFOYx3YvReGxZk8YQ7u eSXw== X-Gm-Message-State: AJaThX7hiY7eRtGjAusGo7+d7+FQLHG4nw3MhdZNr8z00lNVL2OBiojN tJvPqHeW2V9lQbk3eLs51kYb9A== X-Received: by 10.223.132.101 with SMTP id 92mr6212435wrf.85.1512147755435; Fri, 01 Dec 2017 09:02:35 -0800 (PST) Received: from localhost.localdomain ([212.45.67.2]) by smtp.googlemail.com with ESMTPSA id 2sm1535253wmk.28.2017.12.01.09.02.33 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 01 Dec 2017 09:02:34 -0800 (PST) From: Georgi Djakov To: sboyd@codeaurora.org, jassisinghbrar@gmail.com, bjorn.andersson@linaro.org, robh@kernel.org Cc: mturquette@baylibre.com, linux-clk@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org, devicetree@vger.kernel.org, georgi.djakov@linaro.org Subject: [PATCH v10 6/6] clk: qcom: Add APCS clock controller support Date: Fri, 1 Dec 2017 19:02:24 +0200 Message-Id: <20171201170224.25053-7-georgi.djakov@linaro.org> X-Mailer: git-send-email 2.14.2 In-Reply-To: <20171201170224.25053-1-georgi.djakov@linaro.org> References: <20171201170224.25053-1-georgi.djakov@linaro.org> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Add a driver for the APCS clock controller. It is part of the APCS hardware block, which among other things implements also a combined mux and half integer divider functionality. It can choose between a fixed-rate clock or the dedicated APCS (A53) PLL. The source and the divider can be set both at the same time. This is required for enabling CPU frequency scaling on MSM8916-based platforms. Signed-off-by: Georgi Djakov --- drivers/clk/qcom/Kconfig | 11 +++ drivers/clk/qcom/Makefile | 1 + drivers/clk/qcom/apcs-msm8916.c | 149 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 161 insertions(+) create mode 100644 drivers/clk/qcom/apcs-msm8916.c diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig index 81ac7b9378fe..255023b439c9 100644 --- a/drivers/clk/qcom/Kconfig +++ b/drivers/clk/qcom/Kconfig @@ -22,6 +22,17 @@ config QCOM_A53PLL Say Y if you want to support higher CPU frequencies on MSM8916 devices. +config QCOM_CLK_APCS_MSM8916 + bool "MSM8916 APCS Clock Controller" + depends on COMMON_CLK_QCOM + depends on QCOM_APCS_IPC + default ARCH_QCOM + help + Support for the APCS Clock Controller on msm8916 devices. The + APCS is managing the mux and divider which feeds the CPUs. + Say Y if you want to support CPU frequency scaling on devices + such as msm8916. + config QCOM_CLK_RPM tristate "RPM based Clock Controller" depends on COMMON_CLK_QCOM && MFD_QCOM_RPM diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile index 7c51d877f967..0408cebf38d4 100644 --- a/drivers/clk/qcom/Makefile +++ b/drivers/clk/qcom/Makefile @@ -34,5 +34,6 @@ obj-$(CONFIG_MSM_MMCC_8960) += mmcc-msm8960.o obj-$(CONFIG_MSM_MMCC_8974) += mmcc-msm8974.o obj-$(CONFIG_MSM_MMCC_8996) += mmcc-msm8996.o obj-$(CONFIG_QCOM_A53PLL) += a53-pll.o +obj-$(CONFIG_QCOM_CLK_APCS_MSM8916) += apcs-msm8916.o obj-$(CONFIG_QCOM_CLK_RPM) += clk-rpm.o obj-$(CONFIG_QCOM_CLK_SMD_RPM) += clk-smd-rpm.o diff --git a/drivers/clk/qcom/apcs-msm8916.c b/drivers/clk/qcom/apcs-msm8916.c new file mode 100644 index 000000000000..f71039ff2347 --- /dev/null +++ b/drivers/clk/qcom/apcs-msm8916.c @@ -0,0 +1,149 @@ +/* + * Qualcomm APCS clock controller driver + * + * Copyright (c) 2017, Linaro Limited + * Author: Georgi Djakov + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "clk-regmap.h" +#include "clk-regmap-mux-div.h" + +enum { + P_GPLL0, + P_A53PLL, +}; + +static const struct parent_map gpll0_a53cc_map[] = { + { P_GPLL0, 4 }, + { P_A53PLL, 5 }, +}; + +static const char * const gpll0_a53cc[] = { + "gpll0_vote", + "a53pll", +}; + +/* + * We use the notifier function for switching to a temporary safe configuration + * (mux and divider), while the A53 PLL is reconfigured. + */ +static int a53cc_notifier_cb(struct notifier_block *nb, unsigned long event, + void *data) +{ + int ret = 0; + struct clk_regmap_mux_div *md = container_of(nb, + struct clk_regmap_mux_div, + clk_nb); + if (event == PRE_RATE_CHANGE) + /* set the mux and divider to safe frequency (400mhz) */ + ret = __mux_div_set_src_div(md, 4, 3); + + return notifier_from_errno(ret); +} + +static int qcom_apcs_msm8916_clk_probe(struct platform_device *pdev) +{ + struct device *dev = pdev->dev.parent; + struct device_node *np = dev->of_node; + struct clk_regmap_mux_div *a53cc; + struct regmap *regmap; + struct clk_init_data init = { }; + int ret; + + regmap = dev_get_regmap(dev, NULL); + if (IS_ERR(regmap)) { + ret = PTR_ERR(regmap); + dev_err(dev, "failed to get regmap: %d\n", ret); + return ret; + } + + a53cc = devm_kzalloc(dev, sizeof(*a53cc), GFP_KERNEL); + if (!a53cc) + return -ENOMEM; + + init.name = "a53mux"; + init.parent_names = gpll0_a53cc; + init.num_parents = ARRAY_SIZE(gpll0_a53cc); + init.ops = &clk_regmap_mux_div_ops; + init.flags = CLK_SET_RATE_PARENT; + + a53cc->clkr.hw.init = &init; + a53cc->clkr.regmap = regmap; + a53cc->reg_offset = 0x50; + a53cc->hid_width = 5; + a53cc->hid_shift = 0; + a53cc->src_width = 3; + a53cc->src_shift = 8; + a53cc->parent_map = gpll0_a53cc_map; + + a53cc->pclk = devm_clk_get(dev, NULL); + if (IS_ERR(a53cc->pclk)) { + ret = PTR_ERR(a53cc->pclk); + dev_err(dev, "failed to get clk: %d\n", ret); + return ret; + } + + a53cc->clk_nb.notifier_call = a53cc_notifier_cb; + ret = clk_notifier_register(a53cc->pclk, &a53cc->clk_nb); + if (ret) { + dev_err(dev, "failed to register clock notifier: %d\n", ret); + return ret; + } + + ret = devm_clk_register_regmap(dev, &a53cc->clkr); + if (ret) { + dev_err(dev, "failed to register regmap clock: %d\n", ret); + goto err; + } + + ret = of_clk_add_hw_provider(np, of_clk_hw_simple_get, + &a53cc->clkr.hw); + if (ret) { + dev_err(dev, "failed to add clock provider: %d\n", ret); + goto err; + } + + platform_set_drvdata(pdev, a53cc); + + return 0; + +err: + clk_notifier_unregister(a53cc->pclk, &a53cc->clk_nb); + return ret; +} + +static int qcom_apcs_msm8916_clk_remove(struct platform_device *pdev) +{ + struct clk_regmap_mux_div *a53cc = platform_get_drvdata(pdev); + + clk_notifier_unregister(a53cc->pclk, &a53cc->clk_nb); + of_clk_del_provider(pdev->dev.of_node); + + return 0; +} + +static struct platform_driver qcom_apcs_msm8916_clk_driver = { + .probe = qcom_apcs_msm8916_clk_probe, + .remove = qcom_apcs_msm8916_clk_remove, + .driver = { + .name = "qcom-apcs-msm8916-clk", + }, +}; +module_platform_driver(qcom_apcs_msm8916_clk_driver); + +MODULE_AUTHOR("Georgi Djakov "); +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("Qualcomm MSM8916 APCS clock driver");