From patchwork Thu Jul 20 05:40:56 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Manivannan Sadhasivam X-Patchwork-Id: 13319772 X-Patchwork-Delegate: viresh.linux@gmail.com 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 45C78EB64DA for ; Thu, 20 Jul 2023 05:44:07 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229638AbjGTFoF (ORCPT ); Thu, 20 Jul 2023 01:44:05 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45310 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229795AbjGTFnS (ORCPT ); Thu, 20 Jul 2023 01:43:18 -0400 Received: from mail-pl1-x630.google.com (mail-pl1-x630.google.com [IPv6:2607:f8b0:4864:20::630]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 035F130C5 for ; Wed, 19 Jul 2023 22:42:56 -0700 (PDT) Received: by mail-pl1-x630.google.com with SMTP id d9443c01a7336-1b8ad8383faso2969065ad.0 for ; Wed, 19 Jul 2023 22:42:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1689831775; x=1690436575; 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=+PtBZ5U/uPeERQpI5byb7Cw2i1LitARzlq3AxNOTl7Y=; b=PSnMmuzeuzp+CHguDgsPdH2ueKHeCczg8ZwasHEQ+OzeEZip46ABNIepHFaQjYbdXC F6mdtMsudDtv6gjzmXu8LtvA415BkI+jcUYYS8xcPSUZqZfu/xjRXp1xZZPWGPB6PQvM rK3xA95hOhrJEiq5Pa5jtCfz4bRT/oBzRA8LL2TJ8GtBxYlGVagJGLaq6VydCzp8I2XK 4nuO5xRcnAcn8LL605V3EZWAW5HPRUEhRJ8rPMlQwbi/s46XluXeFUP34UAir1Fty87i 1XWCReNg/8oRaetNS2siuUJp2rlWVuX+t+EkwWA5DdbbaK9ctdWf+kGg0fgsTLhqaQxq kl3w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1689831775; x=1690436575; 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=+PtBZ5U/uPeERQpI5byb7Cw2i1LitARzlq3AxNOTl7Y=; b=A1nE4P+UOjkGIaiidzYK0m5TQz/jQY7txLjbvoHMtN2PYIYNb1VEOYPGBmXnMMov/q XvNSMk/XikYVObyJ/yaYCZeK12rjKpE9xBJB3w1nGamcsTD7430YCTrFfCALkwic7xt2 /e5qtP8VQgiwvwtE5efUk908uouxX8Omag8TbSRZwbNy+PIFL4RnXMzgq2bAepYyAS5r Tnb1Nl8w3AkysjFoYqUfFIkIuNfQhnpSLHaGbtn4IXlXJkqmItqfK3sOdQVQ6H4txpsx I36/SABQrxEgekZI5N1vjdLUhkuBBFC87gd+BbtVEFGc0O8gEzq/GvK4AhmOOVV51J5k moHA== X-Gm-Message-State: ABy/qLbjmp+aC/R7TdKGw/xMsRJwCB3a6m/rBovvOBpKAPi9tDcW8p97 jEMv41gw5LwOdKYeCkvdBrcL X-Google-Smtp-Source: APBJJlE/LOcw+JdTlwuyAIz4XZg6e4QAMhhdecxDbMa00fwfU20dZgTdg0SX4kh8nI5Jird0qf6KHQ== X-Received: by 2002:a17:902:f543:b0:1b8:6987:de84 with SMTP id h3-20020a170902f54300b001b86987de84mr1418870plf.48.1689831774485; Wed, 19 Jul 2023 22:42:54 -0700 (PDT) Received: from localhost.localdomain ([117.206.119.70]) by smtp.gmail.com with ESMTPSA id r2-20020a170902be0200b001b85bb5fd77sm263367pls.119.2023.07.19.22.42.47 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 19 Jul 2023 22:42:54 -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 v2 11/15] scsi: ufs: host: Add support for parsing OPP Date: Thu, 20 Jul 2023 11:10:56 +0530 Message-Id: <20230720054100.9940-12-manivannan.sadhasivam@linaro.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230720054100.9940-1-manivannan.sadhasivam@linaro.org> References: <20230720054100.9940-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/host/ufshcd-pltfrm.c | 116 +++++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) diff --git a/drivers/ufs/host/ufshcd-pltfrm.c b/drivers/ufs/host/ufshcd-pltfrm.c index 0b7430033047..068c22378c88 100644 --- a/drivers/ufs/host/ufshcd-pltfrm.c +++ b/drivers/ufs/host/ufshcd-pltfrm.c @@ -8,8 +8,10 @@ * Vinayak Holikatti */ +#include #include #include +#include #include #include @@ -17,6 +19,8 @@ #include "ufshcd-pltfrm.h" #include +#include + #define UFSHCD_DEFAULT_LANES_PER_DIRECTION 2 static int ufshcd_parse_clock_info(struct ufs_hba *hba) @@ -205,6 +209,112 @@ static void ufshcd_init_lanes_per_dir(struct ufs_hba *hba) } } +static 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_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 +481,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");