Received: by 2002:a05:7412:31a9:b0:e2:908c:2ebd with SMTP id et41csp2887326rdb; Tue, 12 Sep 2023 15:44:39 -0700 (PDT) X-Google-Smtp-Source: AGHT+IFmmY/jdq724TPy+BD9hkC7MJSyf0wwgWwlpAwtGY9Qi+yWto1EC7cqwyAxClABx0YOhd97 X-Received: by 2002:a17:90a:1f84:b0:263:730b:f568 with SMTP id x4-20020a17090a1f8400b00263730bf568mr601061pja.3.1694558679270; Tue, 12 Sep 2023 15:44:39 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1694558679; cv=none; d=google.com; s=arc-20160816; b=sJ05aJM1ghcszWob1plCETLXGnkJKpnafHxkZQH+yZ2c6llW/vGqa5fH96mAE9LUeV a/L1sRYke5OQbgK85Wv4FacRKCcW9yv2J4Kh+w/PAFe5bd+pdQe0jVLKk/9IH5Rw3IPW IEOC76ooZ/eYprKHrNd7RsdecKcq92gyP+lo0yaC/K/csT32xn/tS4vEVYvoQgwkwfwc f2Fyp6k8xl7CF2AlcasQrgA7nQIvWzeyNcRulYEs+ixkmINQFtm3dU8U66p6Ki0+apTw 6LQs332Fp0Lms8gChgXds5dV+oc0vCUWA9OQwYmKFFt4NGZc3SIKb2iptnAp8CZIdOaV h5sg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:cc:to:in-reply-to:references:message-id :content-transfer-encoding:mime-version:subject:date:from :dkim-signature; bh=d8aTXSfXKUiK1Xyz5/399gXFzKYpAJm1Z7s+7n6AgiA=; fh=10DQ9cLgm4jgsgyilmWpXaSieUpiqS1iqWfjfWaX8GI=; b=LZStGosdtcbl+lBLnSHSdRRYaZ0s2LEeAnCGCWdk63cFyYb3HLOwITZsPvFCI6ORUU V7YVaPm1geZFWGF3+ZETtrBhVg9rUkJVrwkoNSYDRbM0tGj9ccNepchuEcn1UC75wMYZ FoHl6+rQ6Rpju4jUGdQegdSUvxv3Pbmlf/4AHW4jMkYfnd4WJSGkMEbnmjnFBPX+G9Ms yDbbBD+VEhU2OnXIfWTOayCGJ25jjk1RqLDp4hw2Ky1v8dEa5KBg6/FLNWOum2FfeICK txRJG/fztcQYfwwez+XbqrcJMaaIJ6T48MM6HQRxHOLzd6fctRXk+WoQksZgf0fPkCmo +UfQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernkonzept.com header.s=mx1 header.b=VW2OT9ME; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:4 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernkonzept.com Return-Path: Received: from howler.vger.email (howler.vger.email. [2620:137:e000::3:4]) by mx.google.com with ESMTPS id q36-20020a17090a752700b00263f3c1bb86si212484pjk.158.2023.09.12.15.44.38 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 12 Sep 2023 15:44:39 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:4 as permitted sender) client-ip=2620:137:e000::3:4; Authentication-Results: mx.google.com; dkim=pass header.i=@kernkonzept.com header.s=mx1 header.b=VW2OT9ME; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:4 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernkonzept.com Received: from out1.vger.email (depot.vger.email [IPv6:2620:137:e000::3:0]) by howler.vger.email (Postfix) with ESMTP id DFD5D8794384; Tue, 12 Sep 2023 07:31:23 -0700 (PDT) X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.103.10 at howler.vger.email Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235991AbjILObG (ORCPT + 99 others); Tue, 12 Sep 2023 10:31:06 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34208 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235968AbjILOa7 (ORCPT ); Tue, 12 Sep 2023 10:30:59 -0400 Received: from mx.kernkonzept.com (serv1.kernkonzept.com [IPv6:2a01:4f8:1c1c:b490::2]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id EC88FCC7; Tue, 12 Sep 2023 07:30:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=kernkonzept.com; s=mx1; h=Cc:To:In-Reply-To:References:Message-Id: Content-Transfer-Encoding:Content-Type:MIME-Version:Subject:Date:From: Reply-To:Content-ID:Content-Description; bh=d8aTXSfXKUiK1Xyz5/399gXFzKYpAJm1Z7s+7n6AgiA=; b=VW2OT9MEsssDRMkwh3Uc/UV/sU ZvJI7PAAq82QQLTuNMbZ4JB2NvSLaDDhCPziIIIXjoZuw5Si5G7cBoMsE6xSHv21w48NpUQnK+0aS xlAPsANfObrC1zT09ttft7W+z3JCpckVRiUodnA48hUGcsuU5GRfWlotgo1sSQ/yewjwa4Ld/fYdl nImSY9IBb27xYyDp8bkpdUjxhq30ecnHdGpf0m7nyf5FLHMUCl0mrXQXGHsMEw7GBj54hLCAAKRa7 hNAcKfTXX6fvIWrmTWQ9wqC2+4JOJBdElsYVcng7iofUJJ6jJIG88oT9CmsDCrBpjht7ereCuItgF jxnItlew==; Received: from [10.22.3.24] (helo=serv1.dd1.int.kernkonzept.com) by mx.kernkonzept.com with esmtpsa (TLS1.3:ECDHE_X25519__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim 4.96) id 1qg4Pk-0034i9-1z; Tue, 12 Sep 2023 16:30:52 +0200 From: Stephan Gerhold Date: Tue, 12 Sep 2023 16:30:39 +0200 Subject: [PATCH 4/4] spi: qup: Vote for interconnect bandwidth to DRAM MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Message-Id: <20230912-spi-qup-dvfs-v1-4-3e38aa09c2bd@kernkonzept.com> References: <20230912-spi-qup-dvfs-v1-0-3e38aa09c2bd@kernkonzept.com> In-Reply-To: <20230912-spi-qup-dvfs-v1-0-3e38aa09c2bd@kernkonzept.com> To: Mark Brown Cc: Andy Gross , Bjorn Andersson , Konrad Dybcio , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Krzysztof Kozlowski , linux-arm-msm@vger.kernel.org, linux-spi@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Stephan Gerhold X-Mailer: b4 0.12.3 Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-Greylist: Sender passed SPF test, not delayed by milter-greylist-4.6.4 (howler.vger.email [0.0.0.0]); Tue, 12 Sep 2023 07:31:24 -0700 (PDT) When the SPI QUP controller is used together with a DMA engine it needs to vote for the interconnect path to the DRAM. Otherwise it may be unable to access the memory quickly enough. The requested peak bandwidth is dependent on the SPI core/bus clock so that the bandwidth scales together with the selected SPI speed. To avoid sending votes too often the bandwidth is always requested when a transfer starts, but dropped only on runtime suspend. Runtime suspend should only happen if no transfer is active. After resumption we can defer the next vote until the first transfer actually happens. Signed-off-by: Stephan Gerhold --- The bandwidth calculation is taken over from Qualcomm's downstream/vendor driver [1]. Due to lack of documentation about the interconnect setup/behavior I cannot say exactly if this is right. Unfortunately, this is not implemented very consistently downstream... [1]: https://git.codelinaro.org/clo/la/kernel/msm-3.18/-/commit/deca0f346089d32941d6d8194ae9605554486413 --- drivers/spi/spi-qup.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/drivers/spi/spi-qup.c b/drivers/spi/spi-qup.c index bf043be3a2a9..e9c186bc530c 100644 --- a/drivers/spi/spi-qup.c +++ b/drivers/spi/spi-qup.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -122,11 +123,14 @@ #define SPI_DELAY_THRESHOLD 1 #define SPI_DELAY_RETRY 10 +#define SPI_BUS_WIDTH 8 + struct spi_qup { void __iomem *base; struct device *dev; struct clk *cclk; /* core clock */ struct clk *iclk; /* interface clock */ + struct icc_path *icc_path; /* interconnect to RAM */ int irq; spinlock_t lock; @@ -149,6 +153,8 @@ struct spi_qup { int mode; struct dma_slave_config rx_conf; struct dma_slave_config tx_conf; + + u32 bw_speed_hz; }; static int spi_qup_io_config(struct spi_device *spi, struct spi_transfer *xfer); @@ -181,6 +187,23 @@ static inline bool spi_qup_is_valid_state(struct spi_qup *controller) return opstate & QUP_STATE_VALID; } +static int spi_qup_vote_bw(struct spi_qup *controller, u32 speed_hz) +{ + u32 needed_peak_bw; + int ret; + + if (controller->bw_speed_hz == speed_hz) + return 0; + + needed_peak_bw = Bps_to_icc(speed_hz * SPI_BUS_WIDTH); + ret = icc_set_bw(controller->icc_path, 0, needed_peak_bw); + if (ret) + return ret; + + controller->bw_speed_hz = speed_hz; + return 0; +} + static int spi_qup_set_state(struct spi_qup *controller, u32 state) { unsigned long loop; @@ -675,6 +698,12 @@ static int spi_qup_io_prep(struct spi_device *spi, struct spi_transfer *xfer) return -EIO; } + ret = spi_qup_vote_bw(controller, xfer->speed_hz); + if (ret) { + dev_err(controller->dev, "fail to vote for ICC bandwidth: %d\n", ret); + return -EIO; + } + controller->w_size = DIV_ROUND_UP(xfer->bits_per_word, 8); controller->n_words = xfer->len / controller->w_size; @@ -994,6 +1023,7 @@ static void spi_qup_set_cs(struct spi_device *spi, bool val) static int spi_qup_probe(struct platform_device *pdev) { struct spi_controller *host; + struct icc_path *icc_path; struct clk *iclk, *cclk; struct spi_qup *controller; struct resource *res; @@ -1019,6 +1049,11 @@ static int spi_qup_probe(struct platform_device *pdev) if (IS_ERR(iclk)) return PTR_ERR(iclk); + icc_path = devm_of_icc_get(dev, NULL); + if (IS_ERR(icc_path)) + return dev_err_probe(dev, PTR_ERR(icc_path), + "failed to get interconnect path\n"); + /* This is optional parameter */ if (of_property_read_u32(dev->of_node, "spi-max-frequency", &max_freq)) max_freq = SPI_MAX_RATE; @@ -1070,6 +1105,7 @@ static int spi_qup_probe(struct platform_device *pdev) controller->base = base; controller->iclk = iclk; controller->cclk = cclk; + controller->icc_path = icc_path; controller->irq = irq; ret = spi_qup_init_dma(host, res->start); @@ -1190,6 +1226,7 @@ static int spi_qup_pm_suspend_runtime(struct device *device) writel_relaxed(config, controller->base + QUP_CONFIG); clk_disable_unprepare(controller->cclk); + spi_qup_vote_bw(controller, 0); clk_disable_unprepare(controller->iclk); return 0; @@ -1241,6 +1278,7 @@ static int spi_qup_suspend(struct device *device) return ret; clk_disable_unprepare(controller->cclk); + spi_qup_vote_bw(controller, 0); clk_disable_unprepare(controller->iclk); return 0; } -- 2.39.2