Merge remote-tracking branch 'gfiber-internal/nightingale' into nightingale_merge
diff --git a/arch/mips/brcmstb/Makefile b/arch/mips/brcmstb/Makefile
index 1e0280c..e22022a 100644
--- a/arch/mips/brcmstb/Makefile
+++ b/arch/mips/brcmstb/Makefile
@@ -4,3 +4,5 @@
 obj-$(CONFIG_SMP)	+= smp.o
 obj-$(CONFIG_BRCM_HAS_STANDBY)	+= standby.o
 obj-$(CONFIG_BRCM_HAS_AON) += s3_standby.o s3.o
+obj-$(CONFIG_BRUNO)		+= partitionmap.o
+obj-$(CONFIG_REPARTITION)	+= repartition.o
diff --git a/arch/mips/brcmstb/partitionmap.c b/arch/mips/brcmstb/partitionmap.c
new file mode 100644
index 0000000..6dd6374
--- /dev/null
+++ b/arch/mips/brcmstb/partitionmap.c
@@ -0,0 +1,264 @@
+/*
+ *  Copyright (C) 2012 Google Inc. All Rights Reserved.
+ *
+ *  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.
+ *
+ *  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.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+#ifdef CONFIG_BRUNO
+#include <linux/types.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/physmap.h>
+#include <linux/mtd/map.h>
+#include <linux/platform_device.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include "partitionmap.h"
+
+#define CFE_NAME         "cfe"
+#define HNVRAM_NAME      "hnvram"
+#define RESERVED0_NAME   "reserved0"
+#define RESERVED1_NAME   "reserved1"
+#define RESERVED2_NAME   "reserved2"
+#define RESERVED3_NAME   "reserved3"
+#define RESERVED4_NAME   "reserved4"
+#define DRMREGION0_NAME  "drmregion0"
+#define DRMREGION1_NAME  "drmregion1"
+#define NVRAM_NAME       "nvram"
+
+#define KERNEL0_NAME     "kernel0"
+#define KERNEL1_NAME     "kernel1"
+#define ROOTFS0_NAME     "rootfs0"
+#define ROOTFS1_NAME     "rootfs1"
+#define DATA_NAME        "data+ubi"
+#define MISC_NAME        "misc+ubi"
+#define EMERGENCY_NAME   "emergency"
+
+#define CFE_SIZE         0x00200000UL
+#define HNVRAM_SIZE      0x00170000UL
+#define RESERVED0_SIZE   0x00010000UL
+#define RESERVED1_SIZE   0x00010000UL
+#define RESERVED2_SIZE   0x00010000UL
+#define RESERVED3_SIZE   0x00010000UL
+#define RESERVED4_SIZE   0x00010000UL
+#define DRMREGION0_SIZE  0x00010000UL
+#define DRMREGION1_SIZE  0x00010000UL
+#define NVRAM_SIZE       0x00020000UL
+
+#define KERNEL0_SIZE_V1     0x10000000UL
+#define KERNEL1_SIZE_V1     0x10000000UL
+#define ROOTFS0_SIZE_V1     0x40000000UL
+#define ROOTFS1_SIZE_V1     0x40000000UL
+#define DATA_SIZE_V1        0x40000000UL
+#define MISC_SIZE_V1        0x20000000UL
+
+#define KERNEL0_SIZE_V2     0x02000000UL
+#define KERNEL1_SIZE_V2     0x02000000UL
+#define ROOTFS0_SIZE_V2     0x12000000UL
+#define ROOTFS1_SIZE_V2     0x12000000UL
+#define EMERGENCY_SIZE_V2   0x02000000UL
+#define DATA_SIZE_V2        0x15F00000UL
+
+#define CFE_OFFSET          0x00000000UL
+#define HNVRAM_OFFSET       (CFE_OFFSET+CFE_SIZE)
+#define RESERVED0_OFFSET    (HNVRAM_OFFSET+HNVRAM_SIZE)
+#define RESERVED1_OFFSET    (RESERVED0_OFFSET+RESERVED0_SIZE)
+#define RESERVED2_OFFSET    (RESERVED1_OFFSET+RESERVED1_SIZE)
+#define RESERVED3_OFFSET    (RESERVED2_OFFSET+RESERVED2_SIZE)
+#define RESERVED4_OFFSET    (RESERVED3_OFFSET+RESERVED3_SIZE)
+#define DRMREGION0_OFFSET   (RESERVED4_OFFSET+RESERVED4_SIZE)
+#define DRMREGION1_OFFSET   (DRMREGION0_OFFSET+DRMREGION0_SIZE)
+#define NVRAM_OFFSET        (DRMREGION1_OFFSET+DRMREGION1_SIZE)
+
+#define KERNEL0_OFFSET_V1   0x00000000UL
+#define KERNEL1_OFFSET_V1   (KERNEL0_OFFSET_V1+KERNEL0_SIZE_V1)
+#define ROOTFS0_OFFSET_V1   (KERNEL1_OFFSET_V1+KERNEL1_SIZE_V1)
+#define ROOTFS1_OFFSET_V1   (ROOTFS0_OFFSET_V1+ROOTFS0_SIZE_V1)
+#define DATA_OFFSET_V1      (ROOTFS1_OFFSET_V1+ROOTFS1_SIZE_V1)
+#define MISC_OFFSET_V1      (DATA_OFFSET_V1+DATA_SIZE_V1)
+
+#define KERNEL0_OFFSET_V2   0x00000000UL
+#define KERNEL1_OFFSET_V2   (KERNEL0_OFFSET_V2+KERNEL0_SIZE_V2)
+#define ROOTFS0_OFFSET_V2   (KERNEL1_OFFSET_V2+KERNEL1_SIZE_V2)
+#define ROOTFS1_OFFSET_V2   (ROOTFS0_OFFSET_V2+ROOTFS0_SIZE_V2)
+#define EMERGENCY_OFFSET_V2 (ROOTFS1_OFFSET_V2+ROOTFS1_SIZE_V2)
+#define DATA_OFFSET_V2      (EMERGENCY_OFFSET_V2+EMERGENCY_SIZE_V2)
+
+/* Partition map V1 */
+static struct mtd_partition fixed_nor_partition_map_v1[] =
+{
+	{name: CFE_NAME, size: CFE_SIZE, offset: CFE_OFFSET},
+	{name: HNVRAM_NAME, size: HNVRAM_SIZE, offset: HNVRAM_OFFSET},
+	{name: RESERVED0_NAME, size: RESERVED0_SIZE, offset: RESERVED0_OFFSET},
+	{name: RESERVED1_NAME, size: RESERVED1_SIZE, offset: RESERVED1_OFFSET},
+	{name: RESERVED2_NAME, size: RESERVED2_SIZE, offset: RESERVED2_OFFSET},
+	{name: RESERVED3_NAME, size: RESERVED3_SIZE, offset: RESERVED3_OFFSET},
+	{name: RESERVED4_NAME, size: RESERVED4_SIZE, offset: RESERVED4_OFFSET},
+	{name: DRMREGION0_NAME, size: DRMREGION0_SIZE, offset: DRMREGION0_OFFSET},
+	{name: DRMREGION1_NAME, size: DRMREGION1_SIZE, offset: DRMREGION1_OFFSET},
+	{name: NVRAM_NAME, size: NVRAM_SIZE, offset: NVRAM_OFFSET }
+};
+
+static struct mtd_partition fixed_nand_partition_map_v1[] =
+{
+	{name: KERNEL0_NAME, size: KERNEL0_SIZE_V1, offset: KERNEL0_OFFSET_V1},
+	{name: KERNEL1_NAME, size: KERNEL1_SIZE_V1, offset: KERNEL1_OFFSET_V1},
+	{name: ROOTFS0_NAME, size: ROOTFS0_SIZE_V1, offset: ROOTFS0_OFFSET_V1},
+	{name: ROOTFS1_NAME, size: ROOTFS1_SIZE_V1, offset: ROOTFS1_OFFSET_V1},
+	{name: DATA_NAME, size: DATA_SIZE_V1, offset: DATA_OFFSET_V1},
+	{name: MISC_NAME, size: MISC_SIZE_V1, offset: MISC_OFFSET_V1}
+};
+
+/* Partition map V2 */
+#define fixed_nor_partition_map_v2 fixed_nor_partition_map_v1
+static struct mtd_partition fixed_nand_partition_map_v2[] =
+{
+	{name: KERNEL0_NAME, size: KERNEL0_SIZE_V2, offset: KERNEL0_OFFSET_V2},
+	{name: KERNEL1_NAME, size: KERNEL1_SIZE_V2, offset: KERNEL1_OFFSET_V2},
+	{name: ROOTFS0_NAME, size: ROOTFS0_SIZE_V2, offset: ROOTFS0_OFFSET_V2},
+	{name: ROOTFS1_NAME, size: ROOTFS1_SIZE_V2, offset: ROOTFS1_OFFSET_V2},
+	{name: EMERGENCY_NAME, size: DATA_SIZE_V2, offset: EMERGENCY_OFFSET_V2},
+	{name: DATA_NAME, size: DATA_SIZE_V2, offset: DATA_OFFSET_V2}
+};
+
+/* By default, use partition map v2. */
+struct mtd_partition *fixed_nor_partition_map = fixed_nor_partition_map_v1;
+int fixed_nor_partition_map_size = ARRAY_SIZE(fixed_nor_partition_map_v1);
+
+struct mtd_partition *fixed_nand_partition_map = fixed_nand_partition_map_v2;
+int fixed_nand_partition_map_size = ARRAY_SIZE(fixed_nand_partition_map_v2);
+
+static DEFINE_MUTEX(partitionmap_mutex);
+static struct list_head mtd_dev_list = LIST_HEAD_INIT(mtd_dev_list);
+
+int partitionmap_version = 2;	/* partition map version */
+EXPORT_SYMBOL(partitionmap_version);
+
+struct mtd_dev_entry {
+	struct list_head list;
+	struct platform_device *pdev;
+};
+
+size_t partitionmap_print_info(char *buffer, size_t size)
+{
+	size_t ret;
+        size_t pos = 0;
+	struct mtd_dev_entry *mtd;
+
+	ret = scnprintf(buffer + pos, size - pos,
+			"Partition map version: %d\n",
+                        partitionmap_version);
+	if (!ret)
+		return 0;
+
+	pos += ret;
+	mutex_lock(&partitionmap_mutex);
+
+	list_for_each_entry(mtd, &mtd_dev_list, list) {
+		if (pos < size) {
+			ret = (size_t)scnprintf(buffer + pos, size - pos,
+						"%s\n",
+						dev_name(&mtd->pdev->dev));
+		} else {
+			ret = 0;
+		}
+		if (!ret) {
+			mutex_unlock(&partitionmap_mutex);
+			return ret;
+		}
+		pos += ret;
+	}
+
+	mutex_unlock(&partitionmap_mutex);
+
+	return pos;
+}
+EXPORT_SYMBOL(partitionmap_print_info);
+
+int switch_partition(int pver) {
+	if (partitionmap_version == pver) {
+		return 1;
+	}
+
+	switch (pver) {
+		case 1:
+			fixed_nor_partition_map = fixed_nor_partition_map_v1;
+			fixed_nor_partition_map_size =
+					ARRAY_SIZE(fixed_nor_partition_map_v1);
+			fixed_nand_partition_map = fixed_nand_partition_map_v1;
+			fixed_nand_partition_map_size =
+					ARRAY_SIZE(fixed_nand_partition_map_v1);
+			break;
+		case 2:
+			fixed_nor_partition_map = fixed_nor_partition_map_v2;
+			fixed_nor_partition_map_size =
+					ARRAY_SIZE(fixed_nor_partition_map_v2);
+			fixed_nand_partition_map = fixed_nand_partition_map_v2;
+			fixed_nand_partition_map_size =
+					ARRAY_SIZE(fixed_nand_partition_map_v2);
+			break;
+		default:
+			/* Keep the default setting */
+			pr_info("Invalid partition version %d, ignore.\n", pver);
+			return 2;
+	}
+	pr_info("Switched partition from version %d to version %d.\n",
+                partitionmap_version, pver);
+        partitionmap_version = pver;
+	return 0;
+}
+EXPORT_SYMBOL(switch_partition);
+
+void register_nand(struct platform_device *pdev)
+{
+	struct mtd_dev_entry* obj = (struct mtd_dev_entry *)
+			kmalloc(sizeof(struct mtd_dev_entry), GFP_KERNEL);
+
+	if (!obj)
+		panic("Insufficient memory to allocate MTD device entry\n");
+
+	obj->pdev = pdev;
+
+	mutex_lock(&partitionmap_mutex);
+	list_add(&obj->list, &mtd_dev_list);
+	mutex_unlock(&partitionmap_mutex);
+}
+EXPORT_SYMBOL(register_nand);
+
+void flush_nand(void)
+{
+	struct mtd_dev_entry *mtd;
+	struct list_head *pos, *q;
+
+	mutex_lock(&partitionmap_mutex);
+	list_for_each_safe(pos, q, &mtd_dev_list){
+		mtd= list_entry(pos, struct mtd_dev_entry, list);
+		pr_info("Remove mtd device '%s'.\n", dev_name(&mtd->pdev->dev));
+		platform_device_unregister(mtd->pdev);
+		list_del(pos);
+		kfree(mtd);
+	}
+	mutex_unlock(&partitionmap_mutex);
+}
+EXPORT_SYMBOL(flush_nand);
+
+static int __init partitionver_setup(char *options)
+{
+	int pver;
+        char* endp;
+	if (*options == 0)
+		return 0;
+	pver = simple_strtol(options, &endp, 10);
+	switch_partition(pver);
+	return 0;
+}
+__setup("partitionver=", partitionver_setup);
+
+#endif  /* CONFIG_BRUNO */
diff --git a/arch/mips/brcmstb/partitionmap.h b/arch/mips/brcmstb/partitionmap.h
new file mode 100644
index 0000000..4c1ecab
--- /dev/null
+++ b/arch/mips/brcmstb/partitionmap.h
@@ -0,0 +1,27 @@
+/*
+ *  Copyright (C) 2012 Google Inc. All Rights Reserved.
+ *
+ *  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.
+ *
+ *  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.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+#ifndef __PARTITIONMAP_H__
+#define __PARTITIONMAP_H__
+
+extern int partitionmap_version;
+extern int fixed_nor_partition_map_size;
+extern int fixed_nand_partition_map_size;
+extern struct mtd_partition *fixed_nor_partition_map;
+extern struct mtd_partition *fixed_nand_partition_map;
+extern size_t partitionmap_print_info(char *buffer, size_t size);
+extern int switch_partition(int pver);
+extern void register_nand(struct platform_device *pdev);
+extern void flush_nand(void);
+
+#endif  /* __PARTITIONMAP_H__ */
diff --git a/arch/mips/brcmstb/repartition.c b/arch/mips/brcmstb/repartition.c
new file mode 100644
index 0000000..cfb9d13
--- /dev/null
+++ b/arch/mips/brcmstb/repartition.c
@@ -0,0 +1,197 @@
+/*
+ *  Copyright (C) 2012 Google Inc. All Rights Reserved.
+ *
+ *  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.
+ *
+ *  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.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+#ifdef CONFIG_REPARTITION
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/platform_device.h>
+#include <linux/kernel.h>
+#include <linux/sysctl.h>
+#include <linux/proc_fs.h>
+#include <linux/init.h>
+#include "partitionmap.h"
+#include "repartition.h"
+
+#define PARTITIONMAP_STR_SIZE 512
+
+static const char repartition_proc_name[] = "repartition";
+
+static struct repartition_sysctl_setting {
+	char info[PARTITIONMAP_STR_SIZE];   /* partition map info */
+	int version;
+	int disable;
+	int disable_min;
+	int disable_max;
+} setting = {
+	.disable = 0,
+	.disable_min = 0,
+	.disable_max = 1,
+};
+
+static struct ctl_table_header *repartition_sysctl_header;
+
+static int repartition_print_info(void)
+{
+	int ret = partitionmap_print_info(setting.info, sizeof(setting.info));
+	if (!ret)
+		return 1;
+
+	return 0;
+}
+
+static void reinit_nand(void)
+{
+	flush_nand();
+	init_nand();
+}
+
+static int repartition_sysctl_info(ctl_table *ctl, int write,
+				    void __user *buffer, size_t *lenp,
+				    loff_t *ppos)
+{
+	if (!*lenp || (*ppos && !write)) {
+		*lenp = 0;
+		return 0;
+	}
+
+	if(repartition_print_info()) {
+		*lenp = 0;
+		pr_err("insufficient info buffer\n");
+		return -ENOMEM;
+	}
+	proc_dostring(ctl, write, buffer, lenp, ppos);
+        return 0;
+}
+
+static int repartition_sysctl_version(ctl_table *ctl, int write,
+				      void __user *buffer, size_t *lenp,
+				      loff_t *ppos)
+{
+	int ret = 0;
+	if (write) {
+		if (setting.disable) {
+			pr_err("repartition is disabled\n");
+			return -EINVAL;
+		}
+		ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
+		if (0 == switch_partition(setting.version)) {
+			reinit_nand();
+		}
+	} else {
+		setting.version = partitionmap_version;
+		ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
+	}
+	return ret;
+}
+
+static int repartition_sysctl_disable(ctl_table *ctl, int write,
+				      void __user *buffer, size_t *lenp,
+				      loff_t *ppos)
+{
+	int ret = 0;
+	if (write && setting.disable) {
+		pr_err("repartition is disabled\n");
+		return -EINVAL;
+	}
+	ret = proc_dointvec_minmax(ctl, write, buffer, lenp, ppos);
+	return ret;
+}
+
+static ctl_table repartition_data_table[] = {
+	{
+		.procname       = "info",
+		.data           = setting.info,
+		.maxlen         = PARTITIONMAP_STR_SIZE,
+		.mode           = 0444,
+		.proc_handler   = repartition_sysctl_info,
+	},
+	{
+		.procname       = "disable",
+		.data           = &setting.disable,
+		.maxlen         = sizeof(int),
+		.mode           = 0644,
+		.extra1		= &setting.disable_min,
+		.extra2		= &setting.disable_max,
+		.proc_handler   = repartition_sysctl_disable,
+	},
+	{
+		.procname       = "version",
+		.data           = &setting.version,
+		.maxlen         = sizeof(int),
+		.mode           = 0644,
+		.proc_handler   = repartition_sysctl_version,
+	},
+	{ }
+};
+
+static ctl_table repartition_dir_table[] = {
+	{
+		.procname     = repartition_proc_name,
+		.mode         = 0555,
+		.child        = repartition_data_table
+	},
+	{ }
+};
+
+/* Make sure that /proc/sys/dev is there */
+static ctl_table repartition_root_table[] = {
+	{
+		.procname       = "dev",
+		.maxlen         = 0,
+		.mode           = 0555,
+		.child          = repartition_dir_table,
+	},
+	{ }
+};
+
+static int __init repartition_init(void)
+{
+	static int initialized;
+
+	if (initialized == 1)
+		return 0;
+
+	repartition_sysctl_header =
+			register_sysctl_table(repartition_root_table);
+	initialized = 1;
+	return 0;
+}
+
+static int __init partitionver_setup(char *options)
+{
+	int pver;
+        char* endp;
+	if (*options == 0)
+		return 0;
+	pver = simple_strtol(options, &endp, 10);
+	switch_partition(pver);
+	return 0;
+}
+__setup("partitionver=", partitionver_setup);
+
+#ifdef MODULE
+static int __exit repartition_exit(void)
+{
+	if (repartition_sysctl_header)
+		unregister_sysctl_table(repartition_sysctl_header);
+        return 0;
+}
+module_exit(repartition_exit);
+#endif  /* MODULE */
+
+module_init(repartition_init);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Ke Dong <kedong@google.com>");
+MODULE_DESCRIPTION("Partition map");
+
+#endif  /* CONFIG_REPARTITION */
diff --git a/arch/mips/brcmstb/repartition.h b/arch/mips/brcmstb/repartition.h
new file mode 100644
index 0000000..15a5a6d
--- /dev/null
+++ b/arch/mips/brcmstb/repartition.h
@@ -0,0 +1,22 @@
+/*
+ *  Copyright (C) 2012 Google Inc. All Rights Reserved.
+ *
+ *  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.
+ *
+ *  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.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+#ifndef __REPARTITION_H__
+#define __REPARTITION_H__
+
+extern void register_nand(struct platform_device *pdev);
+/* init_nand is defined in setup.c, because most of the code uses the local
+ * variable cs_info and local function brcm_setup_cs in setup.c. */
+extern void init_nand(void);
+
+#endif  /* __REPARTITION_H__ */
diff --git a/arch/mips/brcmstb/setup.c b/arch/mips/brcmstb/setup.c
index 151bbd2..f3c70ea 100644
--- a/arch/mips/brcmstb/setup.c
+++ b/arch/mips/brcmstb/setup.c
@@ -56,6 +56,7 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/physmap.h>
 #include <linux/mtd/map.h>
