From patchwork Mon Oct 24 15:55:56 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Dwivedi, Avaneesh Kumar (avani)" X-Patchwork-Id: 9392419 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 E8D0E607D0 for ; Mon, 24 Oct 2016 15:56:18 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id DBC682907F for ; Mon, 24 Oct 2016 15:56:18 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id D0B50290E9; Mon, 24 Oct 2016 15:56:18 +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=-6.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 211C32907F for ; Mon, 24 Oct 2016 15:56:18 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S941039AbcJXP4R (ORCPT ); Mon, 24 Oct 2016 11:56:17 -0400 Received: from smtp.codeaurora.org ([198.145.29.96]:55309 "EHLO smtp.codeaurora.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S938803AbcJXP4R (ORCPT ); Mon, 24 Oct 2016 11:56:17 -0400 Received: by smtp.codeaurora.org (Postfix, from userid 1000) id 2EF9D61BCA; Mon, 24 Oct 2016 15:56:16 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1477324576; bh=ZyuAyKSXRodA9otF8dmHLxQdsJ8ivrSAs9OguCXcPiA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=NtW0weOmYQw0d5V8VX2bRp8i1rdC4unF1hLl+Ap0YmI3kwgooJM4XidfZyjuU4YBE RF2/5YZYcrlvV1lbCEa1EnYj+AC6S53CWr9l0GTpT7IzEY1J8Fe073pZP1Y1aarri5 nc6XSvClJuUsphMWJD9WOCOx6aMvQ3pdyVotc6eg= Received: from akdwived-linux.qualcomm.com (unknown [202.46.23.54]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: akdwived@smtp.codeaurora.org) by smtp.codeaurora.org (Postfix) with ESMTPSA id 2EE3A61BCA; Mon, 24 Oct 2016 15:56:12 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1477324575; bh=ZyuAyKSXRodA9otF8dmHLxQdsJ8ivrSAs9OguCXcPiA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=QREAlnQ2Ydr9SE19EYu2InUS7Gt6ZyhMFClMp3nZxU4cuvP75YR7V0BrUVphIKnc6 x//ly32jLLAJpVkublO6ErZJMLG170PHy/TBcsnbXE7ve7u3ULo5i8v15OiPZJdahb dqIh/4JsYEsCx1Bg+xBRfCKpOtnloj27qTB9vjrE= DMARC-Filter: OpenDMARC Filter v1.3.1 smtp.codeaurora.org 2EE3A61BCA Authentication-Results: pdx-caf-mail.web.codeaurora.org; dmarc=none header.from=codeaurora.org Authentication-Results: pdx-caf-mail.web.codeaurora.org; spf=pass smtp.mailfrom=akdwived@codeaurora.org From: Avaneesh Kumar Dwivedi To: bjorn.andersson@linaro.org Cc: linux-remoteproc@vger.kernel.org, linux-arm-msm@vger.kernel.org, spjoshi@codeaurora.org, akdwived@codeaurora.org, kaushalk@codeaurora.org Subject: [PATCH 2/5] remoteproc: Adding q6v55 specific regulator, clk, reset interface. Date: Mon, 24 Oct 2016 21:25:56 +0530 Message-Id: <1477324559-24752-3-git-send-email-akdwived@codeaurora.org> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1477324559-24752-1-git-send-email-akdwived@codeaurora.org> References: <1477324559-24752-1-git-send-email-akdwived@codeaurora.org> Sender: linux-remoteproc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-remoteproc@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP q6v55 use different regulator and clock resource than q6v5, hence using separate resource handling for same. Also reset register programming in q6v55 is non secure so resource controller init- ilization is not required for q6v55. Signed-off-by: Avaneesh Kumar Dwivedi --- drivers/remoteproc/qcom_q6v5_pil.c | 271 +++++++++++++++++++++++++++++++++++++ 1 file changed, 271 insertions(+) diff --git a/drivers/remoteproc/qcom_q6v5_pil.c b/drivers/remoteproc/qcom_q6v5_pil.c index 8df95a0..c7dca40 100644 --- a/drivers/remoteproc/qcom_q6v5_pil.c +++ b/drivers/remoteproc/qcom_q6v5_pil.c @@ -215,6 +215,203 @@ static void q6v5_regulator_disable(struct q6v5 *qproc) regulator_set_voltage(mss, 0, 1150000); } +static int q6v55_regulator_init(struct q6v5 *qproc) +{ + int ret; + + qproc->supply[Q6V5_SUPPLY_CX].supply = "vdd_cx"; + qproc->supply[Q6V5_SUPPLY_MX].supply = "vdd_mx"; + qproc->supply[Q6V5_SUPPLY_PLL].supply = "vdd_pll"; + + ret = devm_regulator_bulk_get(qproc->dev, + (ARRAY_SIZE(qproc->supply) - 1), qproc->supply); + if (ret < 0) { + dev_err(qproc->dev, "failed to get supplies\n"); + return ret; + } + + + return 0; +} + +static int q6v55_clk_enable(struct q6v5 *qproc) +{ + int ret; + + ret = clk_prepare_enable(qproc->ahb_clk); + if (ret) + goto out; + + ret = clk_prepare_enable(qproc->axi_clk); + if (ret) + goto err_axi_clk; + + ret = clk_prepare_enable(qproc->rom_clk); + if (ret) + goto err_rom_clk; + + ret = clk_prepare_enable(qproc->gpll0_mss_clk); + if (ret) + goto err_gpll0_mss_clk; + + ret = clk_prepare_enable(qproc->snoc_axi_clk); + if (ret) + goto err_snoc_axi_clk; + + ret = clk_prepare_enable(qproc->mnoc_axi_clk); + if (ret) + goto err_mnoc_axi_clk; + + return 0; +err_mnoc_axi_clk: + clk_disable_unprepare(qproc->snoc_axi_clk); +err_snoc_axi_clk: + clk_disable_unprepare(qproc->gpll0_mss_clk); +err_gpll0_mss_clk: + clk_disable_unprepare(qproc->rom_clk); +err_rom_clk: + clk_disable_unprepare(qproc->axi_clk); +err_axi_clk: + clk_disable_unprepare(qproc->ahb_clk); +out: + dev_err(qproc->dev, "Clk Vote Failed\n"); + return ret; +} + +static void q6v55_clk_disable(struct q6v5 *qproc) +{ + + clk_disable_unprepare(qproc->mnoc_axi_clk); + clk_disable_unprepare(qproc->snoc_axi_clk); + clk_disable_unprepare(qproc->gpll0_mss_clk); + clk_disable_unprepare(qproc->rom_clk); + clk_disable_unprepare(qproc->axi_clk); + if (!qproc->ahb_clk_vote) + clk_disable_unprepare(qproc->ahb_clk); +} + +static int q6v55_proxy_vote(struct q6v5 *qproc) +{ + struct regulator *mx = qproc->supply[Q6V5_SUPPLY_MX].consumer; + struct regulator *cx = qproc->supply[Q6V5_SUPPLY_CX].consumer; + struct regulator *vdd_pll = qproc->supply[Q6V5_SUPPLY_PLL].consumer; + int ret; + + ret = regulator_set_voltage(mx, INT_MAX, INT_MAX); + if (ret) { + dev_err(qproc->dev, "Failed to set voltage for vreg_mx\n"); + return ret; + } + + ret = regulator_enable(mx); + if (ret) { + dev_err(qproc->dev, "Failed to enable vreg_mx\n"); + goto err_mx_enable; + } + + ret = regulator_set_voltage(cx, INT_MAX, INT_MAX); + if (ret) { + dev_err(qproc->dev, "Failed to request vdd_cx voltage.\n"); + goto err_cx_voltage; + } + + ret = regulator_set_load(cx, 100000); + if (ret < 0) { + dev_err(qproc->dev, "Failed to set vdd_cx mode.\n"); + goto err_cx_set_load; + } + + ret = regulator_enable(cx); + if (ret) { + dev_err(qproc->dev, "Failed to vote for vdd_cx\n"); + goto err_cx_enable; + } + + ret = regulator_set_voltage(vdd_pll, 1800000, 1800000); + if (ret) { + dev_err(qproc->dev, "Failed to set voltage for vdd_pll\n"); + goto err_vreg_pll_set_vol; + } + + ret = regulator_set_load(vdd_pll, 10000); + if (ret < 0) { + dev_err(qproc->dev, "Failed to set vdd_pll mode.\n"); + goto err_vreg_pll_load; + } + + ret = regulator_enable(vdd_pll); + if (ret) { + dev_err(qproc->dev, "Failed to vote for vdd_pll\n"); + goto err_vreg_pll_enable; + } + + ret = clk_prepare_enable(qproc->xo); + if (ret) + goto err_xo_vote; + + ret = clk_prepare_enable(qproc->pnoc_clk); + if (ret) + goto err_pnoc_vote; + + ret = clk_prepare_enable(qproc->qdss_clk); + if (ret) + goto err_qdss_vote; + qproc->unvote_flag = false; + return 0; + +err_qdss_vote: + clk_disable_unprepare(qproc->pnoc_clk); +err_pnoc_vote: + clk_disable_unprepare(qproc->xo); +err_xo_vote: + regulator_disable(vdd_pll); +err_vreg_pll_enable: + regulator_set_load(vdd_pll, 0); +err_vreg_pll_load: + regulator_set_voltage(vdd_pll, 0, INT_MAX); +err_vreg_pll_set_vol: + regulator_disable(cx); +err_cx_enable: + regulator_set_load(cx, 0); +err_cx_set_load: + regulator_set_voltage(cx, 0, INT_MAX); +err_cx_voltage: + regulator_disable(mx); +err_mx_enable: + regulator_set_voltage(mx, 0, INT_MAX); + + return ret; +} + +static void q6v55_proxy_unvote(struct q6v5 *qproc) +{ + if (!qproc->unvote_flag) { + regulator_disable(qproc->supply[Q6V5_SUPPLY_PLL].consumer); + regulator_set_load(qproc->supply[Q6V5_SUPPLY_PLL].consumer, 0); + regulator_disable(qproc->supply[Q6V5_SUPPLY_CX].consumer); + regulator_set_load(qproc->supply[Q6V5_SUPPLY_CX].consumer, 0); + regulator_set_voltage(qproc->supply[Q6V5_SUPPLY_CX].consumer, + 0, INT_MAX); + + clk_disable_unprepare(qproc->qdss_clk); + clk_disable_unprepare(qproc->pnoc_clk); + clk_disable_unprepare(qproc->xo); + + regulator_disable(qproc->supply[Q6V5_SUPPLY_MX].consumer); + regulator_set_voltage(qproc->supply[Q6V5_SUPPLY_MX].consumer, + 0, INT_MAX); + } + qproc->unvote_flag = true; +} + +static void pil_mss_restart_reg(struct q6v5 *qproc, u32 mss_restart) +{ + if (qproc->restart_reg) { + writel_relaxed(mss_restart, qproc->restart_reg); + udelay(2); + } +} + static int q6v5_load(struct rproc *rproc, const struct firmware *fw) { struct q6v5 *qproc = rproc->priv; @@ -751,6 +948,65 @@ static int q6v5_init_clocks(struct q6v5 *qproc) return 0; } +static int q6v55_init_clocks(struct q6v5 *qproc) +{ + qproc->ahb_clk = devm_clk_get(qproc->dev, "iface"); + if (IS_ERR(qproc->ahb_clk)) { + dev_err(qproc->dev, "failed to get iface clock\n"); + return PTR_ERR(qproc->ahb_clk); + } + + qproc->axi_clk = devm_clk_get(qproc->dev, "bus"); + if (IS_ERR(qproc->axi_clk)) { + dev_err(qproc->dev, "failed to get bus clock\n"); + return PTR_ERR(qproc->axi_clk); + } + + qproc->rom_clk = devm_clk_get(qproc->dev, "mem"); + if (IS_ERR(qproc->rom_clk)) { + dev_err(qproc->dev, "failed to get mem clock\n"); + return PTR_ERR(qproc->rom_clk); + } + + qproc->snoc_axi_clk = devm_clk_get(qproc->dev, "snoc_axi_clk"); + if (IS_ERR(qproc->snoc_axi_clk)) { + dev_err(qproc->dev, "failed to get snoc_axi_clk\n"); + return PTR_ERR(qproc->snoc_axi_clk); + } + + qproc->mnoc_axi_clk = devm_clk_get(qproc->dev, "mnoc_axi_clk"); + if (IS_ERR(qproc->mnoc_axi_clk)) { + dev_err(qproc->dev, "failed to get mnoc_axi_clk clock\n"); + return PTR_ERR(qproc->mnoc_axi_clk); + } + + qproc->gpll0_mss_clk = devm_clk_get(qproc->dev, "gpll0_mss_clk"); + if (IS_ERR(qproc->gpll0_mss_clk)) { + dev_err(qproc->dev, "failed to get gpll0_mss_clk clock\n"); + return PTR_ERR(qproc->gpll0_mss_clk); + } + + qproc->xo = devm_clk_get(qproc->dev, "xo"); + if (IS_ERR(qproc->xo)) { + dev_err(qproc->dev, "failed to get xo\n"); + return PTR_ERR(qproc->xo); + } + + qproc->pnoc_clk = devm_clk_get(qproc->dev, "pnoc"); + if (IS_ERR(qproc->pnoc_clk)) { + dev_err(qproc->dev, "failed to get pnoc_clk clock\n"); + return PTR_ERR(qproc->pnoc_clk); + } + + qproc->qdss_clk = devm_clk_get(qproc->dev, "qdss"); + if (IS_ERR(qproc->qdss_clk)) { + dev_err(qproc->dev, "failed to get qdss_clk clock\n"); + return PTR_ERR(qproc->qdss_clk); + } + + return 0; +} + static int q6v5_init_reset(struct q6v5 *qproc) { qproc->mss_restart = devm_reset_control_get(qproc->dev, NULL); @@ -762,6 +1018,21 @@ static int q6v5_init_reset(struct q6v5 *qproc) return 0; } +static int q6v55_init_reset(struct q6v5 *qproc, struct platform_device *pdev) +{ + struct resource *res; + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "restart_reg"); + qproc->restart_reg = devm_ioremap(qproc->dev, res->start, + resource_size(res)); + if (IS_ERR(qproc->restart_reg)) { + dev_err(qproc->dev, "failed to get restart_reg\n"); + return PTR_ERR(qproc->restart_reg); + } + + return 0; +} + static int q6v5_request_irq(struct q6v5 *qproc, struct platform_device *pdev, const char *name,