From patchwork Fri Jun 3 23:25:22 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andy Gross X-Patchwork-Id: 9154301 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 6A52B60751 for ; Fri, 3 Jun 2016 23:27:58 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 5AF8228334 for ; Fri, 3 Jun 2016 23:27:58 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 4FE7F28345; Fri, 3 Jun 2016 23:27:58 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.1 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_MED,T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id DF42528334 for ; Fri, 3 Jun 2016 23:27:57 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1b8yTu-0000Im-LS; Fri, 03 Jun 2016 23:26:22 +0000 Received: from mail-oi0-x235.google.com ([2607:f8b0:4003:c06::235]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1b8yTe-0000Cr-Li for linux-arm-kernel@lists.infradead.org; Fri, 03 Jun 2016 23:26:07 +0000 Received: by mail-oi0-x235.google.com with SMTP id j1so149676380oih.3 for ; Fri, 03 Jun 2016 16:25:46 -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; bh=nA1y7bhJoh1CKr4Ffmat1HTv5jZvfBdY4nOULObOSYw=; b=hAWcs3IVa6aNQaFgXm1CMr0ujrjl4uZ3abC49tXH6UUK2XUn1X5KehGMVGwB0cdbgf a/83X2xlHWN0In006SSDJkK+KRgCmVMu3rOyeHFMVEy+7PeGXll8GVT/TVZh7elScyGF L0XyEudYaDz/koOYNbIUdwk6wLkRTWZU67YNQ= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=nA1y7bhJoh1CKr4Ffmat1HTv5jZvfBdY4nOULObOSYw=; b=CSUWIw+4au1UZurDBpzaAB+BPNekXhafNgUNZXP32rANUaym5EkohIFff9bngJ47+W 92pGqiAhsH9RLESY+Nv5QMFDq5w/06jLrW/YHPYcWI4l7/kywEhaRc0FTz817ZbiC3Oa u+alGFihDtOPePGpwIFtDvYp0E1NNSrUbmxqDUwd7H4oUjjYD/O5yqFGUXbrK48bPZ9D Bb6RXmDMHdhm/Tms+2gCzp5DvwencOWAkh9YbxXJqnXBL+txXi7BwkdwaaHbt7vDSsAV 10W5ExCZnH/sT3oEgfOml8NOLVD7gTK7pSXGRWtxMUMv4KlvCVc9jG0VXjoZ7dGcjVp5 epoQ== X-Gm-Message-State: ALyK8tJ7fMwdBNrdvrZTGqVNUyWMuKF6mDq5ycwaaJ5He663u5zZ3A0zj30A8s+sZUfSgIP+ X-Received: by 10.202.89.68 with SMTP id n65mr2992365oib.138.1464996345791; Fri, 03 Jun 2016 16:25:45 -0700 (PDT) Received: from localhost ([2602:306:c558:19b0:a575:d8f4:7700:e330]) by smtp.gmail.com with ESMTPSA id k3sm4382931oih.27.2016.06.03.16.25.45 (version=TLS1_2 cipher=AES128-SHA bits=128/128); Fri, 03 Jun 2016 16:25:45 -0700 (PDT) From: Andy Gross To: linux-arm-msm@vger.kernel.org Subject: [Patch v6 02/10] firmware: qcom: scm: Convert SCM to platform driver Date: Fri, 3 Jun 2016 18:25:22 -0500 Message-Id: <1464996330-16952-3-git-send-email-andy.gross@linaro.org> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1464996330-16952-1-git-send-email-andy.gross@linaro.org> References: <1464996330-16952-1-git-send-email-andy.gross@linaro.org> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20160603_162606_770978_67DBB9C8 X-CRM114-Status: GOOD ( 17.00 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: devicetree@vger.kernel.org, Stephen Boyd , linux-kernel@vger.kernel.org, Bjorn Andersson , Andy Gross , jilai wang , linux-arm-kernel@lists.infradead.org MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP This patch converts the Qualcomm SCM firmware driver into a platform driver. It also adds clock management for firmware calls which require clocks to be enabled during the duration of their execution. Rate setting of the core clock is also in place for higher performance. Signed-off-by: Andy Gross Acked-by: Bjorn Andersson Reviewed-by: Stephen Boyd --- drivers/firmware/qcom_scm.c | 174 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 165 insertions(+), 9 deletions(-) diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c index 45c008d..c4ec60d 100644 --- a/drivers/firmware/qcom_scm.c +++ b/drivers/firmware/qcom_scm.c @@ -10,19 +10,61 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. */ - +#include +#include #include #include #include #include +#include +#include +#include #include "qcom_scm.h" +struct qcom_scm { + struct device *dev; + struct clk *core_clk; + struct clk *iface_clk; + struct clk *bus_clk; +}; + +static struct qcom_scm *__scm; + +static int qcom_scm_clk_enable(void) +{ + int ret; + + ret = clk_prepare_enable(__scm->core_clk); + if (ret) + goto bail; + + ret = clk_prepare_enable(__scm->iface_clk); + if (ret) + goto disable_core; + + ret = clk_prepare_enable(__scm->bus_clk); + if (ret) + goto disable_iface; + + return 0; + +disable_iface: + clk_disable_unprepare(__scm->iface_clk); +disable_core: + clk_disable_unprepare(__scm->core_clk); +bail: + return ret; +} + +static void qcom_scm_clk_disable(void) +{ + clk_disable_unprepare(__scm->core_clk); + clk_disable_unprepare(__scm->iface_clk); + clk_disable_unprepare(__scm->bus_clk); +} + /** * qcom_scm_set_cold_boot_addr() - Set the cold boot address for cpus * @entry: Entry point function for the cpus @@ -72,12 +114,17 @@ EXPORT_SYMBOL(qcom_scm_cpu_power_down); */ bool qcom_scm_hdcp_available(void) { - int ret; + int ret = qcom_scm_clk_enable(); + + if (ret) + return ret; ret = __qcom_scm_is_call_available(QCOM_SCM_SVC_HDCP, - QCOM_SCM_CMD_HDCP); + QCOM_SCM_CMD_HDCP); + + qcom_scm_clk_disable(); - return (ret > 0) ? true : false; + return ret > 0 ? true : false; } EXPORT_SYMBOL(qcom_scm_hdcp_available); @@ -91,6 +138,115 @@ EXPORT_SYMBOL(qcom_scm_hdcp_available); */ int qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp) { - return __qcom_scm_hdcp_req(req, req_cnt, resp); + int ret = qcom_scm_clk_enable(); + + if (ret) + return ret; + + ret = __qcom_scm_hdcp_req(req, req_cnt, resp); + qcom_scm_clk_disable(); + return ret; } EXPORT_SYMBOL(qcom_scm_hdcp_req); + +static int qcom_scm_probe(struct platform_device *pdev) +{ + struct qcom_scm *scm; + int ret; + + scm = devm_kzalloc(&pdev->dev, sizeof(*scm), GFP_KERNEL); + if (!scm) + return -ENOMEM; + + scm->core_clk = devm_clk_get(&pdev->dev, "core"); + if (IS_ERR(scm->core_clk)) { + if (PTR_ERR(scm->core_clk) == -EPROBE_DEFER) + return PTR_ERR(scm->core_clk); + + scm->core_clk = NULL; + } + + if (of_device_is_compatible(pdev->dev.of_node, "qcom,scm")) { + scm->iface_clk = devm_clk_get(&pdev->dev, "iface"); + if (IS_ERR(scm->iface_clk)) { + if (PTR_ERR(scm->iface_clk) != -EPROBE_DEFER) + dev_err(&pdev->dev, "failed to acquire iface clk\n"); + return PTR_ERR(scm->iface_clk); + } + + scm->bus_clk = devm_clk_get(&pdev->dev, "bus"); + if (IS_ERR(scm->bus_clk)) { + if (PTR_ERR(scm->bus_clk) != -EPROBE_DEFER) + dev_err(&pdev->dev, "failed to acquire bus clk\n"); + return PTR_ERR(scm->bus_clk); + } + } + + /* vote for max clk rate for highest performance */ + ret = clk_set_rate(scm->core_clk, INT_MAX); + if (ret) + return ret; + + __scm = scm; + __scm->dev = &pdev->dev; + + return 0; +} + +static const struct of_device_id qcom_scm_dt_match[] = { + { .compatible = "qcom,scm-apq8064",}, + { .compatible = "qcom,scm-msm8660",}, + { .compatible = "qcom,scm-msm8960",}, + { .compatible = "qcom,scm",}, + {} +}; + +MODULE_DEVICE_TABLE(of, qcom_scm_dt_match); + +static struct platform_driver qcom_scm_driver = { + .driver = { + .name = "qcom_scm", + .of_match_table = qcom_scm_dt_match, + }, + .probe = qcom_scm_probe, +}; + +static int __init qcom_scm_init(void) +{ + struct device_node *np, *fw_np; + int ret; + + fw_np = of_find_node_by_name(NULL, "firmware"); + + if (!fw_np) + return -ENODEV; + + np = of_find_matching_node(fw_np, qcom_scm_dt_match); + + if (!np) { + of_node_put(fw_np); + return -ENODEV; + } + + of_node_put(np); + + ret = of_platform_populate(fw_np, qcom_scm_dt_match, NULL, NULL); + + of_node_put(fw_np); + + if (ret) + return ret; + + return platform_driver_register(&qcom_scm_driver); +} + +arch_initcall(qcom_scm_init); + +static void __exit qcom_scm_exit(void) +{ + platform_driver_unregister(&qcom_scm_driver); +} +module_exit(qcom_scm_exit); + +MODULE_DESCRIPTION("Qualcomm SCM driver"); +MODULE_LICENSE("GPL v2");