1a8218d6e4
This contains the following new bigger changes: * new partition parser which still could lake some features or have bugs * new nand flash driver * using physmap-flash flash driver for parallel flash * some changes to the serial flash driver With these changes OpenWrt starts using more of the mainline flash drivers. SVN-Revision: 35632
473 lines
13 KiB
Diff
473 lines
13 KiB
Diff
--- a/arch/mips/bcm47xx/nvram.c
|
|
+++ b/arch/mips/bcm47xx/nvram.c
|
|
@@ -3,7 +3,7 @@
|
|
*
|
|
* Copyright (C) 2005 Broadcom Corporation
|
|
* Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org>
|
|
- * Copyright (C) 2010-2011 Hauke Mehrtens <hauke@hauke-m.de>
|
|
+ * Copyright (C) 2010-2012 Hauke Mehrtens <hauke@hauke-m.de>
|
|
*
|
|
* 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
|
|
@@ -18,83 +18,168 @@
|
|
#include <linux/kernel.h>
|
|
#include <linux/string.h>
|
|
#include <asm/addrspace.h>
|
|
-#include <asm/mach-bcm47xx/nvram.h>
|
|
+#include <bcm47xx_nvram.h>
|
|
#include <asm/mach-bcm47xx/bcm47xx.h>
|
|
|
|
static char nvram_buf[NVRAM_SPACE];
|
|
|
|
+static u32 find_nvram_size(u32 end)
|
|
+{
|
|
+ struct nvram_header *header;
|
|
+ u32 nvram_sizes[] = {0x8000, 0xF000, 0x10000};
|
|
+ int i;
|
|
+
|
|
+ for (i = 0; i < ARRAY_SIZE(nvram_sizes); i++) {
|
|
+ header = (struct nvram_header *)KSEG1ADDR(end - nvram_sizes[i]);
|
|
+ if (header->magic == NVRAM_HEADER)
|
|
+ return nvram_sizes[i];
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
/* Probe for NVRAM header */
|
|
-static void early_nvram_init(void)
|
|
+static int nvram_find_and_copy(u32 base, u32 lim)
|
|
{
|
|
-#ifdef CONFIG_BCM47XX_SSB
|
|
- struct ssb_mipscore *mcore_ssb;
|
|
-#endif
|
|
-#ifdef CONFIG_BCM47XX_BCMA
|
|
- struct bcma_drv_cc *bcma_cc;
|
|
-#endif
|
|
struct nvram_header *header;
|
|
int i;
|
|
- u32 base = 0;
|
|
- u32 lim = 0;
|
|
u32 off;
|
|
u32 *src, *dst;
|
|
+ u32 size;
|
|
|
|
- switch (bcm47xx_bus_type) {
|
|
-#ifdef CONFIG_BCM47XX_SSB
|
|
- case BCM47XX_BUS_TYPE_SSB:
|
|
- mcore_ssb = &bcm47xx_bus.ssb.mipscore;
|
|
- base = mcore_ssb->pflash.window;
|
|
- lim = mcore_ssb->pflash.window_size;
|
|
- break;
|
|
-#endif
|
|
-#ifdef CONFIG_BCM47XX_BCMA
|
|
- case BCM47XX_BUS_TYPE_BCMA:
|
|
- bcma_cc = &bcm47xx_bus.bcma.bus.drv_cc;
|
|
- base = bcma_cc->pflash.window;
|
|
- lim = bcma_cc->pflash.window_size;
|
|
- break;
|
|
-#endif
|
|
- }
|
|
-
|
|
+ /* TODO: when nvram is on nand flash check for bad blocks first. */
|
|
off = FLASH_MIN;
|
|
while (off <= lim) {
|
|
/* Windowed flash access */
|
|
- header = (struct nvram_header *)
|
|
- KSEG1ADDR(base + off - NVRAM_SPACE);
|
|
- if (header->magic == NVRAM_HEADER)
|
|
+ size = find_nvram_size(base + off);
|
|
+ if (size) {
|
|
+ header = (struct nvram_header *)KSEG1ADDR(base + off -
|
|
+ size);
|
|
goto found;
|
|
+ }
|
|
off <<= 1;
|
|
}
|
|
|
|
/* Try embedded NVRAM at 4 KB and 1 KB as last resorts */
|
|
header = (struct nvram_header *) KSEG1ADDR(base + 4096);
|
|
- if (header->magic == NVRAM_HEADER)
|
|
+ if (header->magic == NVRAM_HEADER) {
|
|
+ size = NVRAM_SPACE;
|
|
goto found;
|
|
+ }
|
|
|
|
header = (struct nvram_header *) KSEG1ADDR(base + 1024);
|
|
- if (header->magic == NVRAM_HEADER)
|
|
+ if (header->magic == NVRAM_HEADER) {
|
|
+ size = NVRAM_SPACE;
|
|
goto found;
|
|
+ }
|
|
|
|
- return;
|
|
+ pr_err("no nvram found\n");
|
|
+ return -ENXIO;
|
|
|
|
found:
|
|
+
|
|
+ if (header->len > size)
|
|
+ pr_err("The nvram size accoridng to the header seems to be bigger than the partition on flash\n");
|
|
+ if (header->len > NVRAM_SPACE)
|
|
+ pr_err("nvram on flash (%i bytes) is bigger than the reserved space in memory, will just copy the first %i bytes\n",
|
|
+ header->len, NVRAM_SPACE);
|
|
+
|
|
src = (u32 *) header;
|
|
dst = (u32 *) nvram_buf;
|
|
for (i = 0; i < sizeof(struct nvram_header); i += 4)
|
|
*dst++ = *src++;
|
|
- for (; i < header->len && i < NVRAM_SPACE; i += 4)
|
|
+ for (; i < header->len && i < NVRAM_SPACE && i < size; i += 4)
|
|
*dst++ = le32_to_cpu(*src++);
|
|
+ memset(dst, 0x0, NVRAM_SPACE - i);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+#ifdef CONFIG_BCM47XX_SSB
|
|
+static int nvram_init_ssb(void)
|
|
+{
|
|
+ struct ssb_mipscore *mcore = &bcm47xx_bus.ssb.mipscore;
|
|
+#ifdef CONFIG_SSB_SFLASH
|
|
+ struct ssb_chipcommon *chipco = &bcm47xx_bus.ssb.chipco;
|
|
+#endif
|
|
+ u32 base;
|
|
+ u32 lim;
|
|
+
|
|
+ if (mcore->pflash.present) {
|
|
+ base = mcore->pflash.window;
|
|
+ lim = mcore->pflash.window_size;
|
|
+#ifdef CONFIG_SSB_SFLASH
|
|
+ } else if (chipco->sflash.present) {
|
|
+ base = chipco->sflash.window;
|
|
+ lim = chipco->sflash.size;
|
|
+#endif
|
|
+ } else {
|
|
+ pr_err("Couldn't find supported flash memory\n");
|
|
+ return -ENXIO;
|
|
+ }
|
|
+
|
|
+ return nvram_find_and_copy(base, lim);
|
|
+}
|
|
+#endif
|
|
+
|
|
+#ifdef CONFIG_BCM47XX_BCMA
|
|
+static int nvram_init_bcma(void)
|
|
+{
|
|
+ struct bcma_drv_cc *cc = &bcm47xx_bus.bcma.bus.drv_cc;
|
|
+ u32 base;
|
|
+ u32 lim;
|
|
+
|
|
+#ifdef CONFIG_BCMA_NFLASH
|
|
+ if (cc->nflash.boot) {
|
|
+ base = BCMA_SOC_FLASH1;
|
|
+ lim = BCMA_SOC_FLASH1_SZ;
|
|
+ } else
|
|
+#endif
|
|
+ if (cc->pflash.present) {
|
|
+ base = cc->pflash.window;
|
|
+ lim = cc->pflash.window_size;
|
|
+#ifdef CONFIG_BCMA_SFLASH
|
|
+ } else if (cc->sflash.present) {
|
|
+ base = cc->sflash.window;
|
|
+ lim = cc->sflash.size;
|
|
+#endif
|
|
+ } else {
|
|
+ pr_err("Couldn't find supported flash memory\n");
|
|
+ return -ENXIO;
|
|
+ }
|
|
+
|
|
+ return nvram_find_and_copy(base, lim);
|
|
}
|
|
+#endif
|
|
|
|
-int nvram_getenv(char *name, char *val, size_t val_len)
|
|
+static int nvram_init(void)
|
|
+{
|
|
+ switch (bcm47xx_bus_type) {
|
|
+#ifdef CONFIG_BCM47XX_SSB
|
|
+ case BCM47XX_BUS_TYPE_SSB:
|
|
+ return nvram_init_ssb();
|
|
+#endif
|
|
+#ifdef CONFIG_BCM47XX_BCMA
|
|
+ case BCM47XX_BUS_TYPE_BCMA:
|
|
+ return nvram_init_bcma();
|
|
+#endif
|
|
+ }
|
|
+ return -ENXIO;
|
|
+}
|
|
+
|
|
+int bcm47xx_nvram_getenv(char *name, char *val, size_t val_len)
|
|
{
|
|
char *var, *value, *end, *eq;
|
|
+ int err;
|
|
|
|
if (!name)
|
|
- return NVRAM_ERR_INV_PARAM;
|
|
+ return -EINVAL;
|
|
|
|
- if (!nvram_buf[0])
|
|
- early_nvram_init();
|
|
+ if (!nvram_buf[0]) {
|
|
+ err = nvram_init();
|
|
+ if (err)
|
|
+ return err;
|
|
+ }
|
|
|
|
/* Look for name=value and return value */
|
|
var = &nvram_buf[sizeof(struct nvram_header)];
|
|
@@ -110,6 +195,6 @@ int nvram_getenv(char *name, char *val,
|
|
return snprintf(val, val_len, "%s", value);
|
|
}
|
|
}
|
|
- return NVRAM_ERR_ENVNOTFOUND;
|
|
+ return -ENOENT;
|
|
}
|
|
-EXPORT_SYMBOL(nvram_getenv);
|
|
+EXPORT_SYMBOL(bcm47xx_nvram_getenv);
|
|
--- a/arch/mips/bcm47xx/setup.c
|
|
+++ b/arch/mips/bcm47xx/setup.c
|
|
@@ -35,7 +35,7 @@
|
|
#include <asm/reboot.h>
|
|
#include <asm/time.h>
|
|
#include <bcm47xx.h>
|
|
-#include <asm/mach-bcm47xx/nvram.h>
|
|
+#include <bcm47xx_nvram.h>
|
|
|
|
union bcm47xx_bus bcm47xx_bus;
|
|
EXPORT_SYMBOL(bcm47xx_bus);
|
|
@@ -115,7 +115,7 @@ static int bcm47xx_get_invariants(struct
|
|
memset(&iv->sprom, 0, sizeof(struct ssb_sprom));
|
|
bcm47xx_fill_sprom(&iv->sprom, NULL, false);
|
|
|
|
- if (nvram_getenv("cardbus", buf, sizeof(buf)) >= 0)
|
|
+ if (bcm47xx_nvram_getenv("cardbus", buf, sizeof(buf)) >= 0)
|
|
iv->has_cardbus_slot = !!simple_strtoul(buf, NULL, 10);
|
|
|
|
return 0;
|
|
@@ -138,7 +138,7 @@ static void __init bcm47xx_register_ssb(
|
|
panic("Failed to initialize SSB bus (err %d)", err);
|
|
|
|
mcore = &bcm47xx_bus.ssb.mipscore;
|
|
- if (nvram_getenv("kernel_args", buf, sizeof(buf)) >= 0) {
|
|
+ if (bcm47xx_nvram_getenv("kernel_args", buf, sizeof(buf)) >= 0) {
|
|
if (strstr(buf, "console=ttyS1")) {
|
|
struct ssb_serial_port port;
|
|
|
|
--- a/arch/mips/bcm47xx/sprom.c
|
|
+++ b/arch/mips/bcm47xx/sprom.c
|
|
@@ -27,7 +27,7 @@
|
|
*/
|
|
|
|
#include <bcm47xx.h>
|
|
-#include <nvram.h>
|
|
+#include <bcm47xx_nvram.h>
|
|
|
|
static void create_key(const char *prefix, const char *postfix,
|
|
const char *name, char *buf, int len)
|
|
@@ -50,10 +50,10 @@ static int get_nvram_var(const char *pre
|
|
|
|
create_key(prefix, postfix, name, key, sizeof(key));
|
|
|
|
- err = nvram_getenv(key, buf, len);
|
|
- if (fallback && err == NVRAM_ERR_ENVNOTFOUND && prefix) {
|
|
+ err = bcm47xx_nvram_getenv(key, buf, len);
|
|
+ if (fallback && err == -ENOENT && prefix) {
|
|
create_key(NULL, postfix, name, key, sizeof(key));
|
|
- err = nvram_getenv(key, buf, len);
|
|
+ err = bcm47xx_nvram_getenv(key, buf, len);
|
|
}
|
|
return err;
|
|
}
|
|
@@ -144,7 +144,7 @@ static void nvram_read_macaddr(const cha
|
|
if (err < 0)
|
|
return;
|
|
|
|
- nvram_parse_macaddr(buf, *val);
|
|
+ bcm47xx_nvram_parse_macaddr(buf, *val);
|
|
}
|
|
|
|
static void nvram_read_alpha2(const char *prefix, const char *name,
|
|
--- /dev/null
|
|
+++ b/arch/mips/include/asm/mach-bcm47xx/bcm47xx_nvram.h
|
|
@@ -0,0 +1,51 @@
|
|
+/*
|
|
+ * Copyright (C) 2005, Broadcom Corporation
|
|
+ * Copyright (C) 2006, Felix Fietkau <nbd@openwrt.org>
|
|
+ *
|
|
+ * 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.
|
|
+ */
|
|
+
|
|
+#ifndef __BCM47XX_NVRAM_H
|
|
+#define __BCM47XX_NVRAM_H
|
|
+
|
|
+#include <linux/types.h>
|
|
+#include <linux/kernel.h>
|
|
+
|
|
+struct nvram_header {
|
|
+ u32 magic;
|
|
+ u32 len;
|
|
+ u32 crc_ver_init; /* 0:7 crc, 8:15 ver, 16:31 sdram_init */
|
|
+ u32 config_refresh; /* 0:15 sdram_config, 16:31 sdram_refresh */
|
|
+ u32 config_ncdl; /* ncdl values for memc */
|
|
+};
|
|
+
|
|
+#define NVRAM_HEADER 0x48534C46 /* 'FLSH' */
|
|
+#define NVRAM_VERSION 1
|
|
+#define NVRAM_HEADER_SIZE 20
|
|
+#define NVRAM_SPACE 0x8000
|
|
+
|
|
+#define FLASH_MIN 0x00020000 /* Minimum flash size */
|
|
+
|
|
+#define NVRAM_MAX_VALUE_LEN 255
|
|
+#define NVRAM_MAX_PARAM_LEN 64
|
|
+
|
|
+extern int bcm47xx_nvram_getenv(char *name, char *val, size_t val_len);
|
|
+
|
|
+static inline void bcm47xx_nvram_parse_macaddr(char *buf, u8 macaddr[6])
|
|
+{
|
|
+ if (strchr(buf, ':'))
|
|
+ sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &macaddr[0],
|
|
+ &macaddr[1], &macaddr[2], &macaddr[3], &macaddr[4],
|
|
+ &macaddr[5]);
|
|
+ else if (strchr(buf, '-'))
|
|
+ sscanf(buf, "%hhx-%hhx-%hhx-%hhx-%hhx-%hhx", &macaddr[0],
|
|
+ &macaddr[1], &macaddr[2], &macaddr[3], &macaddr[4],
|
|
+ &macaddr[5]);
|
|
+ else
|
|
+ printk(KERN_WARNING "Can not parse mac address: %s\n", buf);
|
|
+}
|
|
+
|
|
+#endif /* __BCM47XX_NVRAM_H */
|
|
--- a/arch/mips/include/asm/mach-bcm47xx/nvram.h
|
|
+++ /dev/null
|
|
@@ -1,54 +0,0 @@
|
|
-/*
|
|
- * Copyright (C) 2005, Broadcom Corporation
|
|
- * Copyright (C) 2006, Felix Fietkau <nbd@openwrt.org>
|
|
- *
|
|
- * 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.
|
|
- */
|
|
-
|
|
-#ifndef __NVRAM_H
|
|
-#define __NVRAM_H
|
|
-
|
|
-#include <linux/types.h>
|
|
-#include <linux/kernel.h>
|
|
-
|
|
-struct nvram_header {
|
|
- u32 magic;
|
|
- u32 len;
|
|
- u32 crc_ver_init; /* 0:7 crc, 8:15 ver, 16:31 sdram_init */
|
|
- u32 config_refresh; /* 0:15 sdram_config, 16:31 sdram_refresh */
|
|
- u32 config_ncdl; /* ncdl values for memc */
|
|
-};
|
|
-
|
|
-#define NVRAM_HEADER 0x48534C46 /* 'FLSH' */
|
|
-#define NVRAM_VERSION 1
|
|
-#define NVRAM_HEADER_SIZE 20
|
|
-#define NVRAM_SPACE 0x8000
|
|
-
|
|
-#define FLASH_MIN 0x00020000 /* Minimum flash size */
|
|
-
|
|
-#define NVRAM_MAX_VALUE_LEN 255
|
|
-#define NVRAM_MAX_PARAM_LEN 64
|
|
-
|
|
-#define NVRAM_ERR_INV_PARAM -8
|
|
-#define NVRAM_ERR_ENVNOTFOUND -9
|
|
-
|
|
-extern int nvram_getenv(char *name, char *val, size_t val_len);
|
|
-
|
|
-static inline void nvram_parse_macaddr(char *buf, u8 macaddr[6])
|
|
-{
|
|
- if (strchr(buf, ':'))
|
|
- sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &macaddr[0],
|
|
- &macaddr[1], &macaddr[2], &macaddr[3], &macaddr[4],
|
|
- &macaddr[5]);
|
|
- else if (strchr(buf, '-'))
|
|
- sscanf(buf, "%hhx-%hhx-%hhx-%hhx-%hhx-%hhx", &macaddr[0],
|
|
- &macaddr[1], &macaddr[2], &macaddr[3], &macaddr[4],
|
|
- &macaddr[5]);
|
|
- else
|
|
- printk(KERN_WARNING "Can not parse mac address: %s\n", buf);
|
|
-}
|
|
-
|
|
-#endif
|
|
--- a/drivers/mtd/bcm47xxpart.c
|
|
+++ b/drivers/mtd/bcm47xxpart.c
|
|
@@ -14,7 +14,7 @@
|
|
#include <linux/slab.h>
|
|
#include <linux/mtd/mtd.h>
|
|
#include <linux/mtd/partitions.h>
|
|
-#include <asm/mach-bcm47xx/nvram.h>
|
|
+#include <bcm47xx_nvram.h>
|
|
|
|
/* 10 parts were found on sflash on Netgear WNDR4500 */
|
|
#define BCM47XXPART_MAX_PARTS 12
|
|
--- a/drivers/net/ethernet/broadcom/b44.c
|
|
+++ b/drivers/net/ethernet/broadcom/b44.c
|
|
@@ -381,7 +381,7 @@ static void b44_set_flow_ctrl(struct b44
|
|
}
|
|
|
|
#ifdef CONFIG_BCM47XX
|
|
-#include <asm/mach-bcm47xx/nvram.h>
|
|
+#include <bcm47xx_nvram.h>
|
|
static void b44_wap54g10_workaround(struct b44 *bp)
|
|
{
|
|
char buf[20];
|
|
@@ -393,7 +393,7 @@ static void b44_wap54g10_workaround(stru
|
|
* see https://dev.openwrt.org/ticket/146
|
|
* check and reset bit "isolate"
|
|
*/
|
|
- if (nvram_getenv("boardnum", buf, sizeof(buf)) < 0)
|
|
+ if (bcm47xx_nvram_getenv("boardnum", buf, sizeof(buf)) < 0)
|
|
return;
|
|
if (simple_strtoul(buf, NULL, 0) == 2) {
|
|
err = __b44_readphy(bp, 0, MII_BMCR, &val);
|
|
--- a/drivers/ssb/driver_chipcommon_pmu.c
|
|
+++ b/drivers/ssb/driver_chipcommon_pmu.c
|
|
@@ -14,7 +14,7 @@
|
|
#include <linux/delay.h>
|
|
#include <linux/export.h>
|
|
#ifdef CONFIG_BCM47XX
|
|
-#include <asm/mach-bcm47xx/nvram.h>
|
|
+#include <bcm47xx_nvram.h>
|
|
#endif
|
|
|
|
#include "ssb_private.h"
|
|
@@ -322,7 +322,7 @@ static void ssb_pmu_pll_init(struct ssb_
|
|
if (bus->bustype == SSB_BUSTYPE_SSB) {
|
|
#ifdef CONFIG_BCM47XX
|
|
char buf[20];
|
|
- if (nvram_getenv("xtalfreq", buf, sizeof(buf)) >= 0)
|
|
+ if (bcm47xx_nvram_getenv("xtalfreq", buf, sizeof(buf)) >= 0)
|
|
crystalfreq = simple_strtoul(buf, NULL, 0);
|
|
#endif
|
|
}
|
|
--- a/include/linux/ssb/ssb_driver_gige.h
|
|
+++ b/include/linux/ssb/ssb_driver_gige.h
|
|
@@ -98,14 +98,14 @@ static inline bool ssb_gige_must_flush_p
|
|
}
|
|
|
|
#ifdef CONFIG_BCM47XX
|
|
-#include <asm/mach-bcm47xx/nvram.h>
|
|
+#include <bcm47xx_nvram.h>
|
|
/* Get the device MAC address */
|
|
static inline void ssb_gige_get_macaddr(struct pci_dev *pdev, u8 *macaddr)
|
|
{
|
|
char buf[20];
|
|
- if (nvram_getenv("et0macaddr", buf, sizeof(buf)) < 0)
|
|
+ if (bcm47xx_nvram_getenv("et0macaddr", buf, sizeof(buf)) < 0)
|
|
return;
|
|
- nvram_parse_macaddr(buf, macaddr);
|
|
+ bcm47xx_nvram_parse_macaddr(buf, macaddr);
|
|
}
|
|
#else
|
|
static inline void ssb_gige_get_macaddr(struct pci_dev *pdev, u8 *macaddr)
|