[PATCH][MIPS] PowerTV: Cleanup code to handle early bootmem allocations

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Change how memory is set up, especially before the page allocator is ready

Cleanup and divide the work of reserving pre-allocated memory into two pieces:

1.	Avoid passing RAM for fixed-address pre-allocated memory to the
	boot allocator. This is done before the boot allocator is initialized.
2.	After the slab allocator is initialized, allocate memory for the
	pre-allocations that do not have fixed address, then add resources
	for both fixed and non-fixed address preallocations

Also, switch to PREALLOC_* macros in arch/mips/powertv/asic/prealloc-gaia.c to 
manage their configuration.

Signed-off-by: David VomLehn <dvomlehn@xxxxxxxxx>
---
 arch/mips/include/asm/mach-powertv/asic.h          |   30 +-
 arch/mips/include/asm/mach-powertv/painting.h      |  224 ++++++++
 .../include/asm/mach-powertv/powertv-prealloc.h    |   51 ++
 arch/mips/include/asm/mach-powertv/prealloc.h      |  121 +++++
 arch/mips/powertv/Kconfig                          |   12 +
 arch/mips/powertv/asic/Kconfig                     |   38 +-
 arch/mips/powertv/asic/Makefile                    |    6 +-
 arch/mips/powertv/asic/asic_devices.c              |  219 ++-------
 arch/mips/powertv/asic/asic_int.c                  |    4 +-
 arch/mips/powertv/asic/painting.c                  |  298 ++++++++++
 arch/mips/powertv/asic/powertv-prealloc.c          |  136 +++++
 arch/mips/powertv/asic/prealloc-calliope.c         |    9 +-
 arch/mips/powertv/asic/prealloc-cronus.c           |    7 +-
 arch/mips/powertv/asic/prealloc-cronuslite.c       |    5 +-
 arch/mips/powertv/asic/prealloc-gaia.c             |  490 ++++-------------
 arch/mips/powertv/asic/prealloc-zeus.c             |    7 +-
 arch/mips/powertv/asic/prealloc.c                  |  566 ++++++++++++++++++++
 arch/mips/powertv/asic/prealloc.h                  |   70 ---
 arch/mips/powertv/init.c                           |    4 +-
 arch/mips/powertv/ioremap.c                        |   38 +-
 arch/mips/powertv/memory.c                         |  203 ++-----
 arch/mips/powertv/powertv_setup.c                  |    4 +-
 22 files changed, 1690 insertions(+), 852 deletions(-)

diff --git a/arch/mips/include/asm/mach-powertv/asic.h b/arch/mips/include/asm/mach-powertv/asic.h
index c7077a6..0d7f8a5 100644
--- a/arch/mips/include/asm/mach-powertv/asic.h
+++ b/arch/mips/include/asm/mach-powertv/asic.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009  Cisco Systems, Inc.
+ * Copyright (C) 2009-2010  Cisco Systems, Inc.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -51,20 +51,9 @@ extern const struct register_map cronus_register_map;
 extern const struct register_map gaia_register_map;
 extern const struct register_map zeus_register_map;
 
-extern struct resource dvr_cronus_resources[];
-extern struct resource dvr_gaia_resources[];
-extern struct resource dvr_zeus_resources[];
-extern struct resource non_dvr_calliope_resources[];
-extern struct resource non_dvr_cronus_resources[];
-extern struct resource non_dvr_cronuslite_resources[];
-extern struct resource non_dvr_gaia_resources[];
-extern struct resource non_dvr_vz_calliope_resources[];
-extern struct resource non_dvr_vze_calliope_resources[];
-extern struct resource non_dvr_vzf_calliope_resources[];
-extern struct resource non_dvr_zeus_resources[];
-
+/* Platform resources management */
+extern void platform_reserve_bootmem(void);
 extern void powertv_platform_init(void);
-extern void platform_alloc_bootmem(void);
 extern enum asic_type platform_get_asic(void);
 extern enum family_type platform_get_family(void);
 extern int platform_supports_dvr(void);
@@ -73,11 +62,6 @@ extern int platform_supports_pcie(void);
 extern int platform_supports_display(void);
 extern void configure_platform(void);
 
-/* Platform Resources */
-#define ASIC_RESOURCE_GET_EXISTS 1
-extern struct resource *asic_resource_get(const char *name);
-extern void platform_release_memory(void *baddr, int size);
-
 /* USB configuration */
 struct usb_hcd;			/* Forward reference */
 extern void platform_configure_usb_ehci(void);
@@ -87,8 +71,16 @@ extern void platform_unconfigure_usb_ohci(void);
 
 /* Resource for ASIC registers */
 extern struct resource asic_resource;
+#ifdef CONFIG_USB
 extern int platform_usb_devices_init(struct platform_device **echi_dev,
 	struct platform_device **ohci_dev);
+#else
+static inline int platform_usb_devices_init(struct platform_device **echi_dev,
+	struct platform_device **ohci_dev)
+{
+	return 0;
+}
+#endif
 
 /* Reboot Cause */
 extern void set_reboot_cause(char code, unsigned int data, unsigned int data2);
diff --git a/arch/mips/include/asm/mach-powertv/painting.h b/arch/mips/include/asm/mach-powertv/painting.h
new file mode 100644
index 0000000..b748c81
--- /dev/null
+++ b/arch/mips/include/asm/mach-powertv/painting.h
@@ -0,0 +1,224 @@
+/*
+ *				painting.h
+ *
+ * Definitions to use the paint interface, which allows painting kernel
+ * memory allocations in order to be able to track memory usage.
+ *
+ * Author: David VomLehn
+ */
+/*
+ * Copyright (C) 2008-2009  Scientific-Atlanta, Inc.
+ * Copyright (C) 2009-2010  Cisco Systems, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef	_PAINTING_H_
+#define	_PAINTING_H_
+#include <linux/types.h>
+#include <linux/list.h>
+#include <linux/rbtree.h>
+#include <linux/compiler.h>
+#include <linux/err.h>
+
+/* Classifications of relationships between two areas */
+#define MISMATCH_CUR_ENDS_FIRST		((0 << 1) | 0)
+#define MISMATCH_CUR_ENDS_LAST		((0 << 1) | 1)
+#define MATCH_CUR_ENDS_FIRST		((1 << 1) | 0)
+#define MATCH_CUR_ENDS_LAST		((1 << 1) | 1)
+
+struct painting_desc {
+	phys_addr_t	p;		/* Starting location */
+	phys_addr_t	q;		/* Ending location, inclusive */
+	const void	*color;		/* "color" */
+};
+
+/* Data structure that holds the information for one painting area */
+struct painting_area {
+	struct rb_node		node;
+	struct painting_desc	desc;
+};
+
+/* Operations for a particular painting object */
+struct painting_ops {
+	struct painting_area	*(*alloc)(void *ctx);
+	void			(*free)(void *ctx,
+					const struct painting_area *area);
+	bool			(*equals)(const void *l, const void *r);
+};
+
+/* Basic paint object */
+struct painting {
+	struct rb_root			root;
+	struct list_head		areas;
+};
+
+#define PAINTING_INIT(name)					\
+		{						\
+			.root =	RB_ROOT,			\
+			.areas = LIST_HEAD_INIT(name.areas),	\
+		}
+
+#define	PAINTING(name) struct painting name = PAINTING_INIT(name)
+
+static inline void INIT_PAINTING(struct painting *this)
+{
+	this->root = RB_ROOT;
+}
+
+#define painting_for_each_area(pos, this)		\
+	for ((pos) = painting_first(this);		\
+		(pos) != NULL;				\
+		(pos) = painting_next(pos))
+
+#define painting_for_each_area_save(pos, n, this)		\
+	for ((pos) = painting_first(this),			\
+			(n) = (((pos) == NULL) ? NULL : painting_next(pos)); \
+		(pos) != NULL;					\
+		(pos) = (n),					\
+			(n) = (((pos) == NULL) ? NULL : painting_next(pos)))
+
+/* Functions */
+extern struct painting_area *find_neighbor(const struct painting *this,
+	phys_addr_t p);
+extern struct painting_area *
+	painting_do_prev_overlaps_and_abuts(struct painting *this,
+	struct painting_area *cur, struct painting_desc *new,
+	struct painting_area *tail);
+extern struct painting_area *do_successor(struct painting *this,
+	struct painting_area *cur, struct painting_desc *new);
+extern int finish_new_allocation(struct painting *this,
+	struct painting_area *newp, struct painting_desc *new);
+
+/*
+ * _painting_from_rb - convert an rb_node to the containing &painting_area
+ * @rb:	Pointer to the &struct rb_node
+ */
+static struct painting_area *__pure _painting_from_rb(struct rb_node *node)
+{
+	return (node == NULL) ? NULL :
+		container_of(node, struct painting_area, node);
+}
+
+/**
+ * painting_area_first - find the first &painting_area in a &painting
+ * @painting:	Pointer to a &struct pointing
+ * Returns NULL if no areas are in the &painting, otherwise a pointer to
+ * the first &struct painting_area.
+ */
+static inline struct painting_area *__pure
+	painting_first(const struct painting *p)
+{
+	return _painting_from_rb(rb_first(&p->root));
+}
+
+/**
+ * painting_next - find the next &painting_area
+ * @p:	Pointer to a &struct painting_area
+ *
+ * Returns a pointer to the next &struct painting_area
+ */
+static inline struct painting_area *__pure
+	painting_next(const struct painting_area *p)
+{
+	return _painting_from_rb(rb_next(&p->node));
+}
+
+/**
+ * painting_prev - find the previous &painting_area
+ * @p:	Pointer to a &struct painting_area
+ *
+ * Returns a pointer to the previous &struct painting_area
+ */
+static inline struct painting_area *__pure
+	painting_prev(const struct painting_area *p)
+{
+	return _painting_from_rb(rb_prev(&p->node));
+}
+
+/**
+ * classify - categorize the relationship between two areas
+ * @a:	Pointer to a &struct painting_desc for the first area
+ * @b:	Pointer to a &struct painting_desc for the second area
+ */
+static inline int __pure classify(const struct painting_desc *a,
+	const struct painting_desc *b)
+{
+	int same_color, b_ends_before_a, result;
+
+	same_color = (a->color == b->color);
+	b_ends_before_a = (b->q < a->q);
+	result = ((same_color << 1) | b_ends_before_a);
+	return result;
+}
+
+/**
+ * painting_have_prev - see if the current area preceeds the new area
+ * @cur:	Pointer to the &painting_area for the current area
+ * @new:	Pointer to the &painting_desc for the new area
+ *
+ * Returns true if the current area exists before the new area, false otherwise
+ */
+static inline bool __pure painting_have_prev(const struct painting_area *cur,
+	const struct painting_desc *new)
+{
+	return cur != NULL && cur->desc.p < new->p;
+}
+
+/**
+ * painting_prev_overlaps_or_abuts - does prev area overlaps or abuts new area
+ * @cur:	Pointer to &struct painting_desc for the current area
+ * @new:	Pointer to &struct painting_desc for the current area
+ *
+ * Returns true of the current area is before the new area and either overlaps
+ * or abuts the new area.
+ */
+static inline bool __pure
+	painting_prev_overlaps_or_abuts(const struct painting_desc *cur,
+	const struct painting_desc *new)
+{
+	return cur->p < new->p && cur->q >= new->p - 1;
+}
+
+/**
+ * painting_must_make_hole - see if new area makes a hole in the current area
+ * @cur:	Pointer to the &struct painting_desc for the current area
+ * @new:	Pointer to the &struct painting_desc for the new area
+ *
+ * Returns true if the new area makes a hole in the current area, i.e. the
+ * current area ends up on both sides of the new area, false otherwise.
+ */
+static inline bool __pure
+	painting_must_make_hole(const struct painting_desc *cur,
+	const struct painting_desc *new)
+{
+	return classify(cur, new) == MISMATCH_CUR_ENDS_LAST;
+}
+
+/**
+ * painting_add_area - see if previous area overlaps or abuts the new area
+ * @cur:	Pointer to &struct painting_desc for the current area
+ * @new:	Pointer to &struct painting_desc for the current area
+ *
+ * Returns true of the current area is before the new area and either overlaps
+ * or abuts the new area.
+ */
+static inline bool __pure
+painting_add_area(const struct painting_desc *cur,
+	const struct painting_desc *new)
+{
+	return classify(cur, new) != MATCH_CUR_ENDS_LAST;
+}
+#endif
diff --git a/arch/mips/include/asm/mach-powertv/powertv-prealloc.h b/arch/mips/include/asm/mach-powertv/powertv-prealloc.h
new file mode 100644
index 0000000..5b4f938
--- /dev/null
+++ b/arch/mips/include/asm/mach-powertv/powertv-prealloc.h
@@ -0,0 +1,51 @@
+/*
+ * Description:  Does platform-specific hardware initialization
+ *
+ * Copyright (C) 2005-2010 Scientific-Atlanta, Inc.
+ * Copyright (C) 2009-2010 Cisco Systems, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef _POWERTV_ASIC_PREALLOC_H_
+#define _POWERTV_ASIC_PREALLOC_H_
+#include <asm/mach-powertv/asic_regs.h>
+#include "prealloc.h"
+
+/* PLATFORM RESOURCE DEFINITIONS */
+extern const struct dma_resource dvr_cronus_resources[];
+extern const struct dma_resource dvr_gaia_resources[];
+extern const struct dma_resource dvr_zeus_resources[];
+extern const struct dma_resource non_dvr_calliope_resources[];
+extern const struct dma_resource non_dvr_cronus_resources[];
+extern const struct dma_resource non_dvr_cronuslite_resources[];
+extern const struct dma_resource non_dvr_gaia_resources[];
+extern const struct dma_resource non_dvr_vz_calliope_resources[];
+extern const struct dma_resource non_dvr_vze_calliope_resources[];
+extern const struct dma_resource non_dvr_vzf_calliope_resources[];
+extern const struct dma_resource non_dvr_zeus_resources[];
+
+extern const struct dma_resource *gp_resources;
+
+/* Resource for ASIC */
+extern struct resource asic_resource;
+
+/* Point to resource-s of Low memory and High memory extents */
+extern struct resource *ptv_res_loext_root;
+extern struct resource *ptv_res_hiext_root;
+
+extern void plat_resource_init(void);
+extern void register_available_ram(void);
+#endif
diff --git a/arch/mips/include/asm/mach-powertv/prealloc.h b/arch/mips/include/asm/mach-powertv/prealloc.h
new file mode 100644
index 0000000..066c11f
--- /dev/null
+++ b/arch/mips/include/asm/mach-powertv/prealloc.h
@@ -0,0 +1,121 @@
+/*
+ * Definitions for memory preallocations
+ *
+ * Copyright (C) 2005-2009  Scientific-Atlanta, Inc.
+ * Copyright (C) 2009-2010  Cisco Systems, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef _ARCH_MIPS_POWERTV_ASIC_PREALLOC_H
+#define _ARCH_MIPS_POWERTV_ASIC_PREALLOC_H
+#include <linux/ioport.h>
+#include <linux/resource.h>
+#include <asm/mach-powertv/painting.h>
+
+#define KIBIBYTE(n) ((n) * 1024)    /* Number of kibibytes */
+#define MEBIBYTE(n) ((n) * KIBIBYTE(1024)) /* Number of mebibytes */
+
+#define IORESOURCE_PTV_RES_LOEXT	0x1 /* Resource must go in low mem */
+
+/* "struct resource" array element definition */
+#define PREALLOC(NAME, START, END, FLAGS) {	\
+		.name = (NAME),			\
+		.start = (START),		\
+		.end = (END),			\
+		.flags = (FLAGS)		\
+	},
+
+/* Individual resources in the preallocated resource arrays are defined using
+ *  macros.  These macros are conditionally defined based on their
+ *  corresponding kernel configuration flag:
+ *    - CONFIG_PREALLOC_NORMAL: preallocate resources for a normal settop box
+ *    - CONFIG_PREALLOC_TFTP: preallocate the TFTP download resource
+ *    - CONFIG_PREALLOC_DOCSIS: preallocate the DOCSIS resource
+ *    - CONFIG_PREALLOC_PMEM: reserve space for persistent memory
+ */
+#ifdef CONFIG_PREALLOC_NORMAL
+#define PREALLOC_NORMAL(name, start, end, flags) \
+   PREALLOC(name, start, end, flags)
+#else
+#define PREALLOC_NORMAL(name, start, end, flags)
+#endif
+
+#ifdef CONFIG_PREALLOC_TFTP
+#define PREALLOC_TFTP(name, start, end, flags) \
+   PREALLOC(name, start, end, flags)
+#else
+#define PREALLOC_TFTP(name, start, end, flags)
+#endif
+
+#ifdef CONFIG_PREALLOC_DOCSIS
+#define PREALLOC_DOCSIS(name, start, end, flags) \
+   PREALLOC(name, start, end, flags)
+#else
+#define PREALLOC_DOCSIS(name, start, end, flags)
+#endif
+
+#ifdef CONFIG_PREALLOC_PMEM
+#define PREALLOC_PMEM(name, start, end, flags) \
+   PREALLOC(name, start, end, flags)
+#else
+#define PREALLOC_PMEM(name, start, end, flags)
+#endif
+
+/*
+ * Drivers really just need to look up the physical addresss of a resource
+ * name. This is the data we pass back to them
+ */
+struct bus_resource {
+	phys_addr_t start;
+	phys_addr_t end;
+};
+
+/*
+ * For describing resources as DMA addresses
+ */
+struct dma_resource {
+	dma_addr_t	start;
+	dma_addr_t	end;
+	const char	*name;
+	unsigned long	flags;
+};
+
+/* Predefined physical memory types */
+extern const char physmem_bootloader[];
+extern const char physmem_buddy_high[];
+extern const char physmem_buddy_low[];
+extern const char physmem_mem_map[];
+extern const char physmem_ram[];
+extern const char physmem_reserved[];
+extern const char physmem_reset_vector[];
+extern const char physmem_rom_data[];
+extern const char physmem_unknown[];
+extern const char physmem_zero_page[];
+
+/* allow drivers get info but use their data struct instead of passing */
+/* something allocated inside the kernel */
+extern int resource_add_ram(phys_addr_t start, size_t size);
+extern void resource_reserve_static_prealloc(size_t size,
+	const struct dma_resource *dma_res);
+extern void resource_add_memory_regions(void);
+extern size_t __init resource_request_prealloc(size_t n,
+	const struct dma_resource *dma_resources);
+extern bool platform_resource_override(struct resource *plat_res,
+	const struct dma_resource *dma_res);
+extern int platform_lookup_resource(const char *name,
+	struct bus_resource *bres_p);
+extern unsigned long platform_release_memory(unsigned long baddr, int size);
+#endif
diff --git a/arch/mips/powertv/Kconfig b/arch/mips/powertv/Kconfig
index ff0e7e3..e327762 100644
--- a/arch/mips/powertv/Kconfig
+++ b/arch/mips/powertv/Kconfig
@@ -19,3 +19,15 @@ config BOOTLOADER_FAMILY
 	    E1 - Class E  F1 - Class F
 	    44 - 45xx     46 - 46xx
 	    85 - 85xx     86 - 86xx
