# # Patch managed by http://www.mn-logistik.de/unsupported/pxa250/patcher # --- linux-2.4.20/Makefile~2.4.20_broadcom_3_37_2_1109_US.patch 2005-01-07 05:39:02.000000000 -0500 +++ linux-2.4.20/Makefile 2005-01-08 12:16:21.886535400 -0500 @@ -90,11 +90,26 @@ CFLAGS := $(CPPFLAGS) -Wall -Wstrict-prototypes -Wno-trigraphs -O2 \ -fno-strict-aliasing -fno-common + +# Turn on -pg to instrument the kernel with calls to mcount(). +# Unfortunately, gcc won't allow -pg without frame pointers. +ifdef CONFIG_MCOUNT + CFLAGS += -pg + CFLAGS_KERNEL += -pg + CONFIG_FRAME_POINTER = 1 +endif ifndef CONFIG_FRAME_POINTER CFLAGS += -fomit-frame-pointer endif AFLAGS := -D__ASSEMBLY__ $(CPPFLAGS) +# Broadcom HWNBU source tree +export SRCBASE := $(TOPDIR)/../.. +CFLAGS += -I$(SRCBASE)/include +AFLAGS += -I$(SRCBASE)/include +ASFLAGS += -I$(SRCBASE)/include + + # # ROOT_DEV specifies the default root-device when making the image. # This can be either FLOPPY, CURRENT, /dev/xxxx or empty, in which case --- linux-2.4.20/Rules.make~2.4.20_broadcom_3_37_2_1109_US.patch 2005-01-07 05:38:15.000000000 -0500 +++ linux-2.4.20/Rules.make 2005-01-07 05:39:02.000000000 -0500 @@ -176,7 +176,14 @@ _modinst__: dummy ifneq "$(strip $(ALL_MOBJS))" "" mkdir -p $(MODLIB)/kernel/$(MOD_DESTDIR) - cp $(sort $(ALL_MOBJS)) $(MODLIB)/kernel/$(MOD_DESTDIR) +# cp $(sort $(ALL_MOBJS)) $(MODLIB)/kernel/$(MOD_DESTDIR) + for f in $(ALL_MOBJS) ; do \ + $(OBJCOPY) -R __ksymtab -R .comment -R .note -x \ + `$(NM) $$f | cut -f3- -d' ' | sed -n \ + -e 's/__module_parm_\(.*\)/-K \1/p' \ + -e 's/__ks..tab_\(.*\)/-K \1/p'` \ + $$f $(MODLIB)/kernel/$(MOD_DESTDIR)$(MOD_TARGET)$$f ; \ + done endif .PHONY: modules_install --- linux-2.4.20/arch/mips/Makefile~2.4.20_broadcom_3_37_2_1109_US.patch 2005-01-07 05:39:01.000000000 -0500 +++ linux-2.4.20/arch/mips/Makefile 2005-01-08 12:16:19.825848672 -0500 @@ -39,10 +39,10 @@ GCCFLAGS := -I $(TOPDIR)/include/asm/gcc GCCFLAGS += -G 0 -mno-abicalls -fno-pic -pipe LINKFLAGS += -G 0 -static # -N -MODFLAGS += -mlong-calls +MODFLAGS += -mlong-calls -fno-common -ifdef CONFIG_REMOTE_DEBUG -GCCFLAGS += -g +ifdef CONFIG_DEBUG +GCCFLAGS += -gstabs+ ifdef CONFIG_SB1XXX_CORELIS GCCFLAGS += -mno-sched-prolog -fno-omit-frame-pointer endif @@ -499,6 +499,37 @@ endif # +# Broadcom BCM947XX variants +# +ifdef CONFIG_BCM947XX +LIBS += arch/mips/brcm-boards/generic/brcm.o arch/mips/brcm-boards/bcm947xx/bcm947xx.o +SUBDIRS += arch/mips/brcm-boards/generic arch/mips/brcm-boards/bcm947xx +LOADADDR := 0x80001000 +zImage: vmlinux + $(MAKE) -C arch/$(ARCH)/brcm-boards/bcm947xx/compressed +export LOADADDR +endif + +# +# Broadcom BCM933XX variants +# +ifdef CONFIG_BCM933XX +LIBS += arch/mips/brcm-boards/bcm933xx/bcm933xx.o +SUBDIRS += arch/mips/brcm-boards/bcm933xx +LOADADDR := 0x80010000 + +vmlinux.srec: vmlinux + $(OBJCOPY) -O srec $< $@ +linux.srec: vmlinux.srec + $(OBJCOPY) --adjust-vma=0x80000000 -O srec $< $@ +vmlinux.out: vmlinux.bin + $(TOPDIR)/pstore.sh +vmlinux.bin: vmlinux + $(OBJCOPY) -O binary $< $@ +export LOADADDR +endif + +# # SNI RM200 PCI # ifdef CONFIG_SNI_RM200_PCI --- /dev/null 2004-04-06 13:56:48.000000000 -0400 +++ linux-2.4.20/arch/mips/brcm-boards/bcm947xx/Makefile 2005-01-07 05:39:02.000000000 -0500 @@ -0,0 +1,23 @@ +# +# Makefile for Broadcom BCM947XX boards +# +# Copyright 2004, Broadcom Corporation +# All Rights Reserved. +# +# THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY +# KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM +# SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS +# FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. +# +# $Id: Makefile,v 1.1.1.7 2004/04/12 04:31:00 honor Exp $ +# + +O_TARGET := bcm947xx.o + +export-objs := nvram_linux.o setup.o +obj-y := prom.o setup.o time.o sbmips.o sbpci.o pcibios.o perfcntr.o gpio.o +obj-y += sflash.o nvram.o nvram_linux.o + +vpath %.c $(SRCBASE)/shared $(SRCBASE)/shared/nvram + +include $(TOPDIR)/Rules.make --- /dev/null 2004-04-06 13:56:48.000000000 -0400 +++ linux-2.4.20/arch/mips/brcm-boards/bcm947xx/compressed/Makefile 2004-05-30 02:30:00.000000000 -0400 @@ -0,0 +1,100 @@ +# +# Makefile for Broadcom BCM947XX boards +# +# Copyright 2001-2003, Broadcom Corporation +# All Rights Reserved. +# +# THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY +# KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM +# SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS +# FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. +# +# $Id: Makefile,v 1.1.1.6 2003/11/08 08:11:32 honor Exp $ +# +# Copyright 2004 Manuel Novoa III +# Modified to support bzip'd kernels. +# Of course, it would be better to integrate bunzip capability into CFE. +# + +# Link at 3 MB offset in RAM +#TEXT_START ?= 0x80300000 +TEXT_START ?= 0x80001000 +BZ_MEM_TOP := 0x81000000 +BZ_TEXT_START := BZ_MEM_TOP-0x4000 +BZ_STACK_TOP := BZ_TEXT_START-4 + +OBJCOPY := $(CROSS_COMPILE)objcopy -O binary -R .reginfo -R .note -R .comment -R .mdebug -S + +SRCBASE := $(TOPDIR)/../.. +VPATH := $(SRCBASE)/shared +ASFLAGS += -D__ASSEMBLY__ -I$(SRCBASE)/include -DLOADADDR=$(LOADADDR) +ASFLAGS += -DBZ_MEM_TOP=$(BZ_MEM_TOP) +ASFLAGS += -DBZ_TEXT_START=$(BZ_TEXT_START) +ASFLAGS += -DBZ_STACK_TOP=$(BZ_STACK_TOP) +CFLAGS += -I$(SRCBASE)/include -DLOADADDR=$(LOADADDR) +CFLAGS += -DBZ_MEM_TOP=$(BZ_MEM_TOP) +CFLAGS += -DBZ_TEXT_START=$(BZ_TEXT_START) +CFLAGS += -DBZ_STACK_TOP=$(BZ_STACK_TOP) +ifdef CONFIG_MCOUNT +CFLAGS := $(subst -pg,,$(CFLAGS)) +endif +CFLAGS += -ffunction-sections $(call check_gcc, -fvtable-gc, ) +SEDFLAGS := s/BZ_TEXT_START/$(BZ_TEXT_START)/;s/BZ_MEM_TOP/$(BZ_MEM_TOP)/;s/TEXT_START/$(TEXT_START)/ + +SYSTEM ?= $(TOPDIR)/vmlinux +OBJECTS := head.o data.o + +all: bzImage vmlinuz + +# Don't build dependencies, this may die if $(CC) isn't gcc +dep: + +# Create a gzipped version named vmlinuz for compatibility +vmlinuz: piggy + gzip -c9 $< > $@ + +# Our bzImage is a gzip'd binary that decompresses and runs +# the appended bzip'd kernel. +bzImage: bzLoaderImage.gz piggz + cat bzLoaderImage.gz piggz > $@ + +bzLoaderImage.gz: bzLoaderImage + gzip -nc9 $< > $@ + +bzLoaderImage: bzLoader + $(OBJCOPY) $< $@ + +bzLoader: vmlinux.lds $(OBJECTS) + $(LD) -static --gc-sections -no-warn-mismatch -T vmlinux.lds -o $@ $(OBJECTS) + +vmlinux.lds: vmlinux.lds.in Makefile + @sed "$(SEDFLAGS)" < $< > $@ + +piggz: piggy + bzip2 -c9 $< > $@ + +piggy: $(SYSTEM) + $(OBJCOPY) $< $@ + +data.o: data.lds data.image + $(LD) -no-warn-mismatch -T data.lds -r -o $@ -b binary data.image -b elf32-tradlittlemips + +data.lds: + @echo "SECTIONS { .data : { code_start = .; *(.data) code_stop = .; }}" > $@ + +data.image: decompress_bunzip2.image + $(OBJCOPY) $< $@ + +decompress_bunzip2.image: decompress_bunzip2.lds decompress_bunzip2.o + $(LD) -static --gc-sections -no-warn-mismatch -T decompress_bunzip2.lds -o $@ decompress_bunzip2.o + +decompress_bunzip2.lds: decompress_bunzip2.lds.in Makefile + @sed "$(SEDFLAGS)" < $< > $@ + +mrproper: clean + +clean: + rm -f vmlinux vmlinuz piggz piggy *.lds *.o \ + bzLoader bzLoaderImage bzLoaderImage.gz bzImage \ + data.lds data.image \ + decompress_bunzip2.lds decompress_bunzip2.image --- /dev/null 2004-04-06 13:56:48.000000000 -0400 +++ linux-2.4.20/arch/mips/brcm-boards/bcm947xx/compressed/head.S 2004-05-30 02:26:40.000000000 -0400 @@ -0,0 +1,26 @@ +/* Copyright 2004 Manuel Novoa III (mjn3@codepoet.org) */ +/* Licensed under the linux kernel's version of the GPL. */ + +#include +#include + + .text + LEAF(startup) + .set noreorder + + li t1, BZ_TEXT_START + add a0, t1, 0 + la a1, code_start + la a2, code_stop +$L1: + lw t0, 0(a1) + sw t0, 0(a0) + add a1, 4 + add a0, 4 + blt a1, a2, $L1 + + add sp, t1, -4 + jal t1 + + .set reorder + END(startup) --- linux-2.4.20/arch/mips/brcm-boards/bcm947xx/compressed/misc.c~2.4.20_broadcom_3_37_2_1109_US.patch +++ linux-2.4.20/arch/mips/brcm-boards/bcm947xx/compressed/misc.c --- /dev/null 2004-04-06 13:56:48.000000000 -0400 +++ linux-2.4.20/arch/mips/brcm-boards/bcm947xx/compressed/vmlinux.lds.in 2004-05-21 13:13:07.000000000 -0400 @@ -0,0 +1,17 @@ +OUTPUT_ARCH(mips) +ENTRY(startup) +SECTIONS { + . = TEXT_START; + .text : { + *(.text) + *(.rodata) + } + + .data : { + *(.data) + } + + .bss : { + *(.bss) + } +} --- /dev/null 2004-04-06 13:56:48.000000000 -0400 +++ linux-2.4.20/arch/mips/brcm-boards/bcm947xx/gpio.c 2005-01-07 05:39:02.000000000 -0500 @@ -0,0 +1,158 @@ +/* + * GPIO char driver + * + * Copyright 2004, Broadcom Corporation + * All Rights Reserved. + * + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. + * + * $Id: gpio.c,v 1.1.1.7 2004/04/12 04:31:00 honor Exp $ + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +static void *gpio_sbh; +static int gpio_major; +static devfs_handle_t gpio_dir; +static struct { + char *name; + devfs_handle_t handle; +} gpio_file[] = { + { "in", NULL }, + { "out", NULL }, + { "outen", NULL }, + { "control", NULL } +}; + +static int +gpio_open(struct inode *inode, struct file * file) +{ + if (MINOR(inode->i_rdev) > ARRAYSIZE(gpio_file)) + return -ENODEV; + + MOD_INC_USE_COUNT; + return 0; +} + +static int +gpio_release(struct inode *inode, struct file * file) +{ + MOD_DEC_USE_COUNT; + return 0; +} + +static ssize_t +gpio_read(struct file *file, char *buf, size_t count, loff_t *ppos) +{ + u32 val; + + switch (MINOR(file->f_dentry->d_inode->i_rdev)) { + case 0: + val = sb_gpioin(gpio_sbh); + break; + case 1: + val = sb_gpioout(gpio_sbh, 0, 0); + break; + case 2: + val = sb_gpioouten(gpio_sbh, 0, 0); + break; + case 3: + val = sb_gpiocontrol(gpio_sbh, 0, 0); + break; + default: + return -ENODEV; + } + + if (put_user(val, (u32 *) buf)) + return -EFAULT; + + return sizeof(val); +} + +static ssize_t +gpio_write(struct file *file, const char *buf, size_t count, loff_t *ppos) +{ + u32 val; + + if (get_user(val, (u32 *) buf)) + return -EFAULT; + + switch (MINOR(file->f_dentry->d_inode->i_rdev)) { + case 0: + return -EACCES; + case 1: + sb_gpioout(gpio_sbh, ~0, val); + break; + case 2: + sb_gpioouten(gpio_sbh, ~0, val); + break; + case 3: + sb_gpiocontrol(gpio_sbh, ~0, val); + break; + default: + return -ENODEV; + } + + return sizeof(val); +} + +static struct file_operations gpio_fops = { + owner: THIS_MODULE, + open: gpio_open, + release: gpio_release, + read: gpio_read, + write: gpio_write, +}; + +static int __init +gpio_init(void) +{ + int i; + + if (!(gpio_sbh = sb_kattach())) + return -ENODEV; + + sb_gpiosetcore(gpio_sbh); + + if ((gpio_major = devfs_register_chrdev(0, "gpio", &gpio_fops)) < 0) + return gpio_major; + + gpio_dir = devfs_mk_dir(NULL, "gpio", NULL); + + for (i = 0; i < ARRAYSIZE(gpio_file); i++) { + gpio_file[i].handle = devfs_register(gpio_dir, + gpio_file[i].name, + DEVFS_FL_DEFAULT, gpio_major, i, + S_IFCHR | S_IRUGO | S_IWUGO, + &gpio_fops, NULL); + } + + return 0; +} + +static void __exit +gpio_exit(void) +{ + int i; + + for (i = 0; i < ARRAYSIZE(gpio_file); i++) + devfs_unregister(gpio_file[i].handle); + devfs_unregister(gpio_dir); + devfs_unregister_chrdev(gpio_major, "gpio"); + sb_detach(gpio_sbh); +} + +module_init(gpio_init); +module_exit(gpio_exit); --- /dev/null 2004-04-06 13:56:48.000000000 -0400 +++ linux-2.4.20/arch/mips/brcm-boards/bcm947xx/nvram_linux.c 2005-01-07 05:39:02.000000000 -0500 @@ -0,0 +1,638 @@ +/* + * NVRAM variable manipulation (Linux kernel half) + * + * Copyright 2004, Broadcom Corporation + * All Rights Reserved. + * + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. + * + * $Id: nvram_linux.c,v 1.10 2004/04/12 06:07:56 honor Exp $ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* In BSS to minimize text size and page aligned so it can be mmap()-ed */ +static char nvram_buf[NVRAM_SPACE] __attribute__((aligned(PAGE_SIZE))); + +#ifdef MODULE + +#define early_nvram_get(name) nvram_get(name) + +#else /* !MODULE */ + +/* Global SB handle */ +extern void *bcm947xx_sbh; +extern spinlock_t bcm947xx_sbh_lock; + +/* Convenience */ +#define sbh bcm947xx_sbh +#define sbh_lock bcm947xx_sbh_lock +#define KB * 1024 +#define MB * 1024 * 1024 + +/* Probe for NVRAM header */ +static void __init +early_nvram_init(void) +{ + struct nvram_header *header; + chipcregs_t *cc; + struct sflash *info = NULL; + int i; + uint32 base, off, lim; + + if ((cc = sb_setcore(sbh, SB_CC, 0)) != NULL) { + base = CC_FLASH_BASE; + switch (readl(&cc->capabilities) & CAP_FLASH_MASK) { + case PFLASH: + lim = CC_FLASH_MAX; + break; + + case SFLASH_ST: + case SFLASH_AT: + if ((info = sflash_init(cc)) == NULL) + return; + lim = info->size; + break; + + case FLASH_NONE: + default: + return; + } + } else { + /* extif assumed, Stop at 4 MB */ + base = FLASH_BASE; + lim = FLASH_MAX; + } + + off = FLASH_MIN; + while (off <= lim) { + /* Windowed flash access */ + header = (struct nvram_header *) KSEG1ADDR(base + off - NVRAM_SPACE); + if (header->magic == NVRAM_MAGIC) { + u32 *src = (u32 *) header; + u32 *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++ = ltoh32(*src++); + return; + } + + /* Try embedded NVRAM at 4 KB and 1 KB as last resorts */ + if (off == 1 KB) + break; + else if (off == 4 KB) + off = 1 KB; + else if (off == lim) + off = 4 KB; + else + off <<= 1; + } +} + +/* Early (before mm or mtd) read-only access to NVRAM */ +static char * __init +early_nvram_get(const char *name) +{ + char *var, *value, *end, *eq; + + if (!name) + return NULL; + + 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) { + if (!(eq = strchr(var, '='))) + break; + value = eq + 1; + if ((eq - var) == strlen(name) && strncmp(var, name, (eq - var)) == 0) + return value; + } + + return NULL; +} + +#endif /* !MODULE */ + +extern char * _nvram_get(const char *name); +extern int _nvram_set(const char *name, const char *value); +extern int _nvram_unset(const char *name); +extern int _nvram_getall(char *buf, int count); +extern int _nvram_commit(struct nvram_header *header); +extern int _nvram_init(void); +extern void _nvram_exit(void); + +/* Globals */ +static spinlock_t nvram_lock = SPIN_LOCK_UNLOCKED; +static struct semaphore nvram_sem; +static unsigned long nvram_offset = 0; +static int nvram_major = -1; +static devfs_handle_t nvram_handle = NULL; +static struct mtd_info *nvram_mtd = NULL; + +int +_nvram_read(char *buf) +{ + struct nvram_header *header = (struct nvram_header *) buf; + size_t len; + + if (!nvram_mtd || + MTD_READ(nvram_mtd, nvram_mtd->size - NVRAM_SPACE, NVRAM_SPACE, &len, buf) || + len != NVRAM_SPACE || + header->magic != NVRAM_MAGIC) { + /* Maybe we can recover some data from early initialization */ + memcpy(buf, nvram_buf, NVRAM_SPACE); + } + + return 0; +} + +struct nvram_tuple * +_nvram_realloc(struct nvram_tuple *t, const char *name, const char *value) +{ + if ((nvram_offset + strlen(value) + 1) > NVRAM_SPACE) + return NULL; + + if (!t) { + if (!(t = kmalloc(sizeof(struct nvram_tuple) + strlen(name) + 1, GFP_ATOMIC))) + return NULL; + + /* Copy name */ + t->name = (char *) &t[1]; + strcpy(t->name, name); + + t->value = NULL; + } + + /* Copy value */ + if (!t->value || strcmp(t->value, value)) { + t->value = &nvram_buf[nvram_offset]; + strcpy(t->value, value); + nvram_offset += strlen(value) + 1; + } + + return t; +} + +void +_nvram_free(struct nvram_tuple *t) +{ + if (!t) + nvram_offset = 0; + else + kfree(t); +} + +int +nvram_set(const char *name, const char *value) +{ + unsigned long flags; + int ret; + struct nvram_header *header; + + spin_lock_irqsave(&nvram_lock, flags); + if ((ret = _nvram_set(name, value))) { + /* Consolidate space and try again */ + if ((header = kmalloc(NVRAM_SPACE, GFP_ATOMIC))) { + if (_nvram_commit(header) == 0) + ret = _nvram_set(name, value); + kfree(header); + } + } + spin_unlock_irqrestore(&nvram_lock, flags); + + return ret; +} + +char * +real_nvram_get(const char *name) +{ + unsigned long flags; + char *value; + + spin_lock_irqsave(&nvram_lock, flags); + value = _nvram_get(name); + spin_unlock_irqrestore(&nvram_lock, flags); + + return value; +} + +char * +nvram_get(const char *name) +{ + if (nvram_major >= 0) + return real_nvram_get(name); + else + return early_nvram_get(name); +} + +int +nvram_unset(const char *name) +{ + unsigned long flags; + int ret; + + spin_lock_irqsave(&nvram_lock, flags); + ret = _nvram_unset(name); + spin_unlock_irqrestore(&nvram_lock, flags); + + return ret; +} + +static void +erase_callback(struct erase_info *done) +{ + wait_queue_head_t *wait_q = (wait_queue_head_t *) done->priv; + wake_up(wait_q); +} + +int +nvram_commit(void) +{ + char *buf; + size_t erasesize, len; + unsigned int i; + int ret; + struct nvram_header *header; + unsigned long flags; + u_int32_t offset; + DECLARE_WAITQUEUE(wait, current); + wait_queue_head_t wait_q; + struct erase_info erase; + + printk("nvram_commit(): init\n"); + + if (!nvram_mtd) { + printk("nvram_commit: NVRAM not found\n"); + return -ENODEV; + } + + if (in_interrupt()) { + printk("nvram_commit: not committing in interrupt\n"); + return -EINVAL; + } + + /* Backup sector blocks to be erased */ + erasesize = ROUNDUP(NVRAM_SPACE, nvram_mtd->erasesize); + if (!(buf = kmalloc(erasesize, GFP_KERNEL))) { + printk("nvram_commit: out of memory\n"); + return -ENOMEM; + } + + down(&nvram_sem); +#if 0 + offset = nvram_mtd->size - erasesize; + i = erasesize - NVRAM_SPACE; + ret = MTD_READ(nvram_mtd, offset, i, &len, buf); + if (ret || len != i) { + printk("nvram_commit: read error\n"); + ret = -EIO; + goto done; +#endif + if ((i = erasesize - NVRAM_SPACE) > 0) { + offset = nvram_mtd->size - erasesize; + len = 0; + ret = MTD_READ(nvram_mtd, offset, i, &len, buf); + if (ret || len != i) { + printk("nvram_commit: read error ret = %d, len = %d/%d\n", ret, len, i); + ret = -EIO; + goto done; + } + header = (struct nvram_header *)(buf + i); + } else { + offset = nvram_mtd->size - NVRAM_SPACE; + header = (struct nvram_header *)buf; + } + + /* Regenerate NVRAM */ + spin_lock_irqsave(&nvram_lock, flags); + ret = _nvram_commit(header); + spin_unlock_irqrestore(&nvram_lock, flags); + if (ret) + goto done; + + /* Erase sector blocks */ + init_waitqueue_head(&wait_q); + for (; offset < nvram_mtd->size - NVRAM_SPACE + header->len; offset += nvram_mtd->erasesize) { + erase.mtd = nvram_mtd; + erase.addr = offset; + erase.len = nvram_mtd->erasesize; + erase.callback = erase_callback; + erase.priv = (u_long) &wait_q; + + set_current_state(TASK_INTERRUPTIBLE); + add_wait_queue(&wait_q, &wait); + + /* Unlock sector blocks */ + if (nvram_mtd->unlock) + nvram_mtd->unlock(nvram_mtd, offset, nvram_mtd->erasesize); + + if ((ret = MTD_ERASE(nvram_mtd, &erase))) { + set_current_state(TASK_RUNNING); + remove_wait_queue(&wait_q, &wait); + printk("nvram_commit: erase error\n"); + goto done; + } + + /* Wait for erase to finish */ + schedule(); + remove_wait_queue(&wait_q, &wait); + } + + /* Write partition up to end of data area */ + offset = nvram_mtd->size - erasesize; + i = erasesize - NVRAM_SPACE + header->len; + ret = MTD_WRITE(nvram_mtd, offset, i, &len, buf); + if (ret || len != i) { + printk("nvram_commit: write error\n"); + ret = -EIO; + goto done; + } + /* + * Reading a few bytes back here will put the device + * back to the correct mode on certain flashes */ + + offset = nvram_mtd->size - erasesize; + ret = MTD_READ(nvram_mtd, offset, 4, &len, buf); + + done: + up(&nvram_sem); + kfree(buf); + printk("nvram_commit(): end\n"); + return ret; +} + +int +nvram_getall(char *buf, int count) +{ + unsigned long flags; + int ret; + + spin_lock_irqsave(&nvram_lock, flags); + ret = _nvram_getall(buf, count); + spin_unlock_irqrestore(&nvram_lock, flags); + + return ret; +} + +EXPORT_SYMBOL(nvram_get); +EXPORT_SYMBOL(nvram_getall); +EXPORT_SYMBOL(nvram_set); +EXPORT_SYMBOL(nvram_unset); +EXPORT_SYMBOL(nvram_commit); + +/* User mode interface below */ + +static ssize_t +dev_nvram_read(struct file *file, char *buf, size_t count, loff_t *ppos) +{ + char tmp[100], *name = tmp, *value; + ssize_t ret; + unsigned long off; + + if (count > sizeof(tmp)) { + if (!(name = kmalloc(count, GFP_KERNEL))) + return -ENOMEM; + } + + if (copy_from_user(name, buf, count)) { + ret = -EFAULT; + goto done; + } + + if (*name == '\0') { + /* Get all variables */ + ret = nvram_getall(name, count); + if (ret == 0) { + if (copy_to_user(buf, name, count)) { + ret = -EFAULT; + goto done; + } + ret = count; + } + } else { + if (!(value = nvram_get(name))) { + ret = 0; + goto done; + } + + /* Provide the offset into mmap() space */ + off = (unsigned long) value - (unsigned long) nvram_buf; + + if (put_user(off, (unsigned long *) buf)) { + ret = -EFAULT; + goto done; + } + + ret = sizeof(unsigned long); + } + + flush_cache_all(); + +done: + if (name != tmp) + kfree(name); + + return ret; +} + +static ssize_t +dev_nvram_write(struct file *file, const char *buf, size_t count, loff_t *ppos) +{ + char tmp[100], *name = tmp, *value; + ssize_t ret; + + if (count > sizeof(tmp)) { + if (!(name = kmalloc(count, GFP_KERNEL))) + return -ENOMEM; + } + + if (copy_from_user(name, buf, count)) { + ret = -EFAULT; + goto done; + } + + value = name; + name = strsep(&value, "="); + if (value) + ret = nvram_set(name, value) ? : count; + else + ret = nvram_unset(name) ? : count; + + done: + if (name != tmp) + kfree(name); + + return ret; +} + +static int +dev_nvram_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +{ + if (cmd != NVRAM_MAGIC) + return -EINVAL; + return nvram_commit(); +} + +static int +dev_nvram_mmap(struct file *file, struct vm_area_struct *vma) +{ + unsigned long offset = virt_to_phys(nvram_buf); + + if (remap_page_range(vma->vm_start, offset, vma->vm_end-vma->vm_start, + vma->vm_page_prot)) + return -EAGAIN; + + return 0; +} + +static int +dev_nvram_open(struct inode *inode, struct file * file) +{ + MOD_INC_USE_COUNT; + return 0; +} + +static int +dev_nvram_release(struct inode *inode, struct file * file) +{ + MOD_DEC_USE_COUNT; + return 0; +} + +static struct file_operations dev_nvram_fops = { + owner: THIS_MODULE, + open: dev_nvram_open, + release: dev_nvram_release, + read: dev_nvram_read, + write: dev_nvram_write, + ioctl: dev_nvram_ioctl, + mmap: dev_nvram_mmap, +}; + +static void +dev_nvram_exit(void) +{ + int order = 0; + struct page *page, *end; + + if (nvram_handle) + devfs_unregister(nvram_handle); + + if (nvram_major >= 0) + devfs_unregister_chrdev(nvram_major, "nvram"); + + if (nvram_mtd) + put_mtd_device(nvram_mtd); + + while ((PAGE_SIZE << order) < NVRAM_SPACE) + order++; + end = virt_to_page(nvram_buf + (PAGE_SIZE << order) - 1); + for (page = virt_to_page(nvram_buf); page <= end; page++) + mem_map_unreserve(page); + + _nvram_exit(); +} + +static int __init +dev_nvram_init(void) +{ + int order = 0, ret = 0; + struct page *page, *end; + unsigned int i; + + /* Allocate and reserve memory to mmap() */ + while ((PAGE_SIZE << order) < NVRAM_SPACE) + order++; + end = virt_to_page(nvram_buf + (PAGE_SIZE << order) - 1); + for (page = virt_to_page(nvram_buf); page <= end; page++) + mem_map_reserve(page); + +#ifdef CONFIG_MTD + /* Find associated MTD device */ + for (i = 0; i < MAX_MTD_DEVICES; i++) { + nvram_mtd = get_mtd_device(NULL, i); + if (nvram_mtd) { + if (!strcmp(nvram_mtd->name, "nvram") && + nvram_mtd->size >= NVRAM_SPACE) + break; + put_mtd_device(nvram_mtd); + } + } + if (i >= MAX_MTD_DEVICES) + nvram_mtd = NULL; +#endif + + /* Initialize hash table lock */ + spin_lock_init(&nvram_lock); + + /* Initialize commit semaphore */ + init_MUTEX(&nvram_sem); + + /* Register char device */ + if ((nvram_major = devfs_register_chrdev(0, "nvram", &dev_nvram_fops)) < 0) { + ret = nvram_major; + goto err; + } + + /* Initialize hash table */ + _nvram_init(); + + /* Create /dev/nvram handle */ + nvram_handle = devfs_register(NULL, "nvram", DEVFS_FL_NONE, nvram_major, 0, + S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, &dev_nvram_fops, NULL); + + /* Set the SDRAM NCDL value into NVRAM if not already done */ + if (getintvar(NULL, "sdram_ncdl") == 0) { + unsigned int ncdl; + char buf[] = "0x00000000"; + + if ((ncdl = sb_memc_get_ncdl(sbh))) { + sprintf(buf, "0x%08x", ncdl); + nvram_set("sdram_ncdl", buf); + nvram_commit(); + } + } + + return 0; + + err: + dev_nvram_exit(); + return ret; +} + +module_init(dev_nvram_init); +module_exit(dev_nvram_exit); --- /dev/null 2004-04-06 13:56:48.000000000 -0400 +++ linux-2.4.20/arch/mips/brcm-boards/bcm947xx/pcibios.c 2005-01-07 05:39:02.000000000 -0500 @@ -0,0 +1,332 @@ +/* + * Low-Level PCI and SB support for BCM47xx (Linux support code) + * + * Copyright 2004, Broadcom Corporation + * All Rights Reserved. + * + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. + * + * $Id: pcibios.c,v 1.1.1.6 2004/04/12 04:31:00 honor Exp $ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +/* Global SB handle */ +extern void *bcm947xx_sbh; +extern spinlock_t bcm947xx_sbh_lock; + +/* Convenience */ +#define sbh bcm947xx_sbh +#define sbh_lock bcm947xx_sbh_lock + +static int +sbpci_read_config_byte(struct pci_dev *dev, int where, u8 *value) +{ + unsigned long flags; + int ret; + + spin_lock_irqsave(&sbh_lock, flags); + ret = sbpci_read_config(sbh, dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn), where, value, sizeof(*value)); + spin_unlock_irqrestore(&sbh_lock, flags); + return ret ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL; +} + +static int +sbpci_read_config_word(struct pci_dev *dev, int where, u16 *value) +{ + unsigned long flags; + int ret; + + spin_lock_irqsave(&sbh_lock, flags); + ret = sbpci_read_config(sbh, dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn), where, value, sizeof(*value)); + spin_unlock_irqrestore(&sbh_lock, flags); + return ret ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL; +} + +static int +sbpci_read_config_dword(struct pci_dev *dev, int where, u32 *value) +{ + unsigned long flags; + int ret; + + spin_lock_irqsave(&sbh_lock, flags); + ret = sbpci_read_config(sbh, dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn), where, value, sizeof(*value)); + spin_unlock_irqrestore(&sbh_lock, flags); + return ret ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL; +} + +static int +sbpci_write_config_byte(struct pci_dev *dev, int where, u8 value) +{ + unsigned long flags; + int ret; + + spin_lock_irqsave(&sbh_lock, flags); + ret = sbpci_write_config(sbh, dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn), where, &value, sizeof(value)); + spin_unlock_irqrestore(&sbh_lock, flags); + return ret ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL; +} + +static int +sbpci_write_config_word(struct pci_dev *dev, int where, u16 value) +{ + unsigned long flags; + int ret; + + spin_lock_irqsave(&sbh_lock, flags); + ret = sbpci_write_config(sbh, dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn), where, &value, sizeof(value)); + spin_unlock_irqrestore(&sbh_lock, flags); + return ret ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL; +} + +static int +sbpci_write_config_dword(struct pci_dev *dev, int where, u32 value) +{ + unsigned long flags; + int ret; + + spin_lock_irqsave(&sbh_lock, flags); + ret = sbpci_write_config(sbh, dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn), where, &value, sizeof(value)); + spin_unlock_irqrestore(&sbh_lock, flags); + return ret ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL; +} + +static struct pci_ops pcibios_ops = { + sbpci_read_config_byte, + sbpci_read_config_word, + sbpci_read_config_dword, + sbpci_write_config_byte, + sbpci_write_config_word, + sbpci_write_config_dword +}; + + +void __init +pcibios_init(void) +{ + ulong flags; + + if (!(sbh = sb_kattach())) + panic("sb_kattach failed"); + spin_lock_init(&sbh_lock); + + spin_lock_irqsave(&sbh_lock, flags); + sbpci_init(sbh); + spin_unlock_irqrestore(&sbh_lock, flags); + + set_io_port_base((unsigned long) ioremap_nocache(SB_PCI_MEM, 0x04000000)); + + /* Scan the SB bus */ + pci_scan_bus(0, &pcibios_ops, NULL); + +} + +char * __init +pcibios_setup(char *str) +{ + if (!strncmp(str, "ban=", 4)) { + sbpci_ban(simple_strtoul(str + 4, NULL, 0)); + return NULL; + } + + return (str); +} + +static u32 pci_iobase = 0x100; +static u32 pci_membase = SB_PCI_DMA; + +void __init +pcibios_fixup_bus(struct pci_bus *b) +{ + struct list_head *ln; + struct pci_dev *d; + struct resource *res; + int pos, size; + u32 *base; + u8 irq; + + printk("PCI: Fixing up bus %d\n", b->number); + + /* Fix up SB */ + if (b->number == 0) { + for (ln=b->devices.next; ln != &b->devices; ln=ln->next) { + d = pci_dev_b(ln); + /* Fix up interrupt lines */ + pci_read_config_byte(d, PCI_INTERRUPT_LINE, &irq); + d->irq = irq + 2; + pci_write_config_byte(d, PCI_INTERRUPT_LINE, d->irq); + } + } + + /* Fix up external PCI */ + else { + for (ln=b->devices.next; ln != &b->devices; ln=ln->next) { + d = pci_dev_b(ln); + /* Fix up resource bases */ + for (pos = 0; pos < 6; pos++) { + res = &d->resource[pos]; + base = (res->flags & IORESOURCE_IO) ? &pci_iobase : &pci_membase; + if (res->end) { + size = res->end - res->start + 1; + if (*base & (size - 1)) + *base = (*base + size) & ~(size - 1); + res->start = *base; + res->end = res->start + size - 1; + *base += size; + pci_write_config_dword(d, PCI_BASE_ADDRESS_0 + (pos << 2), res->start); + } + /* Fix up PCI bridge BAR0 only */ + if (b->number == 1 && PCI_SLOT(d->devfn) == 0) + break; + } + /* Fix up interrupt lines */ + if (pci_find_device(VENDOR_BROADCOM, SB_PCI, NULL)) + d->irq = (pci_find_device(VENDOR_BROADCOM, SB_PCI, NULL))->irq; + pci_write_config_byte(d, PCI_INTERRUPT_LINE, d->irq); + } + } +} + +unsigned int +pcibios_assign_all_busses(void) +{ + return 1; +} + +void +pcibios_align_resource(void *data, struct resource *res, + unsigned long size, unsigned long align) +{ +} + +int +pcibios_enable_resources(struct pci_dev *dev) +{ + u16 cmd, old_cmd; + int idx; + struct resource *r; + + /* External PCI only */ + if (dev->bus->number == 0) + return 0; + + pci_read_config_word(dev, PCI_COMMAND, &cmd); + old_cmd = cmd; + for(idx=0; idx<6; idx++) { + r = &dev->resource[idx]; + if (r->flags & IORESOURCE_IO) + cmd |= PCI_COMMAND_IO; + if (r->flags & IORESOURCE_MEM) + cmd |= PCI_COMMAND_MEMORY; + } + if (dev->resource[PCI_ROM_RESOURCE].start) + cmd |= PCI_COMMAND_MEMORY; + if (cmd != old_cmd) { + printk("PCI: Enabling device %s (%04x -> %04x)\n", dev->slot_name, old_cmd, cmd); + pci_write_config_word(dev, PCI_COMMAND, cmd); + } + return 0; +} + +int +pcibios_enable_device(struct pci_dev *dev, int mask) +{ + ulong flags; + uint coreidx; + + /* External PCI device enable */ + if (dev->bus->number != 0) + return pcibios_enable_resources(dev); + + /* These cores come out of reset enabled */ + if (dev->device == SB_MIPS || + dev->device == SB_MIPS33 || + dev->device == SB_EXTIF || + dev->device == SB_CC) + return 0; + + spin_lock_irqsave(&sbh_lock, flags); + coreidx = sb_coreidx(sbh); + if (!sb_setcoreidx(sbh, PCI_SLOT(dev->devfn))) + return PCIBIOS_DEVICE_NOT_FOUND; + + /* + * The USB core requires a special bit to be set during core + * reset to enable host (OHCI) mode. Resetting the SB core in + * pcibios_enable_device() is a hack for compatibility with + * vanilla usb-ohci so that it does not have to know about + * SB. A driver that wants to use the USB core in device mode + * should know about SB and should reset the bit back to 0 + * after calling pcibios_enable_device(). + */ + if (sb_coreid(sbh) == SB_USB) { + sb_core_disable(sbh, sb_coreflags(sbh, 0, 0)); + sb_core_reset(sbh, 1 << 29); + } else + sb_core_reset(sbh, 0); + + sb_setcoreidx(sbh, coreidx); + spin_unlock_irqrestore(&sbh_lock, flags); + + return 0; +} + +void +pcibios_update_resource(struct pci_dev *dev, struct resource *root, + struct resource *res, int resource) +{ + unsigned long where, size; + u32 reg; + + /* External PCI only */ + if (dev->bus->number == 0) + return; + + where = PCI_BASE_ADDRESS_0 + (resource * 4); + size = res->end - res->start; + pci_read_config_dword(dev, where, ®); + reg = (reg & size) | (((u32)(res->start - root->start)) & ~size); + pci_write_config_dword(dev, where, reg); +} + +static void __init +quirk_sbpci_bridge(struct pci_dev *dev) +{ + if (dev->bus->number != 1 || PCI_SLOT(dev->devfn) != 0) + return; + + printk("PCI: Fixing up bridge\n"); + + /* Enable PCI bridge bus mastering and memory space */ + pci_set_master(dev); + pcibios_enable_resources(dev); + + /* Enable PCI bridge BAR1 prefetch and burst */ + pci_write_config_dword(dev, PCI_BAR1_CONTROL, 3); +} + +struct pci_fixup pcibios_fixups[] = { + { PCI_FIXUP_HEADER, PCI_ANY_ID, PCI_ANY_ID, quirk_sbpci_bridge }, + { 0 } +}; --- /dev/null 2004-04-06 13:56:48.000000000 -0400 +++ linux-2.4.20/arch/mips/brcm-boards/bcm947xx/perfcntr.c 2005-01-07 05:39:02.000000000 -0500 @@ -0,0 +1,67 @@ +/* + * Broadcom BCM47xx Performance Counter /proc/cpuinfo support + * + * Copyright 2004, Broadcom Corporation + * All Rights Reserved. + * + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. + * + * $Id: perfcntr.c,v 1.1.1.3 2004/04/12 04:31:00 honor Exp $ + */ + +#include + +/* + * BCM4710 performance counter register select values + * No even-odd control-counter mapping, just counters + */ +#define PERF_DCACHE_HIT 0 +#define PERF_DCACHE_MISS 1 +#define PERF_ICACHE_HIT 2 +#define PERF_ICACHE_MISS 3 +#define PERF_ICOUNT 4 + +/* + * Move from Coprocessor 0 Register 25 Select n + * data <- CPR[0,25,n] + * GPR[1] <- data + */ +#define read_bcm4710_perf_cntr(n) \ +({ int __res; \ + __asm__ __volatile__( \ + ".set\tnoreorder\n\t" \ + ".set\tnoat\n\t" \ + ".word\t"STR(0x4001c800|(n))"\n\t" \ + "move\t%0,$1\n\t" \ + ".set\tat\n\t" \ + ".set\treorder" \ + :"=r" (__res)); \ + __res;}) + +asmlinkage unsigned int read_perf_cntr(unsigned int counter) +{ + switch (counter) { + case PERF_DCACHE_HIT: return read_bcm4710_perf_cntr(PERF_DCACHE_HIT); + case PERF_DCACHE_MISS: return read_bcm4710_perf_cntr(PERF_DCACHE_MISS); + case PERF_ICACHE_HIT: return read_bcm4710_perf_cntr(PERF_ICACHE_HIT); + case PERF_ICACHE_MISS: return read_bcm4710_perf_cntr(PERF_ICACHE_MISS); + case PERF_ICOUNT: return read_bcm4710_perf_cntr(PERF_ICOUNT); + } + return 0; +} + +asmlinkage void write_perf_cntr(unsigned int counter, unsigned int val) +{ +} + +asmlinkage unsigned int read_perf_cntl(unsigned int counter) +{ + return 0; +} + +asmlinkage void write_perf_cntl(unsigned int counter, unsigned int val) +{ +} --- /dev/null 2004-04-06 13:56:48.000000000 -0400 +++ linux-2.4.20/arch/mips/brcm-boards/bcm947xx/prom.c 2005-01-07 05:39:02.000000000 -0500 @@ -0,0 +1,41 @@ +/* + * Early initialization code for BCM94710 boards + * + * Copyright 2004, Broadcom Corporation + * All Rights Reserved. + * + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. + * + * $Id: prom.c,v 1.1.1.6 2004/04/12 04:31:00 honor Exp $ + */ + +#include +#include +#include +#include +#include + +void __init +prom_init(int argc, const char **argv) +{ + unsigned long mem; + + mips_machgroup = MACH_GROUP_BRCM; + mips_machtype = MACH_BCM947XX; + + /* Figure out memory size by finding aliases */ + for (mem = (1 << 20); mem < (128 << 20); mem += (1 << 20)) { + if (*(unsigned long *)((unsigned long)(prom_init) + mem) == + *(unsigned long *)(prom_init)) + break; + } + add_memory_region(0, mem, BOOT_MEM_RAM); +} + +void __init +prom_free_prom_memory(void) +{ +} --- /dev/null 2004-04-06 13:56:48.000000000 -0400 +++ linux-2.4.20/arch/mips/brcm-boards/bcm947xx/setup.c 2005-01-07 05:39:02.000000000 -0500 @@ -0,0 +1,284 @@ +/* + * Generic setup routines for Broadcom MIPS boards + * + * Copyright 2004, Broadcom Corporation + * All Rights Reserved. + * + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. + * + * $Id: setup.c,v 1.3 2004/04/12 05:42:38 honor Exp $ + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_MTD_PARTITIONS +#include +#include +#include +#include +#include +#include +#endif + +#include +#include +#include +#include +#include +#include + +extern void bcm947xx_time_init(void); +extern void bcm947xx_timer_setup(struct irqaction *irq); + +#ifdef CONFIG_REMOTE_DEBUG +extern void set_debug_traps(void); +extern void rs_kgdb_hook(struct serial_state *); +extern void breakpoint(void); +#endif + +#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) +extern struct ide_ops std_ide_ops; +#endif + +/* Global SB handle */ +void *bcm947xx_sbh = NULL; +spinlock_t bcm947xx_sbh_lock = SPIN_LOCK_UNLOCKED; +EXPORT_SYMBOL(bcm947xx_sbh); +EXPORT_SYMBOL(bcm947xx_sbh_lock); + +/* Convenience */ +#define sbh bcm947xx_sbh +#define sbh_lock bcm947xx_sbh_lock + +/* Kernel command line */ +char arcs_cmdline[CL_SIZE] __initdata = CONFIG_CMDLINE; + +void +bcm947xx_machine_restart(char *command) +{ + printk("Please stand by while rebooting the system...\n"); + + /* Set the watchdog timer to reset immediately */ + __cli(); + sb_watchdog(sbh, 1); + while (1); +} + +void +bcm947xx_machine_halt(void) +{ + printk("System halted\n"); + + /* Disable interrupts and watchdog and spin forever */ + __cli(); + sb_watchdog(sbh, 0); + while (1); +} + +#ifdef CONFIG_SERIAL + +static struct serial_struct rs = { + line: 0, + flags: ASYNC_BOOT_AUTOCONF, + io_type: SERIAL_IO_MEM, +}; + +static void __init +serial_add(void *regs, uint irq, uint baud_base, uint reg_shift) +{ + rs.iomem_base = regs; + rs.irq = irq + 2; + rs.baud_base = baud_base / 16; + rs.iomem_reg_shift = reg_shift; + + early_serial_setup(&rs); + + rs.line++; +} + +static void __init +serial_setup(void *sbh) +{ + sb_serial_init(sbh, serial_add); + +#ifdef CONFIG_REMOTE_DEBUG + /* Use the last port for kernel debugging */ + if (rs.iomem_base) + rs_kgdb_hook(&rs); +#endif +} + +#endif /* CONFIG_SERIAL */ + +void __init +brcm_setup(void) +{ + char *value; + + /* Get global SB handle */ + sbh = sb_kattach(); + + /* Initialize clocks and interrupts */ + sb_mips_init(sbh); + +#ifdef CONFIG_SERIAL + /* Initialize UARTs */ + serial_setup(sbh); +#endif + +#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) + ide_ops = &std_ide_ops; +#endif + + /* Override default command line arguments */ + value = nvram_get("kernel_args"); + if (value && strlen(value) && strncmp(value, "empty", 5)) + strncpy(arcs_cmdline, value, sizeof(arcs_cmdline)); + + + /* Generic setup */ + _machine_restart = bcm947xx_machine_restart; + _machine_halt = bcm947xx_machine_halt; + _machine_power_off = bcm947xx_machine_halt; + + board_time_init = bcm947xx_time_init; + board_timer_setup = bcm947xx_timer_setup; +} + +const char * +get_system_type(void) +{ + return "Broadcom BCM947XX"; +} + +void __init +bus_error_init(void) +{ +} + +#ifdef CONFIG_MTD_PARTITIONS + +static struct mtd_partition bcm947xx_parts[] = { + { name: "pmon", offset: 0, size: 0, /*mask_flags: MTD_WRITEABLE,*/ }, + { name: "linux", offset: 0, size: 0, }, + { name: "rootfs", offset: 0, size: 0, /*mask_flags: MTD_WRITEABLE,*/ }, + { name: "nvram", offset: 0, size: 0, }, + { name: NULL, }, +}; + +struct mtd_partition * __init +init_mtd_partitions(struct mtd_info *mtd, size_t size) +{ + struct minix_super_block *minixsb; + struct ext2_super_block *ext2sb; + struct romfs_super_block *romfsb; + struct cramfs_super *cramfsb; + struct trx_header *trx; + unsigned char buf[512]; + int off; + size_t len; + + minixsb = (struct minix_super_block *) buf; + ext2sb = (struct ext2_super_block *) buf; + romfsb = (struct romfs_super_block *) buf; + cramfsb = (struct cramfs_super *) buf; + trx = (struct trx_header *) buf; + + /* Look at every 64 KB boundary */ + for (off = 0; off < size; off += (64 * 1024)) { + memset(buf, 0xe5, sizeof(buf)); + + /* + * Read block 0 to test for romfs and cramfs superblock + */ + if (MTD_READ(mtd, off, sizeof(buf), &len, buf) || + len != sizeof(buf)) + continue; + + /* Try looking at TRX header for rootfs offset */ + if (le32_to_cpu(trx->magic) == TRX_MAGIC) { + bcm947xx_parts[1].offset = off; + if (le32_to_cpu(trx->offsets[1]) > off) + off = le32_to_cpu(trx->offsets[1]); + continue; + } + + /* romfs is at block zero too */ + if (romfsb->word0 == ROMSB_WORD0 && + romfsb->word1 == ROMSB_WORD1) { + printk(KERN_NOTICE + "%s: romfs filesystem found at block %d\n", + mtd->name, off / BLOCK_SIZE); + goto done; + } + + /* so is cramfs */ + if (cramfsb->magic == CRAMFS_MAGIC) { + printk(KERN_NOTICE + "%s: cramfs filesystem found at block %d\n", + mtd->name, off / BLOCK_SIZE); + goto done; + } + + /* + * Read block 1 to test for minix and ext2 superblock + */ + if (MTD_READ(mtd, off + BLOCK_SIZE, sizeof(buf), &len, buf) || + len != sizeof(buf)) + continue; + + /* Try minix */ + if (minixsb->s_magic == MINIX_SUPER_MAGIC || + minixsb->s_magic == MINIX_SUPER_MAGIC2) { + printk(KERN_NOTICE + "%s: Minix filesystem found at block %d\n", + mtd->name, off / BLOCK_SIZE); + goto done; + } + + /* Try ext2 */ + if (ext2sb->s_magic == cpu_to_le16(EXT2_SUPER_MAGIC)) { + printk(KERN_NOTICE + "%s: ext2 filesystem found at block %d\n", + mtd->name, off / BLOCK_SIZE); + goto done; + } + } + + printk(KERN_NOTICE + "%s: Couldn't find valid ROM disk image\n", + mtd->name); + + done: + /* Find and size nvram */ + bcm947xx_parts[3].offset = size - ROUNDUP(NVRAM_SPACE, mtd->erasesize); + bcm947xx_parts[3].size = size - bcm947xx_parts[3].offset; + + /* Find and size rootfs */ + if (off < size) { + bcm947xx_parts[2].offset = off; + bcm947xx_parts[2].size = bcm947xx_parts[3].offset - bcm947xx_parts[2].offset; + } + + /* Size linux (kernel and rootfs) */ + bcm947xx_parts[1].size = bcm947xx_parts[3].offset - bcm947xx_parts[1].offset; + + /* Size pmon */ + bcm947xx_parts[0].size = bcm947xx_parts[1].offset - bcm947xx_parts[0].offset; + + return bcm947xx_parts; +} + +EXPORT_SYMBOL(init_mtd_partitions); + +#endif --- /dev/null 2004-04-06 13:56:48.000000000 -0400 +++ linux-2.4.20/arch/mips/brcm-boards/bcm947xx/time.c 2005-01-07 05:39:02.000000000 -0500 @@ -0,0 +1,117 @@ +/* + * Copyright 2004, Broadcom Corporation + * All Rights Reserved. + * + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. + * + * $Id: time.c,v 1.1.1.6 2004/04/12 04:31:00 honor Exp $ + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +/* Global SB handle */ +extern void *bcm947xx_sbh; +extern spinlock_t bcm947xx_sbh_lock; + +/* Convenience */ +#define sbh bcm947xx_sbh +#define sbh_lock bcm947xx_sbh_lock + +extern int panic_timeout; +static int watchdog = 0; +static u8 *mcr = NULL; + +void __init +bcm947xx_time_init(void) +{ + unsigned int hz; + extifregs_t *eir; + + /* + * Use deterministic values for initial counter interrupt + * so that calibrate delay avoids encountering a counter wrap. + */ + write_c0_count(0); + write_c0_compare(0xffff); + + if (!(hz = sb_mips_clock(sbh))) + hz = 100000000; + + printk("CPU: BCM%04x rev %d at %d MHz\n", sb_chip(sbh), sb_chiprev(sbh), + (hz + 500000) / 1000000); + + /* Set MIPS counter frequency for fixed_rate_gettimeoffset() */ + mips_counter_frequency = hz / 2; + + /* Set watchdog interval in ms */ + watchdog = simple_strtoul(nvram_safe_get("watchdog"), NULL, 0); + + /* Please set the watchdog to 3 sec if it is less than 3 but not equal to 0 */ + if (watchdog > 0) { + if (watchdog < 3000) + watchdog = 3000; + } + + + /* Set panic timeout in seconds */ + panic_timeout = watchdog / 1000; + + /* Setup blink */ + if ((eir = sb_setcore(sbh, SB_EXTIF, 0))) { + sbconfig_t *sb = (sbconfig_t *)((unsigned int) eir + SBCONFIGOFF); + unsigned long base = EXTIF_CFGIF_BASE(sb_base(readl(&sb->sbadmatch1))); + mcr = (u8 *) ioremap_nocache(base + UART_MCR, 1); + } +} + +static void +bcm947xx_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + /* Generic MIPS timer code */ + timer_interrupt(irq, dev_id, regs); + + /* Set the watchdog timer to reset after the specified number of ms */ + if (watchdog > 0) + sb_watchdog(sbh, WATCHDOG_CLOCK / 1000 * watchdog); + +#ifdef CONFIG_HWSIM + (*((int *)0xa0000f1c))++; +#else + /* Blink one of the LEDs in the external UART */ + if (mcr && !(jiffies % (HZ/2))) + writeb(readb(mcr) ^ UART_MCR_OUT2, mcr); +#endif +} + +static struct irqaction bcm947xx_timer_irqaction = { + bcm947xx_timer_interrupt, + SA_INTERRUPT, + 0, + "timer", + NULL, + NULL +}; + +void __init +bcm947xx_timer_setup(struct irqaction *irq) +{ + /* Enable the timer interrupt */ + setup_irq(7, &bcm947xx_timer_irqaction); +} --- /dev/null 2004-04-06 13:56:48.000000000 -0400 +++ linux-2.4.20/arch/mips/brcm-boards/generic/Makefile 2005-01-07 05:39:02.000000000 -0500 @@ -0,0 +1,26 @@ +# +# Makefile for generic Broadcom MIPS boards +# +# Copyright 2004, Broadcom Corporation +# All Rights Reserved. +# +# THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY +# KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM +# SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS +# FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. +# +# $Id: Makefile,v 1.1.1.6 2004/04/12 04:31:00 honor Exp $ +# + +.S.s: + $(CPP) $(AFLAGS) $< -o $*.s +.S.o: + $(CC) $(AFLAGS) -c $< -o $*.o + +O_TARGET := brcm.o + +obj-y := int-handler.o irq.o + +obj-$(CONFIG_REMOTE_DEBUG) += gdb_hook.o + +include $(TOPDIR)/Rules.make --- /dev/null 2004-04-06 13:56:48.000000000 -0400 +++ linux-2.4.20/arch/mips/brcm-boards/generic/gdb_hook.c 2005-01-07 05:39:02.000000000 -0500 @@ -0,0 +1,120 @@ +/* + * Copyright 2004, Broadcom Corporation + * All Rights Reserved. + * + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. + * + * Carsten Langgaard, carstenl@mips.com + * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. + * + * ######################################################################## + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * 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., + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * ######################################################################## + * + * This is the interface to the remote debugger stub. + * + */ + +#include +#include + +#include +#include + +static struct async_struct kdb_port_info = {0}; + +static __inline__ unsigned int serial_in(struct async_struct *info, int offset) +{ + return readb((unsigned long) info->iomem_base + + (offset<iomem_reg_shift)); +} + +static __inline__ void serial_out(struct async_struct *info, int offset, + int value) +{ + writeb(value, (unsigned long) info->iomem_base + + (offset<iomem_reg_shift)); +} + +void rs_kgdb_hook(struct serial_state *ser) { + int t; + + kdb_port_info.state = ser; + kdb_port_info.magic = SERIAL_MAGIC; + kdb_port_info.port = ser->port; + kdb_port_info.flags = ser->flags; + kdb_port_info.iomem_base = ser->iomem_base; + kdb_port_info.iomem_reg_shift = ser->iomem_reg_shift; + kdb_port_info.MCR = UART_MCR_DTR | UART_MCR_RTS; + + /* + * Clear all interrupts + */ + serial_in(&kdb_port_info, UART_LSR); + serial_in(&kdb_port_info, UART_RX); + serial_in(&kdb_port_info, UART_IIR); + serial_in(&kdb_port_info, UART_MSR); + + /* + * Now, initialize the UART + */ + serial_out(&kdb_port_info, UART_LCR, UART_LCR_WLEN8); /* reset DLAB */ + serial_out(&kdb_port_info, UART_MCR, kdb_port_info.MCR); + + /* + * and set the speed of the serial port + * (currently hardwired to 115200 8N1 + */ + + /* baud rate is fixed to 115200 (is this sufficient?)*/ + t = kdb_port_info.state->baud_base / 115200; + /* set DLAB */ + serial_out(&kdb_port_info, UART_LCR, UART_LCR_WLEN8 | UART_LCR_DLAB); + serial_out(&kdb_port_info, UART_DLL, t & 0xff);/* LS of divisor */ + serial_out(&kdb_port_info, UART_DLM, t >> 8); /* MS of divisor */ + /* reset DLAB */ + serial_out(&kdb_port_info, UART_LCR, UART_LCR_WLEN8); +} + +int putDebugChar(char c) +{ + + if (!kdb_port_info.state) { /* need to init device first */ + return 0; + } + + while ((serial_in(&kdb_port_info, UART_LSR) & UART_LSR_THRE) == 0) + ; + + serial_out(&kdb_port_info, UART_TX, c); + + return 1; +} + +char getDebugChar(void) +{ + if (!kdb_port_info.state) { /* need to init device first */ + return 0; + } + + while (!(serial_in(&kdb_port_info, UART_LSR) & 1)) + ; + + return(serial_in(&kdb_port_info, UART_RX)); +} --- /dev/null 2004-04-06 13:56:48.000000000 -0400 +++ linux-2.4.20/arch/mips/brcm-boards/generic/int-handler.S 2005-01-07 05:39:02.000000000 -0500 @@ -0,0 +1,51 @@ +/* + * Generic interrupt handler for Broadcom MIPS boards + * + * Copyright 2004, Broadcom Corporation + * All Rights Reserved. + * + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. + * + * $Id: int-handler.S,v 1.1.1.6 2004/04/12 04:31:00 honor Exp $ + */ + +#include + +#include +#include +#include +#include + +/* + * MIPS IRQ Source + * -------- ------ + * 0 Software (ignored) + * 1 Software (ignored) + * 2 Combined hardware interrupt (hw0) + * 3 Hardware + * 4 Hardware + * 5 Hardware + * 6 Hardware + * 7 R4k timer + */ + + .text + .set noreorder + .set noat + .align 5 + NESTED(brcmIRQ, PT_SIZE, sp) + SAVE_ALL + CLI + .set at + .set noreorder + + jal brcm_irq_dispatch + move a0, sp + + j ret_from_irq + nop + + END(brcmIRQ) --- /dev/null 2004-04-06 13:56:48.000000000 -0400 +++ linux-2.4.20/arch/mips/brcm-boards/generic/irq.c 2005-01-07 05:39:02.000000000 -0500 @@ -0,0 +1,130 @@ +/* + * Generic interrupt control functions for Broadcom MIPS boards + * + * Copyright 2004, Broadcom Corporation + * All Rights Reserved. + * + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. + * + * $Id: irq.c,v 1.1.1.6 2004/04/12 04:31:00 honor Exp $ + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5) + +extern asmlinkage void brcmIRQ(void); +extern asmlinkage unsigned int do_IRQ(int irq, struct pt_regs *regs); + +void +brcm_irq_dispatch(struct pt_regs *regs) +{ + u32 cause; + + cause = read_c0_cause() & + read_c0_status() & + CAUSEF_IP; + +#ifdef CONFIG_KERNPROF + change_c0_status(cause | 1, 1); +#else + clear_c0_status(cause); +#endif + + if (cause & CAUSEF_IP7) + do_IRQ(7, regs); + if (cause & CAUSEF_IP2) + do_IRQ(2, regs); + if (cause & CAUSEF_IP3) + do_IRQ(3, regs); + if (cause & CAUSEF_IP4) + do_IRQ(4, regs); + if (cause & CAUSEF_IP5) + do_IRQ(5, regs); + if (cause & CAUSEF_IP6) + do_IRQ(6, regs); +} + +static void +enable_brcm_irq(unsigned int irq) +{ + if (irq < 8) + set_c0_status(1 << (irq + 8)); + else + set_c0_status(IE_IRQ0); +} + +static void +disable_brcm_irq(unsigned int irq) +{ + if (irq < 8) + clear_c0_status(1 << (irq + 8)); + else + clear_c0_status(IE_IRQ0); +} + +static void +ack_brcm_irq(unsigned int irq) +{ + /* Already done in brcm_irq_dispatch */ +} + +static unsigned int +startup_brcm_irq(unsigned int irq) +{ + enable_brcm_irq(irq); + + return 0; /* never anything pending */ +} + +static void +end_brcm_irq(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + enable_brcm_irq(irq); +} + +static struct hw_interrupt_type brcm_irq_type = { + typename: "MIPS", + startup: startup_brcm_irq, + shutdown: disable_brcm_irq, + enable: enable_brcm_irq, + disable: disable_brcm_irq, + ack: ack_brcm_irq, + end: end_brcm_irq, + NULL +}; + +void __init +init_IRQ(void) +{ + int i; + + for (i = 0; i < NR_IRQS; i++) { + irq_desc[i].status = IRQ_DISABLED; + irq_desc[i].action = 0; + irq_desc[i].depth = 1; + irq_desc[i].handler = &brcm_irq_type; + } + + set_except_vector(0, brcmIRQ); + change_c0_status(ST0_IM, ALLINTS); + +#ifdef CONFIG_REMOTE_DEBUG + printk("Breaking into debugger...\n"); + set_debug_traps(); + breakpoint(); +#endif +} --- linux-2.4.20/arch/mips/config-shared.in~2.4.20_broadcom_3_37_2_1109_US.patch 2005-01-07 05:39:01.000000000 -0500 +++ linux-2.4.20/arch/mips/config-shared.in 2005-01-08 12:16:20.335771152 -0500 @@ -191,8 +191,15 @@ fi fi fi +dep_bool 'Support for Broadcom MIPS-based boards' CONFIG_MIPS_BRCM $CONFIG_EXPERIMENTAL +dep_bool 'Support for Broadcom BCM947XX' CONFIG_BCM947XX $CONFIG_MIPS_BRCM +if [ "$CONFIG_BCM947XX" = "y" ] ; then + bool ' Support for Broadcom BCM4710' CONFIG_BCM4710 + bool ' Support for Broadcom BCM4310' CONFIG_BCM4310 + bool ' Support for Broadcom BCM4704' CONFIG_BCM4704 + bool ' Support for Broadcom BCM5365' CONFIG_BCM5365 +fi bool 'Support for SNI RM200 PCI' CONFIG_SNI_RM200_PCI -bool 'Support for TANBAC TB0226 (Mbase)' CONFIG_TANBAC_TB0226 dep_bool 'Support for Toshiba JMR-TX3927 board' CONFIG_TOSHIBA_JMR3927 $CONFIG_MIPS32 bool 'Support for Victor MP-C303/304' CONFIG_VICTOR_MPC30X if [ "$CONFIG_VICTOR_MPC30X" = "y" ]; then @@ -206,6 +213,11 @@ define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM n # +# Provide an option for a default kernel command line +# +string 'Default kernel command string' CONFIG_CMDLINE "" + +# # Select some configuration options automatically based on user selections. # @@ -526,6 +538,13 @@ define_bool CONFIG_SWAP_IO_SPACE_L y define_bool CONFIG_BOOT_ELF32 y fi +if [ "$CONFIG_BCM947XX" = "y" ] ; then + define_bool CONFIG_PCI y + define_bool CONFIG_NONCOHERENT_IO y + define_bool CONFIG_NEW_TIME_C y + define_bool CONFIG_NEW_IRQ y + define_bool CONFIG_HND y +fi if [ "$CONFIG_SNI_RM200_PCI" = "y" ]; then define_bool CONFIG_ARC32 y define_bool CONFIG_ARC_MEMORY y --- /dev/null 2004-04-06 13:56:48.000000000 -0400 +++ linux-2.4.20/arch/mips/defconfig-bcm947xx 2005-01-07 05:39:02.000000000 -0500 @@ -0,0 +1,769 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_MIPS=y +CONFIG_MIPS32=y +# CONFIG_MIPS64 is not set + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y + +# +# Loadable module support +# +CONFIG_MODULES=y +# CONFIG_MODVERSIONS is not set +# CONFIG_KMOD is not set + +# +# Machine selection +# +# CONFIG_ACER_PICA_61 is not set +# CONFIG_MIPS_DB1000 is not set +# CONFIG_MIPS_DB1100 is not set +# CONFIG_MIPS_DB1500 is not set +# CONFIG_MIPS_PB1000 is not set +# CONFIG_MIPS_PB1100 is not set +# CONFIG_MIPS_PB1500 is not set +# CONFIG_BAGET_MIPS is not set +# CONFIG_CASIO_E55 is not set +# CONFIG_MIPS_COBALT is not set +# CONFIG_DECSTATION is not set +# CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_HP_LASERJET is not set +# CONFIG_IBM_WORKPAD is not set +# CONFIG_LASAT is not set +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MAGNUM_4000 is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SEAD is not set +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_DDB5074 is not set +# CONFIG_DDB5476 is not set +# CONFIG_DDB5477 is not set +# CONFIG_NEC_OSPREY is not set +# CONFIG_NEC_EAGLE is not set +# CONFIG_OLIVETTI_M700 is not set +# CONFIG_NINO is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP27 is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SIBYTE_SB1xxx_SOC is not set +CONFIG_MIPS_BRCM=y +CONFIG_BCM947XX=y +CONFIG_BCM4710=y +CONFIG_BCM4310=y +CONFIG_BCM4704=y +# CONFIG_BCM5365 is not set +# CONFIG_SNI_RM200_PCI is not set +# CONFIG_TOSHIBA_JMR3927 is not set +# CONFIG_VICTOR_MPC30X is not set +# CONFIG_ZAO_CAPCELLA is not set +# CONFIG_HIGHMEM is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set +CONFIG_CMDLINE="root=/dev/mtdblock2 noinitrd console=ttyS0,115200" +CONFIG_PCI=y +CONFIG_NONCOHERENT_IO=y +CONFIG_NEW_TIME_C=y +CONFIG_NEW_IRQ=y +CONFIG_HND=y +# CONFIG_MIPS_AU1000 is not set + +# +# CPU selection +# +CONFIG_CPU_MIPS32=y +# CONFIG_CPU_MIPS64 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_TX39XX is not set +# CONFIG_CPU_VR41XX is not set +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set +# CONFIG_CPU_R5000 is not set +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_SB1 is not set +CONFIG_CPU_HAS_PREFETCH=y +# CONFIG_VTAG_ICACHE is not set +# CONFIG_64BIT_PHYS_ADDR is not set +# CONFIG_CPU_ADVANCED is not set +CONFIG_CPU_HAS_LLSC=y +# CONFIG_CPU_HAS_LLDSCD is not set +# CONFIG_CPU_HAS_WB is not set +CONFIG_CPU_HAS_SYNC=y + +# +# General setup +# +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_NET=y +# CONFIG_PCI_NAMES is not set +# CONFIG_ISA is not set +# CONFIG_EISA is not set +# CONFIG_TC is not set +# CONFIG_MCA is not set +# CONFIG_SBUS is not set +CONFIG_HOTPLUG=y + +# +# PCMCIA/CardBus support +# +# CONFIG_PCMCIA is not set + +# +# PCI Hotplug Support +# +# CONFIG_HOTPLUG_PCI is not set +# CONFIG_HOTPLUG_PCI_COMPAQ is not set +# CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM is not set +# CONFIG_HOTPLUG_PCI_ACPI is not set +# CONFIG_SYSVIPC is not set +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +# CONFIG_PRINT_SYSCALLS is not set +CONFIG_KCORE_ELF=y +# CONFIG_KCORE_AOUT is not set +# CONFIG_BINFMT_AOUT is not set +CONFIG_BINFMT_ELF=y +# CONFIG_MIPS32_COMPAT is not set +# CONFIG_MIPS32_O32 is not set +# CONFIG_MIPS32_N32 is not set +# CONFIG_BINFMT_ELF32 is not set +# CONFIG_BINFMT_MISC is not set +# CONFIG_PM is not set + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_CONCAT is not set +# CONFIG_MTD_REDBOOT_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +# CONFIG_MTD_BLOCK is not set +CONFIG_MTD_BLOCK_RO=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_GEN_PROBE=y +CONFIG_MTD_CFI_ADV_OPTIONS=y +CONFIG_MTD_CFI_NOSWAP=y +# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set +# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set +CONFIG_MTD_CFI_GEOMETRY=y +# CONFIG_MTD_CFI_B1 is not set +CONFIG_MTD_CFI_B2=y +# CONFIG_MTD_CFI_B4 is not set +CONFIG_MTD_CFI_I1=y +# CONFIG_MTD_CFI_I2 is not set +# CONFIG_MTD_CFI_I4 is not set +CONFIG_MTD_CFI_INTELEXT=y +CONFIG_MTD_CFI_AMDSTD=y +CONFIG_MTD_CFI_SSTSTD=y +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set +# CONFIG_MTD_OBSOLETE_CHIPS is not set +# CONFIG_MTD_AMDSTD is not set +# CONFIG_MTD_SHARP is not set +# CONFIG_MTD_JEDEC is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_PHYSMAP is not set +CONFIG_MTD_BCM947XX=y +# CONFIG_MTD_PB1000 is not set +# CONFIG_MTD_PB1500 is not set +# CONFIG_MTD_PB1100 is not set +# CONFIG_MTD_CSTM_MIPS_IXX is not set +# CONFIG_MTD_OCELOT is not set +# CONFIG_MTD_LASAT is not set +# CONFIG_MTD_PCI is not set + +# +# Self-contained MTD device drivers +# +CONFIG_MTD_SFLASH=y +# CONFIG_MTD_PMC551 is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLKMTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC1000 is not set +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOCPROBE is not set + +# +# NAND Flash Device Drivers +# +# CONFIG_MTD_NAND is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play configuration +# +# CONFIG_PNP is not set +# CONFIG_ISAPNP is not set + +# +# Block devices +# +# CONFIG_BLK_DEV_MSYS is not set +# CONFIG_NOROOT is not set +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_DEV_XD is not set +# CONFIG_PARIDE is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_CISS_SCSI_TAPE is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set +# CONFIG_BLK_STATS is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set +# CONFIG_BLK_DEV_MD is not set +# CONFIG_MD_LINEAR is not set +# CONFIG_MD_RAID0 is not set +# CONFIG_MD_RAID1 is not set +# CONFIG_MD_RAID5 is not set +# CONFIG_MD_MULTIPATH is not set +# CONFIG_BLK_DEV_LVM is not set + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +# CONFIG_NETLINK_DEV is not set +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set +# CONFIG_FILTER is not set +CONFIG_UNIX=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +# CONFIG_IP_PNP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +CONFIG_IP_MROUTE=y +# CONFIG_IP_PIMSM_V1 is not set +# CONFIG_IP_PIMSM_V2 is not set +# CONFIG_ARPD is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set + +# +# IP: Netfilter Configuration +# +CONFIG_IP_NF_CONNTRACK=y +CONFIG_IP_NF_FTP=y +CONFIG_IP_NF_TFTP=y +CONFIG_IP_NF_H323=y +# CONFIG_IP_NF_IRC is not set +# CONFIG_IP_NF_MMS is not set +CONFIG_IP_NF_CT_PROTO_GRE=y +CONFIG_IP_NF_PPTP=y +# CONFIG_IP_NF_SIP is not set +# CONFIG_IP_NF_QUEUE is not set +CONFIG_IP_NF_IPTABLES=y +# CONFIG_IP_NF_MATCH_LIMIT is not set +# CONFIG_IP_NF_POOL is not set +CONFIG_IP_NF_MATCH_MAC=y +# CONFIG_IP_NF_MATCH_PKTTYPE is not set +CONFIG_IP_NF_MATCH_MARK=y +# CONFIG_IP_NF_MATCH_MULTIPORT is not set +# CONFIG_IP_NF_MATCH_MPORT is not set +CONFIG_IP_NF_MATCH_TOS=y +CONFIG_IP_NF_MATCH_TIME=y +# CONFIG_IP_NF_MATCH_ECN is not set +# CONFIG_IP_NF_MATCH_DSCP is not set +# CONFIG_IP_NF_MATCH_AH_ESP is not set +# CONFIG_IP_NF_MATCH_LENGTH is not set +# CONFIG_IP_NF_MATCH_TTL is not set +CONFIG_IP_NF_MATCH_TCPMSS=y +# CONFIG_IP_NF_MATCH_HELPER is not set +CONFIG_IP_NF_MATCH_STATE=y +# CONFIG_IP_NF_MATCH_CONNTRACK is not set +# CONFIG_IP_NF_MATCH_UNCLEAN is not set +CONFIG_IP_NF_MATCH_WEBSTR=y +# CONFIG_IP_NF_MATCH_OWNER is not set +CONFIG_IP_NF_FILTER=y +CONFIG_IP_NF_TARGET_REJECT=y +# CONFIG_IP_NF_TARGET_MIRROR is not set +CONFIG_IP_NF_NAT=y +CONFIG_IP_NF_NAT_NEEDED=y +CONFIG_IP_NF_TARGET_MASQUERADE=y +CONFIG_IP_NF_TARGET_REDIRECT=y +CONFIG_IP_NF_AUTOFW=y +CONFIG_IP_NF_TARGET_TRIGGER=y +CONFIG_IP_NF_NAT_H323=y +CONFIG_IP_NF_NAT_PPTP=y +# CONFIG_IP_NF_NAT_SIP is not set +CONFIG_IP_NF_NAT_PROTO_GRE=y +# CONFIG_IP_NF_NAT_LOCAL is not set +# CONFIG_IP_NF_NAT_SNMP_BASIC is not set +CONFIG_IP_NF_NAT_FTP=y +CONFIG_IP_NF_NAT_TFTP=y +CONFIG_IP_NF_MANGLE=y +CONFIG_IP_NF_TARGET_TOS=y +# CONFIG_IP_NF_TARGET_ECN is not set +# CONFIG_IP_NF_TARGET_DSCP is not set +CONFIG_IP_NF_TARGET_LOG=y +CONFIG_IP_NF_TARGET_MARK=y +# CONFIG_IP_NF_TARGET_ULOG is not set +CONFIG_IP_NF_TARGET_TCPMSS=y +# CONFIG_IP_NF_ARPTABLES is not set +# CONFIG_IPV6 is not set +# CONFIG_KHTTPD is not set +# CONFIG_ATM is not set +CONFIG_VLAN_8021Q=y + +# +# +# +# CONFIG_IPX is not set +# CONFIG_ATALK is not set + +# +# Appletalk devices +# +# CONFIG_DEV_APPLETALK is not set +# CONFIG_DECNET is not set +CONFIG_BRIDGE=y +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_LLC is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +CONFIG_NET_SCHED=y +CONFIG_NET_SCH_CBQ=y +CONFIG_NET_SCH_HTB=y +# CONFIG_NET_SCH_CSZ is not set +CONFIG_NET_SCH_PRIO=y +# CONFIG_NET_SCH_RED is not set +CONFIG_NET_SCH_SFQ=y +# CONFIG_NET_SCH_TEQL is not set +# CONFIG_NET_SCH_TBF is not set +# CONFIG_NET_SCH_GRED is not set +# CONFIG_NET_SCH_DSMARK is not set +# CONFIG_NET_SCH_INGRESS is not set +CONFIG_NET_QOS=y +CONFIG_NET_ESTIMATOR=y +CONFIG_NET_CLS=y +# CONFIG_NET_CLS_TCINDEX is not set +# CONFIG_NET_CLS_ROUTE4 is not set +# CONFIG_NET_CLS_FW is not set +CONFIG_NET_CLS_U32=y +# CONFIG_NET_CLS_RSVP is not set +# CONFIG_NET_CLS_RSVP6 is not set +# CONFIG_NET_CLS_POLICE is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set +# CONFIG_PHONE_IXJ is not set +# CONFIG_PHONE_IXJ_PCMCIA is not set + +# +# ATA/IDE/MFM/RLL support +# +# CONFIG_IDE is not set +# CONFIG_BLK_DEV_IDE_MODES is not set +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI support +# +# CONFIG_SCSI is not set + +# +# I2O device support +# +# CONFIG_I2O is not set +# CONFIG_I2O_PCI is not set +# CONFIG_I2O_BLOCK is not set +# CONFIG_I2O_LAN is not set +# CONFIG_I2O_SCSI is not set +# CONFIG_I2O_PROC is not set + +# +# Network device support +# +CONFIG_NETDEVICES=y + +# +# Broadcom HND network devices +# +CONFIG_HND=y +# CONFIG_IL is not set +# CONFIG_IL_42XX is not set +# CONFIG_IL_47XX is not set +CONFIG_LARQ_BUF=0 +CONFIG_ET=m +# CONFIG_ET_4413 is not set +CONFIG_ET_47XX=y +CONFIG_WL=m +CONFIG_WL_AP=y +CONFIG_WL_STA=y +# CONFIG_WL_OID is not set + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_ETHERTAP is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_SUNLANCE is not set +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNBMAC is not set +# CONFIG_SUNQE is not set +# CONFIG_SUNGEM is not set +# CONFIG_NET_VENDOR_3COM is not set +# CONFIG_LANCE is not set +# CONFIG_NET_VENDOR_SMC is not set +# CONFIG_NET_VENDOR_RACAL is not set +# CONFIG_HP100 is not set +# CONFIG_NET_ISA is not set +# CONFIG_NET_PCI is not set +# CONFIG_NET_POCKET is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_E1000 is not set +# CONFIG_MYRI_SBUS is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_SK98LIN is not set +# CONFIG_TIGON3 is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PLIP is not set +CONFIG_PPP=y +# CONFIG_PPP_MULTILINK is not set +# CONFIG_PPP_FILTER is not set +CONFIG_PPP_ASYNC=y +CONFIG_PPP_SYNC_TTY=y +# CONFIG_PPP_DEFLATE is not set +# CONFIG_PPP_BSDCOMP is not set +CONFIG_PPPOE=y +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set +# CONFIG_NET_FC is not set +# CONFIG_RCPCI is not set +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Input core support +# +# CONFIG_INPUT is not set +# CONFIG_INPUT_KEYBDEV is not set +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_EVDEV is not set + +# +# Character devices +# +# CONFIG_VT is not set +CONFIG_SERIAL=y +CONFIG_SERIAL_CONSOLE=y +# CONFIG_SERIAL_EXTENDED is not set +CONFIG_SERIAL_NONSTANDARD=y +# CONFIG_COMPUTONE is not set +# CONFIG_ROCKETPORT is not set +# CONFIG_CYCLADES is not set +# CONFIG_DIGIEPCA is not set +# CONFIG_DIGI is not set +# CONFIG_ESPSERIAL is not set +# CONFIG_MOXA_INTELLIO is not set +# CONFIG_MOXA_SMARTIO is not set +# CONFIG_ISI is not set +# CONFIG_SYNCLINK is not set +# CONFIG_SYNCLINKMP is not set +CONFIG_N_HDLC=y +# CONFIG_RISCOM8 is not set +# CONFIG_SPECIALIX is not set +# CONFIG_SX is not set +# CONFIG_RIO is not set +# CONFIG_STALDRV is not set +# CONFIG_SERIAL_TX3912 is not set +# CONFIG_SERIAL_TX3912_CONSOLE is not set +# CONFIG_TXX927_SERIAL is not set +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=16 + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_MOUSE is not set + +# +# Joysticks +# +# CONFIG_INPUT_GAMEPORT is not set + +# +# Input core support is needed for gameports +# + +# +# Input core support is needed for joysticks +# +# CONFIG_QIC02_TAPE is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_AMD_PM768 is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set +# CONFIG_AGP is not set +# CONFIG_DRM is not set + +# +# File systems +# +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_REISERFS_CHECK is not set +# CONFIG_REISERFS_PROC_INFO is not set +# CONFIG_ADFS_FS is not set +# CONFIG_ADFS_FS_RW is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BEFS_DEBUG is not set +# CONFIG_BFS_FS is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +# CONFIG_JBD_DEBUG is not set +# CONFIG_FAT_FS is not set +# CONFIG_MSDOS_FS is not set +# CONFIG_UMSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set +# CONFIG_JFFS2_FS is not set +CONFIG_CRAMFS=y +# CONFIG_TMPFS is not set +CONFIG_RAMFS=y +# CONFIG_ISO9660_FS is not set +# CONFIG_JOLIET is not set +# CONFIG_ZISOFS is not set +# CONFIG_JFS_FS is not set +# CONFIG_JFS_DEBUG is not set +# CONFIG_JFS_STATISTICS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_NTFS_FS is not set +# CONFIG_NTFS_RW is not set +# CONFIG_HPFS_FS is not set +CONFIG_PROC_FS=y +CONFIG_DEVFS_FS=y +CONFIG_DEVFS_MOUNT=y +# CONFIG_DEVFS_DEBUG is not set +# CONFIG_DEVPTS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_QNX4FS_RW is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_EXT2_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UDF_FS is not set +# CONFIG_UDF_RW is not set +# CONFIG_UFS_FS is not set +# CONFIG_UFS_FS_WRITE is not set + +# +# Network File Systems +# +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_NFS_FS is not set +# CONFIG_NFS_V3 is not set +# CONFIG_ROOT_NFS is not set +# CONFIG_NFSD is not set +# CONFIG_NFSD_V3 is not set +# CONFIG_NFSD_TCP is not set +# CONFIG_SUNRPC is not set +# CONFIG_LOCKD is not set +# CONFIG_SMB_FS is not set +# CONFIG_NCP_FS is not set +# CONFIG_NCPFS_PACKET_SIGNING is not set +# CONFIG_NCPFS_IOCTL_LOCKING is not set +# CONFIG_NCPFS_STRONG is not set +# CONFIG_NCPFS_NFS_NS is not set +# CONFIG_NCPFS_OS2_NS is not set +# CONFIG_NCPFS_SMALLDOS is not set +# CONFIG_NCPFS_NLS is not set +# CONFIG_NCPFS_EXTRAS is not set +# CONFIG_ZISOFS_FS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +# CONFIG_MSDOS_PARTITION is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_EFI_PARTITION is not set +# CONFIG_SMB_NLS is not set +# CONFIG_NLS is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +# CONFIG_USB is not set + +# +# Support for USB gadgets +# +# CONFIG_USB_GADGET is not set + +# +# Bluetooth support +# +# CONFIG_BLUEZ is not set + +# +# Kernel hacking +# +CONFIG_CROSSCOMPILE=y +# CONFIG_KERNPROF is not set +# CONFIG_MCOUNT is not set +# CONFIG_DEBUG is not set +CONFIG_MAGIC_SYSRQ=y +# CONFIG_MIPS_UNCACHED is not set +# CONFIG_KTRACE is not set +# CONFIG_HWSIM is not set + +# +# Library routines +# +CONFIG_ZLIB_INFLATE=y +# CONFIG_ZLIB_DEFLATE is not set --- linux-2.4.20/arch/mips/kernel/cpu-probe.c~2.4.20_broadcom_3_37_2_1109_US.patch 2005-01-07 05:39:01.000000000 -0500 +++ linux-2.4.20/arch/mips/kernel/cpu-probe.c 2005-01-07 05:39:02.000000000 -0500 @@ -158,6 +158,16 @@ unsigned long config0 = read_c0_config(); unsigned long config1; + if ((config0 & CONF_BE) != +#ifdef CONFIG_CPU_LITTLE_ENDIAN + 0 +#else + CONF_BE +#endif + ) { + panic("Kernel compiled little-endian, but running on a big-endian cpu"); + } + if (config0 & (1 << 31)) { /* MIPS32 or MIPS64 compliant CPU. Read Config 1 register. */ mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_4KEX | @@ -179,9 +189,9 @@ } #endif mips_cpu.processor_id = read_c0_prid(); - switch (mips_cpu.processor_id & 0xff0000) { + switch (mips_cpu.processor_id & PRID_COMP_MASK) { case PRID_COMP_LEGACY: - switch (mips_cpu.processor_id & 0xff00) { + switch (mips_cpu.processor_id & PRID_IMP_MASK) { case PRID_IMP_R2000: mips_cpu.cputype = CPU_R2000; mips_cpu.isa_level = MIPS_CPU_ISA_I; @@ -191,7 +201,7 @@ mips_cpu.tlbsize = 64; break; case PRID_IMP_R3000: - if ((mips_cpu.processor_id & 0xff) == PRID_REV_R3000A) + if ((mips_cpu.processor_id & PRID_REV_MASK) == PRID_REV_R3000A) if (cpu_has_confreg()) mips_cpu.cputype = CPU_R3081E; else @@ -205,7 +215,7 @@ mips_cpu.tlbsize = 64; break; case PRID_IMP_R4000: - if ((mips_cpu.processor_id & 0xff) >= PRID_REV_R4400) + if ((mips_cpu.processor_id & PRID_REV_MASK) >= PRID_REV_R4400) mips_cpu.cputype = CPU_R4400SC; else mips_cpu.cputype = CPU_R4000SC; @@ -287,7 +297,7 @@ mips_cpu.icache.ways = 2; mips_cpu.dcache.ways = 2; } else { - switch (mips_cpu.processor_id & 0xff) { + switch (mips_cpu.processor_id & PRID_REV_MASK) { case PRID_REV_TX3912: mips_cpu.cputype = CPU_TX3912; mips_cpu.tlbsize = 32; @@ -405,7 +415,7 @@ break; #if defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_MIPS64) case PRID_COMP_MIPS: - switch (mips_cpu.processor_id & 0xff00) { + switch (mips_cpu.processor_id & PRID_IMP_MASK) { case PRID_IMP_4KC: mips_cpu.cputype = CPU_4KC; mips_cpu.isa_level = MIPS_CPU_ISA_M32; @@ -432,10 +442,10 @@ } break; case PRID_COMP_ALCHEMY: - switch (mips_cpu.processor_id & 0xff00) { + switch (mips_cpu.processor_id & PRID_IMP_MASK) { case PRID_IMP_AU1_REV1: case PRID_IMP_AU1_REV2: - switch ((mips_cpu.processor_id >> 24) & 0xff) { + switch ((mips_cpu.processor_id >> 24) & PRID_REV_MASK) { case 0: mips_cpu.cputype = CPU_AU1000; break; @@ -456,9 +466,43 @@ break; } break; + case PRID_COMP_BROADCOM: + switch (mips_cpu.processor_id & PRID_IMP_MASK) { + case PRID_IMP_BCM4710: + mips_cpu.cputype = CPU_BCM4710; + mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_4KEX | + MIPS_CPU_4KTLB | MIPS_CPU_COUNTER; + config1 = read_c0_config1(); + if (config1 & (1 << 3)) + mips_cpu.options |= MIPS_CPU_WATCH; + if (config1 & (1 << 2)) + mips_cpu.options |= MIPS_CPU_MIPS16; + if (config1 & 1) + mips_cpu.options |= MIPS_CPU_FPU; + mips_cpu.scache.flags = MIPS_CACHE_NOT_PRESENT; + break; + case PRID_IMP_4KC: + case PRID_IMP_BCM3302: + mips_cpu.cputype = CPU_BCM3302; + mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_4KEX | + MIPS_CPU_4KTLB | MIPS_CPU_COUNTER; + config1 = read_c0_config1(); + if (config1 & (1 << 3)) + mips_cpu.options |= MIPS_CPU_WATCH; + if (config1 & (1 << 2)) + mips_cpu.options |= MIPS_CPU_MIPS16; + if (config1 & 1) + mips_cpu.options |= MIPS_CPU_FPU; + mips_cpu.scache.flags = MIPS_CACHE_NOT_PRESENT; + break; + default: + mips_cpu.cputype = CPU_UNKNOWN; + break; + } + break; #endif /* CONFIG_CPU_MIPS32 */ case PRID_COMP_SIBYTE: - switch (mips_cpu.processor_id & 0xff00) { + switch (mips_cpu.processor_id & PRID_IMP_MASK) { case PRID_IMP_SB1: mips_cpu.cputype = CPU_SB1; mips_cpu.isa_level = MIPS_CPU_ISA_M64; --- linux-2.4.20/arch/mips/kernel/entry.S~2.4.20_broadcom_3_37_2_1109_US.patch 2005-01-07 05:39:01.000000000 -0500 +++ linux-2.4.20/arch/mips/kernel/entry.S 2005-01-07 05:39:02.000000000 -0500 @@ -100,6 +100,10 @@ * and R4400 SC and MC versions. */ NESTED(except_vec3_generic, 0, sp) +#ifdef CONFIG_BCM4710 + nop + nop +#endif mfc0 k1, CP0_CAUSE la k0, exception_handlers andi k1, k1, 0x7c --- linux-2.4.20/arch/mips/kernel/head.S~2.4.20_broadcom_3_37_2_1109_US.patch 2005-01-07 05:39:01.000000000 -0500 +++ linux-2.4.20/arch/mips/kernel/head.S 2005-01-07 05:39:02.000000000 -0500 @@ -28,12 +28,20 @@ #include #include +#ifdef CONFIG_BCM4710 +#undef eret +#define eret nop; nop; eret +#endif + .text + j kernel_entry + nop + /* * Reserved space for exception handlers. * Necessary for machines which link their kernels at KSEG0. */ - .fill 0x400 + .fill 0x3f4 /* The following two symbols are used for kernel profiling. */ EXPORT(stext) --- linux-2.4.20/arch/mips/kernel/proc.c~2.4.20_broadcom_3_37_2_1109_US.patch 2005-01-07 05:39:01.000000000 -0500 +++ linux-2.4.20/arch/mips/kernel/proc.c 2005-01-07 05:39:02.000000000 -0500 @@ -73,9 +73,12 @@ [CPU_VR4122] "NEC VR4122", [CPU_VR4131] "NEC VR4131", [CPU_VR4181] "NEC VR4181", - [CPU_VR4181A] "NEC VR4181A" + [CPU_VR4181A] "NEC VR4181A", + [CPU_BCM4710] "BCM4710", + [CPU_BCM3302] "BCM3302", }; +extern unsigned long unaligned_instructions; static int show_cpuinfo(struct seq_file *m, void *v) { @@ -124,6 +127,21 @@ seq_printf(m, "sc emulations\t\t: %lu\n", sc_ops); #endif + seq_printf(m, "unaligned_instructions\t: %u\n", unaligned_instructions); + +#if defined(CONFIG_BCM4710) || defined(CONFIG_BCM4310) + seq_printf(m, "dcache hits\t\t: %u\n", + read_perf_cntr(0)); + seq_printf(m, "dcache misses\t\t: %u\n", + read_perf_cntr(1)); + seq_printf(m, "icache hits\t\t: %u\n", + read_perf_cntr(2)); + seq_printf(m, "icache misses\t\t: %u\n", + read_perf_cntr(3)); + seq_printf(m, "instructions\t\t: %u\n", + read_perf_cntr(4)); +#endif + return 0; } --- linux-2.4.20/arch/mips/kernel/setup.c~2.4.20_broadcom_3_37_2_1109_US.patch 2005-01-07 05:39:01.000000000 -0500 +++ linux-2.4.20/arch/mips/kernel/setup.c 2005-01-07 05:39:02.000000000 -0500 @@ -490,12 +490,12 @@ void victor_mpc30x_setup(void); void ibm_workpad_setup(void); void casio_e55_setup(void); - void tanbac_tb0226_setup(void); void jmr3927_setup(void); void it8172_setup(void); void swarm_setup(void); void hp_setup(void); void au1x00_setup(void); + void brcm_setup(void); #ifdef CONFIG_BLK_DEV_FD fd_ops = &no_fd_ops; @@ -671,6 +671,9 @@ hp_setup(); break; #endif + case MACH_GROUP_BRCM: + brcm_setup(); + break; default: panic("Unsupported architecture"); } --- linux-2.4.20/arch/mips/kernel/traps.c~2.4.20_broadcom_3_37_2_1109_US.patch 2005-01-07 05:39:01.000000000 -0500 +++ linux-2.4.20/arch/mips/kernel/traps.c 2005-01-07 05:39:02.000000000 -0500 @@ -405,17 +405,12 @@ unsigned long value) { const struct exception_table_entry *mid; - long diff; - while (first < last) { - mid = (last - first) / 2 + first; - diff = mid->insn - value; - if (diff < 0) - first = mid + 1; - else - last = mid; + for (mid = first; mid <= last; mid++) { + if (mid->insn == value) + return mid->nextinsn; } - return (first == last && first->insn == value) ? first->nextinsn : 0; + return 0; } extern spinlock_t modlist_lock; @@ -918,7 +913,7 @@ void __init trap_init(void) { - extern char except_vec1_generic; + extern char except_vec1_generic, except_vec2_generic; extern char except_vec3_generic, except_vec3_r4000; extern char except_vec_ejtag_debug; extern char except_vec4; @@ -928,6 +923,7 @@ /* Copy the generic exception handler code to it's final destination. */ memcpy((void *)(KSEG0 + 0x80), &except_vec1_generic, 0x80); + memcpy((void *)(KSEG0 + 0x100), &except_vec2_generic, 0x80); /* * Setup default vectors @@ -1014,6 +1010,12 @@ //set_except_vector(15, handle_ndc); } + if (mips_cpu.cputype == CPU_SB1) { + /* Enable timer interrupt and scd mapped interrupt */ + clear_c0_status(0xf000); + set_c0_status(0xc00); + } + if (mips_cpu.options & MIPS_CPU_FPU) { save_fp_context = _save_fp_context; restore_fp_context = _restore_fp_context; --- linux-2.4.20/arch/mips/kernel/unaligned.c~2.4.20_broadcom_3_37_2_1109_US.patch 2005-01-07 05:39:01.000000000 -0500 +++ linux-2.4.20/arch/mips/kernel/unaligned.c 2005-01-07 05:39:02.000000000 -0500 @@ -145,7 +145,7 @@ if (verify_area(VERIFY_READ, addr, 2)) goto sigbus; - __asm__ __volatile__ (".set\tnoat\n" + __asm__(".set\tnoat\n" #ifdef __BIG_ENDIAN "1:\tlb\t%0, 0(%2)\n" "2:\tlbu\t$1, 1(%2)\n\t" @@ -178,7 +178,7 @@ if (verify_area(VERIFY_READ, addr, 4)) goto sigbus; - __asm__ __volatile__ ( + __asm__( #ifdef __BIG_ENDIAN "1:\tlwl\t%0, (%2)\n" "2:\tlwr\t%0, 3(%2)\n\t" @@ -208,7 +208,7 @@ if (verify_area(VERIFY_READ, addr, 2)) goto sigbus; - __asm__ __volatile__ ( + __asm__( ".set\tnoat\n" #ifdef __BIG_ENDIAN "1:\tlbu\t%0, 0(%2)\n" @@ -250,7 +250,7 @@ if (verify_area(VERIFY_READ, addr, 4)) goto sigbus; - __asm__ __volatile__ ( + __asm__( #ifdef __BIG_ENDIAN "1:\tlwl\t%0, (%2)\n" "2:\tlwr\t%0, 3(%2)\n\t" @@ -294,7 +294,7 @@ if (verify_area(VERIFY_READ, addr, 8)) goto sigbus; - __asm__ __volatile__ ( + __asm__( #ifdef __BIG_ENDIAN "1:\tldl\t%0, (%2)\n" "2:\tldr\t%0, 7(%2)\n\t" @@ -329,7 +329,7 @@ goto sigbus; value = regs->regs[insn.i_format.rt]; - __asm__ __volatile__ ( + __asm__( #ifdef __BIG_ENDIAN ".set\tnoat\n" "1:\tsb\t%1, 1(%2)\n\t" @@ -365,7 +365,7 @@ goto sigbus; value = regs->regs[insn.i_format.rt]; - __asm__ __volatile__ ( + __asm__( #ifdef __BIG_ENDIAN "1:\tswl\t%1,(%2)\n" "2:\tswr\t%1, 3(%2)\n\t" @@ -403,7 +403,7 @@ goto sigbus; value = regs->regs[insn.i_format.rt]; - __asm__ __volatile__ ( + __asm__( #ifdef __BIG_ENDIAN "1:\tsdl\t%1,(%2)\n" "2:\tsdr\t%1, 7(%2)\n\t" --- linux-2.4.20/arch/mips/mm/Makefile~2.4.20_broadcom_3_37_2_1109_US.patch 2005-01-07 05:39:01.000000000 -0500 +++ linux-2.4.20/arch/mips/mm/Makefile 2005-01-07 05:39:02.000000000 -0500 @@ -28,6 +28,7 @@ obj-$(CONFIG_CPU_MIPS32) += pg-mips32.o c-mips32.o tlb-r4k.o tlbex-r4k.o obj-$(CONFIG_CPU_MIPS64) += pg-mips32.o c-mips32.o tlb-r4k.o tlbex-r4k.o obj-$(CONFIG_CPU_SB1) += pg-sb1.o c-sb1.o tlb-sb1.o tlbex-r4k.o cex-sb1.o cerr-sb1.o +obj-$(CONFIG_BCM4710) += c-bcm4710.o obj-$(CONFIG_R5000_CPU_SCACHE) += r5k-sc.o --- /dev/null 2004-04-06 13:56:48.000000000 -0400 +++ linux-2.4.20/arch/mips/mm/c-bcm4710.c 2005-01-07 05:39:02.000000000 -0500 @@ -0,0 +1,392 @@ +/* + * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com + * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * 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., + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * MIPS32 CPU variant specific MMU/Cache routines. + */ +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +/* CP0 hazard avoidance. */ +#define BARRIER __asm__ __volatile__(".set noreorder\n\t" \ + "nop; nop; nop; nop; nop; nop;\n\t" \ + ".set reorder\n\t") + +/* Primary cache parameters. */ +extern int icache_size, dcache_size; /* Size in bytes */ +extern int ic_lsize, dc_lsize; /* LineSize in bytes */ + +#include +#include + +#undef DEBUG_CACHE + +static inline void mips32_flush_cache_all_pc(void) +{ + unsigned long flags; + + local_irq_save(flags); + blast_dcache(); blast_icache(); + local_irq_restore(flags); +} + +static void mips32_flush_cache_range_pc(struct mm_struct *mm, + unsigned long start, + unsigned long end) +{ + if(mm->context != 0) { + unsigned long flags; + +#ifdef DEBUG_CACHE + printk("crange[%d,%08lx,%08lx]", (int)mm->context, start, end); +#endif + local_irq_save(flags); + blast_dcache(); blast_icache(); + local_irq_restore(flags); + } +} + +/* + * On architectures like the Sparc, we could get rid of lines in + * the cache created only by a certain context, but on the MIPS + * (and actually certain Sparc's) we cannot. + */ +static void mips32_flush_cache_mm_pc(struct mm_struct *mm) +{ + if(mm->context != 0) { +#ifdef DEBUG_CACHE + printk("cmm[%d]", (int)mm->context); +#endif + mips32_flush_cache_all_pc(); + } +} + +static void mips32_flush_cache_page_pc(struct vm_area_struct *vma, + unsigned long page) +{ + struct mm_struct *mm = vma->vm_mm; + pgd_t *pgdp; + pmd_t *pmdp; + pte_t *ptep; + + /* + * If ownes no valid ASID yet, cannot possibly have gotten + * this page into the cache. + */ + if (mm->context == 0) + return; + +#ifdef DEBUG_CACHE + printk("cpage[%d,%08lx]", (int)mm->context, page); +#endif + page &= PAGE_MASK; + pgdp = pgd_offset(mm, page); + pmdp = pmd_offset(pgdp, page); + ptep = pte_offset(pmdp, page); + + /* + * If the page isn't marked valid, the page cannot possibly be + * in the cache. + */ + if (!(pte_val(*ptep) & _PAGE_VALID)) + return; + + /* + * Doing flushes for another ASID than the current one is + * too difficult since Mips32 caches do a TLB translation + * for every cache flush operation. So we do indexed flushes + * in that case, which doesn't overly flush the cache too much. + */ + if (mm == current->active_mm) { + blast_dcache_page(page); + } else { + /* Do indexed flush, too much work to get the (possible) + * tlb refills to work correctly. + */ + page = (KSEG0 + (page & (dcache_size - 1))); + blast_dcache_page_indexed(page); + } +} + +/* If the addresses passed to these routines are valid, they are + * either: + * + * 1) In KSEG0, so we can do a direct flush of the page. + * 2) In KSEG2, and since every process can translate those + * addresses all the time in kernel mode we can do a direct + * flush. + * 3) In KSEG1, no flush necessary. + */ +static void mips32_flush_page_to_ram_pc(struct page *page) +{ + blast_dcache_page((unsigned long)page_address(page)); +} + +static void +mips32_flush_icache_range(unsigned long start, unsigned long end) +{ + flush_cache_all(); +} + +static void +mips32_flush_icache_page(struct vm_area_struct *vma, struct page *page) +{ + /* + * If there's no context yet, or the page isn't executable, no icache + * flush is needed. + */ + if (!(vma->vm_flags & VM_EXEC)) + return; + + /* + * We're not sure of the virtual address(es) involved here, so + * conservatively flush the entire caches. + */ + flush_cache_all(); +} + +/* + * Writeback and invalidate the primary cache dcache before DMA. + */ +static void +mips32_dma_cache_wback_inv_pc(unsigned long addr, unsigned long size) +{ + unsigned long end, a; + unsigned long flags; + + if (size >= dcache_size) { + blast_dcache(); + } else if (size) { + local_irq_save(flags); + a = addr & ~(dc_lsize - 1); + end = (addr + size - 1) & ~(dc_lsize - 1); + BCM4710_FILL_TLB(a); + BCM4710_FILL_TLB(end); + while (1) { + flush_dcache_line(a); /* Hit_Writeback_Inv_D */ + if (a == end) break; + a += dc_lsize; + } + local_irq_restore(flags); + } + bc_wback_inv(addr, size); +} + +static void +mips32_dma_cache_inv_pc(unsigned long addr, unsigned long size) +{ + unsigned long end, a; + unsigned long flags; + + if (size >= dcache_size) { + blast_dcache(); + } else if (size) { + local_irq_save(flags); + a = addr & ~(dc_lsize - 1); + end = (addr + size - 1) & ~(dc_lsize - 1); + BCM4710_FILL_TLB(a); + BCM4710_FILL_TLB(end); + while (1) { + invalidate_dcache_line(a); /* Hit_Inv_D */ + if (a == end) break; + a += dc_lsize; + } + local_irq_restore(flags); + } + + bc_inv(addr, size); +} + +static void +mips32_dma_cache_wback(unsigned long addr, unsigned long size) +{ + panic("mips32_dma_cache called - should not happen."); +} + +/* + * While we're protected against bad userland addresses we don't care + * very much about what happens in that case. Usually a segmentation + * fault will dump the process later on anyway ... + */ +static void mips32_flush_cache_sigtramp(unsigned long addr) +{ + BCM4710_PROTECTED_FILL_TLB(addr); + BCM4710_PROTECTED_FILL_TLB(addr + 4); + protected_writeback_dcache_line(addr & ~(dc_lsize - 1)); + protected_flush_icache_line(addr & ~(ic_lsize - 1)); +} + +static void mips32_flush_icache_all(void) +{ + if (mips_cpu.icache.flags | MIPS_CACHE_VTAG_CACHE) { + blast_icache(); + } +} + +/* Detect and size the various caches. */ +static void __init probe_icache(unsigned long config) +{ + unsigned long config1; + unsigned int lsize; + + mips_cpu.icache.flags = 0; + if (!(config & (1 << 31))) { + /* + * Not a MIPS32 complainant CPU. + * Config 1 register not supported, we assume R4k style. + */ + icache_size = 1 << (12 + ((config >> 9) & 7)); + ic_lsize = 16 << ((config >> 5) & 1); + mips_cpu.icache.linesz = ic_lsize; + + /* + * We cannot infer associativity - assume direct map + * unless probe template indicates otherwise + */ + if(!mips_cpu.icache.ways) mips_cpu.icache.ways = 1; + mips_cpu.icache.sets = + (icache_size / ic_lsize) / mips_cpu.icache.ways; + } else { + config1 = read_c0_config1(); + + if ((lsize = ((config1 >> 19) & 7))) + mips_cpu.icache.linesz = 2 << lsize; + else + mips_cpu.icache.linesz = lsize; + mips_cpu.icache.sets = 64 << ((config1 >> 22) & 7); + mips_cpu.icache.ways = 1 + ((config1 >> 16) & 7); + + ic_lsize = mips_cpu.icache.linesz; + icache_size = mips_cpu.icache.sets * mips_cpu.icache.ways * + ic_lsize; + + if ((config & 0x8) || (mips_cpu.cputype == CPU_20KC)) { + /* + * The CPU has a virtually tagged I-cache. + * Some older 20Kc chips doesn't have the 'VI' bit in + * the config register, so we also check for 20Kc. + */ + mips_cpu.icache.flags = MIPS_CACHE_VTAG_CACHE; + printk("Virtually tagged I-cache detected\n"); + } + } + printk("Primary instruction cache %dkb, linesize %d bytes (%d ways)\n", + icache_size >> 10, ic_lsize, mips_cpu.icache.ways); +} + +static void __init probe_dcache(unsigned long config) +{ + unsigned long config1; + unsigned int lsize; + + mips_cpu.dcache.flags = 0; + if (!(config & (1 << 31))) { + /* + * Not a MIPS32 complainant CPU. + * Config 1 register not supported, we assume R4k style. + */ + dcache_size = 1 << (12 + ((config >> 6) & 7)); + dc_lsize = 16 << ((config >> 4) & 1); + mips_cpu.dcache.linesz = dc_lsize; + /* + * We cannot infer associativity - assume direct map + * unless probe template indicates otherwise + */ + if(!mips_cpu.dcache.ways) mips_cpu.dcache.ways = 1; + mips_cpu.dcache.sets = + (dcache_size / dc_lsize) / mips_cpu.dcache.ways; + } else { + config1 = read_c0_config1(); + + if ((lsize = ((config1 >> 10) & 7))) + mips_cpu.dcache.linesz = 2 << lsize; + else + mips_cpu.dcache.linesz= lsize; + mips_cpu.dcache.sets = 64 << ((config1 >> 13) & 7); + mips_cpu.dcache.ways = 1 + ((config1 >> 7) & 7); + + dc_lsize = mips_cpu.dcache.linesz; + dcache_size = + mips_cpu.dcache.sets * mips_cpu.dcache.ways + * dc_lsize; + } + printk("Primary data cache %dkb, linesize %d bytes (%d ways)\n", + dcache_size >> 10, dc_lsize, mips_cpu.dcache.ways); +} + +static void __init setup_noscache_funcs(void) +{ + _clear_page = (void *)mips32_clear_page_dc; + _copy_page = (void *)mips32_copy_page_dc; + _flush_cache_all = mips32_flush_cache_all_pc; + ___flush_cache_all = mips32_flush_cache_all_pc; + _flush_cache_mm = mips32_flush_cache_mm_pc; + _flush_cache_range = mips32_flush_cache_range_pc; + _flush_cache_page = mips32_flush_cache_page_pc; + _flush_page_to_ram = mips32_flush_page_to_ram_pc; + + _flush_icache_page = mips32_flush_icache_page; + + _dma_cache_wback_inv = mips32_dma_cache_wback_inv_pc; + _dma_cache_wback = mips32_dma_cache_wback; + _dma_cache_inv = mips32_dma_cache_inv_pc; +} + +static void __init _change_cachability(u32 cm) +{ + change_c0_config(CONF_CM_CMASK, cm); + + if ((mips_cpu.processor_id & (PRID_COMP_MASK | PRID_IMP_MASK)) == + (PRID_COMP_BROADCOM | PRID_IMP_BCM3302)) { + cm = read_c0_diag(); + /* Enable icache */ + cm |= (1 << 31); + /* Enable dcache */ + cm |= (1 << 30); + write_c0_diag(cm); + } +} +static void (*change_cachability)(u32); + +void __init ld_mmu_bcm4710(void) +{ + unsigned long config = read_c0_config(); + + change_cachability = (void (*)(u32)) KSEG1ADDR((unsigned long)(_change_cachability)); + change_cachability(CONF_CM_DEFAULT); + + probe_icache(config); + probe_dcache(config); + setup_noscache_funcs(); + + _flush_cache_sigtramp = mips32_flush_cache_sigtramp; + _flush_icache_range = mips32_flush_icache_range; /* Ouch */ + _flush_icache_all = mips32_flush_icache_all; + + __flush_cache_all(); +} --- linux-2.4.20/arch/mips/mm/c-mips32.c~2.4.20_broadcom_3_37_2_1109_US.patch 2005-01-07 05:39:01.000000000 -0500 +++ linux-2.4.20/arch/mips/mm/c-mips32.c 2005-01-07 05:39:02.000000000 -0500 @@ -163,7 +163,6 @@ unsigned long page) { struct mm_struct *mm = vma->vm_mm; - unsigned long flags; pgd_t *pgdp; pmd_t *pmdp; pte_t *ptep; @@ -212,7 +211,6 @@ unsigned long page) { struct mm_struct *mm = vma->vm_mm; - unsigned long flags; pgd_t *pgdp; pmd_t *pmdp; pte_t *ptep; @@ -313,11 +311,11 @@ mips32_dma_cache_wback_inv_pc(unsigned long addr, unsigned long size) { unsigned long end, a; - unsigned int flags; + unsigned long flags; if (size >= dcache_size) { blast_dcache(); - } else { + } else if (size) { local_irq_save(flags); a = addr & ~(dc_lsize - 1); end = (addr + size - 1) & ~(dc_lsize - 1); @@ -338,9 +336,7 @@ if (size >= scache_size) { blast_scache(); - return; - } - + } else if (size) { a = addr & ~(sc_lsize - 1); end = (addr + size - 1) & ~(sc_lsize - 1); while (1) { @@ -348,17 +344,18 @@ if (a == end) break; a += sc_lsize; } + } } static void mips32_dma_cache_inv_pc(unsigned long addr, unsigned long size) { unsigned long end, a; - unsigned int flags; + unsigned long flags; if (size >= dcache_size) { blast_dcache(); - } else { + } else if (size) { local_irq_save(flags); a = addr & ~(dc_lsize - 1); end = (addr + size - 1) & ~(dc_lsize - 1); @@ -380,9 +377,7 @@ if (size >= scache_size) { blast_scache(); - return; - } - + } else if (size) { a = addr & ~(sc_lsize - 1); end = (addr + size - 1) & ~(sc_lsize - 1); while (1) { @@ -390,6 +385,7 @@ if (a == end) break; a += sc_lsize; } + } } static void @@ -664,16 +660,51 @@ setup_noscache_funcs(); } -void __init ld_mmu_mips32(void) +#if defined(CONFIG_BCM4310) || defined(CONFIG_BCM4704) || defined(CONFIG_BCM5365) +static void __init _change_cachability(u32 cm) { - unsigned long config = read_c0_config(); - extern char except_vec2_generic; + change_c0_config(CONF_CM_CMASK, cm); - /* Default cache error handler for MIPS32 */ - memcpy((void *)(KSEG0 + 0x100), &except_vec2_generic, 0x80); - memcpy((void *)(KSEG1 + 0x100), &except_vec2_generic, 0x80); + if (BCM330X(mips_cpu.processor_id)) { + cm = read_c0_diag(); + /* Enable icache */ + cm |= (1 << 31); + /* Enable dcache */ + cm |= (1 << 30); + write_c0_diag(cm); + } +} +static void (*change_cachability)(u32); +#endif - change_c0_config(CONF_CM_CMASK, CONF_CM_DEFAULT); +#ifdef CONFIG_BCM4704 +static void __init mips32_icache_fill(unsigned long addr, uint nbytes) +{ + int i; + for (i = 0; i < nbytes; i += ic_lsize) + fill_icache_line((addr + i)); + } + +/* + * This must be run from the cache on 4704A0 + * so there are no mips core BIU ops in progress + * when the PFC is enabled. + */ +#define PFC_CR0 0xff400000 /* control reg 0 */ +#define PFC_CR1 0xff400004 /* control reg 1 */ +static void __init enable_pfc(u32 mode) +{ + /* write range */ + *(volatile u32 *)PFC_CR1 = 0xffff0000; + + /* enable */ + *(volatile u32 *)PFC_CR0 = mode; +} +#endif + +void __init ld_mmu_mips32(void) +{ + unsigned long config = read_c0_config(); probe_icache(config); probe_dcache(config); @@ -684,4 +715,20 @@ _flush_icache_all = mips32_flush_icache_all; __flush_cache_all(); + +#if defined(CONFIG_BCM4310) || defined(CONFIG_BCM4704) || defined(CONFIG_BCM5365) + change_cachability = (void (*)(u32)) KSEG1ADDR((unsigned long)(_change_cachability)); + change_cachability(CONF_CM_DEFAULT); +#else + change_c0_config(CONF_CM_CMASK, CONF_CM_DEFAULT); +#endif + +#ifdef CONFIG_BCM4704 + /* enable prefetch cache */ + if (BCM330X(mips_cpu.processor_id) && + (read_c0_diag() & (1 << 29))) { + mips32_icache_fill((unsigned long) &enable_pfc, 64); + enable_pfc(0x15); + } +#endif } --- linux-2.4.20/arch/mips/mm/loadmmu.c~2.4.20_broadcom_3_37_2_1109_US.patch 2005-01-07 05:38:15.000000000 -0500 +++ linux-2.4.20/arch/mips/mm/loadmmu.c 2005-01-07 05:39:02.000000000 -0500 @@ -61,12 +61,21 @@ extern void ld_mmu_andes(void); extern void ld_mmu_sb1(void); extern void ld_mmu_mips32(void); +extern void ld_mmu_bcm4710(void); extern void r3k_tlb_init(void); extern void r4k_tlb_init(void); extern void sb1_tlb_init(void); void __init loadmmu(void) { +#ifdef CONFIG_BCM4710 + if (mips_cpu.cputype == CPU_BCM4710 && + (mips_cpu.processor_id & PRID_REV_MASK) == 0) { + printk("Loading BCM4710 MMU routines.\n"); + ld_mmu_bcm4710(); + r4k_tlb_init(); + } else +#endif if (mips_cpu.options & MIPS_CPU_4KTLB) { #if defined(CONFIG_CPU_R4X00) || defined(CONFIG_CPU_VR41XX) || \ defined(CONFIG_CPU_R4300) || defined(CONFIG_CPU_R5000) || \ --- linux-2.4.20/arch/mips/mm/tlbex-r4k.S~2.4.20_broadcom_3_37_2_1109_US.patch 2005-01-07 05:39:01.000000000 -0500 +++ linux-2.4.20/arch/mips/mm/tlbex-r4k.S 2005-01-07 05:39:02.000000000 -0500 @@ -162,6 +162,9 @@ .set noat LEAF(except_vec0_r4000) .set mips3 +#ifdef CONFIG_BCM4704 + nop +#endif GET_PGD(k0, k1) # get pgd pointer mfc0 k0, CP0_BADVADDR # Get faulting address srl k0, k0, _PGDIR_SHIFT # get pgd only bits @@ -248,15 +251,16 @@ eret # return from trap END(except_vec0_nevada) - /* TLB refill, EXL == 0, SB1 with M3 errata handling version */ - LEAF(except_vec0_sb1) #ifdef BCM1250_M3_WAR + + /* TLB refill, EXL == 0, SB1 with M3 errata handling version */ + LEAF(except_vec0_sb1_m3) mfc0 k0, CP0_BADVADDR mfc0 k1, CP0_ENTRYHI xor k0, k1 - srl k0, k0, PAGE_SHIFT+1 - bnez k0, 1f -#endif + srl k0, k0, 13 # PAGE_SHIFT + 1 + bnez k0, 2f + GET_PGD(k0, k1) # get pgd pointer mfc0 k0, CP0_BADVADDR # Get faulting address srl k0, k0, _PGDIR_SHIFT # get pgd only bits @@ -273,9 +277,12 @@ P_MTC0 k0, CP0_ENTRYLO0 # load it PTE_SRL k1, k1, 6 # convert to entrylo1 P_MTC0 k1, CP0_ENTRYLO1 # load it + b 1f tlbwr # write random tlb entry -1: eret # return from trap - END(except_vec0_sb1) +1: nop +2: eret # return from trap + END(except_vec0_sb1_m3) +#endif /* BCM1250_M3_WAR */ /* TLB refill, EXL == 0, R4[40]00/R5000 badvaddr hwbug version */ LEAF(except_vec0_r45k_bvahwbug) --- linux-2.4.20/arch/mips/ramdisk/Makefile~2.4.20_broadcom_3_37_2_1109_US.patch 2005-01-07 05:39:01.000000000 -0500 +++ linux-2.4.20/arch/mips/ramdisk/Makefile 2005-01-07 05:39:02.000000000 -0500 @@ -5,10 +5,10 @@ # removes any old dependencies. DON'T put your own dependencies here # unless it's something special (ie not a .c file). # - O_FORMAT = $(shell $(OBJDUMP) -i | head -2 | grep elf32) -img = $(CONFIG_EMBEDDED_RAMDISK_IMAGE) -ramdisk.o: ramdisk.gz ld.script +img = $(subst ",,$(CONFIG_EMBEDDED_RAMDISK_IMAGE)) + +ramdisk.o: $(img) ld.script echo "O_FORMAT: " $(O_FORMAT) $(LD) -T ld.script -b binary --oformat $(O_FORMAT) -o $@ $(img) --- linux-2.4.20/drivers/block/Config.in~2.4.20_broadcom_3_37_2_1109_US.patch 2005-01-07 05:38:15.000000000 -0500 +++ linux-2.4.20/drivers/block/Config.in 2005-01-07 05:39:02.000000000 -0500 @@ -4,6 +4,10 @@ mainmenu_option next_comment comment 'Block devices' +tristate 'M-Systems DiskOnChip Block Device support' CONFIG_BLK_DEV_MSYS + +tristate 'No-root support' CONFIG_NOROOT + tristate 'Normal floppy disk support' CONFIG_BLK_DEV_FD if [ "$CONFIG_AMIGA" = "y" ]; then tristate 'Amiga floppy support' CONFIG_AMIGA_FLOPPY --- linux-2.4.20/drivers/block/Makefile~2.4.20_broadcom_3_37_2_1109_US.patch 2005-01-07 05:38:15.000000000 -0500 +++ linux-2.4.20/drivers/block/Makefile 2005-01-07 05:39:02.000000000 -0500 @@ -34,4 +34,9 @@ subdir-$(CONFIG_PARIDE) += paride +ifdef CONFIG_BLK_DEV_MSYS +obj-$(CONFIG_BLK_DEV_MSYS) += ../../../../router/trueffs/linux/doc.o +subdir-$(CONFIG_BLK_DEV_MSYS) += ../../../../router/trueffs/linux +endif + include $(TOPDIR)/Rules.make --- /dev/null 2004-04-06 13:56:48.000000000 -0400 +++ linux-2.4.20/drivers/block/dummy.c 2005-01-07 05:39:02.000000000 -0500 @@ -0,0 +1,70 @@ +/* + * dummyfs: a placeholder filesystem that sleeps forever when mounted + * + * Copyright 2004, Broadcom Corporation + * All Rights Reserved. + * + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. + * + * $Id: dummy.c,v 1.1.1.6 2004/04/12 04:31:22 honor Exp $ + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* I don't thik anyone would mind if we stole CM206_CDROM_MAJOR */ +#define DUMMY_MAJOR 0x20 + +static int dummy_open(struct inode *inode, struct file *file) +{ + DECLARE_WAIT_QUEUE_HEAD(wait); + + for (;;) + sleep_on(&wait); + + return 0; +} + +static struct block_device_operations dummy_fops = { + open: dummy_open, +}; + +int __init dummy_init(void) +{ + if (devfs_register_blkdev(DUMMY_MAJOR, "dummy", &dummy_fops)) { + printk(KERN_WARNING "Unable to get major number for dummy device\n"); + return -EIO; + } + + register_disk(NULL, MKDEV(DUMMY_MAJOR, 0), 1, &dummy_fops, 0); + + return 0; +} + +void dummy_exit(void) +{ + if (devfs_unregister_blkdev(0, "dummy")) + printk(KERN_WARNING "dummy: cannot unregister blkdev\n"); +} + +module_init(dummy_init); +module_exit(dummy_exit); --- linux-2.4.20/drivers/char/mem.c~2.4.20_broadcom_3_37_2_1109_US.patch 2005-01-07 05:38:15.000000000 -0500 +++ linux-2.4.20/drivers/char/mem.c 2005-01-07 05:39:02.000000000 -0500 @@ -621,7 +621,8 @@ {1, "mem", S_IRUSR | S_IWUSR | S_IRGRP, &mem_fops}, {2, "kmem", S_IRUSR | S_IWUSR | S_IRGRP, &kmem_fops}, {3, "null", S_IRUGO | S_IWUGO, &null_fops}, -#if defined(CONFIG_ISA) || !defined(__mc68000__) +#if defined(CONFIG_ISA) || !defined(__mc68000__) || \ + defined(CONFIG_BCM94702_CPCI) {4, "port", S_IRUSR | S_IWUSR | S_IRGRP, &port_fops}, #endif {5, "zero", S_IRUGO | S_IWUGO, &zero_fops}, --- linux-2.4.20/drivers/char/serial.c~2.4.20_broadcom_3_37_2_1109_US.patch 2005-01-07 05:39:01.000000000 -0500 +++ linux-2.4.20/drivers/char/serial.c 2005-01-07 05:39:02.000000000 -0500 @@ -444,6 +444,10 @@ return inb(info->port+1); #endif case SERIAL_IO_MEM: +#ifdef CONFIG_BCM4310 + readb((unsigned long) info->iomem_base + + (UART_SCR<iomem_reg_shift)); +#endif return readb((unsigned long) info->iomem_base + (offset<iomem_reg_shift)); default: @@ -464,6 +468,9 @@ case SERIAL_IO_MEM: writeb(value, (unsigned long) info->iomem_base + (offset<iomem_reg_shift)); +#ifdef CONFIG_BCM4704 + *((volatile unsigned int *) KSEG1ADDR(0x18000000)); +#endif break; default: outb(value, info->port+offset); @@ -5970,6 +5977,13 @@ * Divisor, bytesize and parity */ state = rs_table + co->index; + /* + * Safe guard: state structure must have been initialized + */ + if (state->iomem_base == NULL) { + printk("!unable to setup serial console!\n"); + return -1; + } if (doflow) state->flags |= ASYNC_CONS_FLOW; info = &async_sercons; --- linux-2.4.20/drivers/ide/ide-pci.c~2.4.20_broadcom_3_37_2_1109_US.patch 2005-01-07 05:38:15.000000000 -0500 +++ linux-2.4.20/drivers/ide/ide-pci.c 2005-01-07 05:39:02.000000000 -0500 @@ -793,11 +793,6 @@ goto bypass_piix_dma; if (IDE_PCI_DEVID_EQ(d->devid, DEVID_PDCADMA)) goto bypass_legacy_dma; - if (hwif->udma_four) { - printk("%s: ATA-66/100 forced bit set (WARNING)!!\n", d->name); - } else { - hwif->udma_four = (d->ata66_check) ? d->ata66_check(hwif) : 0; - } #ifdef CONFIG_BLK_DEV_IDEDMA if (IDE_PCI_DEVID_EQ(d->devid, DEVID_SIS5513) || IDE_PCI_DEVID_EQ(d->devid, DEVID_AEC6260) || @@ -855,6 +850,11 @@ printk("%s: %s Bus-Master DMA disabled (BIOS)\n", hwif->name, d->name); } } + if (hwif->udma_four) { + printk("%s: ATA-66/100 forced bit set (WARNING)!!\n", d->name); + } else { + hwif->udma_four = (d->ata66_check) ? d->ata66_check(hwif) : 0; + } #endif /* CONFIG_BLK_DEV_IDEDMA */ bypass_legacy_dma: bypass_piix_dma: --- linux-2.4.20/drivers/mtd/chips/Config.in~2.4.20_broadcom_3_37_2_1109_US.patch 2005-01-07 05:38:15.000000000 -0500 +++ linux-2.4.20/drivers/mtd/chips/Config.in 2005-01-07 05:39:02.000000000 -0500 @@ -43,6 +43,7 @@ fi dep_tristate ' Support for Intel/Sharp flash chips' CONFIG_MTD_CFI_INTELEXT $CONFIG_MTD_GEN_PROBE dep_tristate ' Support for AMD/Fujitsu flash chips' CONFIG_MTD_CFI_AMDSTD $CONFIG_MTD_GEN_PROBE +dep_tristate ' Support for SST flash chips' CONFIG_MTD_CFI_SSTSTD $CONFIG_MTD_GEN_PROBE dep_tristate ' Support for RAM chips in bus mapping' CONFIG_MTD_RAM $CONFIG_MTD dep_tristate ' Support for ROM chips in bus mapping' CONFIG_MTD_ROM $CONFIG_MTD --- linux-2.4.20/drivers/mtd/chips/Makefile~2.4.20_broadcom_3_37_2_1109_US.patch 2005-01-07 05:38:15.000000000 -0500 +++ linux-2.4.20/drivers/mtd/chips/Makefile 2005-01-07 05:39:02.000000000 -0500 @@ -17,6 +17,7 @@ obj-$(CONFIG_MTD) += chipreg.o obj-$(CONFIG_MTD_AMDSTD) += amd_flash.o obj-$(CONFIG_MTD_CFI) += cfi_probe.o +obj-$(CONFIG_MTD_CFI_SSTSTD) += cfi_cmdset_0701.o obj-$(CONFIG_MTD_CFI_AMDSTD) += cfi_cmdset_0002.o obj-$(CONFIG_MTD_CFI_INTELEXT) += cfi_cmdset_0001.o obj-$(CONFIG_MTD_GEN_PROBE) += gen_probe.o --- linux-2.4.20/drivers/mtd/chips/cfi_cmdset_0001.c~2.4.20_broadcom_3_37_2_1109_US.patch 2005-01-07 05:38:15.000000000 -0500 +++ linux-2.4.20/drivers/mtd/chips/cfi_cmdset_0001.c 2005-01-07 05:39:02.000000000 -0500 @@ -59,6 +59,8 @@ #ifdef DEBUG_CFI_FEATURES static void cfi_tell_features(struct cfi_pri_intelext *extp) { + int i; + printk(" Feature/Command Support: %4.4X\n", extp->FeatureSupport); printk(" - Chip Erase: %s\n", extp->FeatureSupport&1?"supported":"unsupported"); printk(" - Suspend Erase: %s\n", extp->FeatureSupport&2?"supported":"unsupported"); @@ -184,7 +186,7 @@ unsigned long devsize = (1<cfiq->DevSize) * cfi->interleave; mtd = kmalloc(sizeof(*mtd), GFP_KERNEL); - //printk(KERN_DEBUG "number of CFI chips: %d\n", cfi->numchips); + printk(KERN_DEBUG "number of CFI chips: %d\n", cfi->numchips); if (!mtd) { printk(KERN_ERR "Failed to allocate memory for MTD device\n"); @@ -1226,6 +1228,9 @@ chip->state = chip->oldstate; wake_up(&chip->wq); } + + /* make absolutely sure that chip is out of lock/suspend state */ + cfi_write(map, CMD(0xFF), 0); spin_unlock_bh(chip->mutex); } } @@ -1319,6 +1324,7 @@ } /* Done and happy. */ + cfi_write(map, CMD(0x70), adr); chip->state = FL_STATUS; DISABLE_VPP(map); wake_up(&chip->wq); @@ -1468,6 +1474,7 @@ } /* Done and happy. */ + cfi_write(map, CMD(0x70), adr); chip->state = FL_STATUS; DISABLE_VPP(map); wake_up(&chip->wq); @@ -1483,34 +1490,96 @@ #ifdef DEBUG_LOCK_BITS int ofs_factor = cfi->interleave * cfi->device_type; #endif + int i, first; + struct mtd_erase_region_info *regions = mtd->eraseregions; + + if (ofs > mtd->size) + return -EINVAL; + + if ((len + ofs) > mtd->size) + return -EINVAL; + + /* Check that both start and end of the requested erase are + * aligned with the erasesize at the appropriate addresses. + */ + + i = 0; + + /* Skip all erase regions which are ended before the start of + the requested erase. Actually, to save on the calculations, + we skip to the first erase region which starts after the + start of the requested erase, and then go back one. + */ + + while (i < mtd->numeraseregions && ofs >= regions[i].offset) + i++; + i--; + + /* OK, now i is pointing at the erase region in which this + erase request starts. Check the start of the requested + erase range is aligned with the erase size which is in + effect here. + */ + + if (ofs & (regions[i].erasesize-1)) + return -EINVAL; + + /* Remember the erase region we start on */ + first = i; + + /* Next, check that the end of the requested erase is aligned + * with the erase region at that address. + */ + + while (inumeraseregions && (ofs + len) >= regions[i].offset) + i++; + + /* As before, drop back one to point at the region in which + the address actually falls + */ + i--; + + if ((ofs + len) & (regions[i].erasesize-1)) + return -EINVAL; chipnum = ofs >> cfi->chipshift; adr = ofs - (chipnum << cfi->chipshift); + i = first; -#ifdef DEBUG_LOCK_BITS - { - unsigned long temp_adr = adr; - unsigned long temp_len = len; + while(len) { +#ifdef DEBUG_LOCK_BITS cfi_send_gen_cmd(0x90, 0x55, 0, map, cfi, cfi->device_type, NULL); - while (temp_len) { - printk("before unlock %x: block status register is %x\n",temp_adr,cfi_read_query(map, temp_adr+(2*ofs_factor))); - temp_adr += mtd->erasesize; - temp_len -= mtd->erasesize; - } + printk("before unlock %x: block status register is %x\n",adr,cfi_read_query(map, adr+(2*ofs_factor))); cfi_send_gen_cmd(0xff, 0x55, 0, map, cfi, cfi->device_type, NULL); - } #endif ret = do_unlock_oneblock(map, &cfi->chips[chipnum], adr); #ifdef DEBUG_LOCK_BITS cfi_send_gen_cmd(0x90, 0x55, 0, map, cfi, cfi->device_type, NULL); - printk("after unlock: block status register is %x\n",cfi_read_query(map, adr+(2*ofs_factor))); + printk("after unlock %x: block status register is %x\n",adr,cfi_read_query(map, adr+(2*ofs_factor))); cfi_send_gen_cmd(0xff, 0x55, 0, map, cfi, cfi->device_type, NULL); #endif + if (ret) return ret; + + adr += regions[i].erasesize; + len -= regions[i].erasesize; + + if (adr % (1<< cfi->chipshift) == ((regions[i].offset + (regions[i].erasesize * regions[i].numblocks)) %( 1<< cfi->chipshift))) + i++; + + if (adr >> cfi->chipshift) { + adr = 0; + chipnum++; + + if (chipnum >= cfi->numchips) + break; + } + } + return 0; } static int cfi_intelext_suspend(struct mtd_info *mtd) --- /dev/null 2004-04-06 13:56:48.000000000 -0400 +++ linux-2.4.20/drivers/mtd/chips/cfi_cmdset_0701.c 2005-01-07 05:39:02.000000000 -0500 @@ -0,0 +1,855 @@ +/* + * Common Flash Interface support: + * SST Standard Vendor Command Set (ID 0x0701) + * + * Copyright (C) 2000 Crossnet Co. + * + * 2_by_8 routines added by Simon Munton + * + * This code is GPL + * + * $Id: cfi_cmdset_0701.c,v 1.1.1.4 2003/10/14 08:08:17 sparq Exp $ + * + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +static int cfi_sststd_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *); +static int cfi_sststd_write(struct mtd_info *, loff_t, size_t, size_t *, const u_char *); +static int cfi_sststd_erase_onesize(struct mtd_info *, struct erase_info *); +static int cfi_sststd_erase_varsize(struct mtd_info *, struct erase_info *); +static void cfi_sststd_sync (struct mtd_info *); +static int cfi_sststd_suspend (struct mtd_info *); +static void cfi_sststd_resume (struct mtd_info *); + +static void cfi_sststd_destroy(struct mtd_info *); + +struct mtd_info *cfi_cmdset_0701(struct map_info *, int); +static struct mtd_info *cfi_sststd_setup (struct map_info *); + + +static struct mtd_chip_driver cfi_sststd_chipdrv = { + probe: NULL, /* Not usable directly */ + destroy: cfi_sststd_destroy, + name: "cfi_cmdset_0701", + module: THIS_MODULE +}; + +struct mtd_info *cfi_cmdset_0701(struct map_info *map, int primary) +{ + struct cfi_private *cfi = map->fldrv_priv; + int ofs_factor = cfi->interleave * cfi->device_type; + int i; + __u8 major, minor; + __u32 base = cfi->chips[0].start; + + if (cfi->cfi_mode==1){ + __u16 adr = primary?cfi->cfiq->P_ADR:cfi->cfiq->A_ADR; + + cfi_send_gen_cmd(0xAA, 0x5555, base, map, cfi, cfi->device_type, NULL); + cfi_send_gen_cmd(0x55, 0x2AAA, base, map, cfi, cfi->device_type, NULL); + cfi_send_gen_cmd(0x98, 0x5555, base, map, cfi, cfi->device_type, NULL); + + major = cfi_read_query(map, base + (adr+3)*ofs_factor); + minor = cfi_read_query(map, base + (adr+4)*ofs_factor); + + printk(" SST Query Table v%c.%c at 0x%4.4X\n", + major, minor, adr); + cfi_send_gen_cmd(0xf0, 0x5555, base, map, cfi, cfi->device_type, NULL); + + cfi_send_gen_cmd(0xAA, 0x5555, base, map, cfi, cfi->device_type, NULL); + cfi_send_gen_cmd(0x55, 0x2AAA, base, map, cfi, cfi->device_type, NULL); + cfi_send_gen_cmd(0x90, 0x5555, base, map, cfi, cfi->device_type, NULL); + cfi->mfr = cfi_read_query(map, base); + cfi->id = cfi_read_query(map, base + ofs_factor); + + cfi_send_gen_cmd(0xAA, 0x5555, base, map, cfi, cfi->device_type, NULL); + cfi_send_gen_cmd(0x55, 0x2AAA, base, map, cfi, cfi->device_type, NULL); + cfi_send_gen_cmd(0x98, 0x5555, base, map, cfi, cfi->device_type, NULL); + + switch (cfi->device_type) { + case CFI_DEVICETYPE_X16: + cfi->addr_unlock1 = 0x5555; + cfi->addr_unlock2 = 0x2AAA; + break; + default: + printk(KERN_NOTICE "Eep. Unknown cfi_cmdset_0701 device type %d\n", cfi->device_type); + return NULL; + } + } /* CFI mode */ + + for (i=0; i< cfi->numchips; i++) { + cfi->chips[i].word_write_time = 1<cfiq->WordWriteTimeoutTyp; + cfi->chips[i].buffer_write_time = 1<cfiq->BufWriteTimeoutTyp; + cfi->chips[i].erase_time = 1<cfiq->BlockEraseTimeoutTyp; + } + + map->fldrv = &cfi_sststd_chipdrv; + MOD_INC_USE_COUNT; + + cfi_send_gen_cmd(0xf0, 0x5555, base, map, cfi, cfi->device_type, NULL); + return cfi_sststd_setup(map); +} + +static struct mtd_info *cfi_sststd_setup(struct map_info *map) +{ + struct cfi_private *cfi = map->fldrv_priv; + struct mtd_info *mtd; + unsigned long devsize = (1<cfiq->DevSize) * cfi->interleave; + + mtd = kmalloc(sizeof(*mtd), GFP_KERNEL); + printk("number of %s chips: %d\n", (cfi->cfi_mode)?"JEDEC":"CFI",cfi->numchips); + + if (!mtd) { + printk("Failed to allocate memory for MTD device\n"); + kfree(cfi->cmdset_priv); + return NULL; + } + + memset(mtd, 0, sizeof(*mtd)); + mtd->priv = map; + mtd->type = MTD_NORFLASH; + /* Also select the correct geometry setup too */ + mtd->size = devsize * cfi->numchips; + + if (cfi->cfiq->NumEraseRegions == 1) { + /* No need to muck about with multiple erase sizes */ + mtd->erasesize = ((cfi->cfiq->EraseRegionInfo[0] >> 8) & ~0xff) * cfi->interleave; + } else { + unsigned long offset = 0; + int i,j; + + mtd->numeraseregions = cfi->cfiq->NumEraseRegions * cfi->numchips; + mtd->eraseregions = kmalloc(sizeof(struct mtd_erase_region_info) * mtd->numeraseregions, GFP_KERNEL); + if (!mtd->eraseregions) { + printk("Failed to allocate memory for MTD erase region info\n"); + kfree(cfi->cmdset_priv); + return NULL; + } + + for (i=0; icfiq->NumEraseRegions; i++) { + unsigned long ernum, ersize; + ersize = ((cfi->cfiq->EraseRegionInfo[i] >> 8) & ~0xff) * cfi->interleave; + ernum = (cfi->cfiq->EraseRegionInfo[i] & 0xffff) + 1; + + if (mtd->erasesize < ersize) { + mtd->erasesize = ersize; + } + for (j=0; jnumchips; j++) { + mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].offset = (j*devsize)+offset; + mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].erasesize = ersize; + mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].numblocks = ernum; + } + offset += (ersize * ernum); + } + + // debug + for (i=0; inumeraseregions;i++){ + printk("%d: offset=0x%x,size=0x%x,blocks=%d\n", + i,mtd->eraseregions[i].offset, + mtd->eraseregions[i].erasesize, + mtd->eraseregions[i].numblocks); + } + } + + switch (CFIDEV_BUSWIDTH) + { + case 1: + case 2: + case 4: + if (mtd->numeraseregions > 1) + mtd->erase = cfi_sststd_erase_varsize; + else + mtd->erase = cfi_sststd_erase_onesize; + mtd->read = cfi_sststd_read; + mtd->write = cfi_sststd_write; + break; + + default: + printk("Unsupported buswidth\n"); + kfree(mtd); + kfree(cfi->cmdset_priv); + return NULL; + break; + } + mtd->sync = cfi_sststd_sync; + mtd->suspend = cfi_sststd_suspend; + mtd->resume = cfi_sststd_resume; + mtd->flags = MTD_CAP_NORFLASH; + map->fldrv = &cfi_sststd_chipdrv; + mtd->name = map->name; + MOD_INC_USE_COUNT; + return mtd; +} + +static inline int do_read_onechip(struct map_info *map, struct flchip *chip, loff_t adr, size_t len, u_char *buf) +{ + DECLARE_WAITQUEUE(wait, current); + unsigned long timeo = jiffies + HZ; + + retry: + cfi_spin_lock(chip->mutex); + + if (chip->state != FL_READY){ + printk("Waiting for chip to read, status = %d\n", chip->state); + set_current_state(TASK_UNINTERRUPTIBLE); + add_wait_queue(&chip->wq, &wait); + + cfi_spin_unlock(chip->mutex); + + schedule(); + remove_wait_queue(&chip->wq, &wait); + timeo = jiffies + HZ; + + goto retry; + } + + adr += chip->start; + + chip->state = FL_READY; + + map->copy_from(map, buf, adr, len); + + wake_up(&chip->wq); + cfi_spin_unlock(chip->mutex); + + return 0; +} + +static int cfi_sststd_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) +{ + struct map_info *map = mtd->priv; + struct cfi_private *cfi = map->fldrv_priv; + unsigned long ofs; + int chipnum; + int ret = 0; + + /* ofs: offset within the first chip that the first read should start */ + + chipnum = (from >> cfi->chipshift); + ofs = from - (chipnum << cfi->chipshift); + + + *retlen = 0; + + while (len) { + unsigned long thislen; + + if (chipnum >= cfi->numchips) + break; + + if ((len + ofs -1) >> cfi->chipshift) + thislen = (1<chipshift) - ofs; + else + thislen = len; + + ret = do_read_onechip(map, &cfi->chips[chipnum], ofs, thislen, buf); + if (ret) + break; + + *retlen += thislen; + len -= thislen; + buf += thislen; + + ofs = 0; + chipnum++; + } + return ret; +} + +static int do_write_oneword(struct map_info *map, struct flchip *chip, unsigned long adr, __u32 datum, int fast) +{ + unsigned long timeo = jiffies + HZ; + unsigned int Last[4]; + unsigned long Count = 0; + struct cfi_private *cfi = map->fldrv_priv; + DECLARE_WAITQUEUE(wait, current); + int ret = 0; + + retry: + cfi_spin_lock(chip->mutex); + + if (chip->state != FL_READY){ + printk("Waiting for chip to write, status = %d\n", chip->state); + set_current_state(TASK_UNINTERRUPTIBLE); + add_wait_queue(&chip->wq, &wait); + + cfi_spin_unlock(chip->mutex); + + schedule(); + remove_wait_queue(&chip->wq, &wait); + printk("Wake up to write:\n"); + timeo = jiffies + HZ; + + goto retry; + } + + chip->state = FL_WRITING; + + adr += chip->start; + ENABLE_VPP(map); + cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X16, NULL); + cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, CFI_DEVICETYPE_X16, NULL); + cfi_send_gen_cmd(0xA0, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X16, NULL); + + cfi_write(map, datum, adr); + + cfi_spin_unlock(chip->mutex); + cfi_udelay(chip->word_write_time); + cfi_spin_lock(chip->mutex); + + Last[0] = cfi_read(map, adr); + // printk("Last[0] is %x\n", Last[0]); + Last[1] = cfi_read(map, adr); + // printk("Last[1] is %x\n", Last[1]); + Last[2] = cfi_read(map, adr); + // printk("Last[2] is %x\n", Last[2]); + + for (Count = 3; Last[(Count - 1) % 4] != Last[(Count - 2) % 4] && Count < 10000; Count++){ + cfi_spin_unlock(chip->mutex); + cfi_udelay(10); + cfi_spin_lock(chip->mutex); + + Last[Count % 4] = cfi_read(map, adr); + // printk("Last[%d%%4] is %x\n", Count, Last[Count%4]); + } + + if (Last[(Count - 1) % 4] != datum){ + printk("Last[%ld] is %x, datum is %x\n",(Count - 1) % 4,Last[(Count - 1) % 4],datum); + cfi_send_gen_cmd(0xF0, 0, chip->start, map, cfi, cfi->device_type, NULL); + DISABLE_VPP(map); + ret = -EIO; + } + DISABLE_VPP(map); + chip->state = FL_READY; + wake_up(&chip->wq); + cfi_spin_unlock(chip->mutex); + + return ret; +} + +static int cfi_sststd_write (struct mtd_info *mtd, loff_t to , size_t len, size_t *retlen, const u_char *buf) +{ + struct map_info *map = mtd->priv; + struct cfi_private *cfi = map->fldrv_priv; + int ret = 0; + int chipnum; + unsigned long ofs, chipstart; + + *retlen = 0; + if (!len) + return 0; + + chipnum = to >> cfi->chipshift; + ofs = to - (chipnum << cfi->chipshift); + chipstart = cfi->chips[chipnum].start; + + /* If it's not bus-aligned, do the first byte write */ + if (ofs & (CFIDEV_BUSWIDTH-1)) { + unsigned long bus_ofs = ofs & ~(CFIDEV_BUSWIDTH-1); + int i = ofs - bus_ofs; + int n = 0; + u_char tmp_buf[4]; + __u32 datum; + + map->copy_from(map, tmp_buf, bus_ofs + cfi->chips[chipnum].start, CFIDEV_BUSWIDTH); + while (len && i < CFIDEV_BUSWIDTH) + tmp_buf[i++] = buf[n++], len--; + + if (cfi_buswidth_is_2()) { + datum = *(__u16*)tmp_buf; + } else if (cfi_buswidth_is_4()) { + datum = *(__u32*)tmp_buf; + } else { + return -EINVAL; /* should never happen, but be safe */ + } + + ret = do_write_oneword(map, &cfi->chips[chipnum], + bus_ofs, datum, 0); + if (ret) + return ret; + + ofs += n; + buf += n; + (*retlen) += n; + + if (ofs >> cfi->chipshift) { + chipnum ++; + ofs = 0; + if (chipnum == cfi->numchips) + return 0; + } + } + + /* We are now aligned, write as much as possible */ + while(len >= CFIDEV_BUSWIDTH) { + __u32 datum; + + if (cfi_buswidth_is_1()) { + datum = *(__u8*)buf; + } else if (cfi_buswidth_is_2()) { + datum = *(__u16*)buf; + } else if (cfi_buswidth_is_4()) { + datum = *(__u32*)buf; + } else { + return -EINVAL; + } + ret = do_write_oneword(map, &cfi->chips[chipnum], + ofs, datum, cfi->fast_prog); + if (ret) { + return ret; + } + + ofs += CFIDEV_BUSWIDTH; + buf += CFIDEV_BUSWIDTH; + (*retlen) += CFIDEV_BUSWIDTH; + len -= CFIDEV_BUSWIDTH; + + if (ofs >> cfi->chipshift) { + chipnum ++; + ofs = 0; + if (chipnum == cfi->numchips) + return 0; + chipstart = cfi->chips[chipnum].start; + } + } + + if (len & (CFIDEV_BUSWIDTH-1)) { + int i = 0, n = 0; + u_char tmp_buf[4]; + __u32 datum; + + map->copy_from(map, tmp_buf, ofs + cfi->chips[chipnum].start, CFIDEV_BUSWIDTH); + while (len--) + tmp_buf[i++] = buf[n++]; + + if (cfi_buswidth_is_2()) { + datum = *(__u16*)tmp_buf; + } else if (cfi_buswidth_is_4()) { + datum = *(__u32*)tmp_buf; + } else { + return -EINVAL; /* should never happen, but be safe */ + } + + ret = do_write_oneword(map, &cfi->chips[chipnum], + ofs, datum, 0); + if (ret) + return ret; + + (*retlen) += n; + } + + return 0; +} + +static inline int do_erase_oneblock(struct map_info *map, struct flchip *chip, unsigned long adr) +{ + unsigned int status; + unsigned long timeo = jiffies + HZ; + struct cfi_private *cfi = map->fldrv_priv; + unsigned int rdy_mask; + DECLARE_WAITQUEUE(wait, current); + + retry: + cfi_spin_lock(chip->mutex); + + if (chip->state != FL_READY){ + set_current_state(TASK_UNINTERRUPTIBLE); + add_wait_queue(&chip->wq, &wait); + + cfi_spin_unlock(chip->mutex); + + schedule(); + remove_wait_queue(&chip->wq, &wait); + timeo = jiffies + HZ; + + goto retry; + } + + chip->state = FL_ERASING; + + adr += chip->start; + ENABLE_VPP(map); + cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X16, NULL); + cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, CFI_DEVICETYPE_X16, NULL); + cfi_send_gen_cmd(0x80, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X16, NULL); + cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X16, NULL); + cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, CFI_DEVICETYPE_X16, NULL); + cfi_write(map, CMD(0x30), adr); + + timeo = jiffies + (HZ*20); + + cfi_spin_unlock(chip->mutex); + schedule_timeout(HZ); + cfi_spin_lock(chip->mutex); + + rdy_mask = CMD(0x80); + + /* Once the state machine's known to be working I'll do that */ + + while ( ( (status = cfi_read(map,adr)) & rdy_mask ) != rdy_mask ) { + static int z=0; + + if (chip->state != FL_ERASING) { + /* Someone's suspended the erase. Sleep */ + set_current_state(TASK_UNINTERRUPTIBLE); + add_wait_queue(&chip->wq, &wait); + + cfi_spin_unlock(chip->mutex); + printk("erase suspended. Sleeping\n"); + + schedule(); + remove_wait_queue(&chip->wq, &wait); + timeo = jiffies + (HZ*2); + cfi_spin_lock(chip->mutex); + continue; + } + + /* OK Still waiting */ + if (time_after(jiffies, timeo)) { + chip->state = FL_READY; + cfi_spin_unlock(chip->mutex); + printk("waiting for erase to complete timed out."); + DISABLE_VPP(map); + return -EIO; + } + + /* Latency issues. Drop the lock, wait a while and retry */ + cfi_spin_unlock(chip->mutex); + + z++; + if ( 0 && !(z % 100 )) + printk("chip not ready yet after erase. looping\n"); + + cfi_udelay(1); + + cfi_spin_lock(chip->mutex); + continue; + } + + /* Done and happy. */ + DISABLE_VPP(map); + chip->state = FL_READY; + wake_up(&chip->wq); + cfi_spin_unlock(chip->mutex); + return 0; +} + +static int cfi_sststd_erase_varsize(struct mtd_info *mtd, struct erase_info *instr) +{ + struct map_info *map = mtd->priv; + struct cfi_private *cfi = map->fldrv_priv; + unsigned long adr, len; + int chipnum, ret = 0; + int i, first; + struct mtd_erase_region_info *regions = mtd->eraseregions; + + if (instr->addr > mtd->size) + return -EINVAL; + + if ((instr->len + instr->addr) > mtd->size) + return -EINVAL; + + /* Check that both start and end of the requested erase are + * aligned with the erasesize at the appropriate addresses. + */ + + i = 0; + + /* Skip all erase regions which are ended before the start of + the requested erase. Actually, to save on the calculations, + we skip to the first erase region which starts after the + start of the requested erase, and then go back one. + */ + + while (i < mtd->numeraseregions && instr->addr >= regions[i].offset) + i++; + i--; + + /* OK, now i is pointing at the erase region in which this + erase request starts. Check the start of the requested + erase range is aligned with the erase size which is in + effect here. + */ + + if (instr->addr & (regions[i].erasesize-1)) + return -EINVAL; + + /* Remember the erase region we start on */ + first = i; + + /* Next, check that the end of the requested erase is aligned + * with the erase region at that address. + */ + + while (inumeraseregions && (instr->addr + instr->len) >= regions[i].offset) + i++; + + /* As before, drop back one to point at the region in which + the address actually falls + */ + i--; + + if ((instr->addr + instr->len) & (regions[i].erasesize-1)) + return -EINVAL; + + chipnum = instr->addr >> cfi->chipshift; + adr = instr->addr - (chipnum << cfi->chipshift); + len = instr->len; + + i=first; + + while(len) { + ret = do_erase_oneblock(map, &cfi->chips[chipnum], adr); + + if (ret) + return ret; + + adr += regions[i].erasesize; + len -= regions[i].erasesize; + + if (adr % (1<< cfi->chipshift) == ((regions[i].offset + (regions[i].erasesize * regions[i].numblocks)) %( 1<< cfi->chipshift))) + i++; + + if (adr >> cfi->chipshift) { + adr = 0; + chipnum++; + + if (chipnum >= cfi->numchips) + break; + } + } + + instr->state = MTD_ERASE_DONE; + if (instr->callback) + instr->callback(instr); + + return 0; +} + +static int cfi_sststd_erase_onesize(struct mtd_info *mtd, struct erase_info *instr) +{ + struct map_info *map = mtd->priv; + struct cfi_private *cfi = map->fldrv_priv; + unsigned long adr, len; + int chipnum, ret = 0; + + if (instr->addr & (mtd->erasesize - 1)) + return -EINVAL; + + if (instr->len & (mtd->erasesize -1)) + return -EINVAL; + + if ((instr->len + instr->addr) > mtd->size) + return -EINVAL; + + chipnum = instr->addr >> cfi->chipshift; + adr = instr->addr - (chipnum << cfi->chipshift); + len = instr->len; + + while(len) { + ret = do_erase_oneblock(map, &cfi->chips[chipnum], adr); + + if (ret) + return ret; + + adr += mtd->erasesize; + len -= mtd->erasesize; + + if (adr >> cfi->chipshift) { + adr = 0; + chipnum++; + + if (chipnum >= cfi->numchips) + break; + } + } + + instr->state = MTD_ERASE_DONE; + if (instr->callback) + instr->callback(instr); + + return 0; +} + +static void cfi_sststd_sync (struct mtd_info *mtd) +{ + struct map_info *map = mtd->priv; + struct cfi_private *cfi = map->fldrv_priv; + int i; + struct flchip *chip; + int ret = 0; + DECLARE_WAITQUEUE(wait, current); + + for (i=0; !ret && inumchips; i++) { + chip = &cfi->chips[i]; + + retry: + cfi_spin_lock(chip->mutex); + + switch(chip->state) { + case FL_READY: + case FL_STATUS: + case FL_CFI_QUERY: + case FL_JEDEC_QUERY: + chip->oldstate = chip->state; + chip->state = FL_SYNCING; + /* No need to wake_up() on this state change - + * as the whole point is that nobody can do anything + * with the chip now anyway. + */ + case FL_SYNCING: + cfi_spin_unlock(chip->mutex); + break; + + default: + /* Not an idle state */ + add_wait_queue(&chip->wq, &wait); + + cfi_spin_unlock(chip->mutex); + + schedule(); + + remove_wait_queue(&chip->wq, &wait); + + goto retry; + } + } + + /* Unlock the chips again */ + + for (i--; i >=0; i--) { + chip = &cfi->chips[i]; + + cfi_spin_lock(chip->mutex); + + if (chip->state == FL_SYNCING) { + chip->state = chip->oldstate; + wake_up(&chip->wq); + } + cfi_spin_unlock(chip->mutex); + } +} + + +static int cfi_sststd_suspend(struct mtd_info *mtd) +{ + struct map_info *map = mtd->priv; + struct cfi_private *cfi = map->fldrv_priv; + int i; + struct flchip *chip; + int ret = 0; +//printk("suspend\n"); + + for (i=0; !ret && inumchips; i++) { + chip = &cfi->chips[i]; + + cfi_spin_lock(chip->mutex); + + switch(chip->state) { + case FL_READY: + case FL_STATUS: + case FL_CFI_QUERY: + case FL_JEDEC_QUERY: + chip->oldstate = chip->state; + chip->state = FL_PM_SUSPENDED; + /* No need to wake_up() on this state change - + * as the whole point is that nobody can do anything + * with the chip now anyway. + */ + case FL_PM_SUSPENDED: + break; + + default: + ret = -EAGAIN; + break; + } + cfi_spin_unlock(chip->mutex); + } + + /* Unlock the chips again */ + + if (ret) { + for (i--; i >=0; i--) { + chip = &cfi->chips[i]; + + cfi_spin_lock(chip->mutex); + + if (chip->state == FL_PM_SUSPENDED) { + chip->state = chip->oldstate; + wake_up(&chip->wq); + } + cfi_spin_unlock(chip->mutex); + } + } + + return ret; +} + +static void cfi_sststd_resume(struct mtd_info *mtd) +{ + struct map_info *map = mtd->priv; + struct cfi_private *cfi = map->fldrv_priv; + int i; + struct flchip *chip; +//printk("resume\n"); + + for (i=0; inumchips; i++) { + + chip = &cfi->chips[i]; + + cfi_spin_lock(chip->mutex); + + if (chip->state == FL_PM_SUSPENDED) { + chip->state = FL_READY; + cfi_write(map, CMD(0xF0), chip->start); + wake_up(&chip->wq); + } + else + printk("Argh. Chip not in PM_SUSPENDED state upon resume()\n"); + + cfi_spin_unlock(chip->mutex); + } +} + +static void cfi_sststd_destroy(struct mtd_info *mtd) +{ + struct map_info *map = mtd->priv; + struct cfi_private *cfi = map->fldrv_priv; + kfree(cfi->cmdset_priv); + kfree(cfi); +} + +#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE) +#define cfi_sststd_init init_module +#define cfi_sststd_exit cleanup_module +#endif + +static char im_name[]="cfi_cmdset_0701"; + +mod_init_t cfi_sststd_init(void) +{ + inter_module_register(im_name, THIS_MODULE, &cfi_cmdset_0701); + return 0; +} + +mod_exit_t cfi_sststd_exit(void) +{ + inter_module_unregister(im_name); +} + +module_init(cfi_sststd_init); +module_exit(cfi_sststd_exit); + --- linux-2.4.20/drivers/mtd/chips/cfi_probe.c~2.4.20_broadcom_3_37_2_1109_US.patch 2005-01-07 05:38:15.000000000 -0500 +++ linux-2.4.20/drivers/mtd/chips/cfi_probe.c 2005-01-07 05:39:02.000000000 -0500 @@ -58,8 +58,15 @@ cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL); cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL); + if (!qry_present(map,base,cfi)) { + /* rather broken SST cfi probe (requires SST unlock) */ + cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL); + cfi_send_gen_cmd(0xAA, 0x5555, base, map, cfi, cfi->device_type, NULL); + cfi_send_gen_cmd(0x55, 0x2AAA, base, map, cfi, cfi->device_type, NULL); + cfi_send_gen_cmd(0x98, 0x5555, base, map, cfi, cfi->device_type, NULL); if (!qry_present(map,base,cfi)) return 0; + } if (!cfi->numchips) { /* This is the first time we're called. Set up the CFI --- linux-2.4.20/drivers/mtd/chips/gen_probe.c~2.4.20_broadcom_3_37_2_1109_US.patch 2005-01-07 05:38:15.000000000 -0500 +++ linux-2.4.20/drivers/mtd/chips/gen_probe.c 2005-01-07 05:39:02.000000000 -0500 @@ -289,6 +289,10 @@ case 0x0002: return cfi_cmdset_0002(map, primary); #endif +#ifdef CONFIG_MTD_CFI_SSTSTD + case 0x0701: + return cfi_cmdset_0701(map, primary); +#endif } return cfi_cmdset_unknown(map, primary); --- linux-2.4.20/drivers/mtd/devices/Config.in~2.4.20_broadcom_3_37_2_1109_US.patch 2005-01-07 05:39:01.000000000 -0500 +++ linux-2.4.20/drivers/mtd/devices/Config.in 2005-01-07 05:39:02.000000000 -0500 @@ -5,6 +5,7 @@ mainmenu_option next_comment comment 'Self-contained MTD device drivers' +bool ' Broadcom Chipcommon Serial Flash support' CONFIG_MTD_SFLASH dep_tristate ' Ramix PMC551 PCI Mezzanine RAM card support' CONFIG_MTD_PMC551 $CONFIG_MTD $CONFIG_PCI if [ "$CONFIG_MTD_PMC551" = "y" -o "$CONFIG_MTD_PMC551" = "m" ]; then bool ' PMC551 256M DRAM Bugfix' CONFIG_MTD_PMC551_BUGFIX --- linux-2.4.20/drivers/mtd/devices/Makefile~2.4.20_broadcom_3_37_2_1109_US.patch 2005-01-07 05:38:15.000000000 -0500 +++ linux-2.4.20/drivers/mtd/devices/Makefile 2005-01-07 05:39:02.000000000 -0500 @@ -12,6 +12,7 @@ # here where previously there was none. We now have to ensure that # doc200[01].o are linked before docprobe.o +obj-$(CONFIG_MTD_SFLASH) += sflash.o obj-$(CONFIG_MTD_DOC1000) += doc1000.o obj-$(CONFIG_MTD_DOC2000) += doc2000.o obj-$(CONFIG_MTD_DOC2001) += doc2001.o --- /dev/null 2004-04-06 13:56:48.000000000 -0400 +++ linux-2.4.20/drivers/mtd/devices/sflash.c 2005-01-07 05:39:02.000000000 -0500 @@ -0,0 +1,283 @@ +/* + * Broadcom SiliconBackplane chipcommon serial flash interface + * + * Copyright 2004, Broadcom Corporation + * All Rights Reserved. + * + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. + * + * $Id: sflash.c,v 1.1.1.7 2004/04/12 04:31:46 honor Exp $ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_MTD_PARTITIONS +extern struct mtd_partition * init_mtd_partitions(struct mtd_info *mtd, size_t size); +#endif + +struct sflash_mtd { + chipcregs_t *cc; + struct semaphore lock; + struct mtd_info mtd; + struct mtd_erase_region_info region; +}; + +/* Private global state */ +static struct sflash_mtd sflash; + +static int +sflash_mtd_poll(struct sflash_mtd *sflash, unsigned int offset, int timeout) +{ + int now = jiffies; + int ret = 0; + + for (;;) { + if (!sflash_poll(sflash->cc, offset)) { + ret = 0; + break; + } + if (time_after(jiffies, now + timeout)) { + printk(KERN_ERR "sflash: timeout\n"); + ret = -ETIMEDOUT; + break; + } + if (current->need_resched) { + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(timeout / 10); + } else + udelay(1); + } + + return ret; +} + +static int +sflash_mtd_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) +{ + struct sflash_mtd *sflash = (struct sflash_mtd *) mtd->priv; + int bytes, ret = 0; + + /* Check address range */ + if (!len) + return 0; + if ((from + len) > mtd->size) + return -EINVAL; + + down(&sflash->lock); + + *retlen = 0; + while (len) { + if ((bytes = sflash_read(sflash->cc, (uint) from, len, buf)) < 0) { + ret = bytes; + break; + } + from += (loff_t) bytes; + len -= bytes; + buf += bytes; + *retlen += bytes; + } + + up(&sflash->lock); + + return ret; +} + +static int +sflash_mtd_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf) +{ + struct sflash_mtd *sflash = (struct sflash_mtd *) mtd->priv; + int bytes, ret = 0; + + /* Check address range */ + if (!len) + return 0; + if ((to + len) > mtd->size) + return -EINVAL; + + down(&sflash->lock); + + *retlen = 0; + while (len) { + if ((bytes = sflash_write(sflash->cc, (uint) to, len, buf)) < 0) { + ret = bytes; + break; + } + if ((ret = sflash_mtd_poll(sflash, (unsigned int) to, HZ / 10))) + break; + to += (loff_t) bytes; + len -= bytes; + buf += bytes; + *retlen += bytes; + } + + up(&sflash->lock); + + return ret; +} + +static int +sflash_mtd_erase(struct mtd_info *mtd, struct erase_info *erase) +{ + struct sflash_mtd *sflash = (struct sflash_mtd *) mtd->priv; + int i, j, ret = 0; + unsigned int addr, len; + + /* Check address range */ + if (!erase->len) + return 0; + if ((erase->addr + erase->len) > mtd->size) + return -EINVAL; + + addr = erase->addr; + len = erase->len; + + down(&sflash->lock); + + /* Ensure that requested region is aligned */ + for (i = 0; i < mtd->numeraseregions; i++) { + for (j = 0; j < mtd->eraseregions[i].numblocks; j++) { + if (addr == mtd->eraseregions[i].offset + mtd->eraseregions[i].erasesize * j && + len >= mtd->eraseregions[i].erasesize) { + if ((ret = sflash_erase(sflash->cc, addr)) < 0) + break; + if ((ret = sflash_mtd_poll(sflash, addr, 10 * HZ))) + break; + addr += mtd->eraseregions[i].erasesize; + len -= mtd->eraseregions[i].erasesize; + } + } + if (ret) + break; + } + + up(&sflash->lock); + + /* Set erase status */ + if (ret) + erase->state = MTD_ERASE_FAILED; + else + erase->state = MTD_ERASE_DONE; + + /* Call erase callback */ + if (erase->callback) + erase->callback(erase); + + return ret; +} + +#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE) +#define sflash_mtd_init init_module +#define sflash_mtd_exit cleanup_module +#endif + +mod_init_t +sflash_mtd_init(void) +{ + struct pci_dev *pdev; + int ret = 0; + struct sflash *info; + uint i; +#ifdef CONFIG_MTD_PARTITIONS + struct mtd_partition *parts; +#endif + + if (!(pdev = pci_find_device(VENDOR_BROADCOM, SB_CC, NULL))) { + printk(KERN_ERR "sflash: chipcommon not found\n"); + return -ENODEV; + } + + memset(&sflash, 0, sizeof(struct sflash_mtd)); + init_MUTEX(&sflash.lock); + + /* Map registers and flash base */ + if (!(sflash.cc = ioremap_nocache(pci_resource_start(pdev, 0), + pci_resource_len(pdev, 0)))) { + printk(KERN_ERR "sflash: error mapping registers\n"); + ret = -EIO; + goto fail; + } + + /* Initialize serial flash access */ + info = sflash_init(sflash.cc); + + if (!info) { + printk(KERN_ERR "sflash: found no supported devices\n"); + ret = -ENODEV; + goto fail; + } + + /* Setup region info */ + sflash.region.offset = 0; + sflash.region.erasesize = info->blocksize; + sflash.region.numblocks = info->numblocks; + if (sflash.region.erasesize > sflash.mtd.erasesize) + sflash.mtd.erasesize = sflash.region.erasesize; + sflash.mtd.size = info->size; + sflash.mtd.numeraseregions = 1; + + /* Register with MTD */ + sflash.mtd.name = "sflash"; + sflash.mtd.type = MTD_NORFLASH; + sflash.mtd.flags = MTD_CAP_NORFLASH; + sflash.mtd.eraseregions = &sflash.region; + sflash.mtd.module = THIS_MODULE; + sflash.mtd.erase = sflash_mtd_erase; + sflash.mtd.read = sflash_mtd_read; + sflash.mtd.write = sflash_mtd_write; + sflash.mtd.priv = &sflash; + +#ifdef CONFIG_MTD_PARTITIONS + parts = init_mtd_partitions(&sflash.mtd, sflash.mtd.size); + for (i = 0; parts[i].name; i++); + ret = add_mtd_partitions(&sflash.mtd, parts, i); +#else + ret = add_mtd_device(&sflash.mtd); +#endif + if (ret) { + printk(KERN_ERR "sflash: add_mtd failed\n"); + goto fail; + } + + return 0; + + fail: + if (sflash.cc) + iounmap((void *) sflash.cc); + return ret; +} + +mod_exit_t +sflash_mtd_exit(void) +{ +#ifdef CONFIG_MTD_PARTITIONS + del_mtd_partitions(&sflash.mtd); +#else + del_mtd_device(&sflash.mtd); +#endif + iounmap((void *) sflash.cc); +} + +module_init(sflash_mtd_init); +module_exit(sflash_mtd_exit); --- linux-2.4.20/drivers/mtd/maps/Config.in~2.4.20_broadcom_3_37_2_1109_US.patch 2005-01-07 05:39:01.000000000 -0500 +++ linux-2.4.20/drivers/mtd/maps/Config.in 2005-01-07 05:39:02.000000000 -0500 @@ -44,6 +44,7 @@ fi if [ "$CONFIG_MIPS" = "y" ]; then + dep_tristate ' CFI Flash device mapped on Broadcom BCM947XX boards' CONFIG_MTD_BCM947XX $CONFIG_MTD_CFI dep_tristate ' Pb1000 boot flash device' CONFIG_MTD_PB1000 $CONFIG_MIPS_PB1000 dep_tristate ' Pb1500 MTD support' CONFIG_MTD_PB1500 $CONFIG_MIPS_PB1500 dep_tristate ' Pb1100 MTD support' CONFIG_MTD_PB1100 $CONFIG_MIPS_PB1100 --- linux-2.4.20/drivers/mtd/maps/Makefile~2.4.20_broadcom_3_37_2_1109_US.patch 2005-01-07 05:39:01.000000000 -0500 +++ linux-2.4.20/drivers/mtd/maps/Makefile 2005-01-07 05:39:02.000000000 -0500 @@ -6,6 +6,7 @@ O_TARGET := mapslink.o # Chip mappings +obj-$(CONFIG_MTD_BCM947XX) += bcm947xx-flash.o obj-$(CONFIG_MTD_CDB89712) += cdb89712.o obj-$(CONFIG_MTD_ARM_INTEGRATOR)+= integrator-flash.o obj-$(CONFIG_MTD_CFI_FLAGADM) += cfi_flagadm.o --- /dev/null 2004-04-06 13:56:48.000000000 -0400 +++ linux-2.4.20/drivers/mtd/maps/bcm947xx-flash.c 2005-01-08 12:16:21.889534944 -0500 @@ -0,0 +1,225 @@ +/* + * Flash mapping for BCM947XX boards + * + * Copyright 2004, Broadcom Corporation + * All Rights Reserved. + * + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. + * + * $Id: bcm947xx-flash.c,v 1.8 2004/04/12 05:42:38 honor Exp $ + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +/* Global SB handle */ +extern void *bcm947xx_sbh; +extern spinlock_t bcm947xx_sbh_lock; + +/* Convenience */ +#define sbh bcm947xx_sbh +#define sbh_lock bcm947xx_sbh_lock + +#ifdef CONFIG_MTD_PARTITIONS +extern struct mtd_partition * init_mtd_partitions(struct mtd_info *mtd, size_t size); +#endif + +#define WINDOW_ADDR 0x1fc00000 +#define WINDOW_SIZE 0x400000 +#define BUSWIDTH 2 + +/* e.g., flash=2M or flash=4M */ +static int flash = 0; +MODULE_PARM(flash, "i"); +static int __init +bcm947xx_setup(char *str) +{ + flash = memparse(str, &str); + return 1; +} +__setup("flash=", bcm947xx_setup); + +static struct mtd_info *bcm947xx_mtd; + +__u8 bcm947xx_map_read8(struct map_info *map, unsigned long ofs) +{ + if (map->map_priv_2 == 1) + return __raw_readb(map->map_priv_1 + ofs); + + u16 val = __raw_readw(map->map_priv_1 + (ofs & ~1)); + if (ofs & 1) + return ((val >> 8) & 0xff); + else + return (val & 0xff); +} + +__u16 bcm947xx_map_read16(struct map_info *map, unsigned long ofs) +{ + return __raw_readw(map->map_priv_1 + ofs); +} + +__u32 bcm947xx_map_read32(struct map_info *map, unsigned long ofs) +{ + return __raw_readl(map->map_priv_1 + ofs); +} + +void bcm947xx_map_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) +{ + memcpy_fromio(to, map->map_priv_1 + from, len); +} + +void bcm947xx_map_write8(struct map_info *map, __u8 d, unsigned long adr) +{ + __raw_writeb(d, map->map_priv_1 + adr); + mb(); +} + +void bcm947xx_map_write16(struct map_info *map, __u16 d, unsigned long adr) +{ + __raw_writew(d, map->map_priv_1 + adr); + mb(); +} + +void bcm947xx_map_write32(struct map_info *map, __u32 d, unsigned long adr) +{ + __raw_writel(d, map->map_priv_1 + adr); + mb(); +} + +void bcm947xx_map_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) +{ + memcpy_toio(map->map_priv_1 + to, from, len); +} + +struct map_info bcm947xx_map = { + name: "Physically mapped flash", + size: WINDOW_SIZE, + buswidth: BUSWIDTH, + read8: bcm947xx_map_read8, + read16: bcm947xx_map_read16, + read32: bcm947xx_map_read32, + copy_from: bcm947xx_map_copy_from, + write8: bcm947xx_map_write8, + write16: bcm947xx_map_write16, + write32: bcm947xx_map_write32, + copy_to: bcm947xx_map_copy_to +}; + +#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE) +#define init_bcm947xx_map init_module +#define cleanup_bcm947xx_map cleanup_module +#endif + +mod_init_t init_bcm947xx_map(void) +{ + ulong flags; + uint coreidx; + chipcregs_t *cc; + uint32 fltype; + uint window_addr = 0, window_size = 0; + size_t size; + int ret = 0; +#ifdef CONFIG_MTD_PARTITIONS + struct mtd_partition *parts; + int i; +#endif + + spin_lock_irqsave(&sbh_lock, flags); + coreidx = sb_coreidx(sbh); + + /* Check strapping option if chipcommon exists */ + if ((cc = sb_setcore(sbh, SB_CC, 0))) { + fltype = readl(&cc->capabilities) & CAP_FLASH_MASK; + if (fltype == PFLASH) { + bcm947xx_map.map_priv_2 = 1; + window_addr = 0x1c000000; + bcm947xx_map.size = window_size = 32 * 1024 * 1024; + if ((readl(&cc->flash_config) & CC_CFG_DS) == 0) + bcm947xx_map.buswidth = 1; + } + } else { + fltype = PFLASH; + bcm947xx_map.map_priv_2 = 0; + window_addr = WINDOW_ADDR; + window_size = WINDOW_SIZE; + } + + sb_setcoreidx(sbh, coreidx); + spin_unlock_irqrestore(&sbh_lock, flags); + + if (fltype != PFLASH) { + printk(KERN_ERR "pflash: found no supported devices\n"); + ret = -ENODEV; + goto fail; + } + + bcm947xx_map.map_priv_1 = (unsigned long) ioremap(window_addr, window_size); + if (!bcm947xx_map.map_priv_1) { + printk(KERN_ERR "pflash: ioremap failed\n"); + ret = -EIO; + goto fail; + } + + if (!(bcm947xx_mtd = do_map_probe("cfi_probe", &bcm947xx_map))) { + printk(KERN_ERR "pflash: cfi_probe failed\n"); + ret = -ENXIO; + goto fail; + } + + bcm947xx_mtd->module = THIS_MODULE; + + /* Allow size override for testing */ + size = flash ? : bcm947xx_mtd->size; + + printk(KERN_NOTICE "Flash device: 0x%x at 0x%x\n", size, window_addr); + +#ifdef CONFIG_MTD_PARTITIONS + parts = init_mtd_partitions(bcm947xx_mtd, size); + for (i = 0; parts[i].name; i++); + ret = add_mtd_partitions(bcm947xx_mtd, parts, i); + if (ret) { + printk(KERN_ERR "pflash: add_mtd_partitions failed\n"); + goto fail; + } +#endif + + return 0; + + fail: + if (bcm947xx_mtd) + map_destroy(bcm947xx_mtd); + if (bcm947xx_map.map_priv_1) + iounmap((void *) bcm947xx_map.map_priv_1); + bcm947xx_map.map_priv_1 = 0; + return ret; +} + +mod_exit_t cleanup_bcm947xx_map(void) +{ +#ifdef CONFIG_MTD_PARTITIONS + del_mtd_partitions(bcm947xx_mtd); +#endif + map_destroy(bcm947xx_mtd); + iounmap((void *) bcm947xx_map.map_priv_1); + bcm947xx_map.map_priv_1 = 0; +} + +module_init(init_bcm947xx_map); +module_exit(cleanup_bcm947xx_map); --- linux-2.4.20/drivers/mtd/mtdblock_ro.c~2.4.20_broadcom_3_37_2_1109_US.patch 2005-01-07 05:38:15.000000000 -0500 +++ linux-2.4.20/drivers/mtd/mtdblock_ro.c 2005-01-08 12:16:19.492899288 -0500 @@ -1,18 +1,16 @@ /* - * $Id: mtdblock_ro.c,v 1.12 2001/11/20 11:42:33 dwmw2 Exp $ + * Direct MTD block device access * - * Read-only version of the mtdblock device, without the - * read/erase/modify/writeback stuff + * $Id: mtdblock_ro.c,v 1.1.1.4 2003/10/14 08:08:16 sparq Exp $ + * + * 02-nov-2000 Nicolas Pitre Added read-modify-write with cache */ -#ifdef MTDBLOCK_DEBUG -#define DEBUGLVL debug -#endif - - -#include +#include #include - +#include +#include +#include #include #include @@ -24,56 +22,106 @@ #define DEVICE_OFF(device) #define DEVICE_NO_RANDOM #include - +/* for old kernels... */ +#ifndef QUEUE_EMPTY +#define QUEUE_EMPTY (!CURRENT) +#endif #if LINUX_VERSION_CODE < 0x20300 -#define RQFUNC_ARG void -#define blkdev_dequeue_request(req) do {CURRENT = req->next;} while (0) +#define QUEUE_PLUGGED (blk_dev[MAJOR_NR].plug_tq.sync) #else -#define RQFUNC_ARG request_queue_t *q +#define QUEUE_PLUGGED (blk_dev[MAJOR_NR].request_queue.plugged) #endif -#ifdef MTDBLOCK_DEBUG -static int debug = MTDBLOCK_DEBUG; -MODULE_PARM(debug, "i"); +#ifdef CONFIG_DEVFS_FS +#include +static void mtd_notify_add(struct mtd_info* mtd); +static void mtd_notify_remove(struct mtd_info* mtd); +static struct mtd_notifier notifier = { + mtd_notify_add, + mtd_notify_remove, + NULL +}; +static devfs_handle_t devfs_dir_handle = NULL; +static devfs_handle_t devfs_ro_handle[MAX_MTD_DEVICES]; #endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,14) -#define BLK_INC_USE_COUNT MOD_INC_USE_COUNT -#define BLK_DEC_USE_COUNT MOD_DEC_USE_COUNT -#else -#define BLK_INC_USE_COUNT do {} while(0) -#define BLK_DEC_USE_COUNT do {} while(0) -#endif +static struct mtdblk_dev { + struct mtd_info *mtd; /* Locked */ + int count; +} *mtdblks[MAX_MTD_DEVICES]; -static int mtd_sizes[MAX_MTD_DEVICES]; +static spinlock_t mtdblks_lock; +static int mtd_sizes[MAX_MTD_DEVICES]; static int mtdblock_open(struct inode *inode, struct file *file) { - struct mtd_info *mtd = NULL; - + struct mtdblk_dev *mtdblk; + struct mtd_info *mtd; int dev; - DEBUG(1,"mtdblock_open\n"); + DEBUG(MTD_DEBUG_LEVEL1,"mtdblock_open\n"); - if (inode == 0) + if (!inode) return -EINVAL; dev = MINOR(inode->i_rdev); + if (dev >= MAX_MTD_DEVICES) + return -EINVAL; mtd = get_mtd_device(NULL, dev); if (!mtd) - return -EINVAL; + return -ENODEV; if (MTD_ABSENT == mtd->type) { put_mtd_device(mtd); - return -EINVAL; + return -ENODEV; } - BLK_INC_USE_COUNT; + spin_lock(&mtdblks_lock); - mtd_sizes[dev] = mtd->size>>9; + /* If it's already open, no need to piss about. */ + if (mtdblks[dev]) { + mtdblks[dev]->count++; + spin_unlock(&mtdblks_lock); + return 0; + } - DEBUG(1, "ok\n"); + /* OK, it's not open. Try to find it */ + + /* First we have to drop the lock, because we have to + to things which might sleep. + */ + spin_unlock(&mtdblks_lock); + + mtdblk = kmalloc(sizeof(struct mtdblk_dev), GFP_KERNEL); + if (!mtdblk) { + put_mtd_device(mtd); + return -ENOMEM; + } + memset(mtdblk, 0, sizeof(*mtdblk)); + mtdblk->count = 1; + mtdblk->mtd = mtd; + + /* OK, we've created a new one. Add it to the list. */ + + spin_lock(&mtdblks_lock); + + if (mtdblks[dev]) { + /* Another CPU made one at the same time as us. */ + mtdblks[dev]->count++; + spin_unlock(&mtdblks_lock); + put_mtd_device(mtdblk->mtd); + kfree(mtdblk); + return 0; + } + + mtdblks[dev] = mtdblk; + mtd_sizes[dev] = mtdblk->mtd->size/1024; + set_device_ro (inode->i_rdev, !(mtdblk->mtd->flags & MTD_WRITEABLE)); + + spin_unlock(&mtdblks_lock); + + DEBUG(MTD_DEBUG_LEVEL1, "ok\n"); return 0; } @@ -81,162 +129,169 @@ static release_t mtdblock_release(struct inode *inode, struct file *file) { int dev; - struct mtd_info *mtd; - - DEBUG(1, "mtdblock_release\n"); + struct mtdblk_dev *mtdblk; + DEBUG(MTD_DEBUG_LEVEL1, "mtdblock_release\n"); if (inode == NULL) release_return(-ENODEV); dev = MINOR(inode->i_rdev); - mtd = __get_mtd_device(NULL, dev); + mtdblk = mtdblks[dev]; - if (!mtd) { - printk(KERN_WARNING "MTD device is absent on mtd_release!\n"); - BLK_DEC_USE_COUNT; - release_return(-ENODEV); + spin_lock(&mtdblks_lock); + if (!--mtdblk->count) { + /* It was the last usage. Free the device */ + mtdblks[dev] = NULL; + spin_unlock(&mtdblks_lock); + if (mtdblk->mtd->sync) + mtdblk->mtd->sync(mtdblk->mtd); + put_mtd_device(mtdblk->mtd); + kfree(mtdblk); + } else { + spin_unlock(&mtdblks_lock); } - if (mtd->sync) - mtd->sync(mtd); - - put_mtd_device(mtd); - - DEBUG(1, "ok\n"); + DEBUG(MTD_DEBUG_LEVEL1, "ok\n"); - BLK_DEC_USE_COUNT; release_return(0); } -static void mtdblock_request(RQFUNC_ARG) +/* + * This is a special request_fn because it is executed in a process context + * to be able to sleep independently of the caller. The io_request_lock + * is held upon entry and exit. + * The head of our request queue is considered active so there is no need + * to dequeue requests before we are done. + */ +static void handle_mtdblock_request(void) { - struct request *current_request; - unsigned int res = 0; - struct mtd_info *mtd; + struct request *req; + struct mtdblk_dev *mtdblk; + unsigned int res; - while (1) - { - /* Grab the Request and unlink it from the request list, INIT_REQUEST - will execute a return if we are done. */ + for (;;) { INIT_REQUEST; - current_request = CURRENT; - - if (MINOR(current_request->rq_dev) >= MAX_MTD_DEVICES) - { - printk("mtd: Unsupported device!\n"); - end_request(0); - continue; - } - - // Grab our MTD structure - - mtd = __get_mtd_device(NULL, MINOR(current_request->rq_dev)); - if (!mtd) { - printk("MTD device %d doesn't appear to exist any more\n", CURRENT_DEV); - end_request(0); - } + req = CURRENT; + spin_unlock_irq(&io_request_lock); + mtdblk = mtdblks[MINOR(req->rq_dev)]; + res = 0; - if (current_request->sector << 9 > mtd->size || - (current_request->sector + current_request->nr_sectors) << 9 > mtd->size) - { - printk("mtd: Attempt to read past end of device!\n"); - printk("size: %x, sector: %lx, nr_sectors %lx\n", mtd->size, current_request->sector, current_request->nr_sectors); - end_request(0); - continue; - } + if (MINOR(req->rq_dev) >= MAX_MTD_DEVICES) + panic(__FUNCTION__": minor out of bound"); - /* Remove the request we are handling from the request list so nobody messes - with it */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) - /* Now drop the lock that the ll_rw_blk functions grabbed for us - and process the request. This is necessary due to the extreme time - we spend processing it. */ - spin_unlock_irq(&io_request_lock); -#endif + if ((req->sector + req->current_nr_sectors) > (mtdblk->mtd->size >> 9)) + goto end_req; // Handle the request - switch (current_request->cmd) + switch (req->cmd) { + int err; size_t retlen; case READ: - if (MTD_READ(mtd,current_request->sector<<9, - current_request->nr_sectors << 9, - &retlen, current_request->buffer) == 0) + err = MTD_READ (mtdblk->mtd, req->sector << 9, + req->current_nr_sectors << 9, + &retlen, req->buffer); + if (!err) res = 1; - else - res = 0; break; + } - case WRITE: - - /* printk("mtdblock_request WRITE sector=%d(%d)\n",current_request->sector, - current_request->nr_sectors); - */ - - // Read only device - if ((mtd->flags & MTD_CAP_RAM) == 0) - { - res = 0; - break; +end_req: + spin_lock_irq(&io_request_lock); + end_request(res); } +} - // Do the write - if (MTD_WRITE(mtd,current_request->sector<<9, - current_request->nr_sectors << 9, - &retlen, current_request->buffer) == 0) - res = 1; - else - res = 0; - break; +static volatile int leaving = 0; +static DECLARE_MUTEX_LOCKED(thread_sem); +static DECLARE_WAIT_QUEUE_HEAD(thr_wq); - // Shouldn't happen - default: - printk("mtd: unknown request\n"); - break; - } +int mtdblock_thread(void *dummy) +{ + struct task_struct *tsk = current; + DECLARE_WAITQUEUE(wait, tsk); - // Grab the lock and re-thread the item onto the linked list -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) + tsk->session = 1; + tsk->pgrp = 1; + /* we might get involved when memory gets low, so use PF_MEMALLOC */ + tsk->flags |= PF_MEMALLOC; + strcpy(tsk->comm, "mtdblockd"); + tsk->tty = NULL; + spin_lock_irq(&tsk->sigmask_lock); + sigfillset(&tsk->blocked); + recalc_sigpending(tsk); + spin_unlock_irq(&tsk->sigmask_lock); + exit_mm(tsk); + exit_files(tsk); + exit_sighand(tsk); + exit_fs(tsk); + + while (!leaving) { + add_wait_queue(&thr_wq, &wait); + set_current_state(TASK_INTERRUPTIBLE); spin_lock_irq(&io_request_lock); -#endif - end_request(res); + if (QUEUE_EMPTY || QUEUE_PLUGGED) { + spin_unlock_irq(&io_request_lock); + schedule(); + remove_wait_queue(&thr_wq, &wait); + } else { + remove_wait_queue(&thr_wq, &wait); + set_current_state(TASK_RUNNING); + handle_mtdblock_request(); + spin_unlock_irq(&io_request_lock); + } } + + up(&thread_sem); + return 0; } +#if LINUX_VERSION_CODE < 0x20300 +#define RQFUNC_ARG void +#else +#define RQFUNC_ARG request_queue_t *q +#endif + +static void mtdblock_request(RQFUNC_ARG) +{ + /* Don't do anything, except wake the thread if necessary */ + wake_up(&thr_wq); +} static int mtdblock_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg) { - struct mtd_info *mtd; + struct mtdblk_dev *mtdblk; - mtd = __get_mtd_device(NULL, MINOR(inode->i_rdev)); + mtdblk = mtdblks[MINOR(inode->i_rdev)]; - if (!mtd) return -EINVAL; +#ifdef PARANOIA + if (!mtdblk) + BUG(); +#endif switch (cmd) { case BLKGETSIZE: /* Return device size */ - return put_user((mtd->size >> 9), (unsigned long *) arg); - -#ifdef BLKGETSIZE64 + return put_user((mtdblk->mtd->size >> 9), (unsigned long *) arg); case BLKGETSIZE64: - return put_user((u64)mtd->size, (u64 *)arg); -#endif + return put_user((u64)mtdblk->mtd->size, (u64 *)arg); case BLKFLSBUF: #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) - if(!capable(CAP_SYS_ADMIN)) return -EACCES; + if(!capable(CAP_SYS_ADMIN)) + return -EACCES; #endif fsync_dev(inode->i_rdev); invalidate_buffers(inode->i_rdev); - if (mtd->sync) - mtd->sync(mtd); + if (mtdblk->mtd->sync) + mtdblk->mtd->sync(mtdblk->mtd); return 0; default: - return -ENOTTY; + return -EINVAL; } } @@ -261,34 +316,85 @@ }; #endif +#ifdef CONFIG_DEVFS_FS +/* Notification that a new device has been added. Create the devfs entry for + * it. */ + +static void mtd_notify_add(struct mtd_info* mtd) +{ + char name[8]; + + if (!mtd || mtd->type == MTD_ABSENT) + return; + + sprintf(name, "%d", mtd->index); + devfs_ro_handle[mtd->index] = devfs_register(devfs_dir_handle, name, + DEVFS_FL_DEFAULT, MTD_BLOCK_MAJOR, mtd->index, + S_IFBLK | S_IRUGO | S_IWUGO, + &mtd_fops, NULL); +} + +static void mtd_notify_remove(struct mtd_info* mtd) +{ + if (!mtd || mtd->type == MTD_ABSENT) + return; + + devfs_unregister(devfs_ro_handle[mtd->index]); +} +#endif + int __init init_mtdblock(void) { int i; + spin_lock_init(&mtdblks_lock); +#ifdef CONFIG_DEVFS_FS + if (devfs_register_blkdev(MTD_BLOCK_MAJOR, DEVICE_NAME, &mtd_fops)) + { + printk(KERN_NOTICE "Can't allocate major number %d for Memory Technology Devices.\n", + MTD_BLOCK_MAJOR); + return -EAGAIN; + } + + devfs_dir_handle = devfs_mk_dir(NULL, DEVICE_NAME, NULL); + register_mtd_user(¬ifier); +#else if (register_blkdev(MAJOR_NR,DEVICE_NAME,&mtd_fops)) { printk(KERN_NOTICE "Can't allocate major number %d for Memory Technology Devices.\n", MTD_BLOCK_MAJOR); return -EAGAIN; } +#endif /* We fill it in at open() time. */ for (i=0; i< MAX_MTD_DEVICES; i++) { mtd_sizes[i] = 0; } - + init_waitqueue_head(&thr_wq); /* Allow the block size to default to BLOCK_SIZE. */ blksize_size[MAJOR_NR] = NULL; blk_size[MAJOR_NR] = mtd_sizes; blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), &mtdblock_request); + kernel_thread (mtdblock_thread, NULL, CLONE_FS|CLONE_FILES|CLONE_SIGHAND); return 0; } static void __exit cleanup_mtdblock(void) { + leaving = 1; + wake_up(&thr_wq); + down(&thread_sem); +#ifdef CONFIG_DEVFS_FS + unregister_mtd_user(¬ifier); + devfs_unregister(devfs_dir_handle); + devfs_unregister_blkdev(MTD_BLOCK_MAJOR, DEVICE_NAME); +#else unregister_blkdev(MAJOR_NR,DEVICE_NAME); - blksize_size[MAJOR_NR] = NULL; +#endif blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); + blksize_size[MAJOR_NR] = NULL; + blk_size[MAJOR_NR] = NULL; } module_init(init_mtdblock); @@ -296,5 +402,5 @@ MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Erwin Authried et al."); -MODULE_DESCRIPTION("Simple read-only block device emulation access to MTD devices"); +MODULE_AUTHOR("Nicolas Pitre et al."); +MODULE_DESCRIPTION("Caching read/erase/writeback block device emulation access to MTD devices"); --- linux-2.4.20/drivers/net/Config.in~2.4.20_broadcom_3_37_2_1109_US.patch 2005-01-07 05:39:01.000000000 -0500 +++ linux-2.4.20/drivers/net/Config.in 2005-01-08 12:16:21.077658368 -0500 @@ -2,6 +2,7 @@ # Network device configuration # +source drivers/net/hnd/Config.in source drivers/net/arcnet/Config.in tristate 'Dummy net driver support' CONFIG_DUMMY --- linux-2.4.20/drivers/net/Makefile~2.4.20_broadcom_3_37_2_1109_US.patch 2005-01-07 05:39:01.000000000 -0500 +++ linux-2.4.20/drivers/net/Makefile 2005-01-08 12:16:21.891534640 -0500 @@ -21,6 +21,17 @@ list-multi := rcpci.o rcpci-objs := rcpci45.o rclanmtl.o +subdir-m += mac +subdir-m += diag + +ifeq ($(CONFIG_HW_QOS),y) +subdir-m += port_based_qos +else + ifeq ($(CONFIG_PERFORMANCE),y) + subdir-m += port_based_qos + endif +endif + ifeq ($(CONFIG_TULIP),y) obj-y += tulip/tulip.o endif @@ -242,6 +253,36 @@ endif endif +# +# Broadcom HND devices +# + +ifdef CONFIG_HND +subdir-$(CONFIG_HND) += hnd +endif +ifdef CONFIG_ET +subdir-$(CONFIG_ET) += et.4702 +subdir-$(CONFIG_ET) += et +endif +ifdef CONFIG_IL +subdir-$(CONFIG_IL) += il +endif +ifdef CONFIG_WL +subdir-$(CONFIG_WL) += wl +endif +ifeq ($(CONFIG_HND),y) + obj-y += hnd/hnd.o +endif +ifeq ($(CONFIG_ET),y) + obj-y += et/et.o +endif +ifeq ($(CONFIG_IL),y) + obj-y += il/il.o +endif +ifeq ($(CONFIG_WL),y) + obj-y += wl/wl.o +endif + include $(TOPDIR)/Rules.make clean: --- /dev/null 2004-04-06 13:56:48.000000000 -0400 +++ linux-2.4.20/drivers/net/diag/Makefile 2005-01-07 05:39:02.000000000 -0500 @@ -0,0 +1,27 @@ +# Copyright 2001, Cybertan Corporation +# All Rights Reserved. +# +# This is UNPUBLISHED PROPRIETARY SOURCE CODE of Cybertan Corporation; +# the contents of this file may not be disclosed to third parties, copied or +# duplicated in any form, in whole or in part, without the prior written +# permission of Cybertan Corporation. +# +# +# $Id: Makefile,v 1.1 2003/07/09 14:09:58 honor Exp $ +# + +O_TARGET := diag.o + +MAC_OBJS := diag_led.o + +export-objs := +obj-y := $(MAC_OBJS) +obj-m := $(O_TARGET) + +SRCBASE := $(TOPDIR)/../.. +EXTRA_CFLAGS += -I$(SRCBASE)/include + +vpath %.c $(SRCBASE)/shared + +include $(TOPDIR)/Rules.make + --- /dev/null 2004-04-06 13:56:48.000000000 -0400 +++ linux-2.4.20/drivers/net/et/Makefile 2005-01-07 05:39:02.000000000 -0500 @@ -0,0 +1,42 @@ +# +# Makefile for the Broadcom et driver +# +# Copyright 2004, Broadcom Corporation +# All Rights Reserved. +# +# THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY +# KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM +# SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS +# FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. +# +# $Id: Makefile,v 1.1.1.6 2004/04/12 04:31:57 honor Exp $ +# + +O_TARGET := et.o + +ET_OBJS := et_linux.o etc.o + +ifeq ($(CONFIG_ET_47XX),y) +ET_OBJS += etc47xx.o etc_robo.o etc_adm.o +EXTRA_CFLAGS += -DBCM47XX_CHOPS +endif +ifeq ($(CONFIG_ET_4413),y) +ET_OBJS += etc4413.o +EXTRA_CFLAGS += -DBCM4413_CHOPS +endif + +export-objs := +obj-y := $(ET_OBJS) +obj-m := $(O_TARGET) + +EXTRA_CFLAGS += -DDMA + +# Search for sources under src/et/sys or objects under src/et/linux +ifneq ($(wildcard $(SRCBASE)/et/sys),) +EXTRA_CFLAGS += -I$(SRCBASE)/et/sys +vpath %.c $(SRCBASE)/et/sys $(SRCBASE)/shared +else +obj-y := $(foreach obj,$(ET_OBJS),$(SRCBASE)/et/linux/$(obj)) +endif + +include $(TOPDIR)/Rules.make --- /dev/null 2004-04-06 13:56:48.000000000 -0400 +++ linux-2.4.20/drivers/net/et.4702/Makefile 2005-01-07 05:39:02.000000000 -0500 @@ -0,0 +1,43 @@ +# Copyright 2001, Broadcom Corporation +# All Rights Reserved. +# +# This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation; +# the contents of this file may not be disclosed to third parties, copied or +# duplicated in any form, in whole or in part, without the prior written +# permission of Broadcom Corporation. +# +# Makefile for the Broadcom et driver +# +# $Id: Makefile,v 1.2 2003/11/13 13:04:22 honor Exp $ +# + +O_TARGET := 4702et.o + +ET_OBJS := et_linux.o etc.o + +ifeq ($(CONFIG_ET_47XX),y) +ET_OBJS += etc47xx.o etc_robo.o +EXTRA_CFLAGS += -DBCM47XX_CHOPS +endif +ifeq ($(CONFIG_ET_4413),y) +ET_OBJS += etc4413.o +EXTRA_CFLAGS += -DBCM4413_CHOPS +endif + +export-objs := +obj-y := $(ET_OBJS) +obj-m := $(O_TARGET) + +SRCBASE := $(TOPDIR)/../.. +EXTRA_CFLAGS += -I$(SRCBASE)/include +EXTRA_CFLAGS += -DDMA + +# Search for sources under src/et/sys or objects under src/et/linux +ifneq ($(wildcard $(SRCBASE)/et.4702/sys),) +EXTRA_CFLAGS += -I$(SRCBASE)/et.4702/sys +vpath %.c $(SRCBASE)/et.4702/sys $(SRCBASE)/shared +else +obj-y := $(foreach obj,$(ET_OBJS),$(SRCBASE)/et.4702/linux/$(obj)) +endif + +include $(TOPDIR)/Rules.make --- /dev/null 2004-04-06 13:56:48.000000000 -0400 +++ linux-2.4.20/drivers/net/hnd/Config.in 2005-01-07 05:39:02.000000000 -0500 @@ -0,0 +1,35 @@ +# +# Broadcom Home Networking Division (HND) driver configuration +# +# Copyright 2004, Broadcom Corporation +# All Rights Reserved. +# +# THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY +# KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM +# SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS +# FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. +# + +mainmenu_option next_comment +comment 'Broadcom HND network devices' + tristate 'Broadcom HND network device support' CONFIG_HND $CONFIG_PCI + if [ "$CONFIG_HND" != "n" ]; then + dep_tristate ' Broadcom InsideLine HPNA support' CONFIG_IL $CONFIG_HND + if [ "$CONFIG_IL" != "n" ]; then + bool ' Broadcom BCM42xx support' CONFIG_IL_42XX + bool ' Broadcom BCM47xx support' CONFIG_IL_47XX + int ' LARQ buffer allocation (0 = tiny, 2 = huge)' CONFIG_LARQ_BUF 0 + fi + dep_tristate ' Broadcom 10/100 Ethernet support' CONFIG_ET $CONFIG_HND + if [ "$CONFIG_ET" != "n" ]; then + bool ' Broadcom BCM4413 support' CONFIG_ET_4413 + bool ' Broadcom BCM47xx support' CONFIG_ET_47XX + fi + dep_tristate ' Broadcom BCM43xx 802.11 Wireless support' CONFIG_WL $CONFIG_HND + if [ "$CONFIG_WL" != "n" ]; then + bool ' Access Point Mode Supported' CONFIG_WL_AP + bool ' STA Mode Supported' CONFIG_WL_STA + bool ' OID Interface Supported' CONFIG_WL_OID + fi + fi +endmenu --- /dev/null 2004-04-06 13:56:48.000000000 -0400 +++ linux-2.4.20/drivers/net/hnd/Makefile 2005-01-07 05:39:02.000000000 -0500 @@ -0,0 +1,67 @@ +# +# Makefile for Broadcom Home Networking Division (HND) shared driver code +# +# Copyright 2004, Broadcom Corporation +# All Rights Reserved. +# +# THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY +# KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM +# SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS +# FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. +# +# $Id: Makefile,v 1.1.1.7 2004/04/12 04:31:58 honor Exp $ +# + +O_TARGET := hnd.o + +HND_OBJS := bcmutils.o hnddma.o linux_osl.o sbutils.o bcmsrom.o + +ifneq ($(CONFIG_BCM947XX),y) +HND_OBJS += nvramstubs.o +endif + +export-objs := shared_ksyms.o +obj-y := shared_ksyms.o $(HND_OBJS) +obj-m := $(O_TARGET) + +vpath %.c $(SRCBASE)/shared $(SRCBASE)/shared/nvram + +include $(TOPDIR)/Rules.make + +ifeq ($(wildcard $(SRCBASE)/shared/bcmutils.c),) +bcmutils.o: $(SRCBASE)/shared/linux/bcmutils.o + cp $< $@ +endif + +ifeq ($(wildcard $(SRCBASE)/shared/hnddma.c),) +hnddma.o: $(SRCBASE)/shared/linux/hnddma.o + cp $< $@ +endif + +ifeq ($(wildcard $(SRCBASE)/shared/linux_osl.c),) +linux_osl.o: $(SRCBASE)/shared/linux/linux_osl.o + cp $< $@ +endif + +ifeq ($(wildcard $(SRCBASE)/shared/sbutils.c),) +sbutils.o: $(SRCBASE)/shared/linux/sbutils.o + cp $< $@ +endif + +ifeq ($(wildcard $(SRCBASE)/shared/bcmsrom.c),) +bcmsrom.o: $(SRCBASE)/shared/linux/bcmsrom.o + cp $< $@ +endif + +ifeq ($(wildcard $(SRCBASE)/shared/nvramstubs.c),) +nvramstubs.o: $(SRCBASE)/shared/linux/nvramstubs.o + cp $< $@ +endif + +ifeq ($(wildcard $(SRCBASE)/shared/bcmwpa.c),) +bcmwpa.o: $(SRCBASE)/shared/linux/bcmwpa.o + cp $< $@ +endif + +shared_ksyms.c: shared_ksyms.sh $(HND_OBJS) + sh -e $< $(HND_OBJS) > $@ --- /dev/null 2004-04-06 13:56:48.000000000 -0400 +++ linux-2.4.20/drivers/net/hnd/shared_ksyms.sh 2005-01-07 05:39:02.000000000 -0500 @@ -0,0 +1,21 @@ +#!/bin/sh +# +# Copyright 2004, Broadcom Corporation +# All Rights Reserved. +# +# THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY +# KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM +# SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS +# FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. +# +# $Id: shared_ksyms.sh,v 1.1.1.6 2004/04/12 04:31:58 honor Exp $ +# + +cat < +#include +EOF + +for file in $* ; do + ${NM} $file | sed -ne 's/[0-9A-Fa-f]* [DT] \([^ ]*\)/extern void \1; EXPORT_SYMBOL(\1);/p' +done --- /dev/null 2004-04-06 13:56:48.000000000 -0400 +++ linux-2.4.20/drivers/net/il/Makefile 2005-01-07 05:39:02.000000000 -0500 @@ -0,0 +1,50 @@ +# +# Makefile for the Broadcom il driver +# +# Copyright 2004, Broadcom Corporation +# All Rights Reserved. +# +# THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY +# KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM +# SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS +# FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. +# +# $Id: Makefile,v 1.1.1.6 2004/04/12 04:31:58 honor Exp $ +# + +O_TARGET := il.o + +IL_OBJS := il_linux.o ilc.o cert.o plarq.o pe_select_maxse.o + +ifeq ($(CONFIG_IL_47XX),y) +IL_OBJS += ilc47xx.o +EXTRA_CFLAGS += -DBCM47XX_CHOPS +endif +ifeq ($(CONFIG_IL_42XX),y) +IL_OBJS += ilc42xx.o +EXTRA_CFLAGS += -DBCM42XX_CHOPS +endif + +export-objs := +obj-y := $(IL_OBJS) +obj-m := $(O_TARGET) + +EXTRA_CFLAGS += -DDMA -DIL_CERT -DIL_PROTOS + +ifneq ($(CONFIG_BRIDGE),n) +EXTRA_CFLAGS += -DIL_BRIDGE +endif + +ifeq ($(CONFIG_LARQ_BUF),0) +EXTRA_CFLAGS += -DLARQ_TINY +endif + +# Search for sources under src/il/sys or objects under src/il/linux +ifneq ($(wildcard $(SRCBASE)/il/sys),) +EXTRA_CFLAGS += -I$(SRCBASE)/il/sys +vpath %.c $(SRCBASE)/il/sys $(SRCBASE)/shared +else +obj-y := $(foreach obj,$(IL_OBJS),$(SRCBASE)/il/linux/$(obj)) +endif + +include $(TOPDIR)/Rules.make --- /dev/null 2004-04-06 13:56:48.000000000 -0400 +++ linux-2.4.20/drivers/net/mac/Makefile 2005-01-07 05:39:02.000000000 -0500 @@ -0,0 +1,27 @@ +# Copyright 2001, Cybertan Corporation +# All Rights Reserved. +# +# This is UNPUBLISHED PROPRIETARY SOURCE CODE of Cybertan Corporation; +# the contents of this file may not be disclosed to third parties, copied or +# duplicated in any form, in whole or in part, without the prior written +# permission of Cybertan Corporation. +# +# +# $Id: Makefile,v 1.1 2003/07/09 14:10:26 honor Exp $ +# + +O_TARGET := writemac.o + +MAC_OBJS := mac.o + +export-objs := +obj-y := $(MAC_OBJS) +obj-m := $(O_TARGET) + +SRCBASE := $(TOPDIR)/../.. +EXTRA_CFLAGS += -I$(SRCBASE)/include + +vpath %.c $(SRCBASE)/shared + +include $(TOPDIR)/Rules.make + --- /dev/null 2004-04-06 13:56:48.000000000 -0400 +++ linux-2.4.20/drivers/net/port_based_qos/Atan.c 2005-01-07 05:39:02.000000000 -0500 @@ -0,0 +1,177 @@ +#include "Atan.h" +#include "c47xx.h" + +extern void conf_gpio(int x); + +/*---------------------------------------------------------------------------- +Write specified data to eeprom +entry: *src = pointer to specified data to write + len = number of short(2 bytes) to be written +*/ +void write_eeprom( short RegNumber, unsigned short *data, int len ) +{ + int i2; + unsigned short s_addr, s_data; + unsigned short *src; + + src = data; + SetEEpromToSendState(); +// the write enable(WEN) instruction must be executed before any device +// programming can be done + + s_data = 0x04c0; + SendAddrToEEprom(s_data); //00000001 0011000000B + SetCSToLowForEEprom(); + + s_addr = 0x0500 | (RegNumber & 0x0ff); //00000001 01dddddddd + s_data = *src; + + for (i2 = len; i2 > 0 ; i2 --) + { + SendAddrToEEprom(s_addr); //00000001 01dddddd + SendDataToEEprom(s_data); //dddddddd dddddddd + SetCSToLowForEEprom(); + SetCSToLowForEEprom(); + //WriteWait(); + s_addr ++; + src ++; + s_data = *src; + } +// after all data has been written to EEprom , the write disable(WDS) +// instruction must be executed + SetCSToHighForEEprom(); + s_data = 0x0400; + SendAddrToEEprom(s_data); //00000001 00000000B + SetCSToLowForEEprom(); + SetCSToLowForEEprom(); +} + +void SetEEpromToSendState() +{ + conf_gpio(0x0); + conf_gpio(0x0); + conf_gpio(B_ECS); + conf_gpio(B_ECS); + +// ;cs __-- ,bit 2 +// ;sck ____ ,bit 3 +// ;di ____ ,bit 5 +// ;do ____ ,bit 4 +// ; +} + +void ResetEEpromToSendState() +{ + conf_gpio(0x0); + conf_gpio(0x0); + conf_gpio(0x0); + conf_gpio(0x0); + +// ;cs ____ ,bit 2 +// ;sck ____ ,bit 3 +// ;di ____ ,bit 5 +// ;do ____ ,bit 4 +// ; +} + +void SetCSToLowForEEprom() +{ + conf_gpio(0x0); + conf_gpio(B_ECK); + conf_gpio(B_ECK); + conf_gpio(0x0); + +// ;cs ____ ,bit 2 +// ;sck _--_ ,bit 3 +// ;di ____ ,bit 5 +// ;do ____ ,bit 4 +// ; +} + +void SetCSToHighForEEprom() +{ + conf_gpio(B_ECS); + conf_gpio(B_ECS|B_ECK); + conf_gpio(B_ECS|B_ECK); + conf_gpio(B_ECS); + +// ;cs ---- ,bit 2 +// ;sck _--_ ,bit 3 +// ;di ____ ,bit 5 +// ;do ____ ,bit 4 +// ; +} + +void send_1ToEEprom() +{ + conf_gpio(B_ECS|B_EDI); + conf_gpio(B_ECS|B_ECK|B_EDI); + conf_gpio(B_ECS|B_ECK|B_EDI); + conf_gpio(B_ECS|B_EDI); + +// ;cs ---- ,bit 2 +// ;sck _--_ ,bit 3 +// ;di ---- ,bit 5 +// ;do ____ ,bit 4 +// ; +} + +void send_0ToEEprom() +{ + conf_gpio(B_ECS); + conf_gpio(B_ECS|B_ECK); + conf_gpio(B_ECS|B_ECK); + conf_gpio(B_ECS); + +// ;cs ---- ,bit 2 +// ;sck _--_ ,bit 3 +// ;di ____ ,bit 5 +// ;do ____ ,bit 4 +// ; +} + +#if 0 +void WriteWait() +{ + unsigned int status; + + SetCSToLowForEEprom(); + SetCSToHighForEEprom(); + do { + SetCSToHighForEEprom(); + //status = ReadGPIOData(EDO); + status = gpio & B_EDO; // read EDO bit + } + while (!status); // wait for write - ready + SetCSToLowForEEprom(); +} +#endif + +void SendDataToEEprom(short s_data) +{ + int data_mask; + + for (data_mask = 0x8000; data_mask != 0; ) + { + if (s_data & data_mask) + send_1ToEEprom(); + else + send_0ToEEprom(); + data_mask = data_mask >> 1; + } +} + +void SendAddrToEEprom(short s_data) +{ + int data_mask; + + for (data_mask = 0x0400 ;data_mask != 0; ) + { + if (s_data & data_mask) + send_1ToEEprom(); + else + send_0ToEEprom(); + data_mask = data_mask >> 1; + } +} + --- /dev/null 2004-04-06 13:56:48.000000000 -0400 +++ linux-2.4.20/drivers/net/port_based_qos/Atan.h 2005-01-07 05:39:02.000000000 -0500 @@ -0,0 +1,18 @@ +#ifndef _ATAN_H_ +#define _ATAN_H_ + +#define SINGLECOLOUR 0x1 +#define DUALCOLOUR 0x2 + +void write_eeprom(short,unsigned short *,int); +void SetEEpromToSendState(void); +void ResetEEpromToSendState(void); +void SetCSToLowForEEprom(void); +void SetCSToHighForEEprom(void); +void send_1ToEEprom(void); +void send_0ToEEprom(void); +//void WriteWait(void); +void SendAddrToEEprom(short); +void SendDataToEEprom(short); + +#endif --- /dev/null 2004-04-06 13:56:48.000000000 -0400 +++ linux-2.4.20/drivers/net/port_based_qos/Makefile 2005-01-07 05:39:02.000000000 -0500 @@ -0,0 +1,27 @@ +# Copyright 2001, Cybertan Corporation +# All Rights Reserved. +# +# This is UNPUBLISHED PROPRIETARY SOURCE CODE of Cybertan Corporation; +# the contents of this file may not be disclosed to third parties, copied or +# duplicated in any form, in whole or in part, without the prior written +# permission of Cybertan Corporation. +# +# +# $Id: Makefile,v 1.2 2004/03/02 13:23:33 cnhsieh Exp $ +# + +O_TARGET := port_based_qos_mod.o + +PORT_BASED_QOS_MOD_OBJS := port_based_qos.o Atan.o c47xx.o eeprom.o + +export-objs := +obj-y := $(PORT_BASED_QOS_MOD_OBJS) +obj-m := $(O_TARGET) + +SRCBASE := $(TOPDIR)/../.. +EXTRA_CFLAGS += -I$(SRCBASE)/include -Wall -I$(SRCBASE)/ + +vpath %.c $(SRCBASE)/shared + +include $(TOPDIR)/Rules.make + --- /dev/null 2004-04-06 13:56:48.000000000 -0400 +++ linux-2.4.20/drivers/net/port_based_qos/c47xx.c 2005-01-07 05:39:02.000000000 -0500 @@ -0,0 +1,85 @@ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include "c47xx.h" +extern uint32 sb_gpioouten(void *sbh, uint32 mask, uint32 val); +extern uint32 sb_gpioout(void *sbh, uint32 mask, uint32 val); +extern uint32 sb_gpioin(void *sbh); +extern uint32 sb_gpiointmask(void *sbh, uint32 mask, uint32 val); + +#define OUTENMASK B_RESET|B_ECS|B_ECK|B_EDI +#define CFGMASK B_ECS|B_ECK|B_EDI +#define BIT(x) (1 << (x)) +#define ASSERT(exp) do {} while (0) + +void +conf_gpio(int x) +{ + ASSERT(sbh); + + /* Enable all of output pins */ + sb_gpioouten(sbh, OUTENMASK, OUTENMASK); + + /* We don't want the B_RESET pin changed, unless + * it tries to set the B_RESET pin. + */ + if (x & B_RESET) + sb_gpioout(sbh, OUTENMASK, x); + else + sb_gpioout(sbh, CFGMASK, x); + +} + +void +gpio_line_set(int x, unsigned int value) +{ + ASSERT(sbh); + + if (value == 1) + sb_gpioout(sbh, BIT(x), BIT(x)); + else if (value == 0) + sb_gpioout(sbh, BIT(x), 0); +} + +void +gpio_line_get(int x, int *value) +{ + ASSERT(sbh); + + *value = (sb_gpioin(sbh) >> x) & 0x1; +} + +void +gpio_line_config_in(int x) +{ + ASSERT(sbh); + + sb_gpioouten(sbh, BIT(x), 0); + sb_gpiointmask(sbh, BIT(x), BIT(x)); +} + +void +gpio_line_config_out(int x) +{ + ASSERT(sbh); + + sb_gpiointmask(sbh, BIT(x), 0); + sb_gpioouten(sbh, BIT(x), BIT(x)); +} + +void +gpio_line_config_out_all(int x) +{ + ASSERT(sbh); + + sb_gpioouten(sbh, OUTENMASK, OUTENMASK); +} --- /dev/null 2004-04-06 13:56:48.000000000 -0400 +++ linux-2.4.20/drivers/net/port_based_qos/c47xx.h 2005-01-07 05:39:02.000000000 -0500 @@ -0,0 +1,23 @@ +#ifndef _C47XX_H_ +#define _C47XX_H_ + +extern void *bcm947xx_sbh; +#define sbh bcm947xx_sbh + +#define GPIO0 0 +#define GPIO1 1 +#define GPIO2 2 +#define GPIO3 3 +#define GPIO4 4 +#define GPIO5 5 +#define GPIO6 6 +#define GPIO7 7 +#define GPIO8 8 + +#define B_RESET 1< + +#define EEDO_PIN 4 +#define EECS_PIN 2 +#define EECK_PIN 3 +#define EEDI_PIN 5 +#define RESET_PIN 0 + +static void SetCSToLowForEEprom(void); +//static void SetCSToHighForEEprom(void); +static void send1ToEEprom(void); +static void send0ToEEprom(void); +static void InitSerialInterface(void); +static void SerialPulse(void); +static void WriteDataToRegister(unsigned short RegNumber, unsigned short data); +void ReadDataFromRegister(unsigned short addr, unsigned short *hidata, unsigned short *lodata,int select_count); +static void WriteDataToEEprom(unsigned short addr, unsigned short data); +static void WriteCmdToEEprom(unsigned short cmd); +extern void gpio_line_set(int x, unsigned int value); +extern void gpio_line_get(int x, int *value); +extern void gpio_line_config_out(int x); +extern void gpio_line_config_in(int x); +extern void gpio_line_config_out_all(void); +// ;cs __-- ,bit 3 +// ;sck ____ ,bit 4 +// ;di ____ ,bit 5 +// ;do ____ ,bit 6 +// ; + +static void SetEEpromToSendState(void) +{ + gpio_line_set(EECS_PIN, 0); + gpio_line_set(EECK_PIN, 0); + gpio_line_set(EEDI_PIN, 1); +// gpio_line_set(EEDO_PIN, 1); /* high impedance */ + + mdelay(1); + gpio_line_set(EECS_PIN, 1); +// gpio_line_set(EEDO_PIN, 1); /* high impedance */ +} + +#if 0 +static void EEpromInit(void) +{ + gpio_line_set(EECS_PIN, 0); + gpio_line_set(EECK_PIN, 0); + gpio_line_set(EEDI_PIN, 1); + gpio_line_set(EEDO_PIN, 1); /* high impedance */ + + mdelay(1); +} + +// ;cs ____ ,bit 3 +// ;sck ____ ,bit 4 +// ;di ____ ,bit 5 +// ;do ____ ,bit 6 +// ; +static void ResetEEpromToSendState(void) +{ + gpio_line_set(EECS_PIN, 0); + gpio_line_set(EEDI_PIN, 0); + //gpio_line_set(EEDO_PIN, 0); + gpio_line_set(EECK_PIN, 0); +} +#endif /* 0 */ + +// ;cs ____ ,bit 3 +// ;sck _--_ ,bit 4 +// ;di ____ ,bit 5 +// ;do ____ ,bit 6 +// ; +static void SetCSToLowForEEprom(void) +{ + /* minimum tcs is 1us */ + gpio_line_set(EECS_PIN, 0); + gpio_line_set(EECS_PIN, 0); + + gpio_line_set(EECK_PIN, 0); + gpio_line_set(EECK_PIN, 1); + gpio_line_set(EECK_PIN, 1); + gpio_line_set(EECK_PIN, 1); + gpio_line_set(EECK_PIN, 1); + gpio_line_set(EECK_PIN, 0); + + gpio_line_set(EECS_PIN, 1); + + udelay(10); +} + +#if 0 +// ;cs ---- ,bit 3 +// ;sck _--_ ,bit 4 +// ;di ____ ,bit 5 +// ;do ____ ,bit 6 +// ; +static void SetCSToHighForEEprom(void) +{ + gpio_line_set(EECS_PIN, 1); + + /* min tskh and tskl is 1us */ + gpio_line_set(EECK_PIN, 1); + udelay(2); + gpio_line_set(EECK_PIN, 0); +} +#endif /* 0 */ + +// ;cs ---- ,bit 3 +// ;sck _--_ ,bit 4 +// ;di ---- ,bit 5 +// ;do ____ ,bit 6 +// ; +static void send1ToEEprom(void) +{ +//printf("send1ToEEprom(1)..."); + gpio_line_set(EEDI_PIN, 1); + + gpio_line_set(EECK_PIN, 0); + udelay(1); + gpio_line_set(EECK_PIN, 1); + gpio_line_set(EECK_PIN, 1); + gpio_line_set(EECK_PIN, 1); + udelay(1); + gpio_line_set(EECK_PIN, 0); +} + +// ;cs ---- ,bit 3 +// ;sck _--_ ,bit 4 +// ;di ____ ,bit 5 +// ;do ____ ,bit 6 +// ; +static void send0ToEEprom(void) +{ +//printf("send0ToEEprom(0)..."); + gpio_line_set(EEDI_PIN, 0); + + gpio_line_set(EECK_PIN, 0); + udelay(1); + gpio_line_set(EECK_PIN, 1); + gpio_line_set(EECK_PIN, 1); + gpio_line_set(EECK_PIN, 1); + udelay(1); + gpio_line_set(EECK_PIN, 0); +} + +static void WriteDataToEEprom(unsigned short addr, unsigned short data) +{ + unsigned short addr_mask, data_mask; + + SetEEpromToSendState(); + for (addr_mask = 0x400; addr_mask != 0; ) + { + if (addr & addr_mask) + send1ToEEprom(); + else + send0ToEEprom(); + addr_mask = addr_mask >> 1; + } + for (data_mask = 0x8000; data_mask != 0; ) + { + if (data & data_mask) + send1ToEEprom(); + else + send0ToEEprom(); + data_mask = data_mask >> 1; + } + SetCSToLowForEEprom(); +} + +static void WriteCmdToEEprom(unsigned short cmd) +{ + unsigned short cmd_mask; + + SetEEpromToSendState(); + for (cmd_mask = 0x0400 ;cmd_mask != 0; ) + { + if (cmd & cmd_mask) + send1ToEEprom(); + else + send0ToEEprom(); + cmd_mask = cmd_mask >> 1; + } + SetCSToLowForEEprom(); +} + +/* + * Write data to configure registers through EEPROM interface, even we do not have + * an external EEPROM connectted, ADM6996 got a virtual AT39C66 inside + */ +static void WriteDataToRegister(unsigned short RegNumber, unsigned short data) +{ + unsigned short cmd, addr; + + printk("WriteDataToRegister(RegNumber=0x%x, data=0x%x)\n", RegNumber, data); + +// the write enable(WEN) instruction must be executed before any device +// programming can be done + cmd = 0x04c0; + WriteCmdToEEprom(cmd); //00000001 0011000000B + + addr = 0x0500 | (RegNumber & 0x0ff); //00000001 01dddddddd + WriteDataToEEprom(addr, data); //00000001 01dddddd + + +// after all data has been written to EEprom , the write disable(WDS) +// instruction must be executed + cmd = 0x0400; + WriteCmdToEEprom(cmd); //00000001 00000000B +} + +static void SerialDelay(int count) +{ + udelay(count); +} + +static void InitSerialInterface(void) +{ + gpio_line_set(EECK_PIN, 0); + gpio_line_set(EEDI_PIN, 0); +} + +static void SerialPulse(void) +{ + gpio_line_set(EECK_PIN, 0); + gpio_line_set(EECK_PIN, 1); + SerialDelay(10); + gpio_line_set(EECK_PIN, 1); + gpio_line_set(EECK_PIN, 0); +} +/* + * Since there is no EEPROM is our board, read from EEPROM need to obey the timing alike + * MII interface, EECK = MDC, EEDI = MDIO, please refer to section 4.3 of ADM6996 datasheet + */ +void ReadDataFromRegister(unsigned short addr, unsigned short *hidata, unsigned short *lodata, int select_count) +{ + unsigned short addr_mask, data_mask; + int value, i; + unsigned char StartBits, Opcode, TAbits; + + gpio_line_config_out_all(); + mdelay(1); + /* initialize serial interface */ + gpio_line_set(EECS_PIN, 0); + InitSerialInterface(); + + /* Preamble, 35 bits */ + gpio_line_set(EECK_PIN, 0); + gpio_line_set(EEDI_PIN, 1); + for (i = 0; i < 35; i++) + { + gpio_line_set(EECK_PIN, 1); + SerialDelay(10); + gpio_line_set(EECK_PIN, 0); + SerialDelay(10); + } + + /* Start bits, 2-bit(01b) */ + InitSerialInterface(); + StartBits = 0x01; + for (i = 0; i < 2; i++) + { + value = (StartBits & 2) ? 1 : 0; + gpio_line_set(EEDI_PIN, value); + SerialDelay(1); + SerialPulse(); + StartBits <<= 1; + } + + /* Opcode, read = 10b */ + InitSerialInterface(); + Opcode = 0x02; + for (i = 0; i < 2; i++) + { + value = (Opcode & 0x02) ? 1 : 0; + gpio_line_set(EEDI_PIN, value); + SerialDelay(1); + SerialPulse(); + Opcode <<= 1; + } + + /* 10 bits register address */ + /* 1-bit Table Select, 2-bit Device Address, 7-bit Register Address */ + InitSerialInterface(); + if (select_count) + addr = (addr & 0x7f) | 0x200; + else + addr = addr & 0x7f ; + for (addr_mask = 0x200; addr_mask != 0; addr_mask >>= 1) + { + value = (addr & addr_mask) ? 1 : 0; + gpio_line_set(EEDI_PIN, value); + SerialDelay(1); + SerialPulse(); + } + + /* TA, turnaround 2-bit */ + InitSerialInterface(); + TAbits = 0x02; + gpio_line_config_in(EEDI_PIN); + for (i = 0; i < 2; i++) + { + gpio_line_set(EECK_PIN, 1); + SerialDelay(4); + gpio_line_get(EEDI_PIN, &value); + SerialDelay(4); + TAbits <<= 1; + gpio_line_set(EECK_PIN, 1); + } + + + /* Latch data from serial management EEDI pin */ + *hidata = 0; + gpio_line_set(EECK_PIN, 0); + for (data_mask = 0x8000; data_mask != 0; data_mask >>= 1) + { + SerialDelay(4); + gpio_line_set(EECK_PIN, 1); + gpio_line_get(EEDI_PIN, &value); + if (value) + { + *hidata |= data_mask; + } + gpio_line_set(EECK_PIN, 0); + SerialDelay(4); + } + *lodata = 0; + gpio_line_set(EECK_PIN, 0); + for (data_mask = 0x8000; data_mask != 0; data_mask >>= 1) + { + SerialDelay(4); + gpio_line_set(EECK_PIN, 1); + gpio_line_get(EEDI_PIN, &value); + if (value) + { + *lodata |= data_mask; + } + gpio_line_set(EECK_PIN, 0); + SerialDelay(4); + } + + SerialDelay(2); + + /* Idle, EECK must send at least one clock at idle time */ + SerialPulse(); + gpio_line_set(EECK_PIN, 0); + SerialDelay(10); + gpio_line_set(EECK_PIN, 1); + SerialDelay(10); + gpio_line_set(EECK_PIN, 0); + SerialPulse(); + + gpio_line_config_out(EEDI_PIN); + gpio_line_set(EECS_PIN, 1); + + printk("ReadDataFromRegister(addr=0x%x, hidata=0x%x, lodata=0x%x)\n", addr, *hidata, *lodata); +} --- /dev/null 2004-04-06 13:56:48.000000000 -0400 +++ linux-2.4.20/drivers/net/port_based_qos/port_based_qos.c 2005-01-07 05:39:02.000000000 -0500 @@ -0,0 +1,460 @@ + /* + * Remaining issues: + * + stats support + * + multicast support + * + media sense + * + half/full duplex + * - random MAC addr. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define MODULE_NAME "port_based_qos_mod" +#define DEVICE_NAME "qos" +#define MODULE_VERSION "0.0.1" + +extern void ReadDataFromRegister(unsigned short addr, unsigned short *hidata, unsigned short *lodata,int select_count); + +#ifdef PERFORMANCE_SUPPORT +static struct ctl_table_header *qos_sysctl_header; +static unsigned long qos[28]; + +static ctl_table mytable[] = { + { 2000, "qos", + qos, sizeof(qos), + 0644, NULL, + proc_dointvec }, + { 0 } +}; + +static unsigned short statis_addr_map[7][6] ={ + {0x04, 0x06, 0x08, 0x0a, 0x0b, 0x0c}, + {0x16, 0x18, 0x1a, 0x1c, 0x1d, 0x1e}, + {0x0d, 0x0f, 0x11, 0x13, 0x14, 0x15}, + {0x1f, 0x21, 0x23, 0x25, 0x26, 0x27}, + {0x31, 0x33, 0x35, 0x37, 0x38, 0x39}, + {0x28, 0x2a, 0x2c, 0x2e, 0x2f, 0x30}, + {0x01, 0x01, 0x01, 0x01, 0x01, 0x01} +}; + +unsigned long get_statistic_from_serial(unsigned short port, unsigned short item) +{ + unsigned short hidata, lodata; + + ReadDataFromRegister(statis_addr_map[item][port], &hidata, &lodata, 1); + return ((hidata << 16) | lodata); +} +#endif + +#ifdef HW_QOS_SUPPORT +struct port_qos_t{ + int addr; + int content_mask; + int *content_set; +}; + +void WriteDataToRegister_(unsigned short reg_idx, unsigned short content_idx); +extern void write_eeprom(short,short *,int); + +#define BANDWIDTH_1_BIT 2 +#define BANDWIDTH_2_BIT 4 +#define BANDWIDTH_3_BIT 6 +#define BANDWIDTH_4_BIT 7 + +#define PORT_CONFIG_1 0x3 +#define PORT_CONFIG_2 0x5 +#define PORT_CONFIG_3 0x7 +#define PORT_CONFIG_4 0x8 +#define BANDWIDTH_CTL_123 0x31 +#define BANDWIDTH_CTL_4 0x32 +#define BANDWIDTH_CTL_ENABLE 0x33 +#define DISCARD_MODE 0x10 +#define TOS_PRIO_MAP 0xf + +#define PRIORITY_MASK 0xfc7f +#define PRIORITY_DISABLE_MASK 0xfc7e +#define FLOW_CTL_MASK 0xfffe +#define RATE_LIMIT_MASK_1 0xff8f +#define RATE_LIMIT_MASK_2 0xf8ff +#define RATE_LIMIT_MASK_3 0x8fff +#define RATE_LIMIT_MASK_4 0xfff8 +#define BANDWIDTH_CTL_MASK 0xff2b +#define DISCARD_MASK 0x0fff + +#define BANDWIDTH_ENABLE_1 1 << BANDWIDTH_1_BIT//04 +#define BANDWIDTH_ENABLE_2 1 << BANDWIDTH_2_BIT//10 +#define BANDWIDTH_ENABLE_3 1 << BANDWIDTH_3_BIT//40 +#define BANDWIDTH_ENABLE_4 1 << BANDWIDTH_4_BIT//80 +#define BANDWIDTH_CTL_MASK_1 0xffff^BANDWIDTH_ENABLE_1//0xfffb +#define BANDWIDTH_CTL_MASK_2 0xffff^BANDWIDTH_ENABLE_2//0xffef +#define BANDWIDTH_CTL_MASK_3 0xffff^BANDWIDTH_ENABLE_3//0xffbf +#define BANDWIDTH_CTL_MASK_4 0xffff^BANDWIDTH_ENABLE_4//0xff7f + +/*static int disable_content[] = {0x0}; +//static int enable_content[] = {0xd4, 0x0cff};//bit 7,6,4,2; Q1=11(50%),Q0=00(0%)*/ +//static int sw_content[] = {0x0,0x0c00};//bit 7,6,4,2; Q1=11(50%),Q0=00(0%) +static int sw_content[] = {0x0,0xc000};//bit 7,6,4,2; Q1=11(50%),Q0=00(0%) +static int port_priority_content[] = {0x080,0x380};//Q0,Q3 +//static int port_priority_content[] = {0x300,0x0};//Q1,Q0 +static int port_flow_ctl_content[] = {0x0,0x1}; +static int port_rate_limit_content_1[] = {0x0,0x00,0x10,0x20,0x30,0x40,0x50,0x60,0x70}; +static int port_rate_limit_content_2[] = {0x0,0x000,0x100,0x200,0x300,0x400,0x500,0x600,0x700}; +static int port_rate_limit_content_3[] = {0x0,0x0000,0x1000,0x2000,0x3000,0x4000,0x5000,0x6000,0x7000}; +static int port_rate_limit_content_4[] = {0x0,0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7}; +static int port_rate_limit_enable_1[] = {0x0, BANDWIDTH_ENABLE_1}; +static int port_rate_limit_enable_2[] = {0x0, BANDWIDTH_ENABLE_2}; +static int port_rate_limit_enable_3[] = {0x0, BANDWIDTH_ENABLE_3}; +static int port_rate_limit_enable_4[] = {0x0, BANDWIDTH_ENABLE_4}; + +static struct port_qos_t port_mii_disable[] = { + { BANDWIDTH_CTL_ENABLE, BANDWIDTH_CTL_MASK, sw_content}, + //{ DISCARD_MODE, DISCARD_MASK, sw_content}, + { PORT_CONFIG_1, PRIORITY_MASK, sw_content},//port_priority_1 + { PORT_CONFIG_2, PRIORITY_MASK, sw_content},//port_priority_2 + { PORT_CONFIG_3, PRIORITY_MASK, sw_content},//port_priority_3 + { PORT_CONFIG_4, PRIORITY_MASK, sw_content},//port_priority_4 + { PORT_CONFIG_1, FLOW_CTL_MASK, &port_flow_ctl_content[1]},//port_flow_control_1 + { PORT_CONFIG_2, FLOW_CTL_MASK, &port_flow_ctl_content[1]},//port_flow_control_2 + { PORT_CONFIG_3, FLOW_CTL_MASK, &port_flow_ctl_content[1]},//port_flow_control_3 + { PORT_CONFIG_4, FLOW_CTL_MASK, &port_flow_ctl_content[1]},//port_flow_control_4 + { -1} +}; + +static struct port_qos_t port_mii_enable[] = { + //{ BANDWIDTH_CTL_ENABLE, BANDWIDTH_CTL_MASK, enable_content}, + //{ DISCARD_MODE, DISCARD_MASK, sw_content}, + { -1} +}; + +struct port_qos_t *port_mii_sw_array[] = {port_mii_disable, port_mii_enable}; + +/*static struct port_qos_t port_mii_addr[] = { + { PORT_CONFIG_1, PRIORITY_MASK, port_priority_content},//port_priority_1 + { PORT_CONFIG_1, FLOW_CTL_MASK, port_flow_ctl_content},//port_flow_control_1 + //{ "port_frame_type_1", 0x3}, + { BANDWIDTH_CTL_123, RATE_LIMIT_MASK_14, port_rate_limit_content_14},//port_rate_limit_1 + { PORT_CONFIG_2, PRIORITY_MASK, port_priority_content},//port_priority_2 + { PORT_CONFIG_2, FLOW_CTL_MASK, port_flow_ctl_content},//port_flow_control_2 + //{ "port_frame_type_2", 0x5}, + { BANDWIDTH_CTL_123, RATE_LIMIT_MASK_2, port_rate_limit_content_2},//port_rate_limit_2 + { PORT_CONFIG_3, PRIORITY_MASK, port_priority_content},//port_priority_3 + { PORT_CONFIG_3, FLOW_CTL_MASK, port_flow_ctl_content},//port_flow_control_3 + //{ "port_frame_type_3", 0x7}, + { BANDWIDTH_CTL_123, RATE_LIMIT_MASK_3, port_rate_limit_content_3},//port_rate_limit_3 + //{ "port_priority_4", 0x8, 0x380}, + { PORT_CONFIG_4, PRIORITY_MASK, port_priority_content},//port_priority_4 + { PORT_CONFIG_4, FLOW_CTL_MASK, port_flow_ctl_content},//port_flow_control_4 + //{ "port_frame_type_4", 0x8}, + { BANDWIDTH_CTL_4, RATE_LIMIT_MASK_14, port_rate_limit_content_14},//port_rate_limit_4 + { -1} +};*/ + +static struct port_qos_t priority_1[] = { + { PORT_CONFIG_1, PRIORITY_MASK, port_priority_content},//port_priority_1 + { -1} +}; +static struct port_qos_t flow_control_1[] = { + { PORT_CONFIG_1, FLOW_CTL_MASK, port_flow_ctl_content},//port_flow_control_1 + { -1} +}; +static struct port_qos_t rate_limit_1[] = { + { BANDWIDTH_CTL_123, RATE_LIMIT_MASK_1, port_rate_limit_content_1},//port_rate_limit_1 + { BANDWIDTH_CTL_ENABLE, BANDWIDTH_CTL_MASK_1, port_rate_limit_enable_1},//port_rate_limit_4 + { -1} +}; +static struct port_qos_t priority_2[] = { + { PORT_CONFIG_2, PRIORITY_MASK, port_priority_content},//port_priority_2 + { -1} +}; +static struct port_qos_t flow_control_2[] = { + { PORT_CONFIG_2, FLOW_CTL_MASK, port_flow_ctl_content},//port_flow_control_2 + { -1} +}; +static struct port_qos_t rate_limit_2[] = { + { BANDWIDTH_CTL_123, RATE_LIMIT_MASK_2, port_rate_limit_content_2},//port_rate_limit_2 + { BANDWIDTH_CTL_ENABLE, BANDWIDTH_CTL_MASK_2, port_rate_limit_enable_2},//port_rate_limit_4 + { -1} +}; +static struct port_qos_t priority_3[] = { + { PORT_CONFIG_3, PRIORITY_MASK, port_priority_content},//port_priority_3 + { -1} +}; +static struct port_qos_t flow_control_3[] = { + { PORT_CONFIG_3, FLOW_CTL_MASK, port_flow_ctl_content},//port_flow_control_3 + { -1} +}; +static struct port_qos_t rate_limit_3[] = { + { BANDWIDTH_CTL_123, RATE_LIMIT_MASK_3, port_rate_limit_content_3},//port_rate_limit_3 + { BANDWIDTH_CTL_ENABLE, BANDWIDTH_CTL_MASK_3, port_rate_limit_enable_3},//port_rate_limit_4 + { -1} +}; +static struct port_qos_t priority_4[] = { + { PORT_CONFIG_4, PRIORITY_MASK, port_priority_content},//port_priority_4 + { -1} +}; +static struct port_qos_t flow_control_4[] = { + { PORT_CONFIG_4, FLOW_CTL_MASK, port_flow_ctl_content},//port_flow_control_4 + { -1} +}; +static struct port_qos_t rate_limit_4[] = { + { BANDWIDTH_CTL_4, RATE_LIMIT_MASK_4, port_rate_limit_content_4},//port_rate_limit_4 + { BANDWIDTH_CTL_ENABLE, BANDWIDTH_CTL_MASK_4, port_rate_limit_enable_4},//port_rate_limit_4 + { -1} +}; + +static struct port_qos_t *port_mii_addr[] = { + priority_1, + flow_control_1, + rate_limit_1, + priority_2, + flow_control_2, + rate_limit_2, + priority_3, + flow_control_3, + rate_limit_3, + priority_4, + flow_control_4, + rate_limit_4, + NULL +}; + +void WriteDataToRegister_(unsigned short reg_idx, unsigned short content_idx) +{ + short RegNumber; + unsigned short data, hidata=0x0, lodata=0x0; + int i; + struct port_qos_t *port_qos = port_mii_addr[reg_idx]; + + //printk("\nWriteDataToRegister_:reg_idx=%d content_idx=%d\n", reg_idx, content_idx); + if (!port_qos) + port_qos = port_mii_sw_array[content_idx]; + + for (i=0; port_qos[i].addr != -1; i++) + { + RegNumber = port_qos[i].addr; + ReadDataFromRegister(RegNumber, &hidata, &lodata, 0); + + if (!(RegNumber % 2)) /* even port number use lower word */ + hidata = lodata; + + data = (hidata & port_qos[i].content_mask) | (((i > 0) && (content_idx > 1))? port_qos[i].content_set[1] : port_qos[i].content_set[content_idx]); + + write_eeprom(RegNumber, &data, 1); + ReadDataFromRegister(RegNumber, &hidata, &lodata, 0); + } + ReadDataFromRegister(0xf, &hidata, &lodata, 0); + + /*RegNumber = port_mii_addr[reg_idx].addr; + if (RegNumber == -1)//Disable or Enable + { + struct port_qos_t *port_mii_sw = port_mii_sw_array[content_idx]; + + printk("\nWriteDataToRegister_:reg_idx=%d content_idx=%d\n", reg_idx, content_idx); + for (i=0; port_mii_sw[i].addr != -1; i++) + { + RegNumber = port_mii_sw[i].addr; + + ReadDataFromRegister(RegNumber, &hidata, &lodata, 0); + + if (!(RegNumber % 2)) + hidata = lodata; + + data = (hidata & port_mii_sw[i].content_mask) | port_mii_sw[i].content_set[i]; + + write_eeprom(RegNumber, &data, 1); + + ReadDataFromRegister(RegNumber, &hidata, &lodata, 0); + printk("\n============== %s===============\n", (content_idx==0)?"disable":"enable"); + } + } + else + { + ReadDataFromRegister(RegNumber, &hidata, &lodata, 0); + + if (!(RegNumber % 2)) + hidata = lodata; + + data = (hidata & port_mii_addr[reg_idx].content_mask) | port_mii_addr[reg_idx].content_set[content_idx]; + + write_eeprom(RegNumber, &data, 1); + ReadDataFromRegister(RegNumber, &hidata, &lodata, 0); + }*/ +} +#endif + +static int dev_do_ioctl(struct net_device *dev, struct ifreq *req, int cmd) +{ + struct mii_ioctl_data *data = (struct mii_ioctl_data *)req->ifr_data; +#ifdef PERFORMANCE_SUPPORT + int item, port; + + unsigned long status_item; +#endif + + switch (cmd) + { + case SIOCGMIIPHY: /* Get address of MII PHY in use. */ + case SIOCDEVPRIVATE: /* for binary compat, remove in 2.5 */ + + /* Fall through to the SIOCGMIIREG, taken from eepro100 and rtl + * drivers */ +#ifdef PERFORMANCE_SUPPORT + case SIOCGMIIREG: /* Read MII PHY register. */ + for (item=0; item<6; item++) + for (port=1; port<5; port++){ + qos[(item * 4) + (port-1)] = get_statistic_from_serial(port, item); + } + + status_item = get_statistic_from_serial(0, 6); + + qos[24] = (0x1 & (status_item >> 8)); + qos[25] = (0x1 & (status_item >> 16)); + qos[26] = (0x1 & (status_item >> 24)); + qos[27] = (0x1 & (status_item >> 28)); + + return 0; +#endif + + case SIOCDEVPRIVATE+1: /* for binary compat, remove in 2.5 */ +#ifdef HW_QOS_SUPPORT + case SIOCSMIIREG: /* Write MII PHY register. */ + { + printk("\n x phy_id=%x\n", data->phy_id); + printk("\n x reg_num=%x\n", data->reg_num); + printk("\n x val_in=%x\n", data->val_in); + printk("\n x val_out=%x\n", data->val_out); + + WriteDataToRegister_(data->phy_id, data->val_in); + return 0; + } +#endif + case SIOCDEVPRIVATE+2: /* for binary compat, remove in 2.5 */ + default: + return -EOPNOTSUPP; + } +} + +static int __devinit qos_eth_probe(struct net_device *dev) +{ + + SET_MODULE_OWNER(dev); + + ether_setup(dev); + + strcpy(dev->name, DEVICE_NAME "0"); + + dev->do_ioctl = dev_do_ioctl; + + return 0; +} + +#ifdef HW_QOS_SUPPORT +static char *port_option_name[] = { + "port_priority_1", + "port_flow_control_1", + //{ "port_frame_type_1", + "port_rate_limit_1", + "port_priority_2", + "port_flow_control_2", + //{ "port_frame_type_2", + "port_rate_limit_2", + "port_priority_3", + "port_flow_control_3", + //{ "port_frame_type_3", + "port_rate_limit_3", + "port_priority_4", + //{ "port_priority_4", PORT_CONFIG_4, PRIORITY_MASK, port_priority_content}, + "port_flow_control_4", + //{ "port_frame_type_4", + "port_rate_limit_4", + "QoS", + NULL +}; + +extern char *nvram_get(const char *name); +extern uint bcm_atoi(char *s); + +static int set_port_option(struct net_device *dev, unsigned short port_addr, char *option_content) +{ + struct ifreq ifr; + struct mii_ioctl_data stats; + + stats.phy_id=port_addr; + stats.val_in=bcm_atoi(option_content); + + ifr.ifr_data = (void *)&stats; + + return dev_do_ioctl(dev, &ifr, SIOCSMIIREG); +} + + +void +restore_default_from_NV(struct net_device *dev) +{ + unsigned short i; + char *value = NULL; + + for (i = 0; port_option_name[i]; i++) + { + if((value = nvram_get(port_option_name[i]))) + set_port_option(dev, i, value); + } + return; +} +#endif + +static struct net_device qos_devices; + +/* Module initialization and cleanup */ +int init_module(void) +{ + int res; + struct net_device *dev; + + printk("Initializing " MODULE_NAME " driver " MODULE_VERSION "\n"); + + dev = &qos_devices; + + dev->init = qos_eth_probe; + + if ((res = register_netdev(dev))) + printk("Failed to register netdev. res = %d\n", res); + +#ifdef PERFORMANCE_SUPPORT + qos_sysctl_header = register_sysctl_table(mytable, 0); +#endif +#ifdef HW_QOS_SUPPORT + restore_default_from_NV(dev); + write_eeprom(TOS_PRIO_MAP, &sw_content[0], 1);/* disable TOS priority map*/ +#endif + return 0; +} + +void cleanup_module(void) +{ + struct net_device *dev = &qos_devices; + if (dev->priv != NULL) + { + unregister_netdev(dev); + kfree(dev->priv); + dev->priv = NULL; + } + +#ifdef PERFORMANCE_SUPPORT + unregister_sysctl_table(qos_sysctl_header); +#endif +} + --- /dev/null 2004-04-06 13:56:48.000000000 -0400 +++ linux-2.4.20/drivers/net/wl/Makefile 2005-01-07 05:39:02.000000000 -0500 @@ -0,0 +1,68 @@ +# +# Makefile for the Broadcom wl driver +# +# Copyright 2004, Broadcom Corporation +# All Rights Reserved. +# +# THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY +# KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM +# SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS +# FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. +# +# $Id: Makefile,v 1.1.1.7 2004/04/12 04:32:06 honor Exp $ +# + +O_TARGET := wl.o + +WL_OBJS := wl_linux.o wlc.o d11ucode.o wlc_phy.o wlc_rate.o wlc_led.o wlc_security.o rc4.o tkhash.o bcmwpa.o + +INSUP_OBJS := aes.o aeskeywrap.o hmac.o md5.o passhash.o prf.o rijndael-alg-fst.o sha1.o + +# Alternate ioctl interfaces +ifeq ($(CONFIG_NET_WIRELESS),y) +WL_OBJS += wlc_cmn_ioctl.o +endif +ifeq ($(CONFIG_WL_OID),y) +WL_OBJS += wl_oid.o +endif + +ifeq ($(CONFIG_WL_STA),y) +WL_OBJS += $(INSUP_OBJS) +endif + +# Prefix driver variants +WL_APOBJS := $(foreach obj,$(WL_OBJS),ap_$(obj)) +WL_STAOBJS := $(foreach obj,$(WL_OBJS) wlc_sup.o,sta_$(obj)) +WL_APSTAOBJS := $(foreach obj,$(WL_OBJS) wlc_sup.o,apsta_$(obj)) +ifneq ($(CONFIG_WL_STA),y) +WL_APSTAOBJS += $(foreach obj,$(INSUP_OBJS), apsta_$(obj)) +endif + +# Either or both +ifeq ($(CONFIG_WL_AP),y) +AP := AP +endif +ifeq ($(CONFIG_WL_STA),y) +STA := STA +endif + +# Build all variants as modules but link only one of them +export-objs := +obj-y := $(WL_$(AP)$(STA)OBJS) +obj-m := $(O_TARGET) +variant-objs := $(WL_APOBJS) $(WL_STAOBJS) $(WL_APSTAOBJS) + +EXTRA_CFLAGS += -DDMA + +# Search for sources under src/wl/sys or objects under src/wl/linux +ifneq ($(wildcard $(SRCBASE)/wl/sys),) +EXTRA_CFLAGS += -I$(SRCBASE)/wl/sys +vpath %.c $(SRCBASE)/wl/sys $(SRCBASE)/shared $(SRCBASE)/crypto +else +obj-y := $(foreach obj,$(obj-y),$(SRCBASE)/wl/linux/$(obj)) +variant-objs := $(foreach obj,$(variant-objs),$(SRCBASE)/wl/linux/$(obj)) +endif + +include $(TOPDIR)/Rules.make + + --- linux-2.4.20/drivers/pcmcia/Makefile~2.4.20_broadcom_3_37_2_1109_US.patch 2005-01-07 05:39:01.000000000 -0500 +++ linux-2.4.20/drivers/pcmcia/Makefile 2005-01-07 05:39:02.000000000 -0500 @@ -64,6 +64,10 @@ au1000_ss-objs-$(CONFIG_PCMCIA_PB1X00) += au1000_pb1x00.o au1000_ss-objs-$(CONFIG_PCMCIA_DB1X00) += au1000_db1x00.o +obj-$(CONFIG_PCMCIA_BCM4710) += bcm4710_ss.o +bcm4710_ss-objs := bcm4710_generic.o +bcm4710_ss-objs += bcm4710_pcmcia.o + obj-$(CONFIG_PCMCIA_SA1100) += sa1100_cs.o obj-$(CONFIG_PCMCIA_M8XX) += m8xx_pcmcia.o @@ -98,5 +102,8 @@ au1x00_ss.o: $(au1000_ss-objs-y) $(LD) -r -o $@ $(au1000_ss-objs-y) +bcm4710_ss.o: $(bcm4710_ss-objs) + $(LD) -r -o $@ $(bcm4710_ss-objs) + yenta_socket.o: $(yenta_socket-objs) $(LD) $(LD_RFLAG) -r -o $@ $(yenta_socket-objs) --- /dev/null 2004-04-06 13:56:48.000000000 -0400 +++ linux-2.4.20/drivers/pcmcia/bcm4710_generic.c 2005-01-07 05:39:02.000000000 -0500 @@ -0,0 +1,912 @@ +/* + * + * bcm47xx pcmcia driver + * + * Copyright 2004, Broadcom Corporation + * All Rights Reserved. + * + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. + * + * Based on sa1100_generic.c from www.handhelds.org, + * and au1000_generic.c from oss.sgi.com. + * + * $Id: bcm4710_generic.c,v 1.1.1.7 2004/04/12 04:32:07 honor Exp $ + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include "cs_internal.h" + +#include +#include +#include + +#include +#include +#include + +#include "bcm4710pcmcia.h" + +#ifdef PCMCIA_DEBUG +static int pc_debug = PCMCIA_DEBUG; +#endif + +MODULE_DESCRIPTION("Linux PCMCIA Card Services: bcm47xx Socket Controller"); + +/* This structure maintains housekeeping state for each socket, such + * as the last known values of the card detect pins, or the Card Services + * callback value associated with the socket: + */ +static struct bcm47xx_pcmcia_socket *pcmcia_socket; +static int socket_count; + + +/* Returned by the low-level PCMCIA interface: */ +static struct pcmcia_low_level *pcmcia_low_level; + +/* Event poll timer structure */ +static struct timer_list poll_timer; + + +/* Prototypes for routines which are used internally: */ + +static int bcm47xx_pcmcia_driver_init(void); +static void bcm47xx_pcmcia_driver_shutdown(void); +static void bcm47xx_pcmcia_task_handler(void *data); +static void bcm47xx_pcmcia_poll_event(unsigned long data); +static void bcm47xx_pcmcia_interrupt(int irq, void *dev, struct pt_regs *regs); +static struct tq_struct bcm47xx_pcmcia_task; + +#ifdef CONFIG_PROC_FS +static int bcm47xx_pcmcia_proc_status(char *buf, char **start, + off_t pos, int count, int *eof, void *data); +#endif + + +/* Prototypes for operations which are exported to the + * in-kernel PCMCIA core: + */ + +static int bcm47xx_pcmcia_init(unsigned int sock); +static int bcm47xx_pcmcia_suspend(unsigned int sock); +static int bcm47xx_pcmcia_register_callback(unsigned int sock, + void (*handler)(void *, unsigned int), void *info); +static int bcm47xx_pcmcia_inquire_socket(unsigned int sock, socket_cap_t *cap); +static int bcm47xx_pcmcia_get_status(unsigned int sock, u_int *value); +static int bcm47xx_pcmcia_get_socket(unsigned int sock, socket_state_t *state); +static int bcm47xx_pcmcia_set_socket(unsigned int sock, socket_state_t *state); +static int bcm47xx_pcmcia_get_io_map(unsigned int sock, struct pccard_io_map *io); +static int bcm47xx_pcmcia_set_io_map(unsigned int sock, struct pccard_io_map *io); +static int bcm47xx_pcmcia_get_mem_map(unsigned int sock, struct pccard_mem_map *mem); +static int bcm47xx_pcmcia_set_mem_map(unsigned int sock, struct pccard_mem_map *mem); +#ifdef CONFIG_PROC_FS +static void bcm47xx_pcmcia_proc_setup(unsigned int sock, struct proc_dir_entry *base); +#endif + +static struct pccard_operations bcm47xx_pcmcia_operations = { + bcm47xx_pcmcia_init, + bcm47xx_pcmcia_suspend, + bcm47xx_pcmcia_register_callback, + bcm47xx_pcmcia_inquire_socket, + bcm47xx_pcmcia_get_status, + bcm47xx_pcmcia_get_socket, + bcm47xx_pcmcia_set_socket, + bcm47xx_pcmcia_get_io_map, + bcm47xx_pcmcia_set_io_map, + bcm47xx_pcmcia_get_mem_map, + bcm47xx_pcmcia_set_mem_map, +#ifdef CONFIG_PROC_FS + bcm47xx_pcmcia_proc_setup +#endif +}; + + +/* + * bcm47xx_pcmcia_driver_init() + * + * This routine performs a basic sanity check to ensure that this + * kernel has been built with the appropriate board-specific low-level + * PCMCIA support, performs low-level PCMCIA initialization, registers + * this socket driver with Card Services, and then spawns the daemon + * thread which is the real workhorse of the socket driver. + * + * Please see linux/Documentation/arm/SA1100/PCMCIA for more information + * on the low-level kernel interface. + * + * Returns: 0 on success, -1 on error + */ +static int __init bcm47xx_pcmcia_driver_init(void) +{ + servinfo_t info; + struct pcmcia_init pcmcia_init; + struct pcmcia_state state; + unsigned int i; + unsigned long tmp; + + + printk("\nBCM47XX PCMCIA (CS release %s)\n", CS_RELEASE); + + CardServices(GetCardServicesInfo, &info); + + if (info.Revision != CS_RELEASE_CODE) { + printk(KERN_ERR "Card Services release codes do not match\n"); + return -1; + } + +#ifdef CONFIG_BCM4710 + pcmcia_low_level=&bcm4710_pcmcia_ops; +#else +#error Unsupported Broadcom BCM47XX board. +#endif + + pcmcia_init.handler=bcm47xx_pcmcia_interrupt; + + if ((socket_count = pcmcia_low_level->init(&pcmcia_init)) < 0) { + printk(KERN_ERR "Unable to initialize PCMCIA service.\n"); + return -EIO; + } else { + printk("\t%d PCMCIA sockets initialized.\n", socket_count); + } + + pcmcia_socket = + kmalloc(sizeof(struct bcm47xx_pcmcia_socket) * socket_count, + GFP_KERNEL); + memset(pcmcia_socket, 0, + sizeof(struct bcm47xx_pcmcia_socket) * socket_count); + if (!pcmcia_socket) { + printk(KERN_ERR "Card Services can't get memory \n"); + return -1; + } + + for (i = 0; i < socket_count; i++) { + if (pcmcia_low_level->socket_state(i, &state) < 0) { + printk(KERN_ERR "Unable to get PCMCIA status\n"); + return -EIO; + } + pcmcia_socket[i].k_state = state; + pcmcia_socket[i].cs_state.csc_mask = SS_DETECT; + + if (i == 0) { + pcmcia_socket[i].virt_io = + (unsigned long)ioremap_nocache(EXTIF_PCMCIA_IOBASE(BCM4710_EXTIF), 0x1000); + /* Substract ioport base which gets added by in/out */ + pcmcia_socket[i].virt_io -= mips_io_port_base; + pcmcia_socket[i].phys_attr = + (unsigned long)EXTIF_PCMCIA_CFGBASE(BCM4710_EXTIF); + pcmcia_socket[i].phys_mem = + (unsigned long)EXTIF_PCMCIA_MEMBASE(BCM4710_EXTIF); + } else { + printk(KERN_ERR "bcm4710: socket 1 not supported\n"); + return 1; + } + } + + /* Only advertise as many sockets as we can detect: */ + if (register_ss_entry(socket_count, &bcm47xx_pcmcia_operations) < 0) { + printk(KERN_ERR "Unable to register socket service routine\n"); + return -ENXIO; + } + + /* Start the event poll timer. + * It will reschedule by itself afterwards. + */ + bcm47xx_pcmcia_poll_event(0); + + DEBUG(1, "bcm4710: initialization complete\n"); + return 0; + +} + +module_init(bcm47xx_pcmcia_driver_init); + + +/* + * bcm47xx_pcmcia_driver_shutdown() + * + * Invokes the low-level kernel service to free IRQs associated with this + * socket controller and reset GPIO edge detection. + */ +static void __exit bcm47xx_pcmcia_driver_shutdown(void) +{ + int i; + + del_timer_sync(&poll_timer); + unregister_ss_entry(&bcm47xx_pcmcia_operations); + pcmcia_low_level->shutdown(); + flush_scheduled_tasks(); + for (i = 0; i < socket_count; i++) { + if (pcmcia_socket[i].virt_io) + iounmap((void *)pcmcia_socket[i].virt_io); + if (pcmcia_socket[i].phys_attr) + iounmap((void *)pcmcia_socket[i].phys_attr); + if (pcmcia_socket[i].phys_mem) + iounmap((void *)pcmcia_socket[i].phys_mem); + } + DEBUG(1, "bcm4710: shutdown complete\n"); +} + +module_exit(bcm47xx_pcmcia_driver_shutdown); + +/* + * bcm47xx_pcmcia_init() + * We perform all of the interesting initialization tasks in + * bcm47xx_pcmcia_driver_init(). + * + * Returns: 0 + */ +static int bcm47xx_pcmcia_init(unsigned int sock) +{ + DEBUG(1, "%s(): initializing socket %u\n", __FUNCTION__, sock); + + return 0; +} + +/* + * bcm47xx_pcmcia_suspend() + * + * We don't currently perform any actions on a suspend. + * + * Returns: 0 + */ +static int bcm47xx_pcmcia_suspend(unsigned int sock) +{ + DEBUG(1, "%s(): suspending socket %u\n", __FUNCTION__, sock); + + return 0; +} + + +/* + * bcm47xx_pcmcia_events() + * + * Helper routine to generate a Card Services event mask based on + * state information obtained from the kernel low-level PCMCIA layer + * in a recent (and previous) sampling. Updates `prev_state'. + * + * Returns: an event mask for the given socket state. + */ +static inline unsigned +bcm47xx_pcmcia_events(struct pcmcia_state *state, + struct pcmcia_state *prev_state, + unsigned int mask, unsigned int flags) +{ + unsigned int events=0; + + if (state->bvd1 != prev_state->bvd1) { + + DEBUG(3, "%s(): card BVD1 value %u\n", __FUNCTION__, state->bvd1); + + events |= mask & (flags & SS_IOCARD) ? SS_STSCHG : SS_BATDEAD; + } + + if (state->bvd2 != prev_state->bvd2) { + + DEBUG(3, "%s(): card BVD2 value %u\n", __FUNCTION__, state->bvd2); + + events |= mask & (flags & SS_IOCARD) ? 0 : SS_BATWARN; + } + + if (state->detect != prev_state->detect) { + + DEBUG(3, "%s(): card detect value %u\n", __FUNCTION__, state->detect); + + events |= mask & SS_DETECT; + } + + + if (state->ready != prev_state->ready) { + + DEBUG(3, "%s(): card ready value %u\n", __FUNCTION__, state->ready); + + events |= mask & ((flags & SS_IOCARD) ? 0 : SS_READY); + } + + if (events != 0) { + DEBUG(2, "events: %s%s%s%s%s\n", + (events & SS_DETECT) ? "DETECT " : "", + (events & SS_READY) ? "READY " : "", + (events & SS_BATDEAD) ? "BATDEAD " : "", + (events & SS_BATWARN) ? "BATWARN " : "", + (events & SS_STSCHG) ? "STSCHG " : ""); + } + + *prev_state=*state; + return events; +} + + +/* + * bcm47xx_pcmcia_task_handler() + * + * Processes serviceable socket events using the "eventd" thread context. + * + * Event processing (specifically, the invocation of the Card Services event + * callback) occurs in this thread rather than in the actual interrupt + * handler due to the use of scheduling operations in the PCMCIA core. + */ +static void bcm47xx_pcmcia_task_handler(void *data) +{ + struct pcmcia_state state; + int i, events, irq_status; + + DEBUG(4, "%s(): entering PCMCIA monitoring thread\n", __FUNCTION__); + + for (i = 0; i < socket_count; i++) { + if ((irq_status = pcmcia_low_level->socket_state(i, &state)) < 0) + printk(KERN_ERR "Error in kernel low-level PCMCIA service.\n"); + + events = bcm47xx_pcmcia_events(&state, + &pcmcia_socket[i].k_state, + pcmcia_socket[i].cs_state.csc_mask, + pcmcia_socket[i].cs_state.flags); + + if (pcmcia_socket[i].handler != NULL) { + pcmcia_socket[i].handler(pcmcia_socket[i].handler_info, + events); + } + } +} + +static struct tq_struct bcm47xx_pcmcia_task = { + routine: bcm47xx_pcmcia_task_handler +}; + + +/* + * bcm47xx_pcmcia_poll_event() + * + * Let's poll for events in addition to IRQs since IRQ only is unreliable... + */ +static void bcm47xx_pcmcia_poll_event(unsigned long dummy) +{ + DEBUG(4, "%s(): polling for events\n", __FUNCTION__); + + poll_timer.function = bcm47xx_pcmcia_poll_event; + poll_timer.expires = jiffies + BCM47XX_PCMCIA_POLL_PERIOD; + add_timer(&poll_timer); + schedule_task(&bcm47xx_pcmcia_task); +} + + +/* + * bcm47xx_pcmcia_interrupt() + * + * Service routine for socket driver interrupts (requested by the + * low-level PCMCIA init() operation via bcm47xx_pcmcia_thread()). + * + * The actual interrupt-servicing work is performed by + * bcm47xx_pcmcia_task(), largely because the Card Services event- + * handling code performs scheduling operations which cannot be + * executed from within an interrupt context. + */ +static void +bcm47xx_pcmcia_interrupt(int irq, void *dev, struct pt_regs *regs) +{ + DEBUG(3, "%s(): servicing IRQ %d\n", __FUNCTION__, irq); + schedule_task(&bcm47xx_pcmcia_task); +} + + +/* + * bcm47xx_pcmcia_register_callback() + * + * Implements the register_callback() operation for the in-kernel + * PCMCIA service (formerly SS_RegisterCallback in Card Services). If + * the function pointer `handler' is not NULL, remember the callback + * location in the state for `sock', and increment the usage counter + * for the driver module. (The callback is invoked from the interrupt + * service routine, bcm47xx_pcmcia_interrupt(), to notify Card Services + * of interesting events.) Otherwise, clear the callback pointer in the + * socket state and decrement the module usage count. + * + * Returns: 0 + */ +static int +bcm47xx_pcmcia_register_callback(unsigned int sock, + void (*handler)(void *, unsigned int), void *info) +{ + if (handler == NULL) { + pcmcia_socket[sock].handler = NULL; + MOD_DEC_USE_COUNT; + } else { + MOD_INC_USE_COUNT; + pcmcia_socket[sock].handler = handler; + pcmcia_socket[sock].handler_info = info; + } + return 0; +} + + +/* + * bcm47xx_pcmcia_inquire_socket() + * + * Implements the inquire_socket() operation for the in-kernel PCMCIA + * service (formerly SS_InquireSocket in Card Services). Of note is + * the setting of the SS_CAP_PAGE_REGS bit in the `features' field of + * `cap' to "trick" Card Services into tolerating large "I/O memory" + * addresses. Also set is SS_CAP_STATIC_MAP, which disables the memory + * resource database check. (Mapped memory is set up within the socket + * driver itself.) + * + * In conjunction with the STATIC_MAP capability is a new field, + * `io_offset', recommended by David Hinds. Rather than go through + * the SetIOMap interface (which is not quite suited for communicating + * window locations up from the socket driver), we just pass up + * an offset which is applied to client-requested base I/O addresses + * in alloc_io_space(). + * + * Returns: 0 on success, -1 if no pin has been configured for `sock' + */ +static int +bcm47xx_pcmcia_inquire_socket(unsigned int sock, socket_cap_t *cap) +{ + struct pcmcia_irq_info irq_info; + + if (sock >= socket_count) { + printk(KERN_ERR "bcm47xx: socket %u not configured\n", sock); + return -1; + } + + /* SS_CAP_PAGE_REGS: used by setup_cis_mem() in cistpl.c to set the + * force_low argument to validate_mem() in rsrc_mgr.c -- since in + * general, the mapped * addresses of the PCMCIA memory regions + * will not be within 0xffff, setting force_low would be + * undesirable. + * + * SS_CAP_STATIC_MAP: don't bother with the (user-configured) memory + * resource database; we instead pass up physical address ranges + * and allow other parts of Card Services to deal with remapping. + * + * SS_CAP_PCCARD: we can deal with 16-bit PCMCIA & CF cards, but + * not 32-bit CardBus devices. + */ + cap->features = (SS_CAP_PAGE_REGS | SS_CAP_STATIC_MAP | SS_CAP_PCCARD); + + irq_info.sock = sock; + irq_info.irq = -1; + + if (pcmcia_low_level->get_irq_info(&irq_info) < 0) { + printk(KERN_ERR "Error obtaining IRQ info socket %u\n", sock); + return -1; + } + + cap->irq_mask = 0; + cap->map_size = PAGE_SIZE; + cap->pci_irq = irq_info.irq; + cap->io_offset = pcmcia_socket[sock].virt_io; + + return 0; +} + + +/* + * bcm47xx_pcmcia_get_status() + * + * Implements the get_status() operation for the in-kernel PCMCIA + * service (formerly SS_GetStatus in Card Services). Essentially just + * fills in bits in `status' according to internal driver state or + * the value of the voltage detect chipselect register. + * + * As a debugging note, during card startup, the PCMCIA core issues + * three set_socket() commands in a row the first with RESET deasserted, + * the second with RESET asserted, and the last with RESET deasserted + * again. Following the third set_socket(), a get_status() command will + * be issued. The kernel is looking for the SS_READY flag (see + * setup_socket(), reset_socket(), and unreset_socket() in cs.c). + * + * Returns: 0 + */ +static int +bcm47xx_pcmcia_get_status(unsigned int sock, unsigned int *status) +{ + struct pcmcia_state state; + + + if ((pcmcia_low_level->socket_state(sock, &state)) < 0) { + printk(KERN_ERR "Unable to get PCMCIA status from kernel.\n"); + return -1; + } + + pcmcia_socket[sock].k_state = state; + + *status = state.detect ? SS_DETECT : 0; + + *status |= state.ready ? SS_READY : 0; + + /* The power status of individual sockets is not available + * explicitly from the hardware, so we just remember the state + * and regurgitate it upon request: + */ + *status |= pcmcia_socket[sock].cs_state.Vcc ? SS_POWERON : 0; + + if (pcmcia_socket[sock].cs_state.flags & SS_IOCARD) + *status |= state.bvd1 ? SS_STSCHG : 0; + else { + if (state.bvd1 == 0) + *status |= SS_BATDEAD; + else if (state.bvd2 == 0) + *status |= SS_BATWARN; + } + + *status |= state.vs_3v ? SS_3VCARD : 0; + + *status |= state.vs_Xv ? SS_XVCARD : 0; + + DEBUG(2, "\tstatus: %s%s%s%s%s%s%s%s\n", + (*status&SS_DETECT)?"DETECT ":"", + (*status&SS_READY)?"READY ":"", + (*status&SS_BATDEAD)?"BATDEAD ":"", + (*status&SS_BATWARN)?"BATWARN ":"", + (*status&SS_POWERON)?"POWERON ":"", + (*status&SS_STSCHG)?"STSCHG ":"", + (*status&SS_3VCARD)?"3VCARD ":"", + (*status&SS_XVCARD)?"XVCARD ":""); + + return 0; +} + + +/* + * bcm47xx_pcmcia_get_socket() + * + * Implements the get_socket() operation for the in-kernel PCMCIA + * service (formerly SS_GetSocket in Card Services). Not a very + * exciting routine. + * + * Returns: 0 + */ +static int +bcm47xx_pcmcia_get_socket(unsigned int sock, socket_state_t *state) +{ + DEBUG(2, "%s() for sock %u\n", __FUNCTION__, sock); + + /* This information was given to us in an earlier call to set_socket(), + * so we're just regurgitating it here: + */ + *state = pcmcia_socket[sock].cs_state; + return 0; +} + + +/* + * bcm47xx_pcmcia_set_socket() + * + * Implements the set_socket() operation for the in-kernel PCMCIA + * service (formerly SS_SetSocket in Card Services). We more or + * less punt all of this work and let the kernel handle the details + * of power configuration, reset, &c. We also record the value of + * `state' in order to regurgitate it to the PCMCIA core later. + * + * Returns: 0 + */ +static int +bcm47xx_pcmcia_set_socket(unsigned int sock, socket_state_t *state) +{ + struct pcmcia_configure configure; + + DEBUG(2, "\tmask: %s%s%s%s%s%s\n\tflags: %s%s%s%s%s%s\n" + "\tVcc %d Vpp %d irq %d\n", + (state->csc_mask == 0) ? "" : "", + (state->csc_mask & SS_DETECT) ? "DETECT " : "", + (state->csc_mask & SS_READY) ? "READY " : "", + (state->csc_mask & SS_BATDEAD) ? "BATDEAD " : "", + (state->csc_mask & SS_BATWARN) ? "BATWARN " : "", + (state->csc_mask & SS_STSCHG) ? "STSCHG " : "", + (state->flags == 0) ? "" : "", + (state->flags & SS_PWR_AUTO) ? "PWR_AUTO " : "", + (state->flags & SS_IOCARD) ? "IOCARD " : "", + (state->flags & SS_RESET) ? "RESET " : "", + (state->flags & SS_SPKR_ENA) ? "SPKR_ENA " : "", + (state->flags & SS_OUTPUT_ENA) ? "OUTPUT_ENA " : "", + state->Vcc, state->Vpp, state->io_irq); + + configure.sock = sock; + configure.vcc = state->Vcc; + configure.vpp = state->Vpp; + configure.output = (state->flags & SS_OUTPUT_ENA) ? 1 : 0; + configure.speaker = (state->flags & SS_SPKR_ENA) ? 1 : 0; + configure.reset = (state->flags & SS_RESET) ? 1 : 0; + + if (pcmcia_low_level->configure_socket(&configure) < 0) { + printk(KERN_ERR "Unable to configure socket %u\n", sock); + return -1; + } + + pcmcia_socket[sock].cs_state = *state; + return 0; +} + + +/* + * bcm47xx_pcmcia_get_io_map() + * + * Implements the get_io_map() operation for the in-kernel PCMCIA + * service (formerly SS_GetIOMap in Card Services). Just returns an + * I/O map descriptor which was assigned earlier by a set_io_map(). + * + * Returns: 0 on success, -1 if the map index was out of range + */ +static int +bcm47xx_pcmcia_get_io_map(unsigned int sock, struct pccard_io_map *map) +{ + DEBUG(2, "bcm47xx_pcmcia_get_io_map: sock %d\n", sock); + + if (map->map >= MAX_IO_WIN) { + printk(KERN_ERR "%s(): map (%d) out of range\n", + __FUNCTION__, map->map); + return -1; + } + + *map = pcmcia_socket[sock].io_map[map->map]; + return 0; +} + + +/* + * bcm47xx_pcmcia_set_io_map() + * + * Implements the set_io_map() operation for the in-kernel PCMCIA + * service (formerly SS_SetIOMap in Card Services). We configure + * the map speed as requested, but override the address ranges + * supplied by Card Services. + * + * Returns: 0 on success, -1 on error + */ +int +bcm47xx_pcmcia_set_io_map(unsigned int sock, struct pccard_io_map *map) +{ + unsigned int speed; + unsigned long start; + + DEBUG(2, "\tmap %u speed %u\n\tstart 0x%08lx stop 0x%08lx\n" + "\tflags: %s%s%s%s%s%s%s%s\n", + map->map, map->speed, map->start, map->stop, + (map->flags == 0) ? "" : "", + (map->flags & MAP_ACTIVE) ? "ACTIVE " : "", + (map->flags & MAP_16BIT) ? "16BIT " : "", + (map->flags & MAP_AUTOSZ) ? "AUTOSZ " : "", + (map->flags & MAP_0WS) ? "0WS " : "", + (map->flags & MAP_WRPROT) ? "WRPROT " : "", + (map->flags & MAP_USE_WAIT) ? "USE_WAIT " : "", + (map->flags & MAP_PREFETCH) ? "PREFETCH " : ""); + + if (map->map >= MAX_IO_WIN) { + printk(KERN_ERR "%s(): map (%d) out of range\n", + __FUNCTION__, map->map); + return -1; + } + + if (map->flags & MAP_ACTIVE) { + speed = (map->speed > 0) ? map->speed : BCM47XX_PCMCIA_IO_SPEED; + pcmcia_socket[sock].speed_io = speed; + } + + start = map->start; + + if (map->stop == 1) { + map->stop = PAGE_SIZE - 1; + } + + map->start = pcmcia_socket[sock].virt_io; + map->stop = map->start + (map->stop - start); + pcmcia_socket[sock].io_map[map->map] = *map; + DEBUG(2, "set_io_map %d start %x stop %x\n", + map->map, map->start, map->stop); + return 0; +} + + +/* + * bcm47xx_pcmcia_get_mem_map() + * + * Implements the get_mem_map() operation for the in-kernel PCMCIA + * service (formerly SS_GetMemMap in Card Services). Just returns a + * memory map descriptor which was assigned earlier by a + * set_mem_map() request. + * + * Returns: 0 on success, -1 if the map index was out of range + */ +static int +bcm47xx_pcmcia_get_mem_map(unsigned int sock, struct pccard_mem_map *map) +{ + DEBUG(2, "%s() for sock %u\n", __FUNCTION__, sock); + + if (map->map >= MAX_WIN) { + printk(KERN_ERR "%s(): map (%d) out of range\n", + __FUNCTION__, map->map); + return -1; + } + + *map = pcmcia_socket[sock].mem_map[map->map]; + return 0; +} + + +/* + * bcm47xx_pcmcia_set_mem_map() + * + * Implements the set_mem_map() operation for the in-kernel PCMCIA + * service (formerly SS_SetMemMap in Card Services). We configure + * the map speed as requested, but override the address ranges + * supplied by Card Services. + * + * Returns: 0 on success, -1 on error + */ +static int +bcm47xx_pcmcia_set_mem_map(unsigned int sock, struct pccard_mem_map *map) +{ + unsigned int speed; + unsigned long start; + u_long flags; + + if (map->map >= MAX_WIN) { + printk(KERN_ERR "%s(): map (%d) out of range\n", + __FUNCTION__, map->map); + return -1; + } + + DEBUG(2, "\tmap %u speed %u\n\tsys_start %#lx\n" + "\tsys_stop %#lx\n\tcard_start %#x\n" + "\tflags: %s%s%s%s%s%s%s%s\n", + map->map, map->speed, map->sys_start, map->sys_stop, + map->card_start, (map->flags == 0) ? "" : "", + (map->flags & MAP_ACTIVE) ? "ACTIVE " : "", + (map->flags & MAP_16BIT) ? "16BIT " : "", + (map->flags & MAP_AUTOSZ) ? "AUTOSZ " : "", + (map->flags & MAP_0WS) ? "0WS " : "", + (map->flags & MAP_WRPROT) ? "WRPROT " : "", + (map->flags & MAP_ATTRIB) ? "ATTRIB " : "", + (map->flags & MAP_USE_WAIT) ? "USE_WAIT " : ""); + + if (map->flags & MAP_ACTIVE) { + /* When clients issue RequestMap, the access speed is not always + * properly configured: + */ + speed = (map->speed > 0) ? map->speed : BCM47XX_PCMCIA_MEM_SPEED; + + /* TBD */ + if (map->flags & MAP_ATTRIB) { + pcmcia_socket[sock].speed_attr = speed; + } else { + pcmcia_socket[sock].speed_mem = speed; + } + } + + save_flags(flags); + cli(); + start = map->sys_start; + + if (map->sys_stop == 0) + map->sys_stop = PAGE_SIZE - 1; + + if (map->flags & MAP_ATTRIB) { + map->sys_start = pcmcia_socket[sock].phys_attr + + map->card_start; + } else { + map->sys_start = pcmcia_socket[sock].phys_mem + + map->card_start; + } + + map->sys_stop = map->sys_start + (map->sys_stop - start); + pcmcia_socket[sock].mem_map[map->map] = *map; + restore_flags(flags); + DEBUG(2, "set_mem_map %d start %x stop %x card_start %x\n", + map->map, map->sys_start, map->sys_stop, + map->card_start); + return 0; +} + + +#if defined(CONFIG_PROC_FS) + +/* + * bcm47xx_pcmcia_proc_setup() + * + * Implements the proc_setup() operation for the in-kernel PCMCIA + * service (formerly SS_ProcSetup in Card Services). + * + * Returns: 0 on success, -1 on error + */ +static void +bcm47xx_pcmcia_proc_setup(unsigned int sock, struct proc_dir_entry *base) +{ + struct proc_dir_entry *entry; + + if ((entry = create_proc_entry("status", 0, base)) == NULL) { + printk(KERN_ERR "Unable to install \"status\" procfs entry\n"); + return; + } + + entry->read_proc = bcm47xx_pcmcia_proc_status; + entry->data = (void *)sock; +} + + +/* + * bcm47xx_pcmcia_proc_status() + * + * Implements the /proc/bus/pccard/??/status file. + * + * Returns: the number of characters added to the buffer + */ +static int +bcm47xx_pcmcia_proc_status(char *buf, char **start, off_t pos, + int count, int *eof, void *data) +{ + char *p = buf; + unsigned int sock = (unsigned int)data; + + p += sprintf(p, "k_flags : %s%s%s%s%s%s%s\n", + pcmcia_socket[sock].k_state.detect ? "detect " : "", + pcmcia_socket[sock].k_state.ready ? "ready " : "", + pcmcia_socket[sock].k_state.bvd1 ? "bvd1 " : "", + pcmcia_socket[sock].k_state.bvd2 ? "bvd2 " : "", + pcmcia_socket[sock].k_state.wrprot ? "wrprot " : "", + pcmcia_socket[sock].k_state.vs_3v ? "vs_3v " : "", + pcmcia_socket[sock].k_state.vs_Xv ? "vs_Xv " : ""); + + p += sprintf(p, "status : %s%s%s%s%s%s%s%s%s\n", + pcmcia_socket[sock].k_state.detect ? "SS_DETECT " : "", + pcmcia_socket[sock].k_state.ready ? "SS_READY " : "", + pcmcia_socket[sock].cs_state.Vcc ? "SS_POWERON " : "", + pcmcia_socket[sock].cs_state.flags & SS_IOCARD ? "SS_IOCARD " : "", + (pcmcia_socket[sock].cs_state.flags & SS_IOCARD && + pcmcia_socket[sock].k_state.bvd1) ? "SS_STSCHG " : "", + ((pcmcia_socket[sock].cs_state.flags & SS_IOCARD) == 0 && + (pcmcia_socket[sock].k_state.bvd1 == 0)) ? "SS_BATDEAD " : "", + ((pcmcia_socket[sock].cs_state.flags & SS_IOCARD) == 0 && + (pcmcia_socket[sock].k_state.bvd2 == 0)) ? "SS_BATWARN " : "", + pcmcia_socket[sock].k_state.vs_3v ? "SS_3VCARD " : "", + pcmcia_socket[sock].k_state.vs_Xv ? "SS_XVCARD " : ""); + + p += sprintf(p, "mask : %s%s%s%s%s\n", + pcmcia_socket[sock].cs_state.csc_mask & SS_DETECT ? "SS_DETECT " : "", + pcmcia_socket[sock].cs_state.csc_mask & SS_READY ? "SS_READY " : "", + pcmcia_socket[sock].cs_state.csc_mask & SS_BATDEAD ? "SS_BATDEAD " : "", + pcmcia_socket[sock].cs_state.csc_mask & SS_BATWARN ? "SS_BATWARN " : "", + pcmcia_socket[sock].cs_state.csc_mask & SS_STSCHG ? "SS_STSCHG " : ""); + + p += sprintf(p, "cs_flags : %s%s%s%s%s\n", + pcmcia_socket[sock].cs_state.flags & SS_PWR_AUTO ? + "SS_PWR_AUTO " : "", + pcmcia_socket[sock].cs_state.flags & SS_IOCARD ? + "SS_IOCARD " : "", + pcmcia_socket[sock].cs_state.flags & SS_RESET ? + "SS_RESET " : "", + pcmcia_socket[sock].cs_state.flags & SS_SPKR_ENA ? + "SS_SPKR_ENA " : "", + pcmcia_socket[sock].cs_state.flags & SS_OUTPUT_ENA ? + "SS_OUTPUT_ENA " : ""); + + p += sprintf(p, "Vcc : %d\n", pcmcia_socket[sock].cs_state.Vcc); + p += sprintf(p, "Vpp : %d\n", pcmcia_socket[sock].cs_state.Vpp); + p += sprintf(p, "irq : %d\n", pcmcia_socket[sock].cs_state.io_irq); + p += sprintf(p, "I/O : %u\n", pcmcia_socket[sock].speed_io); + p += sprintf(p, "attribute: %u\n", pcmcia_socket[sock].speed_attr); + p += sprintf(p, "common : %u\n", pcmcia_socket[sock].speed_mem); + return p-buf; +} + + +#endif /* defined(CONFIG_PROC_FS) */ --- /dev/null 2004-04-06 13:56:48.000000000 -0400 +++ linux-2.4.20/drivers/pcmcia/bcm4710_pcmcia.c 2005-01-07 05:39:02.000000000 -0500 @@ -0,0 +1,266 @@ +/* + * BCM4710 specific pcmcia routines. + * + * Copyright 2004, Broadcom Corporation + * All Rights Reserved. + * + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. + * + * $Id: bcm4710_pcmcia.c,v 1.1.1.7 2004/04/12 04:32:07 honor Exp $ + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include "cs_internal.h" + +#include +#include +#include + + +#include +#include +#include +#include +#include + +#include "bcm4710pcmcia.h" + +/* Use a static var for irq dev_id */ +static int bcm47xx_pcmcia_dev_id; + +/* Do we think we have a card or not? */ +static int bcm47xx_pcmcia_present = 0; + + +static void bcm4710_pcmcia_reset(void) +{ + extifregs_t *eir; + unsigned long s; + uint32 out0, out1, outen; + + + eir = (extifregs_t *) ioremap_nocache(BCM4710_REG_EXTIF, sizeof(extifregs_t)); + + save_and_cli(s); + + /* Use gpio7 to reset the pcmcia slot */ + outen = readl(&eir->gpio[0].outen); + outen |= BCM47XX_PCMCIA_RESET; + out0 = readl(&eir->gpio[0].out); + out0 &= ~(BCM47XX_PCMCIA_RESET); + out1 = out0 | BCM47XX_PCMCIA_RESET; + + writel(out0, &eir->gpio[0].out); + writel(outen, &eir->gpio[0].outen); + mdelay(1); + writel(out1, &eir->gpio[0].out); + mdelay(1); + writel(out0, &eir->gpio[0].out); + + restore_flags(s); +} + + +static int bcm4710_pcmcia_init(struct pcmcia_init *init) +{ + struct pci_dev *pdev; + extifregs_t *eir; + uint32 outen, intp, intm, tmp; + uint16 *attrsp; + int rc = 0, i; + extern unsigned long bcm4710_cpu_cycle; + + + if (!(pdev = pci_find_device(VENDOR_BROADCOM, SB_EXTIF, NULL))) { + printk(KERN_ERR "bcm4710_pcmcia: extif not found\n"); + return -ENODEV; + } + eir = (extifregs_t *) ioremap_nocache(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0)); + + /* Initialize the pcmcia i/f: 16bit no swap */ + writel(CF_EM_PCMCIA | CF_DS | CF_EN, &eir->pcmcia_config); + +#ifdef notYet + + /* Set the timing for memory accesses */ + tmp = (19 / bcm4710_cpu_cycle) << 24; /* W3 = 10nS */ + tmp = tmp | ((29 / bcm4710_cpu_cycle) << 16); /* W2 = 20nS */ + tmp = tmp | ((109 / bcm4710_cpu_cycle) << 8); /* W1 = 100nS */ + tmp = tmp | (129 / bcm4710_cpu_cycle); /* W0 = 120nS */ + writel(tmp, &eir->pcmcia_memwait); /* 0x01020a0c for a 100Mhz clock */ + + /* Set the timing for I/O accesses */ + tmp = (19 / bcm4710_cpu_cycle) << 24; /* W3 = 10nS */ + tmp = tmp | ((29 / bcm4710_cpu_cycle) << 16); /* W2 = 20nS */ + tmp = tmp | ((109 / bcm4710_cpu_cycle) << 8); /* W1 = 100nS */ + tmp = tmp | (129 / bcm4710_cpu_cycle); /* W0 = 120nS */ + writel(tmp, &eir->pcmcia_iowait); /* 0x01020a0c for a 100Mhz clock */ + + /* Set the timing for attribute accesses */ + tmp = (19 / bcm4710_cpu_cycle) << 24; /* W3 = 10nS */ + tmp = tmp | ((29 / bcm4710_cpu_cycle) << 16); /* W2 = 20nS */ + tmp = tmp | ((109 / bcm4710_cpu_cycle) << 8); /* W1 = 100nS */ + tmp = tmp | (129 / bcm4710_cpu_cycle); /* W0 = 120nS */ + writel(tmp, &eir->pcmcia_attrwait); /* 0x01020a0c for a 100Mhz clock */ + +#endif + /* Make sure gpio0 and gpio5 are inputs */ + outen = readl(&eir->gpio[0].outen); + outen &= ~(BCM47XX_PCMCIA_WP | BCM47XX_PCMCIA_STSCHG | BCM47XX_PCMCIA_RESET); + writel(outen, &eir->gpio[0].outen); + + /* Issue a reset to the pcmcia socket */ + bcm4710_pcmcia_reset(); + +#ifdef DO_BCM47XX_PCMCIA_INTERRUPTS + /* Setup gpio5 to be the STSCHG interrupt */ + intp = readl(&eir->gpiointpolarity); + writel(intp | BCM47XX_PCMCIA_STSCHG, &eir->gpiointpolarity); /* Active low */ + intm = readl(&eir->gpiointmask); + writel(intm | BCM47XX_PCMCIA_STSCHG, &eir->gpiointmask); /* Enable it */ +#endif + + DEBUG(2, "bcm4710_pcmcia after reset:\n"); + DEBUG(2, "\textstatus\t= 0x%08x:\n", readl(&eir->extstatus)); + DEBUG(2, "\tpcmcia_config\t= 0x%08x:\n", readl(&eir->pcmcia_config)); + DEBUG(2, "\tpcmcia_memwait\t= 0x%08x:\n", readl(&eir->pcmcia_memwait)); + DEBUG(2, "\tpcmcia_attrwait\t= 0x%08x:\n", readl(&eir->pcmcia_attrwait)); + DEBUG(2, "\tpcmcia_iowait\t= 0x%08x:\n", readl(&eir->pcmcia_iowait)); + DEBUG(2, "\tgpioin\t\t= 0x%08x:\n", readl(&eir->gpioin)); + DEBUG(2, "\tgpio_outen0\t= 0x%08x:\n", readl(&eir->gpio[0].outen)); + DEBUG(2, "\tgpio_out0\t= 0x%08x:\n", readl(&eir->gpio[0].out)); + DEBUG(2, "\tgpiointpolarity\t= 0x%08x:\n", readl(&eir->gpiointpolarity)); + DEBUG(2, "\tgpiointmask\t= 0x%08x:\n", readl(&eir->gpiointmask)); + +#ifdef DO_BCM47XX_PCMCIA_INTERRUPTS + /* Request pcmcia interrupt */ + rc = request_irq(BCM47XX_PCMCIA_IRQ, init->handler, SA_INTERRUPT, + "PCMCIA Interrupt", &bcm47xx_pcmcia_dev_id); +#endif + + attrsp = (uint16 *)ioremap_nocache(EXTIF_PCMCIA_CFGBASE(BCM4710_EXTIF), 0x1000); + tmp = readw(&attrsp[0]); + DEBUG(2, "\tattr[0] = 0x%04x\n", tmp); + if ((tmp == 0x7fff) || (tmp == 0x7f00)) { + bcm47xx_pcmcia_present = 0; + } else { + bcm47xx_pcmcia_present = 1; + } + + /* There's only one socket */ + return 1; +} + +static int bcm4710_pcmcia_shutdown(void) +{ + extifregs_t *eir; + uint32 intm; + + eir = (extifregs_t *) ioremap_nocache(BCM4710_REG_EXTIF, sizeof(extifregs_t)); + + /* Disable the pcmcia i/f */ + writel(0, &eir->pcmcia_config); + + /* Reset gpio's */ + intm = readl(&eir->gpiointmask); + writel(intm & ~BCM47XX_PCMCIA_STSCHG, &eir->gpiointmask); /* Disable it */ + + free_irq(BCM47XX_PCMCIA_IRQ, &bcm47xx_pcmcia_dev_id); + + return 0; +} + +static int +bcm4710_pcmcia_socket_state(unsigned sock, struct pcmcia_state *state) +{ + extifregs_t *eir; + + eir = (extifregs_t *) ioremap_nocache(BCM4710_REG_EXTIF, sizeof(extifregs_t)); + + + if (sock != 0) { + printk(KERN_ERR "bcm4710 socket_state bad sock %d\n", sock); + return -1; + } + + if (bcm47xx_pcmcia_present) { + state->detect = 1; + state->ready = 1; + state->bvd1 = 1; + state->bvd2 = 1; + state->wrprot = (readl(&eir->gpioin) & BCM47XX_PCMCIA_WP) == BCM47XX_PCMCIA_WP; + state->vs_3v = 0; + state->vs_Xv = 0; + } else { + state->detect = 0; + state->ready = 0; + } + + return 1; +} + + +static int bcm4710_pcmcia_get_irq_info(struct pcmcia_irq_info *info) +{ + if (info->sock >= BCM47XX_PCMCIA_MAX_SOCK) return -1; + + info->irq = BCM47XX_PCMCIA_IRQ; + + return 0; +} + + +static int +bcm4710_pcmcia_configure_socket(const struct pcmcia_configure *configure) +{ + if (configure->sock >= BCM47XX_PCMCIA_MAX_SOCK) return -1; + + + DEBUG(2, "Vcc %dV Vpp %dV output %d speaker %d reset %d\n", configure->vcc, + configure->vpp, configure->output, configure->speaker, configure->reset); + + if ((configure->vcc != 50) || (configure->vpp != 50)) { + printk("%s: bad Vcc/Vpp (%d:%d)\n", __FUNCTION__, configure->vcc, + configure->vpp); + } + + if (configure->reset) { + /* Issue a reset to the pcmcia socket */ + DEBUG(1, "%s: Reseting socket\n", __FUNCTION__); + bcm4710_pcmcia_reset(); + } + + + return 0; +} + +struct pcmcia_low_level bcm4710_pcmcia_ops = { + bcm4710_pcmcia_init, + bcm4710_pcmcia_shutdown, + bcm4710_pcmcia_socket_state, + bcm4710_pcmcia_get_irq_info, + bcm4710_pcmcia_configure_socket +}; + --- /dev/null 2004-04-06 13:56:48.000000000 -0400 +++ linux-2.4.20/drivers/pcmcia/bcm4710pcmcia.h 2005-01-07 05:39:02.000000000 -0500 @@ -0,0 +1,118 @@ +/* + * + * bcm47xx pcmcia driver + * + * Copyright 2004, Broadcom Corporation + * All Rights Reserved. + * + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. + * + * Based on sa1100.h and include/asm-arm/arch-sa1100/pcmica.h + * from www.handhelds.org, + * and au1000_generic.c from oss.sgi.com. + * + * $Id: bcm4710pcmcia.h,v 1.1.1.7 2004/04/12 04:32:07 honor Exp $ + */ + +#if !defined(_BCM4710PCMCIA_H) +#define _BCM4710PCMCIA_H + +#include +#include +#include +#include +#include "cs_internal.h" + + +/* The 47xx can only support one socket */ +#define BCM47XX_PCMCIA_MAX_SOCK 1 + +/* In the bcm947xx gpio's are used for some pcmcia functions */ +#define BCM47XX_PCMCIA_WP 0x01 /* Bit 0 is WP input */ +#define BCM47XX_PCMCIA_STSCHG 0x20 /* Bit 5 is STSCHG input/interrupt */ +#define BCM47XX_PCMCIA_RESET 0x80 /* Bit 7 is RESET */ + +#define BCM47XX_PCMCIA_IRQ 2 + +/* The socket driver actually works nicely in interrupt-driven form, + * so the (relatively infrequent) polling is "just to be sure." + */ +#define BCM47XX_PCMCIA_POLL_PERIOD (2 * HZ) + +#define BCM47XX_PCMCIA_IO_SPEED (255) +#define BCM47XX_PCMCIA_MEM_SPEED (300) + + +struct pcmcia_state { + unsigned detect: 1, + ready: 1, + bvd1: 1, + bvd2: 1, + wrprot: 1, + vs_3v: 1, + vs_Xv: 1; +}; + + +struct pcmcia_configure { + unsigned sock: 8, + vcc: 8, + vpp: 8, + output: 1, + speaker: 1, + reset: 1; +}; + +struct pcmcia_irq_info { + unsigned int sock; + unsigned int irq; +}; + +/* This structure encapsulates per-socket state which we might need to + * use when responding to a Card Services query of some kind. + */ +struct bcm47xx_pcmcia_socket { + socket_state_t cs_state; + struct pcmcia_state k_state; + unsigned int irq; + void (*handler)(void *, unsigned int); + void *handler_info; + pccard_io_map io_map[MAX_IO_WIN]; + pccard_mem_map mem_map[MAX_WIN]; + ioaddr_t virt_io, phys_attr, phys_mem; + unsigned short speed_io, speed_attr, speed_mem; +}; + +struct pcmcia_init { + void (*handler)(int irq, void *dev, struct pt_regs *regs); +}; + +struct pcmcia_low_level { + int (*init)(struct pcmcia_init *); + int (*shutdown)(void); + int (*socket_state)(unsigned sock, struct pcmcia_state *); + int (*get_irq_info)(struct pcmcia_irq_info *); + int (*configure_socket)(const struct pcmcia_configure *); +}; + +extern struct pcmcia_low_level bcm47xx_pcmcia_ops; + +/* I/O pins replacing memory pins + * (PCMCIA System Architecture, 2nd ed., by Don Anderson, p.75) + * + * These signals change meaning when going from memory-only to + * memory-or-I/O interface: + */ +#define iostschg bvd1 +#define iospkr bvd2 + + +/* + * Declaration for implementation specific low_level operations. + */ +extern struct pcmcia_low_level bcm4710_pcmcia_ops; + +#endif /* !defined(_BCM4710PCMCIA_H) */ --- linux-2.4.20/include/asm-mips/asm.h~2.4.20_broadcom_3_37_2_1109_US.patch 2005-01-07 05:39:02.000000000 -0500 +++ linux-2.4.20/include/asm-mips/asm.h 2005-01-08 12:10:12.593676448 -0500 @@ -387,4 +387,16 @@ #define SSNOP sll zero,zero,1 +/* + * mips32/64 has some extra CP0 register selected by the low bits of + * the mfc0/mtc0 instruction. Note that dst and src CANNOT have '$' + * signs in them. + */ +#define MFC0_SEL(dst, src, sel)\ + .word (0x40000000 | ((dst)<<16) | ((src)<<11) | (sel)) + + +#define MTC0_SEL(dst, src, sel)\ + .word (0x40800000 | ((dst)<<16) | ((src)<<11) | (sel)) + #endif /* __ASM_ASM_H */ --- /dev/null 2004-04-06 13:56:48.000000000 -0400 +++ linux-2.4.20/include/asm-mips/bcm4710_cache.h 2005-01-07 05:39:02.000000000 -0500 @@ -0,0 +1,229 @@ + +#ifndef _MIPS_R4KCACHE_H +#define _MIPS_R4KCACHE_H + +#include +#include + +#include +#include +#include +#include +#define BCM4710_DUMMY_RREG() (((sbconfig_t *)(KSEG1ADDR(BCM4710_REG_SDRAM + SBCONFIGOFF)))->sbimstate) +#define BCM4710_FILL_TLB(addr) (*(volatile unsigned long *)(addr)) +#define BCM4710_PROTECTED_FILL_TLB(addr) ({ unsigned long x; get_dbe(x, (volatile unsigned long *)(addr)); }) + +static inline void flush_icache_line_indexed(unsigned long addr) +{ + unsigned long waystep = icache_size/mips_cpu.icache.ways; + unsigned int way; + + for (way = 0; way < mips_cpu.icache.ways; way++) + { + __asm__ __volatile__( + ".set noreorder\n\t" + ".set mips3\n\t" + "cache %1, (%0)\n\t" + ".set mips0\n\t" + ".set reorder" + : + : "r" (addr), + "i" (Index_Invalidate_I)); + + addr += waystep; + } +} + +static inline void flush_dcache_line_indexed(unsigned long addr) +{ + unsigned long waystep = dcache_size/mips_cpu.dcache.ways; + unsigned int way; + + for (way = 0; way < mips_cpu.dcache.ways; way++) + { + BCM4710_DUMMY_RREG(); + __asm__ __volatile__( + ".set noreorder\n\t" + ".set mips3\n\t" + "cache %1, (%0)\n\t" + ".set mips0\n\t" + ".set reorder" + : + : "r" (addr), + "i" (Index_Writeback_Inv_D)); + + addr += waystep; + } +} + +static inline void flush_icache_line(unsigned long addr) +{ + + __asm__ __volatile__( + ".set noreorder\n\t" + ".set mips3\n\t" + "cache %1, (%0)\n\t" + ".set mips0\n\t" + ".set reorder" + : + : "r" (addr), + "i" (Hit_Invalidate_I)); +} + +static inline void flush_dcache_line(unsigned long addr) +{ + BCM4710_DUMMY_RREG(); + __asm__ __volatile__( + ".set noreorder\n\t" + ".set mips3\n\t" + "cache %1, (%0)\n\t" + ".set mips0\n\t" + ".set reorder" + : + : "r" (addr), + "i" (Hit_Writeback_Inv_D)); +} + +static inline void invalidate_dcache_line(unsigned long addr) +{ + __asm__ __volatile__( + ".set noreorder\n\t" + ".set mips3\n\t" + "cache %1, (%0)\n\t" + ".set mips0\n\t" + ".set reorder" + : + : "r" (addr), + "i" (Hit_Invalidate_D)); +} + +/* + * The next two are for badland addresses like signal trampolines. + */ +static inline void protected_flush_icache_line(unsigned long addr) +{ + __asm__ __volatile__( + ".set noreorder\n\t" + ".set mips3\n" + "1:\tcache %1,(%0)\n" + "2:\t.set mips0\n\t" + ".set reorder\n\t" + ".section\t__ex_table,\"a\"\n\t" + STR(PTR)"\t1b,2b\n\t" + ".previous" + : + : "r" (addr), + "i" (Hit_Invalidate_I)); +} + +static inline void protected_writeback_dcache_line(unsigned long addr) +{ + BCM4710_DUMMY_RREG(); + __asm__ __volatile__( + ".set noreorder\n\t" + ".set mips3\n" + "1:\tcache %1,(%0)\n" + "2:\t.set mips0\n\t" + ".set reorder\n\t" + ".section\t__ex_table,\"a\"\n\t" + STR(PTR)"\t1b,2b\n\t" + ".previous" + : + : "r" (addr), + "i" (Hit_Writeback_D)); +} + +#define cache_unroll(base,op) \ + __asm__ __volatile__(" \ + .set noreorder; \ + .set mips3; \ + cache %1, (%0); \ + .set mips0; \ + .set reorder" \ + : \ + : "r" (base), \ + "i" (op)); + + +static inline void blast_dcache(void) +{ + unsigned long start = KSEG0; + unsigned long end = (start + dcache_size); + + while(start < end) { + BCM4710_DUMMY_RREG(); + cache_unroll(start,Index_Writeback_Inv_D); + start += dc_lsize; + } +} + +static inline void blast_dcache_page(unsigned long page) +{ + unsigned long start = page; + unsigned long end = (start + PAGE_SIZE); + + BCM4710_FILL_TLB(start); + while(start < end) { + BCM4710_DUMMY_RREG(); + cache_unroll(start,Hit_Writeback_Inv_D); + start += dc_lsize; + } +} + +static inline void blast_dcache_page_indexed(unsigned long page) +{ + unsigned long start; + unsigned long end = (page + PAGE_SIZE); + unsigned long waystep = dcache_size/mips_cpu.dcache.ways; + unsigned int way; + + for (way = 0; way < mips_cpu.dcache.ways; way++) { + start = page + way*waystep; + while(start < end) { + BCM4710_DUMMY_RREG(); + cache_unroll(start,Index_Writeback_Inv_D); + start += dc_lsize; + } + } +} + +static inline void blast_icache(void) +{ + unsigned long start = KSEG0; + unsigned long end = (start + icache_size); + + while(start < end) { + cache_unroll(start,Index_Invalidate_I); + start += ic_lsize; + } +} + +static inline void blast_icache_page(unsigned long page) +{ + unsigned long start = page; + unsigned long end = (start + PAGE_SIZE); + + BCM4710_FILL_TLB(start); + while(start < end) { + cache_unroll(start,Hit_Invalidate_I); + start += ic_lsize; + } +} + +static inline void blast_icache_page_indexed(unsigned long page) +{ + unsigned long start; + unsigned long end = (page + PAGE_SIZE); + unsigned long waystep = icache_size/mips_cpu.icache.ways; + unsigned int way; + + for (way = 0; way < mips_cpu.icache.ways; way++) { + start = page + way*waystep; + while(start < end) { + cache_unroll(start,Index_Invalidate_I); + start += ic_lsize; + } + } +} + +#endif /* !(_MIPS_R4KCACHE_H) */ --- linux-2.4.20/include/asm-mips/bootinfo.h~2.4.20_broadcom_3_37_2_1109_US.patch 2005-01-07 05:39:02.000000000 -0500 +++ linux-2.4.20/include/asm-mips/bootinfo.h 2005-01-08 12:17:06.878695552 -0500 @@ -36,6 +36,7 @@ #define MACH_GROUP_NEC_VR41XX 19 /* NEC Vr41xx based boards/gadgets */ #define MACH_GROUP_HP_LJ 20 /* Hewlett Packard LaserJet */ #define MACH_GROUP_LASAT 21 +#define MACH_GROUP_BRCM 22 /* Broadcom Boards */ /* * Valid machtype values for group unknown (low order halfword of mips_machtype) @@ -179,7 +180,15 @@ #define MACH_VICTOR_MPC30X 3 /* Victor MP-C303/304 */ #define MACH_IBM_WORKPAD 4 /* IBM WorkPad z50 */ #define MACH_CASIO_E55 5 /* CASIO CASSIOPEIA E-10/15/55/65 */ -#define MACH_TANBAC_TB0226 6 /* TANBAC TB0226 (MBASE) */ + +/* + * Valid machtypes for group Broadcom + */ +#define MACH_BCM93725 0 +#define MACH_BCM93725_VJ 1 +#define MACH_BCM93730 2 +#define MACH_BCM947XX 3 +#define MACH_BCM933XX 4 #define CL_SIZE (256) --- linux-2.4.20/include/asm-mips/cpu.h~2.4.20_broadcom_3_37_2_1109_US.patch 2005-01-07 05:38:15.000000000 -0500 +++ linux-2.4.20/include/asm-mips/cpu.h 2005-01-08 12:10:11.203887728 -0500 @@ -24,6 +24,11 @@ spec. */ +#define PRID_COPT_MASK 0xff000000 +#define PRID_COMP_MASK 0x00ff0000 +#define PRID_IMP_MASK 0x0000ff00 +#define PRID_REV_MASK 0x000000ff + #define PRID_COMP_LEGACY 0x000000 #define PRID_COMP_MIPS 0x010000 #define PRID_COMP_BROADCOM 0x020000 @@ -65,10 +70,17 @@ #define PRID_IMP_20KC 0x8200 #define PRID_IMP_4KEC 0x8400 #define PRID_IMP_4KSC 0x8600 - +#define PRID_IMP_BCM4710 0x4000 +#define PRID_IMP_BCM3302 0x9000 +#define PRID_IMP_BCM3303 0x9100 +#define PRID_IMP_BCM3303 0x9100 #define PRID_IMP_UNKNOWN 0xff00 +#define BCM330X(id) \ + (((id & (PRID_COMP_MASK | PRID_IMP_MASK)) == (PRID_COMP_BROADCOM | PRID_IMP_BCM3302)) \ + || ((id & (PRID_COMP_MASK | PRID_IMP_MASK)) == (PRID_COMP_BROADCOM | PRID_IMP_BCM3303))) + /* * These are the PRID's for when 23:16 == PRID_COMP_SIBYTE */ @@ -139,7 +151,7 @@ CPU_TX3912, CPU_TX3922, CPU_TX3927, CPU_AU1000, CPU_4KEC, CPU_4KSC, CPU_VR41XX, CPU_R5500, CPU_TX49XX, CPU_TX39XX, CPU_AU1500, CPU_20KC, CPU_VR4111, CPU_VR4121, CPU_VR4122, CPU_VR4131, CPU_VR4181, CPU_VR4181A, - CPU_AU1100, CPU_LAST + CPU_AU1100, CPU_BCM4710, CPU_BCM3302, CPU_LAST }; #endif /* !__ASSEMBLY__ */ --- linux-2.4.20/include/asm-mips/mips32_cache.h~2.4.20_broadcom_3_37_2_1109_US.patch 2005-01-07 05:39:02.000000000 -0500 +++ linux-2.4.20/include/asm-mips/mips32_cache.h 2005-01-07 05:39:02.000000000 -0500 @@ -325,4 +325,17 @@ } } +extern inline void fill_icache_line(unsigned long addr) +{ + __asm__ __volatile__( + ".set noreorder\n\t" + ".set mips3\n\t" + "cache %1, (%0)\n\t" + ".set mips0\n\t" + ".set reorder" + : + : "r" (addr), + "i" (Fill)); +} + #endif /* !(_MIPS_R4KCACHE_H) */ --- linux-2.4.20/include/asm-mips/mipsregs.h~2.4.20_broadcom_3_37_2_1109_US.patch 2005-01-07 05:39:02.000000000 -0500 +++ linux-2.4.20/include/asm-mips/mipsregs.h 2005-01-07 05:39:44.000000000 -0500 @@ -400,13 +400,75 @@ #define TX49_CONF_HALT (_ULCAST_(1) << 18) #define TX49_CONF_CWFON (_ULCAST_(1) << 27) -/* - * R10000 performance counter definitions. - * - * FIXME: The R10000 performance counter opens a nice way to implement CPU - * time accounting with a precission of one cycle. I don't have - * R10000 silicon but just a manual, so ... - */ +/* mips32/64 definitions for CP0 config register */ +#define CONF_MT_MASK 0x00000380 /* MMU Type */ +#define CONF_MT_NONE 0x00000000 /* No mmu */ +#define CONF_MT_TLB 0x00000080 /* TLB present */ +#define CONF_MT_BAT 0x00000100 /* Block address translation */ +#define CONF_MT_FM 0x00000180 /* Fixed map (Like 4Kp/4Km) */ +#define CONF_AR_MASK 0x00001c00 /* Architecture revision */ +#define CONF_AT_MASK 0x00006000 /* Architecture type */ +#define CONF_AT_M32 0x00000000 /* mips32 */ +#define CONF_AT_M6432 0x00002000 /* mips64/mips32?? */ +#define CONF_AT_M64 0x00004000 /* mips64 */ +#define CONF_BE 0x00008000 /* BigEndian */ +#define CONF_BM 0x00010000 /* Burst Mode */ +#define CONF_BM_SEQ 0x00000000 /* Sequential */ +#define CONF_BM_SB 0x00010000 /* SubBlock */ +#define CONF_MM_MASK 0x00060000 /* Merge Mode */ +#define CONF_MM_NONE 0x00000000 /* No merging */ +#define CONF_MM_SYSAD 0x00020000 /* SysAD merging */ +#define CONF_MM_FULL 0x00040000 /* Full merging */ +#define CONF_MDU 0x00100000 /* Slow MDU */ +#define CONF_KU_MASK 0x0e000000 /* Kuseg and useg cacheability (for MT=FM) */ +#define CONF_K23_MASK 0x70000000 /* Kseg2 and Kseg3 cacheability (for MT=FM) */ +#define CONF_M 0x80000000 /* config1 register present */ + +/* mips32/64 definitions for CP0 config1 register */ +#define CONF1_FP 0x00000001 /* FPU present */ +#define CONF1_EP 0x00000002 /* EJTAG present */ +#define CONF1_CA 0x00000004 /* Code compression (mips16) implemented */ +#define CONF1_WR 0x00000008 /* Watch registers present */ +#define CONF1_PC 0x00000010 /* Performance counters present */ +#define CONF1_DA_SHIFT 7 /* Data cache associativity */ +#define CONF1_DA_MASK 0x00000380 +#define CONF1_DA_BASE 1 +#define CONF1_DA_DM 0x00000000 /* Direct mapped */ +#define CONF1_DA_2W 0x00000080 /* 2-way */ +#define CONF1_DA_3W 0x00000100 /* 3-way */ +#define CONF1_DA_4W 0x00000180 /* 4-way */ +#define CONF1_DL_SHIFT 10 /* Data cache line size */ +#define CONF1_DL_MASK 0x00001c00 +#define CONF1_DL_BASE 2 +#define CONF1_DL_NONE 0x00000000 /* No data cache present */ +#define CONF1_DL_16 0x00000c00 /* 16 bytes */ +#define CONF1_DS_SHIFT 13 /* Data cache sets/way */ +#define CONF1_DS_MASK 0x0000e000 +#define CONF1_DS_BASE 64 +#define CONF1_DS_64 0x00000000 /* 64 sets */ +#define CONF1_DS_128 0x00002000 /* 128 sets */ +#define CONF1_DS_256 0x00004000 /* 256 sets */ +#define CONF1_IA_SHIFT 16 /* Instruction cache associativity */ +#define CONF1_IA_MASK 0x00070000 +#define CONF1_IA_BASE 1 +#define CONF1_IA_DM 0x00000000 /* Direct mapped */ +#define CONF1_IA_2W 0x00010000 /* 2-way */ +#define CONF1_IA_3W 0x00020000 /* 3-way */ +#define CONF1_IA_4W 0x00030000 /* 4-way */ +#define CONF1_IL_SHIFT 19 /* Instruction cache line size */ +#define CONF1_IL_MASK 0x00380000 +#define CONF1_IL_BASE 2 +#define CONF1_IL_NONE 0x00000000 /* No data cache present */ +#define CONF1_IL_16 0x00180000 /* 16 bytes */ +#define CONF1_IS_SHIFT 22 /* Instruction cache sets/way */ +#define CONF1_IS_MASK 0x01c00000 +#define CONF1_IS_BASE 64 +#define CONF1_IS_64 0x00000000 /* 64 sets */ +#define CONF1_IS_128 0x00400000 /* 128 sets */ +#define CONF1_IS_256 0x00800000 /* 256 sets */ +#define CONF1_MS_MASK 0x7e000000 /* Number of tlb entries */ +#define CONF1_MS_SHIFT 25 + /* * Events counted by counter #0 @@ -727,6 +789,20 @@ #define read_c0_framemask() __read_32bit_c0_register($21, 0) #define write_c0_framemask(val) __write_32bit_c0_register($21, 0, val) +#define read_c0_diag() __read_32bit_c0_register($22, 0) +#define read_c0_diag1() __read_32bit_c0_register($22, 1) +#define read_c0_diag2() __read_32bit_c0_register($22, 2) +#define read_c0_diag3() __read_32bit_c0_register($22, 3) +#define read_c0_diag4() __read_32bit_c0_register($22, 4) +#define read_c0_diag5() __read_32bit_c0_register($22, 5) + +#define write_c0_diag(val) __write_32bit_c0_register($22, 0, val) +#define write_c0_diag1(val) __write_32bit_c0_register($22, 1, val) +#define write_c0_diag2(val) __write_32bit_c0_register($22, 2, val) +#define write_c0_diag3(val) __write_32bit_c0_register($22, 3, val) +#define write_c0_diag4(val) __write_32bit_c0_register($22, 4, val) +#define write_c0_diag5(val) __write_32bit_c0_register($22, 5, val) + #define read_c0_debug() __read_32bit_c0_register($23, 0) #define write_c0_debug(val) __write_32bit_c0_register($23, 0, val) @@ -844,6 +920,14 @@ __BUILD_SET_C0(cause,CP0_CAUSE) __BUILD_SET_C0(config,CP0_CONFIG) +/* + * Functions to access the performance counter and control registers + */ +extern asmlinkage unsigned int read_perf_cntr(unsigned int counter); +extern asmlinkage void write_perf_cntr(unsigned int counter, unsigned int val); +extern asmlinkage unsigned int read_perf_cntl(unsigned int counter); +extern asmlinkage void write_perf_cntl(unsigned int counter, unsigned int val); + #endif /* !__ASSEMBLY__ */ #endif /* _ASM_MIPSREGS_H */ --- linux-2.4.20/include/asm-mips/pci.h~2.4.20_broadcom_3_37_2_1109_US.patch 2005-01-07 05:39:02.000000000 -0500 +++ linux-2.4.20/include/asm-mips/pci.h 2005-01-08 12:15:03.133507680 -0500 @@ -117,12 +117,7 @@ if (direction == PCI_DMA_NONE) out_of_line_bug(); - if (direction != PCI_DMA_TODEVICE) { - unsigned long addr; - - addr = baddr_to_bus(hwdev->bus, dma_addr) + PAGE_OFFSET; - dma_cache_wback_inv(addr, size); - } + /* Nothing to do */ } /* @@ -203,8 +198,7 @@ } else { sg->dma_address = page_to_bus(sg->page) + sg->offset; - dma_cache_wback_inv((unsigned long) - (page_address(sg->page) + sg->offset), + dma_cache_wback_inv((unsigned long)page_address(sg->page) + sg->offset, sg->length); } } --- linux-2.4.20/include/asm-mips/serial.h~2.4.20_broadcom_3_37_2_1109_US.patch 2005-01-07 05:39:02.000000000 -0500 +++ linux-2.4.20/include/asm-mips/serial.h 2005-01-08 12:15:06.999919896 -0500 @@ -181,6 +181,13 @@ #define TXX927_SERIAL_PORT_DEFNS #endif +#ifdef CONFIG_BCM947XX +/* reserve 4 ports to be configured at runtime */ +#define BCM947XX_SERIAL_PORT_DEFNS { 0, }, { 0, }, { 0, }, { 0, }, +#else +#define BCM947XX_SERIAL_PORT_DEFNS +#endif + #ifdef CONFIG_HAVE_STD_PC_SERIAL_PORT #define STD_SERIAL_PORT_DEFNS \ /* UART CLK PORT IRQ FLAGS */ \ @@ -313,6 +320,7 @@ #endif #define SERIAL_PORT_DFNS \ + BCM947XX_SERIAL_PORT_DEFNS \ IVR_SERIAL_PORT_DEFNS \ ITE_SERIAL_PORT_DEFNS \ ATLAS_SERIAL_PORT_DEFNS \ --- linux-2.4.20/include/asm-mips/stackframe.h~2.4.20_broadcom_3_37_2_1109_US.patch 2005-01-07 05:38:15.000000000 -0500 +++ linux-2.4.20/include/asm-mips/stackframe.h 2005-01-08 12:15:32.798997840 -0500 @@ -201,12 +201,25 @@ lw $3, PT_R3(sp); \ lw $2, PT_R2(sp) +#ifdef CONFIG_BCM4710 + #define RESTORE_SP_AND_RET \ lw sp, PT_R29(sp); \ .set mips3; \ + nop; \ + nop; \ eret; \ .set mips0 +#else + +#define RESTORE_SP_AND_RET \ + lw sp, PT_R29(sp); \ + .set mips3; \ + eret; \ + .set mips0 +#endif + #endif #define RESTORE_SP \ --- linux-2.4.20/include/asm-mips/system.h~2.4.20_broadcom_3_37_2_1109_US.patch 2005-01-07 05:39:02.000000000 -0500 +++ linux-2.4.20/include/asm-mips/system.h 2005-01-08 12:15:03.002527592 -0500 @@ -16,6 +16,8 @@ #ifndef _ASM_SYSTEM_H #define _ASM_SYSTEM_H +#ifdef __KERNEL__ + #include #include @@ -316,4 +318,6 @@ #define die_if_kernel(msg, regs) \ __die_if_kernel(msg, regs, __FILE__ ":", __FUNCTION__, __LINE__) +#endif /* __KERNEL__ */ + #endif /* _ASM_SYSTEM_H */ --- linux-2.4.20/init/do_mounts.c~2.4.20_broadcom_3_37_2_1109_US.patch 2005-01-07 05:38:15.000000000 -0500 +++ linux-2.4.20/init/do_mounts.c 2005-01-08 12:16:21.913531296 -0500 @@ -238,7 +238,16 @@ { "ftlb", 0x2c08 }, { "ftlc", 0x2c10 }, { "ftld", 0x2c18 }, +#if defined(CONFIG_MTD_BLOCK) || defined(CONFIG_MTD_BLOCK_RO) { "mtdblock", 0x1f00 }, + { "mtdblock0",0x1f00 }, + { "mtdblock1",0x1f01 }, + { "mtdblock2",0x1f02 }, + { "mtdblock3",0x1f03 }, +#endif +#ifdef CONFIG_BLK_DEV_DUMMY + { "dummy",0x2000 }, +#endif { NULL, 0 } }; @@ -468,6 +477,7 @@ struct minix_super_block *minixsb; struct ext2_super_block *ext2sb; struct romfs_super_block *romfsb; + struct cramfs_super *cramfsb; int nblocks = -1; unsigned char *buf; @@ -478,6 +488,7 @@ minixsb = (struct minix_super_block *) buf; ext2sb = (struct ext2_super_block *) buf; romfsb = (struct romfs_super_block *) buf; + cramfsb = (struct cramfs_super *) buf; memset(buf, 0xe5, size); /* @@ -497,6 +508,13 @@ goto done; } +#ifdef CONFIG_BLK_DEV_INITRD + /* + * Fallback if size cannot be determined by superblock + */ + nblocks = (initrd_end-initrd_start+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS; +#endif + /* romfs is at block zero too */ if (romfsb->word0 == ROMSB_WORD0 && romfsb->word1 == ROMSB_WORD1) { @@ -507,6 +525,16 @@ goto done; } + /* so is cramfs */ + if (cramfsb->magic == CRAMFS_MAGIC) { + printk(KERN_NOTICE + "RAMDISK: cramfs filesystem found at block %d\n", + start_block); + if (cramfsb->flags & CRAMFS_FLAG_FSID_VERSION_2) + nblocks = (cramfsb->size+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS; + goto done; + } + /* * Read block 1 to test for minix and ext2 superblock */ @@ -535,6 +563,7 @@ printk(KERN_NOTICE "RAMDISK: Couldn't find valid RAM disk image starting at %d.\n", start_block); + nblocks = -1; done: lseek(fd, start_block * BLOCK_SIZE, 0); @@ -757,6 +786,17 @@ change_floppy("root floppy"); } #endif +#if defined(CONFIG_MTD_BLOCK) || defined(CONFIG_MTD_BLOCK_RO) + if (MAJOR(ROOT_DEV) == 31) { + /* rd_doload is for a ramload setup */ + if (rd_doload) { + if (rd_load_disk(0)) { + ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0); + create_dev("/dev/root", ROOT_DEV, NULL); + } + } + } +#endif mount_block_root("/dev/root", root_mountflags); } --- linux-2.4.20/init/main.c~2.4.20_broadcom_3_37_2_1109_US.patch 2005-01-07 05:39:02.000000000 -0500 +++ linux-2.4.20/init/main.c 2005-01-07 05:39:02.000000000 -0500 @@ -554,6 +554,13 @@ free_initmem(); unlock_kernel(); +#ifdef CONFIG_NOROOT + for (;;) { + DECLARE_WAIT_QUEUE_HEAD(wait); + sleep_on(&wait); + } +#endif + if (open("/dev/console", O_RDWR, 0) < 0) printk("Warning: unable to open an initial console.\n"); --- linux-2.4.20/net/bridge/br_device.c~2.4.20_broadcom_3_37_2_1109_US.patch 2005-01-07 05:38:15.000000000 -0500 +++ linux-2.4.20/net/bridge/br_device.c 2005-01-07 05:39:02.000000000 -0500 @@ -121,6 +121,25 @@ return -1; } +extern void br_stp_change_bridge_id(struct net_bridge *br, unsigned char *addr); + +static int +br_set_mac_address(struct net_device *dev, void *addr) +{ + struct net_bridge *br = dev->priv; + struct sockaddr *sa = (struct sockaddr *) addr; + + write_lock_bh(&br->lock); + + memcpy(br->preferred_id.addr, sa->sa_data, ETH_ALEN); + + br_stp_recalculate_bridge_id(br); + + write_unlock_bh(&br->lock); + + return 0; +} + void br_dev_setup(struct net_device *dev) { memset(dev->dev_addr, 0, ETH_ALEN); @@ -133,5 +152,5 @@ dev->stop = br_dev_stop; dev->accept_fastpath = br_dev_accept_fastpath; dev->tx_queue_len = 0; - dev->set_mac_address = NULL; + dev->set_mac_address = br_set_mac_address; } --- linux-2.4.20/net/bridge/br_fdb.c~2.4.20_broadcom_3_37_2_1109_US.patch 2005-01-07 05:38:15.000000000 -0500 +++ linux-2.4.20/net/bridge/br_fdb.c 2005-01-07 05:39:02.000000000 -0500 @@ -290,10 +290,10 @@ hash = br_mac_hash(addr); write_lock_bh(&br->hash_lock); + if (!is_local) { fdb = br->hash[hash]; while (fdb != NULL) { - if (!fdb->is_local && - !memcmp(fdb->addr.addr, addr, ETH_ALEN)) { + if (!memcmp(fdb->addr.addr, addr, ETH_ALEN)) { __fdb_possibly_replace(fdb, source, is_local); write_unlock_bh(&br->hash_lock); return; @@ -301,6 +301,7 @@ fdb = fdb->next_hash; } + } fdb = kmalloc(sizeof(*fdb), GFP_ATOMIC); if (fdb == NULL) { --- linux-2.4.20/net/bridge/br_private.h~2.4.20_broadcom_3_37_2_1109_US.patch 2005-01-07 05:38:15.000000000 -0500 +++ linux-2.4.20/net/bridge/br_private.h 2005-01-08 12:16:21.367614288 -0500 @@ -96,6 +96,7 @@ int hello_time; int forward_delay; bridge_id bridge_id; + bridge_id preferred_id; int bridge_max_age; int bridge_hello_time; int bridge_forward_delay; --- linux-2.4.20/net/bridge/br_stp_if.c~2.4.20_broadcom_3_37_2_1109_US.patch 2005-01-07 05:38:15.000000000 -0500 +++ linux-2.4.20/net/bridge/br_stp_if.c 2005-01-07 05:39:02.000000000 -0500 @@ -162,6 +162,12 @@ p = br->port_list; while (p != NULL) { + /* match against preferred address first */ + if (memcmp(p->dev->dev_addr, br->preferred_id.addr, ETH_ALEN) == 0) { + addr = p->dev->dev_addr; + break; + } + if (addr == br_mac_zero || memcmp(p->dev->dev_addr, addr, ETH_ALEN) < 0) addr = p->dev->dev_addr; --- linux-2.4.20/net/core/Makefile~2.4.20_broadcom_3_37_2_1109_US.patch 2005-01-07 05:38:15.000000000 -0500 +++ linux-2.4.20/net/core/Makefile 2005-01-08 12:16:20.333771456 -0500 @@ -7,6 +7,8 @@ # # Note 2! The CFLAGS definition is now in the main makefile... +SRCBASE := $(TOPDIR)/../.. +EXTRA_CFLAGS += -Wall -I$(SRCBASE)/ O_TARGET := core.o export-objs := netfilter.o profile.o --- linux-2.4.20/net/core/dev.c~2.4.20_broadcom_3_37_2_1109_US.patch 2005-01-07 05:38:15.000000000 -0500 +++ linux-2.4.20/net/core/dev.c 2005-01-08 12:16:21.372613528 -0500 @@ -1245,6 +1245,19 @@ local_irq_save(flags); netdev_rx_stat[this_cpu].total++; + +#if defined(CONFIG_BCM4710) && defined(CONFIG_BRIDGE) + /* Optimisation for framebursting (allow interleaving of pkts by + immediately processing the rx pkt instead of Qing the pkt and deferring + the processing). Only optimise for bridging and guard against non + TASKLET based netif_rx calls. + */ + if (!in_irq() && skb->dev->br_port != NULL && br_handle_frame_hook != NULL){ + local_irq_restore(flags); + return(netif_receive_skb(skb)); + } +#endif + if (queue->input_pkt_queue.qlen <= netdev_max_backlog) { if (queue->input_pkt_queue.qlen) { if (queue->throttle) @@ -2005,6 +2018,7 @@ { struct net_device *dev; int err; + struct net_device_stats *stats; if ((dev = __dev_get_by_name(ifr->ifr_name)) == NULL) return -ENODEV; @@ -2119,6 +2133,16 @@ ifr->ifr_ifindex = dev->ifindex; return 0; +#ifdef PERFORMANCE_SUPPORT + case SIOCGIFSTATS: + if (!dev->get_stats || !(stats = dev->get_stats(dev))) + return -ENODEV; + if (copy_to_user(ifr->ifr_data, stats, + sizeof(struct net_device_stats))) + return -EFAULT; + return 0; +#endif + case SIOCGIFTXQLEN: ifr->ifr_qlen = dev->tx_queue_len; return 0; --- linux-2.4.20/net/netsyms.c~2.4.20_broadcom_3_37_2_1109_US.patch 2005-01-07 05:38:15.000000000 -0500 +++ linux-2.4.20/net/netsyms.c 2005-01-08 12:16:21.745556832 -0500 @@ -435,20 +435,12 @@ EXPORT_SYMBOL(neigh_add); EXPORT_SYMBOL(neigh_dump_info); -EXPORT_SYMBOL(dev_set_allmulti); -EXPORT_SYMBOL(dev_set_promiscuity); -EXPORT_SYMBOL(sklist_remove_socket); -EXPORT_SYMBOL(rtnl_sem); -EXPORT_SYMBOL(rtnl_lock); -EXPORT_SYMBOL(rtnl_unlock); - /* ABI emulation layers need this */ EXPORT_SYMBOL(move_addr_to_kernel); EXPORT_SYMBOL(move_addr_to_user); /* Used by at least ipip.c. */ EXPORT_SYMBOL(ipv4_config); -EXPORT_SYMBOL(dev_open); /* Used by other modules */ EXPORT_SYMBOL(xrlim_allow); @@ -460,6 +452,14 @@ #endif /* CONFIG_INET */ +EXPORT_SYMBOL(dev_open); +EXPORT_SYMBOL(dev_set_allmulti); +EXPORT_SYMBOL(dev_set_promiscuity); +EXPORT_SYMBOL(sklist_remove_socket); +EXPORT_SYMBOL(rtnl_sem); +EXPORT_SYMBOL(rtnl_lock); +EXPORT_SYMBOL(rtnl_unlock); + #ifdef CONFIG_TR EXPORT_SYMBOL(tr_type_trans); #endif