summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2011-12-05 17:54:37 +0100
committerSascha Hauer <s.hauer@pengutronix.de>2011-12-05 17:54:37 +0100
commit6cd0c4a3584c1a12094a1b56129dbc509621e36e (patch)
tree692050bea0f9f7f8cdd02ec33dc662e1d4b26bb3
parent6cfdba4760bbd64498ba10e776ba551dea83b829 (diff)
parent18e845efd935c2a4bf79c2ed2fbd9766c18af3f9 (diff)
downloadbarebox-6cd0c4a3584c1a12094a1b56129dbc509621e36e.tar.gz
barebox-6cd0c4a3584c1a12094a1b56129dbc509621e36e.tar.xz
Merge branch 'pu/resources' into next
-rw-r--r--arch/arm/lib/arm.c2
-rw-r--r--arch/blackfin/lib/board.c2
-rw-r--r--arch/mips/lib/memory.c2
-rw-r--r--arch/nios2/lib/board.c2
-rw-r--r--arch/ppc/lib/board.c2
-rw-r--r--arch/sandbox/os/common.c2
-rw-r--r--arch/x86/lib/memory.c4
-rw-r--r--commands/Kconfig7
-rw-r--r--commands/Makefile1
-rw-r--r--commands/iomem.c56
-rw-r--r--common/Makefile1
-rw-r--r--common/memory.c58
-rw-r--r--common/resource.c121
-rw-r--r--drivers/base/driver.c29
-rw-r--r--include/driver.h6
-rw-r--r--include/linux/ioport.h14
-rw-r--r--include/memory.h5
17 files changed, 299 insertions, 15 deletions
diff --git a/arch/arm/lib/arm.c b/arch/arm/lib/arm.c
index c85aae14a0..80b62e988d 100644
--- a/arch/arm/lib/arm.c
+++ b/arch/arm/lib/arm.c
@@ -7,7 +7,7 @@
static int arm_mem_malloc_init(void)
{
mem_malloc_init((void *)MALLOC_BASE,
- (void *)(MALLOC_BASE + MALLOC_SIZE));
+ (void *)(MALLOC_BASE + MALLOC_SIZE - 1));
return 0;
}
diff --git a/arch/blackfin/lib/board.c b/arch/blackfin/lib/board.c
index d1b39fa347..bf5c1b64a5 100644
--- a/arch/blackfin/lib/board.c
+++ b/arch/blackfin/lib/board.c
@@ -38,7 +38,7 @@
int blackfin_mem_malloc_init(void)
{
mem_malloc_init((void *)(MALLOC_BASE),
- (void *)(MALLOC_BASE + MALLOC_SIZE));
+ (void *)(MALLOC_BASE + MALLOC_SIZE - 1));
return 0;
}
diff --git a/arch/mips/lib/memory.c b/arch/mips/lib/memory.c
index ad9f6a6a40..8d2d51b72b 100644
--- a/arch/mips/lib/memory.c
+++ b/arch/mips/lib/memory.c
@@ -26,7 +26,7 @@
static int mips_mem_malloc_init(void)
{
mem_malloc_init((void *)MALLOC_BASE,
- (void *)(MALLOC_BASE + MALLOC_SIZE));
+ (void *)(MALLOC_BASE + MALLOC_SIZE - 1));
return 0;
}
core_initcall(mips_mem_malloc_init);
diff --git a/arch/nios2/lib/board.c b/arch/nios2/lib/board.c
index d50f05adee..ed3af49a86 100644
--- a/arch/nios2/lib/board.c
+++ b/arch/nios2/lib/board.c
@@ -31,7 +31,7 @@ int altera_mem_malloc_init(void)
{
mem_malloc_init((void *)(NIOS_SOPC_TEXT_BASE - MALLOC_SIZE),
- (void *)(NIOS_SOPC_TEXT_BASE));
+ (void *)(NIOS_SOPC_TEXT_BASE - 1));
return 0;
}
diff --git a/arch/ppc/lib/board.c b/arch/ppc/lib/board.c
index 0b610a5c95..0e839eb053 100644
--- a/arch/ppc/lib/board.c
+++ b/arch/ppc/lib/board.c
@@ -56,7 +56,7 @@ void board_init_r (ulong end_of_ram)
debug("malloc_end: 0x%08x\n", malloc_end);
debug("TEXT_BASE after relocation: 0x%08x\n", _text_base);
- mem_malloc_init((void *)(malloc_end - MALLOC_SIZE), (void *)malloc_end);
+ mem_malloc_init((void *)(malloc_end - MALLOC_SIZE), (void *)(malloc_end - 1));
/*
* Setup trap handlers
diff --git a/arch/sandbox/os/common.c b/arch/sandbox/os/common.c
index 1c5ae5d34b..9258c66156 100644
--- a/arch/sandbox/os/common.c
+++ b/arch/sandbox/os/common.c
@@ -262,7 +262,7 @@ int main(int argc, char *argv[])
printf("unable to get malloc space\n");
exit(1);
}
- mem_malloc_init(ram, ram + malloc_size);
+ mem_malloc_init(ram, ram + malloc_size - 1);
while (1) {
int option_index = 0;
diff --git a/arch/x86/lib/memory.c b/arch/x86/lib/memory.c
index fa7bc03962..1774ef34fd 100644
--- a/arch/x86/lib/memory.c
+++ b/arch/x86/lib/memory.c
@@ -54,12 +54,12 @@ static int x86_mem_malloc_init(void)
*/
if (memory_size >= (15 * 1024 * 1024 + MALLOC_SIZE))
mem_malloc_init((void*)(16 * 1024 * 1024),
- (void*)(16 * 1024 * 1024) + MALLOC_SIZE);
+ (void*)(16 * 1024 * 1024 + MALLOC_SIZE - 1));
else
return -1;
#else
mem_malloc_init((void *)MALLOC_BASE,
- (void *)(MALLOC_BASE + MALLOC_SIZE));
+ (void *)(MALLOC_BASE + MALLOC_SIZE - 1));
#endif
return 0;
}
diff --git a/commands/Kconfig b/commands/Kconfig
index c2492fa6c9..2badea3b7b 100644
--- a/commands/Kconfig
+++ b/commands/Kconfig
@@ -215,6 +215,13 @@ config CMD_MEMINFO
tristate
prompt "meminfo"
+config CMD_IOMEM
+ tristate
+ prompt "iomem"
+ help
+ Show information about iomem usage. Pendant to 'cat /proc/iomem'
+ under Linux.
+
config CMD_MEMORY
bool
default y
diff --git a/commands/Makefile b/commands/Makefile
index f82dcfa8dd..e95fdc375d 100644
--- a/commands/Makefile
+++ b/commands/Makefile
@@ -60,3 +60,4 @@ obj-$(CONFIG_CMD_USB) += usb.o
obj-$(CONFIG_CMD_TIME) += time.o
obj-$(CONFIG_CMD_OFTREE) += oftree.o
obj-$(CONFIG_CMD_MAGICVAR) += magicvar.o
+obj-$(CONFIG_CMD_IOMEM) += iomem.o
diff --git a/commands/iomem.c b/commands/iomem.c
new file mode 100644
index 0000000000..78566c1f5b
--- /dev/null
+++ b/commands/iomem.c
@@ -0,0 +1,56 @@
+/*
+ * iomem.c - barebox iomem command
+ *
+ * Copyright (c) 2011 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation.
+ */
+#include <common.h>
+#include <command.h>
+
+static void __print_resources(struct resource *res, int indent)
+{
+ struct resource *r;
+ int i;
+
+ for (i = 0; i < indent; i++)
+ printf(" ");
+
+ printf("0x%08x - 0x%08x (size 0x%08x) %s\n", res->start,
+ res->start + res->size - 1,
+ res->size, res->name);
+
+ list_for_each_entry(r, &res->children, sibling)
+ __print_resources(r, indent + 1);
+}
+
+static void print_resources(struct resource *res)
+{
+ __print_resources(res, 0);
+}
+
+static int do_iomem(struct command *cmdtp, int argc, char *argv[])
+{
+ print_resources(&iomem_resource);
+
+ return 0;
+}
+
+BAREBOX_CMD_START(iomem)
+ .cmd = do_iomem,
+ .usage = "show iomem usage",
+BAREBOX_CMD_END
diff --git a/common/Makefile b/common/Makefile
index 55d9dbcb43..9bce47943c 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -27,6 +27,7 @@ obj-y += startup.o
obj-y += misc.o
obj-y += memsize.o
obj-y += filetype.o
+obj-y += resource.o
obj-$(CONFIG_MENU) += menu.o
obj-$(CONFIG_PASSWORD) += password.o
obj-$(CONFIG_MODULES) += module.o
diff --git a/common/memory.c b/common/memory.c
index 0ba9a18e88..7d0f4cab2a 100644
--- a/common/memory.c
+++ b/common/memory.c
@@ -25,6 +25,9 @@
#include <of.h>
#include <init.h>
#include <libfdt.h>
+#include <linux/ioport.h>
+#include <asm-generic/memory_layout.h>
+#include <asm/sections.h>
/*
* Begin and End of memory area for malloc(), and current "brk"
@@ -50,6 +53,33 @@ void mem_malloc_init(void *start, void *end)
malloc_brk = malloc_start;
}
+static int mem_malloc_resource(void)
+{
+ /*
+ * Normally it's a bug when one of these fails,
+ * but we have some setups where some of these
+ * regions are outside of sdram in which case
+ * the following fails.
+ */
+ request_sdram_region("malloc space",
+ malloc_start,
+ malloc_end - malloc_start + 1);
+ request_sdram_region("barebox",
+ (unsigned long)&_stext,
+ (unsigned long)&_etext -
+ (unsigned long)&_stext + 1);
+ request_sdram_region("bss",
+ (unsigned long)&__bss_start,
+ (unsigned long)&__bss_stop -
+ (unsigned long)&__bss_start + 1);
+#ifdef STACK_BASE
+ request_sdram_region("stack", STACK_BASE, STACK_SIZE);
+#endif
+
+ return 0;
+}
+coredevice_initcall(mem_malloc_resource);
+
static void *sbrk_no_zero(ptrdiff_t increment)
{
unsigned long old = malloc_brk;
@@ -82,6 +112,10 @@ void barebox_add_memory_bank(const char *name, resource_size_t start,
struct memory_bank *bank = xzalloc(sizeof(*bank));
struct device_d *dev;
+ bank->res = request_iomem_region(name, start, size);
+
+ BUG_ON(!bank->res);
+
dev = add_mem_device(name, start, size, IORESOURCE_MEM_WRITEABLE);
bank->dev = dev;
@@ -91,6 +125,30 @@ void barebox_add_memory_bank(const char *name, resource_size_t start,
list_add_tail(&bank->list, &memory_banks);
}
+/*
+ * Request a region from the registered sdram
+ */
+struct resource *request_sdram_region(const char *name, resource_size_t start,
+ resource_size_t size)
+{
+ struct memory_bank *bank;
+
+ for_each_memory_bank(bank) {
+ struct resource *res;
+
+ res = request_region(bank->res, name, start, size);
+ if (res)
+ return res;
+ }
+
+ return NULL;
+}
+
+int release_sdram_region(struct resource *res)
+{
+ return release_region(res);
+}
+
#ifdef CONFIG_OFTREE
/*
diff --git a/common/resource.c b/common/resource.c
new file mode 100644
index 0000000000..63e9c49ca1
--- /dev/null
+++ b/common/resource.c
@@ -0,0 +1,121 @@
+/*
+ * resource.c - barebox resource management
+ *
+ * Copyright (c) 2011 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation.
+ */
+#include <common.h>
+#include <malloc.h>
+#include <errno.h>
+#include <init.h>
+#include <linux/ioport.h>
+
+static int init_resource(struct resource *res, const char *name)
+{
+ INIT_LIST_HEAD(&res->children);
+ res->parent = NULL;
+ res->name = xstrdup(name);
+
+ return 0;
+}
+
+/*
+ * request a region.
+ * This will succedd when the requested region is completely inside
+ * the parent resource and does not conflict with any of the child
+ * resources.
+ */
+struct resource *request_region(struct resource *parent,
+ const char *name, resource_size_t start,
+ resource_size_t size)
+{
+ struct resource *r, *new;
+
+ /* outside parent resource? */
+ if (start < parent->start ||
+ start + size > parent->start + parent->size) {
+ debug("%s: 0x%08x:0x%08x outside parent resource 0x%08x:0x%08x\n",
+ __func__, start, size, parent->start,
+ parent->size);
+ return NULL;
+ }
+
+ /*
+ * We keep the list of child resources ordered which helps
+ * us searching for conflicts here.
+ */
+ list_for_each_entry(r, &parent->children, sibling) {
+ if (start + size <= r->start)
+ goto ok;
+ if (start >= r->start + r->size)
+ continue;
+ debug("%s: 0x%08x:0x%08x conflicts with 0x%08x:0x%08x\n",
+ __func__, start, size, r->start, r->size);
+ return NULL;
+ }
+
+ok:
+ debug("%s ok: 0x%08x 0x%08x\n", __func__, start, size);
+
+ new = xzalloc(sizeof(*new));
+ init_resource(new, name);
+ new->start = start;
+ new->size = size;
+ new->parent = parent;
+ list_add_tail(&new->sibling, &r->sibling);
+
+ return new;
+}
+
+/*
+ * release a region previously requested with request_region
+ */
+int release_region(struct resource *res)
+{
+ if (!list_empty(&res->children))
+ return -EBUSY;
+
+ list_del(&res->sibling);
+ free((char *)res->name);
+ free(res);
+
+ return 0;
+}
+
+/* The root resource for the whole io space */
+struct resource iomem_resource = {
+ .start = 0,
+ .size = ~0,
+};
+
+/*
+ * request a region inside the io space
+ */
+struct resource *request_iomem_region(const char *name,
+ resource_size_t start, resource_size_t size)
+{
+ return request_region(&iomem_resource, name, start, size);
+}
+
+static int iomem_init(void)
+{
+ init_resource(&iomem_resource, "iomem");
+
+ return 0;
+}
+postcore_initcall(iomem_init);
diff --git a/drivers/base/driver.c b/drivers/base/driver.c
index 0b80103144..0132e7dcf8 100644
--- a/drivers/base/driver.c
+++ b/drivers/base/driver.c
@@ -214,7 +214,7 @@ int register_driver(struct driver_d *drv)
}
EXPORT_SYMBOL(register_driver);
-void __iomem *dev_get_mem_region(struct device_d *dev, int num)
+static struct resource *dev_get_resource(struct device_d *dev, int num)
{
int i, n = 0;
@@ -222,15 +222,40 @@ void __iomem *dev_get_mem_region(struct device_d *dev, int num)
struct resource *res = &dev->resource[i];
if (resource_type(res) == IORESOURCE_MEM) {
if (n == num)
- return (void __force __iomem *)res->start;
+ return res;
n++;
}
}
return NULL;
}
+
+void __iomem *dev_get_mem_region(struct device_d *dev, int num)
+{
+ struct resource *res;
+
+ res = dev_get_resource(dev, num);
+ if (!res)
+ return res;
+
+ return (void __force __iomem *)res->start;
+}
EXPORT_SYMBOL(dev_get_mem_region);
+void __iomem *dev_request_mem_region(struct device_d *dev, int num)
+{
+ struct resource *res;
+
+ res = dev_get_resource(dev, num);
+ if (!res)
+ return NULL;
+
+ res = request_iomem_region(dev_name(dev), res->start, res->size);
+
+ return (void __force __iomem *)res->start;
+}
+EXPORT_SYMBOL(dev_request_mem_region);
+
int dev_protect(struct device_d *dev, size_t count, unsigned long offset, int prot)
{
printf("%s: currently broken\n", __func__);
diff --git a/include/driver.h b/include/driver.h
index fe9d37ae3d..bbe724833f 100644
--- a/include/driver.h
+++ b/include/driver.h
@@ -190,11 +190,7 @@ void __iomem *dev_get_mem_region(struct device_d *dev, int num);
/*
* exlusively request register base 'num' for a device
*/
-static inline void __iomem *dev_request_mem_region(struct device_d *dev, int num)
-{
- /* no resource tracking yet */
- return dev_get_mem_region(dev, num);
-}
+void __iomem *dev_request_mem_region(struct device_d *dev, int num);
/*
* register a generic device
diff --git a/include/linux/ioport.h b/include/linux/ioport.h
index 51431158d3..c837b53491 100644
--- a/include/linux/ioport.h
+++ b/include/linux/ioport.h
@@ -20,6 +20,9 @@ struct resource {
resource_size_t size;
const char *name;
unsigned long flags;
+ struct resource *parent;
+ struct list_head children;
+ struct list_head sibling;
};
/*
@@ -111,5 +114,16 @@ static inline unsigned long resource_type(const struct resource *res)
return res->flags & IORESOURCE_TYPE_BITS;
}
+struct resource *request_iomem_region(const char *name,
+ resource_size_t start, resource_size_t size);
+
+struct resource *request_region(struct resource *parent,
+ const char *name, resource_size_t start,
+ resource_size_t size);
+
+int release_region(struct resource *res);
+
+extern struct resource iomem_resource;
+
#endif /* __ASSEMBLY__ */
#endif /* _LINUX_IOPORT_H */
diff --git a/include/memory.h b/include/memory.h
index cb185afa65..4be4340b14 100644
--- a/include/memory.h
+++ b/include/memory.h
@@ -13,6 +13,7 @@ struct memory_bank {
struct device_d *dev;
unsigned long start;
unsigned long size;
+ struct resource *res;
};
extern struct list_head memory_banks;
@@ -22,4 +23,8 @@ void barebox_add_memory_bank(const char *name, resource_size_t start,
#define for_each_memory_bank(mem) list_for_each_entry(mem, &memory_banks, list)
+struct resource *request_sdram_region(const char *name, resource_size_t start,
+ resource_size_t size);
+int release_sdram_region(struct resource *res);
+
#endif