[PATCH 1/4] misc: sram: add support for remapping reserved regions only

From: Mian Yousaf Kaukab
Date: Tue May 12 2020 - 10:48:44 EST


Some SRAM kernel users may be interested in SRAMâs reserved regions
only, though a bigger SRAM is available on the platform. Add an
optional flag 'reserved-only' which allows to ioremap reserved regions
only. Rest of SRAM is not remapped. ioremap type is selected depending
upon no-memory-wc as usual.

Signed-off-by: Mian Yousaf Kaukab <ykaukab@xxxxxxx>
---
*Tested only on Jetson TX2. Jetson AGX Xavier is untested.*

drivers/misc/sram.c | 73 ++++++++++++++++++++++++++++++++++-----------
drivers/misc/sram.h | 3 ++
2 files changed, 58 insertions(+), 18 deletions(-)

diff --git a/drivers/misc/sram.c b/drivers/misc/sram.c
index 6c1a23cb3e8c..44e459f39e22 100644
--- a/drivers/misc/sram.c
+++ b/drivers/misc/sram.c
@@ -97,7 +97,7 @@ static int sram_add_partition(struct sram_dev *sram, struct sram_reserve *block,
struct sram_partition *part = &sram->partition[sram->partitions];

mutex_init(&part->lock);
- part->base = sram->virt_base + block->start;
+ part->base = block->virt_start;

if (block->pool) {
ret = sram_add_pool(sram, block, start, part);
@@ -153,6 +153,25 @@ static int sram_reserve_cmp(void *priv, struct list_head *a,
return ra->start - rb->start;
}

+static int sram_remap_resource(struct sram_dev *sram,
+ struct resource *res, void __iomem **virt)
+{
+ void __iomem *addr;
+
+ if (sram->no_memory_wc)
+ addr = devm_ioremap_resource(sram->dev, res);
+ else
+ addr = devm_ioremap_resource_wc(sram->dev, res);
+
+ if (IS_ERR(addr)) {
+ dev_err(sram->dev, "could not map SRAM region\n");
+ return PTR_ERR(addr);
+ }
+
+ *virt = addr;
+ return 0;
+}
+
static int sram_reserve_regions(struct sram_dev *sram, struct resource *res)
{
struct device_node *np = sram->dev->of_node, *child;
@@ -239,6 +258,16 @@ static int sram_reserve_regions(struct sram_dev *sram, struct resource *res)
block->start, block->start + block->size);
}

+ /* ioremap reserved block as whole sram is not remapped */
+ if (sram->reserved_only) {
+ ret = sram_remap_resource(sram, &child_res,
+ &block->virt_start);
+ if (ret)
+ goto err_chunks;
+ } else {
+ block->virt_start = sram->virt_base + block->start;
+ }
+
block++;
}
child = NULL;
@@ -282,8 +311,11 @@ static int sram_reserve_regions(struct sram_dev *sram, struct resource *res)
}
}

- /* current start is in a reserved block, so continue after it */
- if (block->start == cur_start) {
+ /*
+ * Current start is in a reserved block, so continue after it.
+ * Or if only using reserved blocks
+ */
+ if (block->start == cur_start || sram->reserved_only) {
cur_start = block->start + block->size;
continue;
}
@@ -342,6 +374,7 @@ static int sram_probe(struct platform_device *pdev)
struct sram_dev *sram;
int ret;
int (*init_func)(void);
+ struct resource *res;

sram = devm_kzalloc(&pdev->dev, sizeof(*sram), GFP_KERNEL);
if (!sram)
@@ -349,19 +382,22 @@ static int sram_probe(struct platform_device *pdev)

sram->dev = &pdev->dev;

- if (of_property_read_bool(pdev->dev.of_node, "no-memory-wc"))
- sram->virt_base = devm_platform_ioremap_resource(pdev, 0);
- else
- sram->virt_base = devm_platform_ioremap_resource_wc(pdev, 0);
- if (IS_ERR(sram->virt_base)) {
- dev_err(&pdev->dev, "could not map SRAM registers\n");
- return PTR_ERR(sram->virt_base);
- }
+ sram->no_memory_wc =
+ of_property_read_bool(pdev->dev.of_node, "no-memory-wc");
+ sram->reserved_only =
+ of_property_read_bool(pdev->dev.of_node, "reserved-only");

- sram->pool = devm_gen_pool_create(sram->dev, ilog2(SRAM_GRANULARITY),
- NUMA_NO_NODE, NULL);
- if (IS_ERR(sram->pool))
- return PTR_ERR(sram->pool);
+ if (!sram->reserved_only) {
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ ret = sram_remap_resource(sram, res, &sram->virt_base);
+ if (ret)
+ return ret;
+
+ sram->pool = devm_gen_pool_create(sram->dev,
+ ilog2(SRAM_GRANULARITY), NUMA_NO_NODE, NULL);
+ if (IS_ERR(sram->pool))
+ return PTR_ERR(sram->pool);
+ }

sram->clk = devm_clk_get(sram->dev, NULL);
if (IS_ERR(sram->clk))
@@ -383,8 +419,9 @@ static int sram_probe(struct platform_device *pdev)
goto err_free_partitions;
}

- dev_dbg(sram->dev, "SRAM pool: %zu KiB @ 0x%p\n",
- gen_pool_size(sram->pool) / 1024, sram->virt_base);
+ if (sram->pool)
+ dev_dbg(sram->dev, "SRAM pool: %zu KiB @ 0x%p\n",
+ gen_pool_size(sram->pool) / 1024, sram->virt_base);

return 0;

@@ -403,7 +440,7 @@ static int sram_remove(struct platform_device *pdev)

sram_free_partitions(sram);

- if (gen_pool_avail(sram->pool) < gen_pool_size(sram->pool))
+ if (sram->pool && gen_pool_avail(sram->pool) < gen_pool_size(sram->pool))
dev_err(sram->dev, "removed while SRAM allocated\n");

if (sram->clk)
diff --git a/drivers/misc/sram.h b/drivers/misc/sram.h
index 9c1d21ff7347..a485fa29458b 100644
--- a/drivers/misc/sram.h
+++ b/drivers/misc/sram.h
@@ -23,6 +23,8 @@ struct sram_dev {

struct sram_partition *partition;
u32 partitions;
+ bool no_memory_wc;
+ bool reserved_only;
};

struct sram_reserve {
@@ -33,6 +35,7 @@ struct sram_reserve {
bool pool;
bool protect_exec;
const char *label;
+ void __iomem *virt_start;
};

#ifdef CONFIG_SRAM_EXEC
--
2.25.0