+
+config PREALLOCATED_AREAS_ITEMS
+	int "Number items for handling driver pre-allocations"
+	default 100
+	depends on POWERTV
+	help
+	  Very early allocations of large chunks of memory is done before any
+	  of the memory allocators are in use. This requires that any memory
+	  required be statically allocated. It is difficult to calculate the
+	  exact value, but it is roughly twice the number of preallocations
+	  plus two for the kernel and an extra two for each contiguous chunk
+	  of memory.
diff --git a/arch/mips/powertv/asic/Kconfig b/arch/mips/powertv/asic/Kconfig
index 2016bfe..1a48e17 100644
--- a/arch/mips/powertv/asic/Kconfig
+++ b/arch/mips/powertv/asic/Kconfig
@@ -1,28 +1,34 @@
-config MIN_RUNTIME_RESOURCES
-	bool "Support for minimum runtime resources"
-	default n
+menu "Preallocated resource options"
+
+config PREALLOC_NORMAL
+	bool "Preallocate normal resources"
 	depends on POWERTV
+	default y
 	help
-	  Enables support for minimizing the number of (SA asic) runtime
-	  resources that are preallocated by the kernel.
+	  Enables support for the preallocated kernel resources used in normal
+	  settop operation.  This includes all preallocated resources that
+	  aren't individually controlled via a separate CONFIG_PREALLOC_
+	  option.
 
-config MIN_RUNTIME_DOCSIS
-	bool "Support for minimum DOCSIS resource"
+config PREALLOC_DOCSIS
+	bool "Preallocate the DOCSIS resource"
+	depends on POWERTV
 	default y
-	depends on MIN_RUNTIME_RESOURCES
 	help
 	  Enables support for the preallocated DOCSIS resource.
 
-config MIN_RUNTIME_PMEM
-	bool "Support for minimum PMEM resource"
+config PREALLOC_PMEM
+	bool "Preallocate the PMEM resource"
+	depends on POWERTV
 	default y
-	depends on MIN_RUNTIME_RESOURCES
 	help
-	  Enables support for the preallocated Memory resource.
+	  Enables support for the preallocated persistent memory resource.
 
-config MIN_RUNTIME_TFTP
-	bool "Support for minimum TFTP resource"
-	default y
-	depends on MIN_RUNTIME_RESOURCES
+config PREALLOC_TFTP
+	bool "Preallocate the TFTP resource"
+	depends on POWERTV
+	default n
 	help
 	  Enables support for the preallocated TFTP resource.
+
+endmenu
diff --git a/arch/mips/powertv/asic/Makefile b/arch/mips/powertv/asic/Makefile
index f0e95dc..db0846b 100644
--- a/arch/mips/powertv/asic/Makefile
+++ b/arch/mips/powertv/asic/Makefile
@@ -1,5 +1,6 @@
 #
 # Copyright (C) 2009  Scientific-Atlanta, Inc.
+# Copyright (C) 2010  Cisco Systems, Inc.
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -17,7 +18,8 @@
 #
 
 obj-y += asic-calliope.o asic-cronus.o asic-gaia.o asic-zeus.o \
-	asic_devices.o asic_int.o irq_asic.o prealloc-calliope.o \
-	prealloc-cronus.o prealloc-cronuslite.o prealloc-gaia.o prealloc-zeus.o
+	asic_devices.o asic_int.o irq_asic.o painting.o \
+	powertv-prealloc.o prealloc.o prealloc-calliope.o prealloc-cronus.o \
+	prealloc-cronuslite.o prealloc-gaia.o prealloc-zeus.o
 
 EXTRA_CFLAGS += -Wall -Werror
diff --git a/arch/mips/powertv/asic/asic_devices.c b/arch/mips/powertv/asic/asic_devices.c
index e56fa61..a8c018b 100644
--- a/arch/mips/powertv/asic/asic_devices.c
+++ b/arch/mips/powertv/asic/asic_devices.c
@@ -1,8 +1,9 @@
 /*
  *
- * Description:  Defines the platform resources for Gaia-based settops.
+ * Description:  Does platform-specific hardware initialization
  *
  * Copyright (C) 2005-2009 Scientific-Atlanta, Inc.
+ * Copyright (C) 2009-2010 Cisco Systems, Inc.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -21,22 +22,16 @@
  * NOTE: The bootloader allocates persistent memory at an address which is
  * 16 MiB below the end of the highest address in KSEG0. All fixed
  * address memory reservations must avoid this region.
+ *
+ * NOTE: This does not pre-allocate memory areas with dynamic address in
+ * memory outside of kseg0/kseg1. Dynamic allocation is restricted to
+ * kseg0/kseg1 memory. It wouldn't really be all that hard to support it;
+ * it just hasn't been needed.
  */
 
-#include <linux/device.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/resource.h>
-#include <linux/serial_reg.h>
-#include <linux/io.h>
-#include <linux/bootmem.h>
-#include <linux/mm.h>
-#include <linux/platform_device.h>
 #include <linux/module.h>
-#include <asm/page.h>
-#include <linux/swap.h>
-#include <linux/highmem.h>
-#include <linux/dma-mapping.h>
 
 #include <asm/mach-powertv/asic.h>
 #include <asm/mach-powertv/asic_regs.h>
@@ -46,15 +41,11 @@
 #include <asm/mach-powertv/kbldr.h>
 #endif
 #include <asm/bootinfo.h>
+#include <asm/mach-powertv/powertv-prealloc.h>
 
 #define BOOTLDRFAMILY(byte1, byte0) (((byte1) << 8) | (byte0))
 
 /*
- * Forward Prototypes
- */
-static void pmem_setup_resource(void);
-
-/*
  * Global Variables
  */
 enum asic_type asic;
@@ -66,14 +57,6 @@ EXPORT_SYMBOL(_asic_register_map);		/* Exported for testing */
 unsigned long asic_phy_base;
 unsigned long asic_base;
 EXPORT_SYMBOL(asic_base);			/* Exported for testing */
-struct resource *gp_resources;
-
-/*
- * Don't recommend to use it directly, it is usually used by kernel internally.
- * Portable code should be using interfaces such as ioremp, dma_map_single, etc.
- */
-unsigned long phys_to_dma_offset;
-EXPORT_SYMBOL(phys_to_dma_offset);
 
 /*
  *
@@ -89,6 +72,13 @@ struct resource asic_resource = {
 };
 
 /*
+ * Don't recommend to use it directly, it is usually used by kernel internally.
+ * Portable code should be using interfaces such as ioremp, dma_map_single, etc.
+ */
+unsigned long phys_to_dma_offset;
+EXPORT_SYMBOL(phys_to_dma_offset);
+
+/*
  * Allow override of bootloader-specified model
  * Returns zero on success, a negative errno value on failure.  This parameter
  * allows overriding of the bootloader-specified model.
@@ -236,9 +226,9 @@ static void __init set_register_map(unsigned long phys_base,
 }
 
 /**
- * configure_platform - configuration based on platform type.
+ * powertv_platform_init - configuration based on platform type.
  */
-void __init configure_platform(void)
+void __init powertv_platform_init(void)
 {
 	platform_set_family();
 
@@ -374,176 +364,35 @@ void __init configure_platform(void)
 	}
 }
 
-/*
- * RESOURCE ALLOCATION
- *
- */
-/*
- * Allocates/reserves the Platform memory resources early in the boot process.
- * This ignores any resources that are designated IORESOURCE_IO
- */
-void __init platform_alloc_bootmem(void)
-{
-	int i;
-	int total = 0;
-
-	/* Get persistent memory data from command line before allocating
-	 * resources. This need to happen before normal command line parsing
-	 * has been done */
-	pmem_setup_resource();
-
-	/* Loop through looking for resources that want a particular address */
-	for (i = 0; gp_resources[i].flags != 0; i++) {
-		int size = gp_resources[i].end - gp_resources[i].start + 1;
-		if ((gp_resources[i].start != 0) &&
-			((gp_resources[i].flags & IORESOURCE_MEM) != 0)) {
-			reserve_bootmem(dma_to_phys(gp_resources[i].start),
-				size, 0);
-			total += gp_resources[i].end -
-				gp_resources[i].start + 1;
-			pr_info("reserve resource %s at %08x (%u bytes)\n",
-				gp_resources[i].name, gp_resources[i].start,
-				gp_resources[i].end -
-					gp_resources[i].start + 1);
-		}
-	}
-
-	/* Loop through assigning addresses for those that are left */
-	for (i = 0; gp_resources[i].flags != 0; i++) {
-		int size = gp_resources[i].end - gp_resources[i].start + 1;
-		if ((gp_resources[i].start == 0) &&
-			((gp_resources[i].flags & IORESOURCE_MEM) != 0)) {
-			void *mem = alloc_bootmem_pages(size);
-
-			if (mem == NULL)
-				pr_err("Unable to allocate bootmem pages "
-					"for %s\n", gp_resources[i].name);
-
-			else {
-				gp_resources[i].start =
-					phys_to_dma(virt_to_phys(mem));
-				gp_resources[i].end =
-					gp_resources[i].start + size - 1;
-				total += size;
-				pr_info("allocate resource %s at %08x "
-						"(%u bytes)\n",
-					gp_resources[i].name,
-					gp_resources[i].start, size);
-			}
-		}
-	}
-
-	pr_info("Total Platform driver memory allocation: 0x%08x\n", total);
-
-	/* indicate resources that are platform I/O related */
-	for (i = 0; gp_resources[i].flags != 0; i++) {
-		if ((gp_resources[i].start != 0) &&
-			((gp_resources[i].flags & IORESOURCE_IO) != 0)) {
-			pr_info("reserved platform resource %s at %08x\n",
-				gp_resources[i].name, gp_resources[i].start);
-		}
-	}
-}
-
-/*
- *
- * PERSISTENT MEMORY (PMEM) CONFIGURATION
- *
- */
-static unsigned long pmemaddr __initdata;
-
-static int __init early_param_pmemaddr(char *p)
-{
-	pmemaddr = (unsigned long)simple_strtoul(p, NULL, 0);
-	return 0;
-}
-early_param("pmemaddr", early_param_pmemaddr);
-
-static long pmemlen __initdata;
-
-static int __init early_param_pmemlen(char *p)
-{
-/* TODO: we can use this code when and if the bootloader ever changes this */
-#if 0
-	pmemlen = (unsigned long)simple_strtoul(p, NULL, 0);
+#ifdef CONFIG_USB
+#define NUM_USB_IFS	2
 #else
-	pmemlen = 0x20000;
+#define NUM_USB_IFS	0
 #endif
-	return 0;
-}
-early_param("pmemlen", early_param_pmemlen);
 
