[PATCH v3 2/6] misc: sram: add ability to mark sram sections as reserved
From: Rob Herring <hidden>
Date: 2013-07-07 19:46:40
Also in:
linux-devicetree, lkml
On Fri, Jul 5, 2013 at 7:41 AM, Heiko St?bner [off-list ref] wrote:
Some SoCs need parts of their sram for special purposes. So while being part of the periphal, it should not be part of the genpool controlling the sram.
s/periphal/peripheral/
Threfore add an option mmio-sram-reserved to keep arbitary portions of the
s/Threfore/Therefore/ s/arbitary/arbitrary/
quoted hunk ↗ jump to hunk
sram from being part of the pool. Suggested-by: Rob Herring <redacted> Signed-off-by: Heiko Stuebner <heiko@sntech.de> Tested-by: Ulrich Prinz <redacted> --- Documentation/devicetree/bindings/misc/sram.txt | 8 +++ drivers/misc/sram.c | 80 +++++++++++++++++++++-- 2 files changed, 82 insertions(+), 6 deletions(-)diff --git a/Documentation/devicetree/bindings/misc/sram.txt b/Documentation/devicetree/bindings/misc/sram.txt index 4d0a00e..eae080e 100644 --- a/Documentation/devicetree/bindings/misc/sram.txt +++ b/Documentation/devicetree/bindings/misc/sram.txt@@ -8,9 +8,17 @@ Required properties: - reg : SRAM iomem address range +Optional properties: + +- mmio-sram-reserved: ordered list of reserved chunks inside the sram that + should not become part of the genalloc pool.
genalloc is linux specific. "should not be used by the OS" would be better.
quoted hunk ↗ jump to hunk
+ Format is <base size>, <base size>, ...; with base being relative to the + reg property base. + Example: sram: sram at 5c000000 { compatible = "mmio-sram"; reg = <0x5c000000 0x40000>; /* 256 KiB SRAM at address 0x5c000000 */ + mmio-sram-reserved = <0x0 0x100>; /* reserve 0x5c000000-0x5c000100 */ };diff --git a/drivers/misc/sram.c b/drivers/misc/sram.c index afe66571..9131e4a 100644 --- a/drivers/misc/sram.c +++ b/drivers/misc/sram.c@@ -42,6 +42,13 @@ static int sram_probe(struct platform_device *pdev) struct sram_dev *sram; struct resource *res; unsigned long size; + const __be32 *reserved_list = NULL; + int reserved_size = 0; + unsigned int cur_start = 0; + unsigned int cur_size; + unsigned int rstart; + unsigned int rsize;
Use one line for each type.
quoted hunk ↗ jump to hunk
+ int i; int ret; res = platform_get_resource(pdev, IORESOURCE_MEM, 0);@@ -65,12 +72,73 @@ static int sram_probe(struct platform_device *pdev) if (!sram->pool) return -ENOMEM; - ret = gen_pool_add_virt(sram->pool, (unsigned long)virt_base, - res->start, size, -1); - if (ret < 0) { - if (sram->clk) - clk_disable_unprepare(sram->clk); - return ret; + if (pdev->dev.of_node) { + reserved_list = of_get_property(pdev->dev.of_node, + "mmio-sram-reserved", + &reserved_size); + if (reserved_list) { + reserved_size /= sizeof(*reserved_list); + if (!reserved_size || reserved_size % 2) { + dev_warn(&pdev->dev, "wrong number of arguments in mmio-sram-reserved\n"); + reserved_list = NULL; + } + } + } + + if (!reserved_list) + reserved_size = 0;
This can be moved to where you set reserved_list to NULL.
+
+ for (i = 0; i < (reserved_size + 2); i += 2) {
+ if (i < reserved_size) {This loop is hard to follow. For example, it is not immediate obvious why you loop an extra time. I think it would be more straight forward to determine the free regions first and then do the allocations. This will require a kmalloc or fixed max number of regions, but would improve readability. Rob
+ /* get the next reserved block */
+ rstart = be32_to_cpu(*reserved_list++);
+ rsize = be32_to_cpu(*reserved_list++);
+
+ /* catch unsorted list entries */
+ if (rstart < cur_start) {
+ dev_err(&pdev->dev,
+ "unsorted reserved list (0x%x before current 0x%x)\n",
+ rstart, cur_start);
+ if (sram->clk)
+ clk_disable_unprepare(sram->clk);
+ return -EINVAL;
+ }
+
+ dev_dbg(&pdev->dev,
+ "found reserved block 0x%x-0x%x\n",
+ rstart, rstart + rsize);
+ } else {
+ /* the last chunk extends to the end of the region */
+ rstart = size;
+ rsize = 0;
+ }
+
+ /* current start is in a reserved block */
+ if (rstart <= cur_start) {
+ cur_start = rstart + rsize;
+ continue;
+ }
+
+ /*
+ * allocate the space between the current starting
+ * address and the following reserved block, or the
+ * end of the region.
+ */
+ cur_size = rstart - cur_start;
+
+ dev_dbg(&pdev->dev, "adding chunk 0x%x-0x%x\n",
+ cur_start, cur_start + cur_size);
+ ret = gen_pool_add_virt(sram->pool,
+ (unsigned long)virt_base + cur_start,
+ res->start + cur_start, cur_size, -1);
+ if (ret < 0) {
+ if (sram->clk)
+ clk_disable_unprepare(sram->clk);
+ return ret;
+ }
+
+ /* next allocation after this reserved block */
+ cur_start = rstart + rsize;
}
platform_set_drvdata(pdev, sram);
--
1.7.10.4