From nobody Tue Feb 10 03:39:35 2026 Received: from smtpout-04.galae.net (smtpout-04.galae.net [185.171.202.116]) (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 6135C36D51C; Thu, 15 Jan 2026 09:25:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.171.202.116 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768469154; cv=none; b=UIs2oFaGr3X26p+GOq0/H9tgSGpINgU2JyAOP5utCHg7zZtJSe1eBl/h/R0kaYqccNg1cF1pAgMyvQ7jOcjcnY60e/fQngK1BFCImRjF7eonpMZ7NEUIrzHMmeIoOab/P5XtCrvlyG0z7K9W3t3GMWBv89CKX91JWdHOvdiRIKM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768469154; c=relaxed/simple; bh=YpDz/vG3DLbjkSP8w4hH9fZsadfIh0jV+dj16U2Mki4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=YaolgdmvdoFM8CaBGjFGOcecwK/S9sgMavNzgUk2hHIts9J45l6zMJMItMZQhjMINHqwgCX9dkMjwfe8Ic1lI3Hi6jjGB0YggmbV3iMO+V2LMoj27VzzUaFSIzwQ2lTF4c5tFPJbNs+NPXflAlJCnTZ+LHBqdqnug032aY/nPHo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=fyJTSoCa; arc=none smtp.client-ip=185.171.202.116 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="fyJTSoCa" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-04.galae.net (Postfix) with ESMTPS id 13313C1F1E5; Thu, 15 Jan 2026 09:25:24 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id BE9E3606B6; Thu, 15 Jan 2026 09:25:50 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id DFB4710B684F6; Thu, 15 Jan 2026 10:25:47 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1768469149; h=from:subject:date:message-id:to:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:references; bh=m2OlrB1WHxCAT8bt6bn0v6vCet93lc8eeCwRus+Rn4A=; b=fyJTSoCa/xmuWaNWYHiuD3d6R8B3Gs1Qxq+IlyvQMrpPe/xdcNHB6JzEB/KRSX36dPpiS1 NrwAyLACwTCRLosCoW19rlJCKhCQkf+SDi6nqN287hUa9pB6mUZZ6jPqcTNNGmatVvQMLK /Lu3udZQrB8htsitlc2CesheJbeaSYePx39BJ6ica7XXxrSK0A5CVpEwbcFkrD/DncRkk0 9HSa/d2yr5Zqzo73SnBE8rWU6sbjOQncCdpZtTTQskh+K3uz8om1FBk6plsX6+zSyzzSZF yIdJjfHOavoCba3oOGPE6QZNxVA08PZsH3VHl7HN0QrWZj6WAG0s9xkIuQ7GHQ== From: "Miquel Raynal (Schneider Electric)" Date: Thu, 15 Jan 2026 10:25:00 +0100 Subject: [PATCH v2 09/13] spi: cadence-qspi: Kill cqspi_jh7110_clk_init Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260115-schneider-6-19-rc1-qspi-v2-9-7e6a06e1e17b@bootlin.com> References: <20260115-schneider-6-19-rc1-qspi-v2-0-7e6a06e1e17b@bootlin.com> In-Reply-To: <20260115-schneider-6-19-rc1-qspi-v2-0-7e6a06e1e17b@bootlin.com> To: Mark Brown , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Geert Uytterhoeven , Magnus Damm , Vaishnav Achath Cc: Thomas Petazzoni , =?utf-8?q?Herv=C3=A9_Codina?= , Wolfram Sang , Vignesh Raghavendra , Santhosh Kumar K , Pratyush Yadav , Pascal Eberhard , linux-spi@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-renesas-soc@vger.kernel.org, "Miquel Raynal (Schneider Electric)" X-Mailer: b4 0.14.3 X-Last-TLS-Session-Version: TLSv1.3 This controller can be fed by either a main "ref" clock, or three clocks ("ref" again, "ahb", "apb"). In practice, it is likely that all controllers have the same inputs, but a single clock feeds the three interfaces (ref is used for controlling the external interface, ahb/apb the internal ones). Handling these clocks is in no way SoC specific, only the number of expected clocks may change. Plus, we will soon be adding another controller requiring an AHB and an APB clock as well, so it is time to align the whole clock handling. Furthermore, the use of the cqspi_jh7110_clk_init() helper, which specifically grabs and enables the "ahb" and "apb" clocks, is a bit convoluted: - only the JH7110 compatible provides the ->jh7110_clk_init() callback, - in the probe, if the above callback is set in the driver data, the driver does not call the callback (!) but instead calls the helper directly (?), - in the helper, the is_jh7110 boolean is set. This logic does not make sense. Instead: - in the probe, set the is_jh7110 boolean based on the compatible, - collect all available clocks with the "bulk" helper, - enable the extra clocks if they are available, - kill the SoC specific cqspi_jh7110_clk_init() helper. This also allows to group the clock handling instead of depending on the driver data pointer, which further simplifies the error path and the remove callback. Signed-off-by: Miquel Raynal (Schneider Electric) --- drivers/spi/spi-cadence-quadspi.c | 120 ++++++++++++----------------------= ---- 1 file changed, 37 insertions(+), 83 deletions(-) diff --git a/drivers/spi/spi-cadence-quadspi.c b/drivers/spi/spi-cadence-qu= adspi.c index af0ad24d8d39..e389422fe95e 100644 --- a/drivers/spi/spi-cadence-quadspi.c +++ b/drivers/spi/spi-cadence-quadspi.c @@ -55,7 +55,8 @@ static_assert(CQSPI_MAX_CHIPSELECT <=3D SPI_DEVICE_CS_CNT= _MAX); #define CQSPI_OP_WIDTH(part) ((part).nbytes ? ilog2((part).buswidth) : 0) =20 enum { - CLK_QSPI_APB =3D 0, + CLK_QSPI_REF =3D 0, + CLK_QSPI_APB, CLK_QSPI_AHB, CLK_QSPI_NUM, }; @@ -76,8 +77,7 @@ struct cqspi_flash_pdata { struct cqspi_st { struct platform_device *pdev; struct spi_controller *host; - struct clk *clk; - struct clk *clks[CLK_QSPI_NUM]; + struct clk_bulk_data clks[CLK_QSPI_NUM]; unsigned int sclk; =20 void __iomem *iobase; @@ -121,8 +121,6 @@ struct cqspi_driver_platdata { int (*indirect_read_dma)(struct cqspi_flash_pdata *f_pdata, u_char *rxbuf, loff_t from_addr, size_t n_rx); u32 (*get_dma_status)(struct cqspi_st *cqspi); - int (*jh7110_clk_init)(struct platform_device *pdev, - struct cqspi_st *cqspi); }; =20 /* Operation timeout value */ @@ -1763,61 +1761,20 @@ static int cqspi_setup_flash(struct cqspi_st *cqspi) return 0; } =20 -static int cqspi_jh7110_clk_init(struct platform_device *pdev, struct cqsp= i_st *cqspi) -{ - static struct clk_bulk_data qspiclk[] =3D { - { .id =3D "apb" }, - { .id =3D "ahb" }, - }; - - int ret =3D 0; - - ret =3D devm_clk_bulk_get(&pdev->dev, ARRAY_SIZE(qspiclk), qspiclk); - if (ret) { - dev_err(&pdev->dev, "%s: failed to get qspi clocks\n", __func__); - return ret; - } - - cqspi->clks[CLK_QSPI_APB] =3D qspiclk[0].clk; - cqspi->clks[CLK_QSPI_AHB] =3D qspiclk[1].clk; - - ret =3D clk_prepare_enable(cqspi->clks[CLK_QSPI_APB]); - if (ret) { - dev_err(&pdev->dev, "%s: failed to enable CLK_QSPI_APB\n", __func__); - return ret; - } - - ret =3D clk_prepare_enable(cqspi->clks[CLK_QSPI_AHB]); - if (ret) { - dev_err(&pdev->dev, "%s: failed to enable CLK_QSPI_AHB\n", __func__); - goto disable_apb_clk; - } - - cqspi->is_jh7110 =3D true; - - return 0; - -disable_apb_clk: - clk_disable_unprepare(cqspi->clks[CLK_QSPI_APB]); - - return ret; -} - -static void cqspi_jh7110_disable_clk(struct platform_device *pdev, struct = cqspi_st *cqspi) -{ - clk_disable_unprepare(cqspi->clks[CLK_QSPI_AHB]); - clk_disable_unprepare(cqspi->clks[CLK_QSPI_APB]); -} static int cqspi_probe(struct platform_device *pdev) { const struct cqspi_driver_platdata *ddata; struct reset_control *rstc, *rstc_ocp, *rstc_ref; + static const char *clk_ids[CLK_QSPI_NUM] =3D { + [CLK_QSPI_REF] =3D "ref", + [CLK_QSPI_APB] =3D "apb", + [CLK_QSPI_AHB] =3D "ahb", + }; struct device *dev =3D &pdev->dev; struct spi_controller *host; struct resource *res_ahb; struct cqspi_st *cqspi; - int ret; - int irq; + int ret, i, irq; =20 host =3D devm_spi_alloc_host(&pdev->dev, sizeof(*cqspi)); if (!host) @@ -1829,10 +1786,11 @@ static int cqspi_probe(struct platform_device *pdev) host->dev.of_node =3D pdev->dev.of_node; =20 cqspi =3D spi_controller_get_devdata(host); + if (of_device_is_compatible(pdev->dev.of_node, "starfive,jh7110-qspi")) + cqspi->is_jh7110 =3D true; =20 cqspi->pdev =3D pdev; cqspi->host =3D host; - cqspi->is_jh7110 =3D false; cqspi->ddata =3D ddata =3D of_device_get_match_data(dev); platform_set_drvdata(pdev, cqspi); =20 @@ -1849,12 +1807,17 @@ static int cqspi_probe(struct platform_device *pdev) return ret; } =20 - /* Obtain QSPI clock. */ - cqspi->clk =3D devm_clk_get(dev, NULL); - if (IS_ERR(cqspi->clk)) { - dev_err(dev, "Cannot claim QSPI clock.\n"); - ret =3D PTR_ERR(cqspi->clk); - return ret; + /* Obtain QSPI clocks. */ + for (i =3D 0; i < CLK_QSPI_NUM; ++i) + cqspi->clks[i].id =3D clk_ids[i]; + + ret =3D devm_clk_bulk_get_optional(dev, CLK_QSPI_NUM, cqspi->clks); + if (ret) + return dev_err_probe(dev, ret, "Failed to get clocks\n"); + + if (!cqspi->clks[CLK_QSPI_REF].clk) { + dev_err(dev, "Cannot claim mandatory QSPI ref clock.\n"); + return -ENODEV; } =20 /* Obtain and remap controller address. */ @@ -1886,10 +1849,9 @@ static int cqspi_probe(struct platform_device *pdev) if (ret) return ret; =20 - - ret =3D clk_prepare_enable(cqspi->clk); + ret =3D clk_bulk_prepare_enable(CLK_QSPI_NUM, cqspi->clks); if (ret) { - dev_err(dev, "Cannot enable QSPI clock.\n"); + dev_err(dev, "Cannot enable QSPI clocks.\n"); goto disable_rpm; } =20 @@ -1898,22 +1860,22 @@ static int cqspi_probe(struct platform_device *pdev) if (IS_ERR(rstc)) { ret =3D PTR_ERR(rstc); dev_err(dev, "Cannot get QSPI reset.\n"); - goto disable_clk; + goto disable_clks; } =20 rstc_ocp =3D devm_reset_control_get_optional_exclusive(dev, "qspi-ocp"); if (IS_ERR(rstc_ocp)) { ret =3D PTR_ERR(rstc_ocp); dev_err(dev, "Cannot get QSPI OCP reset.\n"); - goto disable_clk; + goto disable_clks; } =20 - if (of_device_is_compatible(pdev->dev.of_node, "starfive,jh7110-qspi")) { + if (cqspi->is_jh7110) { rstc_ref =3D devm_reset_control_get_optional_exclusive(dev, "rstc_ref"); if (IS_ERR(rstc_ref)) { ret =3D PTR_ERR(rstc_ref); dev_err(dev, "Cannot get QSPI REF reset.\n"); - goto disable_clk; + goto disable_clks; } reset_control_assert(rstc_ref); reset_control_deassert(rstc_ref); @@ -1925,7 +1887,7 @@ static int cqspi_probe(struct platform_device *pdev) reset_control_assert(rstc_ocp); reset_control_deassert(rstc_ocp); =20 - cqspi->master_ref_clk_hz =3D clk_get_rate(cqspi->clk); + cqspi->master_ref_clk_hz =3D clk_get_rate(cqspi->clks[CLK_QSPI_REF].clk); host->max_speed_hz =3D cqspi->master_ref_clk_hz; =20 /* write completion is supported by default */ @@ -1951,12 +1913,6 @@ static int cqspi_probe(struct platform_device *pdev) cqspi->slow_sram =3D true; if (ddata->quirks & CQSPI_NEEDS_APB_AHB_HAZARD_WAR) cqspi->apb_ahb_hazard =3D true; - - if (ddata->jh7110_clk_init) { - ret =3D cqspi_jh7110_clk_init(pdev, cqspi); - if (ret) - goto disable_clk; - } if (ddata->quirks & CQSPI_DISABLE_STIG_MODE) cqspi->disable_stig_mode =3D true; =20 @@ -2022,11 +1978,8 @@ static int cqspi_probe(struct platform_device *pdev) disable_controller: cqspi_controller_enable(cqspi, 0); disable_clks: - if (cqspi->is_jh7110) - cqspi_jh7110_disable_clk(pdev, cqspi); -disable_clk: if (pm_runtime_get_sync(&pdev->dev) >=3D 0) - clk_disable_unprepare(cqspi->clk); + clk_bulk_disable_unprepare(CLK_QSPI_NUM, cqspi->clks); disable_rpm: if (!(ddata && (ddata->quirks & CQSPI_DISABLE_RUNTIME_PM))) pm_runtime_disable(dev); @@ -2055,14 +2008,12 @@ static void cqspi_remove(struct platform_device *pd= ev) =20 cqspi_controller_enable(cqspi, 0); =20 - if (cqspi->is_jh7110) - cqspi_jh7110_disable_clk(pdev, cqspi); =20 if (!(ddata && (ddata->quirks & CQSPI_DISABLE_RUNTIME_PM))) ret =3D pm_runtime_get_sync(&pdev->dev); =20 if (ret >=3D 0) - clk_disable(cqspi->clk); + clk_bulk_disable_unprepare(CLK_QSPI_NUM, cqspi->clks); =20 if (!(ddata && (ddata->quirks & CQSPI_DISABLE_RUNTIME_PM))) { pm_runtime_put_sync(&pdev->dev); @@ -2075,15 +2026,19 @@ static int cqspi_runtime_suspend(struct device *dev) struct cqspi_st *cqspi =3D dev_get_drvdata(dev); =20 cqspi_controller_enable(cqspi, 0); - clk_disable_unprepare(cqspi->clk); + clk_bulk_disable_unprepare(CLK_QSPI_NUM, cqspi->clks); return 0; } =20 static int cqspi_runtime_resume(struct device *dev) { struct cqspi_st *cqspi =3D dev_get_drvdata(dev); + int ret; + + ret =3D clk_bulk_prepare_enable(CLK_QSPI_NUM, cqspi->clks); + if (ret) + return ret; =20 - clk_prepare_enable(cqspi->clk); cqspi_wait_idle(cqspi); cqspi_controller_enable(cqspi, 0); cqspi_controller_init(cqspi); @@ -2166,7 +2121,6 @@ static const struct cqspi_driver_platdata versal2_osp= i =3D { =20 static const struct cqspi_driver_platdata jh7110_qspi =3D { .quirks =3D CQSPI_DISABLE_DAC_MODE, - .jh7110_clk_init =3D cqspi_jh7110_clk_init, }; =20 static const struct cqspi_driver_platdata pensando_cdns_qspi =3D { --=20 2.51.1