diff options
Diffstat (limited to 'arch/mips/bcm47xx')
-rw-r--r-- | arch/mips/bcm47xx/Kconfig | 3 | ||||
-rw-r--r-- | arch/mips/bcm47xx/Makefile | 2 | ||||
-rw-r--r-- | arch/mips/bcm47xx/nvram.c | 163 | ||||
-rw-r--r-- | arch/mips/bcm47xx/serial.c | 2 | ||||
-rw-r--r-- | arch/mips/bcm47xx/setup.c | 6 | ||||
-rw-r--r-- | arch/mips/bcm47xx/sprom.c | 26 | ||||
-rw-r--r-- | arch/mips/bcm47xx/wgt634u.c | 40 |
7 files changed, 160 insertions, 82 deletions
diff --git a/arch/mips/bcm47xx/Kconfig b/arch/mips/bcm47xx/Kconfig index d7af29f1fcf0..ba611927749b 100644 --- a/arch/mips/bcm47xx/Kconfig +++ b/arch/mips/bcm47xx/Kconfig @@ -8,8 +8,10 @@ config BCM47XX_SSB select SSB_DRIVER_EXTIF select SSB_EMBEDDED select SSB_B43_PCI_BRIDGE if PCI + select SSB_DRIVER_PCICORE if PCI select SSB_PCICORE_HOSTMODE if PCI select SSB_DRIVER_GPIO + select GPIOLIB default y help Add support for old Broadcom BCM47xx boards with Sonics Silicon Backplane support. @@ -25,6 +27,7 @@ config BCM47XX_BCMA select BCMA_HOST_PCI if PCI select BCMA_DRIVER_PCI_HOSTMODE if PCI select BCMA_DRIVER_GPIO + select GPIOLIB default y help Add support for new Broadcom BCM47xx boards with Broadcom specific Advanced Microcontroller Bus. diff --git a/arch/mips/bcm47xx/Makefile b/arch/mips/bcm47xx/Makefile index 1a3567f07e73..f3bf6d5bfb9d 100644 --- a/arch/mips/bcm47xx/Makefile +++ b/arch/mips/bcm47xx/Makefile @@ -3,5 +3,5 @@ # under Linux. # -obj-y += irq.o nvram.o prom.o serial.o setup.o time.o sprom.o +obj-y += irq.o nvram.o prom.o serial.o setup.o time.o sprom.o obj-$(CONFIG_BCM47XX_SSB) += wgt634u.o diff --git a/arch/mips/bcm47xx/nvram.c b/arch/mips/bcm47xx/nvram.c index 48a4c70b3842..cc40b74940f5 100644 --- a/arch/mips/bcm47xx/nvram.c +++ b/arch/mips/bcm47xx/nvram.c @@ -3,10 +3,10 @@ * * 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 + * 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. */ @@ -18,83 +18,160 @@ #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; } -int nvram_getenv(char *name, char *val, size_t val_len) +#ifdef CONFIG_BCM47XX_SSB +static int nvram_init_ssb(void) +{ + struct ssb_mipscore *mcore = &bcm47xx_bus.ssb.mipscore; + u32 base; + u32 lim; + + if (mcore->pflash.present) { + base = mcore->pflash.window; + lim = mcore->pflash.window_size; + } 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 + +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 +187,6 @@ int nvram_getenv(char *name, char *val, size_t val_len) return snprintf(val, val_len, "%s", value); } } - return NVRAM_ERR_ENVNOTFOUND; + return -ENOENT; } -EXPORT_SYMBOL(nvram_getenv); +EXPORT_SYMBOL(bcm47xx_nvram_getenv); diff --git a/arch/mips/bcm47xx/serial.c b/arch/mips/bcm47xx/serial.c index 57981e4fe2bc..b8ef965705cf 100644 --- a/arch/mips/bcm47xx/serial.c +++ b/arch/mips/bcm47xx/serial.c @@ -62,7 +62,7 @@ static int __init uart8250_init_bcma(void) p->mapbase = (unsigned int) bcma_port->regs; p->membase = (void *) bcma_port->regs; - p->irq = bcma_port->irq + 2; + p->irq = bcma_port->irq; p->uartclk = bcma_port->baud_base; p->regshift = bcma_port->reg_shift; p->iotype = UPIO_MEM; diff --git a/arch/mips/bcm47xx/setup.c b/arch/mips/bcm47xx/setup.c index 4d54b58dbd32..b2246cd9ca12 100644 --- 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 ssb_bus *bus, 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(void) 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; diff --git a/arch/mips/bcm47xx/sprom.c b/arch/mips/bcm47xx/sprom.c index 289cc0a38638..ad03c931b905 100644 --- 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,18 +50,18 @@ static int get_nvram_var(const char *prefix, const char *postfix, 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; } #define NVRAM_READ_VAL(type) \ static void nvram_read_ ## type (const char *prefix, \ - const char *postfix, const char *name, \ - type *val, type allset, bool fallback) \ + const char *postfix, const char *name, \ + type *val, type allset, bool fallback) \ { \ char buf[100]; \ int err; \ @@ -71,7 +71,7 @@ static void nvram_read_ ## type (const char *prefix, \ fallback); \ if (err < 0) \ return; \ - err = kstrto ## type (buf, 0, &var); \ + err = kstrto ## type(strim(buf), 0, &var); \ if (err) { \ pr_warn("can not parse nvram name %s%s%s with value %s got %i\n", \ prefix, name, postfix, buf, err); \ @@ -99,7 +99,7 @@ static void nvram_read_u32_2(const char *prefix, const char *name, err = get_nvram_var(prefix, NULL, name, buf, sizeof(buf), fallback); if (err < 0) return; - err = kstrtou32(buf, 0, &val); + err = kstrtou32(strim(buf), 0, &val); if (err) { pr_warn("can not parse nvram name %s%s with value %s got %i\n", prefix, name, buf, err); @@ -120,7 +120,7 @@ static void nvram_read_leddc(const char *prefix, const char *name, err = get_nvram_var(prefix, NULL, name, buf, sizeof(buf), fallback); if (err < 0) return; - err = kstrtou32(buf, 0, &val); + err = kstrtou32(strim(buf), 0, &val); if (err) { pr_warn("can not parse nvram name %s%s with value %s got %i\n", prefix, name, buf, err); @@ -144,7 +144,7 @@ static void nvram_read_macaddr(const char *prefix, const char *name, 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, @@ -652,12 +652,10 @@ static void bcm47xx_fill_sprom_ethernet(struct ssb_sprom *sprom, static void bcm47xx_fill_board_data(struct ssb_sprom *sprom, const char *prefix, bool fallback) { - nvram_read_u16(prefix, NULL, "boardrev", &sprom->board_rev, 0, - fallback); + nvram_read_u16(prefix, NULL, "boardrev", &sprom->board_rev, 0, true); nvram_read_u16(prefix, NULL, "boardnum", &sprom->board_num, 0, fallback); - nvram_read_u16(prefix, NULL, "boardtype", &sprom->board_type, 0, - fallback); + nvram_read_u16(prefix, NULL, "boardtype", &sprom->board_type, 0, true); nvram_read_u32_2(prefix, "boardflags", &sprom->boardflags_lo, &sprom->boardflags_hi, fallback); nvram_read_u32_2(prefix, "boardflags2", &sprom->boardflags2_lo, diff --git a/arch/mips/bcm47xx/wgt634u.c b/arch/mips/bcm47xx/wgt634u.c index 9d111e8087ec..c63a4c287b5c 100644 --- a/arch/mips/bcm47xx/wgt634u.c +++ b/arch/mips/bcm47xx/wgt634u.c @@ -36,13 +36,13 @@ static struct gpio_led wgt634u_leds[] = { }; static struct gpio_led_platform_data wgt634u_led_data = { - .num_leds = ARRAY_SIZE(wgt634u_leds), - .leds = wgt634u_leds, + .num_leds = ARRAY_SIZE(wgt634u_leds), + .leds = wgt634u_leds, }; static struct platform_device wgt634u_gpio_leds = { - .name = "leds-gpio", - .id = -1, + .name = "leds-gpio", + .id = -1, .dev = { .platform_data = &wgt634u_led_data, } @@ -53,35 +53,35 @@ static struct platform_device wgt634u_gpio_leds = { firmware. */ static struct mtd_partition wgt634u_partitions[] = { { - .name = "cfe", - .offset = 0, - .size = 0x60000, /* 384k */ - .mask_flags = MTD_WRITEABLE /* force read-only */ + .name = "cfe", + .offset = 0, + .size = 0x60000, /* 384k */ + .mask_flags = MTD_WRITEABLE /* force read-only */ }, { - .name = "config", + .name = "config", .offset = 0x60000, - .size = 0x20000 /* 128k */ + .size = 0x20000 /* 128k */ }, { - .name = "linux", + .name = "linux", .offset = 0x80000, - .size = 0x140000 /* 1280k */ + .size = 0x140000 /* 1280k */ }, { - .name = "jffs", + .name = "jffs", .offset = 0x1c0000, - .size = 0x620000 /* 6272k */ + .size = 0x620000 /* 6272k */ }, { - .name = "nvram", + .name = "nvram", .offset = 0x7e0000, - .size = 0x20000 /* 128k */ + .size = 0x20000 /* 128k */ }, }; static struct physmap_flash_data wgt634u_flash_data = { - .parts = wgt634u_partitions, + .parts = wgt634u_partitions, .nr_parts = ARRAY_SIZE(wgt634u_partitions) }; @@ -90,9 +90,9 @@ static struct resource wgt634u_flash_resource = { }; static struct platform_device wgt634u_flash = { - .name = "physmap-flash", - .id = 0, - .dev = { .platform_data = &wgt634u_flash_data, }, + .name = "physmap-flash", + .id = 0, + .dev = { .platform_data = &wgt634u_flash_data, }, .resource = &wgt634u_flash_resource, .num_resources = 1, }; |