[PATCH 4/7] soc: sunxi: sram: Allow SRAM to be claimed multiple times

Chen-Yu Tsai
2026-03-24T16:44:25Z

On the H616, the SRAM C region is an alias mapping to part of the VE
SRAM (accessible in whole at a different address) and part of the DE
SRAM (otherwise unaccessible). As such both the VE and DE need to claim
this SRAM region to prevent access from the CPU.

The SRAM claim API is designed so that a "claim" routes the SRAM to the
peripheral device, disabling access from the CPU. So long as the written
register value is the same for all the claimants involved, allowing
multiple or repeated claims is trivial. This is indeed the case for all
supported SRAM regions. The only known SRAM region to have multiple
different settings is the SRAM C2 region; this can be claimed by the AE,
CE, or ACE (assumed to be AE + CE). This region is not supported, and
likely will never be needed nor supported, as there is no documentation
for the peripherals involved.

Change the SRAM region "claimed" field from a boolean to a reference
count. A claim will increment the count, while a release decreases it.
The first claim will trigger the register value write. The driver
otherwise behaves as before.

Signed-off-by: Chen-Yu Tsai <wens@kernel.org>
---
drivers/soc/sunxi/sunxi_sram.c | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/drivers/soc/sunxi/sunxi_sram.c b/drivers/soc/sunxi/sunxi_sram.c
index 5e8c80ae3509..aba155379ccc 100644
--- a/drivers/soc/sunxi/sunxi_sram.c
+++ b/drivers/soc/sunxi/sunxi_sram.c
@@ -12,6 +12,7 @@

#include <linux/debugfs.h>
#include <linux/io.h>
+#include <linux/limits.h>
#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/of.h>
@@ -38,7 +39,7 @@ struct sunxi_sram_data {

struct sunxi_sram_desc {
struct sunxi_sram_data data;
- bool claimed;
+ u8 claim_cnt;
};

#define SUNXI_SRAM_MAP(_reg_val, _val, _func) \
@@ -244,9 +245,11 @@ int sunxi_sram_claim(struct device *dev)

spin_lock(&sram_lock);

- if (sram_desc->claimed) {
+ if (sram_desc->claim_cnt) {
+ if (!WARN_ON(sram_desc->claim_cnt == U8_MAX))
+ sram_desc->claim_cnt++;
spin_unlock(&sram_lock);
- return -EBUSY;
+ return 0;
}

mask = GENMASK(sram_data->offset + sram_data->width - 1,
@@ -256,7 +259,7 @@ int sunxi_sram_claim(struct device *dev)
writel(val | ((device << sram_data->offset) & mask),
base + sram_data->reg);

- sram_desc->claimed = true;
+ sram_desc->claim_cnt++;
spin_unlock(&sram_lock);

return 0;
@@ -278,7 +281,8 @@ void sunxi_sram_release(struct device *dev)
sram_desc = to_sram_desc(sram_data);

spin_lock(&sram_lock);
- sram_desc->claimed = false;
+ if (!WARN_ON(sram_desc->claim_cnt == 0))
+ sram_desc->claim_cnt--;
spin_unlock(&sram_lock);
}
EXPORT_SYMBOL(sunxi_sram_release);
--
2.47.3