-/*
- * Set up persistent memory. If we were given values, we patch the array of
- * resources. Otherwise, persistent memory may be allocated anywhere at all.
- */
-static void __init pmem_setup_resource(void)
-{
-	struct resource *resource;
-	resource = asic_resource_get("DiagPersistentMemory");
-
-	if (resource && pmemaddr && pmemlen) {
-		/* The address provided by bootloader is in kseg0. Convert to
-		 * a bus address. */
-		resource->start = phys_to_dma(pmemaddr - 0x80000000);
-		resource->end = resource->start + pmemlen - 1;
-
-		pr_info("persistent memory: start=0x%x  end=0x%x\n",
-			resource->start, resource->end);
-	}
-}
+static struct platform_device *platform_devices[NUM_USB_IFS];
 
 /*
- *
- * RESOURCE ACCESS FUNCTIONS
- *
+ * platform_devices_init - initialize platform resource usage
  */
-
-/**
- * asic_resource_get - retrieves parameters for a platform resource.
- * @name:	string to match resource
- *
- * Returns a pointer to a struct resource corresponding to the given name.
- *
- * CANNOT BE NAMED platform_resource_get, which would be the obvious choice,
- * as this function name is already declared
- */
-struct resource *asic_resource_get(const char *name)
+int __init platform_devices_init(void)
 {
-	int i;
+	int ret;
 
-	for (i = 0; gp_resources[i].flags != 0; i++) {
-		if (strcmp(gp_resources[i].name, name) == 0)
-			return &gp_resources[i];
-	}
+	asic_resource.start = asic_phy_base;
+	asic_resource.end += asic_resource.start;
 
-	return NULL;
-}
-EXPORT_SYMBOL(asic_resource_get);
-
-/**
- * platform_release_memory - release pre-allocated memory
- * @ptr:	pointer to memory to release
- * @size:	size of resource
- *
- * This must only be called for memory allocated or reserved via the boot
- * memory allocator.
- */
-void platform_release_memory(void *ptr, int size)
-{
-	unsigned long addr;
-	unsigned long end;
+	ret = platform_usb_devices_init(&platform_devices[0],
+		&platform_devices[1]);
+	if (ret != 0)
+		return ret;
 
-	addr = ((unsigned long)ptr + (PAGE_SIZE - 1)) & PAGE_MASK;
-	end = ((unsigned long)ptr + size) & PAGE_MASK;
+	set_io_port_base(0);
+	platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
 
-	for (; addr < end; addr += PAGE_SIZE) {
-		ClearPageReserved(virt_to_page(__va(addr)));
-		init_page_count(virt_to_page(__va(addr)));
-		free_page((unsigned long)__va(addr));
-	}
+	return 0;
 }
-EXPORT_SYMBOL(platform_release_memory);
+arch_initcall(platform_devices_init);
 
 /*
  *
diff --git a/arch/mips/powertv/asic/asic_int.c b/arch/mips/powertv/asic/asic_int.c
index 7362f63..6866302 100644
--- a/arch/mips/powertv/asic/asic_int.c
+++ b/arch/mips/powertv/asic/asic_int.c
@@ -2,7 +2,7 @@
  * Carsten Langgaard, carstenl@xxxxxxxx
  * Copyright (C) 2000, 2001, 2004 MIPS Technologies, Inc.
  * Copyright (C) 2001 Ralf Baechle
- * Portions copyright (C) 2009  Cisco Systems, Inc.
+ * Portions copyright (C) 2009-2010  Cisco Systems, Inc.
  *
  *  This program is free software; you can distribute it and/or modify it
  *  under the terms of the GNU General Public License (Version 2) as
@@ -37,6 +37,7 @@
 #include <asm/mips-boards/generic.h>
 
 #include <asm/mach-powertv/asic_regs.h>
+#include <asm/mach-powertv/powertv-prealloc.h>
 
 static DEFINE_RAW_SPINLOCK(asic_irq_lock);
 
@@ -98,6 +99,7 @@ void __init arch_init_irq(void)
 {
 	int i;
 
+	plat_resource_init();
 	asic_irq_init();
 
 	/*
diff --git a/arch/mips/powertv/asic/painting.c b/arch/mips/powertv/asic/painting.c
new file mode 100644
index 0000000..306622e
--- /dev/null
+++ b/arch/mips/powertv/asic/painting.c
@@ -0,0 +1,298 @@
+/*
+ *				painting.c
+ *
+ * Functions that allow assigning "paints" (really, arbitrary tokens) to
+ * different areas of a "painting". This is useful for keeping track of
+ * the usage of given chunks of memory or I/O devices. Areas are
+ * described using phys_addr_t values to keep the representation as
+ * abstract as possible. Areas are not intended to wrap around the value
+ * space, e.g. if an area starts at zero, it won't be consolidated with an area
+ * of the same color ending at ~0.
+ *
+ * Copyright (C) 2008  Scientific-Atlanta, Inc.
+ * Copyright (C) 2010  Cisco Systems, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * Author: David VomLehn
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <asm/mach-powertv/painting.h>
+
+/**
+ * painting_link - link a &painting_area into a &painting
+ * @this:	Pointer to &struct painting in which to add the
+ *		&struct painting_area
+ * @new:	Pointer to the &struct painting area to add
+ *
+ * Returns zero on success or a negative errno value on error
+ */
+static int painting_link(struct painting *this, struct painting_area *new)
+{
+	struct rb_node **n = &(this->root.rb_node), *parent = NULL;
+
+	while (*n) {
+		struct painting_area *this;
+		phys_addr_t p;
+
+		this = container_of(*n, struct painting_area, node);
+		parent = *n;
+		p = new->desc.p;
+
+		if (p < this->desc.p)
+			n = &((*n)->rb_left);
+		else if (p > this->desc.p)
+			n = &((*n)->rb_right);
+		else
+			return false;
+	}
+
+	rb_link_node(&new->node, parent, n);
+	rb_insert_color(&new->node, &this->root);
+
+	return true;
+}
+
+/**
+ * find_neighbor - find a neighbor close to the beginning of a &painting_area
+ * @this:	Pointer to the &struct painting we are coloring
+ * @p:		Location the area about which we are search starts
+ *
+ * Returns NULL if it didn't find anything at all. Otherwise it returns
+ * either a pointer to the last &struct painting_area before @p or, if
+ * there wasn't one, a pointer to the first &struct painting_area after p.
+ */
+struct painting_area *find_neighbor(const struct painting *this,
+	phys_addr_t p)
+{
+	struct rb_node *n = this->root.rb_node;
+	struct rb_node *parent;
+	struct painting_area *parent_area = NULL;
+
+	while (n) {
+		parent = n;
+		parent_area = container_of(n, struct painting_area, node);
+
+		if (p < parent_area->desc.p)
+			n = n->rb_left;
+		else if (p > parent_area->desc.p)
+			n = n->rb_right;
+		else
+			n = NULL;
+	}
+
+	if (parent_area != NULL && parent_area->desc.p > p) {
+		struct painting_area *right;
+		right = painting_prev(parent_area);
+		if (right != NULL)
+			parent_area = right;
+	}
+
+	return parent_area;
+}
+
+/**
+ * painting_unlink - remove an area from the tree
+ * @this:	Pointer to the &struct painting in which we are working
+ * @area:	Start of the &struct painting_area
+ */
+static void painting_unlink(struct painting *this,
+	struct painting_area *cur)
+{
+	rb_erase(&cur->node, &this->root);
+}
+
+/**
+ * make_a_hole - create a hole for new area in current area
+ * @this:	Pointer &struct painting
+ * @cur:	Pointer to current &pointer_area. This might be NULL if we're
+ *		all done.
+ * @new:	Starting location of new area. This has not yet been linked
+ * @tail:	Newly allocated &struct painting_area to hold the end of the
+ *		current area
+ *
+ * Returns zero on success, a negative errno value on failure.
+ */
+static int make_a_hole(struct painting *this,
+	struct painting_desc *cur, struct painting_desc *new,
+	struct painting_area *tail)
+{
+	int retval;
+
+	if (tail == NULL)
+		retval = -ENOMEM;
+	else {
+		tail->desc.p = new->q + 1;
+		tail->desc.q = cur->q;
+		tail->desc.color = cur->color;
+		painting_link(this, tail);
+
+		cur->q = new->p - 1;
+		retval = 0;
+	}
+
+	return retval;
+}
+
+/**
+ * extend_new - extend a new painting area, discarding an overlapping area
+ * @this:	Pointer to a &struct painting in which we are working
+ * @cur:	Pointer to the &struct painting_area for the overlapping
+ *		area to be discarded
+ * @new:	Pointer to the &struct painting_desc of an area to be extended
+ */
+static void extend_new(struct painting *this, struct painting_area *cur,
+	struct painting_desc *new)
+{
+	new->p = cur->desc.p;
+	painting_unlink(this, cur);
+}
+
+/**
+ * chop_cur - truncate an area current in the list
+ * @cur:	Pointer to a &struct painting_area for an area in the list
+ * @new:	New area that overwrites the current area
+ */
+static void chop_cur(struct painting_area *cur, const struct painting_desc *new)
+{
+	cur->desc.q = new->p - 1;
+}
+
+/**
+ * painting_do_prev_overlaps_and_abuts - handle previous that overlaps or abuts
+ * @this:	Pointer to &struct painting on which we're working
+ * @cur:	Pointer to &struct painting_area for the current area
+ * @new:	Pointer to the &struct painting_desc for the current area
+ * @tail:	Pointer to storage alloted for the left side of the hole made
+ *		in the current area by the new area
+ *
+ * Returns an ERR_PTR if an error occurred, a non-NULL pointer of we have
+ * a &struct painting_area to free, and a NULL pointer otherwise.
+ *
+ * Here we handle a current area that is overlapping and before
+ * the new area. There are four cases:
+ * Cur	RRRRRR          RRRRRRRRRR	RRRRRR		RRRRRRRR
+ * New	  bbbbbb	  bbbbbb	  RRRRRR	  RRRR
+ * Res	RRbbbbbb	RRbbbbbbRR	RRRRRRRR	RRRRRRRR
+ * Rslt	New+Cur		Cur+New+Head	Cur		Cur
+ * Done	No		Yes		No		Yes
+ */
+struct painting_area *
+	painting_do_prev_overlaps_and_abuts(struct painting *this,
+	struct painting_area *cur, struct painting_desc *new,
+	struct painting_area *tail)
+{
+	struct painting_area *free_me = NULL;
+	int retval;
+
+	switch (classify(&cur->desc, new)) {
+	case MISMATCH_CUR_ENDS_FIRST:
+		chop_cur(cur, new);
+		break;
+
+	case MISMATCH_CUR_ENDS_LAST:
+		retval = make_a_hole(this, &cur->desc, new, tail);
+		if (retval != 0)
+			free_me = ERR_PTR(retval);
+		break;
+
+	case MATCH_CUR_ENDS_FIRST:
+		extend_new(this, cur, new);
+		free_me = cur;
+		break;
+
+	case MATCH_CUR_ENDS_LAST:
+		/* Nothing to do since all of the new area is already the same
+		 * color as the current area. */
+		break;
+	}
+
+	return free_me;
+}
+
+/**
+ * do_successor - do an area at or following the new area
+ * @this:	Pointer to the &struct painting we're working on
+ * @cur:	Current area in the area list
+ * @new:	Pointer to the &struct painting_desc we're trying to add
+ *
+ * Returns a pointer to a &struct painting_area if it needs to be freed,
+ * otherwise it returns NULL.
+ */
+struct painting_area *do_successor(struct painting *this,
+	struct painting_area *cur, struct painting_desc *new)
+{
+	struct painting_area *retval = NULL;
+
+	/*
+	 * Every remaining area starts after the new area. Cases are therefore
+	 * Cur	RRRRRR		RRRRRRRR	RRRRRR		RRRRRRRR
+	 * New	bbbbbbbb	bbbbbb		RRRRRRRR	RRRRRR
+	 * Res	bbbbbbbb	bbbbbbRR	RRRRRRRR	RRRRRRRR
+	 * Name	past end	before end	overpaint	extend
+	 * Rslt	New+Cur		New		New		New
+	 */
+	switch (classify(&cur->desc, new)) {
+	case MISMATCH_CUR_ENDS_FIRST:
+		painting_unlink(this, cur);
+		retval = cur;
+		break;
+
+	case MISMATCH_CUR_ENDS_LAST:
+		painting_unlink(this, cur);
+		cur->desc.p = new->q + 1;
+		painting_link(this, cur);
+		break;
+
+	case MATCH_CUR_ENDS_FIRST:
+		painting_unlink(this, cur);
+		retval = cur;
+		break;
+
+	case MATCH_CUR_ENDS_LAST:
+		new->q = cur->desc.q;
+		painting_unlink(this, cur);
+		retval = cur;
+		break;
+	}
+
+	return retval;
+}
+
+/**
+ * finish_new_allocation - finish the work for add an area to the list
+ * @this:	Pointer to the &struct painting on which we are working
+ * @newp:	Pointer to the newly allocated &struct painting_area.
+ * @new:	Pointer to the &struct painting_desc values to be stored
+ *		in the new area
+ *
+ * Returns 0 in success, otherwise a negative errno value
+ */
+int finish_new_allocation(struct painting *this,
+	struct painting_area *newp, struct painting_desc *new)
+{
+	int	retval = 0;
+
+	if (newp == NULL)
+		retval = -ENOMEM;
+	else {
+		newp->desc = *new;
+		painting_link(this, newp);
+	}
+
+	return retval;
+}
diff --git a/arch/mips/powertv/asic/powertv-prealloc.c b/arch/mips/powertv/asic/powertv-prealloc.c
new file mode 100644
index 0000000..1047b5b
--- /dev/null
+++ b/arch/mips/powertv/asic/powertv-prealloc.c
@@ -0,0 +1,136 @@
+/*
+ * Handle platform-specific resources
+ *
+ * Copyright (C) 2005-2009 Scientific-Atlanta, Inc.
+ * Copyright (C) 2009-2010 Cisco Systems, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <linux/init.h>
+#include <asm/mach-powertv/asic.h>
+#include <asm/mach-powertv/powertv-prealloc.h>
+
+static struct dma_resource base_resources[] __initdata = {
+	{0x10000000, 0x10000000 + 0x40000 - 1, physmem_bootloader},
+	{0x1fc00000, 0x1fc00000 + 0x400000 - 1, physmem_reset_vector},
+};
+
+static unsigned long pmemaddr __initdata;
+
+static int __init early_param_pmemaddr(char *p)
+{
+	pmemaddr = (unsigned long)simple_strtoul(p, NULL, 0);
+	return 0;
+}
+early_param("pmemaddr", early_param_pmemaddr);
+
+static long pmemlen __initdata;
+
+static int __init early_param_pmemlen(char *p)
+{
+/* TODO: we can use this code when and if the bootloader ever changes this */
+#if 0
+	pmemlen = (unsigned long)simple_strtoul(p, NULL, 0);
+#else
+	pmemlen = 0x20000;
+#endif
+	return 0;
+}
+early_param("pmemlen", early_param_pmemlen);
+
+/*
+ * platform_resource_override - override information from platform resources
+ * @plat_res:	Pointer to &struct resource to set if this resource is being
+ *		overridden.
+ * @res:	Pointer to &struct dma_resource to check whether it should be
+ *		overridden.
+ *
+ * Returns true if the resource was overridden and should not be further
+ * processed, false if the resource wasn't overriden and should be processed
+ * as normal.
+ */
+bool __init platform_resource_override(struct resource *plat_res,
+	const struct dma_resource *res)
+{
+	if (strcmp(res->name, "DiagPersistentMemory") == 0) {
+		if (pmemaddr && pmemlen) {
+			/* The address provided by bootloader is in kseg0.
+			 * Convert to a physical address. */
+			plat_res->start = __pa(pmemaddr);
+			plat_res->end = plat_res->start + pmemlen - 1;
+			pr_info("persistent memory: start=0x%0*x  end=0x%0*x\n",
+				2 * sizeof(plat_res->start), plat_res->start,
+				2 * sizeof(plat_res->end), plat_res->end);
+		}
+		return true;
+	}
+
+	return false;
+}
+
+/*
+ * dma_resource_count - tallies the number of DMA resources available
+ * @plat_res:	Pointer to an array of &struct dma_resource objects
+ *
+ * Returns the number of non empty entries found
+ */
+static size_t __init dma_resource_count(const struct dma_resource *dma_res)
+{
+	int i;
+	/* Count number of resources */
+	for (i = 0; dma_res[i].flags != 0; i++)
+		;
+	return i;
+}
+
+/**
+ * register_available_ram - give RAM minus preallocations to the sytem
+ */
+void __init register_available_ram()
+{
+	size_t num_plat_res;
+
+	/* Subtract all of the preallocated RAM at a static address */
+	resource_reserve_static_prealloc(ARRAY_SIZE(base_resources),
+		base_resources);
+	num_plat_res = dma_resource_count(gp_resources);
+	resource_reserve_static_prealloc(num_plat_res, gp_resources);
+
+	/* Give all of the remaining RAM to the system */
+	resource_add_memory_regions();
+}
+
+/**
+ * plat_resource_init - request resources for preallocated memory
+ */
+void __init plat_resource_init()
+{
+	size_t size;
+	size_t total = 0;
+	size_t num_plat_res;
+
+	size = resource_request_prealloc(ARRAY_SIZE(base_resources),
+		base_resources);
+	if (size > 0)
+		total += size;
+
+	num_plat_res = dma_resource_count(gp_resources);
+	size = resource_request_prealloc(num_plat_res, gp_resources);
+	if (size > 0)
+		total += size;
+
+	pr_info("Total platform driver memory allocation: 0x%08x\n", total);
+}
diff --git a/arch/mips/powertv/asic/prealloc-calliope.c b/arch/mips/powertv/asic/prealloc-calliope.c
index 3fc5d46..d1ad146 100644
--- a/arch/mips/powertv/asic/prealloc-calliope.c
+++ b/arch/mips/powertv/asic/prealloc-calliope.c
@@ -2,6 +2,7 @@
  * Memory pre-allocations for Calliope boxes.
  *
  * Copyright (C) 2005-2009 Scientific-Atlanta, Inc.
