M7350v1_en_gpl

This commit is contained in:
T
2024-09-09 08:52:07 +00:00
commit f9cc65cfda
65988 changed files with 26357421 additions and 0 deletions

View File

@ -0,0 +1,31 @@
if BCM47XX
config BCM47XX_SSB
bool "SSB Support for Broadcom BCM47XX"
select SYS_HAS_CPU_MIPS32_R1
select SSB
select SSB_DRIVER_MIPS
select SSB_DRIVER_EXTIF
select SSB_EMBEDDED
select SSB_B43_PCI_BRIDGE if PCI
select SSB_PCICORE_HOSTMODE if PCI
default y
help
Add support for old Broadcom BCM47xx boards with Sonics Silicon Backplane support.
This will generate an image with support for SSB and MIPS32 R1 instruction set.
config BCM47XX_BCMA
bool "BCMA Support for Broadcom BCM47XX"
select SYS_HAS_CPU_MIPS32_R2
select BCMA
select BCMA_HOST_SOC
select BCMA_DRIVER_MIPS
select BCMA_DRIVER_PCI_HOSTMODE if PCI
default y
help
Add support for new Broadcom BCM47xx boards with Broadcom specific Advanced Microcontroller Bus.
This will generate an image with support for BCMA and MIPS32 R2 instruction set.
endif

View File

@ -0,0 +1,7 @@
#
# Makefile for the BCM47XX specific kernel interface routines
# under Linux.
#
obj-y += gpio.o irq.o nvram.o prom.o serial.o setup.o time.o sprom.o
obj-$(CONFIG_BCM47XX_SSB) += wgt634u.o

View File

@ -0,0 +1,7 @@
#
# Broadcom BCM47XX boards
#
platform-$(CONFIG_BCM47XX) += bcm47xx/
cflags-$(CONFIG_BCM47XX) += \
-I$(srctree)/arch/mips/include/asm/mach-bcm47xx
load-$(CONFIG_BCM47XX) := 0xffffffff80001000

View File

@ -0,0 +1,102 @@
/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) 2007 Aurelien Jarno <aurelien@aurel32.net>
*/
#include <linux/export.h>
#include <linux/ssb/ssb.h>
#include <linux/ssb/ssb_driver_chipcommon.h>
#include <linux/ssb/ssb_driver_extif.h>
#include <asm/mach-bcm47xx/bcm47xx.h>
#include <asm/mach-bcm47xx/gpio.h>
#if (BCM47XX_CHIPCO_GPIO_LINES > BCM47XX_EXTIF_GPIO_LINES)
static DECLARE_BITMAP(gpio_in_use, BCM47XX_CHIPCO_GPIO_LINES);
#else
static DECLARE_BITMAP(gpio_in_use, BCM47XX_EXTIF_GPIO_LINES);
#endif
int gpio_request(unsigned gpio, const char *tag)
{
switch (bcm47xx_bus_type) {
#ifdef CONFIG_BCM47XX_SSB
case BCM47XX_BUS_TYPE_SSB:
if (ssb_chipco_available(&bcm47xx_bus.ssb.chipco) &&
((unsigned)gpio >= BCM47XX_CHIPCO_GPIO_LINES))
return -EINVAL;
if (ssb_extif_available(&bcm47xx_bus.ssb.extif) &&
((unsigned)gpio >= BCM47XX_EXTIF_GPIO_LINES))
return -EINVAL;
if (test_and_set_bit(gpio, gpio_in_use))
return -EBUSY;
return 0;
#endif
#ifdef CONFIG_BCM47XX_BCMA
case BCM47XX_BUS_TYPE_BCMA:
if (gpio >= BCM47XX_CHIPCO_GPIO_LINES)
return -EINVAL;
if (test_and_set_bit(gpio, gpio_in_use))
return -EBUSY;
return 0;
#endif
}
return -EINVAL;
}
EXPORT_SYMBOL(gpio_request);
void gpio_free(unsigned gpio)
{
switch (bcm47xx_bus_type) {
#ifdef CONFIG_BCM47XX_SSB
case BCM47XX_BUS_TYPE_SSB:
if (ssb_chipco_available(&bcm47xx_bus.ssb.chipco) &&
((unsigned)gpio >= BCM47XX_CHIPCO_GPIO_LINES))
return;
if (ssb_extif_available(&bcm47xx_bus.ssb.extif) &&
((unsigned)gpio >= BCM47XX_EXTIF_GPIO_LINES))
return;
clear_bit(gpio, gpio_in_use);
return;
#endif
#ifdef CONFIG_BCM47XX_BCMA
case BCM47XX_BUS_TYPE_BCMA:
if (gpio >= BCM47XX_CHIPCO_GPIO_LINES)
return;
clear_bit(gpio, gpio_in_use);
return;
#endif
}
}
EXPORT_SYMBOL(gpio_free);
int gpio_to_irq(unsigned gpio)
{
switch (bcm47xx_bus_type) {
#ifdef CONFIG_BCM47XX_SSB
case BCM47XX_BUS_TYPE_SSB:
if (ssb_chipco_available(&bcm47xx_bus.ssb.chipco))
return ssb_mips_irq(bcm47xx_bus.ssb.chipco.dev) + 2;
else if (ssb_extif_available(&bcm47xx_bus.ssb.extif))
return ssb_mips_irq(bcm47xx_bus.ssb.extif.dev) + 2;
else
return -EINVAL;
#endif
#ifdef CONFIG_BCM47XX_BCMA
case BCM47XX_BUS_TYPE_BCMA:
return bcma_core_mips_irq(bcm47xx_bus.bcma.bus.drv_cc.core) + 2;
#endif
}
return -EINVAL;
}
EXPORT_SYMBOL_GPL(gpio_to_irq);

View File

@ -0,0 +1,67 @@
/*
* Copyright (C) 2004 Florian Schirmer <jolt@tuxbox.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.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* 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.
*/
#include <linux/types.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <asm/irq_cpu.h>
#include <bcm47xx.h>
void plat_irq_dispatch(void)
{
u32 cause;
cause = read_c0_cause() & read_c0_status() & CAUSEF_IP;
clear_c0_status(cause);
if (cause & CAUSEF_IP7)
do_IRQ(7);
if (cause & CAUSEF_IP2)
do_IRQ(2);
if (cause & CAUSEF_IP3)
do_IRQ(3);
if (cause & CAUSEF_IP4)
do_IRQ(4);
if (cause & CAUSEF_IP5)
do_IRQ(5);
if (cause & CAUSEF_IP6)
do_IRQ(6);
}
void __init arch_init_irq(void)
{
#ifdef CONFIG_BCM47XX_BCMA
if (bcm47xx_bus_type == BCM47XX_BUS_TYPE_BCMA) {
bcma_write32(bcm47xx_bus.bcma.bus.drv_mips.core,
BCMA_MIPS_MIPS74K_INTMASK(5), 1 << 31);
/*
* the kernel reads the timer irq from some register and thinks
* it's #5, but we offset it by 2 and route to #7
*/
cp0_compare_irq = 7;
}
#endif
mips_cpu_irq_init();
}

View File

@ -0,0 +1,115 @@
/*
* BCM947xx nvram variable access
*
* Copyright (C) 2005 Broadcom Corporation
* Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org>
* Copyright (C) 2010-2011 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
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
#include <linux/init.h>
#include <linux/types.h>
#include <linux/module.h>
#include <linux/ssb/ssb.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <asm/addrspace.h>
#include <asm/mach-bcm47xx/nvram.h>
#include <asm/mach-bcm47xx/bcm47xx.h>
static char nvram_buf[NVRAM_SPACE];
/* Probe for NVRAM header */
static void early_nvram_init(void)
{
#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;
switch (bcm47xx_bus_type) {
#ifdef CONFIG_BCM47XX_SSB
case BCM47XX_BUS_TYPE_SSB:
mcore_ssb = &bcm47xx_bus.ssb.mipscore;
base = mcore_ssb->flash_window;
lim = mcore_ssb->flash_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
}
off = FLASH_MIN;
while (off <= lim) {
/* Windowed flash access */
header = (struct nvram_header *)
KSEG1ADDR(base + off - NVRAM_SPACE);
if (header->magic == NVRAM_HEADER)
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)
goto found;
header = (struct nvram_header *) KSEG1ADDR(base + 1024);
if (header->magic == NVRAM_HEADER)
goto found;
return;
found:
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)
*dst++ = le32_to_cpu(*src++);
}
int nvram_getenv(char *name, char *val, size_t val_len)
{
char *var, *value, *end, *eq;
if (!name)
return NVRAM_ERR_INV_PARAM;
if (!nvram_buf[0])
early_nvram_init();
/* Look for name=value and return value */
var = &nvram_buf[sizeof(struct nvram_header)];
end = nvram_buf + sizeof(nvram_buf) - 2;
end[0] = end[1] = '\0';
for (; *var; var = value + strlen(value) + 1) {
eq = strchr(var, '=');
if (!eq)
break;
value = eq + 1;
if ((eq - var) == strlen(name) &&
strncmp(var, name, (eq - var)) == 0) {
return snprintf(val, val_len, "%s", value);
}
}
return NVRAM_ERR_ENVNOTFOUND;
}
EXPORT_SYMBOL(nvram_getenv);