+#include "partitionmap.h"
 
 /* Default SPI flash chip selects to scan at boot time
    Can be overriden with spics=N kernel boot argument
@@ -639,6 +640,7 @@
 #define TYPE_SPI		3
 #define TYPE_MAX		TYPE_SPI
 
+static int nand_id = 0;
 static const char type_names[][8] = { "NONE", "NOR", "NAND", "SPI" };
 
 struct ebi_cs_info {
@@ -741,7 +743,7 @@
 
 __setup("spics", spics_setup);
 
-static void __init brcm_setup_cs(int cs, int nr_parts,
+static void brcm_setup_cs(int cs, int nr_parts,
 	struct mtd_partition *parts)
 {
 	struct platform_device *pdev;
@@ -775,7 +777,6 @@
 	}
 	case TYPE_NAND: {
 		struct brcmnand_platform_data pdata;
-		static int nand_id;
 
 		pdata.chip_select = cs;
 		pdata.nr_parts = nr_parts;
@@ -786,6 +787,8 @@
 		    platform_device_add_data(pdev, &pdata, sizeof(pdata)) ||
 		    platform_device_add(pdev))
 			platform_device_put(pdev);
+                else
+			register_nand(pdev);
 		break;
 	}
 	case TYPE_SPI: {
@@ -826,97 +829,47 @@
 static int __initdata noflash;
 static int __initdata nandcs[NUM_CS];
 
-/***********************************************************************
- * Platform BRUNO GFHD100 specific setup
- ***********************************************************************/
-#ifdef CONFIG_BRUNO
-#ifdef CONFIG_BRUNO_GFHD100
-#define BRUNO_CFE_NAME         "cfe"
-#define BRUNO_HNVRAM_NAME      "hnvram"
-#define BRUNO_RESERVED0_NAME   "reserved0"
-#define BRUNO_RESERVED1_NAME   "reserved1"
-#define BRUNO_RESERVED2_NAME   "reserved2"
-#define BRUNO_RESERVED3_NAME   "reserved3"
-#define BRUNO_RESERVED4_NAME   "reserved4"
-#define BRUNO_DRMREGION0_NAME  "drmregion0"
-#define BRUNO_DRMREGION1_NAME  "drmregion1"
-#define BRUNO_NVRAM_NAME       "nvram"
-
-#define BRUNO_KERNEL0_NAME     "kernel0"
-#define BRUNO_KERNEL1_NAME     "kernel1"
-#define BRUNO_ROOTFS0_NAME     "rootfs0"
-#define BRUNO_ROOTFS1_NAME     "rootfs1"
-#define BRUNO_DATA_NAME        "data+ubi"
-#define BRUNO_MISC_NAME        "misc+ubi"
-
-#define BRUNO_CFE_SIZE         0x00200000UL
-#define BRUNO_HNVRAM_SIZE      0x00170000UL
-#define BRUNO_RESERVED0_SIZE   0x00010000UL
-#define BRUNO_RESERVED1_SIZE   0x00010000UL
-#define BRUNO_RESERVED2_SIZE   0x00010000UL
-#define BRUNO_RESERVED3_SIZE   0x00010000UL
-#define BRUNO_RESERVED4_SIZE   0x00010000UL
-#define BRUNO_DRMREGION0_SIZE  0x00010000UL
-#define BRUNO_DRMREGION1_SIZE  0x00010000UL
-#define BRUNO_NVRAM_SIZE       0x00020000UL
-
-#define BRUNO_KERNEL0_SIZE     0x10000000UL
-#define BRUNO_KERNEL1_SIZE     0x10000000UL
-#define BRUNO_ROOTFS0_SIZE     0x40000000UL
-#define BRUNO_ROOTFS1_SIZE     0x40000000UL
-#define BRUNO_DATA_SIZE        0x40000000UL
-#define BRUNO_MISC_SIZE        0x20000000UL
-
-#define BRUNO_CFE_OFFSET       0x00000000UL
-#define BRUNO_HNVRAM_OFFSET (BRUNO_CFE_OFFSET+BRUNO_CFE_SIZE)
-#define BRUNO_RESERVED0_OFFSET (BRUNO_HNVRAM_OFFSET+BRUNO_HNVRAM_SIZE)
-#define BRUNO_RESERVED1_OFFSET (BRUNO_RESERVED0_OFFSET+BRUNO_RESERVED0_SIZE)
-#define BRUNO_RESERVED2_OFFSET (BRUNO_RESERVED1_OFFSET+BRUNO_RESERVED1_SIZE)
-#define BRUNO_RESERVED3_OFFSET (BRUNO_RESERVED2_OFFSET+BRUNO_RESERVED2_SIZE)
-#define BRUNO_RESERVED4_OFFSET (BRUNO_RESERVED3_OFFSET+BRUNO_RESERVED3_SIZE)
-#define BRUNO_DRMREGION0_OFFSET (BRUNO_RESERVED4_OFFSET+BRUNO_RESERVED4_SIZE)
-#define BRUNO_DRMREGION1_OFFSET (BRUNO_DRMREGION0_OFFSET+BRUNO_DRMREGION0_SIZE)
-#define BRUNO_NVRAM_OFFSET (BRUNO_DRMREGION1_OFFSET+BRUNO_DRMREGION1_SIZE)
-
-#define BRUNO_KERNEL0_OFFSET   0x00000000UL
-#define BRUNO_KERNEL1_OFFSET   (BRUNO_KERNEL0_OFFSET+BRUNO_KERNEL0_SIZE)
-#define BRUNO_ROOTFS0_OFFSET   (BRUNO_KERNEL1_OFFSET+BRUNO_KERNEL1_SIZE)
-#define BRUNO_ROOTFS1_OFFSET   (BRUNO_ROOTFS0_OFFSET+BRUNO_ROOTFS0_SIZE)
-#define BRUNO_DATA_OFFSET      (BRUNO_ROOTFS1_OFFSET+BRUNO_ROOTFS1_SIZE)
-#define BRUNO_MISC_OFFSET      (BRUNO_DATA_OFFSET+BRUNO_DATA_SIZE)
-#endif /* CONFIG_BRUNO_GFHD100 */
-
-/* Partition map */
-static struct mtd_partition fixed_nor_partition_map[] =
-{
-  {   name: BRUNO_CFE_NAME, size: BRUNO_CFE_SIZE, offset: BRUNO_CFE_OFFSET },
-  {   name: BRUNO_HNVRAM_NAME, size: BRUNO_HNVRAM_SIZE, offset: BRUNO_HNVRAM_OFFSET },
-  {   name: BRUNO_RESERVED0_NAME, size: BRUNO_RESERVED0_SIZE, offset: BRUNO_RESERVED0_OFFSET },
-  {   name: BRUNO_RESERVED1_NAME, size: BRUNO_RESERVED1_SIZE, offset: BRUNO_RESERVED1_OFFSET },
-  {   name: BRUNO_RESERVED2_NAME, size: BRUNO_RESERVED2_SIZE, offset: BRUNO_RESERVED2_OFFSET },
-  {   name: BRUNO_RESERVED3_NAME, size: BRUNO_RESERVED3_SIZE, offset: BRUNO_RESERVED3_OFFSET },
-  {   name: BRUNO_RESERVED4_NAME, size: BRUNO_RESERVED4_SIZE, offset: BRUNO_RESERVED4_OFFSET },
-  {   name: BRUNO_DRMREGION0_NAME, size: BRUNO_DRMREGION0_SIZE, offset: BRUNO_DRMREGION0_OFFSET },
-  {   name: BRUNO_DRMREGION1_NAME, size: BRUNO_DRMREGION1_SIZE, offset: BRUNO_DRMREGION1_OFFSET },
-  {   name: BRUNO_NVRAM_NAME, size: BRUNO_NVRAM_SIZE, offset: BRUNO_NVRAM_OFFSET },
-};
-
-static struct mtd_partition fixed_nand_partition_map[] =
-{
-  {   name: BRUNO_KERNEL0_NAME, size: BRUNO_KERNEL0_SIZE, offset: BRUNO_KERNEL0_OFFSET },
-  {   name: BRUNO_KERNEL1_NAME, size: BRUNO_KERNEL1_SIZE, offset: BRUNO_KERNEL1_OFFSET },
-  {   name: BRUNO_ROOTFS0_NAME, size: BRUNO_ROOTFS0_SIZE, offset: BRUNO_ROOTFS0_OFFSET },
-  {   name: BRUNO_ROOTFS1_NAME, size: BRUNO_ROOTFS1_SIZE, offset: BRUNO_ROOTFS1_OFFSET },
-  {   name: BRUNO_DATA_NAME, size: BRUNO_DATA_SIZE, offset: BRUNO_DATA_OFFSET },
-  {   name: BRUNO_MISC_NAME, size: BRUNO_MISC_SIZE, offset: BRUNO_MISC_OFFSET }
-};
-#endif /* CONFIG_BRUNO */
-
-
 static struct map_info brcm_dummy_map = {
 	.name			= "DUMMY",
 };
 
