diff -Naur linux-mips-2.6.8.1-orig/arch/mips/brcm-boards/bcm963xx/irq.c linux-mips-2.6.8.1-bcm/arch/mips/brcm-boards/bcm963xx/irq.c --- linux-mips-2.6.8.1-orig/arch/mips/brcm-boards/bcm963xx/irq.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/arch/mips/brcm-boards/bcm963xx/irq.c 2007-01-24 17:22:47.000000000 +0100 @@ -0,0 +1,417 @@ +/* +<:copyright-gpl + Copyright 2002 Broadcom Corp. 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. +:> +*/ +/* + * Interrupt control functions for Broadcom 963xx MIPS boards + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +extern asmlinkage unsigned int do_IRQ(int irq, struct pt_regs *regs); + +static void irq_dispatch_int(struct pt_regs *regs) +{ + unsigned int pendingIrqs; + static unsigned int irqBit; + static unsigned int isrNumber = 31; + + pendingIrqs = PERF->IrqStatus & PERF->IrqMask; + if (!pendingIrqs) { + return; + } + + while (1) { + irqBit <<= 1; + isrNumber++; + if (isrNumber == 32) { + isrNumber = 0; + irqBit = 0x1; + } + if (pendingIrqs & irqBit) { + unsigned int irq = isrNumber + INTERNAL_ISR_TABLE_OFFSET; +#if defined(CONFIG_BCM96358) + if (irq >= INTERRUPT_ID_EXTERNAL_0 && irq <= INTERRUPT_ID_EXTERNAL_3) { + PERF->ExtIrqCfg |= (1 << (irq - INTERRUPT_ID_EXTERNAL_0 + EI_CLEAR_SHFT)); // Clear + } + else if (irq >= INTERRUPT_ID_EXTERNAL_4 && irq <= INTERRUPT_ID_EXTERNAL_5) { + PERF->ExtIrqCfg1 |= (1 << (irq - INTERRUPT_ID_EXTERNAL_4 + EI_CLEAR_SHFT)); // Clear + } +#endif + PERF->IrqMask &= ~irqBit; // mask + do_IRQ(irq, regs); + break; + } + } +} + +#if defined(CONFIG_BCM96338) || defined(CONFIG_BCM96348) +static void irq_dispatch_ext(uint32 irq, struct pt_regs *regs) +{ + if (!(PERF->ExtIrqCfg & (1 << (irq - INTERRUPT_ID_EXTERNAL_0 + EI_MASK_SHFT)))) { + printk("**** Ext IRQ mask. Should not dispatch ****\n"); + } + /* disable and clear interrupt in the controller */ + PERF->ExtIrqCfg |= (1 << (irq - INTERRUPT_ID_EXTERNAL_0 + EI_CLEAR_SHFT)); + PERF->ExtIrqCfg &= ~(1 << (irq - INTERRUPT_ID_EXTERNAL_0 + EI_MASK_SHFT)); + do_IRQ(irq, regs); +} +#endif + +static void irq_dispatch_sw(uint32 irq, struct pt_regs *regs) +{ + clear_c0_cause(0x1 << (CAUSEB_IP0 + irq - INTERRUPT_ID_SOFTWARE_0)); + do_IRQ(irq, regs); +} + + +void brcm_irq_dispatch(struct pt_regs *regs) +{ + u32 cause; + while((cause = (read_c0_cause() & read_c0_status() & CAUSEF_IP))) { + if (cause & CAUSEF_IP7) + do_IRQ(MIPS_TIMER_INT, regs); + else if (cause & CAUSEF_IP2) + irq_dispatch_int(regs); +#if defined(CONFIG_BCM96338) || defined(CONFIG_BCM96348) + else if (cause & CAUSEF_IP3) + irq_dispatch_ext(INTERRUPT_ID_EXTERNAL_0, regs); + else if (cause & CAUSEF_IP4) + irq_dispatch_ext(INTERRUPT_ID_EXTERNAL_1, regs); + else if (cause & CAUSEF_IP5) + irq_dispatch_ext(INTERRUPT_ID_EXTERNAL_2, regs); + else if (cause & CAUSEF_IP6) + irq_dispatch_ext(INTERRUPT_ID_EXTERNAL_3, regs); +#endif + else if (cause & CAUSEF_IP0) + irq_dispatch_sw(INTERRUPT_ID_SOFTWARE_0, regs); + else if (cause & CAUSEF_IP1) + irq_dispatch_sw(INTERRUPT_ID_SOFTWARE_1, regs); + cli(); + } +} + + +void enable_brcm_irq(unsigned int irq) +{ + unsigned long flags; + + local_irq_save(flags); + if( irq >= INTERNAL_ISR_TABLE_OFFSET ) { + PERF->IrqMask |= (1 << (irq - INTERNAL_ISR_TABLE_OFFSET)); + } +#if defined(CONFIG_BCM96338) || defined(CONFIG_BCM96348) + else if (irq >= INTERRUPT_ID_EXTERNAL_0 && irq <= INTERRUPT_ID_EXTERNAL_3) { + /* enable and clear interrupt in the controller */ + PERF->ExtIrqCfg |= (1 << (irq - INTERRUPT_ID_EXTERNAL_0 + EI_CLEAR_SHFT)); + PERF->ExtIrqCfg |= (1 << (irq - INTERRUPT_ID_EXTERNAL_0 + EI_MASK_SHFT)); + } +#endif + else if ((irq == INTERRUPT_ID_SOFTWARE_0) || (irq == INTERRUPT_ID_SOFTWARE_1)) { + set_c0_status(0x1 << (STATUSB_IP0 + irq - INTERRUPT_ID_SOFTWARE_0)); + } + local_irq_restore(flags); +} + +void disable_brcm_irq(unsigned int irq) +{ + unsigned long flags; + + local_irq_save(flags); + if( irq >= INTERNAL_ISR_TABLE_OFFSET ) { + PERF->IrqMask &= ~(1 << (irq - INTERNAL_ISR_TABLE_OFFSET)); + } +#if defined(CONFIG_BCM96338) || defined(CONFIG_BCM96348) + else if (irq >= INTERRUPT_ID_EXTERNAL_0 && irq <= INTERRUPT_ID_EXTERNAL_3) { + /* disable interrupt in the controller */ + PERF->ExtIrqCfg &= ~(1 << (irq - INTERRUPT_ID_EXTERNAL_0 + EI_MASK_SHFT)); + } +#endif + else if ((irq == INTERRUPT_ID_SOFTWARE_0) || (irq == INTERRUPT_ID_SOFTWARE_1)) { + clear_c0_status(0x1 << (STATUSB_IP0 + irq - INTERRUPT_ID_SOFTWARE_0)); + } + local_irq_restore(flags); +} + +void ack_brcm_irq(unsigned int irq) +{ + /* Already done in brcm_irq_dispatch */ +} + +unsigned int startup_brcm_irq(unsigned int irq) +{ + enable_brcm_irq(irq); + + return 0; /* never anything pending */ +} + +unsigned int startup_brcm_none(unsigned int irq) +{ + return 0; +} + +void end_brcm_irq(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + enable_brcm_irq(irq); +} + +void end_brcm_none(unsigned int irq) +{ +} + +#if defined (CONFIG_BCM96358) +#define ALLINTS_NOTIMER IE_IRQ0 +#else +#define ALLINTS_NOTIMER (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4) +#endif + +static void __init brcm_irq_setup(void) +{ + extern asmlinkage void brcmIRQ(void); + + clear_c0_status(ST0_BEV); + set_except_vector(0, brcmIRQ); + change_c0_status(ST0_IM, ALLINTS_NOTIMER); + +#ifdef CONFIG_REMOTE_DEBUG + rs_kgdb_hook(0); +#endif +} + +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, + .set_affinity = NULL +}; + +static struct hw_interrupt_type brcm_irq_no_end_type = { + .typename = "MIPS", + .startup = startup_brcm_none, + .shutdown = disable_brcm_irq, + .enable = enable_brcm_irq, + .disable = disable_brcm_irq, + .ack = ack_brcm_irq, + .end = end_brcm_none, + .set_affinity = NULL +}; + +void __init arch_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; + } + + brcm_irq_setup(); +} + +#if defined(CONFIG_BCM96338) || defined(CONFIG_BCM96348) +int request_external_irq(unsigned int irq, + FN_HANDLER handler, + unsigned long irqflags, + const char * devname, + void *dev_id) +{ + unsigned long flags; + + local_irq_save(flags); + + PERF->ExtIrqCfg |= (1 << (irq - INTERRUPT_ID_EXTERNAL_0 + EI_CLEAR_SHFT)); // Clear + PERF->ExtIrqCfg &= ~(1 << (irq - INTERRUPT_ID_EXTERNAL_0 + EI_MASK_SHFT)); // Mask + PERF->ExtIrqCfg &= ~(1 << (irq - INTERRUPT_ID_EXTERNAL_0 + EI_INSENS_SHFT)); // Edge insesnsitive + PERF->ExtIrqCfg |= (1 << (irq - INTERRUPT_ID_EXTERNAL_0 + EI_LEVEL_SHFT)); // Level triggered + PERF->ExtIrqCfg &= ~(1 << (irq - INTERRUPT_ID_EXTERNAL_0 + EI_SENSE_SHFT)); // Low level + + local_irq_restore(flags); + + return( request_irq(irq, handler, irqflags, devname, dev_id) ); +} +#endif + + +unsigned int +neufbox_map_interrupt (FN_HANDLER pfunc, char const *const name, void * param, uint32_t irq) +{ + unsigned long flags; + char * devname = kmalloc(16, GFP_KERNEL); + + + if ( devname ) { + snprintf (devname, 16, name); + } + + /* Set the IRQ description to not automatically enable the interrupt at + * the end of an ISR. The driver that handles the interrupt must + * explicitly call BcmHalInterruptEnable or enable_brcm_irq. This behavior + * is consistent with interrupt handling on VxWorks. + */ + irq_desc[irq].handler = &brcm_irq_no_end_type; + + + local_irq_save (flags); + + if ( irq >= INTERRUPT_ID_EXTERNAL_0 && irq <= INTERRUPT_ID_EXTERNAL_3 ) { + // Clear + PERF->ExtIrqCfg |= (1 << (irq - INTERRUPT_ID_EXTERNAL_0 + EI_CLEAR_SHFT)); + // Unmask + PERF->ExtIrqCfg |= (1 << (irq - INTERRUPT_ID_EXTERNAL_0 + EI_MASK_SHFT)); + // Edge insesnsitive + PERF->ExtIrqCfg &= ~(1 << (irq - INTERRUPT_ID_EXTERNAL_0 + EI_INSENS_SHFT)); + // Level triggered + PERF->ExtIrqCfg |= (1 << (irq - INTERRUPT_ID_EXTERNAL_0 + EI_LEVEL_SHFT)); + // Low level + PERF->ExtIrqCfg &= ~(1 << (irq - INTERRUPT_ID_EXTERNAL_0 + EI_SENSE_SHFT)); + } + else if ( irq >= INTERRUPT_ID_EXTERNAL_4 && irq <= INTERRUPT_ID_EXTERNAL_5 ) { + // Clear + PERF->ExtIrqCfg1 |= (1 << (irq - INTERRUPT_ID_EXTERNAL_4 + EI_CLEAR_SHFT)); + // Unmask + PERF->ExtIrqCfg1 |= (1 << (irq - INTERRUPT_ID_EXTERNAL_4 + EI_MASK_SHFT)); + // Edge insesnsitive + PERF->ExtIrqCfg1 &= ~(1 << (irq - INTERRUPT_ID_EXTERNAL_4 + EI_INSENS_SHFT)); + // Level triggered + PERF->ExtIrqCfg1 |= (1 << (irq - INTERRUPT_ID_EXTERNAL_4 + EI_LEVEL_SHFT)); + // Low level + PERF->ExtIrqCfg1 &= ~(1 << (irq - INTERRUPT_ID_EXTERNAL_4 + EI_SENSE_SHFT)); + } + + local_irq_restore (flags); + + return request_irq (irq, pfunc, SA_SAMPLE_RANDOM | SA_INTERRUPT, devname, param); +} + + + +unsigned int BcmHalMapInterrupt(FN_HANDLER pfunc, unsigned int param, + unsigned int irq) +{ + int nRet = -1; + char *devname; + + devname = kmalloc(16, GFP_KERNEL); + if (devname) + sprintf( devname, "brcm_%d", irq ); + + /* Set the IRQ description to not automatically enable the interrupt at + * the end of an ISR. The driver that handles the interrupt must + * explicitly call BcmHalInterruptEnable or enable_brcm_irq. This behavior + * is consistent with interrupt handling on VxWorks. + */ + irq_desc[irq].handler = &brcm_irq_no_end_type; + +#if defined(CONFIG_BCM96348) || defined(CONFIG_BCM96358) + if( irq == INTERRUPT_ID_MPI ) { + nRet = request_irq( irq, pfunc, SA_SAMPLE_RANDOM | SA_INTERRUPT | SA_SHIRQ, + devname, (void *) param ); + + } + else +#endif + if( irq >= INTERNAL_ISR_TABLE_OFFSET ) + { +#if defined(CONFIG_BCM96358) + unsigned long flags; + + local_irq_save(flags); + if (irq >= INTERRUPT_ID_EXTERNAL_0 && irq <= INTERRUPT_ID_EXTERNAL_3) { + PERF->ExtIrqCfg |= (1 << (irq - INTERRUPT_ID_EXTERNAL_0 + EI_CLEAR_SHFT)); // Clear + PERF->ExtIrqCfg |= (1 << (irq - INTERRUPT_ID_EXTERNAL_0 + EI_MASK_SHFT)); // Unmask + PERF->ExtIrqCfg &= ~(1 << (irq - INTERRUPT_ID_EXTERNAL_0 + EI_INSENS_SHFT)); // Edge insesnsitive + PERF->ExtIrqCfg |= (1 << (irq - INTERRUPT_ID_EXTERNAL_0 + EI_LEVEL_SHFT)); // Level triggered + PERF->ExtIrqCfg &= ~(1 << (irq - INTERRUPT_ID_EXTERNAL_0 + EI_SENSE_SHFT)); // Low level + } + else if (irq >= INTERRUPT_ID_EXTERNAL_4 && irq <= INTERRUPT_ID_EXTERNAL_5) { + PERF->ExtIrqCfg1 |= (1 << (irq - INTERRUPT_ID_EXTERNAL_4 + EI_CLEAR_SHFT)); // Clear + PERF->ExtIrqCfg1 |= (1 << (irq - INTERRUPT_ID_EXTERNAL_4 + EI_MASK_SHFT)); // Unmask + PERF->ExtIrqCfg1 &= ~(1 << (irq - INTERRUPT_ID_EXTERNAL_4 + EI_INSENS_SHFT)); // Edge insesnsitive + PERF->ExtIrqCfg1 |= (1 << (irq - INTERRUPT_ID_EXTERNAL_4 + EI_LEVEL_SHFT)); // Level triggered + PERF->ExtIrqCfg1 &= ~(1 << (irq - INTERRUPT_ID_EXTERNAL_4 + EI_SENSE_SHFT)); // Low level + } + local_irq_restore(flags); +#endif + nRet = request_irq( irq, pfunc, SA_SAMPLE_RANDOM | SA_INTERRUPT, + devname, (void *) param ); + + } +#if defined(CONFIG_BCM96338) || defined(CONFIG_BCM96348) + else if (irq >= INTERRUPT_ID_EXTERNAL_0 && irq <= INTERRUPT_ID_EXTERNAL_3) + { + nRet = request_external_irq( irq, pfunc, SA_SAMPLE_RANDOM | SA_INTERRUPT, + devname, (void *) param ); + } +#endif + else if ((irq == INTERRUPT_ID_SOFTWARE_0) || (irq == INTERRUPT_ID_SOFTWARE_1)) + { + nRet = request_irq( irq, pfunc, SA_SAMPLE_RANDOM | SA_INTERRUPT, + devname, (void *) param ); + } + + return( nRet ); +} + + +//*************************************************************************** +// void BcmHalGenerateSoftInterrupt +// +// Triggers a software interrupt. +// +//*************************************************************************** +void BcmHalGenerateSoftInterrupt( unsigned int irq ) +{ + unsigned long flags; + + local_irq_save(flags); + + set_c0_cause(0x1 << (CAUSEB_IP0 + irq - INTERRUPT_ID_SOFTWARE_0)); + + local_irq_restore(flags); +} + +EXPORT_SYMBOL(enable_brcm_irq); +EXPORT_SYMBOL(disable_brcm_irq); +#if defined(CONFIG_BCM96338) || defined(CONFIG_BCM96348) +EXPORT_SYMBOL(request_external_irq); +#endif +EXPORT_SYMBOL(BcmHalMapInterrupt); +EXPORT_SYMBOL(neufbox_map_interrupt); +EXPORT_SYMBOL(BcmHalGenerateSoftInterrupt); diff -Naur linux-mips-2.6.8.1-orig/arch/mips/brcm-boards/bcm963xx/Kconfig linux-mips-2.6.8.1-bcm/arch/mips/brcm-boards/bcm963xx/Kconfig --- linux-mips-2.6.8.1-orig/arch/mips/brcm-boards/bcm963xx/Kconfig 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/arch/mips/brcm-boards/bcm963xx/Kconfig 2006-12-20 18:48:39.000000000 +0100 @@ -0,0 +1,177 @@ +# Kernel and Driver configuration for Broadcom Commengine ADSL board +choice + prompt "Broadcom Commengine ADSL board" + depends on MIPS_BRCM + default BCM96348 + help + Select different Broadcom ADSL board + +config BCM96338 + bool "96338 ADSL board" + select DMA_NONCOHERENT + +config BCM96348 + bool "96348 ADSL board" + select DMA_NONCOHERENT + +config BCM96358 + bool "96358 ADSL board" + select DMA_NONCOHERENT + +endchoice + +config BCM_BOARD + bool "Support for Broadcom Board" + depends on BCM96338 || BCM96348 || BCM96358 + +config BCM_SERIAL + bool "Support for Serial Port" + depends on BCM96338 || BCM96348 || BCM96358 + +config BCM_ENET + tristate "Support for Ethernet" + depends on BCM96338 || BCM96348 || BCM96358 + +config BCM_USB + tristate "Support for USB" + depends on BCM96338 || BCM96348 || BCM96358 + +config BCM_WLAN + tristate "Support for Wireless" + depends on BCM96338 || BCM96348 || BCM96358 + +config BCM_MIMO + bool "EWC 802.11n MIMO Support" + depends on BCM96338 || BCM96348 || BCM96358 + +config BCM_PCI + bool "Support for PCI" + depends on BCM96338 || BCM96348 || BCM96358 + select PCI + +config BCM_ATMAPI + tristate "Support for ATM" + depends on BCM96338 || BCM96348 || BCM96358 + +config BCM_ATMTEST + tristate "Support for ATM Diagnostic" + depends on BCM96338 || BCM96348 || BCM96358 + +config BCM_ADSL + tristate "Support for ADSL" + depends on BCM96338 || BCM96348 || BCM96358 + +config BCM_ENDPOINT + tristate "Support for VOICE" + depends on BCM96338 || BCM96348 || BCM96358 + +config BCM_BCMPROF + tristate "Support for profiling" + depends on BCM96338 || BCM96348 || BCM96358 + +config BCM_PROCFS + tristate "Support for PROCFS" + depends on BCM96338 || BCM96348 || BCM96358 + +config BCM_VDSL + tristate "Support for VDSL" + depends on BCM96338 || BCM96348 || BCM96358 + +config BCM_SECURITY + tristate "Support for SECURITY" + depends on BCM96338 || BCM96348 || BCM96358 + +config BCM_HPNA + tristate "Support for HPNA" + depends on BCM96338 || BCM96348 || BCM96358 + +config BCM_BOARD_IMPL + int "Implementation index for ADSL Board" + depends on BCM96338 || BCM96348 || BCM96358 + +config BCM_SERIAL_IMPL + int "Implementation index for Serial" + depends on BCM96338 || BCM96348 || BCM96358 + +config BCM_ENET_IMPL + int "Implementation index for Ethernet" + depends on BCM96338 || BCM96348 || BCM96358 + +config BCM_USB_IMPL + int "Implementation index for USB" + depends on BCM96338 || BCM96348 || BCM96358 + +config BCM_WLAN_IMPL + int "Implementation index for WIRELESS" + depends on BCM96338 || BCM96348 || BCM96358 + +config BCM_ATMAPI_IMPL + int "Implementation index for ATM" + depends on BCM96338 || BCM96348 || BCM96358 + +config BCM_ATMTEST_IMPL + int "Implementation index for ATM Diagnostic" + depends on BCM96338 || BCM96348 || BCM96358 + +config BCM_BLAA_IMPL + int "Implementation index for BLAA" + depends on BCM96338 || BCM96348 || BCM96358 + +config BCM_ADSL_IMPL + int "Implementation index for ADSL" + depends on BCM96338 || BCM96348 || BCM96358 + +config BCM_ENDPOINT_IMPL + int "Implementation index for VOICE" + depends on BCM96338 || BCM96348 || BCM96358 + +config BCM_BCMPROF_IMPL + int "Implementation index for PROFILING" + depends on BCM96338 || BCM96348 || BCM96358 + +config BCM_PROCFS_IMPL + int "Implementation index for PROCFS" + depends on BCM96338 || BCM96348 || BCM96358 + +config BCM_SECURITY_IMPL + int "Implementation index for SECURITY" + depends on BCM96338 || BCM96348 || BCM96358 + +config BCM_HPNA_IMPL + int "Implementation index for HPNA" + depends on BCM96338 || BCM96348 || BCM96358 + +choice + prompt "Root File System" + depends on MIPS_BRCM + default ROOTFS_SQUASHFS + help + Select root file system on the board flash. + +config ROOTFS_SQUASHFS + bool "SQUASHFS" +config ROOTFS_CRAMFS + bool "CRAMFS" +config ROOTFS_JFFS2 + bool "JFFS2" +config ROOTFS_NFS + bool "NFS" + +endchoice + +config ROOT_FLASHFS + string "flash partition" + depends on ROOTFS_SQUASHFS || ROOTFS_CRAMFS || ROOTFS_JFFS2 + default "root=31:0 ro noinitrd" if ROOTFS_SQUASHFS = y || ROOTFS_CRAMFS = y + default "root=31:2 ro noinitrd" if ROOTFS_JFFS2 = y + help + This is the root file system partition on flash memory + +config ROOT_NFS_DIR + string "NFS server path" + depends on ROOTFS_NFS + default "/opt/bcm96338/targets/96338R/fs" if BCM96338 = y + default "/opt/bcm96348/targets/96348R/fs" if BCM96348 = y + default "/opt/bcm96358/targets/96358R/fs" if BCM96358 = y + help + This is the path of NFS server (host system) diff -Naur linux-mips-2.6.8.1-orig/arch/mips/brcm-boards/bcm963xx/Makefile linux-mips-2.6.8.1-bcm/arch/mips/brcm-boards/bcm963xx/Makefile --- linux-mips-2.6.8.1-orig/arch/mips/brcm-boards/bcm963xx/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/arch/mips/brcm-boards/bcm963xx/Makefile 2006-12-20 18:48:39.000000000 +0100 @@ -0,0 +1,23 @@ +# +# Makefile for generic Broadcom MIPS boards +# +# Copyright (C) 2004 Broadcom Corporation +# +obj-y := irq.o prom.o setup.o time.o ser_init.o + +SRCBASE := $(TOPDIR) +EXTRA_CFLAGS += -I$(INC_BRCMBOARDPARMS_PATH)/$(BRCM_BOARD) -I$(SRCBASE)/include -I$(INC_BRCMDRIVER_PUB_PATH)/$(BRCM_BOARD) -I$(INC_BRCMSHARED_PUB_PATH)/$(BRCM_BOARD) +#EXTRA_CFLAGS += -I$(INC_ADSLDRV_PATH) -DDBG +EXTRA_CFLAGS += -I$(INC_ADSLDRV_PATH) + + +ifeq "$(ADSL)" "ANNEX_B" +EXTRA_CFLAGS += -DADSL_ANNEXB +endif +ifeq "$(ADSL)" "SADSL" +EXTRA_CFLAGS += -DADSL_SADSL +endif +ifeq "$(ADSL)" "ANNEX_C" +EXTRA_CFLAGS += -DADSL_ANNEXC +endif + diff -Naur linux-mips-2.6.8.1-orig/arch/mips/brcm-boards/bcm963xx/prom.c linux-mips-2.6.8.1-bcm/arch/mips/brcm-boards/bcm963xx/prom.c --- linux-mips-2.6.8.1-orig/arch/mips/brcm-boards/bcm963xx/prom.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/arch/mips/brcm-boards/bcm963xx/prom.c 2006-12-20 18:48:39.000000000 +0100 @@ -0,0 +1,261 @@ +/* +<:copyright-gpl + Copyright 2004 Broadcom Corp. 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. +:> +*/ +/* + * prom.c: PROM library initialization code. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include "boardparms.h" +#include "softdsl/AdslCoreDefs.h" + + +extern int do_syslog(int, char *, int); +extern void serial_init(void); +extern void __init InitNvramInfo( void ); +extern void kerSysFlashInit( void ); +extern unsigned long get_nvram_start_addr(void); +void __init create_root_nfs_cmdline( char *cmdline ); + +#if defined(CONFIG_BCM96338) +#define CPU_CLOCK 240000000 +#define MACH_BCM MACH_BCM96338 +#endif +#if defined(CONFIG_BCM96348) +void __init calculateCpuSpeed(void); +static unsigned long cpu_speed; +#define CPU_CLOCK cpu_speed +#define MACH_BCM MACH_BCM96348 +#endif +#if defined(CONFIG_BCM96358) +void __init calculateCpuSpeed(void); +static unsigned long cpu_speed; +#define CPU_CLOCK cpu_speed +#define MACH_BCM MACH_BCM96358 +#endif + +const char *get_system_type(void) +{ + PNVRAM_DATA pNvramData = (PNVRAM_DATA) get_nvram_start_addr(); + + return( pNvramData->szBoardId ); +} + +unsigned long getMemorySize(void) +{ + unsigned long ulSdramType = BOARD_SDRAM_TYPE; + + unsigned long ulSdramSize; + + switch( ulSdramType ) + { + case BP_MEMORY_16MB_1_CHIP: + case BP_MEMORY_16MB_2_CHIP: + ulSdramSize = 16 * 1024 * 1024; + break; + case BP_MEMORY_32MB_1_CHIP: + case BP_MEMORY_32MB_2_CHIP: + ulSdramSize = 32 * 1024 * 1024; + break; + case BP_MEMORY_64MB_2_CHIP: + ulSdramSize = 64 * 1024 * 1024; + break; + default: + ulSdramSize = 8 * 1024 * 1024; + break; + } + + return ulSdramSize; +} + +/* -------------------------------------------------------------------------- + Name: prom_init + -------------------------------------------------------------------------- */ +void __init prom_init(void) +{ + extern ulong r4k_interval; + + serial_init(); + + kerSysFlashInit(); + + do_syslog(8, NULL, 8); + + printk( "%s prom init\n", get_system_type() ); + + PERF->IrqMask = 0; + + arcs_cmdline[0] = '\0'; + +#if defined(CONFIG_ROOT_NFS) + create_root_nfs_cmdline( arcs_cmdline ); +#elif defined(CONFIG_ROOT_FLASHFS) + strcpy(arcs_cmdline, CONFIG_ROOT_FLASHFS); +#endif + +#if defined(CONFIG_BCM96358) && defined(CONFIG_BCM_ENDPOINT_MODULE) + add_memory_region(0, (getMemorySize() - 1024*1024), BOOT_MEM_RAM); +#else + add_memory_region(0, (getMemorySize() - ADSL_SDRAM_IMAGE_SIZE), BOOT_MEM_RAM); +#endif + +#if defined(CONFIG_BCM96348) || defined(CONFIG_BCM96358) + calculateCpuSpeed(); +#endif + /* Count register increments every other clock */ + r4k_interval = CPU_CLOCK / HZ / 2; + mips_hpt_frequency = CPU_CLOCK / 2; + + mips_machgroup = MACH_GROUP_BRCM; + mips_machtype = MACH_BCM; +} + +/* -------------------------------------------------------------------------- + Name: prom_free_prom_memory +Abstract: + -------------------------------------------------------------------------- */ +void __init prom_free_prom_memory(void) +{ + +} + + +#if defined(CONFIG_ROOT_NFS) +/* This function reads in a line that looks something like this: + * + * + * CFE bootline=bcmEnet(0,0)host:vmlinux e=192.169.0.100:ffffff00 h=192.169.0.1 + * + * + * and retuns in the cmdline parameter some that looks like this: + * + * CONFIG_CMDLINE="root=/dev/nfs nfsroot=192.168.0.1:/opt/targets/96345R/fs + * ip=192.168.0.100:192.168.0.1::255.255.255.0::eth0:off rw" + */ +#define BOOT_LINE_ADDR 0x0 +#define HEXDIGIT(d) ((d >= '0' && d <= '9') ? (d - '0') : ((d | 0x20) - 'W')) +#define HEXBYTE(b) (HEXDIGIT((b)[0]) << 4) + HEXDIGIT((b)[1]) +extern unsigned long get_nvram_start_addr(void); + +void __init create_root_nfs_cmdline( char *cmdline ) +{ + char root_nfs_cl[] = "root=/dev/nfs nfsroot=%s:" CONFIG_ROOT_NFS_DIR + " ip=%s:%s::%s::eth0:off rw"; + + char *localip = NULL; + char *hostip = NULL; + char mask[16] = ""; + PNVRAM_DATA pNvramData = (PNVRAM_DATA) get_nvram_start_addr(); + char bootline[128] = ""; + char *p = bootline; + + memcpy(bootline, pNvramData->szBootline, sizeof(bootline)); + while( *p ) + { + if( p[0] == 'e' && p[1] == '=' ) + { + /* Found local ip address */ + p += 2; + localip = p; + while( *p && *p != ' ' && *p != ':' ) + p++; + if( *p == ':' ) + { + /* Found network mask (eg FFFFFF00 */ + *p++ = '\0'; + sprintf( mask, "%u.%u.%u.%u", HEXBYTE(p), HEXBYTE(p + 2), + HEXBYTE(p + 4), HEXBYTE(p + 6) ); + p += 4; + } + else if( *p == ' ' ) + *p++ = '\0'; + } + else if( p[0] == 'h' && p[1] == '=' ) + { + /* Found host ip address */ + p += 2; + hostip = p; + while( *p && *p != ' ' ) + p++; + if( *p == ' ' ) + *p++ = '\0'; + } + else + p++; + } + + if( localip && hostip ) + sprintf( cmdline, root_nfs_cl, hostip, localip, hostip, mask ); +} +#endif + +#if defined(CONFIG_BCM96348) +/* ********************************************************************* + * calculateCpuSpeed() + * Calculate the BCM6348 CPU speed by reading the PLL strap register + * and applying the following formula: + * cpu_clk = (.25 * 64MHz freq) * (N1 + 1) * (N2 + 2) / (M1_CPU + 1) + * Input parameters: + * none + * Return value: + * none + ********************************************************************* */ +void __init calculateCpuSpeed(void) +{ + UINT32 pllStrap = PERF->PllStrap; + int n1 = (pllStrap & PLL_N1_MASK) >> PLL_N1_SHFT; + int n2 = (pllStrap & PLL_N2_MASK) >> PLL_N2_SHFT; + int m1cpu = (pllStrap & PLL_M1_CPU_MASK) >> PLL_M1_CPU_SHFT; + + cpu_speed = (16 * (n1 + 1) * (n2 + 2) / (m1cpu + 1)) * 1000000; +} +#endif + +#if defined(CONFIG_BCM96358) +/* ********************************************************************* + * calculateCpuSpeed() + * Calculate the BCM6358 CPU speed by reading the PLL Config register + * and applying the following formula: + * Fcpu_clk = (25 * MIPSDDR_NDIV) / MIPS_MDIV + * Input parameters: + * none + * Return value: + * none + ********************************************************************* */ +void __init calculateCpuSpeed(void) +{ + UINT32 pllConfig = DDR->MIPSDDRPLLConfig; + int numerator; + + cpu_speed = 64000000 / ((pllConfig & MIPS_MDIV_MASK) >> MIPS_MDIV_SHFT); + numerator = (((pllConfig & MIPSDDR_N2_MASK) >> MIPSDDR_N2_SHFT) * ((pllConfig & MIPSDDR_N1_MASK) >> MIPSDDR_N1_SHFT)); + cpu_speed = (cpu_speed * numerator) / 4; + +} +#endif diff -Naur linux-mips-2.6.8.1-orig/arch/mips/brcm-boards/bcm963xx/ser_init.c linux-mips-2.6.8.1-bcm/arch/mips/brcm-boards/bcm963xx/ser_init.c --- linux-mips-2.6.8.1-orig/arch/mips/brcm-boards/bcm963xx/ser_init.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/arch/mips/brcm-boards/bcm963xx/ser_init.c 2006-12-20 18:48:39.000000000 +0100 @@ -0,0 +1,175 @@ +/* +<:copyright-gpl + Copyright 2004 Broadcom Corp. 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. +:> +*/ +/* + * Broadcom bcm63xx serial port initialization, also prepare for printk + * by registering with console_init + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#define SER63XX_DEFAULT_BAUD 115200 +#define BD_BCM63XX_TIMER_CLOCK_INPUT (FPERIPH) +#define stUart ((volatile Uart * const) UART_BASE) + +// Transmit interrupts +#define TXINT (TXFIFOEMT | TXUNDERR | TXOVFERR) +// Receive interrupts +#define RXINT (RXFIFONE | RXOVFERR) + +/* -------------------------------------------------------------------------- + Name: serial_init + Purpose: Initalize the UART +-------------------------------------------------------------------------- */ +void __init serial_init(void) +{ + UINT32 tmpVal = SER63XX_DEFAULT_BAUD; + ULONG clockFreqHz; + + /* Dissable channel's receiver and transmitter. */ + stUart->control &= ~(BRGEN|TXEN|RXEN); + + /*--------------------------------------------------------------------*/ + /* Write the table value to the clock select register. */ + /* DPullen - this is the equation to use: */ + /* value = clockFreqHz / baud / 32-1; */ + /* (snmod) Actually you should also take into account any necessary */ + /* rounding. Divide by 16, look at lsb, if 0, divide by 2 */ + /* and subtract 1. If 1, just divide by 2 */ + /*--------------------------------------------------------------------*/ + clockFreqHz = BD_BCM63XX_TIMER_CLOCK_INPUT; + tmpVal = (clockFreqHz / tmpVal) / 16; + if( tmpVal & 0x01 ) + tmpVal /= 2; //Rounding up, so sub is already accounted for + else + tmpVal = (tmpVal / 2) - 1; // Rounding down so we must sub 1 + stUart->baudword = tmpVal; + + /* Finally, re-enable the transmitter and receiver. */ + stUart->control |= (BRGEN|TXEN|RXEN); + + stUart->config = (BITS8SYM | ONESTOP); + // Set the FIFO interrupt depth ... stUart->fifocfg = 0xAA; + stUart->fifoctl = RSTTXFIFOS | RSTRXFIFOS; + stUart->intMask = 0; + stUart->intMask = RXINT | TXINT; +} + + +/* prom_putc() + * Output a character to the UART + */ +void prom_putc(char c) +{ + /* Wait for Tx uffer to empty */ + while (! (READ16(stUart->intStatus) & TXFIFOEMT)); + /* Send character */ + stUart->Data = c; +} + +/* prom_puts() + * Write a string to the UART + */ +void prom_puts(const char *s) +{ + while (*s) { + if (*s == '\n') { + prom_putc('\r'); + } + prom_putc(*s++); + } +} + + +/* prom_getc_nowait() + * Returns a character from the UART + * Returns -1 if no characters available or corrupted + */ +int prom_getc_nowait(void) +{ + uint16 uStatus; + int cData = -1; + + uStatus = READ16(stUart->intStatus); + + if (uStatus & RXFIFONE) { /* Do we have a character? */ + cData = READ16(stUart->Data) & 0xff; /* Read character */ + if (uStatus & (RXFRAMERR | RXPARERR)) { /* If we got an error, throw it away */ + cData = -1; + } + } + + return cData; +} + +/* prom_getc() + * Returns a charcter from the serial port + * Will block until it receives a valid character +*/ +char prom_getc(void) +{ + int cData = -1; + + /* Loop until we get a valid character */ + while(cData == -1) { + cData = prom_getc_nowait(); + } + return (char) cData; +} + +/* prom_testc() + * Returns 0 if no characters available + */ +int prom_testc(void) +{ + uint16 uStatus; + + uStatus = READ16(stUart->intStatus); + + return (uStatus & RXFIFONE); +} + +#if CONFIG_REMOTE_DEBUG +/* Prevent other code from writing to the serial port */ +void _putc(char c) { } +void _puts(const char *ptr) { } +#else +/* Low level outputs call prom routines */ +void _putc(char c) { + prom_putc(c); +} +void _puts(const char *ptr) { + prom_puts(ptr); +} +#endif diff -Naur linux-mips-2.6.8.1-orig/arch/mips/brcm-boards/bcm963xx/setup.c linux-mips-2.6.8.1-bcm/arch/mips/brcm-boards/bcm963xx/setup.c --- linux-mips-2.6.8.1-orig/arch/mips/brcm-boards/bcm963xx/setup.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/arch/mips/brcm-boards/bcm963xx/setup.c 2006-12-20 18:48:39.000000000 +0100 @@ -0,0 +1,571 @@ +/* +<:copyright-gpl + Copyright 2002 Broadcom Corp. 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. +:> +*/ +/* + * Generic setup routines for Broadcom 963xx MIPS boards + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +extern void brcm_timer_setup(struct irqaction *irq); +extern unsigned long getMemorySize(void); + +#include + +#if defined(CONFIG_PCI) +#include +#include +#include +#endif + +/* This function should be in a board specific directory. For now, + * assume that all boards that include this file use a Broadcom chip + * with a soft reset bit in the PLL control register. + */ +static void brcm_machine_restart(char *command) +{ + PERF->pll_control |= SOFT_RESET; +} + +static void brcm_machine_halt(void) +{ + printk("System halted\n"); + while (1); +} + +#if defined(CONFIG_PCI) + +static void mpi_SetLocalPciConfigReg(uint32 reg, uint32 value) +{ + /* write index then value */ + MPI->pcicfgcntrl = PCI_CFG_REG_WRITE_EN + reg;; + MPI->pcicfgdata = value; +} + +static uint32 mpi_GetLocalPciConfigReg(uint32 reg) +{ + /* write index then get value */ + MPI->pcicfgcntrl = PCI_CFG_REG_WRITE_EN + reg;; + return MPI->pcicfgdata; +} + +/* + * mpi_ResetPcCard: Set/Reset the PcCard + */ +static void mpi_ResetPcCard(int cardtype, BOOL bReset) +{ + if (cardtype == MPI_CARDTYPE_NONE) { + return; + } + + if (cardtype == MPI_CARDTYPE_CARDBUS) { + bReset = ! bReset; + } + + if (bReset) { + MPI->pcmcia_cntl1 = (MPI->pcmcia_cntl1 & ~PCCARD_CARD_RESET); + } else { + MPI->pcmcia_cntl1 = (MPI->pcmcia_cntl1 | PCCARD_CARD_RESET); + } +} + +/* + * mpi_ConfigCs: Configure an MPI/EBI chip select + */ +static void mpi_ConfigCs(uint32 cs, uint32 base, uint32 size, uint32 flags) +{ + MPI->cs[cs].base = ((base & 0x1FFFFFFF) | size); + MPI->cs[cs].config = flags; +} + +/* + * mpi_InitPcmciaSpace + */ +static void mpi_InitPcmciaSpace(void) +{ + // ChipSelect 4 controls PCMCIA Memory accesses + mpi_ConfigCs(PCMCIA_COMMON_BASE, pcmciaMem, EBI_SIZE_1M, (EBI_WORD_WIDE|EBI_ENABLE)); + // ChipSelect 5 controls PCMCIA Attribute accesses + mpi_ConfigCs(PCMCIA_ATTRIBUTE_BASE, pcmciaAttr, EBI_SIZE_1M, (EBI_WORD_WIDE|EBI_ENABLE)); + // ChipSelect 6 controls PCMCIA I/O accesses + mpi_ConfigCs(PCMCIA_IO_BASE, pcmciaIo, EBI_SIZE_64K, (EBI_WORD_WIDE|EBI_ENABLE)); + + MPI->pcmcia_cntl2 = ((PCMCIA_ATTR_ACTIVE << RW_ACTIVE_CNT_BIT) | + (PCMCIA_ATTR_INACTIVE << INACTIVE_CNT_BIT) | + (PCMCIA_ATTR_CE_SETUP << CE_SETUP_CNT_BIT) | + (PCMCIA_ATTR_CE_HOLD << CE_HOLD_CNT_BIT)); + + MPI->pcmcia_cntl2 |= (PCMCIA_HALFWORD_EN | PCMCIA_BYTESWAP_DIS); +} + +/* + * cardtype_vcc_detect: PC Card's card detect and voltage sense connection + * + * CD1#/ CD2#/ VS1#/ VS2#/ Card Initial Vcc + * CCD1# CCD2# CVS1 CVS2 Type + * + * GND GND open open 16-bit 5 vdc + * + * GND GND GND open 16-bit 3.3 vdc + * + * GND GND open GND 16-bit x.x vdc + * + * GND GND GND GND 16-bit 3.3 & x.x vdc + * + *==================================================================== + * + * CVS1 GND CCD1# open CardBus 3.3 vdc + * + * GND CVS2 open CCD2# CardBus x.x vdc + * + * GND CVS1 CCD2# open CardBus y.y vdc + * + * GND CVS2 GND CCD2# CardBus 3.3 & x.x vdc + * + * CVS2 GND open CCD1# CardBus x.x & y.y vdc + * + * GND CVS1 CCD2# open CardBus 3.3, x.x & y.y vdc + * + */ +static int cardtype_vcc_detect(void) +{ + uint32 data32; + int cardtype; + + cardtype = MPI_CARDTYPE_NONE; + MPI->pcmcia_cntl1 = (CARDBUS_ENABLE|PCMCIA_GPIO_ENABLE); // Turn on the output enables and drive + // the CVS pins to 0. + data32 = MPI->pcmcia_cntl1; + switch (data32 & (CD2_IN|CD1_IN)) // Test CD1# and CD2#, see if card is plugged in. + { + case (CD2_IN|CD1_IN): // No Card is in the slot. + printk("MPI: No Card is in the PCMCIA slot\n"); + break; + + case CD2_IN: // Partial insertion, No CD2#. + printk("MPI: Card in the PCMCIA slot partial insertion, no CD2 signal\n"); + break; + + case CD1_IN: // Partial insertion, No CD1#. + printk("MPI: Card in the PCMCIA slot partial insertion, no CD1 signal\n"); + break; + + case 0x00000000: + MPI->pcmcia_cntl1 = (CARDBUS_ENABLE|PCMCIA_GPIO_ENABLE|VS2_OEN|VS1_OEN); + // Turn off the CVS output enables and + // float the CVS pins. + mdelay(1); + data32 = MPI->pcmcia_cntl1; + // Read the Register. + switch (data32 & (VS2_IN|VS1_IN)) // See what is on the CVS pins. + { + case 0x00000000: // CVS1 and CVS2 are tied to ground, only 1 option. + printk("MPI: Detected 3.3 & x.x 16-bit PCMCIA card\n"); + cardtype = MPI_CARDTYPE_PCMCIA; + break; + + case VS1_IN: // CVS1 is open or tied to CCD1/CCD2 and CVS2 is tied to ground. + // 2 valid voltage options. + switch (data32 & (CD2_IN|CD1_IN)) // Test the values of CCD1 and CCD2. + { + case (CD2_IN|CD1_IN): // CCD1 and CCD2 are tied to 1 of the CVS pins. + // This is not a valid combination. + printk("MPI: Unknown card plugged into slot\n"); + break; + + case CD2_IN: // CCD2 is tied to either CVS1 or CVS2. + MPI->pcmcia_cntl1 = (CARDBUS_ENABLE|PCMCIA_GPIO_ENABLE|VS2_OEN); // Drive CVS1 to a 0. + mdelay(1); + data32 = MPI->pcmcia_cntl1; + if (data32 & CD2_IN) { // CCD2 is tied to CVS2, not valid. + printk("MPI: Unknown card plugged into slot\n"); + } else { // CCD2 is tied to CVS1. + printk("MPI: Detected 3.3, x.x and y.y Cardbus card\n"); + cardtype = MPI_CARDTYPE_CARDBUS; + } + break; + + case CD1_IN: // CCD1 is tied to either CVS1 or CVS2. + // This is not a valid combination. + printk("MPI: Unknown card plugged into slot\n"); + break; + + case 0x00000000: // CCD1 and CCD2 are tied to ground. + printk("MPI: Detected x.x vdc 16-bit PCMCIA card\n"); + cardtype = MPI_CARDTYPE_PCMCIA; + break; + } + break; + + case VS2_IN: // CVS2 is open or tied to CCD1/CCD2 and CVS1 is tied to ground. + // 2 valid voltage options. + switch (data32 & (CD2_IN|CD1_IN)) // Test the values of CCD1 and CCD2. + { + case (CD2_IN|CD1_IN): // CCD1 and CCD2 are tied to 1 of the CVS pins. + // This is not a valid combination. + printk("MPI: Unknown card plugged into slot\n"); + break; + + case CD2_IN: // CCD2 is tied to either CVS1 or CVS2. + MPI->pcmcia_cntl1 = (CARDBUS_ENABLE|PCMCIA_GPIO_ENABLE|VS1_OEN);// Drive CVS2 to a 0. + mdelay(1); + data32 = MPI->pcmcia_cntl1; + if (data32 & CD2_IN) { // CCD2 is tied to CVS1, not valid. + printk("MPI: Unknown card plugged into slot\n"); + } else {// CCD2 is tied to CVS2. + printk("MPI: Detected 3.3 and x.x Cardbus card\n"); + cardtype = MPI_CARDTYPE_CARDBUS; + } + break; + + case CD1_IN: // CCD1 is tied to either CVS1 or CVS2. + // This is not a valid combination. + printk("MPI: Unknown card plugged into slot\n"); + break; + + case 0x00000000: // CCD1 and CCD2 are tied to ground. + cardtype = MPI_CARDTYPE_PCMCIA; + printk("MPI: Detected 3.3 vdc 16-bit PCMCIA card\n"); + break; + } + break; + + case (VS2_IN|VS1_IN): // CVS1 and CVS2 are open or tied to CCD1/CCD2. + // 5 valid voltage options. + + switch (data32 & (CD2_IN|CD1_IN)) // Test the values of CCD1 and CCD2. + { + case (CD2_IN|CD1_IN): // CCD1 and CCD2 are tied to 1 of the CVS pins. + // This is not a valid combination. + printk("MPI: Unknown card plugged into slot\n"); + break; + + case CD2_IN: // CCD2 is tied to either CVS1 or CVS2. + // CCD1 is tied to ground. + MPI->pcmcia_cntl1 = (CARDBUS_ENABLE|PCMCIA_GPIO_ENABLE|VS1_OEN);// Drive CVS2 to a 0. + mdelay(1); + data32 = MPI->pcmcia_cntl1; + if (data32 & CD2_IN) { // CCD2 is tied to CVS1. + printk("MPI: Detected y.y vdc Cardbus card\n"); + } else { // CCD2 is tied to CVS2. + printk("MPI: Detected x.x vdc Cardbus card\n"); + } + cardtype = MPI_CARDTYPE_CARDBUS; + break; + + case CD1_IN: // CCD1 is tied to either CVS1 or CVS2. + // CCD2 is tied to ground. + + MPI->pcmcia_cntl1 = (CARDBUS_ENABLE|PCMCIA_GPIO_ENABLE|VS1_OEN);// Drive CVS2 to a 0. + mdelay(1); + data32 = MPI->pcmcia_cntl1; + if (data32 & CD1_IN) {// CCD1 is tied to CVS1. + printk("MPI: Detected 3.3 vdc Cardbus card\n"); + } else { // CCD1 is tied to CVS2. + printk("MPI: Detected x.x and y.y Cardbus card\n"); + } + cardtype = MPI_CARDTYPE_CARDBUS; + break; + + case 0x00000000: // CCD1 and CCD2 are tied to ground. + cardtype = MPI_CARDTYPE_PCMCIA; + printk("MPI: Detected 5 vdc 16-bit PCMCIA card\n"); + break; + } + break; + + default: + printk("MPI: Unknown card plugged into slot\n"); + break; + + } + } + return cardtype; +} + +/* + * mpi_DetectPcCard: Detect the plugged in PC-Card + * Return: < 0 => Unknown card detected + * 0 => No card detected + * 1 => 16-bit card detected + * 2 => 32-bit CardBus card detected + */ +static int mpi_DetectPcCard(void) +{ + int cardtype; + + cardtype = cardtype_vcc_detect(); + switch(cardtype) { + case MPI_CARDTYPE_PCMCIA: + MPI->pcmcia_cntl1 &= ~(CARDBUS_ENABLE|PCMCIA_ENABLE|PCMCIA_GPIO_ENABLE); // disable enable bits + MPI->pcmcia_cntl1 |= (PCMCIA_ENABLE | PCMCIA_GPIO_ENABLE); + mpi_InitPcmciaSpace(); + mpi_ResetPcCard(cardtype, FALSE); + // Hold card in reset for 10ms + mdelay(10); + mpi_ResetPcCard(cardtype, TRUE); + // Let card come out of reset + mdelay(100); + break; + case MPI_CARDTYPE_CARDBUS: + // 8 => CardBus Enable + // 1 => PCI Slot Number + // C => Float VS1 & VS2 + MPI->pcmcia_cntl1 = (MPI->pcmcia_cntl1 & 0xFFFF0000) | + CARDBUS_ENABLE | + (CARDBUS_SLOT << 8)| + VS2_OEN | + VS1_OEN | PCMCIA_GPIO_ENABLE; + /* access to this memory window will be to/from CardBus */ + MPI->l2pmremap1 |= CARDBUS_MEM; + + // Need to reset the Cardbus Card. There's no CardManager to do this, + // and we need to be ready for PCI configuration. + mpi_ResetPcCard(cardtype, FALSE); + // Hold card in reset for 10ms + mdelay(10); + mpi_ResetPcCard(cardtype, TRUE); + // Let card come out of reset + mdelay(100); + break; + default: + break; + } + return cardtype; +} + +static int mpi_init(void) +{ + unsigned long data; + unsigned int chipid; + unsigned int chiprev; + unsigned int sdramsize; + unsigned int modesel; + + chipid = (PERF->RevID & 0xFFFF0000) >> 16; + chiprev = (PERF->RevID & 0xFF); + sdramsize = getMemorySize(); + +#if defined(CONFIG_BCM96348) + /* + * Init the pci interface + */ + data = GPIO->GPIOMode; // GPIO mode register + data |= GROUP2_PCI | GROUP1_MII_PCCARD; // PCI internal arbiter + Cardbus + GPIO->GPIOMode = data; // PCI internal arbiter +#endif + /* + * CardBus support is defaulted to Slot 0 + * because there is no external IDSEL for CardBus. To disable + * the CardBus and allow a standard PCI card in Slot 0 + * set the cbus_idsel field to 0x1f. + */ + /* + uData = MPI->pcmcia_cntl1; + uData |= CARDBUS_IDSEL; + MPI->pcmcia_cntl1 = uData; + */ + + // UBUS to PCI address range + // Memory Window 1. Used for devices in slot 0. Potentially can be CardBus + MPI->l2pmrange1 = ~(BCM_PCI_MEM_SIZE_16MB-1); + // UBUS to PCI Memory base address. This is akin to the ChipSelect base + // register. + MPI->l2pmbase1 = BCM_CB_MEM_BASE & BCM_PCI_ADDR_MASK; + // UBUS to PCI Remap Address. Replaces the masked address bits in the + // range register with this setting. + // Also, enable direct I/O and direct Memory accesses + MPI->l2pmremap1 = (BCM_PCI_MEM_BASE | MEM_WINDOW_EN); + + // Memory Window 2. Used for devices in other slots + MPI->l2pmrange2 = ~(BCM_PCI_MEM_SIZE_16MB-1); + // UBUS to PCI Memory base address. + MPI->l2pmbase2 = BCM_PCI_MEM_BASE & BCM_PCI_ADDR_MASK; + // UBUS to PCI Remap Address + MPI->l2pmremap2 = (BCM_PCI_MEM_BASE | MEM_WINDOW_EN); + + // Setup PCI I/O Window range. Give 64K to PCI I/O + MPI->l2piorange = ~(BCM_PCI_IO_SIZE_64KB-1); + // UBUS to PCI I/O base address + MPI->l2piobase = BCM_PCI_IO_BASE & BCM_PCI_ADDR_MASK; + // UBUS to PCI I/O Window remap + MPI->l2pioremap = (BCM_PCI_IO_BASE | MEM_WINDOW_EN); + + // enable PCI related GPIO pins and data swap between system and PCI bus + MPI->locbuscntrl = (EN_PCI_GPIO | DIR_U2P_NOSWAP); + + /* Enable BusMaster and Memory access mode */ + data = mpi_GetLocalPciConfigReg(PCI_COMMAND); + data |= (PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); + mpi_SetLocalPciConfigReg(PCI_COMMAND, data); + + /* Configure two 16 MByte PCI to System memory regions. */ + /* These memory regions are used when PCI device is a bus master */ + /* Accesses to the SDRAM from PCI bus will be "byte swapped" for this region */ + mpi_SetLocalPciConfigReg(PCI_BASE_ADDRESS_3, BCM_HOST_MEM_SPACE1); + +#if defined(CONFIG_BCM96348) + MPI->sp0remap = 0x0; +#else + MPI->sp0remap = MEM_WINDOW_EN; +#endif + + /* Accesses to the SDRAM from PCI bus will be "byte swapped" for this region */ + mpi_SetLocalPciConfigReg(PCI_BASE_ADDRESS_4, BCM_HOST_MEM_SPACE2); + +#if defined(CONFIG_BCM96348) + MPI->sp1remap = 0x0; +#else + MPI->sp1remap = MEM_WINDOW_EN; +#endif + + modesel = MPI->pcimodesel; + modesel &= ~PCI_INT_BUS_RD_PREFETCH; +#if defined(CONFIG_BCM96348) + modesel |= 0x80; +#else + modesel |= 0x100; +#endif + MPI->pcimodesel = modesel; + + if (!((chipid == 0x6348) && ((chiprev & 0xF0) == 0xa0))) { + MPI->sp0range = ~(sdramsize-1); + MPI->sp1range = ~(sdramsize-1); + } + /* + * Change PCI Cfg Reg. offset 0x40 to PCI memory read retry count infinity + * by set 0 in bit 8~15. This resolve read Bcm4306 srom return 0xffff in + * first read. + */ + data = mpi_GetLocalPciConfigReg(BRCM_PCI_CONFIG_TIMER); + data &= ~BRCM_PCI_CONFIG_TIMER_RETRY_MASK; + data |= 0x00000080; + mpi_SetLocalPciConfigReg(BRCM_PCI_CONFIG_TIMER, data); + + /* enable pci interrupt */ + MPI->locintstat |= (EXT_PCI_INT << 16); + +#if !defined(CONFIG_BCM_VDSL) + mpi_DetectPcCard(); +#endif + + ioport_resource.start = BCM_PCI_IO_BASE; + ioport_resource.end = BCM_PCI_IO_BASE + BCM_PCI_IO_SIZE_64KB; + + return 0; +} +#endif + +static int __init bcm63xx_hw_init(void) +{ +#if defined(CONFIG_PCI) + /* MPI initialization */ + mpi_init(); +#endif + +#if defined(CONFIG_USB) +#if defined(CONFIG_BCM96348) + PERF->blkEnables |= USBH_CLK_EN; + mdelay(100); + *USBH = USBH_BYTE_SWAP; +#else + USBH->SwapControl = EHCI_ENDIAN_SWAP | OHCI_ENDIAN_SWAP; + USBH->TestPortControl = 0x001c0020; +#endif +#endif + + return 0; +} + +arch_initcall(bcm63xx_hw_init); + +static int __init brcm63xx_setup(void) +{ + extern int panic_timeout; + + _machine_restart = brcm_machine_restart; + _machine_halt = brcm_machine_halt; + _machine_power_off = brcm_machine_halt; + + board_timer_setup = brcm_timer_setup; + + panic_timeout = 1; + + return 0; +} + +early_initcall(brcm63xx_setup); + +/*************************************************************************** + * C++ New and delete operator functions + ***************************************************************************/ + +/* void *operator new(unsigned int sz) */ +void *_Znwj(unsigned int sz) +{ + return( kmalloc(sz, GFP_KERNEL) ); +} + +/* void *operator new[](unsigned int sz)*/ +void *_Znaj(unsigned int sz) +{ + return( kmalloc(sz, GFP_KERNEL) ); +} + +/* placement new operator */ +/* void *operator new (unsigned int size, void *ptr) */ +void *ZnwjPv(unsigned int size, void *ptr) +{ + return ptr; +} + +/* void operator delete(void *m) */ +void _ZdlPv(void *m) +{ + kfree(m); +} + +/* void operator delete[](void *m) */ +void _ZdaPv(void *m) +{ + kfree(m); +} + +EXPORT_SYMBOL(_Znwj); +EXPORT_SYMBOL(_Znaj); +EXPORT_SYMBOL(ZnwjPv); +EXPORT_SYMBOL(_ZdlPv); +EXPORT_SYMBOL(_ZdaPv); + diff -Naur linux-mips-2.6.8.1-orig/arch/mips/brcm-boards/bcm963xx/time.c linux-mips-2.6.8.1-bcm/arch/mips/brcm-boards/bcm963xx/time.c --- linux-mips-2.6.8.1-orig/arch/mips/brcm-boards/bcm963xx/time.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/arch/mips/brcm-boards/bcm963xx/time.c 2006-12-20 18:48:39.000000000 +0100 @@ -0,0 +1,277 @@ +/* +<:copyright-gpl + Copyright 2004 Broadcom Corp. 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. +:> +*/ +/* + * Setup time for Broadcom 963xx MIPS boards + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +unsigned long r4k_interval; /* Amount to increment compare reg each time */ +static unsigned long r4k_cur; /* What counter should be at next timer irq */ + +/* Cycle counter value at the previous timer interrupt.. */ +static unsigned int timerhi = 0, timerlo = 0; + +extern volatile unsigned long wall_jiffies; + +/* Optional board-specific timer routine */ +void (*board_timer_interrupt)(int irq, void *dev_id, struct pt_regs * regs); + +static inline void ack_r4ktimer(unsigned long newval) +{ + write_c0_compare(newval); +} + +/* + * There are a lot of conceptually broken versions of the MIPS timer interrupt + * handler floating around. This one is rather different, but the algorithm + * is provably more robust. + */ +static irqreturn_t brcm_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + unsigned int count; + + if (r4k_interval == 0) + goto null; + + do { + do_timer(regs); + + if (board_timer_interrupt) + board_timer_interrupt(irq, dev_id, regs); + + r4k_cur += r4k_interval; + ack_r4ktimer(r4k_cur); + + } while (((count = (unsigned long)read_c0_count()) + - r4k_cur) < 0x7fffffff); + + if (!jiffies) { + /* + * If jiffies has overflowed in this timer_interrupt we must + * update the timer[hi]/[lo] to make do_fast_gettimeoffset() + * quotient calc still valid. -arca + */ + timerhi = timerlo = 0; + } else { + /* + * The cycle counter is only 32 bit which is good for about + * a minute at current count rates of upto 150MHz or so. + */ + timerhi += (count < timerlo); /* Wrap around */ + timerlo = count; + } + + return IRQ_HANDLED; + +null: + ack_r4ktimer(0); + return IRQ_NONE; +} + +static struct irqaction brcm_timer_action = { + .handler = brcm_timer_interrupt, + .flags = SA_INTERRUPT, + .mask = CPU_MASK_NONE, + .name = "timer", + .next = NULL, + .dev_id = brcm_timer_interrupt, +}; + + +void __init brcm_timer_setup(struct irqaction *irq) +{ + r4k_cur = (read_c0_count() + r4k_interval); + write_c0_compare(r4k_cur); + + /* we are using the cpu counter for timer interrupts */ + irq->handler = no_action; /* we use our own handler */ + setup_irq(MIPS_TIMER_INT, &brcm_timer_action); + set_c0_status(IE_IRQ5); +} + +#if 0 +/* This is for machines which generate the exact clock. */ +#define USECS_PER_JIFFY (1000000/HZ) +#define USECS_PER_JIFFY_FRAC (0x100000000*1000000/HZ&0xffffffff) + +static void call_do_div64_32( unsigned long *res, unsigned int high, + unsigned int low, unsigned long base ) +{ + do_div64_32(*res, high, low, base); +} + +/* + * FIXME: Does playing with the RP bit in c0_status interfere with this code? + */ +static unsigned long do_fast_gettimeoffset(void) +{ + u32 count; + unsigned long res, tmp; + + /* Last jiffy when do_fast_gettimeoffset() was called. */ + static unsigned long last_jiffies=0; + unsigned long quotient; + + /* + * Cached "1/(clocks per usec)*2^32" value. + * It has to be recalculated once each jiffy. + */ + static unsigned long cached_quotient=0; + + tmp = jiffies; + + quotient = cached_quotient; + + if (tmp && last_jiffies != tmp) { + last_jiffies = tmp; +#ifdef CONFIG_CPU_MIPS32 + if (last_jiffies != 0) { + + unsigned long r0; + /* gcc 3.0.1 gets an internal compiler error if there are two + * do_div64_32 inline macros. To work around this problem, + * do_div64_32 is called as a function. + */ + call_do_div64_32(&r0, timerhi, timerlo, tmp); + call_do_div64_32("ient, USECS_PER_JIFFY, + USECS_PER_JIFFY_FRAC, r0); + + cached_quotient = quotient; + + } +#else + __asm__(".set\tnoreorder\n\t" + ".set\tnoat\n\t" + ".set\tmips3\n\t" + "lwu\t%0,%2\n\t" + "dsll32\t$1,%1,0\n\t" + "or\t$1,$1,%0\n\t" + "ddivu\t$0,$1,%3\n\t" + "mflo\t$1\n\t" + "dsll32\t%0,%4,0\n\t" + "nop\n\t" + "ddivu\t$0,%0,$1\n\t" + "mflo\t%0\n\t" + ".set\tmips0\n\t" + ".set\tat\n\t" + ".set\treorder" + :"=&r" (quotient) + :"r" (timerhi), + "m" (timerlo), + "r" (tmp), + "r" (USECS_PER_JIFFY) + :"$1"); + cached_quotient = quotient; +#endif + } + + /* Get last timer tick in absolute kernel time */ + count = read_c0_count(); + + /* .. relative to previous jiffy (32 bits is enough) */ + count -= timerlo; + + __asm__("multu\t%1,%2\n\t" + "mfhi\t%0" + :"=r" (res) + :"r" (count), + "r" (quotient)); + + /* + * Due to possible jiffies inconsistencies, we need to check + * the result so that we'll get a timer that is monotonic. + */ + if (res >= USECS_PER_JIFFY) + res = USECS_PER_JIFFY-1; + + return res; +} + +void do_gettimeofday(struct timeval *tv) +{ + unsigned int flags; + + read_lock_irqsave (&xtime_lock, flags); + tv->tv_sec = xtime.tv_sec; + tv->tv_usec = xtime.tv_nsec/1000; + tv->tv_usec += do_fast_gettimeoffset(); + + /* + * xtime is atomically updated in timer_bh. jiffies - wall_jiffies + * is nonzero if the timer bottom half hasnt executed yet. + */ + if (jiffies - wall_jiffies) + tv->tv_usec += USECS_PER_JIFFY; + + read_unlock_irqrestore (&xtime_lock, flags); + + if (tv->tv_usec >= 1000000) { + tv->tv_usec -= 1000000; + tv->tv_sec++; + } +} + +EXPORT_SYMBOL(do_gettimeofday); + +int do_settimeofday(struct timespec *tv) +{ + write_lock_irq (&xtime_lock); + + /* This is revolting. We need to set the xtime.tv_usec correctly. + * However, the value in this location is is value at the last tick. + * Discover what correction gettimeofday would have done, and then + * undo it! + */ + tv->tv_nsec -= do_fast_gettimeoffset()*NSEC_PER_USEC; + + if (tv->tv_nsec < 0) { + tv->tv_nsec += 1000000*NSEC_PER_USEC; + tv->tv_sec--; + } + + xtime.tv_sec = tv->tv_sec; + xtime.tv_nsec = tv->tv_nsec; + time_adjust = 0; /* stop active adjtime() */ + time_status |= STA_UNSYNC; + time_maxerror = NTP_PHASE_LIMIT; + time_esterror = NTP_PHASE_LIMIT; + + write_unlock_irq (&xtime_lock); +} + +EXPORT_SYMBOL(do_settimeofday); + +#endif diff -Naur linux-mips-2.6.8.1-orig/arch/mips/brcm-boards/generic/dbg_io.c linux-mips-2.6.8.1-bcm/arch/mips/brcm-boards/generic/dbg_io.c --- linux-mips-2.6.8.1-orig/arch/mips/brcm-boards/generic/dbg_io.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/arch/mips/brcm-boards/generic/dbg_io.c 2006-12-20 18:48:39.000000000 +0100 @@ -0,0 +1,260 @@ +/* +<:copyright-gpl + Copyright 2003 Broadcom Corp. 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. +:> +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#undef PRNT /* define for debug printing */ + +#define UART16550_BAUD_2400 2400 +#define UART16550_BAUD_4800 4800 +#define UART16550_BAUD_9600 9600 +#define UART16550_BAUD_19200 19200 +#define UART16550_BAUD_38400 38400 +#define UART16550_BAUD_57600 57600 +#define UART16550_BAUD_115200 115200 + +#define UART16550_PARITY_NONE 0 +#define UART16550_PARITY_ODD 0x08 +#define UART16550_PARITY_EVEN 0x18 +#define UART16550_PARITY_MARK 0x28 +#define UART16550_PARITY_SPACE 0x38 + +#define UART16550_DATA_5BIT 0x0 +#define UART16550_DATA_6BIT 0x1 +#define UART16550_DATA_7BIT 0x2 +#define UART16550_DATA_8BIT 0x3 + +#define UART16550_STOP_1BIT 0x0 +#define UART16550_STOP_2BIT 0x4 + +volatile Uart * stUart = UART_BASE; + +#define WRITE16(addr, value) ((*(volatile UINT16 *)((ULONG)&addr)) = value) + +/* Low level UART routines from promcon.c */ +extern void prom_putc(char c); +extern char prom_getc(void); +extern int prom_getc_nowait(void); +extern int prom_testc(void); + +extern void set_debug_traps(void); +extern void breakpoint(void); +extern void enable_brcm_irq(unsigned int); +extern void set_async_breakpoint(unsigned int epc); + +#ifdef CONFIG_GDB_CONSOLE +extern void register_gdb_console(void); +#endif + +int gdb_initialized = 0; + +#define GDB_BUF_SIZE 512 /* power of 2, please */ + +static char gdb_buf[GDB_BUF_SIZE] ; +static int gdb_buf_in_inx ; +static atomic_t gdb_buf_in_cnt ; +static int gdb_buf_out_inx ; + +void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop) +{ + /* Do nothing, assume boot loader has already set up serial port */ + printk("debugInit called\n"); +} + +/* + * Get a char if available, return -1 if nothing available. + * Empty the receive buffer first, then look at the interface hardware. + */ +static int read_char(void) +{ + if (atomic_read(&gdb_buf_in_cnt) != 0) /* intr routine has q'd chars */ + { + int chr ; + + chr = gdb_buf[gdb_buf_out_inx++] ; + gdb_buf_out_inx &= (GDB_BUF_SIZE - 1) ; + atomic_dec(&gdb_buf_in_cnt) ; + return(chr) ; + } + return(prom_getc_nowait()) ; /* read from hardware */ +} /* read_char */ + +/* + * This is the receiver interrupt routine for the GDB stub. + * It will receive a limited number of characters of input + * from the gdb host machine and save them up in a buffer. + * + * When the gdb stub routine getDebugChar() is called it + * draws characters out of the buffer until it is empty and + * then reads directly from the serial port. + * + * We do not attempt to write chars from the interrupt routine + * since the stubs do all of that via putDebugChar() which + * writes one byte after waiting for the interface to become + * ready. + * + * The debug stubs like to run with interrupts disabled since, + * after all, they run as a consequence of a breakpoint in + * the kernel. + * + * Perhaps someone who knows more about the tty driver than I + * care to learn can make this work for any low level serial + * driver. + */ +static void gdb_interrupt(int irq, void *dev_id, struct pt_regs * regs) +{ + int chr ; + int more; + do + { + chr = prom_getc_nowait() ; + more = prom_testc(); + if (chr < 0) continue ; + + /* If we receive a Ctrl-C then this is GDB trying to break in */ + if (chr == 3) + { + /* Replace current instruction with breakpoint */ + set_async_breakpoint(regs->cp0_epc); + //breakpoint(); + } + +#ifdef PRNT + printk("gdb_interrupt: chr=%02x '%c', more = %x\n", + chr, chr > ' ' && chr < 0x7F ? chr : ' ', more) ; +#endif + + if (atomic_read(&gdb_buf_in_cnt) >= GDB_BUF_SIZE) + { /* buffer overflow, clear it */ + gdb_buf_in_inx = 0 ; + atomic_set(&gdb_buf_in_cnt, 0) ; + gdb_buf_out_inx = 0 ; + break ; + } + + gdb_buf[gdb_buf_in_inx++] = chr ; + gdb_buf_in_inx &= (GDB_BUF_SIZE - 1) ; + atomic_inc(&gdb_buf_in_cnt) ; + } + while (more !=0); + +} /* gdb_interrupt */ + +/* + * getDebugChar + * + * This is a GDB stub routine. It waits for a character from the + * serial interface and then returns it. If there is no serial + * interface connection then it returns a bogus value which will + * almost certainly cause the system to hang. + */ +int getDebugChar(void) +{ + volatile int chr ; + +#ifdef PRNT + printk("getDebugChar: ") ; +#endif + + while ( (chr = read_char()) < 0 ) ; + +#ifdef PRNT + printk("%c\n", chr > ' ' && chr < 0x7F ? chr : ' ') ; +#endif + return(chr) ; + +} /* getDebugChar */ + +/* + * putDebugChar + * + * This is a GDB stub routine. It waits until the interface is ready + * to transmit a char and then sends it. If there is no serial + * interface connection then it simply returns to its caller, having + * pretended to send the char. + */ +int putDebugChar(unsigned char chr) +{ +#ifdef PRNT + printk("putDebugChar: chr=%02x '%c'\n", chr, + chr > ' ' && chr < 0x7F ? chr : ' ') ; +#endif + + prom_putc(chr) ; /* this routine will wait */ + return 1; + +} /* putDebugChar */ + +/* Just a NULL routine for testing. */ +void gdb_null(void) +{ +} + +void rs_kgdb_hook(int tty_no) +{ + printk("rs_kgdb_hook: tty %d\n", tty_no); + + /* Call GDB routine to setup the exception vectors for the debugger */ + set_debug_traps(); + + printk("Breaking into debugger...\n"); + breakpoint(); + gdb_null() ; + printk("Connected.\n"); + + gdb_initialized = 1; + +#ifdef CONFIG_GDB_CONSOLE + register_gdb_console(); +#endif +} + +void kgdb_hook_irq() +{ + int retval ; + uint16 uMask; + + printk("GDB: Hooking UART interrupt\n"); + + retval = request_irq(INTERRUPT_ID_UART, + gdb_interrupt, + SA_INTERRUPT, + "GDB-stub", NULL); + + if (retval != 0) + printk("gdb_hook: request_irq(irq=%d) failed: %d\n", INTERRUPT_ID_UART, retval); + + // Enable UART config Rx not empty IRQ + uMask = READ16(stUart->intMask) ; + // printk("intMask: 0x%x\n", uMask); + WRITE16(stUart->intMask, uMask | RXFIFONE); +} + + diff -Naur linux-mips-2.6.8.1-orig/arch/mips/brcm-boards/generic/int-handler.S linux-mips-2.6.8.1-bcm/arch/mips/brcm-boards/generic/int-handler.S --- linux-mips-2.6.8.1-orig/arch/mips/brcm-boards/generic/int-handler.S 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/arch/mips/brcm-boards/generic/int-handler.S 2006-12-20 18:48:39.000000000 +0100 @@ -0,0 +1,59 @@ +/* +<:copyright-gpl + Copyright 2002 Broadcom Corp. 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. +:> +*/ +/* + * Generic interrupt handler for Broadcom MIPS boards + */ + +#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 noreorder + .set at + + jal brcm_irq_dispatch + move a0, sp + + j ret_from_irq + nop + + END(brcmIRQ) diff -Naur linux-mips-2.6.8.1-orig/arch/mips/brcm-boards/generic/Makefile linux-mips-2.6.8.1-bcm/arch/mips/brcm-boards/generic/Makefile --- linux-mips-2.6.8.1-orig/arch/mips/brcm-boards/generic/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/arch/mips/brcm-boards/generic/Makefile 2006-12-20 18:48:39.000000000 +0100 @@ -0,0 +1,11 @@ +# +# Makefile for generic Broadcom MIPS boards +# +# Copyright (C) 2001 Broadcom Corporation +# +obj-y := int-handler.o + +ifdef CONFIG_REMOTE_DEBUG +obj-y += dbg_io.o +endif + diff -Naur linux-mips-2.6.8.1-orig/arch/mips/defconfig linux-mips-2.6.8.1-bcm/arch/mips/defconfig --- linux-mips-2.6.8.1-orig/arch/mips/defconfig 2004-08-22 12:44:19.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/arch/mips/defconfig 1970-01-01 01:00:00.000000000 +0100 @@ -1,883 +0,0 @@ -# -# Automatically generated make config: don't edit -# -CONFIG_MIPS=y -# CONFIG_MIPS64 is not set -# CONFIG_64BIT is not set -CONFIG_MIPS32=y - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y -CONFIG_CLEAN_COMPILE=y -CONFIG_BROKEN_ON_SMP=y - -# -# General setup -# -CONFIG_SWAP=y -CONFIG_SYSVIPC=y -# CONFIG_POSIX_MQUEUE is not set -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y -# CONFIG_AUDIT is not set -CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_HOTPLUG is not set -CONFIG_IKCONFIG=y -CONFIG_IKCONFIG_PROC=y -CONFIG_EMBEDDED=y -CONFIG_KALLSYMS=y -# CONFIG_KALLSYMS_EXTRA_PASS is not set -CONFIG_FUTEX=y -CONFIG_EPOLL=y -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y -# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set - -# -# Loadable module support -# -CONFIG_MODULES=y -CONFIG_MODULE_UNLOAD=y -# CONFIG_MODULE_FORCE_UNLOAD is not set -CONFIG_OBSOLETE_MODPARM=y -CONFIG_MODVERSIONS=y -CONFIG_KMOD=y - -# -# Machine selection -# -# CONFIG_MACH_JAZZ is not set -# CONFIG_BAGET_MIPS is not set -# CONFIG_MACH_VR41XX is not set -# CONFIG_TOSHIBA_JMR3927 is not set -# CONFIG_MIPS_COBALT is not set -# CONFIG_MACH_DECSTATION is not set -# CONFIG_MIPS_EV64120 is not set -# CONFIG_MIPS_EV96100 is not set -# CONFIG_MIPS_IVR is not set -# CONFIG_LASAT is not set -# CONFIG_MIPS_ITE8172 is not set -# CONFIG_MIPS_ATLAS 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_MOMENCO_OCELOT_C is not set -# CONFIG_MOMENCO_JAGUAR_ATX is not set -# CONFIG_PMC_YOSEMITE 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_SGI_IP22=y -# CONFIG_SGI_IP32 is not set -# CONFIG_SOC_AU1X00 is not set -# CONFIG_SIBYTE_SB1xxx_SOC is not set -# CONFIG_SNI_RM200_PCI is not set -# CONFIG_TOSHIBA_RBTX4927 is not set -CONFIG_RWSEM_GENERIC_SPINLOCK=y -CONFIG_HAVE_DEC_LOCK=y -CONFIG_ARC=y -CONFIG_DMA_NONCOHERENT=y -# CONFIG_CPU_LITTLE_ENDIAN is not set -CONFIG_IRQ_CPU=y -CONFIG_SWAP_IO_SPACE=y -CONFIG_BOOT_ELF32=y -CONFIG_MIPS_L1_CACHE_SHIFT=5 -CONFIG_ARC32=y -# CONFIG_FB is not set -CONFIG_ARC_CONSOLE=y -CONFIG_ARC_PROMLIB=y - -# -# CPU selection -# -# CONFIG_CPU_MIPS32 is not set -# 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=y -# 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_RM9000 is not set -# CONFIG_CPU_SB1 is not set -CONFIG_PAGE_SIZE_4KB=y -# CONFIG_PAGE_SIZE_8KB is not set -# CONFIG_PAGE_SIZE_16KB is not set -# CONFIG_PAGE_SIZE_64KB is not set -CONFIG_BOARD_SCACHE=y -CONFIG_IP22_CPU_SCACHE=y -# CONFIG_64BIT_PHYS_ADDR is not set -# CONFIG_CPU_ADVANCED is not set -CONFIG_CPU_HAS_LLSC=y -CONFIG_CPU_HAS_LLDSCD=y -CONFIG_CPU_HAS_SYNC=y -# CONFIG_PREEMPT is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set - -# -# Bus options (PCI, PCMCIA, EISA, ISA, TC) -# -# CONFIG_EISA is not set -CONFIG_MMU=y - -# -# Executable file formats -# -CONFIG_BINFMT_ELF=y -CONFIG_BINFMT_MISC=m -CONFIG_TRAD_SIGNALS=y -CONFIG_BINFMT_IRIX=y - -# -# Device Drivers -# - -# -# Generic Driver Options -# -CONFIG_STANDALONE=y -CONFIG_PREVENT_FIRMWARE_BUILD=y - -# -# Memory Technology Devices (MTD) -# -# CONFIG_MTD is not set - -# -# Parallel port support -# -# CONFIG_PARPORT is not set - -# -# Plug and Play support -# - -# -# Block devices -# -# CONFIG_BLK_DEV_FD 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_LBD is not set - -# -# ATA/ATAPI/MFM/RLL support -# -# CONFIG_IDE is not set - -# -# SCSI device support -# -CONFIG_SCSI=y -CONFIG_SCSI_PROC_FS=y - -# -# SCSI support type (disk, tape, CD-ROM) -# -CONFIG_BLK_DEV_SD=y -CONFIG_CHR_DEV_ST=y -# CONFIG_CHR_DEV_OSST is not set -CONFIG_BLK_DEV_SR=y -# CONFIG_BLK_DEV_SR_VENDOR is not set -# CONFIG_CHR_DEV_SG is not set - -# -# Some SCSI devices (e.g. CD jukebox) support multiple LUNs -# -# CONFIG_SCSI_MULTI_LUN is not set -CONFIG_SCSI_CONSTANTS=y -# CONFIG_SCSI_LOGGING is not set - -# -# SCSI Transport Attributes -# -CONFIG_SCSI_SPI_ATTRS=m -# CONFIG_SCSI_FC_ATTRS is not set - -# -# SCSI low-level drivers -# -CONFIG_SGIWD93_SCSI=y -# CONFIG_SCSI_AIC7XXX_OLD is not set -# CONFIG_SCSI_SATA is not set -# CONFIG_SCSI_EATA_PIO is not set -# CONFIG_SCSI_DEBUG is not set - -# -# Multi-device support (RAID and LVM) -# -# CONFIG_MD is not set - -# -# Fusion MPT device support -# - -# -# IEEE 1394 (FireWire) support -# - -# -# I2O device support -# - -# -# Networking support -# -CONFIG_NET=y - -# -# Networking options -# -CONFIG_PACKET=y -CONFIG_PACKET_MMAP=y -CONFIG_NETLINK_DEV=y -CONFIG_UNIX=y -CONFIG_NET_KEY=y -CONFIG_INET=y -CONFIG_IP_MULTICAST=y -# CONFIG_IP_ADVANCED_ROUTER is not set -CONFIG_IP_PNP=y -# CONFIG_IP_PNP_DHCP is not set -CONFIG_IP_PNP_BOOTP=y -# CONFIG_IP_PNP_RARP is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_IP_MROUTE is not set -# CONFIG_ARPD is not set -# CONFIG_SYN_COOKIES is not set -CONFIG_INET_AH=m -CONFIG_INET_ESP=m -CONFIG_INET_IPCOMP=m - -# -# IP: Virtual Server Configuration -# -CONFIG_IP_VS=m -# CONFIG_IP_VS_DEBUG is not set -CONFIG_IP_VS_TAB_BITS=12 - -# -# IPVS transport protocol load balancing support -# -CONFIG_IP_VS_PROTO_TCP=y -CONFIG_IP_VS_PROTO_UDP=y -CONFIG_IP_VS_PROTO_ESP=y -CONFIG_IP_VS_PROTO_AH=y - -# -# IPVS scheduler -# -CONFIG_IP_VS_RR=m -CONFIG_IP_VS_WRR=m -CONFIG_IP_VS_LC=m -CONFIG_IP_VS_WLC=m -CONFIG_IP_VS_LBLC=m -CONFIG_IP_VS_LBLCR=m -CONFIG_IP_VS_DH=m -CONFIG_IP_VS_SH=m -CONFIG_IP_VS_SED=m -CONFIG_IP_VS_NQ=m - -# -# IPVS application helper -# -CONFIG_IP_VS_FTP=m -CONFIG_IPV6=m -CONFIG_IPV6_PRIVACY=y -CONFIG_INET6_AH=m -CONFIG_INET6_ESP=m -CONFIG_INET6_IPCOMP=m -CONFIG_IPV6_TUNNEL=m -CONFIG_NETFILTER=y -# CONFIG_NETFILTER_DEBUG is not set - -# -# IP: Netfilter Configuration -# -CONFIG_IP_NF_CONNTRACK=m -CONFIG_IP_NF_FTP=m -CONFIG_IP_NF_IRC=m -CONFIG_IP_NF_TFTP=m -CONFIG_IP_NF_AMANDA=m -CONFIG_IP_NF_QUEUE=m -CONFIG_IP_NF_IPTABLES=m -CONFIG_IP_NF_MATCH_LIMIT=m -CONFIG_IP_NF_MATCH_IPRANGE=m -CONFIG_IP_NF_MATCH_MAC=m -CONFIG_IP_NF_MATCH_PKTTYPE=m -CONFIG_IP_NF_MATCH_MARK=m -CONFIG_IP_NF_MATCH_MULTIPORT=m -CONFIG_IP_NF_MATCH_TOS=m -CONFIG_IP_NF_MATCH_RECENT=m -CONFIG_IP_NF_MATCH_ECN=m -CONFIG_IP_NF_MATCH_DSCP=m -CONFIG_IP_NF_MATCH_AH_ESP=m -CONFIG_IP_NF_MATCH_LENGTH=m -CONFIG_IP_NF_MATCH_TTL=m -CONFIG_IP_NF_MATCH_TCPMSS=m -CONFIG_IP_NF_MATCH_HELPER=m -CONFIG_IP_NF_MATCH_STATE=m -CONFIG_IP_NF_MATCH_CONNTRACK=m -CONFIG_IP_NF_MATCH_OWNER=m -CONFIG_IP_NF_FILTER=m -CONFIG_IP_NF_TARGET_REJECT=m -CONFIG_IP_NF_NAT=m -CONFIG_IP_NF_NAT_NEEDED=y -CONFIG_IP_NF_TARGET_MASQUERADE=m -CONFIG_IP_NF_TARGET_REDIRECT=m -CONFIG_IP_NF_TARGET_NETMAP=m -CONFIG_IP_NF_TARGET_SAME=m -CONFIG_IP_NF_NAT_LOCAL=y -CONFIG_IP_NF_NAT_SNMP_BASIC=m -CONFIG_IP_NF_NAT_IRC=m -CONFIG_IP_NF_NAT_FTP=m -CONFIG_IP_NF_NAT_TFTP=m -CONFIG_IP_NF_NAT_AMANDA=m -CONFIG_IP_NF_MANGLE=m -CONFIG_IP_NF_TARGET_TOS=m -CONFIG_IP_NF_TARGET_ECN=m -CONFIG_IP_NF_TARGET_DSCP=m -CONFIG_IP_NF_TARGET_MARK=m -CONFIG_IP_NF_TARGET_CLASSIFY=m -CONFIG_IP_NF_TARGET_LOG=m -CONFIG_IP_NF_TARGET_ULOG=m -CONFIG_IP_NF_TARGET_TCPMSS=m -CONFIG_IP_NF_ARPTABLES=m -CONFIG_IP_NF_ARPFILTER=m -CONFIG_IP_NF_ARP_MANGLE=m -CONFIG_IP_NF_COMPAT_IPCHAINS=m -CONFIG_IP_NF_COMPAT_IPFWADM=m -CONFIG_IP_NF_TARGET_NOTRACK=m -CONFIG_IP_NF_RAW=m -CONFIG_IP_NF_MATCH_ADDRTYPE=m -CONFIG_IP_NF_MATCH_REALM=m - -# -# IPv6: Netfilter Configuration -# -CONFIG_IP6_NF_QUEUE=m -CONFIG_IP6_NF_IPTABLES=m -CONFIG_IP6_NF_MATCH_LIMIT=m -CONFIG_IP6_NF_MATCH_MAC=m -CONFIG_IP6_NF_MATCH_RT=m -CONFIG_IP6_NF_MATCH_OPTS=m -CONFIG_IP6_NF_MATCH_FRAG=m -CONFIG_IP6_NF_MATCH_HL=m -CONFIG_IP6_NF_MATCH_MULTIPORT=m -CONFIG_IP6_NF_MATCH_OWNER=m -CONFIG_IP6_NF_MATCH_MARK=m -CONFIG_IP6_NF_MATCH_IPV6HEADER=m -CONFIG_IP6_NF_MATCH_AHESP=m -CONFIG_IP6_NF_MATCH_LENGTH=m -CONFIG_IP6_NF_MATCH_EUI64=m -CONFIG_IP6_NF_FILTER=m -CONFIG_IP6_NF_TARGET_LOG=m -CONFIG_IP6_NF_MANGLE=m -CONFIG_IP6_NF_TARGET_MARK=m -CONFIG_IP6_NF_RAW=m -CONFIG_XFRM=y -CONFIG_XFRM_USER=m - -# -# SCTP Configuration (EXPERIMENTAL) -# -CONFIG_IP_SCTP=m -# CONFIG_SCTP_DBG_MSG is not set -# CONFIG_SCTP_DBG_OBJCNT is not set -# CONFIG_SCTP_HMAC_NONE is not set -# CONFIG_SCTP_HMAC_SHA1 is not set -CONFIG_SCTP_HMAC_MD5=y -# CONFIG_ATM is not set -# CONFIG_BRIDGE is not set -# CONFIG_VLAN_8021Q is not set -# CONFIG_DECNET is not set -# CONFIG_LLC2 is not set -# CONFIG_IPX is not set -# CONFIG_ATALK is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -CONFIG_NET_DIVERT=y -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_NET_HW_FLOWCONTROL is not set - -# -# QoS and/or fair queueing -# -CONFIG_NET_SCHED=y -# CONFIG_NET_SCH_CLK_JIFFIES is not set -CONFIG_NET_SCH_CLK_GETTIMEOFDAY=y -# CONFIG_NET_SCH_CLK_CPU is not set -CONFIG_NET_SCH_CBQ=m -CONFIG_NET_SCH_HTB=m -CONFIG_NET_SCH_HFSC=m -CONFIG_NET_SCH_PRIO=m -CONFIG_NET_SCH_RED=m -CONFIG_NET_SCH_SFQ=m -CONFIG_NET_SCH_TEQL=m -CONFIG_NET_SCH_TBF=m -CONFIG_NET_SCH_GRED=m -CONFIG_NET_SCH_DSMARK=m -CONFIG_NET_SCH_NETEM=m -CONFIG_NET_SCH_INGRESS=m -CONFIG_NET_QOS=y -CONFIG_NET_ESTIMATOR=y -CONFIG_NET_CLS=y -CONFIG_NET_CLS_TCINDEX=m -CONFIG_NET_CLS_ROUTE4=m -CONFIG_NET_CLS_ROUTE=y -CONFIG_NET_CLS_FW=m -CONFIG_NET_CLS_U32=m -# CONFIG_CLS_U32_PERF is not set -# CONFIG_NET_CLS_IND is not set -CONFIG_NET_CLS_RSVP=m -CONFIG_NET_CLS_RSVP6=m -# CONFIG_NET_CLS_ACT is not set -CONFIG_NET_CLS_POLICE=y - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set -# CONFIG_HAMRADIO is not set -# CONFIG_IRDA is not set -# CONFIG_BT is not set -CONFIG_NETDEVICES=y -CONFIG_DUMMY=m -CONFIG_BONDING=m -CONFIG_EQUALIZER=m -CONFIG_TUN=m -CONFIG_ETHERTAP=m - -# -# Ethernet (10 or 100Mbit) -# -CONFIG_NET_ETHERNET=y -# CONFIG_MII is not set -CONFIG_SGISEEQ=y - -# -# Ethernet (1000 Mbit) -# - -# -# Ethernet (10000 Mbit) -# - -# -# Token Ring devices -# - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set - -# -# Wan interfaces -# -# CONFIG_WAN is not set -# CONFIG_PPP is not set -# CONFIG_SLIP is not set -# CONFIG_SHAPER is not set -# CONFIG_NETCONSOLE is not set - -# -# ISDN subsystem -# -# CONFIG_ISDN is not set - -# -# Telephony Support -# -# CONFIG_PHONE is not set - -# -# Input device support -# -CONFIG_INPUT=y - -# -# Userland interfaces -# -CONFIG_INPUT_MOUSEDEV=y -CONFIG_INPUT_MOUSEDEV_PSAUX=y -CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 -CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 -# CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_TSDEV is not set -# CONFIG_INPUT_EVDEV is not set -# CONFIG_INPUT_EVBUG is not set - -# -# Input I/O drivers -# -# CONFIG_GAMEPORT is not set -CONFIG_SOUND_GAMEPORT=y -CONFIG_SERIO=y -CONFIG_SERIO_I8042=y -CONFIG_SERIO_SERPORT=y -# CONFIG_SERIO_CT82C710 is not set - -# -# Input Device Drivers -# -CONFIG_INPUT_KEYBOARD=y -CONFIG_KEYBOARD_ATKBD=y -# CONFIG_KEYBOARD_SUNKBD is not set -# CONFIG_KEYBOARD_LKKBD is not set -# CONFIG_KEYBOARD_XTKBD is not set -# CONFIG_KEYBOARD_NEWTON is not set -# CONFIG_INPUT_MOUSE is not set -# CONFIG_INPUT_JOYSTICK is not set -# CONFIG_INPUT_TOUCHSCREEN is not set -# CONFIG_INPUT_MISC is not set - -# -# Character devices -# -CONFIG_VT=y -CONFIG_VT_CONSOLE=y -CONFIG_HW_CONSOLE=y -# CONFIG_SERIAL_NONSTANDARD is not set - -# -# Serial drivers -# -# CONFIG_SERIAL_8250 is not set - -# -# Non-8250 serial port support -# -CONFIG_SERIAL_IP22_ZILOG=m -CONFIG_SERIAL_CORE=m -CONFIG_UNIX98_PTYS=y -CONFIG_LEGACY_PTYS=y -CONFIG_LEGACY_PTY_COUNT=256 -# CONFIG_QIC02_TAPE is not set - -# -# IPMI -# -# CONFIG_IPMI_HANDLER is not set - -# -# Watchdog Cards -# -CONFIG_WATCHDOG=y -# CONFIG_WATCHDOG_NOWAYOUT is not set - -# -# Watchdog Device Drivers -# -# CONFIG_SOFT_WATCHDOG is not set -CONFIG_INDYDOG=m -# CONFIG_RTC is not set -CONFIG_SGI_DS1286=m -# CONFIG_GEN_RTC is not set -# CONFIG_DTLK is not set -# CONFIG_R3964 is not set - -# -# Ftape, the floppy tape device driver -# -# CONFIG_AGP is not set -# CONFIG_DRM is not set -CONFIG_RAW_DRIVER=m -CONFIG_MAX_RAW_DEVS=256 - -# -# I2C support -# -# CONFIG_I2C is not set - -# -# Dallas's 1-wire bus -# -# CONFIG_W1 is not set - -# -# Misc devices -# - -# -# Multimedia devices -# -# CONFIG_VIDEO_DEV is not set - -# -# Digital Video Broadcasting Devices -# -# CONFIG_DVB is not set - -# -# Graphics support -# - -# -# Console display driver support -# -# CONFIG_VGA_CONSOLE is not set -# CONFIG_MDA_CONSOLE is not set -CONFIG_SGI_NEWPORT_CONSOLE=y -CONFIG_DUMMY_CONSOLE=y -CONFIG_FONT_8x16=y - -# -# Logo configuration -# -CONFIG_LOGO=y -# CONFIG_LOGO_LINUX_MONO is not set -# CONFIG_LOGO_LINUX_VGA16 is not set -# CONFIG_LOGO_LINUX_CLUT224 is not set -CONFIG_LOGO_SGI_CLUT224=y - -# -# Sound -# -# CONFIG_SOUND is not set - -# -# USB support -# - -# -# USB Gadget Support -# -# CONFIG_USB_GADGET is not set - -# -# File systems -# -CONFIG_EXT2_FS=m -# CONFIG_EXT2_FS_XATTR is not set -CONFIG_EXT3_FS=y -CONFIG_EXT3_FS_XATTR=y -CONFIG_EXT3_FS_POSIX_ACL=y -CONFIG_EXT3_FS_SECURITY=y -CONFIG_JBD=y -# CONFIG_JBD_DEBUG is not set -CONFIG_FS_MBCACHE=y -# CONFIG_REISERFS_FS is not set -# CONFIG_JFS_FS is not set -CONFIG_FS_POSIX_ACL=y -CONFIG_XFS_FS=m -# CONFIG_XFS_RT is not set -CONFIG_XFS_QUOTA=y -CONFIG_XFS_SECURITY=y -# CONFIG_XFS_POSIX_ACL is not set -CONFIG_MINIX_FS=m -# CONFIG_ROMFS_FS is not set -CONFIG_QUOTA=y -# CONFIG_QFMT_V1 is not set -CONFIG_QFMT_V2=m -CONFIG_QUOTACTL=y -CONFIG_AUTOFS_FS=m -CONFIG_AUTOFS4_FS=m - -# -# CD-ROM/DVD Filesystems -# -CONFIG_ISO9660_FS=m -CONFIG_JOLIET=y -CONFIG_ZISOFS=y -CONFIG_ZISOFS_FS=m -CONFIG_UDF_FS=m -CONFIG_UDF_NLS=y - -# -# DOS/FAT/NT Filesystems -# -CONFIG_FAT_FS=m -CONFIG_MSDOS_FS=m -CONFIG_VFAT_FS=m -CONFIG_FAT_DEFAULT_CODEPAGE=437 -CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" -# CONFIG_NTFS_FS is not set - -# -# Pseudo filesystems -# -CONFIG_PROC_FS=y -CONFIG_PROC_KCORE=y -CONFIG_SYSFS=y -# CONFIG_DEVFS_FS is not set -CONFIG_DEVPTS_FS_XATTR=y -CONFIG_DEVPTS_FS_SECURITY=y -# CONFIG_TMPFS is not set -# CONFIG_HUGETLB_PAGE is not set -CONFIG_RAMFS=y - -# -# Miscellaneous filesystems -# -# CONFIG_ADFS_FS is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_HFSPLUS_FS is not set -# CONFIG_BEFS_FS is not set -# CONFIG_BFS_FS is not set -CONFIG_EFS_FS=m -# CONFIG_CRAMFS is not set -# CONFIG_VXFS_FS is not set -# CONFIG_HPFS_FS is not set -# CONFIG_QNX4FS_FS is not set -# CONFIG_SYSV_FS is not set -CONFIG_UFS_FS=m -# CONFIG_UFS_FS_WRITE is not set - -# -# Network File Systems -# -CONFIG_NFS_FS=m -CONFIG_NFS_V3=y -# CONFIG_NFS_V4 is not set -# CONFIG_NFS_DIRECTIO is not set -CONFIG_NFSD=m -CONFIG_NFSD_V3=y -# CONFIG_NFSD_V4 is not set -CONFIG_NFSD_TCP=y -CONFIG_LOCKD=m -CONFIG_LOCKD_V4=y -CONFIG_EXPORTFS=m -CONFIG_SUNRPC=m -CONFIG_SUNRPC_GSS=m -CONFIG_RPCSEC_GSS_KRB5=m -CONFIG_SMB_FS=m -CONFIG_SMB_NLS_DEFAULT=y -CONFIG_SMB_NLS_REMOTE="cp437" -CONFIG_CIFS=m -# CONFIG_CIFS_STATS is not set -# CONFIG_CIFS_XATTR is not set -# CONFIG_CIFS_POSIX is not set -# CONFIG_NCP_FS is not set -CONFIG_CODA_FS=m -# CONFIG_CODA_FS_OLD_API is not set -# CONFIG_AFS_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=y -# CONFIG_BSD_DISKLABEL is not set -# CONFIG_MINIX_SUBPARTITION is not set -# CONFIG_SOLARIS_X86_PARTITION is not set -# CONFIG_UNIXWARE_DISKLABEL is not set -# CONFIG_LDM_PARTITION is not set -CONFIG_SGI_PARTITION=y -# CONFIG_ULTRIX_PARTITION is not set -# CONFIG_SUN_PARTITION is not set -# CONFIG_EFI_PARTITION is not set - -# -# Native Language Support -# -CONFIG_NLS=m -CONFIG_NLS_DEFAULT="iso8859-1" -CONFIG_NLS_CODEPAGE_437=m -CONFIG_NLS_CODEPAGE_737=m -CONFIG_NLS_CODEPAGE_775=m -CONFIG_NLS_CODEPAGE_850=m -CONFIG_NLS_CODEPAGE_852=m -CONFIG_NLS_CODEPAGE_855=m -CONFIG_NLS_CODEPAGE_857=m -CONFIG_NLS_CODEPAGE_860=m -CONFIG_NLS_CODEPAGE_861=m -CONFIG_NLS_CODEPAGE_862=m -CONFIG_NLS_CODEPAGE_863=m -CONFIG_NLS_CODEPAGE_864=m -CONFIG_NLS_CODEPAGE_865=m -CONFIG_NLS_CODEPAGE_866=m -CONFIG_NLS_CODEPAGE_869=m -CONFIG_NLS_CODEPAGE_936=m -CONFIG_NLS_CODEPAGE_950=m -CONFIG_NLS_CODEPAGE_932=m -CONFIG_NLS_CODEPAGE_949=m -CONFIG_NLS_CODEPAGE_874=m -CONFIG_NLS_ISO8859_8=m -CONFIG_NLS_CODEPAGE_1250=m -CONFIG_NLS_CODEPAGE_1251=m -CONFIG_NLS_ASCII=m -CONFIG_NLS_ISO8859_1=m -CONFIG_NLS_ISO8859_2=m -CONFIG_NLS_ISO8859_3=m -CONFIG_NLS_ISO8859_4=m -CONFIG_NLS_ISO8859_5=m -CONFIG_NLS_ISO8859_6=m -CONFIG_NLS_ISO8859_7=m -CONFIG_NLS_ISO8859_9=m -CONFIG_NLS_ISO8859_13=m -CONFIG_NLS_ISO8859_14=m -CONFIG_NLS_ISO8859_15=m -CONFIG_NLS_KOI8_R=m -CONFIG_NLS_KOI8_U=m -CONFIG_NLS_UTF8=m - -# -# Kernel hacking -# -CONFIG_CROSSCOMPILE=y -CONFIG_CMDLINE="" -# CONFIG_DEBUG_KERNEL is not set - -# -# Security options -# -# CONFIG_SECURITY is not set - -# -# Cryptographic options -# -CONFIG_CRYPTO=y -CONFIG_CRYPTO_HMAC=y -CONFIG_CRYPTO_NULL=y -CONFIG_CRYPTO_MD4=y -CONFIG_CRYPTO_MD5=y -CONFIG_CRYPTO_SHA1=y -CONFIG_CRYPTO_SHA256=y -CONFIG_CRYPTO_SHA512=y -CONFIG_CRYPTO_DES=y -CONFIG_CRYPTO_BLOWFISH=y -CONFIG_CRYPTO_TWOFISH=y -CONFIG_CRYPTO_SERPENT=y -CONFIG_CRYPTO_AES=m -CONFIG_CRYPTO_CAST5=m -CONFIG_CRYPTO_CAST6=m -CONFIG_CRYPTO_TEA=m -CONFIG_CRYPTO_ARC4=m -CONFIG_CRYPTO_KHAZAD=m -CONFIG_CRYPTO_DEFLATE=y -CONFIG_CRYPTO_MICHAEL_MIC=m -CONFIG_CRYPTO_CRC32C=m -CONFIG_CRYPTO_TEST=m - -# -# Library routines -# -# CONFIG_CRC_CCITT is not set -# CONFIG_CRC32 is not set -CONFIG_LIBCRC32C=m -CONFIG_ZLIB_INFLATE=y -CONFIG_ZLIB_DEFLATE=y diff -Naur linux-mips-2.6.8.1-orig/arch/mips/Kconfig linux-mips-2.6.8.1-bcm/arch/mips/Kconfig --- linux-mips-2.6.8.1-orig/arch/mips/Kconfig 2004-08-03 08:07:02.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/arch/mips/Kconfig 2006-12-20 18:48:49.000000000 +0100 @@ -27,6 +27,17 @@ menu "Machine selection" +# CONFIG_MIPS_BRCM Begin Broadcom changed code. + +config MIPS_BRCM + bool "Support for the Broadcom boards" + help + This is a family of boards based on the Broadcom MIPS32 + +source "arch/mips/brcm-boards/bcm963xx/Kconfig" + +# CONFIG_MIPS_BRCM End Broadcom changed code. + config MACH_JAZZ bool "Support for the Jazz family of machines" select ISA diff -Naur linux-mips-2.6.8.1-orig/arch/mips/kernel/cpu-probe.c linux-mips-2.6.8.1-bcm/arch/mips/kernel/cpu-probe.c --- linux-mips-2.6.8.1-orig/arch/mips/kernel/cpu-probe.c 2004-05-19 17:31:49.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/arch/mips/kernel/cpu-probe.c 2006-12-20 18:48:38.000000000 +0100 @@ -108,6 +108,9 @@ /* case CPU_20KC:*/ case CPU_24K: case CPU_25KF: +/* case CPU_BCM6338:*/ +/* case CPU_BCM6348:*/ +/* case CPU_BCM6358:*/ cpu_wait = r4k_wait; printk(" available.\n"); break; @@ -538,6 +541,27 @@ } } +#if defined(CONFIG_MIPS_BRCM) +static inline void cpu_probe_broadcom(struct cpuinfo_mips *c) +{ + decode_config1(c); + switch (c->processor_id & 0xff00) { + case PRID_IMP_BCM6338: + c->cputype = CPU_BCM6338; + break; + case PRID_IMP_BCM6348: + c->cputype = CPU_BCM6348; + break; + case PRID_IMP_BCM6358: + c->cputype = CPU_BCM6358; + break; + default: + c->cputype = CPU_UNKNOWN; + break; + } +} +#endif + static inline void cpu_probe_sandcraft(struct cpuinfo_mips *c) { decode_config1(c); @@ -576,6 +600,11 @@ case PRID_COMP_SIBYTE: cpu_probe_sibyte(c); break; +#if defined(CONFIG_MIPS_BRCM) + case PRID_COMP_BROADCOM: + cpu_probe_broadcom(c); + break; +#endif case PRID_COMP_SANDCRAFT: cpu_probe_sandcraft(c); diff -Naur linux-mips-2.6.8.1-orig/arch/mips/kernel/Makefile linux-mips-2.6.8.1-bcm/arch/mips/kernel/Makefile --- linux-mips-2.6.8.1-orig/arch/mips/kernel/Makefile 2004-06-24 23:49:57.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/arch/mips/kernel/Makefile 2006-12-20 18:48:38.000000000 +0100 @@ -8,6 +8,13 @@ ptrace.o reset.o semaphore.o setup.o signal.o syscall.o \ time.o traps.o unaligned.o +# CONFIG_MIPS_BRCM Begin Broadcom added code. +# gcc 3.4.x reorders code with -Os and -O2, breaking the save_static stuff. +CFLAGS_syscall.o := -O1 +CFLAGS_signal.o := -O1 +CFLAGS_signal32.o := -O1 +# CONFIG_MIPS_BRCM End Broadcom added code. + ifdef CONFIG_MODULES obj-y += mips_ksyms.o module.o obj-$(CONFIG_MIPS32) += module-elf32.o diff -Naur linux-mips-2.6.8.1-orig/arch/mips/kernel/proc.c linux-mips-2.6.8.1-bcm/arch/mips/kernel/proc.c --- linux-mips-2.6.8.1-orig/arch/mips/kernel/proc.c 2004-03-24 11:37:26.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/arch/mips/kernel/proc.c 2006-12-20 18:48:38.000000000 +0100 @@ -75,6 +75,11 @@ [CPU_VR4133] "NEC VR4133", [CPU_VR4181] "NEC VR4181", [CPU_VR4181A] "NEC VR4181A", +#if defined(CONFIG_MIPS_BRCM) + [CPU_BCM6338] "BCM6338", + [CPU_BCM6348] "BCM6348", + [CPU_BCM6358] "BCM6358", +#endif [CPU_SR71000] "Sandcraft SR71000" }; diff -Naur linux-mips-2.6.8.1-orig/arch/mips/kernel/setup.c linux-mips-2.6.8.1-bcm/arch/mips/kernel/setup.c --- linux-mips-2.6.8.1-orig/arch/mips/kernel/setup.c 2004-06-28 23:04:12.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/arch/mips/kernel/setup.c 2006-12-20 18:48:38.000000000 +0100 @@ -78,7 +78,9 @@ * mips_io_port_base is the begin of the address space to which x86 style * I/O ports are mapped. */ -const unsigned long mips_io_port_base = -1; + +const unsigned long mips_io_port_base = KSEG1; + EXPORT_SYMBOL(mips_io_port_base); /* diff -Naur linux-mips-2.6.8.1-orig/arch/mips/kernel/time.c linux-mips-2.6.8.1-bcm/arch/mips/kernel/time.c --- linux-mips-2.6.8.1-orig/arch/mips/kernel/time.c 2004-06-08 22:35:30.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/arch/mips/kernel/time.c 2006-12-20 18:48:38.000000000 +0100 @@ -274,11 +274,15 @@ /* .. relative to previous jiffy (32 bits is enough) */ count -= timerlo; - + __asm__("multu %1,%2" : "=h" (res) : "r" (count), "r" (sll32_usecs_per_cycle) +#if defined(CONFIG_MIPS_BRCM) + : "lo"); +#else : "lo", "accum"); +#endif /* * Due to possible jiffies inconsistencies, we need to check @@ -333,7 +337,11 @@ __asm__("multu %1,%2" : "=h" (res) : "r" (count), "r" (quotient) +#if defined(CONFIG_MIPS_BRCM) + : "lo"); +#else : "lo", "accum"); +#endif /* * Due to possible jiffies inconsistencies, we need to check @@ -375,7 +383,11 @@ : "r" (timerhi), "m" (timerlo), "r" (tmp), "r" (USECS_PER_JIFFY), "r" (USECS_PER_JIFFY_FRAC) +#if defined(CONFIG_MIPS_BRCM) + : "hi", "lo"); +#else : "hi", "lo", "accum"); +#endif cached_quotient = quotient; } } @@ -389,7 +401,11 @@ __asm__("multu %1,%2" : "=h" (res) : "r" (count), "r" (quotient) +#if defined(CONFIG_MIPS_BRCM) + : "lo"); +#else : "lo", "accum"); +#endif /* * Due to possible jiffies inconsistencies, we need to check @@ -738,6 +754,7 @@ board_timer_setup(&timer_irqaction); } + #define FEBRUARY 2 #define STARTOFTIME 1970 #define SECDAY 86400L diff -Naur linux-mips-2.6.8.1-orig/arch/mips/kernel/traps.c linux-mips-2.6.8.1-bcm/arch/mips/kernel/traps.c --- linux-mips-2.6.8.1-orig/arch/mips/kernel/traps.c 2004-06-28 23:04:12.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/arch/mips/kernel/traps.c 2006-12-20 18:48:38.000000000 +0100 @@ -246,6 +246,13 @@ static spinlock_t die_lock = SPIN_LOCK_UNLOCKED; +#if defined(CONFIG_MIPS_BRCM) +#ifdef CONFIG_REMOTE_DEBUG +#include +extern void handle_exception(struct gdb_regs *regs); +#endif +#endif + NORET_TYPE void __die(const char * str, struct pt_regs * regs, const char * file, const char * func, unsigned long line) { @@ -258,6 +265,29 @@ printk(" in %s:%s, line %ld", file, func, line); printk("[#%d]:\n", ++die_counter); show_registers(regs); +#if defined(CONFIG_MIPS_BRCM) +#ifdef CONFIG_REMOTE_DEBUG + { + struct gdb_regs regs2; + int i; + long *ptr; + + ptr = ®s2.reg0; + /* Copy registers to GDB structure */ + for(i=0; i<32;i++) + *ptr++ = regs->regs[i]; + + regs2.lo = regs->lo; + regs2.hi = regs->hi; + regs2.cp0_epc = regs->cp0_epc; + regs2.cp0_badvaddr = regs->cp0_badvaddr; + regs2.cp0_status = regs->cp0_status; + regs2.cp0_cause = regs->cp0_cause; + + handle_exception(®s2); /* Break to GDB */ + } +#endif +#endif spin_unlock_irq(&die_lock); do_exit(SIGSEGV); } diff -Naur linux-mips-2.6.8.1-orig/arch/mips/Makefile linux-mips-2.6.8.1-bcm/arch/mips/Makefile --- linux-mips-2.6.8.1-orig/arch/mips/Makefile 2004-07-01 00:05:24.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/arch/mips/Makefile 2006-12-20 18:48:49.000000000 +0100 @@ -41,8 +41,14 @@ endif ifdef CONFIG_CROSSCOMPILE +# CONFIG_MIPS_BRCM Begin Broadcom added code. +ifdef CONFIG_MIPS_BRCM +#CROSS_COMPILE := $(tool-prefix) +else CROSS_COMPILE := $(tool-prefix) endif +# CONFIG_MIPS_BRCM End Broadcom added code. +endif # # GCC uses -G 0 -mabicalls -fpic as default. We don't want PIC in the kernel @@ -57,6 +63,9 @@ cflags-y := -I $(TOPDIR)/include/asm/gcc cflags-y += -G 0 -mno-abicalls -fno-pic -pipe cflags-y += $(call check_gcc, -finline-limit=100000,) +ifeq ($(strip $(JTAG_KERNEL_DEBUG)),y) +cflags-y += -g +endif LDFLAGS_vmlinux += -G 0 -static -n MODFLAGS += -mlong-calls @@ -64,6 +73,12 @@ check_warning = $(shell if $(CC) $(1) -c -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi) +# CONFIG_MIPS_BRCM Begin Broadcom changed code. +ifdef CONFIG_MIPS_BRCM +cflags-$(CONFIG_REMOTE_DEBUG) += -ggdb +endif +# CONFIG_MIPS_BRCM End Broadcom changed code. + # # Use: $(call set_gccflags,,,,,) # @@ -302,6 +317,20 @@ libs-$(CONFIG_BAGET_MIPS) += arch/mips/baget/ arch/mips/baget/prom/ load-$(CONFIG_BAGET_MIPS) += 0x80001000 +# CONFIG_MIPS_BRCM Begin Broadcom added code. +ifdef CONFIG_MIPS_BRCM +# +# Broadcom board +core-$(CONFIG_BCM96338) += arch/mips/brcm-boards/generic/ arch/mips/brcm-boards/bcm963xx/ +cflags-$(CONFIG_BCM96338) += -Iinclude/asm-mips/mach-bcm963xx +core-$(CONFIG_BCM96348) += arch/mips/brcm-boards/generic/ arch/mips/brcm-boards/bcm963xx/ +cflags-$(CONFIG_BCM96348) += -Iinclude/asm-mips/mach-bcm963xx +core-$(CONFIG_BCM96358) += arch/mips/brcm-boards/generic/ arch/mips/brcm-boards/bcm963xx/ +cflags-$(CONFIG_BCM96358) += -Iinclude/asm-mips/mach-bcm963xx +load-$(CONFIG_MIPS_BRCM) += 0x80010000 +endif +# CONFIG_MIPS_BRCM End Broadcom added code. + # # Cobalt Server # diff -Naur linux-mips-2.6.8.1-orig/arch/mips/mm/c-r4k.c linux-mips-2.6.8.1-bcm/arch/mips/mm/c-r4k.c --- linux-mips-2.6.8.1-orig/arch/mips/mm/c-r4k.c 2004-07-16 14:06:13.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/arch/mips/mm/c-r4k.c 2006-12-20 18:48:47.000000000 +0100 @@ -803,6 +803,11 @@ if (!(config & MIPS_CONF_M)) panic("Don't know how to probe P-caches on this cpu."); +#if defined(CONFIG_MIPS_BRCM) + printk("brcm mips: enabling icache and dcache...\n"); + /* Enable caches */ + write_c0_diag(read_c0_diag() | 0xC0000000); +#endif /* * So we seem to be a MIPS32 or MIPS64 CPU * So let's probe the I-cache ... diff -Naur linux-mips-2.6.8.1-orig/arch/mips/mm/fault.c linux-mips-2.6.8.1-bcm/arch/mips/mm/fault.c --- linux-mips-2.6.8.1-orig/arch/mips/mm/fault.c 2004-04-19 18:36:35.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/arch/mips/mm/fault.c 2006-12-20 18:48:47.000000000 +0100 @@ -1,237 +1,237 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (C) 1995 - 2000 by Ralf Baechle - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include /* For unblank_screen() */ -#include - -#include -#include -#include -#include -#include -#include - -/* - * This routine handles page faults. It determines the address, - * and the problem, and then passes it off to one of the appropriate - * routines. - */ -asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long write, - unsigned long address) -{ - struct vm_area_struct * vma = NULL; - struct task_struct *tsk = current; - struct mm_struct *mm = tsk->mm; - const int field = sizeof(unsigned long) * 2; - siginfo_t info; - -#if 0 - printk("Cpu%d[%s:%d:%0*lx:%ld:%0*lx]\n", smp_processor_id(), - current->comm, current->pid, field, address, write, - field, regs->cp0_epc); -#endif - - info.si_code = SEGV_MAPERR; - - /* - * We fault-in kernel-space virtual memory on-demand. The - * 'reference' page table is init_mm.pgd. - * - * NOTE! We MUST NOT take any locks for this case. We may - * be in an interrupt or a critical region, and should - * only copy the information from the master page table, - * nothing more. - */ - if (unlikely(address >= VMALLOC_START)) - goto vmalloc_fault; - - /* - * If we're in an interrupt or have no user - * context, we must not take the fault.. - */ - if (in_atomic() || !mm) - goto bad_area_nosemaphore; - - down_read(&mm->mmap_sem); - vma = find_vma(mm, address); - if (!vma) - goto bad_area; - if (vma->vm_start <= address) - goto good_area; - if (!(vma->vm_flags & VM_GROWSDOWN)) - goto bad_area; - if (expand_stack(vma, address)) - goto bad_area; -/* - * Ok, we have a good vm_area for this memory access, so - * we can handle it.. - */ -good_area: - info.si_code = SEGV_ACCERR; - - if (write) { - if (!(vma->vm_flags & VM_WRITE)) - goto bad_area; - } else { - if (!(vma->vm_flags & (VM_READ | VM_EXEC))) - goto bad_area; - } - -survive: - /* - * If for any reason at all we couldn't handle the fault, - * make sure we exit gracefully rather than endlessly redo - * the fault. - */ - switch (handle_mm_fault(mm, vma, address, write)) { - case VM_FAULT_MINOR: - tsk->min_flt++; - break; - case VM_FAULT_MAJOR: - tsk->maj_flt++; - break; - case VM_FAULT_SIGBUS: - goto do_sigbus; - case VM_FAULT_OOM: - goto out_of_memory; - default: - BUG(); - } - - up_read(&mm->mmap_sem); - return; - -/* - * Something tried to access memory that isn't in our memory map.. - * Fix it, but check if it's kernel or user first.. - */ -bad_area: - up_read(&mm->mmap_sem); - -bad_area_nosemaphore: - /* User mode accesses just cause a SIGSEGV */ - if (user_mode(regs)) { - tsk->thread.cp0_badvaddr = address; - tsk->thread.error_code = write; -#if 0 - printk("do_page_fault() #2: sending SIGSEGV to %s for " - "invalid %s\n%0*lx (epc == %0*lx, ra == %0*lx)\n", - tsk->comm, - write ? "write access to" : "read access from", - field, address, - field, (unsigned long) regs->cp0_epc, - field, (unsigned long) regs->regs[31]); -#endif - info.si_signo = SIGSEGV; - info.si_errno = 0; - /* info.si_code has been set above */ - info.si_addr = (void *) address; - force_sig_info(SIGSEGV, &info, tsk); - return; - } - -no_context: - /* Are we prepared to handle this kernel fault? */ - if (fixup_exception(regs)) { - current->thread.cp0_baduaddr = address; - return; - } - - /* - * Oops. The kernel tried to access some bad page. We'll have to - * terminate things with extreme prejudice. - */ - - bust_spinlocks(1); - - printk(KERN_ALERT "CPU %d Unable to handle kernel paging request at " - "virtual address %0*lx, epc == %0*lx, ra == %0*lx\n", - smp_processor_id(), field, address, field, regs->cp0_epc, - field, regs->regs[31]); - die("Oops", regs); - -/* - * We ran out of memory, or some other thing happened to us that made - * us unable to handle the page fault gracefully. - */ -out_of_memory: - up_read(&mm->mmap_sem); - if (tsk->pid == 1) { - yield(); - down_read(&mm->mmap_sem); - goto survive; - } - printk("VM: killing process %s\n", tsk->comm); - if (user_mode(regs)) - do_exit(SIGKILL); - goto no_context; - -do_sigbus: - up_read(&mm->mmap_sem); - - /* Kernel mode? Handle exceptions or die */ - if (!user_mode(regs)) - goto no_context; - - /* - * Send a sigbus, regardless of whether we were in kernel - * or user mode. - */ - tsk->thread.cp0_badvaddr = address; - info.si_signo = SIGBUS; - info.si_errno = 0; - info.si_code = BUS_ADRERR; - info.si_addr = (void *) address; - force_sig_info(SIGBUS, &info, tsk); - - return; - -vmalloc_fault: - { - /* - * Synchronize this task's top level page-table - * with the 'reference' page table. - * - * Do _not_ use "tsk" here. We might be inside - * an interrupt in the middle of a task switch.. - */ - int offset = __pgd_offset(address); - pgd_t *pgd, *pgd_k; - pmd_t *pmd, *pmd_k; - pte_t *pte_k; - - pgd = (pgd_t *) pgd_current[smp_processor_id()] + offset; - pgd_k = init_mm.pgd + offset; - - if (!pgd_present(*pgd_k)) - goto no_context; - set_pgd(pgd, *pgd_k); - - pmd = pmd_offset(pgd, address); - pmd_k = pmd_offset(pgd_k, address); - if (!pmd_present(*pmd_k)) - goto no_context; - set_pmd(pmd, *pmd_k); - - pte_k = pte_offset_kernel(pmd_k, address); - if (!pte_present(*pte_k)) - goto no_context; - return; - } -} +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1995 - 2000 by Ralf Baechle + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* For unblank_screen() */ +#include + +#include +#include +#include +#include +#include +#include + +/* + * This routine handles page faults. It determines the address, + * and the problem, and then passes it off to one of the appropriate + * routines. + */ +asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long write, + unsigned long address) +{ + struct vm_area_struct * vma = NULL; + struct task_struct *tsk = current; + struct mm_struct *mm = tsk->mm; + const int field = sizeof(unsigned long) * 2; + siginfo_t info; + +#if 0 + printk("Cpu%d[%s:%d:%0*lx:%ld:%0*lx]\n", smp_processor_id(), + current->comm, current->pid, field, address, write, + field, regs->cp0_epc); +#endif + + info.si_code = SEGV_MAPERR; + + /* + * We fault-in kernel-space virtual memory on-demand. The + * 'reference' page table is init_mm.pgd. + * + * NOTE! We MUST NOT take any locks for this case. We may + * be in an interrupt or a critical region, and should + * only copy the information from the master page table, + * nothing more. + */ + if (unlikely(address >= VMALLOC_START)) + goto vmalloc_fault; + + /* + * If we're in an interrupt or have no user + * context, we must not take the fault.. + */ + if (in_atomic() || !mm) + goto bad_area_nosemaphore; + + down_read(&mm->mmap_sem); + vma = find_vma(mm, address); + if (!vma) + goto bad_area; + if (vma->vm_start <= address) + goto good_area; + if (!(vma->vm_flags & VM_GROWSDOWN)) + goto bad_area; + if (expand_stack(vma, address)) + goto bad_area; +/* + * Ok, we have a good vm_area for this memory access, so + * we can handle it.. + */ +good_area: + info.si_code = SEGV_ACCERR; + + if (write) { + if (!(vma->vm_flags & VM_WRITE)) + goto bad_area; + } else { + if (!(vma->vm_flags & (VM_READ | VM_EXEC))) + goto bad_area; + } + +survive: + /* + * If for any reason at all we couldn't handle the fault, + * make sure we exit gracefully rather than endlessly redo + * the fault. + */ + switch (handle_mm_fault(mm, vma, address, write)) { + case VM_FAULT_MINOR: + tsk->min_flt++; + break; + case VM_FAULT_MAJOR: + tsk->maj_flt++; + break; + case VM_FAULT_SIGBUS: + goto do_sigbus; + case VM_FAULT_OOM: + goto out_of_memory; + default: + BUG(); + } + + up_read(&mm->mmap_sem); + return; + +/* + * Something tried to access memory that isn't in our memory map.. + * Fix it, but check if it's kernel or user first.. + */ +bad_area: + up_read(&mm->mmap_sem); + +bad_area_nosemaphore: + /* User mode accesses just cause a SIGSEGV */ + if (user_mode(regs)) { + tsk->thread.cp0_badvaddr = address; + tsk->thread.error_code = write; +#if 1 + printk("do_page_fault() #2: sending SIGSEGV to %s for " + "invalid %s\n%0*lx (epc == %0*lx, ra == %0*lx)\n", + tsk->comm, + write ? "write access to" : "read access from", + field, address, + field, (unsigned long) regs->cp0_epc, + field, (unsigned long) regs->regs[31]); +#endif + info.si_signo = SIGSEGV; + info.si_errno = 0; + /* info.si_code has been set above */ + info.si_addr = (void *) address; + force_sig_info(SIGSEGV, &info, tsk); + return; + } + +no_context: + /* Are we prepared to handle this kernel fault? */ + if (fixup_exception(regs)) { + current->thread.cp0_baduaddr = address; + return; + } + + /* + * Oops. The kernel tried to access some bad page. We'll have to + * terminate things with extreme prejudice. + */ + + bust_spinlocks(1); + + printk(KERN_ALERT "CPU %d Unable to handle kernel paging request at " + "virtual address %0*lx, epc == %0*lx, ra == %0*lx\n", + smp_processor_id(), field, address, field, regs->cp0_epc, + field, regs->regs[31]); + die("Oops", regs); + +/* + * We ran out of memory, or some other thing happened to us that made + * us unable to handle the page fault gracefully. + */ +out_of_memory: + up_read(&mm->mmap_sem); + if (tsk->pid == 1) { + yield(); + down_read(&mm->mmap_sem); + goto survive; + } + printk("VM: killing process %s\n", tsk->comm); + if (user_mode(regs)) + do_exit(SIGKILL); + goto no_context; + +do_sigbus: + up_read(&mm->mmap_sem); + + /* Kernel mode? Handle exceptions or die */ + if (!user_mode(regs)) + goto no_context; + + /* + * Send a sigbus, regardless of whether we were in kernel + * or user mode. + */ + tsk->thread.cp0_badvaddr = address; + info.si_signo = SIGBUS; + info.si_errno = 0; + info.si_code = BUS_ADRERR; + info.si_addr = (void *) address; + force_sig_info(SIGBUS, &info, tsk); + + return; + +vmalloc_fault: + { + /* + * Synchronize this task's top level page-table + * with the 'reference' page table. + * + * Do _not_ use "tsk" here. We might be inside + * an interrupt in the middle of a task switch.. + */ + int offset = __pgd_offset(address); + pgd_t *pgd, *pgd_k; + pmd_t *pmd, *pmd_k; + pte_t *pte_k; + + pgd = (pgd_t *) pgd_current[smp_processor_id()] + offset; + pgd_k = init_mm.pgd + offset; + + if (!pgd_present(*pgd_k)) + goto no_context; + set_pgd(pgd, *pgd_k); + + pmd = pmd_offset(pgd, address); + pmd_k = pmd_offset(pgd_k, address); + if (!pmd_present(*pmd_k)) + goto no_context; + set_pmd(pmd, *pmd_k); + + pte_k = pte_offset_kernel(pmd_k, address); + if (!pte_present(*pte_k)) + goto no_context; + return; + } +} diff -Naur linux-mips-2.6.8.1-orig/arch/mips/pci/fixup-bcm63xx.c linux-mips-2.6.8.1-bcm/arch/mips/pci/fixup-bcm63xx.c --- linux-mips-2.6.8.1-orig/arch/mips/pci/fixup-bcm63xx.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/arch/mips/pci/fixup-bcm63xx.c 2006-12-20 18:48:43.000000000 +0100 @@ -0,0 +1,84 @@ +/* +<:copyright-gpl + Copyright 2002 Broadcom Corp. 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. +:> +*/ +#include +#include +#include + +#include +#include +#include + +static char irq_tab_bcm63xx[] __initdata = { + [0] = INTERRUPT_ID_MPI, + [1] = INTERRUPT_ID_MPI, +#if defined(CONFIG_USB) + [USB_HOST_SLOT] = INTERRUPT_ID_USBH, +#if !defined(CONFIG_BCM96348) + [USB20_HOST_SLOT] = INTERRUPT_ID_USBH20 +#endif +#endif +}; + +int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) +{ + return irq_tab_bcm63xx[slot]; +} + +static void bcm63xx_fixup(struct pci_dev *dev) +{ + uint32 memaddr; + uint32 size; + uint32 resno; + + memaddr = pci_resource_start(dev, 0); + size = pci_resource_len(dev, 0); + + switch (PCI_SLOT(dev->devfn)) { + case 0: + // Move device in slot 0 to a different memory range + // In case this is a CB device, it will be accessed via l2pmremap1 + // which will have CARDBUS_MEM bit set + for (resno = 0; resno < 6; resno++) { + if (dev->resource[resno].end && (dev->resource[resno].start < BCM_CB_MEM_BASE)) { + dev->resource[resno].start += (BCM_CB_MEM_BASE - BCM_PCI_MEM_BASE); + dev->resource[resno].end += (BCM_CB_MEM_BASE - BCM_PCI_MEM_BASE); + } + } + break; + +#if defined(CONFIG_USB) + case USB_HOST_SLOT: + dev->resource[0].start = USB_OHCI_BASE; + dev->resource[0].end = USB_OHCI_BASE+USB_BAR0_MEM_SIZE-1; + break; + +#if !defined(CONFIG_BCM96348) + case USB20_HOST_SLOT: + dev->resource[0].start = USB_EHCI_BASE; + dev->resource[0].end = USB_EHCI_BASE+USB_BAR0_MEM_SIZE-1; + break; +#endif +#endif + } +} + +struct pci_fixup pcibios_fixups[] = { + { PCI_FIXUP_FINAL, PCI_ANY_ID, PCI_ANY_ID, bcm63xx_fixup }, + {0} +}; diff -Naur linux-mips-2.6.8.1-orig/arch/mips/pci/Makefile linux-mips-2.6.8.1-bcm/arch/mips/pci/Makefile --- linux-mips-2.6.8.1-orig/arch/mips/pci/Makefile 2004-07-01 00:05:24.000000000 +0200 +++ linux-mips-2.6.8.1-bcm/arch/mips/pci/Makefile 2006-12-20 18:48:43.000000000 +0100 @@ -17,6 +17,8 @@ obj-$(CONFIG_MIPS_NILE4) += ops-nile4.o obj-$(CONFIG_MIPS_TX3927) += ops-jmr3927.o obj-$(CONFIG_PCI_VR41XX) += ops-vr41xx.o pci-vr41xx.o +obj-$(CONFIG_PCI_VR41XX) += ops-vr41xx.o pci-vr41xx.o +obj-$(CONFIG_BCM_PCI) += fixup-bcm63xx.o pci-bcm63xx.o ops-bcm63xx.o # # These are still pretty much in the old state, watch, go blind. @@ -51,3 +53,7 @@ obj-$(CONFIG_TOSHIBA_RBTX4927) += fixup-rbtx4927.o ops-tx4927.o obj-$(CONFIG_VICTOR_MPC30X) += fixup-mpc30x.o obj-$(CONFIG_ZAO_CAPCELLA) += fixup-capcella.o + +ifeq "$(CONFIG_BCM_PCI)" "y" +EXTRA_CFLAGS += -I$(INC_BRCMDRIVER_PUB_PATH)/$(BRCM_BOARD) -I$(INC_BRCMSHARED_PUB_PATH)/$(BRCM_BOARD) +endif diff -Naur linux-mips-2.6.8.1-orig/arch/mips/pci/ops-bcm63xx.c linux-mips-2.6.8.1-bcm/arch/mips/pci/ops-bcm63xx.c --- linux-mips-2.6.8.1-orig/arch/mips/pci/ops-bcm63xx.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/arch/mips/pci/ops-bcm63xx.c 2006-12-20 18:48:43.000000000 +0100 @@ -0,0 +1,408 @@ +/* +<:copyright-gpl + Copyright 2002 Broadcom Corp. 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. +:> +*/ +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#if defined(CONFIG_USB) +#if 0 +#define DPRINT(x...) printk(x) +#else +#define DPRINT(x...) +#endif + +static int pci63xx_int_usb_read(unsigned int devfn, int where, u32 * value, int size); +static int pci63xx_int_usb_write(unsigned int devfn, int where, u32 * value, int size); + +static bool usb_mem_size_rd = FALSE; +static uint32 usb_mem_base = 0; +static uint32 usb_cfg_space_cmd_reg = 0; + +#if !defined(CONFIG_BCM96348) +static int pci63xx_int_usb20_read(unsigned int devfn, int where, u32 * value, int size); +static int pci63xx_int_usb20_write(unsigned int devfn, int where, u32 * value, int size); + +static bool usb20_mem_size_rd = FALSE; +static uint32 usb20_mem_base = 0; +static uint32 usb20_cfg_space_cmd_reg = 0; +#endif + +#endif +static bool pci_mem_size_rd = FALSE; + +static volatile MpiRegisters * mpi = (MpiRegisters *)(MPI_BASE); + +static void mpi_SetupPciConfigAccess(uint32 addr) +{ + mpi->l2pcfgctl = (DIR_CFG_SEL | DIR_CFG_USEREG | addr) & ~CONFIG_TYPE; +} + +static void mpi_ClearPciConfigAccess(void) +{ + mpi->l2pcfgctl = 0x00000000; +} + +#if defined(CONFIG_USB) +/* -------------------------------------------------------------------------- + Name: pci63xx_int_usb_write +Abstract: PCI Config write on internal device(s) + -------------------------------------------------------------------------- */ +static int pci63xx_int_usb_write(unsigned int devfn, int where, u32 * value, int size) +{ + switch (size) { + case 1: + DPRINT("W => Slot: %d Where: %2X Len: %d Data: %02X\n", + PCI_SLOT(devfn), where, size, *value); + break; + case 2: + DPRINT("W => Slot: %d Where: %2X Len: %d Data: %04X\n", + PCI_SLOT(devfn), where, size, *value); + switch (where) { + case PCI_COMMAND: + usb_cfg_space_cmd_reg = *value; + break; + default: + break; + } + break; + case 4: + DPRINT("W => Slot: %d Where: %2X Len: %d Data: %08lX\n", + PCI_SLOT(devfn), where, size, *value); + switch (where) { + case PCI_BASE_ADDRESS_0: + if (*value == 0xffffffff) { + usb_mem_size_rd = TRUE; + } else { + usb_mem_base = *value; + } + break; + default: + break; + } + break; + default: + break; + } + + return PCIBIOS_SUCCESSFUL; +} + +/* -------------------------------------------------------------------------- + Name: pci63xx_int_usb_read +Abstract: PCI Config read on internal device(s) + -------------------------------------------------------------------------- */ +static int pci63xx_int_usb_read(unsigned int devfn, int where, u32 * value, int size) +{ + uint32 retValue = 0xFFFFFFFF; + + // For now, this is specific to the USB Host controller. We can + // make it more general if we have to... + // Emulate PCI Config accesses + switch (where) { + case PCI_VENDOR_ID: + case PCI_DEVICE_ID: + retValue = PCI_VENDOR_ID_BROADCOM | 0x63000000; + break; + case PCI_COMMAND: + case PCI_STATUS: + retValue = (0x0006 << 16) | usb_cfg_space_cmd_reg; + break; + case PCI_CLASS_REVISION: + case PCI_CLASS_DEVICE: + retValue = (PCI_CLASS_SERIAL_USB << 16) | (0x10 << 8) | 0x01; + break; + case PCI_BASE_ADDRESS_0: + if (usb_mem_size_rd) { + retValue = USB_BAR0_MEM_SIZE; + } else { + if (usb_mem_base != 0) + retValue = usb_mem_base; + else + retValue = USB_OHCI_BASE; + } + usb_mem_size_rd = FALSE; + break; + case PCI_CACHE_LINE_SIZE: + case PCI_LATENCY_TIMER: + retValue = 0; + break; + case PCI_HEADER_TYPE: + retValue = PCI_HEADER_TYPE_NORMAL; + break; + case PCI_SUBSYSTEM_VENDOR_ID: + retValue = PCI_VENDOR_ID_BROADCOM; + break; + case PCI_SUBSYSTEM_ID: + retValue = 0x6300; + break; + case PCI_INTERRUPT_LINE: + retValue = INTERRUPT_ID_USBH; + break; + default: + break; + } + + switch (size) { + case 1: + *value = (retValue >> ((where & 3) << 3)) & 0xff; + DPRINT("R <= Slot: %d Where: %2X Len: %d Data: %02X\n", + PCI_SLOT(devfn), where, size, *value); + break; + case 2: + *value = (retValue >> ((where & 3) << 3)) & 0xffff; + DPRINT("R <= Slot: %d Where: %2X Len: %d Data: %04X\n", + PCI_SLOT(devfn), where, size, *value); + break; + case 4: + *value = retValue; + DPRINT("R <= Slot: %d Where: %2X Len: %d Data: %08lX\n", + PCI_SLOT(devfn), where, size, *value); + break; + default: + break; + } + + return PCIBIOS_SUCCESSFUL; +} + +#if !defined(CONFIG_BCM96348) +/* -------------------------------------------------------------------------- + Name: pci63xx_int_usb20_write +Abstract: PCI Config write on internal device(s) + -------------------------------------------------------------------------- */ +static int pci63xx_int_usb20_write(unsigned int devfn, int where, u32 * value, int size) +{ + switch (size) { + case 1: + DPRINT("W => Slot: %d Where: %2X Len: %d Data: %02X\n", + PCI_SLOT(devfn), where, size, *value); + break; + case 2: + DPRINT("W => Slot: %d Where: %2X Len: %d Data: %04X\n", + PCI_SLOT(devfn), where, size, *value); + switch (where) { + case PCI_COMMAND: + usb20_cfg_space_cmd_reg = *value; + break; + default: + break; + } + break; + case 4: + DPRINT("W => Slot: %d Where: %2X Len: %d Data: %08lX\n", + PCI_SLOT(devfn), where, size, *value); + switch (where) { + case PCI_BASE_ADDRESS_0: + if (*value == 0xffffffff) { + usb20_mem_size_rd = TRUE; + } else { + usb20_mem_base = *value; + } + break; + default: + break; + } + break; + default: + break; + } + + return PCIBIOS_SUCCESSFUL; +} + +/* -------------------------------------------------------------------------- + Name: pci63xx_int_usb20_read +Abstract: PCI Config read on internal device(s) + -------------------------------------------------------------------------- */ +static int pci63xx_int_usb20_read(unsigned int devfn, int where, u32 * value, int size) +{ + uint32 retValue = 0xFFFFFFFF; + + // For now, this is specific to the USB Host controller. We can + // make it more general if we have to... + // Emulate PCI Config accesses + switch (where) { + case PCI_VENDOR_ID: + case PCI_DEVICE_ID: + retValue = PCI_VENDOR_ID_BROADCOM | 0x63000000; + break; + case PCI_COMMAND: + case PCI_STATUS: + retValue = (0x0006 << 16) | usb20_cfg_space_cmd_reg; + break; + case PCI_CLASS_REVISION: + case PCI_CLASS_DEVICE: + retValue = (PCI_CLASS_SERIAL_USB << 16) | (0x20 << 8) | 0x01; + break; + case PCI_BASE_ADDRESS_0: + if (usb20_mem_size_rd) { + retValue = USB_BAR0_MEM_SIZE; + } else { + if (usb20_mem_base != 0) + retValue = usb20_mem_base; + else + retValue = USB_EHCI_BASE; + } + usb20_mem_size_rd = FALSE; + break; + case PCI_CACHE_LINE_SIZE: + case PCI_LATENCY_TIMER: + retValue = 0; + break; + case PCI_HEADER_TYPE: + retValue = PCI_HEADER_TYPE_NORMAL; + break; + case PCI_SUBSYSTEM_VENDOR_ID: + retValue = PCI_VENDOR_ID_BROADCOM; + break; + case PCI_SUBSYSTEM_ID: + retValue = 0x6300; + break; + case PCI_INTERRUPT_LINE: + retValue = INTERRUPT_ID_USBH20; + break; + default: + break; + } + + switch (size) { + case 1: + *value = (retValue >> ((where & 3) << 3)) & 0xff; + DPRINT("R <= Slot: %d Where: %2X Len: %d Data: %02X\n", + PCI_SLOT(devfn), where, size, *value); + break; + case 2: + *value = (retValue >> ((where & 3) << 3)) & 0xffff; + DPRINT("R <= Slot: %d Where: %2X Len: %d Data: %04X\n", + PCI_SLOT(devfn), where, size, *value); + break; + case 4: + *value = retValue; + DPRINT("R <= Slot: %d Where: %2X Len: %d Data: %08lX\n", + PCI_SLOT(devfn), where, size, *value); + break; + default: + break; + } + + return PCIBIOS_SUCCESSFUL; +} +#endif +#endif + +static int bcm63xx_pcibios_read(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 * val) +{ + volatile unsigned char *ioBase = (unsigned char *)(mpi->l2piobase | KSEG1); + uint32 data; + +#if defined(CONFIG_USB) + if (PCI_SLOT(devfn) == USB_HOST_SLOT) + return pci63xx_int_usb_read(devfn, where, val, size); +#if !defined(CONFIG_BCM96348) + if (PCI_SLOT(devfn) == USB20_HOST_SLOT) + return pci63xx_int_usb20_read(devfn, where, val, size); +#endif +#endif + + mpi_SetupPciConfigAccess(BCM_PCI_CFG(PCI_SLOT(devfn), PCI_FUNC(devfn), where)); + data = *(uint32 *)ioBase; + switch(size) { + case 1: + *val = (data >> ((where & 3) << 3)) & 0xff; + break; + case 2: + *val = (data >> ((where & 3) << 3)) & 0xffff; + break; + case 4: + *val = data; + /* Special case for reading PCI device range */ + if ((where >= PCI_BASE_ADDRESS_0) && (where <= PCI_BASE_ADDRESS_5)) { + if (pci_mem_size_rd) { + /* bcm63xx PCI memory window minimum size is 64K */ + /* preserve the lower 4 bits */ + if ((*val & PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_IO) + *val &= (PCI_SIZE_64K + ~PCI_BASE_ADDRESS_MEM_MASK); + } + } + break; + default: + break; + } + pci_mem_size_rd = FALSE; + mpi_ClearPciConfigAccess(); + + return PCIBIOS_SUCCESSFUL; +} + +static int bcm63xx_pcibios_write(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 val) +{ + volatile unsigned char *ioBase = (unsigned char *)(mpi->l2piobase | KSEG1); + uint32 data; + +#if defined(CONFIG_USB) + if (PCI_SLOT(devfn) == USB_HOST_SLOT) + return pci63xx_int_usb_write(devfn, where, &val, size); +#if !defined(CONFIG_BCM96348) + if (PCI_SLOT(devfn) == USB20_HOST_SLOT) + return pci63xx_int_usb20_write(devfn, where, &val, size); +#endif +#endif + mpi_SetupPciConfigAccess(BCM_PCI_CFG(PCI_SLOT(devfn), PCI_FUNC(devfn), where)); + data = *(uint32 *)ioBase; + switch(size) { + case 1: + data = (data & ~(0xff << ((where & 3) << 3))) | + (val << ((where & 3) << 3)); + break; + case 2: + data = (data & ~(0xffff << ((where & 3) << 3))) | + (val << ((where & 3) << 3)); + break; + case 4: + data = val; + /* Special case for reading PCI device range */ + if ((where >= PCI_BASE_ADDRESS_0) && (where <= PCI_BASE_ADDRESS_5)) { + if (val == 0xffffffff) + pci_mem_size_rd = TRUE; + } + break; + default: + break; + } + *(uint32 *)ioBase = data; + udelay(500); + mpi_ClearPciConfigAccess(); + + return PCIBIOS_SUCCESSFUL; +} + +struct pci_ops bcm63xx_pci_ops = { + .read = bcm63xx_pcibios_read, + .write = bcm63xx_pcibios_write +}; diff -Naur linux-mips-2.6.8.1-orig/arch/mips/pci/pci-bcm63xx.c linux-mips-2.6.8.1-bcm/arch/mips/pci/pci-bcm63xx.c --- linux-mips-2.6.8.1-orig/arch/mips/pci/pci-bcm63xx.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-mips-2.6.8.1-bcm/arch/mips/pci/pci-bcm63xx.c 2006-12-20 18:48:43.000000000 +0100 @@ -0,0 +1,56 @@ +/* +<:copyright-gpl + Copyright 2002 Broadcom Corp. 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. +:> +*/ +#include +#include +#include +#include + +#include +#include + +static struct resource bcm_pci_io_resource = { + .name = "bcm63xx pci IO space", + .start = BCM_PCI_IO_BASE, + .end = BCM_PCI_IO_BASE + BCM_PCI_IO_SIZE_64KB - 1, + .flags = IORESOURCE_IO +}; + +static struct resource bcm_pci_mem_resource = { + .name = "bcm63xx pci memory space", +