From ea95e92228ccc90b82b5b393b712735b9e2cba45 Mon Sep 17 00:00:00 2001
From: Dmitry Osipenko <dmitry.osipenko@collabora.com>
Date: Wed, 9 Apr 2025 15:34:08 +0300
Subject: [PATCH] WIP: mfd: rk8xx: Use atomic SPI transfer for power-off

Signed-off-by: Dmitry Osipenko <dmitry.osipenko@collabora.com>
---
 drivers/mfd/rk8xx-core.c |  2 +-
 drivers/mfd/rk8xx-spi.c  | 13 +++++++++++++
 2 files changed, 14 insertions(+), 1 deletion(-)

diff --git a/drivers/mfd/rk8xx-core.c b/drivers/mfd/rk8xx-core.c
index 71c2b80a4678d..8e0d32582e17f 100644
--- a/drivers/mfd/rk8xx-core.c
+++ b/drivers/mfd/rk8xx-core.c
@@ -634,7 +634,7 @@ static int rk808_power_off(struct sys_off_data *data)
 	default:
 		return NOTIFY_DONE;
 	}
-	ret = regmap_update_bits(rk808->regmap, reg, bit, bit);
+	ret = regmap_update_bits_atomic(rk808->regmap, reg, bit, bit);
 	if (ret)
 		dev_err(rk808->dev, "Failed to shutdown device!\n");
 
diff --git a/drivers/mfd/rk8xx-spi.c b/drivers/mfd/rk8xx-spi.c
index 3405fb82ff9fb..2812a5429e4c0 100644
--- a/drivers/mfd/rk8xx-spi.c
+++ b/drivers/mfd/rk8xx-spi.c
@@ -38,6 +38,12 @@ static const struct regmap_config rk806_regmap_config_spi = {
 	.volatile_table = &rk806_volatile_table,
 };
 
+static inline bool in_atomic_xfer_mode(void)
+{
+	return system_state > SYSTEM_RUNNING &&
+	       (IS_ENABLED(CONFIG_PREEMPT_COUNT) ? !preemptible() : irqs_disabled());
+}
+
 static int rk806_spi_bus_write(void *context, const void *vdata, size_t count)
 {
 	struct device *dev = context;
@@ -57,6 +63,9 @@ static int rk806_spi_bus_write(void *context, const void *vdata, size_t count)
 	xfer[1].tx_buf = vdata;
 	xfer[1].len = count;
 
+	if (in_atomic_xfer_mode())
+		return spi_sync_transfer_atomic(spi, xfer, ARRAY_SIZE(xfer));
+
 	return spi_sync_transfer(spi, xfer, ARRAY_SIZE(xfer));
 }
 
@@ -75,6 +84,10 @@ static int rk806_spi_bus_read(void *context, const void *vreg, size_t reg_size,
 	txbuf[0] = RK806_CMD_WITH_SIZE(READ, val_size);
 	memcpy(txbuf+1, vreg, reg_size);
 
+	if (in_atomic_xfer_mode())
+		return spi_write_then_read_atomic(spi, txbuf, sizeof(txbuf),
+						  val, val_size);
+
 	return spi_write_then_read(spi, txbuf, sizeof(txbuf), val, val_size);
 }
 
-- 
GitLab