From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 140A03984AA; Mon, 5 May 2025 23:07:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1746486446; cv=none; b=JXKrHNnN7lGuF2rOsj6QzYEgL2tK7Yp9GCQygAcMC6XWLfCqxcxV98pNMa+k+U/bTQHgo82voeY+zUcAJ+eELup+pDVYB0oVzq6z4Hmy0PamdznS4GJJnpBPwE2h5Kiabnt+Fx2nZycsjlj26CmlS9xR4yz//g0yUTZvY6ZW210= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1746486446; c=relaxed/simple; bh=OqvEyzsv9AdFaQrtdXjMiFxu/DeT79NiQI0Tu3tEQCk=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=GiV4DmlYrrKKTY+Yb71nA0FN3Gz2CXElNV9MBVmFYLKKO/gWNa2FkcKzHb8UZGAZoeRaAM2FfodoJMkVhNkejkmJXcHC7dtVXYhr6FQ9ijzzedeXLnZYDu8Zj4vXtq7JsCkLtY+KQzEwzhXXovQo1GcyCqv+k5h4969dnuJTA2A= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=MqNbRQT5; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="MqNbRQT5" Received: by smtp.kernel.org (Postfix) with ESMTPSA id A7F87C4CEEF; Mon, 5 May 2025 23:07:24 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1746486445; bh=OqvEyzsv9AdFaQrtdXjMiFxu/DeT79NiQI0Tu3tEQCk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=MqNbRQT5qrywc7lqeK5l6tHyBGeRPGB4LEnd3/W7GXsHCNwCs9ZIgPxV7EUOTMsFE 7pDNKUQVbLqalnBavYsIz93XGf1NADjSMEq7V30MctQFMWuFa2Yg/80Y7C4QC5n+si CtmSyXRh09pt+uKCP/s4VbZm2Idtk+2X2jKnYO1PEiPy2oQNCoPgvfDFZ2AwpHwUVU HhLGzDG/uldogNNZ5S606ovqmO6GZpbe1Sr24eXQ1vx+DQaGQrPW0XHTzNvCelwDZE 8PB6O+kV0Bnt/JhK7srQt7j63gzHBVn+rps+WBSYP2gHdTuvHsK4GFMEa4Uy3lWPfC QGdyAviBHFh8Q== From: Sasha Levin To: linux-kernel@vger.kernel.org, stable@vger.kernel.org Cc: Stephan Gerhold , Andi Shyti , Sasha Levin , linux-arm-msm@vger.kernel.org, linux-i2c@vger.kernel.org Subject: [PATCH AUTOSEL 6.1 032/212] i2c: qup: Vote for interconnect bandwidth to DRAM Date: Mon, 5 May 2025 19:03:24 -0400 Message-Id: <20250505230624.2692522-32-sashal@kernel.org> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20250505230624.2692522-1-sashal@kernel.org> References: <20250505230624.2692522-1-sashal@kernel.org> Precedence: bulk X-Mailing-List: stable@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-stable: review X-Patchwork-Hint: Ignore X-stable-base: Linux 6.1.136 Content-Transfer-Encoding: 8bit From: Stephan Gerhold [ Upstream commit d4f35233a6345f62637463ef6e0708f44ffaa583 ] When the I2C 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 I2C core clock. To avoid sending votes too often the bandwidth is always requested when a DMA 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 DMA transfer actually happens. The implementation is largely identical to the one introduced for spi-qup in commit ecdaa9473019 ("spi: qup: Vote for interconnect bandwidth to DRAM") since both drivers represent the same hardware block. Signed-off-by: Stephan Gerhold Signed-off-by: Andi Shyti Link: https://lore.kernel.org/r/20231128-i2c-qup-dvfs-v1-3-59a0e3039111@kernkonzept.com Signed-off-by: Sasha Levin --- drivers/i2c/busses/i2c-qup.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c index 78682388e02ed..82de4651d18f0 100644 --- a/drivers/i2c/busses/i2c-qup.c +++ b/drivers/i2c/busses/i2c-qup.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -150,6 +151,8 @@ /* TAG length for DATA READ in RX FIFO */ #define READ_RX_TAGS_LEN 2 +#define QUP_BUS_WIDTH 8 + static unsigned int scl_freq; module_param_named(scl_freq, scl_freq, uint, 0444); MODULE_PARM_DESC(scl_freq, "SCL frequency override"); @@ -227,6 +230,7 @@ struct qup_i2c_dev { int irq; struct clk *clk; struct clk *pclk; + struct icc_path *icc_path; struct i2c_adapter adap; int clk_ctl; @@ -255,6 +259,10 @@ struct qup_i2c_dev { /* To configure when bus is in run state */ u32 config_run; + /* bandwidth votes */ + u32 src_clk_freq; + u32 cur_bw_clk_freq; + /* dma parameters */ bool is_dma; /* To check if the current transfer is using DMA */ @@ -453,6 +461,23 @@ static int qup_i2c_bus_active(struct qup_i2c_dev *qup, int len) return ret; } +static int qup_i2c_vote_bw(struct qup_i2c_dev *qup, u32 clk_freq) +{ + u32 needed_peak_bw; + int ret; + + if (qup->cur_bw_clk_freq == clk_freq) + return 0; + + needed_peak_bw = Bps_to_icc(clk_freq * QUP_BUS_WIDTH); + ret = icc_set_bw(qup->icc_path, 0, needed_peak_bw); + if (ret) + return ret; + + qup->cur_bw_clk_freq = clk_freq; + return 0; +} + static void qup_i2c_write_tx_fifo_v1(struct qup_i2c_dev *qup) { struct qup_i2c_block *blk = &qup->blk; @@ -840,6 +865,10 @@ static int qup_i2c_bam_xfer(struct i2c_adapter *adap, struct i2c_msg *msg, int ret = 0; int idx = 0; + ret = qup_i2c_vote_bw(qup, qup->src_clk_freq); + if (ret) + return ret; + enable_irq(qup->irq); ret = qup_i2c_req_dma(qup); @@ -1645,6 +1674,7 @@ static void qup_i2c_disable_clocks(struct qup_i2c_dev *qup) config = readl(qup->base + QUP_CONFIG); config |= QUP_CLOCK_AUTO_GATE; writel(config, qup->base + QUP_CONFIG); + qup_i2c_vote_bw(qup, 0); clk_disable_unprepare(qup->pclk); } @@ -1745,6 +1775,11 @@ static int qup_i2c_probe(struct platform_device *pdev) goto fail_dma; } qup->is_dma = true; + + qup->icc_path = devm_of_icc_get(&pdev->dev, NULL); + if (IS_ERR(qup->icc_path)) + return dev_err_probe(&pdev->dev, PTR_ERR(qup->icc_path), + "failed to get interconnect path\n"); } nodma: @@ -1793,6 +1828,7 @@ static int qup_i2c_probe(struct platform_device *pdev) qup_i2c_enable_clocks(qup); src_clk_freq = clk_get_rate(qup->clk); } + qup->src_clk_freq = src_clk_freq; /* * Bootloaders might leave a pending interrupt on certain QUP's, -- 2.39.5