+#ifdef CONFIG_BRUNO
+static void init_mtd(void) {
+	int i;
+	for (i = 0; i < ARRAY_SIZE(cs_info); i++) {
+		if (cs_info[i].type != TYPE_NONE) {
+			printk(KERN_INFO "EBI CS%d: setting up %s flash\n", i,
+			       type_names[cs_info[i].type]);
+			switch( cs_info[i].type )
+			{
+				case TYPE_SPI :
+					brcm_setup_cs(i, fixed_nor_partition_map_size,
+						      &fixed_nor_partition_map[0]);
+					break;
+				case TYPE_NAND :
+					brcm_setup_cs(i, fixed_nand_partition_map_size,
+						      &fixed_nand_partition_map[0]);
+					break;
+			}
+		}
+	}
+}
+
+void init_nand(void) {
+	int i;
+	nand_id = 0;
+	for (i = 0; i < ARRAY_SIZE(cs_info); i++) {
+		if (cs_info[i].type == TYPE_NAND) {
+			printk(KERN_INFO "EBI CS%d: setting up %s flash\n", i,
+			       type_names[cs_info[i].type]);
+			brcm_setup_cs(i, fixed_nand_partition_map_size,
+				      &fixed_nand_partition_map[0]);
+		}
+	}
+}
+EXPORT_SYMBOL(init_nand);
+#endif /* CONFIG_BRUNO */
+
 static int __init brcmstb_mtd_setup(void)
 {
 	struct mtd_partition *parts;
@@ -1023,21 +976,7 @@
 	}
 
 #ifdef CONFIG_BRUNO