View File

@ -0,0 +1,171 @@
/*
* Copyright (C) 2004 Florian Schirmer <jolt@tuxbox.org>
* Copyright (C) 2007 Aurelien Jarno <aurelien@aurel32.net>
*
* 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* 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.
*/
#include <linux/init.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/spinlock.h>
#include <asm/bootinfo.h>
#include <asm/fw/cfe/cfe_api.h>
#include <asm/fw/cfe/cfe_error.h>
static int cfe_cons_handle;
const char *get_system_type(void)
{
return "Broadcom BCM47XX";
}
void prom_putchar(char c)
{
while (cfe_write(cfe_cons_handle, &c, 1) == 0)
;
}
static __init void prom_init_cfe(void)
{
uint32_t cfe_ept;
uint32_t cfe_handle;
uint32_t cfe_eptseal;
int argc = fw_arg0;
char **envp = (char **) fw_arg2;
int *prom_vec = (int *) fw_arg3;
/*
* Check if a loader was used; if NOT, the 4 arguments are
* what CFE gives us (handle, 0, EPT and EPTSEAL)
*/
if (argc < 0) {
cfe_handle = (uint32_t)argc;
cfe_ept = (uint32_t)envp;
cfe_eptseal = (uint32_t)prom_vec;
} else {
if ((int)prom_vec < 0) {
/*
* Old loader; all it gives us is the handle,
* so use the "known" entrypoint and assume
* the seal.
*/
cfe_handle = (uint32_t)prom_vec;
cfe_ept = 0xBFC00500;
cfe_eptseal = CFE_EPTSEAL;
} else {
/*
* Newer loaders bundle the handle/ept/eptseal
* Note: prom_vec is in the loader's useg
* which is still alive in the TLB.
*/
cfe_handle = prom_vec[0];
cfe_ept = prom_vec[2];
cfe_eptseal = prom_vec[3];
}
}
if (cfe_eptseal != CFE_EPTSEAL) {
/* too early for panic to do any good */
printk(KERN_ERR "CFE's entrypoint seal doesn't match.");
while (1) ;
}
cfe_init(cfe_handle, cfe_ept);
}
static __init void prom_init_console(void)
{
/* Initialize CFE console */
cfe_cons_handle = cfe_getstdhandle(CFE_STDHANDLE_CONSOLE);
}
static __init void prom_init_cmdline(void)
{
static char buf[COMMAND_LINE_SIZE] __initdata;
/* Get the kernel command line from CFE */
if (cfe_getenv("LINUX_CMDLINE", buf, COMMAND_LINE_SIZE) >= 0) {
buf[COMMAND_LINE_SIZE - 1] = 0;
strcpy(arcs_cmdline, buf);
}
/* Force a console handover by adding a console= argument if needed,
* as CFE is not available anymore later in the boot process. */
if ((strstr(arcs_cmdline, "console=")) == NULL) {
/* Try to read the default serial port used by CFE */
if ((cfe_getenv("BOOT_CONSOLE", buf, COMMAND_LINE_SIZE) < 0)
|| (strncmp("uart", buf, 4)))
/* Default to uart0 */
strcpy(buf, "uart0");
/* Compute the new command line */
snprintf(arcs_cmdline, COMMAND_LINE_SIZE, "%s console=ttyS%c,115200",
arcs_cmdline, buf[4]);
}
}
static __init void prom_init_mem(void)
{
unsigned long mem;
unsigned long max;
/* Figure out memory size by finding aliases.
*
* We should theoretically use the mapping from CFE using cfe_enummem().
* However as the BCM47XX is mostly used on low-memory systems, we
* want to reuse the memory used by CFE (around 4MB). That means cfe_*
* functions stop to work at some point during the boot, we should only
* call them at the beginning of the boot.
*
* BCM47XX uses 128MB for addressing the ram, if the system contains
* less that that amount of ram it remaps the ram more often into the
* available space.
* Accessing memory after 128MB will cause an exception.
* max contains the biggest possible address supported by the platform.
* If the method wants to try something above we assume 128MB ram.
*/
max = ((unsigned long)(prom_init) | ((128 << 20) - 1));
for (mem = (1 << 20); mem < (128 << 20); mem += (1 << 20)) {
if (((unsigned long)(prom_init) + mem) > max) {
mem = (128 << 20);
printk(KERN_DEBUG "assume 128MB RAM\n");
break;
}
if (*(unsigned long *)((unsigned long)(prom_init) + mem) ==
*(unsigned long *)(prom_init))
break;
}
add_memory_region(0, mem, BOOT_MEM_RAM);
}
void __init prom_init(void)
{
prom_init_cfe();
prom_init_console();
prom_init_cmdline();
prom_init_mem();
}
void __init prom_free_prom_memory(void)
{
}

View File

@ -0,0 +1,94 @@
/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) 2007 Aurelien Jarno <aurelien@aurel32.net>
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/serial.h>
#include <linux/serial_8250.h>
#include <linux/ssb/ssb.h>
#include <bcm47xx.h>
static struct plat_serial8250_port uart8250_data[5];
static struct platform_device uart8250_device = {
.name = "serial8250",
.id = PLAT8250_DEV_PLATFORM,
.dev = {
.platform_data = uart8250_data,
},
};
#ifdef CONFIG_BCM47XX_SSB
static int __init uart8250_init_ssb(void)
{
int i;
struct ssb_mipscore *mcore = &(bcm47xx_bus.ssb.mipscore);
memset(&uart8250_data, 0, sizeof(uart8250_data));
for (i = 0; i < mcore->nr_serial_ports; i++) {
struct plat_serial8250_port *p = &(uart8250_data[i]);
struct ssb_serial_port *ssb_port = &(mcore->serial_ports[i]);
p->mapbase = (unsigned int) ssb_port->regs;
p->membase = (void *) ssb_port->regs;
p->irq = ssb_port->irq + 2;
p->uartclk = ssb_port->baud_base;
p->regshift = ssb_port->reg_shift;
p->iotype = UPIO_MEM;
p->flags = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ;
}
return platform_device_register(&uart8250_device);
}
#endif
#ifdef CONFIG_BCM47XX_BCMA
static int __init uart8250_init_bcma(void)
{
int i;
struct bcma_drv_cc *cc = &(bcm47xx_bus.bcma.bus.drv_cc);
memset(&uart8250_data, 0, sizeof(uart8250_data));
for (i = 0; i < cc->nr_serial_ports; i++) {
struct plat_serial8250_port *p = &(uart8250_data[i]);
struct bcma_serial_port *bcma_port;
bcma_port = &(cc->serial_ports[i]);
p->mapbase = (unsigned int) bcma_port->regs;
p->membase = (void *) bcma_port->regs;
p->irq = bcma_port->irq + 2;
p->uartclk = bcma_port->baud_base;
p->regshift = bcma_port->reg_shift;
p->iotype = UPIO_MEM;
p->flags = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ;
}
return platform_device_register(&uart8250_device);
}
#endif
static int __init uart8250_init(void)
{
switch (bcm47xx_bus_type) {
#ifdef CONFIG_BCM47XX_SSB
case BCM47XX_BUS_TYPE_SSB:
return uart8250_init_ssb();
#endif
#ifdef CONFIG_BCM47XX_BCMA
case BCM47XX_BUS_TYPE_BCMA:
return uart8250_init_bcma();
#endif
}
return -EINVAL;
}
module_init(uart8250_init);
MODULE_AUTHOR("Aurelien Jarno <aurelien@aurel32.net>");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("8250 UART probe driver for the BCM47XX platforms");

