brcm63xx: add support for registering parallel flash through dtb

Add the required nodes to the dtsi files and code to prevent double
registration from the board support code.

Signed-off-by: Jonas Gorski <jogo@openwrt.org>

SVN-Revision: 42123
This commit is contained in:
Jonas Gorski 2014-08-11 11:37:01 +00:00
parent 79057c7255
commit 9c6287d6a1
22 changed files with 711 additions and 21 deletions

View file

@ -3,6 +3,10 @@
#size-cells = <1>;
compatible = "brcm,bcm6338";
aliases {
pflash = &pflash;
};
cpus {
cpu@0 {
compatible = "brcm,bmips3300", "mips,mips4Kc";
@ -11,6 +15,16 @@
memory { device_type = "memory"; reg = <0 0>; };
pflash: nor@1fc00000 {
compatible = "cfi-flash";
reg = <0x1fc00000 0x400000>;
bank-witdh = <2>;
#address-cells = <1>;
#size-cells = <1>;
status = "disabled";
};
ubus@fff00000 {
#address-cells = <1>;
#size-cells = <1>;

View file

@ -3,6 +3,10 @@
#size-cells = <1>;
compatible = "brcm,bcm6345";
aliases {
pflash = &pflash;
};
cpus {
cpu@0 {
compatible = "brcm,bmips32", "mips,mips4Kc";
@ -11,6 +15,16 @@
memory { device_type = "memory"; reg = <0 0>; };
pflash: nor@1fc00000 {
compatible = "cfi-flash";
reg = <0x1fc00000 0x400000>;
bank-witdh = <2>;
#address-cells = <1>;
#size-cells = <1>;
status = "disabled";
};
ubus@fff00000 {
#address-cells = <1>;
#size-cells = <1>;

View file

@ -3,6 +3,10 @@
#size-cells = <1>;
compatible = "brcm,bcm6348";
aliases {
pflash = &pflash;
};
cpus {
cpu@0 {
compatible = "brcm,bmips3300", "mips,mips4Kc";
@ -11,6 +15,16 @@
memory { device_type = "memory"; reg = <0 0>; };
pflash: nor@1fc00000 {
compatible = "cfi-flash";
reg = <0x1fc00000 0x400000>;
bank-witdh = <2>;
#address-cells = <1>;
#size-cells = <1>;
status = "disabled";
};
ubus@fff00000 {
#address-cells = <1>;
#size-cells = <1>;

View file

@ -3,6 +3,10 @@
#size-cells = <1>;
compatible = "brcm,bcm6358";
aliases {
pflash = &pflash;
};
cpus {
cpu@0 {
compatible = "brcm,bmips4350", "mips,mips4Kc";
@ -15,6 +19,16 @@
memory { device_type = "memory"; reg = <0 0>; };
pflash: nor@1e000000 {
compatible = "cfi-flash";
reg = <0x1e000000 0x2000000>;
bank-width = <2>;
#address-cells = <1>;
#size-cells = <1>;
status = "disabled";
};
ubus@fff00000 {
#address-cells = <1>;
#size-cells = <1>;

View file

@ -3,6 +3,10 @@
#size-cells = <1>;
compatible = "brcm,bcm6368";
aliases {
pflash = &pflash;
};
cpus {
cpu@0 {
compatible = "brcm,bmips4350", "mips,mips4Kc";
@ -20,4 +24,13 @@
#size-cells = <1>;
compatible = "simple-bus";
};
pflash: nor@18000000 {
compatible = "cfi-flash";
reg = <0x18000000 0x2000000>;
bank-width = <2>;
#address-cells = <1>;
#size-cells = <1>;
status = "disabled";
};
};

View file

@ -0,0 +1,52 @@
From 0d0e02d605c5696a5076510f564fefe659127aa4 Mon Sep 17 00:00:00 2001
From: Grant Likely <grant.likely@linaro.org>
Date: Thu, 22 May 2014 01:04:17 +0900
Subject: [PATCH] of: Create unlocked version of for_each_child_of_node()
When iterating over nodes, sometimes it needs to be done when the DT
lock is already held. This patch makes an unlocked version of the
for_each_child_of_node() macro.
Signed-off-by: Grant Likely <grant.likely@linaro.org>
---
drivers/of/base.c | 22 +++++++++++++++++-----
1 file changed, 17 insertions(+), 5 deletions(-)
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -545,6 +545,22 @@ struct device_node *of_get_next_parent(s
}
EXPORT_SYMBOL(of_get_next_parent);
+static struct device_node *__of_get_next_child(const struct device_node *node,
+ struct device_node *prev)
+{
+ struct device_node *next;
+
+ next = prev ? prev->sibling : node->child;
+ for (; next; next = next->sibling)
+ if (of_node_get(next))
+ break;
+ of_node_put(prev);
+ return next;
+}
+#define __for_each_child_of_node(parent, child) \
+ for (child = __of_get_next_child(parent, NULL); child != NULL; \
+ child = __of_get_next_child(parent, child))
+
/**
* of_get_next_child - Iterate a node childs
* @node: parent node
@@ -560,11 +576,7 @@ struct device_node *of_get_next_child(co
unsigned long flags;
raw_spin_lock_irqsave(&devtree_lock, flags);
- next = prev ? prev->sibling : node->child;
- for (; next; next = next->sibling)
- if (of_node_get(next))
- break;
- of_node_put(prev);
+ next = __of_get_next_child(node, prev);
raw_spin_unlock_irqrestore(&devtree_lock, flags);
return next;
}

View file

@ -0,0 +1,56 @@
From 11d200e95f3e84c1102e4cc9863a3614fd41f3ad Mon Sep 17 00:00:00 2001
From: Grant Likely <grant.likely@linaro.org>
Date: Fri, 14 Mar 2014 17:00:14 +0000
Subject: [PATCH] lib: add glibc style strchrnul() variant
The strchrnul() variant helpfully returns a the end of the string
instead of a NULL if the requested character is not found. This can
simplify string parsing code since it doesn't need to expicitly check
for a NULL return. If a valid string pointer is passed in, then a valid
null terminated string will always come back out.
Signed-off-by: Grant Likely <grant.likely@linaro.org>
---
include/linux/string.h | 3 +++
lib/string.c | 18 ++++++++++++++++++
2 files changed, 21 insertions(+)
--- a/include/linux/string.h
+++ b/include/linux/string.h
@@ -52,6 +52,9 @@ extern int strncasecmp(const char *s1, c
#ifndef __HAVE_ARCH_STRCHR
extern char * strchr(const char *,int);
#endif
+#ifndef __HAVE_ARCH_STRCHRNUL
+extern char * strchrnul(const char *,int);
+#endif
#ifndef __HAVE_ARCH_STRNCHR
extern char * strnchr(const char *, size_t, int);
#endif
--- a/lib/string.c
+++ b/lib/string.c
@@ -301,6 +301,24 @@ char *strchr(const char *s, int c)
EXPORT_SYMBOL(strchr);
#endif
+#ifndef __HAVE_ARCH_STRCHRNUL
+/**
+ * strchrnul - Find and return a character in a string, or end of string
+ * @s: The string to be searched
+ * @c: The character to search for
+ *
+ * Returns pointer to first occurrence of 'c' in s. If c is not found, then
+ * return a pointer to the null byte at the end of s.
+ */
+char *strchrnul(const char *s, int c)
+{
+ while (*s && *s != (char)c)
+ s++;
+ return (char *)s;
+}
+EXPORT_SYMBOL(strchrnul);
+#endif
+
#ifndef __HAVE_ARCH_STRRCHR
/**
* strrchr - Find the last occurrence of a character in a string

View file

@ -0,0 +1,106 @@
From c22e650e66b862babe9c00bebb20b8029c7b0362 Mon Sep 17 00:00:00 2001
From: Grant Likely <grant.likely@linaro.org>
Date: Fri, 14 Mar 2014 17:07:12 +0000
Subject: [PATCH] of: Make of_find_node_by_path() handle /aliases
Make of_find_node_by_path() handle aliases as prefixes. To make this
work the name search is refactored to search by path component instead
of by full string. This should be a more efficient search, and it makes
it possible to start a search at a subnode of a tree.
Signed-off-by: David Daney <david.daney@cavium.com>
Signed-off-by: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
[grant.likely: Rework to not require allocating at runtime]
Acked-by: Rob Herring <robh@kernel.org>
Signed-off-by: Grant Likely <grant.likely@linaro.org>
---
drivers/of/base.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 61 insertions(+), 6 deletions(-)
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -633,23 +633,78 @@ struct device_node *of_get_child_by_name
}
EXPORT_SYMBOL(of_get_child_by_name);
+static struct device_node *__of_find_node_by_path(struct device_node *parent,
+ const char *path)
+{
+ struct device_node *child;
+ int len = strchrnul(path, '/') - path;
+
+ if (!len)
+ return NULL;
+
+ __for_each_child_of_node(parent, child) {
+ const char *name = strrchr(child->full_name, '/');
+ if (WARN(!name, "malformed device_node %s\n", child->full_name))
+ continue;
+ name++;
+ if (strncmp(path, name, len) == 0 && (strlen(name) == len))
+ return child;
+ }
+ return NULL;
+}
+
/**
* of_find_node_by_path - Find a node matching a full OF path
- * @path: The full path to match
+ * @path: Either the full path to match, or if the path does not
+ * start with '/', the name of a property of the /aliases
+ * node (an alias). In the case of an alias, the node
+ * matching the alias' value will be returned.
+ *
+ * Valid paths:
+ * /foo/bar Full path
+ * foo Valid alias
+ * foo/bar Valid alias + relative path
*
* Returns a node pointer with refcount incremented, use
* of_node_put() on it when done.
*/
struct device_node *of_find_node_by_path(const char *path)
{
- struct device_node *np = of_allnodes;
+ struct device_node *np = NULL;
+ struct property *pp;
unsigned long flags;
+ if (strcmp(path, "/") == 0)
+ return of_node_get(of_allnodes);
+
+ /* The path could begin with an alias */
+ if (*path != '/') {
+ char *p = strchrnul(path, '/');
+ int len = p - path;
+
+ /* of_aliases must not be NULL */
+ if (!of_aliases)
+ return NULL;
+
+ for_each_property_of_node(of_aliases, pp) {
+ if (strlen(pp->name) == len && !strncmp(pp->name, path, len)) {
+ np = of_find_node_by_path(pp->value);
+ break;
+ }
+ }
+ if (!np)
+ return NULL;
+ path = p;
+ }
+
+ /* Step down the tree matching path components */
raw_spin_lock_irqsave(&devtree_lock, flags);
- for (; np; np = np->allnext) {
- if (np->full_name && (of_node_cmp(np->full_name, path) == 0)
- && of_node_get(np))
- break;
+ if (!np)
+ np = of_node_get(of_allnodes);
+ while (np && *path == '/') {
+ path++; /* Increment past '/' delimiter */
+ np = __of_find_node_by_path(np, path);
+ path = strchrnul(path, '/');
}
raw_spin_unlock_irqrestore(&devtree_lock, flags);
return np;

View file

@ -0,0 +1,37 @@
--- a/arch/mips/bcm63xx/boards/board_common.c
+++ b/arch/mips/bcm63xx/boards/board_common.c
@@ -147,6 +147,18 @@ void __init device_tree_init(void)
unflatten_and_copy_device_tree();
}
+
+int board_of_device_present(const char *alias)
+{
+ bool present;
+ struct device_node *np;
+
+ np = of_find_node_by_path(alias);
+ present = of_device_is_available(np);
+ of_node_put(np);
+
+ return present;
+}
#endif
static struct gpio_led_platform_data bcm63xx_led_data;
--- a/arch/mips/bcm63xx/boards/board_common.h
+++ b/arch/mips/bcm63xx/boards/board_common.h
@@ -15,4 +15,13 @@ void board_bcm963xx_init(void);
static inline void board_bcm963xx_init(void) { }
#endif
+#if defined(CONFIG_OF)
+int board_of_device_present(const char *alias);
+#else
+static inline void board_of_device_present(const char *alias)
+{
+ return 0;
+}
+#endif
+
#endif /* __BOARD_COMMON_H */

View file

@ -0,0 +1,21 @@
--- a/arch/mips/bcm63xx/dev-flash.c
+++ b/arch/mips/bcm63xx/dev-flash.c
@@ -22,6 +22,8 @@
#include <bcm63xx_regs.h>
#include <bcm63xx_io.h>
+#include "boards/board_common.h"
+
static int flash_type;
static struct mtd_partition mtd_partitions[] = {
@@ -164,6 +166,9 @@ int __init bcm63xx_flash_register(void)
switch (flash_type) {
case BCM63XX_FLASH_TYPE_PARALLEL:
+ /* don't register when already registered through from dtb */
+ if (board_of_device_present("pflash"))
+ return 0;
if (!mtd_resources[0].start) {
/* read base address of boot chip select (0) */

View file

@ -12,7 +12,7 @@ Signed-off-by: Axel Gembe <ago@bastart.eu.org>
--- a/arch/mips/bcm63xx/dev-flash.c
+++ b/arch/mips/bcm63xx/dev-flash.c
@@ -32,7 +32,7 @@ static struct mtd_partition mtd_partitio
@@ -34,7 +34,7 @@ static struct mtd_partition mtd_partitio
}
};

View file

@ -24,7 +24,7 @@ Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
#include <bcm63xx_regs.h>
#include <bcm63xx_io.h>
@@ -63,6 +66,21 @@ void __init bcm63xx_flash_force_phys_bas
@@ -65,6 +68,21 @@ void __init bcm63xx_flash_force_phys_bas
mtd_resources[0].end = end;
}
@ -46,7 +46,7 @@ Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
static int __init bcm63xx_detect_flash_type(void)
{
u32 val;
@@ -70,9 +88,15 @@ static int __init bcm63xx_detect_flash_t
@@ -72,9 +90,15 @@ static int __init bcm63xx_detect_flash_t
switch (bcm63xx_get_cpu_id()) {
case BCM6318_CPU_ID:
/* only support serial flash */
@ -62,7 +62,7 @@ Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
if (val & STRAPBUS_6328_BOOT_SEL_SERIAL)
return BCM63XX_FLASH_TYPE_SERIAL;
else
@@ -91,12 +115,20 @@ static int __init bcm63xx_detect_flash_t
@@ -93,12 +117,20 @@ static int __init bcm63xx_detect_flash_t
return BCM63XX_FLASH_TYPE_SERIAL;
case BCM6362_CPU_ID:
val = bcm_misc_readl(MISC_STRAPBUS_6362_REG);
@ -83,7 +83,7 @@ Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
switch (val & STRAPBUS_6368_BOOT_SEL_MASK) {
case STRAPBUS_6368_BOOT_SEL_NAND:
return BCM63XX_FLASH_TYPE_NAND;
@@ -107,6 +139,11 @@ static int __init bcm63xx_detect_flash_t
@@ -109,6 +141,11 @@ static int __init bcm63xx_detect_flash_t
}
case BCM63268_CPU_ID:
val = bcm_misc_readl(MISC_STRAPBUS_63268_REG);
@ -95,7 +95,7 @@ Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
if (val & STRAPBUS_63268_BOOT_SEL_SERIAL)
return BCM63XX_FLASH_TYPE_SERIAL;
else
@@ -176,8 +213,15 @@ int __init bcm63xx_flash_register(void)
@@ -181,8 +218,15 @@ int __init bcm63xx_flash_register(void)
return platform_device_register(&mtd_dev);
case BCM63XX_FLASH_TYPE_SERIAL:

View file

@ -18,7 +18,7 @@ Subject: [PATCH 58/72] BCM63XX: allow providing fixup data in board data
#include "board_common.h"
@@ -184,6 +185,7 @@ int __init board_register_devices(void)
@@ -196,6 +197,7 @@ int __init board_register_devices(void)
int button_count = 0;
int led_count = 0;
int usbh_ports = 0;
@ -26,7 +26,7 @@ Subject: [PATCH 58/72] BCM63XX: allow providing fixup data in board data
#if CONFIG_OF
if (of_have_populated_dt()) {
@@ -281,6 +283,10 @@ int __init board_register_devices(void)
@@ -293,6 +295,10 @@ int __init board_register_devices(void)
platform_device_register(&bcm63xx_gpio_keys_device);
}

View file

@ -11,7 +11,7 @@ Signed-off-by: Jonas Gorski <jogo@openwrt.org>
--- a/arch/mips/bcm63xx/dev-flash.c
+++ b/arch/mips/bcm63xx/dev-flash.c
@@ -231,3 +231,8 @@ int __init bcm63xx_flash_register(void)
@@ -236,3 +236,8 @@ int __init bcm63xx_flash_register(void)
return -ENODEV;
}
}

View file

@ -11,7 +11,7 @@ Subject: [PATCH 69/80] MIPS: BCM63XX: pass caldata info to flash
--- a/arch/mips/bcm63xx/boards/board_common.c
+++ b/arch/mips/bcm63xx/boards/board_common.c
@@ -255,7 +255,7 @@ int __init board_register_devices(void)
@@ -267,7 +267,7 @@ int __init board_register_devices(void)
if (board.num_spis)
spi_register_board_info(board.spis, board.num_spis);
@ -22,7 +22,7 @@ Subject: [PATCH 69/80] MIPS: BCM63XX: pass caldata info to flash
while (led_count < ARRAY_SIZE(board.leds) && board.leds[led_count].name)
--- a/arch/mips/bcm63xx/dev-flash.c
+++ b/arch/mips/bcm63xx/dev-flash.c
@@ -35,12 +35,15 @@ static struct mtd_partition mtd_partitio
@@ -37,12 +37,15 @@ static struct mtd_partition mtd_partitio
}
};
@ -38,7 +38,7 @@ Subject: [PATCH 69/80] MIPS: BCM63XX: pass caldata info to flash
};
static struct resource mtd_resources[] = {
@@ -68,6 +71,7 @@ void __init bcm63xx_flash_force_phys_bas
@@ -70,6 +73,7 @@ void __init bcm63xx_flash_force_phys_bas
static struct flash_platform_data bcm63xx_flash_data = {
.part_probe_types = bcm63xx_part_types,
@ -46,7 +46,7 @@ Subject: [PATCH 69/80] MIPS: BCM63XX: pass caldata info to flash
};
static struct spi_board_info bcm63xx_spi_flash_info[] = {
@@ -195,9 +199,13 @@ void __init bcm63xx_flash_detect(void)
@@ -197,9 +201,13 @@ void __init bcm63xx_flash_detect(void)
}
}

View file

@ -39,7 +39,7 @@
return;
--- a/arch/mips/bcm63xx/boards/board_common.c
+++ b/arch/mips/bcm63xx/boards/board_common.c
@@ -285,7 +285,8 @@ int __init board_register_devices(void)
@@ -297,7 +297,8 @@ int __init board_register_devices(void)
/* register any fixups */
for (i = 0; i < board.has_caldata; i++)

View file

@ -1,6 +1,6 @@
--- a/arch/mips/bcm63xx/boards/board_common.c
+++ b/arch/mips/bcm63xx/boards/board_common.c
@@ -286,7 +286,7 @@ int __init board_register_devices(void)
@@ -298,7 +298,7 @@ int __init board_register_devices(void)
/* register any fixups */
for (i = 0; i < board.has_caldata; i++)
pci_enable_ath9k_fixup(board.caldata[i].slot, board.caldata[i].caldata_offset,

View file

@ -36,7 +36,7 @@ Subject: [PATCH 72/72] 446-BCM63XX-add-a-fixup-for-rt2x00-devices
#include "board_common.h"
@@ -284,9 +285,19 @@ int __init board_register_devices(void)
@@ -296,9 +297,19 @@ int __init board_register_devices(void)
}
/* register any fixups */
@ -61,7 +61,7 @@ Subject: [PATCH 72/72] 446-BCM63XX-add-a-fixup-for-rt2x00-devices
}
--- a/arch/mips/bcm63xx/dev-flash.c
+++ b/arch/mips/bcm63xx/dev-flash.c
@@ -199,7 +199,7 @@ void __init bcm63xx_flash_detect(void)
@@ -201,7 +201,7 @@ void __init bcm63xx_flash_detect(void)
}
}

View file

@ -0,0 +1,349 @@
--- a/drivers/mtd/bcm63xxpart.c
+++ b/drivers/mtd/bcm63xxpart.c
@@ -32,6 +32,7 @@
#include <linux/vmalloc.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
+#include <linux/of.h>
#include <asm/mach-bcm63xx/bcm63xx_nvram.h>
#include <linux/bcm963xx_tag.h>
@@ -43,66 +44,35 @@
#define BCM63XX_CFE_MAGIC_OFFSET 0x4e0
-static int bcm63xx_parse_cfe_partitions(struct mtd_info *master,
- struct mtd_partition **pparts,
- struct mtd_part_parser_data *data)
+static bool node_has_compatible(struct device_node *pp)
+{
+ return of_get_property(pp, "compatible", NULL);
+}
+
+static int parse_bcmtag(struct mtd_info *master, struct mtd_partition *pparts,
+ int next_part, size_t offset, size_t size)
{
- /* CFE, NVRAM and global Linux are always present */
- int nrparts = 3, curpart = 0;
struct bcm_tag *buf;
- struct mtd_partition *parts;
+ u32 computed_crc;
int ret;
size_t retlen;
- unsigned int rootfsaddr, kerneladdr, spareaddr, nvramaddr;
- unsigned int rootfslen, kernellen, sparelen, totallen;
- unsigned int cfelen, nvramlen;
- unsigned int cfe_erasesize;
- unsigned int caldatalen1 = 0, caldataaddr1 = 0;
- unsigned int caldatalen2 = 0, caldataaddr2 = 0;
- int i;
- u32 computed_crc;
+ unsigned int rootfsaddr, kerneladdr;
+ unsigned int rootfslen, kernellen, totallen;
bool rootfs_first = false;
-
- if (!bcm63xx_is_cfe_present())
- return -EINVAL;
-
- cfe_erasesize = max_t(uint32_t, master->erasesize,
- BCM63XX_CFE_BLOCK_SIZE);
-
- cfelen = cfe_erasesize;
- nvramlen = bcm63xx_nvram_get_psi_size() * SZ_1K;
- nvramlen = roundup(nvramlen, cfe_erasesize);
- nvramaddr = master->size - nvramlen;
-
- if (data) {
- if (data->caldata[0]) {
- caldatalen1 = cfe_erasesize;
- caldataaddr1 = rounddown(data->caldata[0],
- cfe_erasesize);
- }
- if (data->caldata[1]) {
- caldatalen2 = cfe_erasesize;
- caldataaddr2 = rounddown(data->caldata[1],
- cfe_erasesize);
- }
- if (caldataaddr1 == caldataaddr2) {
- caldataaddr2 = 0;
- caldatalen2 = 0;
- }
- }
+ int curr_part = next_part;
/* Allocate memory for buffer */
- buf = vmalloc(sizeof(struct bcm_tag));
+ buf = vmalloc(sizeof(*buf));
if (!buf)
return -ENOMEM;
/* Get the tag */
- ret = mtd_read(master, cfelen, sizeof(struct bcm_tag), &retlen,
+ ret = mtd_read(master, offset, sizeof(*buf), &retlen,
(void *)buf);
- if (retlen != sizeof(struct bcm_tag)) {
+ if (retlen != sizeof(*buf)) {
vfree(buf);
- return -EIO;
+ return 0;
}
computed_crc = crc32_le(IMAGETAG_CRC_START, (u8 *)buf,
@@ -121,7 +91,6 @@ static int bcm63xx_parse_cfe_partitions(
kerneladdr = kerneladdr - BCM63XX_EXTENDED_SIZE;
rootfsaddr = rootfsaddr - BCM63XX_EXTENDED_SIZE;
- spareaddr = roundup(totallen, master->erasesize) + cfelen;
if (rootfsaddr < kerneladdr) {
/* default Broadcom layout */
@@ -130,8 +99,8 @@ static int bcm63xx_parse_cfe_partitions(
} else {
/* OpenWrt layout */
rootfsaddr = kerneladdr + kernellen;
- rootfslen = buf->real_rootfs_length;
- spareaddr = rootfsaddr + rootfslen;
+ rootfslen = size - kernellen -
+ sizeof(*buf);
}
} else {
pr_warn("CFE boot tag CRC invalid (expected %08x, actual %08x)\n",
@@ -139,16 +108,145 @@ static int bcm63xx_parse_cfe_partitions(
kernellen = 0;
rootfslen = 0;
rootfsaddr = 0;
- spareaddr = cfelen;
}
- sparelen = min_not_zero(nvramaddr, caldataaddr1) - spareaddr;
- /* Determine number of partitions */
- if (rootfslen > 0)
- nrparts++;
+ if (kernellen > 0) {
+ int kernelpart = curr_part;
- if (kernellen > 0)
- nrparts++;
+ if (rootfslen > 0 && rootfs_first)
+ kernelpart++;
+ pparts[kernelpart].name = "kernel";
+ pparts[kernelpart].offset = kerneladdr;
+ pparts[kernelpart].size = kernellen;
+ curr_part++;
+ }
+
+ if (rootfslen > 0) {
+ int rootfspart = curr_part;
+
+ if (kernellen > 0 && rootfs_first)
+ rootfspart--;
+ pparts[rootfspart].name = "rootfs";
+ pparts[rootfspart].offset = rootfsaddr;
+ pparts[rootfspart].size = rootfslen;
+
+ curr_part++;
+ }
+
+ vfree(buf);
+
+ return curr_part - next_part;
+}
+
+
+static int bcm63xx_parse_cfe_partitions_of(struct mtd_info *master,
+ struct mtd_partition **pparts,
+ struct mtd_part_parser_data *data)
+{
+ struct device_node *dp = data->of_node;
+ struct device_node *pp;
+ int i, nr_parts = 0;
+ const char *partname;
+ int len;
+
+ for_each_child_of_node(dp, pp) {
+ if (node_has_compatible(pp))
+ continue;
+
+ nr_parts++;
+ }
+
+ *pparts = kzalloc(nr_parts * sizeof(**pparts), GFP_KERNEL);
+ if (!*pparts)
+ return -ENOMEM;
+
+ i = 0;
+ for_each_child_of_node(dp, pp) {
+ const __be32 *reg;
+ int a_cells, s_cells;
+ size_t size, offset;
+
+ if (node_has_compatible(pp))
+ continue;
+
+ reg = of_get_property(pp, "reg", &len);
+ if (!reg) {
+ nr_parts--;
+ continue;
+ }
+
+ a_cells = of_n_addr_cells(pp);
+ s_cells = of_n_size_cells(pp);
+ offset = of_read_number(reg, a_cells);
+ size = of_read_number(reg + a_cells, s_cells);
+ partname = of_get_property(pp, "label", &len);
+ if (!partname)
+ partname = of_get_property(pp, "name", &len);
+
+ if (!strcmp(partname, "linux"))
+ i += parse_bcmtag(master, *pparts, i, offset, size);
+
+ if (of_get_property(pp, "read-only", &len))
+ (*pparts)[i].mask_flags |= MTD_WRITEABLE;
+
+ if (of_get_property(pp, "lock", &len))
+ (*pparts)[i].mask_flags |= MTD_POWERUP_LOCK;
+
+ (*pparts)[i].offset = offset;
+ (*pparts)[i].size = size;
+ (*pparts)[i].name = partname;
+
+ i++;
+ }
+
+ return i;
+}
+
+static int bcm63xx_parse_cfe_partitions(struct mtd_info *master,
+ struct mtd_partition **pparts,
+ struct mtd_part_parser_data *data)
+{
+ /* CFE, NVRAM and global Linux are always present */
+ int nrparts = 5, curpart = 0;
+ struct mtd_partition *parts;
+ unsigned int nvramaddr;
+ unsigned int cfelen, nvramlen;
+ unsigned int cfe_erasesize;
+ unsigned int caldatalen1 = 0, caldataaddr1 = 0;
+ unsigned int caldatalen2 = 0, caldataaddr2 = 0;
+ unsigned int imageaddr, imagelen;
+ int i;
+
+ if (!bcm63xx_is_cfe_present())
+ return -EINVAL;
+
+ cfe_erasesize = max_t(uint32_t, master->erasesize,
+ BCM63XX_CFE_BLOCK_SIZE);
+
+ cfelen = cfe_erasesize;
+ nvramlen = bcm63xx_nvram_get_psi_size() * SZ_1K;
+ nvramlen = roundup(nvramlen, cfe_erasesize);
+ nvramaddr = master->size - nvramlen;
+
+ if (data) {
+ if (data->caldata[0]) {
+ caldatalen1 = cfe_erasesize;
+ caldataaddr1 = rounddown(data->caldata[0],
+ cfe_erasesize);
+ }
+ if (data->caldata[1]) {
+ caldatalen2 = cfe_erasesize;
+ caldataaddr2 = rounddown(data->caldata[1],
+ cfe_erasesize);
+ }
+ if (caldataaddr1 == caldataaddr2) {
+ caldataaddr2 = 0;
+ caldatalen2 = 0;
+ }
+ }
+
+ imageaddr = cfelen;
+ imagelen = min_not_zero(nvramaddr, caldataaddr1) - imageaddr;
if (caldatalen1 > 0)
nrparts++;
@@ -158,10 +256,8 @@ static int bcm63xx_parse_cfe_partitions(
/* Ask kernel for more memory */
parts = kzalloc(sizeof(*parts) * nrparts + 10 * nrparts, GFP_KERNEL);
- if (!parts) {
- vfree(buf);
+ if (!parts)
return -ENOMEM;
- }
/* Start building partition list */
parts[curpart].name = "CFE";
@@ -169,29 +265,7 @@ static int bcm63xx_parse_cfe_partitions(
parts[curpart].size = cfelen;
curpart++;
- if (kernellen > 0) {
- int kernelpart = curpart;
-
- if (rootfslen > 0 && rootfs_first)
- kernelpart++;
- parts[kernelpart].name = "kernel";
- parts[kernelpart].offset = kerneladdr;
- parts[kernelpart].size = kernellen;
- curpart++;
- }
-
- if (rootfslen > 0) {
- int rootfspart = curpart;
-
- if (kernellen > 0 && rootfs_first)
- rootfspart--;
- parts[rootfspart].name = "rootfs";
- parts[rootfspart].offset = rootfsaddr;
- parts[rootfspart].size = rootfslen;
- if (sparelen > 0 && !rootfs_first)
- parts[rootfspart].size += sparelen;
- curpart++;
- }
+ curpart += parse_bcmtag(master, parts, curpart, imageaddr, imagelen);
if (caldatalen1 > 0) {
if (caldatalen2 > 0)
@@ -217,25 +291,33 @@ static int bcm63xx_parse_cfe_partitions(
/* Global partition "linux" to make easy firmware upgrade */
parts[curpart].name = "linux";
- parts[curpart].offset = cfelen;
- parts[curpart].size = min_not_zero(nvramaddr, caldataaddr1) - cfelen;
+ parts[curpart].offset = imageaddr;
+ parts[curpart].size = imagelen;
+ curpart++;
- for (i = 0; i < nrparts; i++)
+ for (i = 0; i < curpart; i++)
pr_info("Partition %d is %s offset %llx and length %llx\n", i,
parts[i].name, parts[i].offset, parts[i].size);
- pr_info("Spare partition is offset %x and length %x\n", spareaddr,
- sparelen);
-
*pparts = parts;
- vfree(buf);
return nrparts;
};
+
+static int bcm63xx_parse_partitions(struct mtd_info *master,
+ struct mtd_partition **pparts,
+ struct mtd_part_parser_data *data)
+{
+ if (data && data->of_node)
+ return bcm63xx_parse_cfe_partitions_of(master, pparts, data);
+ else
+ return bcm63xx_parse_cfe_partitions(master, pparts, data);
+}
+
static struct mtd_part_parser bcm63xx_cfe_parser = {
.owner = THIS_MODULE,
- .parse_fn = bcm63xx_parse_cfe_partitions,
+ .parse_fn = bcm63xx_parse_partitions,
.name = "bcm63xxpart",
};

View file

@ -107,7 +107,7 @@
#include <bcm63xx_cpu.h>
#include <bcm63xx_dev_flash.h>
#include <bcm63xx_dev_hsspi.h>
@@ -215,6 +216,13 @@ int __init bcm63xx_flash_register(int nu
@@ -220,6 +221,13 @@ int __init bcm63xx_flash_register(int nu
val = bcm_mpi_readl(MPI_CSBASE_REG(0));
val &= MPI_CSBASE_BASE_MASK;

View file

@ -44,8 +44,8 @@ Subject: [PATCH 44/44] MIPS: BCM63XX: add inventel Livebox support
static int (*board_get_mac_address)(u8 mac[ETH_ALEN]);
--- a/arch/mips/bcm63xx/boards/board_common.h
+++ b/arch/mips/bcm63xx/boards/board_common.h
@@ -15,4 +15,10 @@ void board_bcm963xx_init(void);
static inline void board_bcm963xx_init(void) { }
@@ -24,4 +24,10 @@ static inline void board_of_device_prese
}
#endif
+#if defined(CONFIG_BOARD_LIVEBOX)

View file

@ -559,7 +559,7 @@
--- a/drivers/mtd/bcm63xxpart.c
+++ b/drivers/mtd/bcm63xxpart.c
@@ -70,6 +70,11 @@ static int bcm63xx_parse_cfe_partitions(
@@ -224,6 +224,11 @@ static int bcm63xx_parse_cfe_partitions(
BCM63XX_CFE_BLOCK_SIZE);
cfelen = cfe_erasesize;