-	for (i = 0; i < NUM_CS; i++) {
-		if (cs_info[i].type != TYPE_NONE) {
-			printk(KERN_INFO "EBI CS%d: setting up %s flash\n", i,
-				   type_names[cs_info[i].type]);
-			switch( cs_info[i].type )
-			{
-				case TYPE_SPI :
-					brcm_setup_cs(i, ARRAY_SIZE(fixed_nor_partition_map), &fixed_nor_partition_map[0]);
-					break;
-				case TYPE_NAND :
-					brcm_setup_cs(i, ARRAY_SIZE(fixed_nand_partition_map), &fixed_nand_partition_map[0]);
-					break;
-			}
-		}
-	}
+	init_mtd();
 #else
 	/* set up primary first, so that it owns mtd0/mtd1/(mtd2) */
 	printk(KERN_INFO "EBI CS%d: setting up %s flash (primary)\n", primary,
diff --git a/arch/mips/bruno/Kconfig b/arch/mips/bruno/Kconfig
index bff904a..75cd112 100644
--- a/arch/mips/bruno/Kconfig
+++ b/arch/mips/bruno/Kconfig
@@ -3,30 +3,6 @@
 	default y
 	help
 	  This enables support for BRUNO platform.
-
-menu "Bruno options"
-	depends on BRUNO
-
-#####################################################################
-# User options: board selection
-#####################################################################
-
-choice
-	prompt "Board selection"
-	depends on BRUNO
-	help
-	  Select the Bruno board you are building for.
-
-config BRUNO_GFHD100
-	bool "GFHD100"
-	select BRUNO_PLATFORM_DEFAULTS
-
-endchoice
-
-endmenu
-
-config BRUNO_PLATFORM_DEFAULTS
-	bool
 	select BCMGENET_0_GPHY
 	select BRCM_OVERRIDE_USB
 	select BRCM_FORCE_USB_PWR_HI
@@ -53,5 +29,12 @@
 	select VIDEO_USB_DRIVERS
 	select VIDEO_V4L2
 	select VIDEO_V4L2_COMMON
+	select REPARTITION
 	# select ARCH_SUSPEND_POSSIBLE
 
+config REPARTITION
+	tristate "Repartition Support"
+	default y
+	depends on BRUNO
+	help
+	  This module enables support for repartition.
diff --git a/arch/mips/configs/bruno_gfhd100b2_defconfig b/arch/mips/configs/bruno_gfhd100b2_defconfig
index 01665a8..ee1fd25 100644
--- a/arch/mips/configs/bruno_gfhd100b2_defconfig
+++ b/arch/mips/configs/bruno_gfhd100b2_defconfig
@@ -173,12 +173,6 @@
 CONFIG_BRCM_PLATFORM_DEFAULTS=y
 CONFIG_BCM7425=y
 CONFIG_BRUNO=y
-
-#
-# Bruno options
-#
-CONFIG_BRUNO_GFHD100=y
-CONFIG_BRUNO_PLATFORM_DEFAULTS=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 # CONFIG_ARCH_HAS_ILOG2_U32 is not set
 # CONFIG_ARCH_HAS_ILOG2_U64 is not set