View File

@ -0,0 +1,242 @@
/*
* Copyright (C) 2004 Florian Schirmer <jolt@tuxbox.org>
* Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org>
* Copyright (C) 2006 Michael Buesch <m@bues.ch>
* Copyright (C) 2010 Waldemar Brodkorb <wbx@openadk.org>
* 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
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* 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.
*/
#include <linux/export.h>
#include <linux/types.h>
#include <linux/ssb/ssb.h>
#include <linux/ssb/ssb_embedded.h>
#include <linux/bcma/bcma_soc.h>
#include <asm/bootinfo.h>
#include <asm/reboot.h>
#include <asm/time.h>
#include <bcm47xx.h>
#include <asm/mach-bcm47xx/nvram.h>
union bcm47xx_bus bcm47xx_bus;
EXPORT_SYMBOL(bcm47xx_bus);
enum bcm47xx_bus_type bcm47xx_bus_type;
EXPORT_SYMBOL(bcm47xx_bus_type);
static void bcm47xx_machine_restart(char *command)
{
printk(KERN_ALERT "Please stand by while rebooting the system...\n");
local_irq_disable();
/* Set the watchdog timer to reset immediately */
switch (bcm47xx_bus_type) {
#ifdef CONFIG_BCM47XX_SSB
case BCM47XX_BUS_TYPE_SSB:
ssb_watchdog_timer_set(&bcm47xx_bus.ssb, 1);
break;
#endif
#ifdef CONFIG_BCM47XX_BCMA
case BCM47XX_BUS_TYPE_BCMA:
bcma_chipco_watchdog_timer_set(&bcm47xx_bus.bcma.bus.drv_cc, 1);
break;
#endif
}
while (1)
cpu_relax();
}
static void bcm47xx_machine_halt(void)
{
/* Disable interrupts and watchdog and spin forever */
local_irq_disable();
switch (bcm47xx_bus_type) {
#ifdef CONFIG_BCM47XX_SSB
case BCM47XX_BUS_TYPE_SSB:
ssb_watchdog_timer_set(&bcm47xx_bus.ssb, 0);
break;
#endif
#ifdef CONFIG_BCM47XX_BCMA
case BCM47XX_BUS_TYPE_BCMA:
bcma_chipco_watchdog_timer_set(&bcm47xx_bus.bcma.bus.drv_cc, 0);
break;
#endif
}
while (1)
cpu_relax();
}
#ifdef CONFIG_BCM47XX_SSB
static int bcm47xx_get_sprom_ssb(struct ssb_bus *bus, struct ssb_sprom *out)
{
char prefix[10];
if (bus->bustype == SSB_BUSTYPE_PCI) {
snprintf(prefix, sizeof(prefix), "pci/%u/%u/",
bus->host_pci->bus->number + 1,
PCI_SLOT(bus->host_pci->devfn));
bcm47xx_fill_sprom(out, prefix);
return 0;
} else {
printk(KERN_WARNING "bcm47xx: unable to fill SPROM for given bustype.\n");
return -EINVAL;
}
}
static int bcm47xx_get_invariants(struct ssb_bus *bus,
struct ssb_init_invariants *iv)
{
char buf[20];
/* Fill boardinfo structure */
memset(&(iv->boardinfo), 0 , sizeof(struct ssb_boardinfo));
if (nvram_getenv("boardvendor", buf, sizeof(buf)) >= 0)
iv->boardinfo.vendor = (u16)simple_strtoul(buf, NULL, 0);
else
iv->boardinfo.vendor = SSB_BOARDVENDOR_BCM;
if (nvram_getenv("boardtype", buf, sizeof(buf)) >= 0)
iv->boardinfo.type = (u16)simple_strtoul(buf, NULL, 0);
if (nvram_getenv("boardrev", buf, sizeof(buf)) >= 0)
iv->boardinfo.rev = (u16)simple_strtoul(buf, NULL, 0);
bcm47xx_fill_sprom(&iv->sprom, NULL);
if (nvram_getenv("cardbus", buf, sizeof(buf)) >= 0)
iv->has_cardbus_slot = !!simple_strtoul(buf, NULL, 10);
return 0;
}
static void __init bcm47xx_register_ssb(void)
{
int err;
char buf[100];
struct ssb_mipscore *mcore;
err = ssb_arch_register_fallback_sprom(&bcm47xx_get_sprom_ssb);
if (err)
printk(KERN_WARNING "bcm47xx: someone else already registered"
" a ssb SPROM callback handler (err %d)\n", err);
err = ssb_bus_ssbbus_register(&(bcm47xx_bus.ssb), SSB_ENUM_BASE,
bcm47xx_get_invariants);
if (err)
panic("Failed to initialize SSB bus (err %d)", err);
mcore = &bcm47xx_bus.ssb.mipscore;
if (nvram_getenv("kernel_args", buf, sizeof(buf)) >= 0) {
if (strstr(buf, "console=ttyS1")) {
struct ssb_serial_port port;
printk(KERN_DEBUG "Swapping serial ports!\n");
/* swap serial ports */
memcpy(&port, &mcore->serial_ports[0], sizeof(port));
memcpy(&mcore->serial_ports[0], &mcore->serial_ports[1],
sizeof(port));
memcpy(&mcore->serial_ports[1], &port, sizeof(port));
}
}
}
#endif
#ifdef CONFIG_BCM47XX_BCMA
static int bcm47xx_get_sprom_bcma(struct bcma_bus *bus, struct ssb_sprom *out)
{
char prefix[10];
struct bcma_device *core;
switch (bus->hosttype) {
case BCMA_HOSTTYPE_PCI:
snprintf(prefix, sizeof(prefix), "pci/%u/%u/",
bus->host_pci->bus->number + 1,
PCI_SLOT(bus->host_pci->devfn));
bcm47xx_fill_sprom(out, prefix);
return 0;
case BCMA_HOSTTYPE_SOC:
bcm47xx_fill_sprom_ethernet(out, NULL);
core = bcma_find_core(bus, BCMA_CORE_80211);
if (core) {
snprintf(prefix, sizeof(prefix), "sb/%u/",
core->core_index);
bcm47xx_fill_sprom(out, prefix);
}
return 0;
default:
pr_warn("bcm47xx: unable to fill SPROM for given bustype.\n");
return -EINVAL;
}
}
static void __init bcm47xx_register_bcma(void)
{
int err;
err = bcma_arch_register_fallback_sprom(&bcm47xx_get_sprom_bcma);
if (err)
pr_warn("bcm47xx: someone else already registered a bcma SPROM callback handler (err %d)\n", err);
err = bcma_host_soc_register(&bcm47xx_bus.bcma);
if (err)
panic("Failed to initialize BCMA bus (err %d)", err);
}
#endif
void __init plat_mem_setup(void)
{
struct cpuinfo_mips *c = &current_cpu_data;
if (c->cputype == CPU_74K) {
printk(KERN_INFO "bcm47xx: using bcma bus\n");
#ifdef CONFIG_BCM47XX_BCMA
bcm47xx_bus_type = BCM47XX_BUS_TYPE_BCMA;
bcm47xx_register_bcma();
#endif
} else {
printk(KERN_INFO "bcm47xx: using ssb bus\n");
#ifdef CONFIG_BCM47XX_SSB
bcm47xx_bus_type = BCM47XX_BUS_TYPE_SSB;
bcm47xx_register_ssb();
#endif
}
_machine_restart = bcm47xx_machine_restart;
_machine_halt = bcm47xx_machine_halt;
pm_power_off = bcm47xx_machine_halt;
}
static int __init bcm47xx_register_bus_complete(void)
{
switch (bcm47xx_bus_type) {
#ifdef CONFIG_BCM47XX_SSB
case BCM47XX_BUS_TYPE_SSB:
/* Nothing to do */
break;
#endif
#ifdef CONFIG_BCM47XX_BCMA
case BCM47XX_BUS_TYPE_BCMA:
bcma_bus_register(&bcm47xx_bus.bcma.bus);
break;
#endif
}
return 0;
}
device_initcall(bcm47xx_register_bus_complete);

