From patchwork Mon Jul 31 16:33:55 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Manivannan Sadhasivam X-Patchwork-Id: 708664 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0AF0FC001DE for ; Mon, 31 Jul 2023 16:35:37 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233381AbjGaQff (ORCPT ); Mon, 31 Jul 2023 12:35:35 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38448 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233332AbjGaQfU (ORCPT ); Mon, 31 Jul 2023 12:35:20 -0400 Received: from mail-pl1-x62d.google.com (mail-pl1-x62d.google.com [IPv6:2607:f8b0:4864:20::62d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D47B01BF4 for ; Mon, 31 Jul 2023 09:35:13 -0700 (PDT) Received: by mail-pl1-x62d.google.com with SMTP id d9443c01a7336-1bb893e6365so29459545ad.2 for ; Mon, 31 Jul 2023 09:35:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1690821313; x=1691426113; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=7YIa5Rshmw2ntNEkTY+rkUxHvA/nhtNXwKaK1yvsaSc=; b=KHoZXLAcLD3i5mZFLHRkTGUtoAsRzwUtdcFQ+syc6XkFMBbnv1i0G3FF4sGPAzy8HZ JrORlPVqjxAtIgsU4EDfL5HD10TOn94qLNxJG5bFPx2c7eExKhEhaCUKE0QU4YbFepAv 7D1utB1n0aHd3qXSUPqOfIqBiZ7NX55SUfJ9szGWG+7n40Zxb4obWAKRC3R8S0IKaIoU 1JpwQyG4VQUqCLKs34+5fcws4I7T6ee3Da5NbpIVCkLjtrKp9pfNEOfkKZQK6v1yyIxN b48/2tDxIT4xXDTRc+2ZwLs7uSvfl2e6flPc7ylkFMp+pbYXCAegKxaq4x5jI1Lm7mkB LfPQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1690821313; x=1691426113; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=7YIa5Rshmw2ntNEkTY+rkUxHvA/nhtNXwKaK1yvsaSc=; b=iDh6GuE0ACnHR23GGP2UdXJsJ6s/eCEr5e4D1I+RZrxnr1lp5ZulVyJfOl3PqvN4kL 3frBMrLfQuthZIuSaIaq1xQuYT89Wul9QDwFsmSOuns6ri0IYUaSsfjJE+x6aIQxknC+ +AeuUiB4nX7vOqMoSSE7QmNqexFh6tfK0v0EvmzQ+s6+QeQYazo6D2kxUlslgM7Viqgx kUxvmC5gcZLcB7f18hiPDtzLDkKLUSgTH0p1GTOou5Vvq4pFmGgLKSoDExWWFRXRu5QP dixvE/XfJPd3JhyCTgL4m1L54A1S2SJB7FcwWu+E7t4tyJlmExwk2Waoido8cHxD3Wak B9Tw== X-Gm-Message-State: ABy/qLbAq8a4NMIWn3+FD3q7FVcPVg4WXaKjoyKAVuOY/o4ZzAdxwTrA eSud1LkfFIsUHN5NGfbT6W8VSLJTCyy7dz1Qmw== X-Google-Smtp-Source: APBJJlFVC1KXN9cx+8dSKq5rZbkr00B2TTGaDBPqzRWcBNaqnO0nijXdfCXbWyDbZelQrqVKcMyfTQ== X-Received: by 2002:a17:902:7295:b0:1bc:3e1:699 with SMTP id d21-20020a170902729500b001bc03e10699mr5226755pll.11.1690821313214; Mon, 31 Jul 2023 09:35:13 -0700 (PDT) Received: from localhost.localdomain ([117.193.209.129]) by smtp.gmail.com with ESMTPSA id w8-20020a170902e88800b001bb1f09189bsm8779541plg.221.2023.07.31.09.35.05 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 31 Jul 2023 09:35:12 -0700 (PDT) From: Manivannan Sadhasivam To: vireshk@kernel.org, nm@ti.com, sboyd@kernel.org, myungjoo.ham@samsung.com, kyungmin.park@samsung.com, cw00.choi@samsung.com, andersson@kernel.org, konrad.dybcio@linaro.org, robh+dt@kernel.org, krzysztof.kozlowski+dt@linaro.org, conor+dt@kernel.org, jejb@linux.ibm.com, martin.petersen@oracle.com Cc: alim.akhtar@samsung.com, avri.altman@wdc.com, bvanassche@acm.org, linux-scsi@vger.kernel.org, linux-pm@vger.kernel.org, linux-arm-msm@vger.kernel.org, devicetree@vger.kernel.org, quic_asutoshd@quicinc.com, quic_cang@quicinc.com, quic_nitirawa@quicinc.com, quic_narepall@quicinc.com, quic_bhaskarv@quicinc.com, quic_richardp@quicinc.com, quic_nguyenb@quicinc.com, quic_ziqichen@quicinc.com, bmasney@redhat.com, krzysztof.kozlowski@linaro.org, linux-kernel@vger.kernel.org, Manivannan Sadhasivam Subject: [PATCH v3 4/6] scsi: ufs: host: Add support for parsing OPP Date: Mon, 31 Jul 2023 22:03:55 +0530 Message-Id: <20230731163357.49045-5-manivannan.sadhasivam@linaro.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230731163357.49045-1-manivannan.sadhasivam@linaro.org> References: <20230731163357.49045-1-manivannan.sadhasivam@linaro.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org OPP framework can be used to scale the clocks along with other entities such as regulators, performance state etc... So let's add support for parsing OPP from devicetree. OPP support in devicetree is added through the "operating-points-v2" property which accepts the OPP table defining clock frequency, regulator voltage, power domain performance state etc... Since the UFS controller requires multiple clocks to be controlled for proper working, devm_pm_opp_set_config() has been used which supports scaling multiple clocks through custom ufshcd_opp_config_clks() callback. It should be noted that the OPP support is not compatible with the old "freq-table-hz" property. So only one can be used at a time even though the UFS core supports both. Co-developed-by: Krzysztof Kozlowski Signed-off-by: Krzysztof Kozlowski Signed-off-by: Manivannan Sadhasivam --- drivers/ufs/core/ufshcd.c | 35 ++++++++++++++ drivers/ufs/host/ufshcd-pltfrm.c | 78 ++++++++++++++++++++++++++++++++ include/ufs/ufshcd.h | 3 ++ 3 files changed, 116 insertions(+) diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c index 263e0c65e19a..3ec5376b9f3f 100644 --- a/drivers/ufs/core/ufshcd.c +++ b/drivers/ufs/core/ufshcd.c @@ -1087,6 +1087,41 @@ static int ufshcd_set_clk_freq(struct ufs_hba *hba, bool scale_up) return ret; } +int ufshcd_opp_config_clks(struct device *dev, struct opp_table *opp_table, + struct dev_pm_opp *opp, void *data, + bool scaling_down) +{ + struct ufs_hba *hba = dev_get_drvdata(dev); + struct list_head *head = &hba->clk_list_head; + struct ufs_clk_info *clki; + unsigned long freq; + u8 idx = 0; + int ret; + + list_for_each_entry(clki, head, list) { + if (!IS_ERR_OR_NULL(clki->clk)) { + freq = dev_pm_opp_get_freq_indexed(opp, idx++); + + /* Do not set rate for clocks having frequency as 0 */ + if (!freq) + continue; + + ret = clk_set_rate(clki->clk, freq); + if (ret) { + dev_err(dev, "%s: %s clk set rate(%ldHz) failed, %d\n", + __func__, clki->name, freq, ret); + return ret; + } + + trace_ufshcd_clk_scaling(dev_name(dev), + (scaling_down ? "scaled down" : "scaled up"), + clki->name, hba->clk_scaling.target_freq, freq); + } + } + + return 0; +} + static int ufshcd_opp_set_rate(struct ufs_hba *hba, unsigned long freq) { struct dev_pm_opp *opp; diff --git a/drivers/ufs/host/ufshcd-pltfrm.c b/drivers/ufs/host/ufshcd-pltfrm.c index 7005046e8a69..7382c70ce552 100644 --- a/drivers/ufs/host/ufshcd-pltfrm.c +++ b/drivers/ufs/host/ufshcd-pltfrm.c @@ -10,6 +10,7 @@ #include #include +#include #include #include @@ -205,6 +206,77 @@ static void ufshcd_init_lanes_per_dir(struct ufs_hba *hba) } } +static int ufshcd_parse_operating_points(struct ufs_hba *hba) +{ + struct device *dev = hba->dev; + struct device_node *np = dev->of_node; + struct dev_pm_opp_config config = {}; + struct ufs_clk_info *clki; + const char **clk_names; + int cnt, i, ret; + + if (!of_find_property(np, "operating-points-v2", NULL)) + return 0; + + if (of_find_property(np, "freq-table-hz", NULL)) { + dev_err(dev, "%s: operating-points and freq-table-hz are incompatible\n", + __func__); + return -EINVAL; + } + + cnt = of_property_count_strings(np, "clock-names"); + if (cnt <= 0) { + dev_err(dev, "%s: Missing clock-names\n", __func__); + return -ENODEV; + } + + /* OPP expects clk_names to be NULL terminated */ + clk_names = devm_kcalloc(dev, cnt + 1, sizeof(*clk_names), GFP_KERNEL); + if (!clk_names) + return -ENOMEM; + + /* + * We still need to get reference to all clocks as the UFS core uses + * them separately. + */ + for (i = 0; i < cnt; i++) { + ret = of_property_read_string_index(np, "clock-names", i, + &clk_names[i]); + if (ret) + return ret; + + clki = devm_kzalloc(dev, sizeof(*clki), GFP_KERNEL); + if (!clki) + return -ENOMEM; + + clki->name = devm_kstrdup(dev, clk_names[i], GFP_KERNEL); + if (!clki->name) + return -ENOMEM; + + if (!strcmp(clk_names[i], "ref_clk")) + clki->keep_link_active = true; + + list_add_tail(&clki->list, &hba->clk_list_head); + } + + config.clk_names = clk_names, + config.config_clks = ufshcd_opp_config_clks; + + ret = devm_pm_opp_set_config(dev, &config); + if (ret) + return ret; + + ret = devm_pm_opp_of_add_table(dev); + if (ret) { + dev_err(dev, "Failed to add OPP table: %d\n", ret); + return ret; + } + + hba->use_pm_opp = true; + + return 0; +} + /** * ufshcd_get_pwr_dev_param - get finally agreed attributes for * power mode change @@ -371,6 +443,12 @@ int ufshcd_pltfrm_init(struct platform_device *pdev, ufshcd_init_lanes_per_dir(hba); + err = ufshcd_parse_operating_points(hba); + if (err) { + dev_err(dev, "%s: OPP parse failed %d\n", __func__, err); + goto dealloc_host; + } + err = ufshcd_init(hba, mmio_base, irq); if (err) { dev_err(dev, "Initialization failed\n"); diff --git a/include/ufs/ufshcd.h b/include/ufs/ufshcd.h index 0e1e813fa491..328cda43dd8b 100644 --- a/include/ufs/ufshcd.h +++ b/include/ufs/ufshcd.h @@ -1237,6 +1237,9 @@ void ufshcd_mcq_make_queues_operational(struct ufs_hba *hba); void ufshcd_mcq_enable_esi(struct ufs_hba *hba); void ufshcd_mcq_config_esi(struct ufs_hba *hba, struct msi_msg *msg); +int ufshcd_opp_config_clks(struct device *dev, struct opp_table *opp_table, + struct dev_pm_opp *opp, void *data, + bool scaling_down); /** * ufshcd_set_variant - set variant specific data to the hba * @hba: per adapter instance