From: Shih-Yuan Lee <fourdollars@debian.org>
To: Mark Brown <broonie@kernel.org>
Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>,
Mika Westerberg <mika.westerberg@linux.intel.com>,
Lukas Wunner <lukas@wunner.de>, Daniel Mack <daniel@zonque.org>,
Haojian Zhuang <haojian.zhuang@gmail.com>,
Robert Jarzmik <robert.jarzmik@free.fr>,
linux-spi@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-arm-kernel@lists.infradead.org,
Shih-Yuan Lee <fourdollars@debian.org>
Subject: [PATCH v17 2/6] spi: pxa2xx: introduce clock enable and disable helper functions
Date: Thu, 1 Oct 2026 00:06:25 +0800 [thread overview]
Message-ID: <20260930160629.1822-3-fourdollars@debian.org> (raw)
In-Reply-To: <20260930160629.1822-1-fourdollars@debian.org>
The driver enables and disables the SOC clock during probe, teardown,
and power management callbacks. Directly calling clk_disable_unprepare()
when the clock is already disabled—such as when removing a device that
is runtime-suspended—causes an unbalanced clock disable warning from the
Common Clock Framework.
Introduce pxa2xx_spi_clk_enable() and pxa2xx_spi_clk_disable() helper
functions that track the clock state with a 'clk_enabled' boolean flag
protected by a 'clk_lock' mutex in struct driver_data. These helpers
make clock toggling idempotent: repeated enable or disable invocations
are safe no-ops serialized by clk_lock.
Convert probe, remove, suspend, resume, and runtime PM callbacks to use
these helpers instead of direct clk_prepare_enable() and
clk_disable_unprepare() calls.
Pack 'clk_enabled' immediately after 'n_bytes' into the existing
padding hole in struct driver_data, avoiding additional alignment
padding.
Assisted-by: Antigravity:gemini-3.8-flash sparse
Signed-off-by: Shih-Yuan Lee <fourdollars@debian.org>
---
drivers/spi/spi-pxa2xx.c | 41 ++++++++++++++++++++++++++++++++--------
drivers/spi/spi-pxa2xx.h | 2 ++
2 files changed, 35 insertions(+), 8 deletions(-)
diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c
index b11e30589074..a9d19d9a5343 100644
--- a/drivers/spi/spi-pxa2xx.c
+++ b/drivers/spi/spi-pxa2xx.c
@@ -713,6 +713,31 @@ static void handle_bad_msg(struct driver_data *drv_data)
dev_err(drv_data->ssp->dev, "bad message state in interrupt handler\n");
}
+static int pxa2xx_spi_clk_enable(struct driver_data *drv_data)
+{
+ int ret = 0;
+
+ mutex_lock(&drv_data->clk_lock);
+ if (!drv_data->clk_enabled) {
+ ret = clk_prepare_enable(drv_data->ssp->clk);
+ if (!ret)
+ drv_data->clk_enabled = true;
+ }
+ mutex_unlock(&drv_data->clk_lock);
+
+ return ret;
+}
+
+static void pxa2xx_spi_clk_disable(struct driver_data *drv_data)
+{
+ mutex_lock(&drv_data->clk_lock);
+ if (drv_data->clk_enabled) {
+ drv_data->clk_enabled = false;
+ clk_disable_unprepare(drv_data->ssp->clk);
+ }
+ mutex_unlock(&drv_data->clk_lock);
+}
+
static irqreturn_t ssp_int(int irq, void *dev_id)
{
struct driver_data *drv_data = dev_id;
@@ -1288,6 +1313,7 @@ int pxa2xx_spi_probe(struct device *dev, struct ssp_device *ssp,
drv_data->controller = controller;
drv_data->controller_info = platform_info;
drv_data->ssp = ssp;
+ mutex_init(&drv_data->clk_lock);
/* The spi->mode bits understood by this driver: */
controller->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LOOP;
@@ -1352,7 +1378,7 @@ int pxa2xx_spi_probe(struct device *dev, struct ssp_device *ssp,
}
/* Enable SOC clock */
- ret = clk_prepare_enable(ssp->clk);
+ ret = pxa2xx_spi_clk_enable(drv_data);
if (ret)
goto out_error_dma_irq_alloc;
@@ -1449,7 +1475,7 @@ int pxa2xx_spi_probe(struct device *dev, struct ssp_device *ssp,
return ret;
out_error_clock_enabled:
- clk_disable_unprepare(ssp->clk);
+ pxa2xx_spi_clk_disable(drv_data);
out_error_dma_irq_alloc:
pxa2xx_spi_dma_release(drv_data);
@@ -1468,7 +1494,7 @@ void pxa2xx_spi_remove(struct device *dev)
/* Disable the SSP at the peripheral and SOC level */
pxa_ssp_disable(ssp);
- clk_disable_unprepare(ssp->clk);
+ pxa2xx_spi_clk_disable(drv_data);
/* Release DMA */
if (drv_data->controller_info->enable_dma)
@@ -1492,7 +1518,7 @@ static int pxa2xx_spi_suspend(struct device *dev)
pxa_ssp_disable(ssp);
if (!pm_runtime_suspended(dev))
- clk_disable_unprepare(ssp->clk);
+ pxa2xx_spi_clk_disable(drv_data);
return 0;
}
@@ -1500,12 +1526,11 @@ static int pxa2xx_spi_suspend(struct device *dev)
static int pxa2xx_spi_resume(struct device *dev)
{
struct driver_data *drv_data = dev_get_drvdata(dev);
- struct ssp_device *ssp = drv_data->ssp;
int ret;
/* Enable the SSP clock */
if (!pm_runtime_suspended(dev)) {
- ret = clk_prepare_enable(ssp->clk);
+ ret = pxa2xx_spi_clk_enable(drv_data);
if (ret)
return ret;
}
@@ -1518,7 +1543,7 @@ static int pxa2xx_spi_runtime_suspend(struct device *dev)
{
struct driver_data *drv_data = dev_get_drvdata(dev);
- clk_disable_unprepare(drv_data->ssp->clk);
+ pxa2xx_spi_clk_disable(drv_data);
return 0;
}
@@ -1526,7 +1551,7 @@ static int pxa2xx_spi_runtime_resume(struct device *dev)
{
struct driver_data *drv_data = dev_get_drvdata(dev);
- return clk_prepare_enable(drv_data->ssp->clk);
+ return pxa2xx_spi_clk_enable(drv_data);
}
EXPORT_NS_GPL_DEV_PM_OPS(pxa2xx_spi_pm_ops, SPI_PXA2xx) = {
diff --git a/drivers/spi/spi-pxa2xx.h b/drivers/spi/spi-pxa2xx.h
index 447be0369384..3352239f74a0 100644
--- a/drivers/spi/spi-pxa2xx.h
+++ b/drivers/spi/spi-pxa2xx.h
@@ -66,6 +66,8 @@ struct driver_data {
void *rx;
void *rx_end;
u8 n_bytes;
+ bool clk_enabled;
+ struct mutex clk_lock;
int (*write)(struct driver_data *drv_data);
int (*read)(struct driver_data *drv_data);
irqreturn_t (*transfer_handler)(struct driver_data *drv_data);
--
2.39.5
next prev parent reply other threads:[~2026-09-30 16:07 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-30 16:06 [PATCH v17 0/6] spi: pxa2xx: PM fixes, teardown overhaul, and LPSS restore for MacBook8,1 Shih-Yuan Lee
2026-09-30 16:06 ` [PATCH v17 1/6] spi: pxa2xx: rename local status variable to ret Shih-Yuan Lee
2026-10-01 7:10 ` Andy Shevchenko
2026-09-30 16:06 ` Shih-Yuan Lee [this message]
2026-09-30 17:31 ` [PATCH v17 2/6] spi: pxa2xx: introduce clock enable and disable helper functions Mark Brown
2026-10-01 7:13 ` Andy Shevchenko
2026-09-30 16:06 ` [PATCH v17 3/6] spi: pxa2xx: acquire active PM runtime reference in interrupt handler Shih-Yuan Lee
2026-09-30 17:40 ` Mark Brown
2026-09-30 16:06 ` [PATCH v17 4/6] spi: pxa2xx: overhaul teardown and suspend sequence to synchronize IRQ before clock gating Shih-Yuan Lee
2026-09-30 16:06 ` [PATCH v17 5/6] spi: pxa2xx-pci: restore LPSS private register state across S3 resume Shih-Yuan Lee
2026-10-01 4:13 ` Mika Westerberg
2026-10-01 7:20 ` Andy Shevchenko
2026-09-30 16:06 ` [PATCH v17 6/6] spi: pxa2xx-pci: disable DMA and runtime autosuspend for Apple MacBook8,1 Shih-Yuan Lee
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260930160629.1822-3-fourdollars@debian.org \
--to=fourdollars@debian.org \
--cc=andriy.shevchenko@linux.intel.com \
--cc=broonie@kernel.org \
--cc=daniel@zonque.org \
--cc=haojian.zhuang@gmail.com \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-spi@vger.kernel.org \
--cc=lukas@wunner.de \
--cc=mika.westerberg@linux.intel.com \
--cc=robert.jarzmik@free.fr \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.