View File

@ -0,0 +1,620 @@
/*
* Copyright (C) 2004 Florian Schirmer <jolt@tuxbox.org>
* Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org>
* Copyright (C) 2006 Michael Buesch <m@bues.ch>
* Copyright (C) 2010 Waldemar Brodkorb <wbx@openadk.org>
* 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
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* 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.
*/
#include <bcm47xx.h>
#include <nvram.h>
static void create_key(const char *prefix, const char *postfix,
const char *name, char *buf, int len)
{
if (prefix && postfix)
snprintf(buf, len, "%s%s%s", prefix, name, postfix);
else if (prefix)
snprintf(buf, len, "%s%s", prefix, name);
else if (postfix)
snprintf(buf, len, "%s%s", name, postfix);
else
snprintf(buf, len, "%s", name);
}
#define NVRAM_READ_VAL(type) \
static void nvram_read_ ## type (const char *prefix, \
const char *postfix, const char *name, \
type *val, type allset) \
{ \
char buf[100]; \
char key[40]; \
int err; \
type var; \
\
create_key(prefix, postfix, name, key, sizeof(key)); \
\
err = nvram_getenv(key, buf, sizeof(buf)); \
if (err < 0) \
return; \
err = kstrto ## type (buf, 0, &var); \
if (err) { \
pr_warn("can not parse nvram name %s with value %s" \
" got %i", key, buf, err); \
return; \
} \
if (allset && var == allset) \
return; \
*val = var; \
}
NVRAM_READ_VAL(u8)
NVRAM_READ_VAL(s8)
NVRAM_READ_VAL(u16)
NVRAM_READ_VAL(u32)
#undef NVRAM_READ_VAL
static void nvram_read_u32_2(const char *prefix, const char *name,
u16 *val_lo, u16 *val_hi)
{
char buf[100];
char key[40];
int err;
u32 val;
create_key(prefix, NULL, name, key, sizeof(key));
err = nvram_getenv(key, buf, sizeof(buf));
if (err < 0)
return;
err = kstrtou32(buf, 0, &val);
if (err) {
pr_warn("can not parse nvram name %s with value %s got %i",
key, buf, err);
return;
}
*val_lo = (val & 0x0000FFFFU);
*val_hi = (val & 0xFFFF0000U) >> 16;
}
static void nvram_read_leddc(const char *prefix, const char *name,
u8 *leddc_on_time, u8 *leddc_off_time)
{
char buf[100];
char key[40];
int err;
u32 val;
create_key(prefix, NULL, name, key, sizeof(key));
err = nvram_getenv(key, buf, sizeof(buf));
if (err < 0)
return;
err = kstrtou32(buf, 0, &val);
if (err) {
pr_warn("can not parse nvram name %s with value %s got %i",
key, buf, err);
return;
}
if (val == 0xffff || val == 0xffffffff)
return;
*leddc_on_time = val & 0xff;
*leddc_off_time = (val >> 16) & 0xff;
}
static void nvram_read_macaddr(const char *prefix, const char *name,
u8 (*val)[6])
{
char buf[100];
char key[40];
int err;
create_key(prefix, NULL, name, key, sizeof(key));
err = nvram_getenv(key, buf, sizeof(buf));
if (err < 0)
return;
nvram_parse_macaddr(buf, *val);
}
static void nvram_read_alpha2(const char *prefix, const char *name,
char (*val)[2])
{
char buf[10];
char key[40];
int err;
create_key(prefix, NULL, name, key, sizeof(key));
err = nvram_getenv(key, buf, sizeof(buf));
if (err < 0)
return;
if (buf[0] == '0')
return;
if (strlen(buf) > 2) {
pr_warn("alpha2 is too long %s", buf);
return;
}
memcpy(val, buf, sizeof(val));
}
static void bcm47xx_fill_sprom_r1234589(struct ssb_sprom *sprom,
const char *prefix)
{
nvram_read_u16(prefix, NULL, "boardrev", &sprom->board_rev, 0);
nvram_read_u16(prefix, NULL, "boardnum", &sprom->board_num, 0);
nvram_read_u8(prefix, NULL, "ledbh0", &sprom->gpio0, 0xff);
nvram_read_u8(prefix, NULL, "ledbh1", &sprom->gpio1, 0xff);
nvram_read_u8(prefix, NULL, "ledbh2", &sprom->gpio2, 0xff);
nvram_read_u8(prefix, NULL, "ledbh3", &sprom->gpio3, 0xff);
nvram_read_u8(prefix, NULL, "aa2g", &sprom->ant_available_bg, 0);
nvram_read_u8(prefix, NULL, "aa5g", &sprom->ant_available_a, 0);
nvram_read_s8(prefix, NULL, "ag0", &sprom->antenna_gain.a0, 0);
nvram_read_s8(prefix, NULL, "ag1", &sprom->antenna_gain.a1, 0);
nvram_read_alpha2(prefix, "ccode", &sprom->alpha2);
}
static void bcm47xx_fill_sprom_r12389(struct ssb_sprom *sprom,
const char *prefix)
{
nvram_read_u16(prefix, NULL, "pa0b0", &sprom->pa0b0, 0);
nvram_read_u16(prefix, NULL, "pa0b1", &sprom->pa0b1, 0);
nvram_read_u16(prefix, NULL, "pa0b2", &sprom->pa0b2, 0);
nvram_read_u8(prefix, NULL, "pa0itssit", &sprom->itssi_bg, 0);
nvram_read_u8(prefix, NULL, "pa0maxpwr", &sprom->maxpwr_bg, 0);
nvram_read_u16(prefix, NULL, "pa1b0", &sprom->pa1b0, 0);
nvram_read_u16(prefix, NULL, "pa1b1", &sprom->pa1b1, 0);
nvram_read_u16(prefix, NULL, "pa1b2", &sprom->pa1b2, 0);
nvram_read_u8(prefix, NULL, "pa1itssit", &sprom->itssi_a, 0);
nvram_read_u8(prefix, NULL, "pa1maxpwr", &sprom->maxpwr_a, 0);
}
static void bcm47xx_fill_sprom_r1(struct ssb_sprom *sprom, const char *prefix)
{
nvram_read_u16(prefix, NULL, "boardflags", &sprom->boardflags_lo, 0);
nvram_read_u8(prefix, NULL, "cc", &sprom->country_code, 0);
}
static void bcm47xx_fill_sprom_r2389(struct ssb_sprom *sprom,
const char *prefix)
{
nvram_read_u8(prefix, NULL, "opo", &sprom->opo, 0);
nvram_read_u16(prefix, NULL, "pa1lob0", &sprom->pa1lob0, 0);
nvram_read_u16(prefix, NULL, "pa1lob1", &sprom->pa1lob1, 0);
nvram_read_u16(prefix, NULL, "pa1lob2", &sprom->pa1lob2, 0);
nvram_read_u16(prefix, NULL, "pa1hib0", &sprom->pa1hib0, 0);
nvram_read_u16(prefix, NULL, "pa1hib1", &sprom->pa1hib1, 0);
nvram_read_u16(prefix, NULL, "pa1hib2", &sprom->pa1hib2, 0);
nvram_read_u8(prefix, NULL, "pa1lomaxpwr", &sprom->maxpwr_al, 0);
nvram_read_u8(prefix, NULL, "pa1himaxpwr", &sprom->maxpwr_ah, 0);
}
static void bcm47xx_fill_sprom_r2(struct ssb_sprom *sprom, const char *prefix)
{
nvram_read_u32_2(prefix, "boardflags", &sprom->boardflags_lo,
&sprom->boardflags_hi);
nvram_read_u16(prefix, NULL, "boardtype", &sprom->board_type, 0);
}
static void bcm47xx_fill_sprom_r389(struct ssb_sprom *sprom, const char *prefix)
{
nvram_read_u8(prefix, NULL, "bxa2g", &sprom->bxa2g, 0);
nvram_read_u8(prefix, NULL, "rssisav2g", &sprom->rssisav2g, 0);
nvram_read_u8(prefix, NULL, "rssismc2g", &sprom->rssismc2g, 0);
nvram_read_u8(prefix, NULL, "rssismf2g", &sprom->rssismf2g, 0);
nvram_read_u8(prefix, NULL, "bxa5g", &sprom->bxa5g, 0);
nvram_read_u8(prefix, NULL, "rssisav5g", &sprom->rssisav5g, 0);
nvram_read_u8(prefix, NULL, "rssismc5g", &sprom->rssismc5g, 0);
nvram_read_u8(prefix, NULL, "rssismf5g", &sprom->rssismf5g, 0);
nvram_read_u8(prefix, NULL, "tri2g", &sprom->tri2g, 0);
nvram_read_u8(prefix, NULL, "tri5g", &sprom->tri5g, 0);
nvram_read_u8(prefix, NULL, "tri5gl", &sprom->tri5gl, 0);
nvram_read_u8(prefix, NULL, "tri5gh", &sprom->tri5gh, 0);
nvram_read_s8(prefix, NULL, "rxpo2g", &sprom->rxpo2g, 0);
nvram_read_s8(prefix, NULL, "rxpo5g", &sprom->rxpo5g, 0);
}
static void bcm47xx_fill_sprom_r3(struct ssb_sprom *sprom, const char *prefix)
{
nvram_read_u32_2(prefix, "boardflags", &sprom->boardflags_lo,
&sprom->boardflags_hi);
nvram_read_u16(prefix, NULL, "boardtype", &sprom->board_type, 0);
nvram_read_u8(prefix, NULL, "regrev", &sprom->regrev, 0);
nvram_read_leddc(prefix, "leddc", &sprom->leddc_on_time,
&sprom->leddc_off_time);
}
static void bcm47xx_fill_sprom_r4589(struct ssb_sprom *sprom,
const char *prefix)
{
nvram_read_u32_2(prefix, "boardflags", &sprom->boardflags_lo,
&sprom->boardflags_hi);
nvram_read_u32_2(prefix, "boardflags2", &sprom->boardflags2_lo,
&sprom->boardflags2_hi);
nvram_read_u16(prefix, NULL, "boardtype", &sprom->board_type, 0);
nvram_read_u8(prefix, NULL, "regrev", &sprom->regrev, 0);
nvram_read_s8(prefix, NULL, "ag2", &sprom->antenna_gain.a2, 0);
nvram_read_s8(prefix, NULL, "ag3", &sprom->antenna_gain.a3, 0);
nvram_read_u8(prefix, NULL, "txchain", &sprom->txchain, 0xf);
nvram_read_u8(prefix, NULL, "rxchain", &sprom->rxchain, 0xf);
nvram_read_u8(prefix, NULL, "antswitch", &sprom->antswitch, 0xff);
nvram_read_leddc(prefix, "leddc", &sprom->leddc_on_time,
&sprom->leddc_off_time);
}
static void bcm47xx_fill_sprom_r458(struct ssb_sprom *sprom, const char *prefix)
{
nvram_read_u16(prefix, NULL, "cck2gpo", &sprom->cck2gpo, 0);
nvram_read_u32(prefix, NULL, "ofdm2gpo", &sprom->ofdm2gpo, 0);
nvram_read_u32(prefix, NULL, "ofdm5gpo", &sprom->ofdm5gpo, 0);
nvram_read_u32(prefix, NULL, "ofdm5glpo", &sprom->ofdm5glpo, 0);
nvram_read_u32(prefix, NULL, "ofdm5ghpo", &sprom->ofdm5ghpo, 0);
nvram_read_u16(prefix, NULL, "cddpo", &sprom->cddpo, 0);
nvram_read_u16(prefix, NULL, "stbcpo", &sprom->stbcpo, 0);
nvram_read_u16(prefix, NULL, "bw40po", &sprom->bw40po, 0);
nvram_read_u16(prefix, NULL, "bwduppo", &sprom->bwduppo, 0);
nvram_read_u16(prefix, NULL, "mcs2gpo0", &sprom->mcs2gpo[0], 0);
nvram_read_u16(prefix, NULL, "mcs2gpo1", &sprom->mcs2gpo[1], 0);
nvram_read_u16(prefix, NULL, "mcs2gpo2", &sprom->mcs2gpo[2], 0);
nvram_read_u16(prefix, NULL, "mcs2gpo3", &sprom->mcs2gpo[3], 0);
nvram_read_u16(prefix, NULL, "mcs2gpo4", &sprom->mcs2gpo[4], 0);
nvram_read_u16(prefix, NULL, "mcs2gpo5", &sprom->mcs2gpo[5], 0);
nvram_read_u16(prefix, NULL, "mcs2gpo6", &sprom->mcs2gpo[6], 0);
nvram_read_u16(prefix, NULL, "mcs2gpo7", &sprom->mcs2gpo[7], 0);
nvram_read_u16(prefix, NULL, "mcs5gpo0", &sprom->mcs5gpo[0], 0);
nvram_read_u16(prefix, NULL, "mcs5gpo1", &sprom->mcs5gpo[1], 0);
nvram_read_u16(prefix, NULL, "mcs5gpo2", &sprom->mcs5gpo[2], 0);
nvram_read_u16(prefix, NULL, "mcs5gpo3", &sprom->mcs5gpo[3], 0);
nvram_read_u16(prefix, NULL, "mcs5gpo4", &sprom->mcs5gpo[4], 0);
nvram_read_u16(prefix, NULL, "mcs5gpo5", &sprom->mcs5gpo[5], 0);
nvram_read_u16(prefix, NULL, "mcs5gpo6", &sprom->mcs5gpo[6], 0);
nvram_read_u16(prefix, NULL, "mcs5gpo7", &sprom->mcs5gpo[7], 0);
nvram_read_u16(prefix, NULL, "mcs5glpo0", &sprom->mcs5glpo[0], 0);
nvram_read_u16(prefix, NULL, "mcs5glpo1", &sprom->mcs5glpo[1], 0);
nvram_read_u16(prefix, NULL, "mcs5glpo2", &sprom->mcs5glpo[2], 0);
nvram_read_u16(prefix, NULL, "mcs5glpo3", &sprom->mcs5glpo[3], 0);
nvram_read_u16(prefix, NULL, "mcs5glpo4", &sprom->mcs5glpo[4], 0);
nvram_read_u16(prefix, NULL, "mcs5glpo5", &sprom->mcs5glpo[5], 0);
nvram_read_u16(prefix, NULL, "mcs5glpo6", &sprom->mcs5glpo[6], 0);
nvram_read_u16(prefix, NULL, "mcs5glpo7", &sprom->mcs5glpo[7], 0);
nvram_read_u16(prefix, NULL, "mcs5ghpo0", &sprom->mcs5ghpo[0], 0);
nvram_read_u16(prefix, NULL, "mcs5ghpo1", &sprom->mcs5ghpo[1], 0);
nvram_read_u16(prefix, NULL, "mcs5ghpo2", &sprom->mcs5ghpo[2], 0);
nvram_read_u16(prefix, NULL, "mcs5ghpo3", &sprom->mcs5ghpo[3], 0);
nvram_read_u16(prefix, NULL, "mcs5ghpo4", &sprom->mcs5ghpo[4], 0);
nvram_read_u16(prefix, NULL, "mcs5ghpo5", &sprom->mcs5ghpo[5], 0);
nvram_read_u16(prefix, NULL, "mcs5ghpo6", &sprom->mcs5ghpo[6], 0);
nvram_read_u16(prefix, NULL, "mcs5ghpo7", &sprom->mcs5ghpo[7], 0);
}
static void bcm47xx_fill_sprom_r45(struct ssb_sprom *sprom, const char *prefix)
{
nvram_read_u8(prefix, NULL, "txpid2ga0", &sprom->txpid2g[0], 0);
nvram_read_u8(prefix, NULL, "txpid2ga1", &sprom->txpid2g[1], 0);
nvram_read_u8(prefix, NULL, "txpid2ga2", &sprom->txpid2g[2], 0);
nvram_read_u8(prefix, NULL, "txpid2ga3", &sprom->txpid2g[3], 0);
nvram_read_u8(prefix, NULL, "txpid5ga0", &sprom->txpid5g[0], 0);
nvram_read_u8(prefix, NULL, "txpid5ga1", &sprom->txpid5g[1], 0);
nvram_read_u8(prefix, NULL, "txpid5ga2", &sprom->txpid5g[2], 0);
nvram_read_u8(prefix, NULL, "txpid5ga3", &sprom->txpid5g[3], 0);
nvram_read_u8(prefix, NULL, "txpid5gla0", &sprom->txpid5gl[0], 0);
nvram_read_u8(prefix, NULL, "txpid5gla1", &sprom->txpid5gl[1], 0);
nvram_read_u8(prefix, NULL, "txpid5gla2", &sprom->txpid5gl[2], 0);
nvram_read_u8(prefix, NULL, "txpid5gla3", &sprom->txpid5gl[3], 0);
nvram_read_u8(prefix, NULL, "txpid5gha0", &sprom->txpid5gh[0], 0);
nvram_read_u8(prefix, NULL, "txpid5gha1", &sprom->txpid5gh[1], 0);
nvram_read_u8(prefix, NULL, "txpid5gha2", &sprom->txpid5gh[2], 0);
nvram_read_u8(prefix, NULL, "txpid5gha3", &sprom->txpid5gh[3], 0);
}
static void bcm47xx_fill_sprom_r89(struct ssb_sprom *sprom, const char *prefix)
{
nvram_read_u8(prefix, NULL, "tssipos2g", &sprom->fem.ghz2.tssipos, 0);
nvram_read_u8(prefix, NULL, "extpagain2g",
&sprom->fem.ghz2.extpa_gain, 0);
nvram_read_u8(prefix, NULL, "pdetrange2g",
&sprom->fem.ghz2.pdet_range, 0);
nvram_read_u8(prefix, NULL, "triso2g", &sprom->fem.ghz2.tr_iso, 0);
nvram_read_u8(prefix, NULL, "antswctl2g", &sprom->fem.ghz2.antswlut, 0);
nvram_read_u8(prefix, NULL, "tssipos5g", &sprom->fem.ghz5.tssipos, 0);
nvram_read_u8(prefix, NULL, "extpagain5g",
&sprom->fem.ghz5.extpa_gain, 0);
nvram_read_u8(prefix, NULL, "pdetrange5g",
&sprom->fem.ghz5.pdet_range, 0);
nvram_read_u8(prefix, NULL, "triso5g", &sprom->fem.ghz5.tr_iso, 0);
nvram_read_u8(prefix, NULL, "antswctl5g", &sprom->fem.ghz5.antswlut, 0);
nvram_read_u8(prefix, NULL, "tempthresh", &sprom->tempthresh, 0);
nvram_read_u8(prefix, NULL, "tempoffset", &sprom->tempoffset, 0);
nvram_read_u16(prefix, NULL, "rawtempsense", &sprom->rawtempsense, 0);
nvram_read_u8(prefix, NULL, "measpower", &sprom->measpower, 0);
nvram_read_u8(prefix, NULL, "tempsense_slope",
&sprom->tempsense_slope, 0);
nvram_read_u8(prefix, NULL, "tempcorrx", &sprom->tempcorrx, 0);
nvram_read_u8(prefix, NULL, "tempsense_option",
&sprom->tempsense_option, 0);
nvram_read_u8(prefix, NULL, "freqoffset_corr",
&sprom->freqoffset_corr, 0);
nvram_read_u8(prefix, NULL, "iqcal_swp_dis", &sprom->iqcal_swp_dis, 0);
nvram_read_u8(prefix, NULL, "hw_iqcal_en", &sprom->hw_iqcal_en, 0);
nvram_read_u8(prefix, NULL, "elna2g", &sprom->elna2g, 0);
nvram_read_u8(prefix, NULL, "elna5g", &sprom->elna5g, 0);
nvram_read_u8(prefix, NULL, "phycal_tempdelta",
&sprom->phycal_tempdelta, 0);
nvram_read_u8(prefix, NULL, "temps_period", &sprom->temps_period, 0);
nvram_read_u8(prefix, NULL, "temps_hysteresis",
&sprom->temps_hysteresis, 0);
nvram_read_u8(prefix, NULL, "measpower1", &sprom->measpower1, 0);
nvram_read_u8(prefix, NULL, "measpower2", &sprom->measpower2, 0);
nvram_read_u8(prefix, NULL, "rxgainerr2ga0",
&sprom->rxgainerr2ga[0], 0);
nvram_read_u8(prefix, NULL, "rxgainerr2ga1",
&sprom->rxgainerr2ga[1], 0);
nvram_read_u8(prefix, NULL, "rxgainerr2ga2",
&sprom->rxgainerr2ga[2], 0);
nvram_read_u8(prefix, NULL, "rxgainerr5gla0",
&sprom->rxgainerr5gla[0], 0);
nvram_read_u8(prefix, NULL, "rxgainerr5gla1",
&sprom->rxgainerr5gla[1], 0);
nvram_read_u8(prefix, NULL, "rxgainerr5gla2",
&sprom->rxgainerr5gla[2], 0);
nvram_read_u8(prefix, NULL, "rxgainerr5gma0",
&sprom->rxgainerr5gma[0], 0);
nvram_read_u8(prefix, NULL, "rxgainerr5gma1",
&sprom->rxgainerr5gma[1], 0);
nvram_read_u8(prefix, NULL, "rxgainerr5gma2",
&sprom->rxgainerr5gma[2], 0);
nvram_read_u8(prefix, NULL, "rxgainerr5gha0",
&sprom->rxgainerr5gha[0], 0);
nvram_read_u8(prefix, NULL, "rxgainerr5gha1",
&sprom->rxgainerr5gha[1], 0);
nvram_read_u8(prefix, NULL, "rxgainerr5gha2",
&sprom->rxgainerr5gha[2], 0);
nvram_read_u8(prefix, NULL, "rxgainerr5gua0",
&sprom->rxgainerr5gua[0], 0);
nvram_read_u8(prefix, NULL, "rxgainerr5gua1",
&sprom->rxgainerr5gua[1], 0);
nvram_read_u8(prefix, NULL, "rxgainerr5gua2",
&sprom->rxgainerr5gua[2], 0);
nvram_read_u8(prefix, NULL, "noiselvl2ga0", &sprom->noiselvl2ga[0], 0);
nvram_read_u8(prefix, NULL, "noiselvl2ga1", &sprom->noiselvl2ga[1], 0);
nvram_read_u8(prefix, NULL, "noiselvl2ga2", &sprom->noiselvl2ga[2], 0);
nvram_read_u8(prefix, NULL, "noiselvl5gla0",
&sprom->noiselvl5gla[0], 0);
nvram_read_u8(prefix, NULL, "noiselvl5gla1",
&sprom->noiselvl5gla[1], 0);
nvram_read_u8(prefix, NULL, "noiselvl5gla2",
&sprom->noiselvl5gla[2], 0);
nvram_read_u8(prefix, NULL, "noiselvl5gma0",
&sprom->noiselvl5gma[0], 0);
nvram_read_u8(prefix, NULL, "noiselvl5gma1",
&sprom->noiselvl5gma[1], 0);
nvram_read_u8(prefix, NULL, "noiselvl5gma2",
&sprom->noiselvl5gma[2], 0);
nvram_read_u8(prefix, NULL, "noiselvl5gha0",
&sprom->noiselvl5gha[0], 0);
nvram_read_u8(prefix, NULL, "noiselvl5gha1",
&sprom->noiselvl5gha[1], 0);
nvram_read_u8(prefix, NULL, "noiselvl5gha2",
&sprom->noiselvl5gha[2], 0);
nvram_read_u8(prefix, NULL, "noiselvl5gua0",
&sprom->noiselvl5gua[0], 0);
nvram_read_u8(prefix, NULL, "noiselvl5gua1",
&sprom->noiselvl5gua[1], 0);
nvram_read_u8(prefix, NULL, "noiselvl5gua2",
&sprom->noiselvl5gua[2], 0);
nvram_read_u8(prefix, NULL, "pcieingress_war",
&sprom->pcieingress_war, 0);
}
static void bcm47xx_fill_sprom_r9(struct ssb_sprom *sprom, const char *prefix)
{
nvram_read_u16(prefix, NULL, "cckbw202gpo", &sprom->cckbw202gpo, 0);
nvram_read_u16(prefix, NULL, "cckbw20ul2gpo", &sprom->cckbw20ul2gpo, 0);
nvram_read_u32(prefix, NULL, "legofdmbw202gpo",
&sprom->legofdmbw202gpo, 0);
nvram_read_u32(prefix, NULL, "legofdmbw20ul2gpo",
&sprom->legofdmbw20ul2gpo, 0);
nvram_read_u32(prefix, NULL, "legofdmbw205glpo",
&sprom->legofdmbw205glpo, 0);
nvram_read_u32(prefix, NULL, "legofdmbw20ul5glpo",
&sprom->legofdmbw20ul5glpo, 0);
nvram_read_u32(prefix, NULL, "legofdmbw205gmpo",
&sprom->legofdmbw205gmpo, 0);
nvram_read_u32(prefix, NULL, "legofdmbw20ul5gmpo",
&sprom->legofdmbw20ul5gmpo, 0);
nvram_read_u32(prefix, NULL, "legofdmbw205ghpo",
&sprom->legofdmbw205ghpo, 0);
nvram_read_u32(prefix, NULL, "legofdmbw20ul5ghpo",
&sprom->legofdmbw20ul5ghpo, 0);
nvram_read_u32(prefix, NULL, "mcsbw202gpo", &sprom->mcsbw202gpo, 0);
nvram_read_u32(prefix, NULL, "mcsbw20ul2gpo", &sprom->mcsbw20ul2gpo, 0);
nvram_read_u32(prefix, NULL, "mcsbw402gpo", &sprom->mcsbw402gpo, 0);
nvram_read_u32(prefix, NULL, "mcsbw205glpo", &sprom->mcsbw205glpo, 0);
nvram_read_u32(prefix, NULL, "mcsbw20ul5glpo",
&sprom->mcsbw20ul5glpo, 0);
nvram_read_u32(prefix, NULL, "mcsbw405glpo", &sprom->mcsbw405glpo, 0);
nvram_read_u32(prefix, NULL, "mcsbw205gmpo", &sprom->mcsbw205gmpo, 0);
nvram_read_u32(prefix, NULL, "mcsbw20ul5gmpo",
&sprom->mcsbw20ul5gmpo, 0);
nvram_read_u32(prefix, NULL, "mcsbw405gmpo", &sprom->mcsbw405gmpo, 0);
nvram_read_u32(prefix, NULL, "mcsbw205ghpo", &sprom->mcsbw205ghpo, 0);
nvram_read_u32(prefix, NULL, "mcsbw20ul5ghpo",
&sprom->mcsbw20ul5ghpo, 0);
nvram_read_u32(prefix, NULL, "mcsbw405ghpo", &sprom->mcsbw405ghpo, 0);
nvram_read_u16(prefix, NULL, "mcs32po", &sprom->mcs32po, 0);
nvram_read_u16(prefix, NULL, "legofdm40duppo",
&sprom->legofdm40duppo, 0);
nvram_read_u8(prefix, NULL, "sar2g", &sprom->sar2g, 0);
nvram_read_u8(prefix, NULL, "sar5g", &sprom->sar5g, 0);
}
static void bcm47xx_fill_sprom_path_r4589(struct ssb_sprom *sprom,
const char *prefix)
{
char postfix[2];
int i;
for (i = 0; i < ARRAY_SIZE(sprom->core_pwr_info); i++) {
struct ssb_sprom_core_pwr_info *pwr_info = &sprom->core_pwr_info[i];
snprintf(postfix, sizeof(postfix), "%i", i);
nvram_read_u8(prefix, postfix, "maxp2ga",
&pwr_info->maxpwr_2g, 0);
nvram_read_u8(prefix, postfix, "itt2ga",
&pwr_info->itssi_2g, 0);
nvram_read_u8(prefix, postfix, "itt5ga",
&pwr_info->itssi_5g, 0);
nvram_read_u16(prefix, postfix, "pa2gw0a",
&pwr_info->pa_2g[0], 0);
nvram_read_u16(prefix, postfix, "pa2gw1a",
&pwr_info->pa_2g[1], 0);
nvram_read_u16(prefix, postfix, "pa2gw2a",
&pwr_info->pa_2g[2], 0);
nvram_read_u8(prefix, postfix, "maxp5ga",
&pwr_info->maxpwr_5g, 0);
nvram_read_u8(prefix, postfix, "maxp5gha",
&pwr_info->maxpwr_5gh, 0);
nvram_read_u8(prefix, postfix, "maxp5gla",
&pwr_info->maxpwr_5gl, 0);
nvram_read_u16(prefix, postfix, "pa5gw0a",
&pwr_info->pa_5g[0], 0);
nvram_read_u16(prefix, postfix, "pa5gw1a",
&pwr_info->pa_5g[1], 0);
nvram_read_u16(prefix, postfix, "pa5gw2a",
&pwr_info->pa_5g[2], 0);
nvram_read_u16(prefix, postfix, "pa5glw0a",
&pwr_info->pa_5gl[0], 0);
nvram_read_u16(prefix, postfix, "pa5glw1a",
&pwr_info->pa_5gl[1], 0);
nvram_read_u16(prefix, postfix, "pa5glw2a",
&pwr_info->pa_5gl[2], 0);
nvram_read_u16(prefix, postfix, "pa5ghw0a",
&pwr_info->pa_5gh[0], 0);
nvram_read_u16(prefix, postfix, "pa5ghw1a",
&pwr_info->pa_5gh[1], 0);
nvram_read_u16(prefix, postfix, "pa5ghw2a",
&pwr_info->pa_5gh[2], 0);
}
}
static void bcm47xx_fill_sprom_path_r45(struct ssb_sprom *sprom,
const char *prefix)
{
char postfix[2];
int i;
for (i = 0; i < ARRAY_SIZE(sprom->core_pwr_info); i++) {
struct ssb_sprom_core_pwr_info *pwr_info = &sprom->core_pwr_info[i];
snprintf(postfix, sizeof(postfix), "%i", i);
nvram_read_u16(prefix, postfix, "pa2gw3a",
&pwr_info->pa_2g[3], 0);
nvram_read_u16(prefix, postfix, "pa5gw3a",
&pwr_info->pa_5g[3], 0);
nvram_read_u16(prefix, postfix, "pa5glw3a",
&pwr_info->pa_5gl[3], 0);
nvram_read_u16(prefix, postfix, "pa5ghw3a",
&pwr_info->pa_5gh[3], 0);
}
}
void bcm47xx_fill_sprom_ethernet(struct ssb_sprom *sprom, const char *prefix)
{
nvram_read_macaddr(prefix, "et0macaddr", &sprom->et0mac);
nvram_read_u8(prefix, NULL, "et0mdcport", &sprom->et0mdcport, 0);
nvram_read_u8(prefix, NULL, "et0phyaddr", &sprom->et0phyaddr, 0);
nvram_read_macaddr(prefix, "et1macaddr", &sprom->et1mac);
nvram_read_u8(prefix, NULL, "et1mdcport", &sprom->et1mdcport, 0);
nvram_read_u8(prefix, NULL, "et1phyaddr", &sprom->et1phyaddr, 0);
nvram_read_macaddr(prefix, "macaddr", &sprom->il0mac);
nvram_read_macaddr(prefix, "il0macaddr", &sprom->il0mac);
}
void bcm47xx_fill_sprom(struct ssb_sprom *sprom, const char *prefix)
{
memset(sprom, 0, sizeof(struct ssb_sprom));
bcm47xx_fill_sprom_ethernet(sprom, prefix);
nvram_read_u8(prefix, NULL, "sromrev", &sprom->revision, 0);
switch (sprom->revision) {
case 1:
bcm47xx_fill_sprom_r1234589(sprom, prefix);
bcm47xx_fill_sprom_r12389(sprom, prefix);
bcm47xx_fill_sprom_r1(sprom, prefix);
break;
case 2:
bcm47xx_fill_sprom_r1234589(sprom, prefix);
bcm47xx_fill_sprom_r12389(sprom, prefix);
bcm47xx_fill_sprom_r2389(sprom, prefix);
bcm47xx_fill_sprom_r2(sprom, prefix);
break;
case 3:
bcm47xx_fill_sprom_r1234589(sprom, prefix);
bcm47xx_fill_sprom_r12389(sprom, prefix);
bcm47xx_fill_sprom_r2389(sprom, prefix);
bcm47xx_fill_sprom_r389(sprom, prefix);
bcm47xx_fill_sprom_r3(sprom, prefix);
break;
case 4:
case 5:
bcm47xx_fill_sprom_r1234589(sprom, prefix);
bcm47xx_fill_sprom_r4589(sprom, prefix);
bcm47xx_fill_sprom_r458(sprom, prefix);
bcm47xx_fill_sprom_r45(sprom, prefix);
bcm47xx_fill_sprom_path_r4589(sprom, prefix);
bcm47xx_fill_sprom_path_r45(sprom, prefix);
break;
case 8:
bcm47xx_fill_sprom_r1234589(sprom, prefix);
bcm47xx_fill_sprom_r12389(sprom, prefix);
bcm47xx_fill_sprom_r2389(sprom, prefix);
bcm47xx_fill_sprom_r389(sprom, prefix);
bcm47xx_fill_sprom_r4589(sprom, prefix);
bcm47xx_fill_sprom_r458(sprom, prefix);
bcm47xx_fill_sprom_r89(sprom, prefix);
bcm47xx_fill_sprom_path_r4589(sprom, prefix);
break;
case 9:
bcm47xx_fill_sprom_r1234589(sprom, prefix);
bcm47xx_fill_sprom_r12389(sprom, prefix);
bcm47xx_fill_sprom_r2389(sprom, prefix);
bcm47xx_fill_sprom_r389(sprom, prefix);
bcm47xx_fill_sprom_r4589(sprom, prefix);
bcm47xx_fill_sprom_r89(sprom, prefix);
bcm47xx_fill_sprom_r9(sprom, prefix);
bcm47xx_fill_sprom_path_r4589(sprom, prefix);
break;
default:
pr_warn("Unsupported SPROM revision %d detected. Will extract"
" v1\n", sprom->revision);
sprom->revision = 1;
bcm47xx_fill_sprom_r1234589(sprom, prefix);
bcm47xx_fill_sprom_r12389(sprom, prefix);
bcm47xx_fill_sprom_r1(sprom, prefix);
}
}