+ * Copyright (C) 2009-2010 Cisco Systems, Inc.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -24,12 +25,12 @@
 #include <linux/init.h>
 #include <linux/ioport.h>
 #include <asm/mach-powertv/asic.h>
-#include "prealloc.h"
+#include <asm/mach-powertv/powertv-prealloc.h>
 
 /*
  * NON_DVR_CAPABLE CALLIOPE RESOURCES
  */
-struct resource non_dvr_calliope_resources[] __initdata =
+const struct dma_resource non_dvr_calliope_resources[] __initdata =
 {
 	/*
 	 * VIDEO / LX1
@@ -158,7 +159,7 @@ struct resource non_dvr_calliope_resources[] __initdata =
 };
 
 
-struct resource non_dvr_vze_calliope_resources[] __initdata =
+const struct dma_resource non_dvr_vze_calliope_resources[] __initdata =
 {
 	/*
 	 * VIDEO / LX1
@@ -264,7 +265,7 @@ struct resource non_dvr_vze_calliope_resources[] __initdata =
 	},
 };
 
-struct resource non_dvr_vzf_calliope_resources[] __initdata =
+const struct dma_resource non_dvr_vzf_calliope_resources[] __initdata =
 {
 	/*
 	 * VIDEO / LX1
diff --git a/arch/mips/powertv/asic/prealloc-cronus.c b/arch/mips/powertv/asic/prealloc-cronus.c
index c532b50..cd0d034 100644
--- a/arch/mips/powertv/asic/prealloc-cronus.c
+++ b/arch/mips/powertv/asic/prealloc-cronus.c
@@ -2,6 +2,7 @@
  * Memory pre-allocations for Cronus boxes.
  *
  * Copyright (C) 2005-2009 Scientific-Atlanta, Inc.
+ * Copyright (C) 2009-2010 Cisco Systems, Inc.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -24,12 +25,12 @@
 #include <linux/init.h>
 #include <linux/ioport.h>
 #include <asm/mach-powertv/asic.h>
-#include "prealloc.h"
+#include <asm/mach-powertv/powertv-prealloc.h>
 
 /*
  * DVR_CAPABLE CRONUS RESOURCES
  */
-struct resource dvr_cronus_resources[] __initdata =
+const struct dma_resource dvr_cronus_resources[] __initdata =
 {
 	/*
 	 * VIDEO1 / LX1
@@ -192,7 +193,7 @@ struct resource dvr_cronus_resources[] __initdata =
 /*
  * NON_DVR_CAPABLE CRONUS RESOURCES
  */
-struct resource non_dvr_cronus_resources[] __initdata =
+const struct dma_resource non_dvr_cronus_resources[] __initdata =
 {
 	/*
 	 * VIDEO1 / LX1
diff --git a/arch/mips/powertv/asic/prealloc-cronuslite.c b/arch/mips/powertv/asic/prealloc-cronuslite.c
index b5537e4..851a626 100644
--- a/arch/mips/powertv/asic/prealloc-cronuslite.c
+++ b/arch/mips/powertv/asic/prealloc-cronuslite.c
@@ -2,6 +2,7 @@
  * Memory pre-allocations for Cronus Lite boxes.
  *
  * Copyright (C) 2005-2009 Scientific-Atlanta, Inc.
+ * Copyright (C) 2009-2010 Cisco Sysems, Inc.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -24,12 +25,12 @@
 #include <linux/init.h>
 #include <linux/ioport.h>
 #include <asm/mach-powertv/asic.h>
-#include "prealloc.h"
+#include <asm/mach-powertv/powertv-prealloc.h>
 
 /*
  * NON_DVR_CAPABLE CRONUSLITE RESOURCES
  */
-struct resource non_dvr_cronuslite_resources[] __initdata =
+const struct dma_resource non_dvr_cronuslite_resources[] __initdata =
 {
 	/*
 	 * VIDEO2 / LX2
diff --git a/arch/mips/powertv/asic/prealloc-gaia.c b/arch/mips/powertv/asic/prealloc-gaia.c
index 8ac8c7a..d3f6694 100644
--- a/arch/mips/powertv/asic/prealloc-gaia.c
+++ b/arch/mips/powertv/asic/prealloc-gaia.c
@@ -2,6 +2,7 @@
  * Memory pre-allocations for Gaia boxes.
  *
  * Copyright (C) 2005-2009 Scientific-Atlanta, Inc.
+ * Copyright (C) 2009-2010 Cisco Sysems, Inc.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -22,291 +23,154 @@
 
 #include <linux/init.h>
 #include <asm/mach-powertv/asic.h>
+#include <asm/mach-powertv/powertv-prealloc.h>
 
 /*
  * DVR_CAPABLE GAIA RESOURCES
  */
-struct resource dvr_gaia_resources[] __initdata = {
+const struct dma_resource dvr_gaia_resources[] __initdata = {
 	/*
-	 *
 	 * VIDEO1 / LX1
-	 *
 	 */
-	{
-		.name   = "ST231aImage",	/* Delta-Mu 1 image and ram */
-		.start  = 0x24000000,
-		.end    = 0x241FFFFF,		/* 2MiB */
-		.flags  = IORESOURCE_MEM,
-	},
-	{
-		.name   = "ST231aMonitor",	/* 8KiB block ST231a monitor */
-		.start  = 0x24200000,
-		.end    = 0x24201FFF,
-		.flags  = IORESOURCE_MEM,
-	},
-	{
-		.name   = "MediaMemory1",
-		.start  = 0x24202000,
-		.end    = 0x25FFFFFF, /*~29.9MiB (32MiB - (2MiB + 8KiB)) */
-		.flags  = IORESOURCE_MEM,
-	},
+	/* Delta-Mu 1 image and RAM (2 MiB) */
+	PREALLOC_NORMAL("ST231aImage", 0x24000000, 0x241FFFFF, IORESOURCE_MEM)
+	/* 8KiB block ST231a monitor */
+	PREALLOC_NORMAL("ST231aMonitor", 0x24200000, 0x24201FFF, IORESOURCE_MEM)
+	/*~29.9MiB (32MiB - (2MiB + 8KiB)) */
+	PREALLOC_NORMAL("MediaMemory1", 0x24202000, 0x25FFFFFF, IORESOURCE_MEM)
 	/*
-	 *
 	 * VIDEO2 / LX2
-	 *
 	 */
-	{
-		.name   = "ST231bImage",	/* Delta-Mu 2 image and ram */
-		.start  = 0x60000000,
-		.end    = 0x601FFFFF,		/* 2MiB */
-		.flags  = IORESOURCE_IO,
-	},
-	{
-		.name   = "ST231bMonitor",	/* 8KiB block ST231b monitor */
-		.start  = 0x60200000,
-		.end    = 0x60201FFF,
-		.flags  = IORESOURCE_IO,
-	},
-	{
-		.name   = "MediaMemory2",
-		.start  = 0x60202000,
-		.end    = 0x61FFFFFF, /*~29.9MiB (32MiB - (2MiB + 8KiB)) */
-		.flags  = IORESOURCE_IO,
-	},
+	/* Delta-Mu 2 image and RAM (2 MiB)*/
+	PREALLOC_NORMAL("ST231bImage", 0x60000000, 0x601FFFFF, IORESOURCE_IO)
+	/* 8KiB block ST231b monitor */
+	PREALLOC_NORMAL("ST231bMonitor", 0x60200000, 0x60201FFF, IORESOURCE_IO)
+	/*~29.9MiB (32MiB - (2MiB + 8KiB)) */
+	PREALLOC_NORMAL("MediaMemory2", 0x60202000, 0x61FFFFFF, IORESOURCE_IO)
 	/*
-	 *
 	 * Sysaudio Driver
-	 *
 	 * This driver requires:
-	 *
 	 * Arbitrary Based Buffers:
 	 *  DSP_Image_Buff - DSP code and data images (1MB)
 	 *  ADSC_CPU_PCM_Buff - ADSC CPU PCM buffer (40KB)
 	 *  ADSC_AUX_Buff - ADSC AUX buffer (16KB)
 	 *  ADSC_Main_Buff - ADSC Main buffer (16KB)
-	 *
 	 */
-	{
-		.name   = "DSP_Image_Buff",
-		.start  = 0x00000000,
-		.end    = 0x000FFFFF,
-		.flags  = IORESOURCE_MEM,
-	},
-	{
-		.name   = "ADSC_CPU_PCM_Buff",
-		.start  = 0x00000000,
-		.end    = 0x00009FFF,
-		.flags  = IORESOURCE_MEM,
-	},
-	{
-		.name   = "ADSC_AUX_Buff",
-		.start  = 0x00000000,
-		.end    = 0x00003FFF,
-		.flags  = IORESOURCE_MEM,
-	},
-	{
-		.name   = "ADSC_Main_Buff",
-		.start  = 0x00000000,
-		.end    = 0x00003FFF,
-		.flags  = IORESOURCE_MEM,
-	},
+	PREALLOC_NORMAL("DSP_Image_Buff", 0x00000000, 0x000FFFFF,
+		IORESOURCE_MEM)
+	PREALLOC_NORMAL("ADSC_CPU_PCM_Buff", 0x00000000, 0x00009FFF,
+		IORESOURCE_MEM)
+	PREALLOC_NORMAL("ADSC_AUX_Buff", 0x00000000, 0x00003FFF, IORESOURCE_MEM)
+	PREALLOC_NORMAL("ADSC_Main_Buff", 0x00000000, 0x00003FFF,
+		IORESOURCE_MEM)
 	/*
-	 *
 	 * STAVEM driver/STAPI
-	 *
 	 * This driver requires:
-	 *
 	 * Arbitrary Based Buffers:
 	 *  This memory area is used for allocating buffers for Video decoding
 	 *  purposes.  Allocation/De-allocation within this buffer is managed
 	 *  by the STAVMEM driver of the STAPI.  They could be Decimated
 	 *  Picture Buffers, Intermediate Buffers, as deemed necessary for
 	 *  video decoding purposes, for any video decoders on Zeus.
-	 *
 	 */
-	{
-		.name   = "AVMEMPartition0",
-		.start  = 0x63580000,
-		.end    = 0x64180000 - 1,  /* 12 MB total */
-		.flags  = IORESOURCE_IO,
-	},
+	/* 12 MB total */
+	PREALLOC_NORMAL("AVMEMPartition0", 0x63580000, 0x64180000 - 1,
+		IORESOURCE_IO)
 	/*
-	 *
 	 * DOCSIS Subsystem
-	 *
 	 * This driver requires:
-	 *
 	 * Arbitrary Based Buffers:
 	 *  Docsis -
-	 *
 	 */
-	{
-		.name   = "Docsis",
-		.start  = 0x62000000,
-		.end    = 0x62700000 - 1,	/* 7 MB total */
-		.flags  = IORESOURCE_IO,
-	},
+	/* 7 MB total */
+	PREALLOC_DOCSIS("Docsis", 0x62000000, 0x62700000 - 1, IORESOURCE_IO)
 	/*
-	 *
 	 * GHW HAL Driver
-	 *
 	 * This driver requires:
-	 *
 	 * Arbitrary Based Buffers:
 	 *  GraphicsHeap - PowerTV Graphics Heap
-	 *
 	 */
-	{
-		.name   = "GraphicsHeap",
-		.start  = 0x62700000,
-		.end    = 0x63500000 - 1,	/* 14 MB total */
-		.flags  = IORESOURCE_IO,
-	},
+	/* 14 MB total */
+	PREALLOC_NORMAL("GraphicsHeap", 0x62700000, 0x63500000 - 1,
+		IORESOURCE_IO)
 	/*
-	 *
 	 * multi com buffer area
-	 *
 	 * This driver requires:
-	 *
 	 * Arbitrary Based Buffers:
 	 *  Docsis -
-	 *
 	 */
-	{
-		.name   = "MulticomSHM",
-		.start  = 0x26000000,
-		.end    = 0x26020000 - 1,
-		.flags  = IORESOURCE_MEM,
-	},
+	PREALLOC_NORMAL("MulticomSHM", 0x26000000, 0x26020000 - 1,
+		IORESOURCE_MEM)
 	/*
-	 *
 	 * DMA Ring buffer
-	 *
 	 * This driver requires:
-	 *
 	 * Arbitrary Based Buffers:
 	 *  Docsis -
-	 *
 	 */
-	{
-		.name   = "BMM_Buffer",
-		.start  = 0x00000000,
-		.end    = 0x00280000 - 1,
-		.flags  = IORESOURCE_MEM,
-	},
+	PREALLOC_NORMAL("BMM_Buffer", 0x00000000, 0x00280000 - 1,
+		IORESOURCE_MEM)
 	/*
-	 *
 	 * Display bins buffer for unit0
-	 *
 	 * This driver requires:
-	 *
 	 * Arbitrary Based Buffers:
 	 *  Display Bins for unit0
-	 *
 	 */
-	{
-		.name   = "DisplayBins0",
-		.start  = 0x00000000,
-		.end    = 0x00000FFF,		/* 4 KB total */
-		.flags  = IORESOURCE_MEM,
-	},
+	/* 4 KB total */
+	PREALLOC_NORMAL("DisplayBins0", 0x00000000, 0x00000FFF, IORESOURCE_MEM)
 	/*
-	 *
 	 * Display bins buffer
-	 *
 	 * This driver requires:
-	 *
 	 * Arbitrary Based Buffers:
 	 *  Display Bins for unit1
-	 *
 	 */
-	{
-		.name   = "DisplayBins1",
-		.start  = 0x64AD4000,
-		.end    = 0x64AD5000 - 1,  /* 4 KB total */
-		.flags  = IORESOURCE_IO,
-	},
+	 /* 4 KB total */
+	PREALLOC_NORMAL("DisplayBins1", 0x64AD4000, 0x64AD5000 - 1,
+		IORESOURCE_IO)
 	/*
-	 *
 	 * ITFS
-	 *
 	 * This driver requires:
-	 *
 	 * Arbitrary Based Buffers:
 	 *  Docsis -
-	 *
 	 */
-	{
-		.name   = "ITFS",
-		.start  = 0x64180000,
-		/* 815,104 bytes each for 2 ITFS partitions. */
-		.end    = 0x6430DFFF,
-		.flags  = IORESOURCE_IO,
-	},
+	/* 815, 104 bytes each for 2 ITFS partitions. */
+	PREALLOC_NORMAL("ITFS", 0x64180000, 0x6430DFFF, IORESOURCE_IO)
 	/*
-	 *
 	 * AVFS
-	 *
 	 * This driver requires:
-	 *
 	 * Arbitrary Based Buffers:
 	 *  Docsis -
-	 *
 	 */
-	{
-		.name   = "AvfsDmaMem",
-		.start  = 0x6430E000,
-		/* (945K * 8) = (128K *3) 5 playbacks / 3 server */
-		.end    = 0x64AD0000 - 1,
-		.flags  = IORESOURCE_IO,
-	},
-	{
-		.name   = "AvfsFileSys",
-		.start  = 0x64AD0000,
-		.end    = 0x64AD1000 - 1,  /* 4K */
-		.flags  = IORESOURCE_IO,
-	},
+	/* (945K * 8) = (128K *3) 5 playbacks / 3 server */
+	PREALLOC_NORMAL("AvfsDmaMem", 0x6430E000, 0x64AD0000 - 1, IORESOURCE_IO)
+	/* 4K */
+	PREALLOC_NORMAL("AvfsFileSys", 0x64AD0000, 0x64AD1000 - 1,
+		IORESOURCE_IO)
+	/*
+	 * PMEM
+	 * This driver requires:
+	 * Arbitrary Based Buffers:
+	 *  Persistent memory for diagnostics.
+	 */
+	PREALLOC_PMEM("DiagPersistentMemory", 0x00000000, 0x10000 - 1,
+		IORESOURCE_MEM)
 	/*
-	 *
 	 * Smartcard
-	 *
 	 * This driver requires:
-	 *
 	 * Arbitrary Based Buffers:
 	 *  Read and write buffers for Internal/External cards
-	 *
 	 */
-	{
-		.name   = "SmartCardInfo",
-		.start  = 0x64AD1000,
-		.end    = 0x64AD3800 - 1,
-		.flags  = IORESOURCE_IO,
-	},
+	PREALLOC_NORMAL("SmartCardInfo", 0x64AD1000, 0x64AD3800 - 1,
+		IORESOURCE_IO)
 	/*
-	 *
 	 * KAVNET
 	 *    NP Reset Vector - must be of the form xxCxxxxx
 	 *	   NP Image - must be video bank 1
 	 *	   NP IPC - must be video bank 2
 	 */
-	{
-		.name   = "NP_Reset_Vector",
-		.start  = 0x27c00000,
-		.end    = 0x27c01000 - 1,
-		.flags  = IORESOURCE_MEM,
-	},
-	{
-		.name   = "NP_Image",
-		.start  = 0x27020000,
-		.end    = 0x27060000 - 1,
-		.flags  = IORESOURCE_MEM,
-	},
-	{
-		.name   = "NP_IPC",
-		.start  = 0x63500000,
-		.end    = 0x63580000 - 1,
-		.flags  = IORESOURCE_IO,
-	},
+	PREALLOC_NORMAL("NP_Reset_Vector", 0x27c00000, 0x27c01000 - 1,
+		IORESOURCE_MEM)
+	PREALLOC_NORMAL("NP_Image", 0x27020000, 0x27060000 - 1, IORESOURCE_MEM)
+	PREALLOC_NORMAL("NP_IPC", 0x63500000, 0x63580000 - 1, IORESOURCE_IO)
 	/*
 	 * Add other resources here
 	 */
@@ -316,274 +180,134 @@ struct resource dvr_gaia_resources[] __initdata = {
 /*
  * NON_DVR_CAPABLE GAIA RESOURCES
  */
-struct resource non_dvr_gaia_resources[] __initdata = {
+const struct dma_resource non_dvr_gaia_resources[] __initdata = {
 	/*
-	 *
 	 * VIDEO1 / LX1
-	 *
 	 */
-	{
-		.name   = "ST231aImage",	/* Delta-Mu 1 image and ram */
-		.start  = 0x24000000,
-		.end    = 0x241FFFFF,		/* 2MiB */
-		.flags  = IORESOURCE_MEM,
-	},
-	{
-		.name   = "ST231aMonitor",	/* 8KiB block ST231a monitor */
-		.start  = 0x24200000,
-		.end    = 0x24201FFF,
-		.flags  = IORESOURCE_MEM,
-	},
-	{
-		.name   = "MediaMemory1",
-		.start  = 0x24202000,
-		.end    = 0x25FFFFFF, /*~29.9MiB (32MiB - (2MiB + 8KiB)) */
-		.flags  = IORESOURCE_MEM,
-	},
+	/* Delta-Mu 1 image and ram (2 MiB) */
+	PREALLOC_NORMAL("ST231aImage", 0x24000000, 0x241FFFFF, IORESOURCE_MEM)
+	/* 8KiB block ST231a monitor */
+	PREALLOC_NORMAL("ST231aMonitor", 0x24200000, 0x24201FFF, IORESOURCE_MEM)
+	/*~29.9MiB (32MiB - (2MiB + 8KiB)) */
+	PREALLOC_NORMAL("MediaMemory1", 0x24202000, 0x25FFFFFF, IORESOURCE_MEM)
 	/*
-	 *
 	 * VIDEO2 / LX2
-	 *
 	 */
-	{
-		.name   = "ST231bImage",	/* Delta-Mu 2 image and ram */
-		.start  = 0x60000000,
-		.end    = 0x601FFFFF,		/* 2MiB */
-		.flags  = IORESOURCE_IO,
-	},
-	{
-		.name   = "ST231bMonitor",	/* 8KiB block ST231b monitor */
-		.start  = 0x60200000,
-		.end    = 0x60201FFF,
-		.flags  = IORESOURCE_IO,
-	},
-	{
-		.name   = "MediaMemory2",
-		.start  = 0x60202000,
-		.end    = 0x61FFFFFF, /*~29.9MiB (32MiB - (2MiB + 8KiB)) */
-		.flags  = IORESOURCE_IO,
-	},
+	/* Delta-Mu 2 image and ram (2 MiB)*/
+	PREALLOC_NORMAL("ST231bImage", 0x60000000, 0x601FFFFF, IORESOURCE_IO)
+	/* 8KiB block ST231b monitor */
+	PREALLOC_NORMAL("ST231bMonitor", 0x60200000, 0x60201FFF, IORESOURCE_IO)
+	/*~29.9MiB (32MiB - (2MiB + 8KiB)) */
+	PREALLOC_NORMAL("MediaMemory2", 0x60202000, 0x61FFFFFF, IORESOURCE_IO)
 	/*
-	 *
 	 * Sysaudio Driver
-	 *
 	 * This driver requires:
-	 *
 	 * Arbitrary Based Buffers:
 	 *  DSP_Image_Buff - DSP code and data images (1MB)
 	 *  ADSC_CPU_PCM_Buff - ADSC CPU PCM buffer (40KB)
 	 *  ADSC_AUX_Buff - ADSC AUX buffer (16KB)
 	 *  ADSC_Main_Buff - ADSC Main buffer (16KB)
-	 *
 	 */
-	{
-		.name   = "DSP_Image_Buff",
-		.start  = 0x00000000,
-		.end    = 0x000FFFFF,
-		.flags  = IORESOURCE_MEM,
-	},
-	{
-		.name   = "ADSC_CPU_PCM_Buff",
-		.start  = 0x00000000,
-		.end    = 0x00009FFF,
-		.flags  = IORESOURCE_MEM,
-	},
-	{
-		.name   = "ADSC_AUX_Buff",
-		.start  = 0x00000000,
-		.end    = 0x00003FFF,
-		.flags  = IORESOURCE_MEM,
-	},
-	{
-		.name   = "ADSC_Main_Buff",
-		.start  = 0x00000000,
-		.end    = 0x00003FFF,
-		.flags  = IORESOURCE_MEM,
-	},
+	PREALLOC_NORMAL("DSP_Image_Buff", 0x00000000, 0x000FFFFF,
+		IORESOURCE_MEM)
+	PREALLOC_NORMAL("ADSC_CPU_PCM_Buff", 0x00000000, 0x00009FFF,
+		IORESOURCE_MEM)
+	PREALLOC_NORMAL("ADSC_AUX_Buff", 0x00000000, 0x00003FFF, IORESOURCE_MEM)
+	PREALLOC_NORMAL("ADSC_Main_Buff", 0x00000000, 0x00003FFF,
+		IORESOURCE_MEM)
 	/*
-	 *
 	 * STAVEM driver/STAPI
-	 *
 	 * This driver requires:
-	 *
 	 * Arbitrary Based Buffers:
 	 *  This memory area is used for allocating buffers for Video decoding
 	 *  purposes.  Allocation/De-allocation within this buffer is managed
 	 *  by the STAVMEM driver of the STAPI.  They could be Decimated
 	 *  Picture Buffers, Intermediate Buffers, as deemed necessary for
 	 *  video decoding purposes, for any video decoders on Zeus.
-	 *
 	 */
-	{
-		.name   = "AVMEMPartition0",
-		.start  = 0x63580000,
-		.end    = 0x64180000 - 1,  /* 12 MB total */
-		.flags  = IORESOURCE_IO,
-	},
+	/* 12 MB total */
+	PREALLOC_NORMAL("AVMEMPartition0", 0x63580000, 0x64180000 - 1,
+		IORESOURCE_IO)
 	/*
-	 *
 	 * DOCSIS Subsystem
-	 *
 	 * This driver requires:
-	 *
 	 * Arbitrary Based Buffers:
 	 *  Docsis -
-	 *
 	 */
-	{
-		.name   = "Docsis",
-		.start  = 0x62000000,
-		.end    = 0x62700000 - 1,	/* 7 MB total */
-		.flags  = IORESOURCE_IO,
-	},
+	/* 7 MB total */
+	PREALLOC_DOCSIS("Docsis", 0x62000000, 0x62700000 - 1, IORESOURCE_IO)
 	/*
-	 *
 	 * GHW HAL Driver
-	 *
 	 * This driver requires:
-	 *
 	 * Arbitrary Based Buffers:
 	 *  GraphicsHeap - PowerTV Graphics Heap
-	 *
 	 */
-	{
-		.name   = "GraphicsHeap",
-		.start  = 0x62700000,
-		.end    = 0x63500000 - 1,	/* 14 MB total */
-		.flags  = IORESOURCE_IO,
-	},
+	/* 14 MB total */
+	PREALLOC_NORMAL("GraphicsHeap", 0x62700000, 0x63500000 - 1,
+		IORESOURCE_IO)
 	/*
-	 *
 	 * multi com buffer area
-	 *
 	 * This driver requires:
-	 *
 	 * Arbitrary Based Buffers:
 	 *  Docsis -
-	 *
 	 */
-	{
-		.name   = "MulticomSHM",
-		.start  = 0x26000000,
-		.end    = 0x26020000 - 1,
-		.flags  = IORESOURCE_MEM,
-	},
+	PREALLOC_NORMAL("MulticomSHM", 0x26000000, 0x26020000 - 1,
+		IORESOURCE_MEM)
 	/*
-	 *
 	 * DMA Ring buffer
-	 *
 	 * This driver requires:
-	 *
 	 * Arbitrary Based Buffers:
 	 *  Docsis -
-	 *
 	 */
-	{
-		.name   = "BMM_Buffer",
-		.start  = 0x00000000,
-		.end    = 0x000AA000 - 1,
-		.flags  = IORESOURCE_MEM,
-	},
+	PREALLOC_NORMAL("BMM_Buffer", 0x00000000, 0x000AA000 - 1,
+		IORESOURCE_MEM)
 	/*
-	 *
 	 * Display bins buffer for unit0
-	 *
 	 * This driver requires:
-	 *
 	 * Arbitrary Based Buffers:
 	 *  Display Bins for unit0
-	 *
 	 */
-	{
-		.name   = "DisplayBins0",
-		.start  = 0x00000000,
-		.end    = 0x00000FFF,		/* 4 KB total */
-		.flags  = IORESOURCE_MEM,
-	},
+	/* 4 KB total */
+	PREALLOC_NORMAL("DisplayBins0", 0x00000000, 0x00000FFF, IORESOURCE_MEM)
 	/*
-	 *
 	 * Display bins buffer
-	 *
 	 * This driver requires:
-	 *
 	 * Arbitrary Based Buffers:
 	 *  Display Bins for unit1
-	 *
 	 */
-	{
-		.name   = "DisplayBins1",
-		.start  = 0x64AD4000,
-		.end    = 0x64AD5000 - 1,  /* 4 KB total */
-		.flags  = IORESOURCE_IO,
-	},
+	/* 4 KB total */
+	PREALLOC_NORMAL("DisplayBins1", 0x64AD4000, 0x64AD5000 - 1,
+		IORESOURCE_IO)
 	/*
-	 *
 	 * AVFS: player HAL memory
-	 *
-	 *
 	 */
-	{
-		.name   = "AvfsDmaMem",
-		.start  = 0x6430E000,
-		.end    = 0x645D2C00 - 1,  /* 945K * 3 for playback */
-		.flags  = IORESOURCE_IO,
-	},
+	/* 945K * 3 for playback */
+	PREALLOC_NORMAL("AvfsDmaMem", 0x6430E000, 0x645D2C00 - 1, IORESOURCE_IO)
 	/*
-	 *
 	 * PMEM
-	 *
 	 * This driver requires:
-	 *
 	 * Arbitrary Based Buffers:
 	 *  Persistent memory for diagnostics.
-	 *
 	 */
-	{
-		.name   = "DiagPersistentMemory",
-		.start  = 0x00000000,
-		.end    = 0x10000 - 1,
-		.flags  = IORESOURCE_MEM,
-	},
+	PREALLOC_PMEM("DiagPersistentMemory", 0x00000000, 0x10000 - 1,
+		IORESOURCE_MEM)
 	/*
-	 *
 	 * Smartcard
-	 *
 	 * This driver requires:
-	 *
 	 * Arbitrary Based Buffers:
 	 *  Read and write buffers for Internal/External cards
-	 *
 	 */
-	{
-		.name   = "SmartCardInfo",
-		.start  = 0x64AD1000,
-		.end    = 0x64AD3800 - 1,
-		.flags  = IORESOURCE_IO,
-	},
+	PREALLOC_NORMAL("SmartCardInfo", 0x64AD1000, 0x64AD3800 - 1,
+		IORESOURCE_IO)
 	/*
-	 *
 	 * KAVNET
 	 *    NP Reset Vector - must be of the form xxCxxxxx
 	 *	   NP Image - must be video bank 1
 	 *	   NP IPC - must be video bank 2
 	 */
-	{
-		.name   = "NP_Reset_Vector",
-		.start  = 0x27c00000,
-		.end    = 0x27c01000 - 1,
-		.flags  = IORESOURCE_MEM,
-	},
-	{
-		.name   = "NP_Image",
-		.start  = 0x27020000,
-		.end    = 0x27060000 - 1,
-		.flags  = IORESOURCE_MEM,
-	},
-	{
-		.name   = "NP_IPC",
-		.start  = 0x63500000,
-		.end    = 0x63580000 - 1,
-		.flags  = IORESOURCE_IO,
-	},
+	PREALLOC_NORMAL("NP_Reset_Vector", 0x27c00000, 0x27c01000 - 1,
+		IORESOURCE_MEM)
+	PREALLOC_NORMAL("NP_Image", 0x27020000, 0x27060000 - 1, IORESOURCE_MEM)
+	PREALLOC_NORMAL("NP_IPC", 0x63500000, 0x63580000 - 1, IORESOURCE_IO)
 	{ },
 };
diff --git a/arch/mips/powertv/asic/prealloc-zeus.c b/arch/mips/powertv/asic/prealloc-zeus.c
index 96480a2..0212f89 100644
--- a/arch/mips/powertv/asic/prealloc-zeus.c
+++ b/arch/mips/powertv/asic/prealloc-zeus.c
@@ -2,6 +2,7 @@
  * Memory pre-allocations for Zeus boxes.
  *
  * Copyright (C) 2005-2009 Scientific-Atlanta, Inc.
+ * Copyright (C) 2009-2010 Cisco Sysems, Inc.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -24,12 +25,12 @@
 #include <linux/init.h>
 #include <linux/ioport.h>
 #include <asm/mach-powertv/asic.h>
-#include "prealloc.h"
+#include <asm/mach-powertv/powertv-prealloc.h>
 
 /*
  * DVR_CAPABLE RESOURCES
  */
-struct resource dvr_zeus_resources[] __initdata =
+const struct dma_resource dvr_zeus_resources[] __initdata =
 {
 	/*
 	 * VIDEO1 / LX1
@@ -182,7 +183,7 @@ struct resource dvr_zeus_resources[] __initdata =
 /*
  * NON_DVR_CAPABLE ZEUS RESOURCES
  */
-struct resource non_dvr_zeus_resources[] __initdata =
+const struct dma_resource non_dvr_zeus_resources[] __initdata =
 {
 	/*
 	 * VIDEO1 / LX1
diff --git a/arch/mips/powertv/asic/prealloc.c b/arch/mips/powertv/asic/prealloc.c
new file mode 100644
index 0000000..f2b63aa
--- /dev/null
+++ b/arch/mips/powertv/asic/prealloc.c
@@ -0,0 +1,566 @@
+/*
+ *
+ * Description:  Preallocate large chunks of memory for drivers
+ *
+ * Copyright (C) 2005-2010 Scientific-Atlanta, Inc.
+ * Copyright (C) 2009-2010 Cisco Sysems, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <linux/init.h>
+#include <linux/bootmem.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <asm/bootinfo.h>
+#include <asm/mach-powertv/powertv-prealloc.h>
+#include <asm/mach-powertv/asic.h>
+
+/*
+ * Type Definitions
+ */
+
+const struct dma_resource *gp_resources __initdata;
+
+/* Definitions for physical memory area information. We don't have
+ * kmalloc working at this point. In fact, we don't even have the boot
+ * memory allocator, so we have no choice but to use a static allocation.
+ * In the best of all possible worlds, we might have a way to switch to
+ * the boot memory allocator, and then the slab/slob/slub allocator when
+ * they become available, but this probably isn't really worth the effort. */
+struct alloc_item {
+	struct list_head	free_areas;
+	struct painting_area	area;
+};
+
+static struct alloc_item areas[CONFIG_PREALLOCATED_AREAS_ITEMS] __initdata;
+
+static LIST_HEAD(free_areas);		/* List of avail. area allocations */
+static int areas_unallocated = ARRAY_SIZE(areas); /* # never-allocated areas */
+static loff_t	num_areas;		/* Current count of areas */
+static bool	alloc_errors;		/* Flag to indicate faulty data */
+static PAINTING(ram_painting);
+
+/*
+ * Allocate a painting_area. We do the allocation so early that we can't
+ * count on running any code to initialize the list of free areas, so we
+ * also have a counter of the number of items unused in the array of areas.
+ *
+ * Returns:	Pointer to a struct painting_area, or NULL if none is
+ * available.
+ */
+static __init struct painting_area *physmem_alloc(void)
+{
+	struct alloc_item	*item;
+	struct painting_area	*result;
+
+	/* First use anything in the areas array that hasn't been used. If
+	 * that fails, then go to our list of free areas. */
+	if (areas_unallocated != 0) {
+		areas_unallocated--;
+		item = &areas[areas_unallocated];
+	} else if (!list_empty(&free_areas)) {
+		item = list_first_entry(&free_areas, struct alloc_item,
+			free_areas);
+		list_del(&item->free_areas);
+	}
+
+	else
+		item = NULL;
+
+	/* If we failed to allocate something, then log it and return NULL.
+	 * Otherwise, return a pointer to the painting_area portion */
+	if (!item) {
+		alloc_errors = true;
+		result = NULL;
+	} else {
+		result = &item->area;
+		num_areas++;
+	}
+
+	return result;
+}
+
+/*
+ * Free a painting area
+ * @p:		Pointer to struct painting_area to free
+ */
+static __init void physmem_free(const struct painting_area *p)
+{
+	struct alloc_item	*item;
+
+	item = container_of(p, struct alloc_item, area);
+	list_add(&item->free_areas, &free_areas);
+	num_areas--;
+}
+
+/*
+ * mem_painting_add - add a painting area to a painting
+ * @this:	Pointer to the &struct painting on which we are working
+ * @desc:	Pointer to a &struct painting_desc to add.
+ *
+ * Returns zere on success, otherwise a negative errno value
+ *
+ * The approach is to start with the area preceeding the new area, then any
+ * areas that start at the same place as the new area, then all of rest of
+ * areas that start before, at, or right after the end of the new area.
+ */
+int __init mem_painting_add(struct painting *this,
+	const struct painting_desc *new_desc)
+{
+	struct painting_area *newp;	/* Area we are adding */
+	struct painting_area *cur;	/* Current area we are working on */
+	struct painting_area *next;
+	struct painting_desc new;
+	int retval = 0;
+	bool add_new = true;
+
+	new = *new_desc;		/* Make a copy so we can modify these */
+	cur = find_neighbor(this, new.p);
+
+	if (painting_have_prev(cur, &new)) {
+		next = painting_next(cur);
+
+		if (painting_prev_overlaps_or_abuts(&cur->desc, &new)) {
+			struct painting_area *tail;
+			struct painting_area *free_me;
+
+			tail = painting_must_make_hole(&cur->desc, &new) ?
+				physmem_alloc() : NULL;
+			free_me = painting_do_prev_overlaps_and_abuts(this,
+				cur, &new, tail);
+			if (IS_ERR(free_me))
+				retval = PTR_ERR(free_me);
+			else if (free_me != NULL)
+				physmem_free(free_me);
+			add_new = painting_add_area(&cur->desc, &new);
+		}
+
+		cur = next;
+	}
+
+	/* TODO: Ensure proper handling of wrap-around of value space here */
+	while (retval == 0 && cur != NULL && cur->desc.p <= new.q + 1) {
+		struct painting_area *ret;
+
+		ret = do_successor(this, cur, &new);
+		if (ret != NULL)
+			physmem_free(ret);
+
+		cur = painting_next(cur);
+	}
+
+	/*
+	 * If the new area wasn't subsumed by another area, we need to allocate
+	 * storage for it and line it in.
+	 */
+	if (retval == 0 && add_new) {
+		newp = physmem_alloc();
+		retval = finish_new_allocation(this, newp, &new);
+	}
+
+	return retval;
+}
+
+/**
+ * resource_add_ram - add actual RAM
+ * @start:	Physical address of the start of RAM
+ * @end:	Physical address of the last byte of RAM
+ *
+ * Returns zero on success, a negative errno value on failure
+ */
+int __init resource_add_ram(phys_addr_t start, phys_addr_t end)
+{
+	struct painting_desc desc;
+	int res;
+
+	desc.p = start;
+	desc.q = end;
+	desc.color = physmem_ram;
+	res = mem_painting_add(&ram_painting, &desc);
+	return res;
+}
+
+/*
+ *
+ * RESOURCE ACCESS FUNCTIONS
+ *
+ */
+
+/*
+ * lookup_root_resource - finds the right root resource for a range
+ * @start:	the physical address of start of resource.
+ * @size:	the size of resource in byte
+ *
+ * Returns a pointer to the resource or NULL upon failure. It finds the most
+ * deeply nested resource that can hold the resource we were passed.
+ */
+static __init struct resource *__init lookup_root_resource(unsigned long start,
+		unsigned long size)
+{
+	struct resource *result;
+	struct resource *res_p;
+
+	result = NULL;
+	res_p = iomem_resource.child;
+
+	while (res_p) {
+		/*
+		 * If we have a resource that can hold the resource we
+		 * were passed, remember it and then switch to scanning
+		 * its children.
+		 */
+		if ((res_p->start <= start) &&
+			(res_p->end >= (start + size - 1))) {
+			result = res_p;
+			res_p = result->child;
+		} else {
+			res_p = res_p->sibling;
+		}
+	}
+
+	if (result == NULL)
+		pr_err("Can't find root resource for resource at "
+			"0x%lx-0x%lx\n", start, start + size - 1);
+
+	return result;
+}
+
+/**
+ * platform_lookup_resource_entry - finds resource entry by name
+ * @name:	pointer to string containing name of resource
+ *
+ * Returns a pointer to the corresponding &struct resource or NULL if it
+ * couldn't find one.
+ */
+static struct resource *platform_lookup_resource_entry(const char *name)
+{
+	struct resource *p;
+	struct resource *next;
+
+	for (p = iomem_resource.child; p != NULL; p = next) {
+		if (strcmp(p->name, name) == 0)
+			return p;
+
+		next = p->child;		/* Go deeper, if possible */
+
+		if (next == NULL) {
+			next = p->sibling;	/* Go sideways, if possible */
+
+			if (next == NULL) {
+				/* Go up and, possibly, over */
+				for (next = p->parent; next != NULL;
+					next = p->parent) {
+					p = next;
+					next = p->sibling;
+					if (next != NULL)
+						break;
+				}
+			}
+		}
+	}
+
+	return NULL;
+}
+
+/*
+ * set_resource_addresses - set platform resource address information
+ * @plat_res:	Pointer to &struct resource whose addresses to are
+ *		be set
+ * @res:	Pointer to &struct dma_resource from which to get addresses.
+ *
+ * Returns true on success, false on failure.
+ */
+static __init bool set_resource_addresses(struct resource *plat_res,
+	const struct dma_resource *dma_res)
+{
+	if (platform_resource_override(plat_res, dma_res))
+		return true;
+
+	if (dma_res->start != 0) {
+		/* Have a statically defined address */
+		plat_res->start = dma_to_phys(dma_res->start);
+		plat_res->end = dma_to_phys(dma_res->end);
+
+		/* We've already warned about these */
+		if (plat_res->start >= HIGHMEM_START)
+			return false;
+	} else {
+		void *virt_start;
+		size_t size;
+
+		/* Need to allocation an address dynamically */
+
+		size = dma_res->end;
+		virt_start = kmalloc(size, GFP_KERNEL);
+		if (virt_start == NULL) {
+			pr_err("Unable to allocate memory for %s\n",
+				dma_res->name);
+			return false;
+		}
+		plat_res->start = virt_to_phys(virt_start);
+		plat_res->end = plat_res->start + size;
+	}
+
+	return true;
+}
+
+/**
+ * plat_reserve_resource_list - reserve a list of dma_resources
+ * @n:			Number of &dma_resources to reserve
+ * @dma_resources:	Pointer to the list of &struct dma_resource items
+ *
+ * Adds the list of &dma_resources to the ram_painting. This changes
+ * color from physmem_ram so that the memory areas won't be given to
+ * the boot memory allocator. Since this is called before any memory
+ * allocator is initialized, it can't allocate memory.
+ */
+void __init resource_reserve_static_prealloc(size_t n,
+	const struct dma_resource *dma_resources)
+{
+	int i;
+
+	for (i = 0; i < n; i++) {
+		const struct dma_resource *dma_res;
+		struct painting_desc desc;
+
+		dma_res = &dma_resources[i];
+
+		/* Skip anything with a dynamically-assigned address */
+		if (dma_res->start == 0)
+			continue;
+
+		desc.p = dma_to_phys(dma_res->start);
+		desc.q = dma_to_phys(dma_res->end);
+
+#ifndef CONFIG_HIGHMEM
+		if (desc.p >= HIGHMEM_START) {
+			pr_warn("No highmem--skipping reservation at %0*x "
+				"for %s\n",
+				2 * sizeof(dma_res->start), dma_res->start,
+				dma_res->name);
+			continue;
+		}
+#endif
+		desc.color = dma_res->name;
+		mem_painting_add(&ram_painting, &desc);
+	}
+}
+
+/**
+ * resource_add_memory_region - add non-preallocated ram
+ */
+void __init resource_add_memory_regions()
+{
+	struct painting_area *area;
+
+	painting_for_each_area(area, &ram_painting) {
+		struct painting_desc *desc;
+
+		desc = &area->desc;
+		add_memory_region(desc->p, desc->q - desc->p + 1,
+			(desc->color == physmem_ram) ? BOOT_MEM_RAM :
+			BOOT_MEM_RESERVED);
+	}
+}
+
+/*
+ * init_one_resource - set up resources for one preallocation
+ * @plat_res:	Pointer to &struct resource that we be set up
+ * @dma_res:	Pointer to &struct dma_resource holding the data
+ *
+ * On success, returns the number of bytes in the resources. Otherwise,
+ * returns zero.
+ */
+int __init init_one_resource(struct resource *plat_res,
+	const struct dma_resource *dma_res)
+{
+	struct resource *root_res;
+	size_t size;
+	int conflict;
+
+	if (platform_lookup_resource_entry(dma_res->name) != NULL) {
+		pr_err("resource %s has already been allocated\n",
+			dma_res->name);
+		return 0;
+	}
+
+	if (!set_resource_addresses(plat_res, dma_res))
+		return 0;
+
+	plat_res->name = kstrdup(dma_res->name, GFP_KERNEL);
+	plat_res->flags = dma_res->flags;
+	size = (plat_res->end - plat_res->start + 1);
+
+	root_res = lookup_root_resource(plat_res->start, size);
+
+	/* If there is no highmem extent root_res_p might be NULL */
+	if (root_res)
+		conflict = request_resource(root_res, plat_res);
+	else
+		conflict = -1;
+
+	if (conflict) {
+		if (request_resource(&iomem_resource, plat_res) != 0) {
+			pr_err("PTV resource request conflict "
+				"%s: 0x%x-0x%x\n",
+				plat_res->name,
+				plat_res->start,
+				plat_res->end);
+			plat_res->start = 0;
+			plat_res->end = 0;
+		}
+		return 0;
+	}
+
+	plat_res->flags |= IORESOURCE_BUSY;
+	pr_info("Reserved resource at 0x%0*x for %s (%u bytes)\n",
+		2 * sizeof(plat_res->start), plat_res->start,
+		plat_res->name, size);
+	return size;
+}
+
+/**
+ * resource_request_prealloc - reserve resources for a list of preallocs
+ * @n:			Number of resources to request
+ * @dma_resources:	Pointer of DMA resources which are to be requested
+ *
+ * Called when we can allocate memory. Requests resources corresponding
+ * to both statically and dynamically assigned addreses.
+ *
+ * Recall that memory for resources at constant addresses was not passed
+ * to the boot memory allocator, so it is already reserved. Such memory still
+ * has still has no resource associated with it. We don't have addresses
+ * for memory whose address can be dynamically defined and will have to
+ * get them.
+ *
+ * Returns the number of bytes of resources successfully requested.
+ */
+size_t __init resource_request_prealloc(size_t n,
+	const struct dma_resource *dma_resources)
+{
+	struct resource *plat_resources;
+	size_t alloc_size;
+	size_t total;
+	int i;
+
+	if (n == 0)
+		return 0;
+
+	/* Allocate an array for the result */
+	alloc_size = sizeof(*plat_resources) * n;
+	plat_resources = kmalloc(alloc_size, GFP_KERNEL | __GFP_ZERO);
+
+	if (plat_resources == NULL) {
+		pr_err("could not allocate %d bytes for platform resource "
+			"structs\n", alloc_size);
+		return 0;
+	}
+
+	total = 0;
+
+	/* Populate the array */
+	for (i = 0; i < n; i++) {
+		const struct dma_resource *dma_res;
+		struct resource *plat_res;
+		size_t size;
+
+		dma_res = &dma_resources[i];
+		plat_res = &plat_resources[i];
+
+		size = init_one_resource(plat_res, dma_res);
+		if (size > 0)
+			total += size;
+	}
+
+	return total;
+}
+
+/**
+ * platform_lookup_resource - provides start and end physical addresses
+ *	for preallocated and reserved resources for drivers.
+ *
+ * @name:	pointer to string containing name of resource
+ * @bres_p:	pointer to callers struct that addrs are copied to
+ * Returns 0 on success, a negative errno value on failure
+ *
+ */
+int platform_lookup_resource(const char *name, struct bus_resource *bres_p)
+{
+	struct resource *p;
+
+	p = platform_lookup_resource_entry(name);
+
+	if (p == NULL)
+		return -ENODEV;
+
+	bres_p->start = p->start;
+	bres_p->end = p->end;
+	return 0;
+}
+EXPORT_SYMBOL(platform_lookup_resource);
+
+/**
+ * platform_release_memory - release pre-allocated memory
+ * @ptr:	pointer to memory to release
+ * @size:	size of resource
+ * @baddr:	Bus address of memory to release
+ * @size:	size of resource, in bytes
+ *
+ * This must only be called for memory allocated or reserved via the boot
+ * or buddy memory allocators.
+ * Returns the number of bytes actually released. This must only be called
+ * for memory allocated or reserved via the boot memory allocator.
+ */
+unsigned long platform_release_memory(unsigned long baddr, int size)
+{
+	unsigned long paddr = dma_to_phys(baddr);
+	unsigned long pfn;
+	unsigned long end_pfn;
+	unsigned long pgs = 0;
+
+	pr_info("Platform_release_memory:\n");
+	pfn = PFN_UP(paddr);
+	end_pfn = PFN_DOWN(paddr + size);
+
+	for (; pfn < end_pfn; pfn++) {
+		struct page *page = pfn_to_page(pfn);
+
+		if (!pfn_valid(pfn)) {
+			pr_err("Trying to release invalid pfn:0x%lx\n", pfn);
+			BUG();
+			break;
+		}
+
+		if (!PageReserved(page)) {
+			pr_err("Trying to release page that is not"
+				" currently \"reserved\":0x%lx\n", pfn);
+			BUG();
+			break;
+		}
+
+		ClearPageReserved(page);
+		init_page_count(page);
+		__free_page(page);
+
+		totalram_pages++;
+		num_physpages++;
+		pgs++;
+	}
+
+	return pgs << PAGE_SHIFT;
+}
+EXPORT_SYMBOL(platform_release_memory);
diff --git a/arch/mips/powertv/asic/prealloc.h b/arch/mips/powertv/asic/prealloc.h
deleted file mode 100644
index 8e682df..0000000
--- a/arch/mips/powertv/asic/prealloc.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Definitions for memory preallocations
- *
- * Copyright (C) 2005-2009 Scientific-Atlanta, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * 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, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifndef _ARCH_MIPS_POWERTV_ASIC_PREALLOC_H
-#define _ARCH_MIPS_POWERTV_ASIC_PREALLOC_H
-
-#define KIBIBYTE(n) ((n) * 1024)    /* Number of kibibytes */
-#define MEBIBYTE(n) ((n) * KIBIBYTE(1024)) /* Number of mebibytes */
-
-/* "struct resource" array element definition */
-#define PREALLOC(NAME, START, END, FLAGS) {	\
-		.name = (NAME),			\
-		.start = (START),		\
-		.end = (END),			\
-		.flags = (FLAGS)		\
-	},
-
-/* Individual resources in the preallocated resource arrays are defined using
- *  macros.  These macros are conditionally defined based on their
- *  corresponding kernel configuration flag:
- *    - CONFIG_PREALLOC_NORMAL: preallocate resources for a normal settop box
- *    - CONFIG_PREALLOC_TFTP: preallocate the TFTP download resource
- *    - CONFIG_PREALLOC_DOCSIS: preallocate the DOCSIS resource
- *    - CONFIG_PREALLOC_PMEM: reserve space for persistent memory
- */
-#ifdef CONFIG_PREALLOC_NORMAL
-#define PREALLOC_NORMAL(name, start, end, flags) \
-   PREALLOC(name, start, end, flags)
-#else
-#define PREALLOC_NORMAL(name, start, end, flags)
-#endif
-
-#ifdef CONFIG_PREALLOC_TFTP
-#define PREALLOC_TFTP(name, start, end, flags) \
-   PREALLOC(name, start, end, flags)
-#else
-#define PREALLOC_TFTP(name, start, end, flags)
-#endif
-
-#ifdef CONFIG_PREALLOC_DOCSIS
-#define PREALLOC_DOCSIS(name, start, end, flags) \
-   PREALLOC(name, start, end, flags)
-#else
-#define PREALLOC_DOCSIS(name, start, end, flags)
-#endif
-
-#ifdef CONFIG_PREALLOC_PMEM
-#define PREALLOC_PMEM(name, start, end, flags) \
-   PREALLOC(name, start, end, flags)
-#else
-#define PREALLOC_PMEM(name, start, end, flags)
-#endif
-#endif
diff --git a/arch/mips/powertv/init.c b/arch/mips/powertv/init.c
index 0aac039..6ee3145 100644
--- a/arch/mips/powertv/init.c
+++ b/arch/mips/powertv/init.c
@@ -3,7 +3,7 @@
  *	All rights reserved.
  *	Authors: Carsten Langgaard <carstenl@xxxxxxxx>
  *		 Maciej W. Rozycki <macro@xxxxxxxx>
- * Portions copyright (C) 2009 Cisco Systems, Inc.
+ * Portions copyright (C) 2009-2010 Cisco Systems, Inc.
  *
  *  This program is free software; you can distribute it and/or modify it
  *  under the terms of the GNU General Public License (Version 2) as
@@ -122,7 +122,7 @@ void __init prom_init(void)
 		strlcat(arcs_cmdline, prom_argv, COMMAND_LINE_SIZE);
 	}
 
-	configure_platform();
+	powertv_platform_init();
 	prom_meminit();
 
 #ifndef CONFIG_BOOTLOADER_DRIVER
diff --git a/arch/mips/powertv/ioremap.c b/arch/mips/powertv/ioremap.c
index a77c6f6..22a5c29 100644
--- a/arch/mips/powertv/ioremap.c
+++ b/arch/mips/powertv/ioremap.c
@@ -4,6 +4,7 @@
  * Support for mapping between dma_addr_t values a phys_addr_t values.
  *
  * Copyright (C) 2005-2009 Scientific-Atlanta, Inc.
+ * Copyright (C) 2009-2010 Cisco Sysems, Inc.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -80,8 +81,17 @@ static void setup_dma_to_phys(dma_addr_t dma, phys_addr_t delta, dma_addr_t s)
 	first_idx = first >> IOR_LSBITS;		/* Convert to indices */
 	last_idx = last >> IOR_LSBITS;
 
-	for (dma_idx = first_idx; dma_idx <= last_idx; dma_idx++)
-		_ior_dma_to_phys[dma_idx].offset = delta >> IOR_DMA_SHIFT;
+	for (dma_idx = first_idx; dma_idx <= last_idx; dma_idx++) {
+		dma_addr_t offset;
+		offset = delta >> IOR_DMA_SHIFT;
+
+		if (_ior_dma_to_phys[dma_idx].offset != 0 &&
+			_ior_dma_to_phys[dma_idx].offset != offset)
+			panic("Memory remapped: DMA %x physical %x size %d\n",
+				dma, dma + delta, s);
+
+		_ior_dma_to_phys[dma_idx].offset = offset;
+	}
 }
 
 /**
@@ -104,11 +114,21 @@ static void setup_phys_to_dma(phys_addr_t phys, dma_addr_t delta, phys_addr_t s)
 	 */
 	first = phys & ~IOR_PHYS_GRAIN_MASK;
 	last = (phys + s - 1) & ~IOR_PHYS_GRAIN_MASK;
-	first_idx = first >> IOR_LSBITS;		/* Convert to indices */
+	first_idx = first >> IOR_LSBITS;	/* Convert to indices */
 	last_idx = last >> IOR_LSBITS;
 
-	for (phys_idx = first_idx; phys_idx <= last_idx; phys_idx++)
-		_ior_phys_to_dma[phys_idx].offset = delta >> IOR_PHYS_SHIFT;
+	for (phys_idx = first_idx; phys_idx <= last_idx; phys_idx++) {
+		dma_addr_t offset;
+
+		offset = delta >> IOR_PHYS_SHIFT;
+
+		if (_ior_phys_to_dma[phys_idx].offset != 0 &&
+			_ior_phys_to_dma[phys_idx].offset != offset)
+			panic("Memory remapped: physical %x DMA %x size %d\n",
+				phys, phys + delta, s);
+
+		_ior_phys_to_dma[phys_idx].offset = offset;
+	}
 }
 
 /**
@@ -120,17 +140,11 @@ static void setup_phys_to_dma(phys_addr_t phys, dma_addr_t delta, phys_addr_t s)
  * NOTE: It might be obvious, but the assumption is that all @size bytes have
  * the same offset between the physical address and the DMA address.
  */
-void ioremap_add_map(phys_addr_t phys, phys_addr_t dma, phys_addr_t size)
+void ioremap_add_map(phys_addr_t phys, dma_addr_t dma, size_t size)
 {
 	if (size == 0)
 		return;
 
-	if ((dma & IOR_DMA_GRAIN_MASK) != 0 ||
-		(phys & IOR_PHYS_GRAIN_MASK) != 0 ||
-		(size & IOR_PHYS_GRAIN_MASK) != 0)
-		pr_crit("Memory allocation must be in chunks of 0x%x bytes\n",
-			IOR_PHYS_GRAIN);
-
 	setup_dma_to_phys(dma, phys - dma, size);
 	setup_phys_to_dma(phys, dma - phys, size);
 }
diff --git a/arch/mips/powertv/memory.c b/arch/mips/powertv/memory.c
index c463cd3..6b0c10e 100644
--- a/arch/mips/powertv/memory.c
+++ b/arch/mips/powertv/memory.c
@@ -1,7 +1,7 @@
 /*
  * Carsten Langgaard, carstenl@xxxxxxxx
  * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
- * Portions copyright (C) 2009 Cisco Systems, Inc.
+ * Portions copyright (C) 2009-2010 Cisco Systems, Inc.
  *
  *  This program is free software; you can distribute it and/or modify it
  *  under the terms of the GNU General Public License (Version 2) as
@@ -25,28 +25,38 @@
 #include <linux/pfn.h>
 #include <linux/string.h>
 
-#include <asm/bootinfo.h>
 #include <asm/page.h>
 #include <asm/sections.h>
+#include <asm/setup.h>
+#include <asm/bootinfo.h>
 
 #include <asm/mips-boards/prom.h>
 #include <asm/mach-powertv/asic.h>
 #include <asm/mach-powertv/ioremap.h>
+#include <asm/mach-powertv/powertv-prealloc.h>
 
 #include "init.h"
 
 /* Memory constants */
 #define KIBIBYTE(n)		((n) * 1024)	/* Number of kibibytes */
 #define MEBIBYTE(n)		((n) * KIBIBYTE(1024)) /* Number of mebibytes */
+#define GIBIBYTE(n)		((n) * MEBIBYTE(1024)) /* Number of mebibytes */
 #define DEFAULT_MEMSIZE		MEBIBYTE(128)	/* If no memsize provided */
 
 #define BLDR_SIZE	KIBIBYTE(256)		/* Memory reserved for bldr */
 #define RV_SIZE		MEBIBYTE(4)		/* Size of reset vector */
 
-#define LOW_MEM_END	0x20000000		/* Highest low memory address */
-#define BLDR_ALIAS	0x10000000		/* Bootloader address */
-#define RV_PHYS		0x1fc00000		/* Reset vector address */
-#define LOW_RAM_END	RV_PHYS			/* End of real RAM in low mem */
+/* Predefined physical memory types */
+const char physmem_bootloader[] = "bootloader";
+const char physmem_buddy_high[] = "buddy allocator (high)";
+const char physmem_buddy_low[] = "buddy allocator (low)";
+const char physmem_mem_map[] = "page descriptors";
+const char physmem_ram[] = "RAM";
+const char physmem_reserved[] = "reserved";
+const char physmem_reset_vector[] = "reset vector";
+const char physmem_rom_data[] = "ROM data";
+const char physmem_unknown[] = "unknown type";
+const char physmem_zero_page[] = "zero page";
 
 /*
  * Very low-level conversion from processor physical address to device
@@ -57,30 +67,8 @@
 unsigned long ptv_memsize;
 
 /*
- * struct low_mem_reserved - Items in low memmory that are reserved
- * @start:	Physical address of item
- * @size:	Size, in bytes, of this item
- * @is_aliased:	True if this is RAM aliased from another location. If false,
- *		it is something other than aliased RAM and the RAM in the
- *		unaliased address is still visible outside of low memory.
- */
-struct low_mem_reserved {
-	phys_addr_t	start;
-	phys_addr_t	size;
-	bool		is_aliased;
-};
-
-/*
- * Must be in ascending address order
- */
-struct low_mem_reserved low_mem_reserved[] = {
-	{BLDR_ALIAS, BLDR_SIZE, true},	/* Bootloader RAM */
-	{RV_PHYS, RV_SIZE, false},	/* Reset vector */
-};
-
-/*
  * struct mem_layout - layout of a piece of the system RAM
- * @phys:	Physical address of the start of this piece of RAM. This is the
+ * @dma:	Physical address of the start of this piece of RAM. This is the
  *		address at which both the processor and I/O devices see the
  *		RAM.
  * @alias:	Alias of this piece of memory in order to make it appear in
@@ -89,9 +77,9 @@ struct low_mem_reserved low_mem_reserved[] = {
  * @size:	Size, in bytes, of this piece of RAM
  */
 struct mem_layout {
-	phys_addr_t	phys;
+	dma_addr_t	dma;
 	phys_addr_t	alias;
-	phys_addr_t	size;
+	size_t		size;
 };
 
 /*
@@ -106,27 +94,32 @@ struct mem_layout_list {
 	struct mem_layout	*layout;
 };
 
-static struct mem_layout f1500_layout[] = {
+static struct mem_layout f1500_layout[] __initdata = {
 	{0x20000000, 0x10000000, MEBIBYTE(256)},
 };
 
-static struct mem_layout f4500_layout[] = {
+static struct mem_layout f4500_layout[] __initdata = {
 	{0x40000000, 0x10000000, MEBIBYTE(256)},
 	{0x20000000, 0x20000000, MEBIBYTE(32)},
 };
 
-static struct mem_layout f8500_layout[] = {
+static struct mem_layout f8500_layout[] __initdata = {
 	{0x40000000, 0x10000000, MEBIBYTE(256)},
 	{0x20000000, 0x20000000, MEBIBYTE(32)},
 	{0x30000000, 0x30000000, MEBIBYTE(32)},
 };
 
-static struct mem_layout fx600_layout[] = {
+static struct mem_layout fx600_layout[] __initdata = {
 	{0x20000000, 0x10000000, MEBIBYTE(256)},
 	{0x60000000, 0x60000000, MEBIBYTE(128)},
 };
 
-static struct mem_layout_list layout_list[] = {
+static struct mem_layout fx700_layout[] __initdata = {
+	{0x20000000, 0x10000000, GIBIBYTE(1)},
+	{0x60000000, 0x60000000, GIBIBYTE(1)},
+};
+
+static struct mem_layout_list layout_list[] __initdata = {
 	{FAMILY_1500, ARRAY_SIZE(f1500_layout), f1500_layout},
 	{FAMILY_1500VZE, ARRAY_SIZE(f1500_layout), f1500_layout},
 	{FAMILY_1500VZF, ARRAY_SIZE(f1500_layout), f1500_layout},
@@ -137,26 +130,15 @@ static struct mem_layout_list layout_list[] = {
 	{FAMILY_4600VZA, ARRAY_SIZE(fx600_layout), fx600_layout},
 	{FAMILY_8600, ARRAY_SIZE(fx600_layout), fx600_layout},
 	{FAMILY_8600VZB, ARRAY_SIZE(fx600_layout), fx600_layout},
+	{FAMILY_8700, ARRAY_SIZE(fx600_layout), fx700_layout},
 };
 
 /* If we can't determine the layout, use this */
-static struct mem_layout default_layout[] = {
+static struct mem_layout default_layout[] __initdata = {
 	{0x20000000, 0x10000000, MEBIBYTE(128)},
 };
 
 /**
- * register_non_ram - register low memory not available for RAM usage
- */
-static __init void register_non_ram(void)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(low_mem_reserved); i++)
-		add_memory_region(low_mem_reserved[i].start,
-			low_mem_reserved[i].size, BOOT_MEM_RESERVED);
-}
-
-/**
  * get_memsize - get the size of memory as a single bank
  */
 static phys_addr_t get_memsize(void)
@@ -201,91 +183,7 @@ static phys_addr_t get_memsize(void)
 }
 
 /**
- * register_low_ram - register an aliased section of RAM
- * @p:		Alias address of memory
- * @n:		Number of bytes in this section of memory
- *
- * Returns the number of bytes registered
- *
- */
-static __init phys_addr_t register_low_ram(phys_addr_t p, phys_addr_t n)
-{
-	phys_addr_t s;
-	int i;
-	phys_addr_t orig_n;
-
-	orig_n = n;
-
-	BUG_ON(p + n > RV_PHYS);
-
-	for (i = 0; n != 0 && i < ARRAY_SIZE(low_mem_reserved); i++) {
-		phys_addr_t start;
-		phys_addr_t size;
-
-		start = low_mem_reserved[i].start;
-		size = low_mem_reserved[i].size;
-
-		/* Handle memory before this low memory section */
-		if (p < start) {
-			phys_addr_t s;
-			s = min(n, start - p);
-			add_memory_region(p, s, BOOT_MEM_RAM);
-			p += s;
-			n -= s;
-		}
-
-		/* Handle the low memory section itself. If it's aliased,
-		 * we reduce the number of byes left, but if not, the RAM
-		 * is available elsewhere and we don't reduce the number of
-		 * bytes remaining. */
-		if (p == start) {
-			if (low_mem_reserved[i].is_aliased) {
-				s = min(n, size);
-				n -= s;
-				p += s;
-			} else
-				p += n;
-		}
-	}
-
-	return orig_n - n;
-}
-
-/*
- * register_ram - register real RAM
- * @p:	Address of memory as seen by devices
- * @alias:	If the memory is seen at an additional address by the processor,
- *		this will be the address, otherwise it is the same as @p.
- * @n:		Number of bytes in this section of memory
- */
-static __init void register_ram(phys_addr_t p, phys_addr_t alias,
-	phys_addr_t n)
-{
-	/*
-	 * If some or all of this memory has an alias, break it into the
-	 * aliased and non-aliased portion.
-	 */
-	if (p != alias) {
-		phys_addr_t alias_size;
-		phys_addr_t registered;
-
-		alias_size = min(n, LOW_RAM_END - alias);
-		registered = register_low_ram(alias, alias_size);
-		ioremap_add_map(alias, p, n);
-		n -= registered;
-		p += registered;
-	}
-
-#ifdef CONFIG_HIGHMEM
-	if (n != 0) {
-		add_memory_region(p, n, BOOT_MEM_RAM);
-		ioremap_add_map(p, p, n);
-	}
-#endif
-}
-
-/**
- * register_address_space - register things in the address space
+ * register_raw_ram - register things in the address space
  * @memsize:	Number of bytes of RAM installed
  *
  * Takes the given number of bytes of RAM and registers as many of the regions,
@@ -294,19 +192,13 @@ static __init void register_ram(phys_addr_t p, phys_addr_t alias,
  * is 384 MiB, it will register the first region with 256 MiB and the second
  * with 128 MiB.
  */
-static __init void register_address_space(phys_addr_t memsize)
+static void __init register_raw_ram(phys_addr_t memsize)
 {
-	int i;
-	phys_addr_t size;
-	size_t n;
 	struct mem_layout *layout;
+	int num_layouts;
 	enum family_type family;
-
-	/*
-	 * Register all of the things that aren't available to the kernel as
-	 * memory.
-	 */
-	register_non_ram();
+	int res;
+	int i;
 
 	/* Find the appropriate memory description */
 	family = platform_get_family();
@@ -317,16 +209,27 @@ static __init void register_address_space(phys_addr_t memsize)
 	}
 
 	if (i == ARRAY_SIZE(layout_list)) {
-		n = ARRAY_SIZE(default_layout);
+		num_layouts = ARRAY_SIZE(default_layout);
 		layout = default_layout;
 	} else {
-		n = layout_list[i].n;
+		num_layouts = layout_list[i].n;
 		layout = layout_list[i].layout;
 	}
 
-	for (i = 0; memsize != 0 && i < n; i++) {
+	/* Add all possible RAM */
+	for (i = 0; memsize != 0 && i < num_layouts; i++) {
+		dma_addr_t dma;
+		phys_addr_t alias;
+		size_t size;
+
+		dma = layout[i].dma;
+		alias = layout[i].alias;
 		size = min(memsize, layout[i].size);
-		register_ram(layout[i].phys, layout[i].alias, size);
+
+		ioremap_add_map(alias, dma, size);
+		res = resource_add_ram(alias, alias + size - 1);
+		if (res != 0)
+			break;
 		memsize -= size;
 	}
 }
@@ -334,7 +237,9 @@ static __init void register_address_space(phys_addr_t memsize)
 void __init prom_meminit(void)
 {
 	ptv_memsize = get_memsize();
-	register_address_space(ptv_memsize);
+	register_raw_ram(ptv_memsize);
+	register_available_ram();
+
 }
 
 void __init prom_free_prom_memory(void)
diff --git a/arch/mips/powertv/powertv_setup.c b/arch/mips/powertv/powertv_setup.c
index af2cae0..f430156 100644
--- a/arch/mips/powertv/powertv_setup.c
+++ b/arch/mips/powertv/powertv_setup.c
@@ -1,7 +1,7 @@
 /*
  * Carsten Langgaard, carstenl@xxxxxxxx
  * Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
- * Portions copyright (C) 2009 Cisco Systems, Inc.
+ * Portions copyright (C) 2009-2010  Cisco Systems, Inc.
  *
  *  This program is free software; you can distribute it and/or modify it
  *  under the terms of the GNU General Public License (Version 2) as
@@ -36,6 +36,8 @@
 #include <asm/asm.h>
 #include <asm/traps.h>
 #include <asm/asm-offsets.h>
+#include <asm/mach-powertv/asic.h>
+#include <asm/mach-powertv/prealloc.h>
 #include "reset.h"
 
 #define VAL(n)		STR(n)



[Index of Archives]     [Linux MIPS Home]     [LKML Archive]     [Linux ARM Kernel]     [Linux ARM]     [Linux]     [Git]     [Yosemite News]     [Linux SCSI]     [Linux Hams]

  Powered by Linux