View File

@ -0,0 +1,60 @@
/*
* Copyright (C) 2004 Florian Schirmer <jolt@tuxbox.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.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* 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.
*/
#include <linux/init.h>
#include <linux/ssb/ssb.h>
#include <asm/time.h>
#include <bcm47xx.h>
void __init plat_time_init(void)
{
unsigned long hz = 0;
/*
* Use deterministic values for initial counter interrupt
* so that calibrate delay avoids encountering a counter wrap.
*/
write_c0_count(0);
write_c0_compare(0xffff);
switch (bcm47xx_bus_type) {
#ifdef CONFIG_BCM47XX_SSB
case BCM47XX_BUS_TYPE_SSB:
hz = ssb_cpu_clock(&bcm47xx_bus.ssb.mipscore) / 2;
break;
#endif
#ifdef CONFIG_BCM47XX_BCMA
case BCM47XX_BUS_TYPE_BCMA:
hz = bcma_cpu_clock(&bcm47xx_bus.bcma.bus.drv_mips) / 2;
break;
#endif
}
if (!hz)
hz = 100000000;
/* Set MIPS counter frequency for fixed_rate_gettimeoffset() */
mips_hpt_frequency = hz;
}

View File

@ -0,0 +1,170 @@
/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) 2007 Aurelien Jarno <aurelien@aurel32.net>
*/
#include <linux/platform_device.h>
#include <linux/module.h>
#include <linux/leds.h>
#include <linux/mtd/physmap.h>
#include <linux/ssb/ssb.h>
#include <linux/interrupt.h>
#include <linux/reboot.h>
#include <linux/gpio.h>
#include <asm/mach-bcm47xx/bcm47xx.h>
/* GPIO definitions for the WGT634U */
#define WGT634U_GPIO_LED 3
#define WGT634U_GPIO_RESET 2
#define WGT634U_GPIO_TP1 7
#define WGT634U_GPIO_TP2 6
#define WGT634U_GPIO_TP3 5
#define WGT634U_GPIO_TP4 4
#define WGT634U_GPIO_TP5 1
static struct gpio_led wgt634u_leds[] = {
{
.name = "power",
.gpio = WGT634U_GPIO_LED,
.active_low = 1,
.default_trigger = "heartbeat",
},
};
static struct gpio_led_platform_data wgt634u_led_data = {
.num_leds = ARRAY_SIZE(wgt634u_leds),
.leds = wgt634u_leds,
};
static struct platform_device wgt634u_gpio_leds = {
.name = "leds-gpio",
.id = -1,
.dev = {
.platform_data = &wgt634u_led_data,
}
};
/* 8MiB flash. The struct mtd_partition matches original Netgear WGT634U
firmware. */
static struct mtd_partition wgt634u_partitions[] = {
{
.name = "cfe",
.offset = 0,
.size = 0x60000, /* 384k */
.mask_flags = MTD_WRITEABLE /* force read-only */
},
{
.name = "config",
.offset = 0x60000,
.size = 0x20000 /* 128k */
},
{
.name = "linux",
.offset = 0x80000,
.size = 0x140000 /* 1280k */
},
{
.name = "jffs",
.offset = 0x1c0000,
.size = 0x620000 /* 6272k */
},
{
.name = "nvram",
.offset = 0x7e0000,
.size = 0x20000 /* 128k */
},
};
static struct physmap_flash_data wgt634u_flash_data = {
.parts = wgt634u_partitions,
.nr_parts = ARRAY_SIZE(wgt634u_partitions)
};
static struct resource wgt634u_flash_resource = {
.flags = IORESOURCE_MEM,
};
static struct platform_device wgt634u_flash = {
.name = "physmap-flash",
.id = 0,
.dev = { .platform_data = &wgt634u_flash_data, },
.resource = &wgt634u_flash_resource,
.num_resources = 1,
};
/* Platform devices */
static struct platform_device *wgt634u_devices[] __initdata = {
&wgt634u_flash,
&wgt634u_gpio_leds,
};
static irqreturn_t gpio_interrupt(int irq, void *ignored)
{
int state;
/* Interrupts are shared, check if the current one is
a GPIO interrupt. */
if (!ssb_chipco_irq_status(&bcm47xx_bus.ssb.chipco,
SSB_CHIPCO_IRQ_GPIO))
return IRQ_NONE;
state = gpio_get_value(WGT634U_GPIO_RESET);
/* Interrupt are level triggered, revert the interrupt polarity
to clear the interrupt. */
gpio_polarity(WGT634U_GPIO_RESET, state);
if (!state) {
printk(KERN_INFO "Reset button pressed");
ctrl_alt_del();
}
return IRQ_HANDLED;
}
static int __init wgt634u_init(void)
{
/* There is no easy way to detect that we are running on a WGT634U
* machine. Use the MAC address as an heuristic. Netgear Inc. has
* been allocated ranges 00:09:5b:xx:xx:xx and 00:0f:b5:xx:xx:xx.
*/
u8 *et0mac;
if (bcm47xx_bus_type != BCM47XX_BUS_TYPE_SSB)
return -ENODEV;
et0mac = bcm47xx_bus.ssb.sprom.et0mac;
if (et0mac[0] == 0x00 &&
((et0mac[1] == 0x09 && et0mac[2] == 0x5b) ||
(et0mac[1] == 0x0f && et0mac[2] == 0xb5))) {
struct ssb_mipscore *mcore = &bcm47xx_bus.ssb.mipscore;
printk(KERN_INFO "WGT634U machine detected.\n");
if (!request_irq(gpio_to_irq(WGT634U_GPIO_RESET),
gpio_interrupt, IRQF_SHARED,
"WGT634U GPIO", &bcm47xx_bus.ssb.chipco)) {
gpio_direction_input(WGT634U_GPIO_RESET);
gpio_intmask(WGT634U_GPIO_RESET, 1);
ssb_chipco_irq_mask(&bcm47xx_bus.ssb.chipco,
SSB_CHIPCO_IRQ_GPIO,
SSB_CHIPCO_IRQ_GPIO);
}
wgt634u_flash_data.width = mcore->flash_buswidth;
wgt634u_flash_resource.start = mcore->flash_window;
wgt634u_flash_resource.end = mcore->flash_window
+ mcore->flash_window_size
- 1;
return platform_add_devices(wgt634u_devices,
ARRAY_SIZE(wgt634u_devices));
} else
return -ENODEV;
}
module_init(wgt634u_init);