Linux-2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
new file mode 100644
index 0000000..5e666aa
--- /dev/null
+++ b/arch/mips/Kconfig
@@ -0,0 +1,1658 @@
+config MIPS
+ bool
+ default y
+ # Horrible source of confusion. Die, die, die ...
+ select EMBEDDED
+
+config MIPS64
+ bool "64-bit kernel"
+ help
+ Select this option if you want to build a 64-bit kernel. You should
+ only select this option if you have hardware that actually has a
+ 64-bit processor and if your application will actually benefit from
+ 64-bit processing, otherwise say N. You must say Y for kernels for
+ SGI IP27 (Origin 200 and 2000) and SGI IP32 (O2). If in doubt say N.
+
+config 64BIT
+ def_bool MIPS64
+
+config MIPS32
+ bool
+ depends on MIPS64 = 'n'
+ default y
+
+mainmenu "Linux/MIPS Kernel Configuration"
+
+source "init/Kconfig"
+
+menu "Machine selection"
+
+config MACH_JAZZ
+ bool "Support for the Jazz family of machines"
+ select ARC
+ select ARC32
+ select GENERIC_ISA_DMA
+ select I8259
+ select ISA
+ help
+ This a family of machines based on the MIPS R4030 chipset which was
+ used by several vendors to build RISC/os and Windows NT workstations.
+ Members include the Acer PICA, MIPS Magnum 4000, MIPS Millenium and
+ Olivetti M700-10 workstations.
+
+config ACER_PICA_61
+ bool "Support for Acer PICA 1 chipset (EXPERIMENTAL)"
+ depends on MACH_JAZZ && EXPERIMENTAL
+ select DMA_NONCOHERENT
+ help
+ This is a machine with a R4400 133/150 MHz CPU. To compile a Linux
+ kernel that runs on these, say Y here. For details about Linux on
+ the MIPS architecture, check out the Linux/MIPS FAQ on the WWW at
+ <http://www.linux-mips.org/>.
+
+config MIPS_MAGNUM_4000
+ bool "Support for MIPS Magnum 4000"
+ depends on MACH_JAZZ
+ select DMA_NONCOHERENT
+ help
+ This is a machine with a R4000 100 MHz CPU. To compile a Linux
+ kernel that runs on these, say Y here. For details about Linux on
+ the MIPS architecture, check out the Linux/MIPS FAQ on the WWW at
+ <http://www.linux-mips.org/>.
+
+config OLIVETTI_M700
+ bool "Support for Olivetti M700-10"
+ depends on MACH_JAZZ
+ select DMA_NONCOHERENT
+ help
+ This is a machine with a R4000 100 MHz CPU. To compile a Linux
+ kernel that runs on these, say Y here. For details about Linux on
+ the MIPS architecture, check out the Linux/MIPS FAQ on the WWW at
+ <http://www.linux-mips.org/>.
+
+config MACH_VR41XX
+ bool "Support for NEC VR41XX-based machines"
+
+config NEC_CMBVR4133
+ bool "Support for NEC CMB-VR4133"
+ depends on MACH_VR41XX
+ select CPU_VR41XX
+ select DMA_NONCOHERENT
+ select IRQ_CPU
+ select HW_HAS_PCI
+ select PCI_VR41XX
+
+config ROCKHOPPER
+ bool "Support for Rockhopper baseboard"
+ depends on NEC_CMBVR4133
+ select I8259
+ select HAVE_STD_PC_SERIAL_PORT
+
+config CASIO_E55
+ bool "Support for CASIO CASSIOPEIA E-10/15/55/65"
+ depends on MACH_VR41XX
+ select DMA_NONCOHERENT
+ select IRQ_CPU
+ select ISA
+
+config IBM_WORKPAD
+ bool "Support for IBM WorkPad z50"
+ depends on MACH_VR41XX
+ select DMA_NONCOHERENT
+ select IRQ_CPU
+ select ISA
+
+config TANBAC_TB0226
+ bool "Support for TANBAC TB0226 (Mbase)"
+ depends on MACH_VR41XX
+ select DMA_NONCOHERENT
+ select HW_HAS_PCI
+ select IRQ_CPU
+ help
+ The TANBAC TB0226 (Mbase) is a MIPS-based platform manufactured by TANBAC.
+ Please refer to <http://www.tanbac.co.jp/> about Mbase.
+
+config TANBAC_TB0229
+ bool "Support for TANBAC TB0229 (VR4131DIMM)"
+ depends on MACH_VR41XX
+ select DMA_NONCOHERENT
+ select HW_HAS_PCI
+ select IRQ_CPU
+ help
+ The TANBAC TB0229 (VR4131DIMM) is a MIPS-based platform manufactured by TANBAC.
+ Please refer to <http://www.tanbac.co.jp/> about VR4131DIMM.
+
+config VICTOR_MPC30X
+ bool "Support for Victor MP-C303/304"
+ select DMA_NONCOHERENT
+ select HW_HAS_PCI
+ select IRQ_CPU
+ depends on MACH_VR41XX
+
+config ZAO_CAPCELLA
+ bool "Support for ZAO Networks Capcella"
+ depends on MACH_VR41XX
+ select DMA_NONCOHERENT
+ select HW_HAS_PCI
+ select IRQ_CPU
+
+config PCI_VR41XX
+ bool "Add PCI control unit support of NEC VR4100 series"
+ depends on MACH_VR41XX && PCI
+
+config VRC4171
+ tristate "Add NEC VRC4171 companion chip support"
+ depends on MACH_VR41XX && ISA
+ ---help---
+ The NEC VRC4171/4171A is a companion chip for NEC VR4111/VR4121.
+
+config VRC4173
+ tristate "Add NEC VRC4173 companion chip support"
+ depends on MACH_VR41XX && PCI_VR41XX
+ ---help---
+ The NEC VRC4173 is a companion chip for NEC VR4122/VR4131.
+
+config TOSHIBA_JMR3927
+ bool "Support for Toshiba JMR-TX3927 board"
+ depends on MIPS32
+ select DMA_NONCOHERENT
+ select HW_HAS_PCI
+ select SWAP_IO_SPACE
+
+config MIPS_COBALT
+ bool "Support for Cobalt Server (EXPERIMENTAL)"
+ depends on EXPERIMENTAL
+ select DMA_NONCOHERENT
+ select HW_HAS_PCI
+ select I8259
+ select IRQ_CPU
+
+config MACH_DECSTATION
+ bool "Support for DECstations"
+ select BOOT_ELF32
+ select DMA_NONCOHERENT
+ select IRQ_CPU
+ depends on MIPS32 || EXPERIMENTAL
+ ---help---
+ This enables support for DEC's MIPS based workstations. For details
+ see the Linux/MIPS FAQ on <http://www.linux-mips.org/> and the
+ DECstation porting pages on <http://decstation.unix-ag.org/>.
+
+ If you have one of the following DECstation Models you definitely
+ want to choose R4xx0 for the CPU Type:
+
+ DECstation 5000/50
+ DECstation 5000/150
+ DECstation 5000/260
+ DECsystem 5900/260
+
+ otherwise choose R3000.
+
+config MIPS_EV64120
+ bool "Support for Galileo EV64120 Evaluation board (EXPERIMENTAL)"
+ depends on EXPERIMENTAL
+ select DMA_NONCOHERENT
+ select HW_HAS_PCI
+ select MIPS_GT64120
+ help
+ This is an evaluation board based on the Galileo GT-64120
+ single-chip system controller that contains a MIPS R5000 compatible
+ core running at 75/100MHz. Their website is located at
+ <http://www.marvell.com/>. Say Y here if you wish to build a
+ kernel for this platform.
+
+config EVB_PCI1
+ bool "Enable Second PCI (PCI1)"
+ depends on MIPS_EV64120
+
+config MIPS_EV96100
+ bool "Support for Galileo EV96100 Evaluation board (EXPERIMENTAL)"
+ depends on EXPERIMENTAL
+ select DMA_NONCOHERENT
+ select HW_HAS_PCI
+ select IRQ_CPU
+ select MIPS_GT96100
+ select RM7000_CPU_SCACHE
+ select SWAP_IO_SPACE
+ help
+ This is an evaluation board based on the Galileo GT-96100 LAN/WAN
+ communications controllers containing a MIPS R5000 compatible core
+ running at 83MHz. Their website is <http://www.marvell.com/>. Say Y
+ here if you wish to build a kernel for this platform.
+
+config MIPS_IVR
+ bool "Support for Globespan IVR board"
+ select DMA_NONCOHERENT
+ select HW_HAS_PCI
+ help
+ This is an evaluation board built by Globespan to showcase thir
+ iVR (Internet Video Recorder) design. It utilizes a QED RM5231
+ R5000 MIPS core. More information can be found out their website
+ located at <http://www.globespan.net/>. Say Y here if you wish to
+ build a kernel for this platform.
+
+config LASAT
+ bool "Support for LASAT Networks platforms"
+ select DMA_NONCOHERENT
+ select HW_HAS_PCI
+ select MIPS_GT64120
+ select R5000_CPU_SCACHE
+
+config PICVUE
+ tristate "PICVUE LCD display driver"
+ depends on LASAT
+
+config PICVUE_PROC
+ tristate "PICVUE LCD display driver /proc interface"
+ depends on PICVUE
+
+config DS1603
+ bool "DS1603 RTC driver"
+ depends on LASAT
+
+config LASAT_SYSCTL
+ bool "LASAT sysctl interface"
+ depends on LASAT
+
+config MIPS_ITE8172
+ bool "Support for ITE 8172G board"
+ select DMA_NONCOHERENT
+ select HW_HAS_PCI
+ help
+ Ths is an evaluation board made by ITE <http://www.ite.com.tw/>
+ with ATX form factor that utilizes a MIPS R5000 to work with its
+ ITE8172G companion internet appliance chip. The MIPS core can be
+ either a NEC Vr5432 or QED RM5231. Say Y here if you wish to build
+ a kernel for this platform.
+
+config IT8172_REVC
+ bool "Support for older IT8172 (Rev C)"
+ depends on MIPS_ITE8172
+ help
+ Say Y here to support the older, Revision C version of the Integrated
+ Technology Express, Inc. ITE8172 SBC. Vendor page at
+ <http://www.ite.com.tw/ia/brief_it8172bsp.htm>; picture of the
+ board at <http://www.mvista.com/partners/semiconductor/ite.html>.
+
+config MIPS_ATLAS
+ bool "Support for MIPS Atlas board"
+ select BOOT_ELF32
+ select DMA_NONCOHERENT
+ select HW_HAS_PCI
+ select MIPS_GT64120
+ select SWAP_IO_SPACE
+ help
+ This enables support for the QED R5231-based MIPS Atlas evaluation
+ board.
+
+config MIPS_MALTA
+ bool "Support for MIPS Malta board"
+ select BOOT_ELF32
+ select HAVE_STD_PC_SERIAL_PORT
+ select DMA_NONCOHERENT
+ select GENERIC_ISA_DMA
+ select HW_HAS_PCI
+ select I8259
+ select MIPS_GT64120
+ select SWAP_IO_SPACE
+ help
+ This enables support for the VR5000-based MIPS Malta evaluation
+ board.
+
+config MIPS_SEAD
+ bool "Support for MIPS SEAD board (EXPERIMENTAL)"
+ depends on EXPERIMENTAL
+ select IRQ_CPU
+ select DMA_NONCOHERENT
+
+config MOMENCO_OCELOT
+ bool "Support for Momentum Ocelot board"
+ select DMA_NONCOHERENT
+ select HW_HAS_PCI
+ select IRQ_CPU
+ select IRQ_CPU_RM7K
+ select MIPS_GT64120
+ select RM7000_CPU_SCACHE
+ select SWAP_IO_SPACE
+ help
+ The Ocelot is a MIPS-based Single Board Computer (SBC) made by
+ Momentum Computer <http://www.momenco.com/>.
+
+config MOMENCO_OCELOT_G
+ bool "Support for Momentum Ocelot-G board"
+ select DMA_NONCOHERENT
+ select HW_HAS_PCI
+ select IRQ_CPU
+ select IRQ_CPU_RM7K
+ select PCI_MARVELL
+ select RM7000_CPU_SCACHE
+ select SWAP_IO_SPACE
+ help
+ The Ocelot is a MIPS-based Single Board Computer (SBC) made by
+ Momentum Computer <http://www.momenco.com/>.
+
+config MOMENCO_OCELOT_C
+ bool "Support for Momentum Ocelot-C board"
+ select DMA_NONCOHERENT
+ select HW_HAS_PCI
+ select IRQ_CPU
+ select IRQ_MV64340
+ select PCI_MARVELL
+ select RM7000_CPU_SCACHE
+ select SWAP_IO_SPACE
+ help
+ The Ocelot is a MIPS-based Single Board Computer (SBC) made by
+ Momentum Computer <http://www.momenco.com/>.
+
+config MOMENCO_OCELOT_3
+ bool "Support for Momentum Ocelot-3 board"
+ select BOOT_ELF32
+ select DMA_NONCOHERENT
+ select HW_HAS_PCI
+ select IRQ_CPU
+ select IRQ_CPU_RM7K
+ select IRQ_MV64340
+ select PCI_MARVELL
+ select RM7000_CPU_SCACHE
+ select SWAP_IO_SPACE
+ help
+ The Ocelot-3 is based off Discovery III System Controller and
+ PMC-Sierra Rm79000 core.
+
+config MOMENCO_JAGUAR_ATX
+ bool "Support for Momentum Jaguar board"
+ select BOOT_ELF32
+ select DMA_NONCOHERENT
+ select HW_HAS_PCI
+ select IRQ_CPU
+ select IRQ_CPU_RM7K
+ select IRQ_MV64340
+ select LIMITED_DMA
+ select PCI_MARVELL
+ select RM7000_CPU_SCACHE
+ select SWAP_IO_SPACE
+ help
+ The Jaguar ATX is a MIPS-based Single Board Computer (SBC) made by
+ Momentum Computer <http://www.momenco.com/>.
+
+config JAGUAR_DMALOW
+ bool "Low DMA Mode"
+ depends on MOMENCO_JAGUAR_ATX
+ help
+ Select to Y if jump JP5 is set on your board, N otherwise. Normally
+ the jumper is set, so if you feel unsafe, just say Y.
+
+config PMC_YOSEMITE
+ bool "Support for PMC-Sierra Yosemite eval board"
+ select DMA_COHERENT
+ select HW_HAS_PCI
+ select IRQ_CPU
+ select IRQ_CPU_RM7K
+ select IRQ_CPU_RM9K
+ select SWAP_IO_SPACE
+ help
+ Yosemite is an evaluation board for the RM9000x2 processor
+ manufactured by PMC-Sierra
+
+config HYPERTRANSPORT
+ bool "Hypertransport Support for PMC-Sierra Yosemite"
+ depends on PMC_YOSEMITE
+
+config DDB5074
+ bool "Support for NEC DDB Vrc-5074 (EXPERIMENTAL)"
+ depends on EXPERIMENTAL
+ select DMA_NONCOHERENT
+ select HAVE_STD_PC_SERIAL_PORT
+ select HW_HAS_PCI
+ select IRQ_CPU
+ select I8259
+ select ISA
+ help
+ This enables support for the VR5000-based NEC DDB Vrc-5074
+ evaluation board.
+
+config DDB5476
+ bool "Support for NEC DDB Vrc-5476"
+ select DMA_NONCOHERENT
+ select HAVE_STD_PC_SERIAL_PORT
+ select HW_HAS_PCI
+ select IRQ_CPU
+ select I8259
+ select ISA
+ help
+ This enables support for the R5432-based NEC DDB Vrc-5476
+ evaluation board.
+
+ Features : kernel debugging, serial terminal, NFS root fs, on-board
+ ether port USB, AC97, PCI, PCI VGA card & framebuffer console,
+ IDE controller, PS2 keyboard, PS2 mouse, etc.
+
+config DDB5477
+ bool "Support for NEC DDB Vrc-5477"
+ select DMA_NONCOHERENT
+ select HW_HAS_PCI
+ select I8259
+ select IRQ_CPU
+ help
+ This enables support for the R5432-based NEC DDB Vrc-5477,
+ or Rockhopper/SolutionGear boards with R5432/R5500 CPUs.
+
+ Features : kernel debugging, serial terminal, NFS root fs, on-board
+ ether port USB, AC97, PCI, etc.
+
+config DDB5477_BUS_FREQUENCY
+ int "bus frequency (in kHZ, 0 for auto-detect)"
+ depends on DDB5477
+ default 0
+
+config NEC_OSPREY
+ bool "Support for NEC Osprey board"
+ select DMA_NONCOHERENT
+ select IRQ_CPU
+
+config SGI_IP22
+ bool "Support for SGI IP22 (Indy/Indigo2)"
+ select ARC
+ select ARC32
+ select BOOT_ELF32
+ select DMA_NONCOHERENT
+ select IP22_CPU_SCACHE
+ select IRQ_CPU
+ select SWAP_IO_SPACE
+ help
+ This are the SGI Indy, Challenge S and Indigo2, as well as certain
+ OEM variants like the Tandem CMN B006S. To compile a Linux kernel
+ that runs on these, say Y here.
+
+config SGI_IP27
+ bool "Support for SGI IP27 (Origin200/2000)"
+ depends on MIPS64
+ select ARC
+ select ARC64
+ select DMA_IP27
+ select HW_HAS_PCI
+ select PCI_DOMAINS
+ help
+ This are the SGI Origin 200, Origin 2000 and Onyx 2 Graphics
+ workstations. To compile a Linux kernel that runs on these, say Y
+ here.
+
+#config SGI_SN0_XXL
+# bool "IP27 XXL"
+# depends on SGI_IP27
+# This options adds support for userspace processes upto 16TB size.
+# Normally the limit is just .5TB.
+
+config SGI_SN0_N_MODE
+ bool "IP27 N-Mode"
+ depends on SGI_IP27
+ help
+ The nodes of Origin 200, Origin 2000 and Onyx 2 systems can be
+ configured in either N-Modes which allows for more nodes or M-Mode
+ which allows for more memory. Your system is most probably
+ running in M-Mode, so you should say N here.
+
+config DISCONTIGMEM
+ bool
+ default y if SGI_IP27
+ help
+ Say Y to upport efficient handling of discontiguous physical memory,
+ for architectures which are either NUMA (Non-Uniform Memory Access)
+ or have huge holes in the physical address space for other reasons.
+ See <file:Documentation/vm/numa> for more.
+
+config NUMA
+ bool "NUMA Support"
+ depends on SGI_IP27
+ help
+ Say Y to compile the kernel to support NUMA (Non-Uniform Memory
+ Access). This option is for configuring high-end multiprocessor
+ server machines. If in doubt, say N.
+
+config MAPPED_KERNEL
+ bool "Mapped kernel support"
+ depends on SGI_IP27
+ help
+ Change the way a Linux kernel is loaded into memory on a MIPS64
+ machine. This is required in order to support text replication and
+ NUMA. If you need to understand it, read the source code.
+
+config REPLICATE_KTEXT
+ bool "Kernel text replication support"
+ depends on SGI_IP27
+ help
+ Say Y here to enable replicating the kernel text across multiple
+ nodes in a NUMA cluster. This trades memory for speed.
+
+config REPLICATE_EXHANDLERS
+ bool "Exception handler replication support"
+ depends on SGI_IP27
+ help
+ Say Y here to enable replicating the kernel exception handlers
+ across multiple nodes in a NUMA cluster. This trades memory for
+ speed.
+
+config SGI_IP32
+ bool "Support for SGI IP32 (O2) (EXPERIMENTAL)"
+ depends on MIPS64 && EXPERIMENTAL
+ select ARC
+ select ARC32
+ select BOOT_ELF32
+ select OWN_DMA
+ select DMA_IP32
+ select DMA_NONCOHERENT
+ select HW_HAS_PCI
+ select R5000_CPU_SCACHE
+ select RM7000_CPU_SCACHE
+ help
+ If you want this kernel to run on SGI O2 workstation, say Y here.
+
+config SOC_AU1X00
+ depends on MIPS32
+ bool "Support for AMD/Alchemy Au1X00 SOCs"
+
+choice
+ prompt "Au1X00 SOC Type"
+ depends on SOC_AU1X00
+ help
+ Say Y here to enable support for one of three AMD/Alchemy
+ SOCs. For additional documentation see www.amd.com.
+
+config SOC_AU1000
+ bool "SOC_AU1000"
+config SOC_AU1100
+ bool "SOC_AU1100"
+config SOC_AU1500
+ bool "SOC_AU1500"
+config SOC_AU1550
+ bool "SOC_AU1550"
+
+endchoice
+
+choice
+ prompt "AMD/Alchemy Au1x00 board support"
+ depends on SOC_AU1X00
+ help
+ These are evaluation boards built by AMD/Alchemy to
+ showcase their Au1X00 Internet Edge Processors. The SOC design
+ is based on the MIPS32 architecture running at 266/400/500MHz
+ with many integrated peripherals. Further information can be
+ found at their website, <http://www.amd.com/>. Say Y here if you
+ wish to build a kernel for this platform.
+
+config MIPS_PB1000
+ bool "PB1000 board"
+ depends on SOC_AU1000
+ select DMA_NONCOHERENT
+ select HW_HAS_PCI
+ select SWAP_IO_SPACE
+
+config MIPS_PB1100
+ bool "PB1100 board"
+ depends on SOC_AU1100
+ select DMA_NONCOHERENT
+ select HW_HAS_PCI
+ select SWAP_IO_SPACE
+
+config MIPS_PB1500
+ bool "PB1500 board"
+ depends on SOC_AU1500
+ select DMA_COHERENT
+ select HW_HAS_PCI
+
+config MIPS_PB1550
+ bool "PB1550 board"
+ depends on SOC_AU1550
+ select DMA_COHERENT
+ select HW_HAS_PCI
+ select MIPS_DISABLE_OBSOLETE_IDE
+
+config MIPS_DB1000
+ bool "DB1000 board"
+ depends on SOC_AU1000
+ select DMA_NONCOHERENT
+ select HW_HAS_PCI
+
+config MIPS_DB1100
+ bool "DB1100 board"
+ depends on SOC_AU1100
+ select DMA_NONCOHERENT
+
+config MIPS_DB1500
+ bool "DB1500 board"
+ depends on SOC_AU1500
+ select DMA_COHERENT
+ select HW_HAS_PCI
+ select MIPS_DISABLE_OBSOLETE_IDE
+
+config MIPS_DB1550
+ bool "DB1550 board"
+ depends on SOC_AU1550
+ select HW_HAS_PCI
+ select DMA_COHERENT
+ select MIPS_DISABLE_OBSOLETE_IDE
+
+config MIPS_BOSPORUS
+ bool "Bosporus board"
+ depends on SOC_AU1500
+ select DMA_NONCOHERENT
+
+config MIPS_MIRAGE
+ bool "Mirage board"
+ depends on SOC_AU1500
+ select DMA_NONCOHERENT
+
+config MIPS_XXS1500
+ bool "MyCable XXS1500 board"
+ depends on SOC_AU1500
+ select DMA_NONCOHERENT
+
+config MIPS_MTX1
+ bool "4G Systems MTX-1 board"
+ depends on SOC_AU1500
+ select HW_HAS_PCI
+ select DMA_NONCOHERENT
+
+endchoice
+
+config SIBYTE_SB1xxx_SOC
+ bool "Support for Broadcom BCM1xxx SOCs (EXPERIMENTAL)"
+ depends on EXPERIMENTAL
+ select BOOT_ELF32
+ select DMA_COHERENT
+ select SWAP_IO_SPACE
+
+choice
+ prompt "BCM1xxx SOC-based board"
+ depends on SIBYTE_SB1xxx_SOC
+ default SIBYTE_SWARM
+ help
+ Enable support for boards based on the SiByte line of SOCs
+ from Broadcom. There are configurations for the known
+ evaluation boards, or you can choose "Other" and add your
+ own board support code.
+
+config SIBYTE_SWARM
+ bool "BCM91250A-SWARM"
+ select SIBYTE_SB1250
+
+config SIBYTE_SENTOSA
+ bool "BCM91250E-Sentosa"
+ select SIBYTE_SB1250
+
+config SIBYTE_RHONE
+ bool "BCM91125E-Rhone"
+ select SIBYTE_BCM1125H
+
+config SIBYTE_CARMEL
+ bool "BCM91120x-Carmel"
+ select SIBYTE_BCM1120
+
+config SIBYTE_PTSWARM
+ bool "BCM91250PT-PTSWARM"
+ select SIBYTE_SB1250
+
+config SIBYTE_LITTLESUR
+ bool "BCM91250C2-LittleSur"
+ select SIBYTE_SB1250
+
+config SIBYTE_CRHINE
+ bool "BCM91120C-CRhine"
+ select SIBYTE_BCM1120
+
+config SIBYTE_CRHONE
+ bool "BCM91125C-CRhone"
+ select SIBYTE_BCM1125
+
+config SIBYTE_UNKNOWN
+ bool "Other"
+
+endchoice
+
+config SIBYTE_BOARD
+ bool
+ depends on SIBYTE_SB1xxx_SOC && !SIBYTE_UNKNOWN
+ default y
+
+choice
+ prompt "BCM1xxx SOC Type"
+ depends on SIBYTE_UNKNOWN
+ default SIBYTE_UNK_BCM1250
+ help
+ Since you haven't chosen a known evaluation board from
+ Broadcom, you must explicitly pick the SOC this kernel is
+ targetted for.
+
+config SIBYTE_UNK_BCM1250
+ bool "BCM1250"
+ select SIBYTE_SB1250
+
+config SIBYTE_UNK_BCM1120
+ bool "BCM1120"
+ select SIBYTE_BCM1120
+
+config SIBYTE_UNK_BCM1125
+ bool "BCM1125"
+ select SIBYTE_BCM1125
+
+config SIBYTE_UNK_BCM1125H
+ bool "BCM1125H"
+ select SIBYTE_BCM1125H
+
+endchoice
+
+config SIBYTE_SB1250
+ bool
+ select HW_HAS_PCI
+
+config SIBYTE_BCM1120
+ bool
+ select SIBYTE_BCM112X
+
+config SIBYTE_BCM1125
+ bool
+ select HW_HAS_PCI
+ select SIBYTE_BCM112X
+
+config SIBYTE_BCM1125H
+ bool
+ select HW_HAS_PCI
+ select SIBYTE_BCM112X
+
+config SIBYTE_BCM112X
+ bool
+
+choice
+ prompt "SiByte SOC Stepping"
+ depends on SIBYTE_SB1xxx_SOC
+
+config CPU_SB1_PASS_1
+ bool "1250 Pass1"
+ depends on SIBYTE_SB1250
+ select CPU_HAS_PREFETCH
+
+config CPU_SB1_PASS_2_1250
+ bool "1250 An"
+ depends on SIBYTE_SB1250
+ select CPU_SB1_PASS_2
+ help
+ Also called BCM1250 Pass 2
+
+config CPU_SB1_PASS_2_2
+ bool "1250 Bn"
+ depends on SIBYTE_SB1250
+ select CPU_HAS_PREFETCH
+ help
+ Also called BCM1250 Pass 2.2
+
+config CPU_SB1_PASS_4
+ bool "1250 Cn"
+ depends on SIBYTE_SB1250
+ select CPU_HAS_PREFETCH
+ help
+ Also called BCM1250 Pass 3
+
+config CPU_SB1_PASS_2_112x
+ bool "112x Hybrid"
+ depends on SIBYTE_BCM112X
+ select CPU_SB1_PASS_2
+
+config CPU_SB1_PASS_3
+ bool "112x An"
+ depends on SIBYTE_BCM112X
+ select CPU_HAS_PREFETCH
+
+endchoice
+
+config CPU_SB1_PASS_2
+ bool
+
+config SIBYTE_HAS_LDT
+ bool
+ depends on PCI && (SIBYTE_SB1250 || SIBYTE_BCM1125H)
+ default y
+
+config SIMULATION
+ bool "Running under simulation"
+ depends on SIBYTE_SB1xxx_SOC
+ help
+ Build a kernel suitable for running under the GDB simulator.
+ Primarily adjusts the kernel's notion of time.
+
+config SIBYTE_CFE
+ bool "Booting from CFE"
+ depends on SIBYTE_SB1xxx_SOC
+ help
+ Make use of the CFE API for enumerating available memory,
+ controlling secondary CPUs, and possibly console output.
+
+config SIBYTE_CFE_CONSOLE
+ bool "Use firmware console"
+ depends on SIBYTE_CFE
+ help
+ Use the CFE API's console write routines during boot. Other console
+ options (VT console, sb1250 duart console, etc.) should not be
+ configured.
+
+config SIBYTE_STANDALONE
+ bool
+ depends on SIBYTE_SB1xxx_SOC && !SIBYTE_CFE
+ default y
+
+config SIBYTE_STANDALONE_RAM_SIZE
+ int "Memory size (in megabytes)"
+ depends on SIBYTE_STANDALONE
+ default "32"
+
+config SIBYTE_BUS_WATCHER
+ bool "Support for Bus Watcher statistics"
+ depends on SIBYTE_SB1xxx_SOC
+ help
+ Handle and keep statistics on the bus error interrupts (COR_ECC,
+ BAD_ECC, IO_BUS).
+
+config SIBYTE_BW_TRACE
+ bool "Capture bus trace before bus error"
+ depends on SIBYTE_BUS_WATCHER
+ help
+ Run a continuous bus trace, dumping the raw data as soon as
+ a ZBbus error is detected. Cannot work if ZBbus profiling
+ is turned on, and also will interfere with JTAG-based trace
+ buffer activity. Raw buffer data is dumped to console, and
+ must be processed off-line.
+
+config SIBYTE_SB1250_PROF
+ bool "Support for SB1/SOC profiling - SB1/SCD perf counters"
+ depends on SIBYTE_SB1xxx_SOC
+
+config SIBYTE_TBPROF
+ bool "Support for ZBbus profiling"
+ depends on SIBYTE_SB1xxx_SOC
+
+config SNI_RM200_PCI
+ bool "Support for SNI RM200 PCI"
+ select ARC
+ select ARC32
+ select BOOT_ELF32
+ select DMA_NONCOHERENT
+ select GENERIC_ISA_DMA
+ select HAVE_STD_PC_SERIAL_PORT
+ select HW_HAS_PCI
+ select I8259
+ select ISA
+ help
+ The SNI RM200 PCI was a MIPS-based platform manufactured by Siemens
+ Nixdorf Informationssysteme (SNI), parent company of Pyramid
+ Technology and now in turn merged with Fujitsu. Say Y here to
+ support this machine type.
+
+config TOSHIBA_RBTX4927
+ bool "Support for Toshiba TBTX49[23]7 board"
+ depends on MIPS32
+ select DMA_NONCOHERENT
+ select HAS_TXX9_SERIAL
+ select HW_HAS_PCI
+ select I8259
+ select ISA
+ select SWAP_IO_SPACE
+ help
+ This Toshiba board is based on the TX4927 processor. Say Y here to
+ support this machine type
+
+config TOSHIBA_FPCIB0
+ bool "FPCIB0 Backplane Support"
+ depends on TOSHIBA_RBTX4927
+
+config RWSEM_GENERIC_SPINLOCK
+ bool
+ default y
+
+config RWSEM_XCHGADD_ALGORITHM
+ bool
+
+config GENERIC_CALIBRATE_DELAY
+ bool
+ default y
+
+config HAVE_DEC_LOCK
+ bool
+ default y
+
+#
+# Select some configuration options automatically based on user selections.
+#
+config ARC
+ bool
+ depends on SNI_RM200_PCI || SGI_IP32 || SGI_IP27 || SGI_IP22 || MIPS_MAGNUM_4000 || OLIVETTI_M700 || ACER_PICA_61
+ default y
+
+config DMA_COHERENT
+ bool
+
+config DMA_IP27
+ bool
+
+config DMA_NONCOHERENT
+ bool
+
+config EARLY_PRINTK
+ bool
+ depends on MACH_DECSTATION
+ default y
+
+config GENERIC_ISA_DMA
+ bool
+ depends on SNI_RM200_PCI || MIPS_MAGNUM_4000 || OLIVETTI_M700 || ACER_PICA_61 || MIPS_MALTA
+ default y
+
+config I8259
+ bool
+ depends on SNI_RM200_PCI || DDB5477 || DDB5476 || DDB5074 || MACH_JAZZ || MIPS_MALTA || MIPS_COBALT
+ default y
+
+config LIMITED_DMA
+ bool
+ select HIGHMEM
+
+config MIPS_BONITO64
+ bool
+ depends on MIPS_ATLAS || MIPS_MALTA
+ default y
+
+config MIPS_MSC
+ bool
+ depends on MIPS_ATLAS || MIPS_MALTA
+ default y
+
+config MIPS_NILE4
+ bool
+ depends on LASAT
+ default y
+
+config MIPS_DISABLE_OBSOLETE_IDE
+ bool
+
+config CPU_LITTLE_ENDIAN
+ bool "Generate little endian code"
+ default y if ACER_PICA_61 || CASIO_E55 || DDB5074 || DDB5476 || DDB5477 || MACH_DECSTATION || IBM_WORKPAD || LASAT || MIPS_COBALT || MIPS_ITE8172 || MIPS_IVR || SOC_AU1X00 || NEC_OSPREY || OLIVETTI_M700 || SNI_RM200_PCI || VICTOR_MPC30X || ZAO_CAPCELLA
+ default n if MIPS_EV64120 || MIPS_EV96100 || MOMENCO_OCELOT || MOMENCO_OCELOT_G || SGI_IP22 || SGI_IP27 || SGI_IP32 || TOSHIBA_JMR3927
+ help
+ Some MIPS machines can be configured for either little or big endian
+ byte order. These modes require different kernels. Say Y if your
+ machine is little endian, N if it's a big endian machine.
+
+config IRQ_CPU
+ bool
+
+config IRQ_CPU_RM7K
+ bool
+
+config IRQ_MV64340
+ bool
+
+config DDB5XXX_COMMON
+ bool
+ depends on DDB5074 || DDB5476 || DDB5477
+ default y
+
+config MIPS_BOARDS_GEN
+ bool
+ depends on MIPS_ATLAS || MIPS_MALTA || MIPS_SEAD
+ default y
+
+config MIPS_GT64111
+ bool
+ depends on MIPS_COBALT
+ default y
+
+config MIPS_GT64120
+ bool
+ depends on MIPS_EV64120 || MIPS_EV96100 || LASAT || MIPS_ATLAS || MIPS_MALTA || MOMENCO_OCELOT
+ default y
+
+config MIPS_TX3927
+ bool
+ depends on TOSHIBA_JMR3927
+ select HAS_TXX9_SERIAL
+ default y
+
+config PCI_MARVELL
+ bool
+
+config ITE_BOARD_GEN
+ bool
+ depends on MIPS_IVR || MIPS_ITE8172
+ default y
+
+config SWAP_IO_SPACE
+ bool
+
+#
+# Unfortunately not all GT64120 systems run the chip at the same clock.
+# As the user for the clock rate and try to minimize the available options.
+#
+choice
+ prompt "Galileo Chip Clock"
+ #default SYSCLK_83 if MIPS_EV64120
+ depends on MIPS_EV64120 || MOMENCO_OCELOT || MOMENCO_OCELOT_G
+ default SYSCLK_83 if MIPS_EV64120
+ default SYSCLK_100 if MOMENCO_OCELOT || MOMENCO_OCELOT_G
+
+config SYSCLK_75
+ bool "75" if MIPS_EV64120
+
+config SYSCLK_83
+ bool "83.3" if MIPS_EV64120
+
+config SYSCLK_100
+ bool "100" if MIPS_EV64120 || MOMENCO_OCELOT || MOMENCO_OCELOT_G
+
+endchoice
+
+config AU1X00_USB_DEVICE
+ bool
+ depends on MIPS_PB1500 || MIPS_PB1100 || MIPS_PB1000
+ default n
+
+config MIPS_GT96100
+ bool
+ depends on MIPS_EV96100
+ default y
+ help
+ Say Y here to support the Galileo Technology GT96100 communications
+ controller card. There is a web page at <http://www.galileot.com/>.
+
+config IT8172_CIR
+ bool
+ depends on MIPS_ITE8172 || MIPS_IVR
+ default y
+
+config IT8712
+ bool
+ depends on MIPS_ITE8172
+ default y
+
+config BOOT_ELF32
+ bool
+ depends on MACH_DECSTATION || MIPS_ATLAS || MIPS_MALTA || MOMENCO_JAGUAR_ATX || MOMENCO_OCELOT_3 || SIBYTE_SB1xxx_SOC || SGI_IP32 || SGI_IP22 || SNI_RM200_PCI
+ default y
+
+config MIPS_L1_CACHE_SHIFT
+ int
+ default "4" if MACH_DECSTATION
+ default "7" if SGI_IP27
+ default "5"
+
+config ARC32
+ bool
+ depends on MACH_JAZZ || SNI_RM200_PCI || SGI_IP22 || SGI_IP32
+ default y
+
+config FB
+ bool
+ depends on MIPS_MAGNUM_4000 || OLIVETTI_M700
+ default y
+ ---help---
+ The frame buffer device provides an abstraction for the graphics
+ hardware. It represents the frame buffer of some video hardware and
+ allows application software to access the graphics hardware through
+ a well-defined interface, so the software doesn't need to know
+ anything about the low-level (hardware register) stuff.
+
+ Frame buffer devices work identically across the different
+ architectures supported by Linux and make the implementation of
+ application programs easier and more portable; at this point, an X
+ server exists which uses the frame buffer device exclusively.
+ On several non-X86 architectures, the frame buffer device is the
+ only way to use the graphics hardware.
+
+ The device is accessed through special device nodes, usually located
+ in the /dev directory, i.e. /dev/fb*.
+
+ You need an utility program called fbset to make full use of frame
+ buffer devices. Please read <file:Documentation/fb/framebuffer.txt>
+ and the Framebuffer-HOWTO at <http://www.tldp.org/docs.html#howto>
+ for more information.
+
+ Say Y here and to the driver for your graphics board below if you
+ are compiling a kernel for a non-x86 architecture.
+
+ If you are compiling for the x86 architecture, you can say Y if you
+ want to play with it, but it is not essential. Please note that
+ running graphical applications that directly touch the hardware
+ (e.g. an accelerated X server) and that are not frame buffer
+ device-aware may cause unexpected results. If unsure, say N.
+
+config HAVE_STD_PC_SERIAL_PORT
+ bool
+
+config VR4181
+ bool
+ depends on NEC_OSPREY
+ default y
+
+config ARC_CONSOLE
+ bool "ARC console support"
+ depends on SGI_IP22 || SNI_RM200_PCI
+
+config ARC_MEMORY
+ bool
+ depends on MACH_JAZZ || SNI_RM200_PCI || SGI_IP32
+ default y
+
+config ARC_PROMLIB
+ bool
+ depends on MACH_JAZZ || SNI_RM200_PCI || SGI_IP22 || SGI_IP32
+ default y
+
+config ARC64
+ bool
+ depends on SGI_IP27
+ default y
+
+config BOOT_ELF64
+ bool
+ depends on SGI_IP27
+ default y
+
+#config MAPPED_PCI_IO y
+# bool
+# depends on SGI_IP27
+# default y
+
+config QL_ISP_A64
+ bool
+ depends on SGI_IP27
+ default y
+
+config TOSHIBA_BOARDS
+ bool
+ depends on TOSHIBA_JMR3927 || TOSHIBA_RBTX4927
+ default y
+
+endmenu
+
+menu "CPU selection"
+
+choice
+ prompt "CPU type"
+ default CPU_R4X00
+
+config CPU_MIPS32
+ bool "MIPS32"
+
+config CPU_MIPS64
+ bool "MIPS64"
+
+config CPU_R3000
+ bool "R3000"
+ depends on MIPS32
+ help
+ Please make sure to pick the right CPU type. Linux/MIPS is not
+ designed to be generic, i.e. Kernels compiled for R3000 CPUs will
+ *not* work on R4000 machines and vice versa. However, since most
+ of the supported machines have an R4000 (or similar) CPU, R4x00
+ might be a safe bet. If the resulting kernel does not work,
+ try to recompile with R3000.
+
+config CPU_TX39XX
+ bool "R39XX"
+ depends on MIPS32
+
+config CPU_VR41XX
+ bool "R41xx"
+ help
+ The options selects support for the NEC VR41xx series of processors.
+ Only choose this option if you have one of these processors as a
+ kernel built with this option will not run on any other type of
+ processor or vice versa.
+
+config CPU_R4300
+ bool "R4300"
+ help
+ MIPS Technologies R4300-series processors.
+
+config CPU_R4X00
+ bool "R4x00"
+ help
+ MIPS Technologies R4000-series processors other than 4300, including
+ the R4000, R4400, R4600, and 4700.
+
+config CPU_TX49XX
+ bool "R49XX"
+
+config CPU_R5000
+ bool "R5000"
+ help
+ MIPS Technologies R5000-series processors other than the Nevada.
+
+config CPU_R5432
+ bool "R5432"
+
+config CPU_R6000
+ bool "R6000"
+ depends on MIPS32 && EXPERIMENTAL
+ help
+ MIPS Technologies R6000 and R6000A series processors. Note these
+ processors are extremly rare and the support for them is incomplete.
+
+config CPU_NEVADA
+ bool "RM52xx"
+ help
+ QED / PMC-Sierra RM52xx-series ("Nevada") processors.
+
+config CPU_R8000
+ bool "R8000"
+ depends on MIPS64 && EXPERIMENTAL
+ help
+ MIPS Technologies R8000 processors. Note these processors are
+ uncommon and the support for them is incomplete.
+
+config CPU_R10000
+ bool "R10000"
+ help
+ MIPS Technologies R10000-series processors.
+
+config CPU_RM7000
+ bool "RM7000"
+
+config CPU_RM9000
+ bool "RM9000"
+
+config CPU_SB1
+ bool "SB1"
+
+endchoice
+
+choice
+ prompt "Kernel page size"
+ default PAGE_SIZE_4KB
+
+config PAGE_SIZE_4KB
+ bool "4kB"
+ help
+ This option select the standard 4kB Linux page size. On some
+ R3000-family processors this is the only available page size. Using
+ 4kB page size will minimize memory consumption and is therefore
+ recommended for low memory systems.
+
+config PAGE_SIZE_8KB
+ bool "8kB"
+ depends on EXPERIMENTAL && CPU_R8000
+ help
+ Using 8kB page size will result in higher performance kernel at
+ the price of higher memory consumption. This option is available
+ only on the R8000 processor. Not that at the time of this writing
+ this option is still high experimental; there are also issues with
+ compatibility of user applications.
+
+config PAGE_SIZE_16KB
+ bool "16kB"
+ depends on EXPERIMENTAL && !CPU_R3000 && !CPU_TX39XX
+ help
+ Using 16kB page size will result in higher performance kernel at
+ the price of higher memory consumption. This option is available on
+ all non-R3000 family processor. Not that at the time of this
+ writing this option is still high experimental; there are also
+ issues with compatibility of user applications.
+
+config PAGE_SIZE_64KB
+ bool "64kB"
+ depends on EXPERIMENTAL && !CPU_R3000 && !CPU_TX39XX
+ help
+ Using 64kB page size will result in higher performance kernel at
+ the price of higher memory consumption. This option is available on
+ all non-R3000 family processor. Not that at the time of this
+ writing this option is still high experimental; there are also
+ issues with compatibility of user applications.
+
+endchoice
+
+config BOARD_SCACHE
+ bool
+
+config IP22_CPU_SCACHE
+ bool
+ select BOARD_SCACHE
+
+config R5000_CPU_SCACHE
+ bool
+ select BOARD_SCACHE
+
+config RM7000_CPU_SCACHE
+ bool
+ select BOARD_SCACHE
+
+config SIBYTE_DMA_PAGEOPS
+ bool "Use DMA to clear/copy pages"
+ depends on CPU_SB1
+ help
+ Instead of using the CPU to zero and copy pages, use a Data Mover
+ channel. These DMA channels are otherwise unused by the standard
+ SiByte Linux port. Seems to give a small performance benefit.
+
+config CPU_HAS_PREFETCH
+ bool "Enable prefetches" if CPU_SB1 && !CPU_SB1_PASS_2
+ default y if CPU_MIPS32 || CPU_MIPS64 || CPU_RM7000 || CPU_RM9000 || CPU_R10000
+
+config VTAG_ICACHE
+ bool "Support for Virtual Tagged I-cache" if CPU_MIPS64 || CPU_MIPS32
+ default y if CPU_SB1
+
+config SB1_PASS_1_WORKAROUNDS
+ bool
+ depends on CPU_SB1_PASS_1
+ default y
+
+config SB1_PASS_2_WORKAROUNDS
+ bool
+ depends on CPU_SB1 && (CPU_SB1_PASS_2_2 || CPU_SB1_PASS_2)
+ default y
+
+config SB1_PASS_2_1_WORKAROUNDS
+ bool
+ depends on CPU_SB1 && CPU_SB1_PASS_2
+ default y
+
+config 64BIT_PHYS_ADDR
+ bool "Support for 64-bit physical address space"
+ depends on (CPU_R4X00 || CPU_R5000 || CPU_RM7000 || CPU_RM9000 || CPU_R10000 || CPU_SB1 || CPU_MIPS32 || CPU_MIPS64) && MIPS32
+
+config CPU_ADVANCED
+ bool "Override CPU Options"
+ depends on MIPS32
+ help
+ Saying yes here allows you to select support for various features
+ your CPU may or may not have. Most people should say N here.
+
+config CPU_HAS_LLSC
+ bool "ll/sc Instructions available" if CPU_ADVANCED
+ default y if !CPU_ADVANCED && !CPU_R3000 && !CPU_VR41XX && !CPU_TX39XX
+ help
+ MIPS R4000 series and later provide the Load Linked (ll)
+ and Store Conditional (sc) instructions. More information is
+ available at <http://www.go-ecs.com/mips/miptek1.htm>.
+
+ Say Y here if your CPU has the ll and sc instructions. Say Y here
+ for better performance, N if you don't know. You must say Y here
+ for multiprocessor machines.
+
+config CPU_HAS_LLDSCD
+ bool "lld/scd Instructions available" if CPU_ADVANCED
+ default y if !CPU_ADVANCED && !CPU_R3000 && !CPU_VR41XX && !CPU_TX39XX && !CPU_MIPS32
+ help
+ Say Y here if your CPU has the lld and scd instructions, the 64-bit
+ equivalents of ll and sc. Say Y here for better performance, N if
+ you don't know. You must say Y here for multiprocessor machines.
+
+config CPU_HAS_WB
+ bool "Writeback Buffer available" if CPU_ADVANCED
+ default y if !CPU_ADVANCED && CPU_R3000 && MACH_DECSTATION
+ help
+ Say N here for slightly better performance. You must say Y here for
+ machines which require flushing of write buffers in software. Saying
+ Y is the safe option; N may result in kernel malfunction and crashes.
+
+config CPU_HAS_SYNC
+ bool
+ depends on !CPU_R3000
+ default y
+
+#
+# - Highmem only makes sense for the 32-bit kernel.
+# - The current highmem code will only work properly on physically indexed
+# caches such as R3000, SB1, R7000 or those that look like they're virtually
+# indexed such as R4000/R4400 SC and MC versions or R10000. So for the
+# moment we protect the user and offer the highmem option only on machines
+# where it's known to be safe. This will not offer highmem on a few systems
+# such as MIPS32 and MIPS64 CPUs which may have virtual and physically
+# indexed CPUs but we're playing safe.
+# - We should not offer highmem for system of which we already know that they
+# don't have memory configurations that could gain from highmem support in
+# the kernel because they don't support configurations with RAM at physical
+# addresses > 0x20000000.
+#
+config HIGHMEM
+ bool "High Memory Support"
+ depends on MIPS32 && (CPU_R3000 || CPU_SB1 || CPU_R7000 || CPU_RM9000 || CPU_R10000) && !(MACH_DECSTATION || MOMENCO_JAGUAR_ATX)
+
+config SMP
+ bool "Multi-Processing support"
+ depends on CPU_RM9000 || (SIBYTE_SB1250 && !SIBYTE_STANDALONE) || SGI_IP27
+ ---help---
+ This enables support for systems with more than one CPU. If you have
+ a system with only one CPU, like most personal computers, say N. If
+ you have a system with more than one CPU, say Y.
+
+ If you say N here, the kernel will run on single and multiprocessor
+ machines, but will use only one CPU of a multiprocessor machine. If
+ you say Y here, the kernel will run on many, but not all,
+ singleprocessor machines. On a singleprocessor machine, the kernel
+ will run faster if you say N here.
+
+ People using multiprocessor machines who say Y here should also say
+ Y to "Enhanced Real Time Clock Support", below.
+
+ See also the <file:Documentation/smp.txt> and the SMP-HOWTO
+ available at <http://www.tldp.org/docs.html#howto>.
+
+ If you don't know what to do here, say N.
+
+config NR_CPUS
+ int "Maximum number of CPUs (2-64)"
+ range 2 64
+ depends on SMP
+ default "64" if SGI_IP27
+ default "2"
+ help
+ This allows you to specify the maximum number of CPUs which this
+ kernel will support. The maximum supported value is 32 for 32-bit
+ kernel and 64 for 64-bit kernels; the minimum value which makes
+ sense is 2.
+
+ This is purely to save memory - each supported CPU adds
+ approximately eight kilobytes to the kernel image.
+
+config PREEMPT
+ bool "Preemptible Kernel"
+ help
+ This option reduces the latency of the kernel when reacting to
+ real-time or interactive events by allowing a low priority process to
+ be preempted even if it is in kernel mode executing a system call.
+ This allows applications to run more reliably even when the system is
+ under load.
+
+config RTC_DS1742
+ bool "DS1742 BRAM/RTC support"
+ depends on TOSHIBA_JMR3927 || TOSHIBA_RBTX4927
+
+config MIPS_INSANE_LARGE
+ bool "Support for large 64-bit configurations"
+ depends on CPU_R10000 && MIPS64
+ help
+ MIPS R10000 does support a 44 bit / 16TB address space as opposed to
+ previous 64-bit processors which only supported 40 bit / 1TB. If you
+ need processes of more than 1TB virtual address space, say Y here.
+ This will result in additional memory usage, so it is not
+ recommended for normal users.
+
+config RWSEM_GENERIC_SPINLOCK
+ bool
+ default y
+
+endmenu
+
+menu "Bus options (PCI, PCMCIA, EISA, ISA, TC)"
+
+config HW_HAS_PCI
+ bool
+
+config PCI
+ bool "Support for PCI controller"
+ depends on HW_HAS_PCI
+ help
+ Find out whether you have a PCI motherboard. PCI is the name of a
+ bus system, i.e. the way the CPU talks to the other stuff inside
+ your box. Other bus systems are ISA, EISA, or VESA. If you have PCI,
+ say Y, otherwise N.
+
+ The PCI-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>, contains valuable
+ information about which PCI hardware does work under Linux and which
+ doesn't.
+
+config PCI_DOMAINS
+ bool
+ depends on PCI
+
+source "drivers/pci/Kconfig"
+
+#
+# ISA support is now enabled via select. Too many systems still have the one
+# or other ISA chip on the board that users don't know about so don't expect
+# users to choose the right thing ...
+#
+config ISA
+ bool
+
+config EISA
+ bool "EISA support"
+ depends on SGI_IP22 || SNI_RM200_PCI
+ select ISA
+ ---help---
+ The Extended Industry Standard Architecture (EISA) bus was
+ developed as an open alternative to the IBM MicroChannel bus.
+
+ The EISA bus provided some of the features of the IBM MicroChannel
+ bus while maintaining backward compatibility with cards made for
+ the older ISA bus. The EISA bus saw limited use between 1988 and
+ 1995 when it was made obsolete by the PCI bus.
+
+ Say Y here if you are building a kernel for an EISA-based machine.
+
+ Otherwise, say N.
+
+source "drivers/eisa/Kconfig"
+
+config TC
+ bool "TURBOchannel support"
+ depends on MACH_DECSTATION
+ help
+ TurboChannel is a DEC (now Compaq (now HP)) bus for Alpha and MIPS
+ processors. Documentation on writing device drivers for TurboChannel
+ is available at:
+ <http://www.cs.arizona.edu/computer.help/policy/DIGITAL_unix/AA-PS3HD-TET1_html/TITLE.html>.
+
+#config ACCESSBUS
+# bool "Access.Bus support"
+# depends on TC
+
+config MMU
+ bool
+ default y
+
+config MCA
+ bool
+
+config SBUS
+ bool
+
+source "drivers/pcmcia/Kconfig"
+
+source "drivers/pci/hotplug/Kconfig"
+
+endmenu
+
+menu "Executable file formats"
+
+source "fs/Kconfig.binfmt"
+
+config TRAD_SIGNALS
+ bool
+ default y if MIPS32
+
+config BUILD_ELF64
+ bool "Use 64-bit ELF format for building"
+ depends on MIPS64
+ help
+ A 64-bit kernel is usually built using the 64-bit ELF binary object
+ format as it's one that allows arbitrary 64-bit constructs. For
+ kernels that are loaded within the KSEG compatibility segments the
+ 32-bit ELF format can optionally be used resulting in a somewhat
+ smaller binary, but this option is not explicitly supported by the
+ toolchain and since binutils 2.14 it does not even work at all.
+
+ Say Y to use the 64-bit format or N to use the 32-bit one.
+
+ If unsure say Y.
+
+config BINFMT_IRIX
+ bool "Include IRIX binary compatibility"
+ depends on !CPU_LITTLE_ENDIAN && MIPS32 && BROKEN
+
+config MIPS32_COMPAT
+ bool "Kernel support for Linux/MIPS 32-bit binary compatibility"
+ depends on MIPS64
+ help
+ Select this option if you want Linux/MIPS 32-bit binary
+ compatibility. Since all software available for Linux/MIPS is
+ currently 32-bit you should say Y here.
+
+config COMPAT
+ bool
+ depends on MIPS32_COMPAT
+ default y
+
+config MIPS32_O32
+ bool "Kernel support for o32 binaries"
+ depends on MIPS32_COMPAT
+ help
+ Select this option if you want to run o32 binaries. These are pure
+ 32-bit binaries as used by the 32-bit Linux/MIPS port. Most of
+ existing binaries are in this format.
+
+ If unsure, say Y.
+
+config MIPS32_N32
+ bool "Kernel support for n32 binaries"
+ depends on MIPS32_COMPAT
+ help
+ Select this option if you want to run n32 binaries. These are
+ 64-bit binaries using 32-bit quantities for addressing and certain
+ data that would normally be 64-bit. They are used in special
+ cases.
+
+ If unsure, say N.
+
+config BINFMT_ELF32
+ bool
+ default y if MIPS32_O32 || MIPS32_N32
+
+config PM
+ bool "Power Management support (EXPERIMENTAL)"
+ depends on EXPERIMENTAL && MACH_AU1X00
+
+endmenu
+
+source "drivers/Kconfig"
+
+source "fs/Kconfig"
+
+source "arch/mips/Kconfig.debug"
+
+source "security/Kconfig"
+
+source "crypto/Kconfig"
+
+source "lib/Kconfig"
+
+#
+# Use the generic interrupt handling code in kernel/irq/:
+#
+config GENERIC_HARDIRQS
+ bool
+ default y
+
+config GENERIC_IRQ_PROBE
+ bool
+ default y
diff --git a/arch/mips/Kconfig.debug b/arch/mips/Kconfig.debug
new file mode 100644
index 0000000..d3c5cc3
--- /dev/null
+++ b/arch/mips/Kconfig.debug
@@ -0,0 +1,76 @@
+menu "Kernel hacking"
+
+source "lib/Kconfig.debug"
+
+config CROSSCOMPILE
+ bool "Are you using a crosscompiler"
+ help
+ Say Y here if you are compiling the kernel on a different
+ architecture than the one it is intended to run on.
+
+config CMDLINE
+ string "Default kernel command string"
+ default ""
+ help
+ On some platforms, there is currently no way for the boot loader to
+ pass arguments to the kernel. For these platforms, you can supply
+ some command-line options at build time by entering them here. In
+ other cases you can specify kernel args so that you don't have
+ to set them up in board prom initialization routines.
+
+config DEBUG_STACK_USAGE
+ bool "Enable stack utilization instrumentation"
+ depends on DEBUG_KERNEL
+ help
+ Enables the display of the minimum amount of free stack which each
+ task has ever had available in the sysrq-T and sysrq-P debug output.
+
+ This option will slow down process creation somewhat.
+
+config KGDB
+ bool "Remote GDB kernel debugging"
+ depends on DEBUG_KERNEL
+ select DEBUG_INFO
+ help
+ If you say Y here, it will be possible to remotely debug the MIPS
+ kernel using gdb. This enlarges your kernel image disk size by
+ several megabytes and requires a machine with more than 16 MB,
+ better 32 MB RAM to avoid excessive linking time. This is only
+ useful for kernel hackers. If unsure, say N.
+
+config GDB_CONSOLE
+ bool "Console output to GDB"
+ depends on KGDB
+ help
+ If you are using GDB for remote debugging over a serial port and
+ would like kernel messages to be formatted into GDB $O packets so
+ that GDB prints them as program output, say 'Y'.
+
+config SB1XXX_CORELIS
+ bool "Corelis Debugger"
+ depends on SIBYTE_SB1xxx_SOC
+ select DEBUG_INFO
+ help
+ Select compile flags that produce code that can be processed by the
+ Corelis mksym utility and UDB Emulator.
+
+config RUNTIME_DEBUG
+ bool "Enable run-time debugging"
+ depends on DEBUG_KERNEL
+ help
+ If you say Y here, some debugging macros will do run-time checking.
+ If you say N here, those macros will mostly turn to no-ops. See
+ include/asm-mips/debug.h for debuging macros.
+ If unsure, say N.
+
+config MIPS_UNCACHED
+ bool "Run uncached"
+ depends on DEBUG_KERNEL && !SMP && !SGI_IP27
+ help
+ If you say Y here there kernel will disable all CPU caches. This will
+ reduce the system's performance dramatically but can help finding
+ otherwise hard to track bugs. It can also useful if you're doing
+ hardware debugging with a logic analyzer and need to see all traffic
+ on the bus.
+
+endmenu
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
new file mode 100644
index 0000000..bc1c442
--- /dev/null
+++ b/arch/mips/Makefile
@@ -0,0 +1,767 @@
+#
+# 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) 1994, 95, 96, 2003 by Ralf Baechle
+# DECStation modifications by Paul M. Antoine, 1996
+# Copyright (C) 2002, 2003, 2004 Maciej W. Rozycki
+#
+# This file is included by the global makefile so that you can add your own
+# architecture-specific flags and dependencies. Remember to do have actions
+# for "archclean" cleaning up for this architecture.
+#
+
+as-option = $(shell if $(CC) $(CFLAGS) $(1) -Wa,-Z -c -o /dev/null \
+ -xassembler /dev/null > /dev/null 2>&1; then echo "$(1)"; \
+ else echo "$(2)"; fi ;)
+
+cflags-y :=
+
+#
+# Select the object file format to substitute into the linker script.
+#
+ifdef CONFIG_CPU_LITTLE_ENDIAN
+32bit-tool-prefix = mipsel-linux-
+64bit-tool-prefix = mips64el-linux-
+32bit-bfd = elf32-tradlittlemips
+64bit-bfd = elf64-tradlittlemips
+32bit-emul = elf32ltsmip
+64bit-emul = elf64ltsmip
+else
+32bit-tool-prefix = mips-linux-
+64bit-tool-prefix = mips64-linux-
+32bit-bfd = elf32-tradbigmips
+64bit-bfd = elf64-tradbigmips
+32bit-emul = elf32btsmip
+64bit-emul = elf64btsmip
+endif
+
+ifdef CONFIG_MIPS32
+gcc-abi = 32
+tool-prefix = $(32bit-tool-prefix)
+UTS_MACHINE := mips
+endif
+ifdef CONFIG_MIPS64
+gcc-abi = 64
+tool-prefix = $(64bit-tool-prefix)
+UTS_MACHINE := mips64
+endif
+
+ifdef CONFIG_CROSSCOMPILE
+CROSS_COMPILE := $(tool-prefix)
+endif
+
+ifdef CONFIG_BUILD_ELF64
+gas-abi = 64
+ld-emul = $(64bit-emul)
+vmlinux-32 = vmlinux.32
+vmlinux-64 = vmlinux
+else
+gas-abi = 32
+ld-emul = $(32bit-emul)
+vmlinux-32 = vmlinux
+vmlinux-64 = vmlinux.64
+
+cflags-$(CONFIG_MIPS64) += $(call cc-option,-mno-explicit-relocs)
+endif
+
+#
+# GCC uses -G 0 -mabicalls -fpic as default. We don't want PIC in the kernel
+# code since it only slows down the whole thing. At some point we might make
+# use of global pointer optimizations but their use of $28 conflicts with
+# the current pointer optimization.
+#
+# The DECStation requires an ECOFF kernel for remote booting, other MIPS
+# machines may also. Since BFD is incredibly buggy with respect to
+# crossformat linking we rely on the elf2ecoff tool for format conversion.
+#
+cflags-y += -I $(TOPDIR)/include/asm/gcc
+cflags-y += -G 0 -mno-abicalls -fno-pic -pipe
+cflags-y += $(call cc-option, -finline-limit=100000)
+LDFLAGS_vmlinux += -G 0 -static -n
+MODFLAGS += -mlong-calls
+
+cflags-$(CONFIG_SB1XXX_CORELIS) += -mno-sched-prolog -fno-omit-frame-pointer
+
+#
+# Use: $(call set_gccflags,<cpu0>,<isa0>,<cpu1>,<isa1>,<isa2>)
+#
+# <cpu0>,<isa0> -- preferred CPU and ISA designations (may require
+# recent tools)
+# <cpu1>,<isa1> -- fallback CPU and ISA designations (have to work
+# with up to the oldest supported tools)
+# <isa2> -- an ISA designation used as an ABI selector for
+# gcc versions that do not support "-mabi=32"
+# (depending on the CPU type, either "mips1" or
+# "mips2")
+#
+set_gccflags = $(shell \
+while :; do \
+ cpu=$(1); isa=-$(2); \
+ for gcc_opt in -march= -mcpu=; do \
+ $(CC) $$gcc_opt$$cpu $$isa -S -o /dev/null \
+ -xc /dev/null > /dev/null 2>&1 && \
+ break 2; \
+ done; \
+ cpu=$(3); isa=-$(4); \
+ for gcc_opt in -march= -mcpu=; do \
+ $(CC) $$gcc_opt$$cpu $$isa -S -o /dev/null \
+ -xc /dev/null > /dev/null 2>&1 && \
+ break 2; \
+ done; \
+ break; \
+done; \
+gcc_abi=-mabi=$(gcc-abi); gcc_cpu=$$cpu; \
+if $(CC) $$gcc_abi -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then \
+ gcc_isa=$$isa; \
+else \
+ gcc_abi=; gcc_isa=-$(5); \
+fi; \
+gas_abi=-Wa,-$(gcc-abi); gas_cpu=$$cpu; gas_isa=-Wa,$$isa; \
+while :; do \
+ for gas_opt in -Wa,-march= -Wa,-mcpu=; do \
+ $(CC) $$gas_abi $$gas_opt$$cpu $$gas_isa -Wa,-Z -c \
+ -o /dev/null -xassembler /dev/null > /dev/null 2>&1 && \
+ break 2; \
+ done; \
+ gas_abi=; gas_opt=; gas_cpu=; gas_isa=; \
+ break; \
+done; \
+if test "$(gcc-abi)" != "$(gas-abi)"; then \
+ gas_abi="-Wa,-$(gas-abi) -Wa,-mgp$(gcc-abi)"; \
+fi; \
+if test "$$gcc_opt" = -march= && test -n "$$gcc_abi"; then \
+ $(CC) $$gcc_abi $$gcc_opt$$gcc_cpu -S -o /dev/null \
+ -xc /dev/null > /dev/null 2>&1 && \
+ gcc_isa=; \
+fi; \
+echo $$gcc_abi $$gcc_opt$$gcc_cpu $$gcc_isa $$gas_abi $$gas_opt$$gas_cpu $$gas_isa)
+
+#
+# CPU-dependent compiler/assembler options for optimization.
+#
+cflags-$(CONFIG_CPU_R3000) += \
+ $(call set_gccflags,r3000,mips1,r3000,mips1,mips1)
+
+cflags-$(CONFIG_CPU_TX39XX) += \
+ $(call set_gccflags,r3900,mips1,r3000,mips1,mips1)
+
+cflags-$(CONFIG_CPU_R6000) += \
+ $(call set_gccflags,r6000,mips2,r6000,mips2,mips2) \
+ -Wa,--trap
+
+cflags-$(CONFIG_CPU_R4300) += \
+ $(call set_gccflags,r4300,mips3,r4300,mips3,mips2) \
+ -Wa,--trap
+
+cflags-$(CONFIG_CPU_VR41XX) += \
+ $(call set_gccflags,r4100,mips3,r4600,mips3,mips2) \
+ -Wa,--trap
+
+cflags-$(CONFIG_CPU_R4X00) += \
+ $(call set_gccflags,r4600,mips3,r4600,mips3,mips2) \
+ -Wa,--trap
+
+cflags-$(CONFIG_CPU_TX49XX) += \
+ $(call set_gccflags,r4600,mips3,r4600,mips3,mips2) \
+ -Wa,--trap
+
+cflags-$(CONFIG_CPU_MIPS32) += \
+ $(call set_gccflags,mips32,mips32,r4600,mips3,mips2) \
+ -Wa,--trap
+
+cflags-$(CONFIG_CPU_MIPS64) += \
+ $(call set_gccflags,mips64,mips64,r4600,mips3,mips2) \
+ -Wa,--trap
+
+cflags-$(CONFIG_CPU_R5000) += \
+ $(call set_gccflags,r5000,mips4,r5000,mips4,mips2) \
+ -Wa,--trap
+
+cflags-$(CONFIG_CPU_R5432) += \
+ $(call set_gccflags,r5400,mips4,r5000,mips4,mips2) \
+ -Wa,--trap
+
+cflags-$(CONFIG_CPU_NEVADA) += \
+ $(call set_gccflags,rm5200,mips4,r5000,mips4,mips2) \
+ -Wa,--trap
+# $(call cc-option,-mmad)
+
+cflags-$(CONFIG_CPU_RM7000) += \
+ $(call set_gccflags,rm7000,mips4,r5000,mips4,mips2) \
+ -Wa,--trap
+
+cflags-$(CONFIG_CPU_RM9000) += \
+ $(call set_gccflags,rm9000,mips4,r5000,mips4,mips2) \
+ -Wa,--trap
+
+cflags-$(CONFIG_CPU_SB1) += \
+ $(call set_gccflags,sb1,mips64,r5000,mips4,mips2) \
+ -Wa,--trap
+
+cflags-$(CONFIG_CPU_R8000) += \
+ $(call set_gccflags,r8000,mips4,r8000,mips4,mips2) \
+ -Wa,--trap
+
+cflags-$(CONFIG_CPU_R10000) += \
+ $(call set_gccflags,r10000,mips4,r8000,mips4,mips2) \
+ -Wa,--trap
+
+ifdef CONFIG_CPU_SB1
+ifdef CONFIG_SB1_PASS_1_WORKAROUNDS
+MODFLAGS += -msb1-pass1-workarounds
+endif
+endif
+
+#
+# Firmware support
+#
+libs-$(CONFIG_ARC) += arch/mips/arc/
+libs-$(CONFIG_SIBYTE_CFE) += arch/mips/sibyte/cfe/
+
+#
+# Board-dependent options and extra files
+#
+
+#
+# Acer PICA 61, Mips Magnum 4000 and Olivetti M700.
+#
+core-$(CONFIG_MACH_JAZZ) += arch/mips/jazz/
+cflags-$(CONFIG_MACH_JAZZ) += -Iinclude/asm-mips/mach-jazz
+load-$(CONFIG_MACH_JAZZ) += 0xffffffff80080000
+
+#
+# Common Alchemy Au1x00 stuff
+#
+core-$(CONFIG_SOC_AU1X00) += arch/mips/au1000/common/
+cflags-$(CONFIG_SOC_AU1X00) += -Iinclude/asm-mips/mach-au1x00
+
+#
+# AMD Alchemy Pb1000 eval board
+#
+libs-$(CONFIG_MIPS_PB1000) += arch/mips/au1000/pb1000/
+cflags-$(CONFIG_MIPS_PB1000) += -Iinclude/asm-mips/mach-pb1x00
+load-$(CONFIG_MIPS_PB1000) += 0xffffffff80100000
+
+#
+# AMD Alchemy Pb1100 eval board
+#
+libs-$(CONFIG_MIPS_PB1100) += arch/mips/au1000/pb1100/
+cflags-$(CONFIG_MIPS_PB1100) += -Iinclude/asm-mips/mach-pb1x00
+load-$(CONFIG_MIPS_PB1100) += 0xffffffff80100000
+
+#
+# AMD Alchemy Pb1500 eval board
+#
+libs-$(CONFIG_MIPS_PB1500) += arch/mips/au1000/pb1500/
+cflags-$(CONFIG_MIPS_PB1500) += -Iinclude/asm-mips/mach-pb1x00
+load-$(CONFIG_MIPS_PB1500) += 0xffffffff80100000
+
+#
+# AMD Alchemy Pb1550 eval board
+#
+libs-$(CONFIG_MIPS_PB1550) += arch/mips/au1000/pb1550/
+cflags-$(CONFIG_MIPS_PB1550) += -Iinclude/asm-mips/mach-pb1x00
+load-$(CONFIG_MIPS_PB1550) += 0xffffffff80100000
+
+#
+# AMD Alchemy Db1000 eval board
+#
+libs-$(CONFIG_MIPS_DB1000) += arch/mips/au1000/db1x00/
+cflags-$(CONFIG_MIPS_DB1000) += -Iinclude/asm-mips/mach-db1x00
+load-$(CONFIG_MIPS_DB1000) += 0xffffffff80100000
+
+#
+# AMD Alchemy Db1100 eval board
+#
+libs-$(CONFIG_MIPS_DB1100) += arch/mips/au1000/db1x00/
+cflags-$(CONFIG_MIPS_DB1100) += -Iinclude/asm-mips/mach-db1x00
+load-$(CONFIG_MIPS_DB1100) += 0xffffffff80100000
+
+#
+# AMD Alchemy Db1500 eval board
+#
+libs-$(CONFIG_MIPS_DB1500) += arch/mips/au1000/db1x00/
+cflags-$(CONFIG_MIPS_DB1500) += -Iinclude/asm-mips/mach-db1x00
+load-$(CONFIG_MIPS_DB1500) += 0xffffffff80100000
+
+#
+# AMD Alchemy Db1550 eval board
+#
+libs-$(CONFIG_MIPS_DB1550) += arch/mips/au1000/db1x00/
+cflags-$(CONFIG_MIPS_DB1550) += -Iinclude/asm-mips/mach-db1x00
+load-$(CONFIG_MIPS_DB1550) += 0xffffffff80100000
+
+#
+# AMD Alchemy Bosporus eval board
+#
+libs-$(CONFIG_MIPS_BOSPORUS) += arch/mips/au1000/db1x00/
+cflags-$(CONFIG_MIPS_BOSPORUS) += -Iinclude/asm-mips/mach-db1x00
+load-$(CONFIG_MIPS_BOSPORUS) += 0xffffffff80100000
+
+#
+# AMD Alchemy Mirage eval board
+#
+libs-$(CONFIG_MIPS_MIRAGE) += arch/mips/au1000/db1x00/
+cflags-$(CONFIG_MIPS_MIRAGE) += -Iinclude/asm-mips/mach-db1x00
+load-$(CONFIG_MIPS_MIRAGE) += 0xffffffff80100000
+
+#
+# 4G-Systems eval board
+#
+libs-$(CONFIG_MIPS_MTX1) += arch/mips/au1000/mtx-1/
+load-$(CONFIG_MIPS_MTX1) += 0xffffffff80100000
+
+#
+# MyCable eval board
+#
+libs-$(CONFIG_MIPS_XXS1500) += arch/mips/au1000/xxs1500/
+load-$(CONFIG_MIPS_XXS1500) += 0xffffffff80100000
+
+#
+# Cobalt Server
+#
+core-$(CONFIG_MIPS_COBALT) += arch/mips/cobalt/
+load-$(CONFIG_MIPS_COBALT) += 0xffffffff80080000
+
+#
+# DECstation family
+#
+core-$(CONFIG_MACH_DECSTATION) += arch/mips/dec/
+cflags-$(CONFIG_MACH_DECSTATION)+= -Iinclude/asm-mips/mach-dec
+libs-$(CONFIG_MACH_DECSTATION) += arch/mips/dec/prom/
+load-$(CONFIG_MACH_DECSTATION) += 0xffffffff80040000
+CLEAN_FILES += drivers/tc/lk201-map.c
+
+#
+# Galileo EV64120 Board
+#
+core-$(CONFIG_MIPS_EV64120) += arch/mips/gt64120/ev64120/
+core-$(CONFIG_MIPS_EV64120) += arch/mips/gt64120/common/
+cflags-$(CONFIG_MIPS_EV64120) += -Iinclude/asm-mips/mach-ev64120
+load-$(CONFIG_MIPS_EV64120) += 0xffffffff80100000
+
+#
+# Galileo EV96100 Board
+#
+core-$(CONFIG_MIPS_EV96100) += arch/mips/galileo-boards/ev96100/
+cflags-$(CONFIG_MIPS_EV96100) += -Iinclude/asm-mips/mach-ev96100
+load-$(CONFIG_MIPS_EV96100) += 0xffffffff80100000
+
+#
+# Globespan IVR eval board with QED 5231 CPU
+#
+core-$(CONFIG_ITE_BOARD_GEN) += arch/mips/ite-boards/generic/
+core-$(CONFIG_MIPS_IVR) += arch/mips/ite-boards/ivr/
+load-$(CONFIG_MIPS_IVR) += 0xffffffff80100000
+
+#
+# ITE 8172 eval board with QED 5231 CPU
+#
+core-$(CONFIG_MIPS_ITE8172) += arch/mips/ite-boards/qed-4n-s01b/
+load-$(CONFIG_MIPS_ITE8172) += 0xffffffff80100000
+
+#
+# For all MIPS, Inc. eval boards
+#
+core-$(CONFIG_MIPS_BOARDS_GEN) += arch/mips/mips-boards/generic/
+
+#
+# MIPS Atlas board
+#
+core-$(CONFIG_MIPS_ATLAS) += arch/mips/mips-boards/atlas/
+cflags-$(CONFIG_MIPS_ATLAS) += -Iinclude/asm-mips/mach-atlas
+cflags-$(CONFIG_MIPS_ATLAS) += -Iinclude/asm-mips/mach-mips
+load-$(CONFIG_MIPS_ATLAS) += 0xffffffff80100000
+
+#
+# MIPS Malta board
+#
+core-$(CONFIG_MIPS_MALTA) += arch/mips/mips-boards/malta/
+cflags-$(CONFIG_MIPS_MALTA) += -Iinclude/asm-mips/mach-mips
+load-$(CONFIG_MIPS_MALTA) += 0xffffffff80100000
+
+#
+# MIPS SEAD board
+#
+core-$(CONFIG_MIPS_SEAD) += arch/mips/mips-boards/sead/
+load-$(CONFIG_MIPS_SEAD) += 0xffffffff80100000
+
+#
+# Momentum Ocelot board
+#
+# The Ocelot setup.o must be linked early - it does the ioremap() for the
+# mips_io_port_base.
+#
+core-$(CONFIG_MOMENCO_OCELOT) += arch/mips/gt64120/common/ \
+ arch/mips/gt64120/momenco_ocelot/
+cflags-$(CONFIG_MOMENCO_OCELOT) += -Iinclude/asm-mips/mach-ocelot
+load-$(CONFIG_MOMENCO_OCELOT) += 0xffffffff80100000
+
+#
+# Momentum Ocelot-G board
+#
+# The Ocelot-G setup.o must be linked early - it does the ioremap() for the
+# mips_io_port_base.
+#
+core-$(CONFIG_MOMENCO_OCELOT_G) += arch/mips/momentum/ocelot_g/
+load-$(CONFIG_MOMENCO_OCELOT_G) += 0xffffffff80100000
+
+#
+# Momentum Ocelot-C and -CS boards
+#
+# The Ocelot-C[S] setup.o must be linked early - it does the ioremap() for the
+# mips_io_port_base.
+core-$(CONFIG_MOMENCO_OCELOT_C) += arch/mips/momentum/ocelot_c/
+load-$(CONFIG_MOMENCO_OCELOT_C) += 0xffffffff80100000
+
+#
+# PMC-Sierra Yosemite
+#
+core-$(CONFIG_PMC_YOSEMITE) += arch/mips/pmc-sierra/yosemite/
+cflags-$(CONFIG_PMC_YOSEMITE) += -Iinclude/asm-mips/mach-yosemite
+load-$(CONFIG_PMC_YOSEMITE) += 0xffffffff80100000
+
+#
+# Momentum Ocelot-3
+#
+core-$(CONFIG_MOMENCO_OCELOT_3) += arch/mips/momentum/ocelot_3/
+cflags-$(CONFIG_MOMENCO_OCELOT_3) += -Iinclude/asm-mips/mach-ocelot3
+load-$(CONFIG_MOMENCO_OCELOT_3) += 0xffffffff80100000
+
+#
+# Momentum Jaguar ATX
+#
+core-$(CONFIG_MOMENCO_JAGUAR_ATX) += arch/mips/momentum/jaguar_atx/
+cflags-$(CONFIG_MOMENCO_JAGUAR_ATX) += -Iinclude/asm-mips/mach-ja
+#ifdef CONFIG_JAGUAR_DMALOW
+#load-$(CONFIG_MOMENCO_JAGUAR_ATX) += 0xffffffff88000000
+#else
+load-$(CONFIG_MOMENCO_JAGUAR_ATX) += 0xffffffff80100000
+#endif
+
+#
+# NEC DDB
+#
+core-$(CONFIG_DDB5XXX_COMMON) += arch/mips/ddb5xxx/common/
+
+#
+# NEC DDB Vrc-5074
+#
+core-$(CONFIG_DDB5074) += arch/mips/ddb5xxx/ddb5074/
+load-$(CONFIG_DDB5074) += 0xffffffff80080000
+
+#
+# NEC DDB Vrc-5476
+#
+core-$(CONFIG_DDB5476) += arch/mips/ddb5xxx/ddb5476/
+load-$(CONFIG_DDB5476) += 0xffffffff80080000
+
+#
+# NEC DDB Vrc-5477
+#
+core-$(CONFIG_DDB5477) += arch/mips/ddb5xxx/ddb5477/
+load-$(CONFIG_DDB5477) += 0xffffffff80100000
+
+core-$(CONFIG_LASAT) += arch/mips/lasat/
+cflags-$(CONFIG_LASAT) += -Iinclude/asm-mips/mach-lasat
+load-$(CONFIG_LASAT) += 0xffffffff80000000
+
+#
+# NEC Osprey (vr4181) board
+#
+core-$(CONFIG_NEC_OSPREY) += arch/mips/vr4181/common/ \
+ arch/mips/vr4181/osprey/
+load-$(CONFIG_NEC_OSPREY) += 0xffffffff80002000
+
+#
+# Common VR41xx
+#
+core-$(CONFIG_MACH_VR41XX) += arch/mips/vr41xx/common/
+cflags-$(CONFIG_MACH_VR41XX) += -Iinclude/asm-mips/mach-vr41xx
+
+#
+# NEC VR4133
+#
+core-$(CONFIG_NEC_CMBVR4133) += arch/mips/vr41xx/nec-cmbvr4133/
+load-$(CONFIG_NEC_CMBVR4133) += 0xffffffff80100000
+
+#
+# ZAO Networks Capcella (VR4131)
+#
+core-$(CONFIG_ZAO_CAPCELLA) += arch/mips/vr41xx/zao-capcella/
+load-$(CONFIG_ZAO_CAPCELLA) += 0xffffffff80000000
+
+#
+# Victor MP-C303/304 (VR4122)
+#
+core-$(CONFIG_VICTOR_MPC30X) += arch/mips/vr41xx/victor-mpc30x/
+load-$(CONFIG_VICTOR_MPC30X) += 0xffffffff80001000
+
+#
+# IBM WorkPad z50 (VR4121)
+#
+core-$(CONFIG_IBM_WORKPAD) += arch/mips/vr41xx/ibm-workpad/
+load-$(CONFIG_IBM_WORKPAD) += 0xffffffff80004000
+
+#
+# CASIO CASSIPEIA E-55/65 (VR4111)
+#
+core-$(CONFIG_CASIO_E55) += arch/mips/vr41xx/casio-e55/
+load-$(CONFIG_CASIO_E55) += 0xffffffff80004000
+
+#
+# TANBAC TB0226 Mbase (VR4131)
+#
+core-$(CONFIG_TANBAC_TB0226) += arch/mips/vr41xx/tanbac-tb0226/
+load-$(CONFIG_TANBAC_TB0226) += 0xffffffff80000000
+
+#
+# TANBAC TB0229 VR4131DIMM (VR4131)
+#
+core-$(CONFIG_TANBAC_TB0229) += arch/mips/vr41xx/tanbac-tb0229/
+load-$(CONFIG_TANBAC_TB0229) += 0xffffffff80000000
+
+#
+# SGI IP22 (Indy/Indigo2)
+#
+# Set the load address to >= 0xffffffff88069000 if you want to leave space for
+# symmon, 0xffffffff80002000 for production kernels. Note that the value must
+# be aligned to a multiple of the kernel stack size or the handling of the
+# current variable will break so for 64-bit kernels we have to raise the start
+# address by 8kb.
+#
+core-$(CONFIG_SGI_IP22) += arch/mips/sgi-ip22/
+cflags-$(CONFIG_SGI_IP22) += -Iinclude/asm-mips/mach-ip22
+ifdef CONFIG_MIPS32
+load-$(CONFIG_SGI_IP22) += 0xffffffff88002000
+endif
+ifdef CONFIG_MIPS64
+load-$(CONFIG_SGI_IP22) += 0xffffffff88004000
+endif
+
+#
+# SGI-IP27 (Origin200/2000)
+#
+# Set the load address to >= 0xc000000000300000 if you want to leave space for
+# symmon, 0xc00000000001c000 for production kernels. Note that the value must
+# be 16kb aligned or the handling of the current variable will break.
+#
+ifdef CONFIG_SGI_IP27
+core-$(CONFIG_SGI_IP27) += arch/mips/sgi-ip27/
+cflags-$(CONFIG_SGI_IP27) += -Iinclude/asm-mips/mach-ip27
+ifdef CONFIG_BUILD_ELF64
+ifdef CONFIG_MAPPED_KERNEL
+load-$(CONFIG_SGI_IP27) += 0xc00000004001c000
+OBJCOPYFLAGS := --change-addresses=0x3fffffff80000000
+dataoffset-$(CONFIG_SGI_IP27) += 0x01000000
+else
+load-$(CONFIG_SGI_IP27) += 0xa80000000001c000
+OBJCOPYFLAGS := --change-addresses=0x57ffffff80000000
+endif
+else
+ifdef CONFIG_MAPPED_KERNEL
+load-$(CONFIG_SGI_IP27) += 0xffffffffc001c000
+OBJCOPYFLAGS := --change-addresses=0xc000000080000000
+dataoffset-$(CONFIG_SGI_IP27) += 0x01000000
+else
+load-$(CONFIG_SGI_IP27) += 0xffffffff8001c000
+OBJCOPYFLAGS := --change-addresses=0xa800000080000000
+endif
+endif
+endif
+
+#
+# SGI-IP32 (O2)
+#
+# Set the load address to >= 80069000 if you want to leave space for symmon,
+# 0xffffffff80004000 for production kernels. Note that the value must be aligned to
+# a multiple of the kernel stack size or the handling of the current variable
+# will break.
+#
+core-$(CONFIG_SGI_IP32) += arch/mips/sgi-ip32/
+cflags-$(CONFIG_SGI_IP32) += -Iinclude/asm-mips/mach-ip32
+load-$(CONFIG_SGI_IP32) += 0xffffffff80004000
+
+#
+# Sibyte SB1250 SOC
+#
+# This is a LIB so that it links at the end, and initcalls are later
+# the sequence; but it is built as an object so that modules don't get
+# removed (as happens, even if they have __initcall/module_init)
+#
+core-$(CONFIG_SIBYTE_BCM112X) += arch/mips/sibyte/sb1250/
+cflags-$(CONFIG_SIBYTE_BCM112X) += -Iinclude/asm-mips/mach-sibyte
+
+core-$(CONFIG_SIBYTE_SB1250) += arch/mips/sibyte/sb1250/
+cflags-$(CONFIG_SIBYTE_SB1250) += -Iinclude/asm-mips/mach-sibyte
+
+#
+# Sibyte BCM91120x (Carmel) board
+# Sibyte BCM91120C (CRhine) board
+# Sibyte BCM91125C (CRhone) board
+# Sibyte BCM91125E (Rhone) board
+# Sibyte SWARM board
+#
+libs-$(CONFIG_SIBYTE_CARMEL) += arch/mips/sibyte/swarm/
+load-$(CONFIG_SIBYTE_CARMEL) := 0xffffffff80100000
+libs-$(CONFIG_SIBYTE_CRHINE) += arch/mips/sibyte/swarm/
+load-$(CONFIG_SIBYTE_CRHINE) := 0xffffffff80100000
+libs-$(CONFIG_SIBYTE_CRHONE) += arch/mips/sibyte/swarm/
+load-$(CONFIG_SIBYTE_CRHONE) := 0xffffffff80100000
+libs-$(CONFIG_SIBYTE_RHONE) += arch/mips/sibyte/swarm/
+load-$(CONFIG_SIBYTE_RHONE) := 0xffffffff80100000
+libs-$(CONFIG_SIBYTE_SENTOSA) += arch/mips/sibyte/swarm/
+load-$(CONFIG_SIBYTE_SENTOSA) := 0xffffffff80100000
+libs-$(CONFIG_SIBYTE_SWARM) += arch/mips/sibyte/swarm/
+load-$(CONFIG_SIBYTE_SWARM) := 0xffffffff80100000
+
+#
+# SNI RM200 PCI
+#
+core-$(CONFIG_SNI_RM200_PCI) += arch/mips/sni/
+cflags-$(CONFIG_SNI_RM200_PCI) += -Iinclude/asm-mips/mach-rm200
+load-$(CONFIG_SNI_RM200_PCI) += 0xffffffff80600000
+
+#
+# Toshiba JMR-TX3927 board
+#
+core-$(CONFIG_TOSHIBA_JMR3927) += arch/mips/jmr3927/rbhma3100/ \
+ arch/mips/jmr3927/common/
+load-$(CONFIG_TOSHIBA_JMR3927) += 0xffffffff80050000
+
+#
+# Toshiba RBTX4927 board or
+# Toshiba RBTX4937 board
+#
+core-$(CONFIG_TOSHIBA_RBTX4927) += arch/mips/tx4927/toshiba_rbtx4927/
+core-$(CONFIG_TOSHIBA_RBTX4927) += arch/mips/tx4927/common/
+load-$(CONFIG_TOSHIBA_RBTX4927) += 0xffffffff80020000
+
+cflags-y += -Iinclude/asm-mips/mach-generic
+drivers-$(CONFIG_PCI) += arch/mips/pci/
+
+ifdef CONFIG_MIPS32
+ifdef CONFIG_CPU_LITTLE_ENDIAN
+JIFFIES = jiffies_64
+else
+JIFFIES = jiffies_64 + 4
+endif
+else
+JIFFIES = jiffies_64
+endif
+
+AFLAGS += $(cflags-y)
+CFLAGS += $(cflags-y)
+
+LDFLAGS += -m $(ld-emul)
+
+OBJCOPYFLAGS += --remove-section=.reginfo
+
+#
+# Choosing incompatible machines durings configuration will result in
+# error messages during linking. Select a default linkscript if
+# none has been choosen above.
+#
+
+CPPFLAGS_vmlinux.lds := \
+ $(CFLAGS) \
+ -D"LOADADDR=$(load-y)" \
+ -D"JIFFIES=$(JIFFIES)" \
+ -D"DATAOFFSET=$(if $(dataoffset-y),$(dataoffset-y),0)"
+
+head-y := arch/mips/kernel/head.o arch/mips/kernel/init_task.o
+
+libs-y += arch/mips/lib/
+libs-$(CONFIG_MIPS32) += arch/mips/lib-32/
+libs-$(CONFIG_MIPS64) += arch/mips/lib-64/
+
+core-y += arch/mips/kernel/ arch/mips/mm/ arch/mips/math-emu/
+
+drivers-$(CONFIG_OPROFILE) += arch/mips/oprofile/
+
+ifdef CONFIG_LASAT
+rom.bin rom.sw: vmlinux
+ $(call descend,arch/mips/lasat/image,$@)
+endif
+
+#
+# Some machines like the Indy need 32-bit ELF binaries for booting purposes.
+# Other need ECOFF, so we build a 32-bit ELF binary for them which we then
+# convert to ECOFF using elf2ecoff.
+#
+vmlinux.32: vmlinux
+ $(OBJCOPY) -O $(32bit-bfd) $(OBJCOPYFLAGS) $< $@
+
+#
+# The 64-bit ELF tools are pretty broken so at this time we generate 64-bit
+# ELF files from 32-bit files by conversion.
+#
+vmlinux.64: vmlinux
+ $(OBJCOPY) -O $(64bit-bfd) $(OBJCOPYFLAGS) $< $@
+
+makeboot =$(Q)$(MAKE) $(build)=arch/mips/boot VMLINUX=$(vmlinux-32) $(1)
+
+ifdef CONFIG_BOOT_ELF32
+all: $(vmlinux-32)
+endif
+
+ifdef CONFIG_BOOT_ELF64
+all: $(vmlinux-64)
+endif
+
+ifdef CONFIG_SNI_RM200_PCI
+all: vmlinux.ecoff
+endif
+
+vmlinux.ecoff vmlinux.rm200: $(vmlinux-32)
+ +@$(call makeboot,$@)
+
+vmlinux.srec: $(vmlinux-32)
+ +@$(call makeboot,$@)
+
+CLEAN_FILES += vmlinux.ecoff \
+ vmlinux.srec \
+ vmlinux.rm200.tmp \
+ vmlinux.rm200
+
+archclean:
+ @$(MAKE) $(clean)=arch/mips/boot
+ @$(MAKE) $(clean)=arch/mips/lasat
+
+# Generate <asm/offset.h
+#
+# The default rule is suffering from funny problems on MIPS so we using our
+# own ...
+#
+# ---------------------------------------------------------------------------
+
+define filechk_gen-asm-offset.h
+ (set -e; \
+ echo "#ifndef _ASM_OFFSET_H"; \
+ echo "#define _ASM_OFFSET_H"; \
+ echo "/*"; \
+ echo " * DO NOT MODIFY."; \
+ echo " *"; \
+ echo " * This file was generated by arch/$(ARCH)/Makefile"; \
+ echo " *"; \
+ echo " */"; \
+ echo ""; \
+ sed -ne "/^@@@/s///p"; \
+ echo "#endif /* _ASM_OFFSET_H */" )
+endef
+
+prepare: include/asm-$(ARCH)/offset.h
+
+arch/$(ARCH)/kernel/offset.s: include/asm include/linux/version.h \
+ include/config/MARKER
+
+include/asm-$(ARCH)/offset.h: arch/$(ARCH)/kernel/offset.s
+ $(call filechk,gen-asm-offset.h)
+
+CLEAN_FILES += include/asm-$(ARCH)/offset.h.tmp \
+ include/asm-$(ARCH)/offset.h \
+ vmlinux.32 \
+ vmlinux.64 \
+ vmlinux.ecoff
diff --git a/arch/mips/arc/Makefile b/arch/mips/arc/Makefile
new file mode 100644
index 0000000..e842493
--- /dev/null
+++ b/arch/mips/arc/Makefile
@@ -0,0 +1,10 @@
+#
+# Makefile for the ARC prom monitor library routines under Linux.
+#
+
+lib-y += cmdline.o env.o file.o identify.o init.o \
+ misc.o time.o tree.o
+
+lib-$(CONFIG_ARC_MEMORY) += memory.o
+lib-$(CONFIG_ARC_CONSOLE) += arc_con.o
+lib-$(CONFIG_ARC_PROMLIB) += promlib.o
diff --git a/arch/mips/arc/arc_con.c b/arch/mips/arc/arc_con.c
new file mode 100644
index 0000000..51785a6
--- /dev/null
+++ b/arch/mips/arc/arc_con.c
@@ -0,0 +1,50 @@
+/*
+ * Wrap-around code for a console using the
+ * ARC io-routines.
+ *
+ * Copyright (c) 1998 Harald Koerfgen
+ * Copyright (c) 2001 Ralf Baechle
+ * Copyright (c) 2002 Thiemo Seufer
+ */
+#include <linux/tty.h>
+#include <linux/major.h>
+#include <linux/init.h>
+#include <linux/console.h>
+#include <linux/fs.h>
+#include <asm/sgialib.h>
+
+static void prom_console_write(struct console *co, const char *s,
+ unsigned count)
+{
+ /* Do each character */
+ while (count--) {
+ if (*s == '\n')
+ prom_putchar('\r');
+ prom_putchar(*s++);
+ }
+}
+
+static int __init prom_console_setup(struct console *co, char *options)
+{
+ return !(prom_flags & PROM_FLAG_USE_AS_CONSOLE);
+}
+
+static struct console arc_cons = {
+ .name = "arc",
+ .write = prom_console_write,
+ .setup = prom_console_setup,
+ .flags = CON_PRINTBUFFER,
+ .index = -1,
+};
+
+/*
+ * Register console.
+ */
+
+static int __init arc_console_init(void)
+{
+ register_console(&arc_cons);
+
+ return 0;
+}
+console_initcall(arc_console_init);
diff --git a/arch/mips/arc/cmdline.c b/arch/mips/arc/cmdline.c
new file mode 100644
index 0000000..fd604ef
--- /dev/null
+++ b/arch/mips/arc/cmdline.c
@@ -0,0 +1,108 @@
+/*
+ * 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.
+ *
+ * cmdline.c: Kernel command line creation using ARCS argc/argv.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+
+#include <asm/sgialib.h>
+#include <asm/bootinfo.h>
+
+#undef DEBUG_CMDLINE
+
+char * __init prom_getcmdline(void)
+{
+ return arcs_cmdline;
+}
+
+static char *ignored[] = {
+ "ConsoleIn=",
+ "ConsoleOut=",
+ "SystemPartition=",
+ "OSLoader=",
+ "OSLoadPartition=",
+ "OSLoadFilename=",
+ "OSLoadOptions="
+};
+
+static char *used_arc[][2] = {
+ { "OSLoadPartition=", "root=" },
+ { "OSLoadOptions=", "" }
+};
+
+static char * __init move_firmware_args(char* cp)
+{
+ char *s;
+ int actr, i;
+
+ actr = 1; /* Always ignore argv[0] */
+
+ while (actr < prom_argc) {
+ for(i = 0; i < ARRAY_SIZE(used_arc); i++) {
+ int len = strlen(used_arc[i][0]);
+
+ if (!strncmp(prom_argv(actr), used_arc[i][0], len)) {
+ /* Ok, we want it. First append the replacement... */
+ strcat(cp, used_arc[i][1]);
+ cp += strlen(used_arc[i][1]);
+ /* ... and now the argument */
+ s = strstr(prom_argv(actr), "=");
+ if (s) {
+ s++;
+ strcpy(cp, s);
+ cp += strlen(s);
+ }
+ *cp++ = ' ';
+ break;
+ }
+ }
+ actr++;
+ }
+
+ return cp;
+}
+
+void __init prom_init_cmdline(void)
+{
+ char *cp;
+ int actr, i;
+
+ actr = 1; /* Always ignore argv[0] */
+
+ cp = arcs_cmdline;
+ /*
+ * Move ARC variables to the beginning to make sure they can be
+ * overridden by later arguments.
+ */
+ cp = move_firmware_args(cp);
+
+ while (actr < prom_argc) {
+ for (i = 0; i < ARRAY_SIZE(ignored); i++) {
+ int len = strlen(ignored[i]);
+
+ if (!strncmp(prom_argv(actr), ignored[i], len))
+ goto pic_cont;
+ }
+ /* Ok, we want it. */
+ strcpy(cp, prom_argv(actr));
+ cp += strlen(prom_argv(actr));
+ *cp++ = ' ';
+
+ pic_cont:
+ actr++;
+ }
+
+ if (cp != arcs_cmdline) /* get rid of trailing space */
+ --cp;
+ *cp = '\0';
+
+#ifdef DEBUG_CMDLINE
+ printk(KERN_DEBUG "prom cmdline: %s\n", arcs_cmdline);
+#endif
+}
diff --git a/arch/mips/arc/console.c b/arch/mips/arc/console.c
new file mode 100644
index 0000000..6a9d144
--- /dev/null
+++ b/arch/mips/arc/console.c
@@ -0,0 +1,63 @@
+/*
+ * 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) 1996 David S. Miller (dm@sgi.com)
+ * Compability with board caches, Ulf Carlsson
+ */
+#include <linux/kernel.h>
+#include <asm/sgialib.h>
+#include <asm/bcache.h>
+
+/*
+ * IP22 boardcache is not compatible with board caches. Thus we disable it
+ * during romvec action. Since r4xx0.c is always compiled and linked with your
+ * kernel, this shouldn't cause any harm regardless what MIPS processor you
+ * have.
+ *
+ * The ARC write and read functions seem to interfere with the serial lines
+ * in some way. You should be careful with them.
+ */
+
+void prom_putchar(char c)
+{
+ ULONG cnt;
+ CHAR it = c;
+
+ bc_disable();
+ ArcWrite(1, &it, 1, &cnt);
+ bc_enable();
+}
+
+char prom_getchar(void)
+{
+ ULONG cnt;
+ CHAR c;
+
+ bc_disable();
+ ArcRead(0, &c, 1, &cnt);
+ bc_enable();
+
+ return c;
+}
+
+void prom_printf(char *fmt, ...)
+{
+ va_list args;
+ char ppbuf[1024];
+ char *bptr;
+
+ va_start(args, fmt);
+ vsprintf(ppbuf, fmt, args);
+
+ bptr = ppbuf;
+
+ while (*bptr != 0) {
+ if (*bptr == '\n')
+ prom_putchar('\r');
+
+ prom_putchar(*bptr++);
+ }
+ va_end(args);
+}
diff --git a/arch/mips/arc/env.c b/arch/mips/arc/env.c
new file mode 100644
index 0000000..e521a6e
--- /dev/null
+++ b/arch/mips/arc/env.c
@@ -0,0 +1,27 @@
+/*
+ * 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.
+ *
+ * env.c: ARCS environment variable routines.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+
+#include <asm/arc/types.h>
+#include <asm/sgialib.h>
+
+PCHAR __init
+ArcGetEnvironmentVariable(CHAR *name)
+{
+ return (CHAR *) ARC_CALL1(get_evar, name);
+}
+
+LONG __init
+ArcSetEnvironmentVariable(PCHAR name, PCHAR value)
+{
+ return ARC_CALL2(set_evar, name, value);
+}
diff --git a/arch/mips/arc/file.c b/arch/mips/arc/file.c
new file mode 100644
index 0000000..a43425b
--- /dev/null
+++ b/arch/mips/arc/file.c
@@ -0,0 +1,75 @@
+/*
+ * 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.
+ *
+ * ARC firmware interface.
+ *
+ * Copyright (C) 1994, 1995, 1996, 1999 Ralf Baechle
+ * Copyright (C) 1999 Silicon Graphics, Inc.
+ */
+#include <linux/init.h>
+
+#include <asm/arc/types.h>
+#include <asm/sgialib.h>
+
+LONG __init
+ArcGetDirectoryEntry(ULONG FileID, struct linux_vdirent *Buffer,
+ ULONG N, ULONG *Count)
+{
+ return ARC_CALL4(get_vdirent, FileID, Buffer, N, Count);
+}
+
+LONG __init
+ArcOpen(CHAR *Path, enum linux_omode OpenMode, ULONG *FileID)
+{
+ return ARC_CALL3(open, Path, OpenMode, FileID);
+}
+
+LONG __init
+ArcClose(ULONG FileID)
+{
+ return ARC_CALL1(close, FileID);
+}
+
+LONG __init
+ArcRead(ULONG FileID, VOID *Buffer, ULONG N, ULONG *Count)
+{
+ return ARC_CALL4(read, FileID, Buffer, N, Count);
+}
+
+LONG __init
+ArcGetReadStatus(ULONG FileID)
+{
+ return ARC_CALL1(get_rstatus, FileID);
+}
+
+LONG __init
+ArcWrite(ULONG FileID, PVOID Buffer, ULONG N, PULONG Count)
+{
+ return ARC_CALL4(write, FileID, Buffer, N, Count);
+}
+
+LONG __init
+ArcSeek(ULONG FileID, struct linux_bigint *Position, enum linux_seekmode SeekMode)
+{
+ return ARC_CALL3(seek, FileID, Position, SeekMode);
+}
+
+LONG __init
+ArcMount(char *name, enum linux_mountops op)
+{
+ return ARC_CALL2(mount, name, op);
+}
+
+LONG __init
+ArcGetFileInformation(ULONG FileID, struct linux_finfo *Information)
+{
+ return ARC_CALL2(get_finfo, FileID, Information);
+}
+
+LONG __init ArcSetFileInformation(ULONG FileID, ULONG AttributeFlags,
+ ULONG AttributeMask)
+{
+ return ARC_CALL3(set_finfo, FileID, AttributeFlags, AttributeMask);
+}
diff --git a/arch/mips/arc/identify.c b/arch/mips/arc/identify.c
new file mode 100644
index 0000000..0dd7a34
--- /dev/null
+++ b/arch/mips/arc/identify.c
@@ -0,0 +1,119 @@
+/*
+ * 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.
+ *
+ * identify.c: identify machine by looking up system identifier
+ *
+ * Copyright (C) 1998 Thomas Bogendoerfer
+ *
+ * This code is based on arch/mips/sgi/kernel/system.c, which is
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/string.h>
+
+#include <asm/sgialib.h>
+#include <asm/bootinfo.h>
+
+struct smatch {
+ char *arcname;
+ char *liname;
+ int group;
+ int type;
+ int flags;
+};
+
+static struct smatch mach_table[] = {
+ { "SGI-IP22",
+ "SGI Indy",
+ MACH_GROUP_SGI,
+ MACH_SGI_IP22,
+ PROM_FLAG_ARCS
+ }, { "SGI-IP27",
+ "SGI Origin",
+ MACH_GROUP_SGI,
+ MACH_SGI_IP27,
+ PROM_FLAG_ARCS
+ }, { "SGI-IP28",
+ "SGI IP28",
+ MACH_GROUP_SGI,
+ MACH_SGI_IP28,
+ PROM_FLAG_ARCS
+ }, { "SGI-IP32",
+ "SGI O2",
+ MACH_GROUP_SGI,
+ MACH_SGI_IP32,
+ PROM_FLAG_ARCS
+ }, { "Microsoft-Jazz",
+ "Jazz MIPS_Magnum_4000",
+ MACH_GROUP_JAZZ,
+ MACH_MIPS_MAGNUM_4000,
+ 0
+ }, { "PICA-61",
+ "Jazz Acer_PICA_61",
+ MACH_GROUP_JAZZ,
+ MACH_ACER_PICA_61,
+ 0
+ }, { "RM200PCI",
+ "SNI RM200_PCI",
+ MACH_GROUP_SNI_RM,
+ MACH_SNI_RM200_PCI,
+ PROM_FLAG_DONT_FREE_TEMP
+ }
+};
+
+int prom_flags;
+
+static struct smatch * __init string_to_mach(const char *s)
+{
+ int i;
+
+ for (i = 0; i < (sizeof(mach_table) / sizeof (mach_table[0])); i++) {
+ if (!strcmp(s, mach_table[i].arcname))
+ return &mach_table[i];
+ }
+
+ panic("Yeee, could not determine architecture type <%s>", s);
+}
+
+char *system_type;
+
+const char *get_system_type(void)
+{
+ return system_type;
+}
+
+void __init prom_identify_arch(void)
+{
+ pcomponent *p;
+ struct smatch *mach;
+ const char *iname;
+
+ /*
+ * The root component tells us what machine architecture we have here.
+ */
+ p = ArcGetChild(PROM_NULL_COMPONENT);
+ if (p == NULL) {
+#ifdef CONFIG_SGI_IP27
+ /* IP27 PROM misbehaves, seems to not implement ARC
+ GetChild(). So we just assume it's an IP27. */
+ iname = "SGI-IP27";
+#else
+ iname = "Unknown";
+#endif
+ } else
+ iname = (char *) (long) p->iname;
+
+ printk("ARCH: %s\n", iname);
+ mach = string_to_mach(iname);
+ system_type = mach->liname;
+
+ mips_machgroup = mach->group;
+ mips_machtype = mach->type;
+ prom_flags = mach->flags;
+}
diff --git a/arch/mips/arc/init.c b/arch/mips/arc/init.c
new file mode 100644
index 0000000..76ab505
--- /dev/null
+++ b/arch/mips/arc/init.c
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ *
+ * PROM library initialisation code.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+
+#include <asm/bootinfo.h>
+#include <asm/sgialib.h>
+
+#undef DEBUG_PROM_INIT
+
+/* Master romvec interface. */
+struct linux_romvec *romvec;
+int prom_argc;
+LONG *_prom_argv, *_prom_envp;
+
+void __init prom_init(void)
+{
+ PSYSTEM_PARAMETER_BLOCK pb = PROMBLOCK;
+ romvec = ROMVECTOR;
+ prom_argc = fw_arg0;
+ _prom_argv = (LONG *) fw_arg1;
+ _prom_envp = (LONG *) fw_arg2;
+
+ if (pb->magic != 0x53435241) {
+ prom_printf("Aieee, bad prom vector magic %08lx\n", pb->magic);
+ while(1)
+ ;
+ }
+
+ prom_init_cmdline();
+ prom_identify_arch();
+ printk(KERN_INFO "PROMLIB: ARC firmware Version %d Revision %d\n",
+ pb->ver, pb->rev);
+ prom_meminit();
+
+#ifdef DEBUG_PROM_INIT
+ prom_printf("Press a key to reboot\n");
+ prom_getchar();
+ ArcEnterInteractiveMode();
+#endif
+}
diff --git a/arch/mips/arc/memory.c b/arch/mips/arc/memory.c
new file mode 100644
index 0000000..958d2eb
--- /dev/null
+++ b/arch/mips/arc/memory.c
@@ -0,0 +1,170 @@
+/*
+ * memory.c: PROM library functions for acquiring/using memory descriptors
+ * given to us from the ARCS firmware.
+ *
+ * Copyright (C) 1996 by David S. Miller
+ * Copyright (C) 1999, 2000, 2001 by Ralf Baechle
+ * Copyright (C) 1999, 2000 by Silicon Graphics, Inc.
+ *
+ * PROM library functions for acquiring/using memory descriptors given to us
+ * from the ARCS firmware. This is only used when CONFIG_ARC_MEMORY is set
+ * because on some machines like SGI IP27 the ARC memory configuration data
+ * completly bogus and alternate easier to use mechanisms are available.
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/bootmem.h>
+#include <linux/swap.h>
+
+#include <asm/sgialib.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/bootinfo.h>
+
+#undef DEBUG
+
+/*
+ * For ARC firmware memory functions the unit of meassuring memory is always
+ * a 4k page of memory
+ */
+#define ARC_PAGE_SHIFT 12
+
+struct linux_mdesc * __init ArcGetMemoryDescriptor(struct linux_mdesc *Current)
+{
+ return (struct linux_mdesc *) ARC_CALL1(get_mdesc, Current);
+}
+
+#ifdef DEBUG /* convenient for debugging */
+static char *arcs_mtypes[8] = {
+ "Exception Block",
+ "ARCS Romvec Page",
+ "Free/Contig RAM",
+ "Generic Free RAM",
+ "Bad Memory",
+ "Standalone Program Pages",
+ "ARCS Temp Storage Area",
+ "ARCS Permanent Storage Area"
+};
+
+static char *arc_mtypes[8] = {
+ "Exception Block",
+ "SystemParameterBlock",
+ "FreeMemory",
+ "Bad Memory",
+ "LoadedProgram",
+ "FirmwareTemporary",
+ "FirmwarePermanent",
+ "FreeContiguous"
+};
+#define mtypes(a) (prom_flags & PROM_FLAG_ARCS) ? arcs_mtypes[a.arcs] \
+ : arc_mtypes[a.arc]
+#endif
+
+static inline int memtype_classify_arcs (union linux_memtypes type)
+{
+ switch (type.arcs) {
+ case arcs_fcontig:
+ case arcs_free:
+ return BOOT_MEM_RAM;
+ case arcs_atmp:
+ return BOOT_MEM_ROM_DATA;
+ case arcs_eblock:
+ case arcs_rvpage:
+ case arcs_bmem:
+ case arcs_prog:
+ case arcs_aperm:
+ return BOOT_MEM_RESERVED;
+ default:
+ BUG();
+ }
+ while(1); /* Nuke warning. */
+}
+
+static inline int memtype_classify_arc (union linux_memtypes type)
+{
+ switch (type.arc) {
+ case arc_free:
+ case arc_fcontig:
+ return BOOT_MEM_RAM;
+ case arc_atmp:
+ return BOOT_MEM_ROM_DATA;
+ case arc_eblock:
+ case arc_rvpage:
+ case arc_bmem:
+ case arc_prog:
+ case arc_aperm:
+ return BOOT_MEM_RESERVED;
+ default:
+ BUG();
+ }
+ while(1); /* Nuke warning. */
+}
+
+static int __init prom_memtype_classify (union linux_memtypes type)
+{
+ if (prom_flags & PROM_FLAG_ARCS) /* SGI is ``different'' ... */
+ return memtype_classify_arcs(type);
+
+ return memtype_classify_arc(type);
+}
+
+void __init prom_meminit(void)
+{
+ struct linux_mdesc *p;
+
+#ifdef DEBUG
+ int i = 0;
+
+ prom_printf("ARCS MEMORY DESCRIPTOR dump:\n");
+ p = ArcGetMemoryDescriptor(PROM_NULL_MDESC);
+ while(p) {
+ prom_printf("[%d,%p]: base<%08lx> pages<%08lx> type<%s>\n",
+ i, p, p->base, p->pages, mtypes(p->type));
+ p = ArcGetMemoryDescriptor(p);
+ i++;
+ }
+#endif
+
+ p = PROM_NULL_MDESC;
+ while ((p = ArcGetMemoryDescriptor(p))) {
+ unsigned long base, size;
+ long type;
+
+ base = p->base << ARC_PAGE_SHIFT;
+ size = p->pages << ARC_PAGE_SHIFT;
+ type = prom_memtype_classify(p->type);
+
+ add_memory_region(base, size, type);
+ }
+}
+
+unsigned long __init prom_free_prom_memory(void)
+{
+ unsigned long freed = 0;
+ unsigned long addr;
+ int i;
+
+ if (prom_flags & PROM_FLAG_DONT_FREE_TEMP)
+ return 0;
+
+ for (i = 0; i < boot_mem_map.nr_map; i++) {
+ if (boot_mem_map.map[i].type != BOOT_MEM_ROM_DATA)
+ continue;
+
+ addr = boot_mem_map.map[i].addr;
+ while (addr < boot_mem_map.map[i].addr
+ + boot_mem_map.map[i].size) {
+ ClearPageReserved(virt_to_page(__va(addr)));
+ set_page_count(virt_to_page(__va(addr)), 1);
+ free_page((unsigned long)__va(addr));
+ addr += PAGE_SIZE;
+ freed += PAGE_SIZE;
+ }
+ }
+ printk(KERN_INFO "Freeing prom memory: %ldkb freed\n", freed >> 10);
+
+ return freed;
+}
diff --git a/arch/mips/arc/misc.c b/arch/mips/arc/misc.c
new file mode 100644
index 0000000..84867de
--- /dev/null
+++ b/arch/mips/arc/misc.c
@@ -0,0 +1,108 @@
+/*
+ * 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.
+ *
+ * Miscellaneous ARCS PROM routines.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ * Copyright (C) 1999 Ralf Baechle (ralf@gnu.org)
+ * Copyright (C) 1999 Silicon Graphics, Inc.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+
+#include <asm/bcache.h>
+
+#include <asm/arc/types.h>
+#include <asm/sgialib.h>
+#include <asm/bootinfo.h>
+#include <asm/system.h>
+
+extern void *sgiwd93_host;
+extern void reset_wd33c93(void *instance);
+
+VOID
+ArcHalt(VOID)
+{
+ bc_disable();
+ local_irq_disable();
+#ifdef CONFIG_SCSI_SGIWD93
+ reset_wd33c93(sgiwd93_host);
+#endif
+ ARC_CALL0(halt);
+never: goto never;
+}
+
+VOID
+ArcPowerDown(VOID)
+{
+ bc_disable();
+ local_irq_disable();
+#ifdef CONFIG_SCSI_SGIWD93
+ reset_wd33c93(sgiwd93_host);
+#endif
+ ARC_CALL0(pdown);
+never: goto never;
+}
+
+/* XXX is this a soft reset basically? XXX */
+VOID
+ArcRestart(VOID)
+{
+ bc_disable();
+ local_irq_disable();
+#ifdef CONFIG_SCSI_SGIWD93
+ reset_wd33c93(sgiwd93_host);
+#endif
+ ARC_CALL0(restart);
+never: goto never;
+}
+
+VOID
+ArcReboot(VOID)
+{
+ bc_disable();
+ local_irq_disable();
+#ifdef CONFIG_SCSI_SGIWD93
+ reset_wd33c93(sgiwd93_host);
+#endif
+ ARC_CALL0(reboot);
+never: goto never;
+}
+
+VOID
+ArcEnterInteractiveMode(VOID)
+{
+ bc_disable();
+ local_irq_disable();
+#ifdef CONFIG_SCSI_SGIWD93
+ reset_wd33c93(sgiwd93_host);
+#endif
+ ARC_CALL0(imode);
+never: goto never;
+}
+
+LONG
+ArcSaveConfiguration(VOID)
+{
+ return ARC_CALL0(cfg_save);
+}
+
+struct linux_sysid *
+ArcGetSystemId(VOID)
+{
+ return (struct linux_sysid *) ARC_CALL0(get_sysid);
+}
+
+VOID __init
+ArcFlushAllCaches(VOID)
+{
+ ARC_CALL0(cache_flush);
+}
+
+DISPLAY_STATUS * __init ArcGetDisplayStatus(ULONG FileID)
+{
+ return (DISPLAY_STATUS *) ARC_CALL1(GetDisplayStatus, FileID);
+}
diff --git a/arch/mips/arc/promlib.c b/arch/mips/arc/promlib.c
new file mode 100644
index 0000000..c508c00
--- /dev/null
+++ b/arch/mips/arc/promlib.c
@@ -0,0 +1,43 @@
+/*
+ * 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) 1996 David S. Miller (dm@sgi.com)
+ * Compability with board caches, Ulf Carlsson
+ */
+#include <linux/kernel.h>
+#include <asm/sgialib.h>
+#include <asm/bcache.h>
+
+/*
+ * IP22 boardcache is not compatible with board caches. Thus we disable it
+ * during romvec action. Since r4xx0.c is always compiled and linked with your
+ * kernel, this shouldn't cause any harm regardless what MIPS processor you
+ * have.
+ *
+ * The ARC write and read functions seem to interfere with the serial lines
+ * in some way. You should be careful with them.
+ */
+
+void prom_putchar(char c)
+{
+ ULONG cnt;
+ CHAR it = c;
+
+ bc_disable();
+ ArcWrite(1, &it, 1, &cnt);
+ bc_enable();
+}
+
+char prom_getchar(void)
+{
+ ULONG cnt;
+ CHAR c;
+
+ bc_disable();
+ ArcRead(0, &c, 1, &cnt);
+ bc_enable();
+
+ return c;
+}
diff --git a/arch/mips/arc/salone.c b/arch/mips/arc/salone.c
new file mode 100644
index 0000000..e6afb64
--- /dev/null
+++ b/arch/mips/arc/salone.c
@@ -0,0 +1,24 @@
+/*
+ * Routines to load into memory and execute stand-along program images using
+ * ARCS PROM firmware.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+#include <linux/init.h>
+#include <asm/sgialib.h>
+
+LONG __init ArcLoad(CHAR *Path, ULONG TopAddr, ULONG *ExecAddr, ULONG *LowAddr)
+{
+ return ARC_CALL4(load, Path, TopAddr, ExecAddr, LowAddr);
+}
+
+LONG __init ArcInvoke(ULONG ExecAddr, ULONG StackAddr, ULONG Argc, CHAR *Argv[],
+ CHAR *Envp[])
+{
+ return ARC_CALL5(invoke, ExecAddr, StackAddr, Argc, Argv, Envp);
+}
+
+LONG __init ArcExecute(CHAR *Path, LONG Argc, CHAR *Argv[], CHAR *Envp[])
+{
+ return ARC_CALL4(exec, Path, Argc, Argv, Envp);
+}
diff --git a/arch/mips/arc/time.c b/arch/mips/arc/time.c
new file mode 100644
index 0000000..299ff2c
--- /dev/null
+++ b/arch/mips/arc/time.c
@@ -0,0 +1,25 @@
+/*
+ * 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.
+ *
+ * Extracting time information from ARCS prom.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+#include <linux/init.h>
+
+#include <asm/arc/types.h>
+#include <asm/sgialib.h>
+
+struct linux_tinfo * __init
+ArcGetTime(VOID)
+{
+ return (struct linux_tinfo *) ARC_CALL0(get_tinfo);
+}
+
+ULONG __init
+ArcGetRelativeTime(VOID)
+{
+ return ARC_CALL0(get_rtime);
+}
diff --git a/arch/mips/arc/tree.c b/arch/mips/arc/tree.c
new file mode 100644
index 0000000..2aedd4f
--- /dev/null
+++ b/arch/mips/arc/tree.c
@@ -0,0 +1,127 @@
+/*
+ * 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.
+ *
+ * PROM component device tree code.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ * Copyright (C) 1999 Ralf Baechle (ralf@gnu.org)
+ * Copyright (C) 1999 Silicon Graphics, Inc.
+ */
+#include <linux/init.h>
+#include <asm/arc/types.h>
+#include <asm/sgialib.h>
+
+#undef DEBUG_PROM_TREE
+
+pcomponent * __init
+ArcGetPeer(pcomponent *Current)
+{
+ if (Current == PROM_NULL_COMPONENT)
+ return PROM_NULL_COMPONENT;
+
+ return (pcomponent *) ARC_CALL1(next_component, Current);
+}
+
+pcomponent * __init
+ArcGetChild(pcomponent *Current)
+{
+ return (pcomponent *) ARC_CALL1(child_component, Current);
+}
+
+pcomponent * __init
+ArcGetParent(pcomponent *Current)
+{
+ if (Current == PROM_NULL_COMPONENT)
+ return PROM_NULL_COMPONENT;
+
+ return (pcomponent *) ARC_CALL1(parent_component, Current);
+}
+
+LONG __init
+ArcGetConfigurationData(VOID *Buffer, pcomponent *Current)
+{
+ return ARC_CALL2(component_data, Buffer, Current);
+}
+
+pcomponent * __init
+ArcAddChild(pcomponent *Current, pcomponent *Template, VOID *ConfigurationData)
+{
+ return (pcomponent *)
+ ARC_CALL3(child_add, Current, Template, ConfigurationData);
+}
+
+LONG __init
+ArcDeleteComponent(pcomponent *ComponentToDelete)
+{
+ return ARC_CALL1(comp_del, ComponentToDelete);
+}
+
+pcomponent * __init
+ArcGetComponent(CHAR *Path)
+{
+ return (pcomponent *)ARC_CALL1(component_by_path, Path);
+}
+
+#ifdef DEBUG_PROM_TREE
+
+static char *classes[] = {
+ "system", "processor", "cache", "adapter", "controller", "peripheral",
+ "memory"
+};
+
+static char *types[] = {
+ "arc", "cpu", "fpu", "picache", "pdcache", "sicache", "sdcache",
+ "sccache", "memdev", "eisa adapter", "tc adapter", "scsi adapter",
+ "dti adapter", "multi-func adapter", "disk controller",
+ "tp controller", "cdrom controller", "worm controller",
+ "serial controller", "net controller", "display controller",
+ "parallel controller", "pointer controller", "keyboard controller",
+ "audio controller", "misc controller", "disk peripheral",
+ "floppy peripheral", "tp peripheral", "modem peripheral",
+ "monitor peripheral", "printer peripheral", "pointer peripheral",
+ "keyboard peripheral", "terminal peripheral", "line peripheral",
+ "net peripheral", "misc peripheral", "anonymous"
+};
+
+static char *iflags[] = {
+ "bogus", "read only", "removable", "console in", "console out",
+ "input", "output"
+};
+
+static void __init
+dump_component(pcomponent *p)
+{
+ prom_printf("[%p]:class<%s>type<%s>flags<%s>ver<%d>rev<%d>",
+ p, classes[p->class], types[p->type],
+ iflags[p->iflags], p->vers, p->rev);
+ prom_printf("key<%08lx>\n\tamask<%08lx>cdsize<%d>ilen<%d>iname<%s>\n",
+ p->key, p->amask, (int)p->cdsize, (int)p->ilen, p->iname);
+}
+
+static void __init
+traverse(pcomponent *p, int op)
+{
+ dump_component(p);
+ if(ArcGetChild(p))
+ traverse(ArcGetChild(p), 1);
+ if(ArcGetPeer(p) && op)
+ traverse(ArcGetPeer(p), 1);
+}
+
+void __init
+prom_testtree(void)
+{
+ pcomponent *p;
+
+ p = ArcGetChild(PROM_NULL_COMPONENT);
+ dump_component(p);
+ p = ArcGetChild(p);
+ while(p) {
+ dump_component(p);
+ p = ArcGetPeer(p);
+ }
+}
+
+#endif /* DEBUG_PROM_TREE */
diff --git a/arch/mips/au1000/common/Makefile b/arch/mips/au1000/common/Makefile
new file mode 100644
index 0000000..594b75e
--- /dev/null
+++ b/arch/mips/au1000/common/Makefile
@@ -0,0 +1,15 @@
+#
+# Copyright 2000 MontaVista Software Inc.
+# Author: MontaVista Software, Inc.
+# ppopov@mvista.com or source@mvista.com
+#
+# Makefile for the Alchemy Au1000 CPU, generic files.
+#
+
+obj-y += prom.o int-handler.o irq.o puts.o time.o reset.o \
+ au1xxx_irqmap.o clocks.o platform.o power.o setup.o \
+ sleeper.o cputable.o dma.o dbdma.o
+
+obj-$(CONFIG_AU1X00_USB_DEVICE) += usbdev.o
+obj-$(CONFIG_KGDB) += dbg_io.o
+obj-$(CONFIG_PCI) += pci.o
diff --git a/arch/mips/au1000/common/au1xxx_irqmap.c b/arch/mips/au1000/common/au1xxx_irqmap.c
new file mode 100644
index 0000000..8a0f39f
--- /dev/null
+++ b/arch/mips/au1000/common/au1xxx_irqmap.c
@@ -0,0 +1,224 @@
+/*
+ * BRIEF MODULE DESCRIPTION
+ * Au1xxx processor specific IRQ tables
+ *
+ * Copyright 2004 Embedded Edge, LLC
+ * dan@embeddededge.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/kernel_stat.h>
+#include <linux/module.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/timex.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+#include <linux/delay.h>
+#include <linux/bitops.h>
+
+#include <asm/bootinfo.h>
+#include <asm/io.h>
+#include <asm/mipsregs.h>
+#include <asm/system.h>
+#include <asm/mach-au1x00/au1000.h>
+
+/* The IC0 interrupt table. This is processor, rather than
+ * board dependent, so no reason to keep this info in the board
+ * dependent files.
+ *
+ * Careful if you change match 2 request!
+ * The interrupt handler is called directly from the low level dispatch code.
+ */
+au1xxx_irq_map_t au1xxx_ic0_map[] = {
+
+#if defined(CONFIG_SOC_AU1000)
+ { AU1000_UART0_INT, INTC_INT_HIGH_LEVEL, 0},
+ { AU1000_UART1_INT, INTC_INT_HIGH_LEVEL, 0},
+ { AU1000_UART2_INT, INTC_INT_HIGH_LEVEL, 0},
+ { AU1000_UART3_INT, INTC_INT_HIGH_LEVEL, 0},
+ { AU1000_SSI0_INT, INTC_INT_HIGH_LEVEL, 0},
+ { AU1000_SSI1_INT, INTC_INT_HIGH_LEVEL, 0},
+ { AU1000_DMA_INT_BASE, INTC_INT_HIGH_LEVEL, 0},
+ { AU1000_DMA_INT_BASE+1, INTC_INT_HIGH_LEVEL, 0},
+ { AU1000_DMA_INT_BASE+2, INTC_INT_HIGH_LEVEL, 0},
+ { AU1000_DMA_INT_BASE+3, INTC_INT_HIGH_LEVEL, 0},
+ { AU1000_DMA_INT_BASE+4, INTC_INT_HIGH_LEVEL, 0},
+ { AU1000_DMA_INT_BASE+5, INTC_INT_HIGH_LEVEL, 0},
+ { AU1000_DMA_INT_BASE+6, INTC_INT_HIGH_LEVEL, 0},
+ { AU1000_DMA_INT_BASE+7, INTC_INT_HIGH_LEVEL, 0},
+ { AU1000_TOY_INT, INTC_INT_RISE_EDGE, 0 },
+ { AU1000_TOY_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
+ { AU1000_TOY_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
+ { AU1000_TOY_MATCH2_INT, INTC_INT_RISE_EDGE, 1 },
+ { AU1000_RTC_INT, INTC_INT_RISE_EDGE, 0 },
+ { AU1000_RTC_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
+ { AU1000_RTC_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
+ { AU1000_RTC_MATCH2_INT, INTC_INT_RISE_EDGE, 0 },
+ { AU1000_IRDA_TX_INT, INTC_INT_HIGH_LEVEL, 0},
+ { AU1000_IRDA_RX_INT, INTC_INT_HIGH_LEVEL, 0},
+ { AU1000_USB_DEV_REQ_INT, INTC_INT_HIGH_LEVEL, 0 },
+ { AU1000_USB_DEV_SUS_INT, INTC_INT_RISE_EDGE, 0 },
+ { AU1000_USB_HOST_INT, INTC_INT_LOW_LEVEL, 0 },
+ { AU1000_ACSYNC_INT, INTC_INT_RISE_EDGE, 0 },
+ { AU1000_MAC0_DMA_INT, INTC_INT_HIGH_LEVEL, 0},
+ { AU1000_MAC1_DMA_INT, INTC_INT_HIGH_LEVEL, 0},
+ { AU1000_AC97C_INT, INTC_INT_RISE_EDGE, 0 },
+
+#elif defined(CONFIG_SOC_AU1500)
+
+ { AU1500_UART0_INT, INTC_INT_HIGH_LEVEL, 0},
+ { AU1000_PCI_INTA, INTC_INT_LOW_LEVEL, 0 },
+ { AU1000_PCI_INTB, INTC_INT_LOW_LEVEL, 0 },
+ { AU1500_UART3_INT, INTC_INT_HIGH_LEVEL, 0},
+ { AU1000_PCI_INTC, INTC_INT_LOW_LEVEL, 0 },
+ { AU1000_PCI_INTD, INTC_INT_LOW_LEVEL, 0 },
+ { AU1000_DMA_INT_BASE, INTC_INT_HIGH_LEVEL, 0},
+ { AU1000_DMA_INT_BASE+1, INTC_INT_HIGH_LEVEL, 0},
+ { AU1000_DMA_INT_BASE+2, INTC_INT_HIGH_LEVEL, 0},
+ { AU1000_DMA_INT_BASE+3, INTC_INT_HIGH_LEVEL, 0},
+ { AU1000_DMA_INT_BASE+4, INTC_INT_HIGH_LEVEL, 0},
+ { AU1000_DMA_INT_BASE+5, INTC_INT_HIGH_LEVEL, 0},
+ { AU1000_DMA_INT_BASE+6, INTC_INT_HIGH_LEVEL, 0},
+ { AU1000_DMA_INT_BASE+7, INTC_INT_HIGH_LEVEL, 0},
+ { AU1000_TOY_INT, INTC_INT_RISE_EDGE, 0 },
+ { AU1000_TOY_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
+ { AU1000_TOY_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
+ { AU1000_TOY_MATCH2_INT, INTC_INT_RISE_EDGE, 1 },
+ { AU1000_RTC_INT, INTC_INT_RISE_EDGE, 0 },
+ { AU1000_RTC_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
+ { AU1000_RTC_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
+ { AU1000_RTC_MATCH2_INT, INTC_INT_RISE_EDGE, 0 },
+ { AU1000_USB_DEV_REQ_INT, INTC_INT_HIGH_LEVEL, 0 },
+ { AU1000_USB_DEV_SUS_INT, INTC_INT_RISE_EDGE, 0 },
+ { AU1000_USB_HOST_INT, INTC_INT_LOW_LEVEL, 0 },
+ { AU1000_ACSYNC_INT, INTC_INT_RISE_EDGE, 0 },
+ { AU1500_MAC0_DMA_INT, INTC_INT_HIGH_LEVEL, 0},
+ { AU1500_MAC1_DMA_INT, INTC_INT_HIGH_LEVEL, 0},
+ { AU1000_AC97C_INT, INTC_INT_RISE_EDGE, 0 },
+
+#elif defined(CONFIG_SOC_AU1100)
+
+ { AU1100_UART0_INT, INTC_INT_HIGH_LEVEL, 0},
+ { AU1100_UART1_INT, INTC_INT_HIGH_LEVEL, 0},
+ { AU1100_SD_INT, INTC_INT_HIGH_LEVEL, 0},
+ { AU1100_UART3_INT, INTC_INT_HIGH_LEVEL, 0},
+ { AU1000_SSI0_INT, INTC_INT_HIGH_LEVEL, 0},
+ { AU1000_SSI1_INT, INTC_INT_HIGH_LEVEL, 0},
+ { AU1000_DMA_INT_BASE, INTC_INT_HIGH_LEVEL, 0},
+ { AU1000_DMA_INT_BASE+1, INTC_INT_HIGH_LEVEL, 0},
+ { AU1000_DMA_INT_BASE+2, INTC_INT_HIGH_LEVEL, 0},
+ { AU1000_DMA_INT_BASE+3, INTC_INT_HIGH_LEVEL, 0},
+ { AU1000_DMA_INT_BASE+4, INTC_INT_HIGH_LEVEL, 0},
+ { AU1000_DMA_INT_BASE+5, INTC_INT_HIGH_LEVEL, 0},
+ { AU1000_DMA_INT_BASE+6, INTC_INT_HIGH_LEVEL, 0},
+ { AU1000_DMA_INT_BASE+7, INTC_INT_HIGH_LEVEL, 0},
+ { AU1000_TOY_INT, INTC_INT_RISE_EDGE, 0 },
+ { AU1000_TOY_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
+ { AU1000_TOY_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
+ { AU1000_TOY_MATCH2_INT, INTC_INT_RISE_EDGE, 1 },
+ { AU1000_RTC_INT, INTC_INT_RISE_EDGE, 0 },
+ { AU1000_RTC_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
+ { AU1000_RTC_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
+ { AU1000_RTC_MATCH2_INT, INTC_INT_RISE_EDGE, 0 },
+ { AU1000_IRDA_TX_INT, INTC_INT_HIGH_LEVEL, 0},
+ { AU1000_IRDA_RX_INT, INTC_INT_HIGH_LEVEL, 0},
+ { AU1000_USB_DEV_REQ_INT, INTC_INT_HIGH_LEVEL, 0 },
+ { AU1000_USB_DEV_SUS_INT, INTC_INT_RISE_EDGE, 0 },
+ { AU1000_USB_HOST_INT, INTC_INT_LOW_LEVEL, 0 },
+ { AU1000_ACSYNC_INT, INTC_INT_RISE_EDGE, 0 },
+ { AU1100_MAC0_DMA_INT, INTC_INT_HIGH_LEVEL, 0},
+ /*{ AU1000_GPIO215_208_INT, INTC_INT_HIGH_LEVEL, 0},*/
+ { AU1100_LCD_INT, INTC_INT_HIGH_LEVEL, 0},
+ { AU1000_AC97C_INT, INTC_INT_RISE_EDGE, 0 },
+
+#elif defined(CONFIG_SOC_AU1550)
+
+ { AU1550_UART0_INT, INTC_INT_HIGH_LEVEL, 0},
+ { AU1550_PCI_INTA, INTC_INT_LOW_LEVEL, 0 },
+ { AU1550_PCI_INTB, INTC_INT_LOW_LEVEL, 0 },
+ { AU1550_DDMA_INT, INTC_INT_HIGH_LEVEL, 0},
+ { AU1550_CRYPTO_INT, INTC_INT_HIGH_LEVEL, 0},
+ { AU1550_PCI_INTC, INTC_INT_LOW_LEVEL, 0 },
+ { AU1550_PCI_INTD, INTC_INT_LOW_LEVEL, 0 },
+ { AU1550_PCI_RST_INT, INTC_INT_LOW_LEVEL, 0 },
+ { AU1550_UART1_INT, INTC_INT_HIGH_LEVEL, 0},
+ { AU1550_UART3_INT, INTC_INT_HIGH_LEVEL, 0},
+ { AU1550_PSC0_INT, INTC_INT_HIGH_LEVEL, 0},
+ { AU1550_PSC1_INT, INTC_INT_HIGH_LEVEL, 0},
+ { AU1550_PSC2_INT, INTC_INT_HIGH_LEVEL, 0},
+ { AU1550_PSC3_INT, INTC_INT_HIGH_LEVEL, 0},
+ { AU1550_TOY_INT, INTC_INT_RISE_EDGE, 0 },
+ { AU1550_TOY_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
+ { AU1550_TOY_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
+ { AU1550_TOY_MATCH2_INT, INTC_INT_RISE_EDGE, 1 },
+ { AU1550_RTC_INT, INTC_INT_RISE_EDGE, 0 },
+ { AU1550_RTC_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
+ { AU1550_RTC_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
+ { AU1550_RTC_MATCH2_INT, INTC_INT_RISE_EDGE, 0 },
+ { AU1550_NAND_INT, INTC_INT_RISE_EDGE, 0},
+ { AU1550_USB_DEV_REQ_INT, INTC_INT_HIGH_LEVEL, 0 },
+ { AU1550_USB_DEV_SUS_INT, INTC_INT_RISE_EDGE, 0 },
+ { AU1550_USB_HOST_INT, INTC_INT_LOW_LEVEL, 0 },
+ { AU1550_MAC0_DMA_INT, INTC_INT_HIGH_LEVEL, 0},
+ { AU1550_MAC1_DMA_INT, INTC_INT_HIGH_LEVEL, 0},
+
+#elif defined(CONFIG_SOC_AU1200)
+
+ { AU1200_UART0_INT, INTC_INT_HIGH_LEVEL, 0},
+ { AU1200_SWT_INT, INTC_INT_RISE_EDGE, 0 },
+ { AU1200_SD_INT, INTC_INT_HIGH_LEVEL, 0},
+ { AU1200_DDMA_INT, INTC_INT_HIGH_LEVEL, 0},
+ { AU1200_MAE_BE_INT, INTC_INT_HIGH_LEVEL, 0 },
+ { AU1200_UART1_INT, INTC_INT_HIGH_LEVEL, 0},
+ { AU1200_MAE_FE_INT, INTC_INT_HIGH_LEVEL, 0 },
+ { AU1200_PSC0_INT, INTC_INT_HIGH_LEVEL, 0},
+ { AU1200_PSC1_INT, INTC_INT_HIGH_LEVEL, 0},
+ { AU1200_AES_INT, INTC_INT_HIGH_LEVEL, 0},
+ { AU1200_CAMERA_INT, INTC_INT_HIGH_LEVEL, 0},
+ { AU1200_TOY_INT, INTC_INT_RISE_EDGE, 0 },
+ { AU1200_TOY_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
+ { AU1200_TOY_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
+ { AU1200_TOY_MATCH2_INT, INTC_INT_RISE_EDGE, 1 },
+ { AU1200_RTC_INT, INTC_INT_RISE_EDGE, 0 },
+ { AU1200_RTC_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
+ { AU1200_RTC_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
+ { AU1200_RTC_MATCH2_INT, INTC_INT_RISE_EDGE, 0 },
+ { AU1200_NAND_INT, INTC_INT_RISE_EDGE, 0},
+ { AU1200_USB_INT, INTC_INT_HIGH_LEVEL, 0 },
+ { AU1200_LCD_INT, INTC_INT_HIGH_LEVEL, 0},
+ { AU1200_MAE_BOTH_INT, INTC_INT_HIGH_LEVEL, 0},
+
+#else
+#error "Error: Unknown Alchemy SOC"
+#endif
+
+};
+
+int au1xxx_ic0_nr_irqs = sizeof(au1xxx_ic0_map)/sizeof(au1xxx_irq_map_t);
+
diff --git a/arch/mips/au1000/common/clocks.c b/arch/mips/au1000/common/clocks.c
new file mode 100644
index 0000000..3ce6cac
--- /dev/null
+++ b/arch/mips/au1000/common/clocks.c
@@ -0,0 +1,96 @@
+/*
+ * BRIEF MODULE DESCRIPTION
+ * Simple Au1000 clocks routines.
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ * ppopov@mvista.com or source@mvista.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <asm/mach-au1x00/au1000.h>
+
+static unsigned int au1x00_clock; // Hz
+static unsigned int lcd_clock; // KHz
+static unsigned long uart_baud_base;
+
+/*
+ * Set the au1000_clock
+ */
+void set_au1x00_speed(unsigned int new_freq)
+{
+ au1x00_clock = new_freq;
+}
+
+unsigned int get_au1x00_speed(void)
+{
+ return au1x00_clock;
+}
+
+
+
+/*
+ * The UART baud base is not known at compile time ... if
+ * we want to be able to use the same code on different
+ * speed CPUs.
+ */
+unsigned long get_au1x00_uart_baud_base(void)
+{
+ return uart_baud_base;
+}
+
+void set_au1x00_uart_baud_base(unsigned long new_baud_base)
+{
+ uart_baud_base = new_baud_base;
+}
+
+/*
+ * Calculate the Au1x00's LCD clock based on the current
+ * cpu clock and the system bus clock, and try to keep it
+ * below 40 MHz (the Pb1000 board can lock-up if the LCD
+ * clock is over 40 MHz).
+ */
+void set_au1x00_lcd_clock(void)
+{
+ unsigned int static_cfg0;
+ unsigned int sys_busclk =
+ (get_au1x00_speed()/1000) /
+ ((int)(au_readl(SYS_POWERCTRL)&0x03) + 2);
+
+ static_cfg0 = au_readl(MEM_STCFG0);
+
+ if (static_cfg0 & (1<<11))
+ lcd_clock = sys_busclk / 5; /* note: BCLK switching fails with D5 */
+ else
+ lcd_clock = sys_busclk / 4;
+
+ if (lcd_clock > 50000) /* Epson MAX */
+ printk("warning: LCD clock too high (%d KHz)\n", lcd_clock);
+}
+
+unsigned int get_au1x00_lcd_clock(void)
+{
+ return lcd_clock;
+}
+
+EXPORT_SYMBOL(get_au1x00_lcd_clock);
diff --git a/arch/mips/au1000/common/cputable.c b/arch/mips/au1000/common/cputable.c
new file mode 100644
index 0000000..f5521df
--- /dev/null
+++ b/arch/mips/au1000/common/cputable.c
@@ -0,0 +1,55 @@
+/*
+ * arch/mips/au1000/common/cputable.c
+ *
+ * Copyright (C) 2004 Dan Malek (dan@embeddededge.com)
+ * Copied from PowerPC and updated for Alchemy Au1xxx processors.
+ *
+ * Copyright (C) 2001 Ben. Herrenschmidt (benh@kernel.crashing.org)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#include <linux/string.h>
+#include <linux/sched.h>
+#include <linux/threads.h>
+#include <linux/init.h>
+#include <asm/mach-au1x00/au1000.h>
+
+struct cpu_spec* cur_cpu_spec[NR_CPUS];
+
+/* With some thought, we can probably use the mask to reduce the
+ * size of the table.
+ */
+struct cpu_spec cpu_specs[] = {
+ { 0xffffffff, 0x00030100, "Au1000 DA", 1, 0 },
+ { 0xffffffff, 0x00030201, "Au1000 HA", 1, 0 },
+ { 0xffffffff, 0x00030202, "Au1000 HB", 1, 0 },
+ { 0xffffffff, 0x00030203, "Au1000 HC", 1, 1 },
+ { 0xffffffff, 0x00030204, "Au1000 HD", 1, 1 },
+ { 0xffffffff, 0x01030200, "Au1500 AB", 1, 1 },
+ { 0xffffffff, 0x01030201, "Au1500 AC", 0, 1 },
+ { 0xffffffff, 0x01030202, "Au1500 AD", 0, 1 },
+ { 0xffffffff, 0x02030200, "Au1100 AB", 1, 1 },
+ { 0xffffffff, 0x02030201, "Au1100 BA", 1, 1 },
+ { 0xffffffff, 0x02030202, "Au1100 BC", 1, 1 },
+ { 0xffffffff, 0x02030203, "Au1100 BD", 0, 1 },
+ { 0xffffffff, 0x02030204, "Au1100 BE", 0, 1 },
+ { 0xffffffff, 0x03030200, "Au1550 AA", 0, 1 },
+ { 0xffffffff, 0x04030200, "Au1200 AA", 0, 1 },
+ { 0x00000000, 0x00000000, "Unknown Au1xxx", 1, 0 },
+};
+
+void
+set_cpuspec(void)
+{
+ struct cpu_spec *sp;
+ u32 prid;
+
+ prid = read_c0_prid();
+ sp = cpu_specs;
+ while ((prid & sp->prid_mask) != sp->prid_value)
+ sp++;
+ cur_cpu_spec[0] = sp;
+}
diff --git a/arch/mips/au1000/common/dbdma.c b/arch/mips/au1000/common/dbdma.c
new file mode 100644
index 0000000..adfc317
--- /dev/null
+++ b/arch/mips/au1000/common/dbdma.c
@@ -0,0 +1,836 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ * The Descriptor Based DMA channel manager that first appeared
+ * on the Au1550. I started with dma.c, but I think all that is
+ * left is this initial comment :-)
+ *
+ * Copyright 2004 Embedded Edge, LLC
+ * dan@embeddededge.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <asm/mach-au1x00/au1000.h>
+#include <asm/mach-au1x00/au1xxx_dbdma.h>
+#include <asm/system.h>
+
+#if defined(CONFIG_SOC_AU1550) || defined(CONFIG_SOC_AU1200)
+
+/*
+ * The Descriptor Based DMA supports up to 16 channels.
+ *
+ * There are 32 devices defined. We keep an internal structure
+ * of devices using these channels, along with additional
+ * information.
+ *
+ * We allocate the descriptors and allow access to them through various
+ * functions. The drivers allocate the data buffers and assign them
+ * to the descriptors.
+ */
+static DEFINE_SPINLOCK(au1xxx_dbdma_spin_lock);
+
+/* I couldn't find a macro that did this......
+*/
+#define ALIGN_ADDR(x, a) ((((u32)(x)) + (a-1)) & ~(a-1))
+
+static volatile dbdma_global_t *dbdma_gptr = (dbdma_global_t *)DDMA_GLOBAL_BASE;
+static int dbdma_initialized;
+static void au1xxx_dbdma_init(void);
+
+typedef struct dbdma_device_table {
+ u32 dev_id;
+ u32 dev_flags;
+ u32 dev_tsize;
+ u32 dev_devwidth;
+ u32 dev_physaddr; /* If FIFO */
+ u32 dev_intlevel;
+ u32 dev_intpolarity;
+} dbdev_tab_t;
+
+typedef struct dbdma_chan_config {
+ u32 chan_flags;
+ u32 chan_index;
+ dbdev_tab_t *chan_src;
+ dbdev_tab_t *chan_dest;
+ au1x_dma_chan_t *chan_ptr;
+ au1x_ddma_desc_t *chan_desc_base;
+ au1x_ddma_desc_t *get_ptr, *put_ptr, *cur_ptr;
+ void *chan_callparam;
+ void (*chan_callback)(int, void *, struct pt_regs *);
+} chan_tab_t;
+
+#define DEV_FLAGS_INUSE (1 << 0)
+#define DEV_FLAGS_ANYUSE (1 << 1)
+#define DEV_FLAGS_OUT (1 << 2)
+#define DEV_FLAGS_IN (1 << 3)
+
+static dbdev_tab_t dbdev_tab[] = {
+#ifdef CONFIG_SOC_AU1550
+ /* UARTS */
+ { DSCR_CMD0_UART0_TX, DEV_FLAGS_OUT, 0, 8, 0x11100004, 0, 0 },
+ { DSCR_CMD0_UART0_RX, DEV_FLAGS_IN, 0, 8, 0x11100000, 0, 0 },
+ { DSCR_CMD0_UART3_TX, DEV_FLAGS_OUT, 0, 8, 0x11400004, 0, 0 },
+ { DSCR_CMD0_UART3_RX, DEV_FLAGS_IN, 0, 8, 0x11400000, 0, 0 },
+
+ /* EXT DMA */
+ { DSCR_CMD0_DMA_REQ0, 0, 0, 0, 0x00000000, 0, 0 },
+ { DSCR_CMD0_DMA_REQ1, 0, 0, 0, 0x00000000, 0, 0 },
+ { DSCR_CMD0_DMA_REQ2, 0, 0, 0, 0x00000000, 0, 0 },
+ { DSCR_CMD0_DMA_REQ3, 0, 0, 0, 0x00000000, 0, 0 },
+
+ /* USB DEV */
+ { DSCR_CMD0_USBDEV_RX0, DEV_FLAGS_IN, 4, 8, 0x10200000, 0, 0 },
+ { DSCR_CMD0_USBDEV_TX0, DEV_FLAGS_OUT, 4, 8, 0x10200004, 0, 0 },
+ { DSCR_CMD0_USBDEV_TX1, DEV_FLAGS_OUT, 4, 8, 0x10200008, 0, 0 },
+ { DSCR_CMD0_USBDEV_TX2, DEV_FLAGS_OUT, 4, 8, 0x1020000c, 0, 0 },
+ { DSCR_CMD0_USBDEV_RX3, DEV_FLAGS_IN, 4, 8, 0x10200010, 0, 0 },
+ { DSCR_CMD0_USBDEV_RX4, DEV_FLAGS_IN, 4, 8, 0x10200014, 0, 0 },
+
+ /* PSC 0 */
+ { DSCR_CMD0_PSC0_TX, DEV_FLAGS_OUT, 0, 0, 0x11a0001c, 0, 0 },
+ { DSCR_CMD0_PSC0_RX, DEV_FLAGS_IN, 0, 0, 0x11a0001c, 0, 0 },
+
+ /* PSC 1 */
+ { DSCR_CMD0_PSC1_TX, DEV_FLAGS_OUT, 0, 0, 0x11b0001c, 0, 0 },
+ { DSCR_CMD0_PSC1_RX, DEV_FLAGS_IN, 0, 0, 0x11b0001c, 0, 0 },
+
+ /* PSC 2 */
+ { DSCR_CMD0_PSC2_TX, DEV_FLAGS_OUT, 0, 0, 0x10a0001c, 0, 0 },
+ { DSCR_CMD0_PSC2_RX, DEV_FLAGS_IN, 0, 0, 0x10a0001c, 0, 0 },
+
+ /* PSC 3 */
+ { DSCR_CMD0_PSC3_TX, DEV_FLAGS_OUT, 0, 0, 0x10b0001c, 0, 0 },
+ { DSCR_CMD0_PSC3_RX, DEV_FLAGS_IN, 0, 0, 0x10b0001c, 0, 0 },
+
+ { DSCR_CMD0_PCI_WRITE, 0, 0, 0, 0x00000000, 0, 0 }, /* PCI */
+ { DSCR_CMD0_NAND_FLASH, 0, 0, 0, 0x00000000, 0, 0 }, /* NAND */
+
+ /* MAC 0 */
+ { DSCR_CMD0_MAC0_RX, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 },
+ { DSCR_CMD0_MAC0_TX, DEV_FLAGS_OUT, 0, 0, 0x00000000, 0, 0 },
+
+ /* MAC 1 */
+ { DSCR_CMD0_MAC1_RX, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 },
+ { DSCR_CMD0_MAC1_TX, DEV_FLAGS_OUT, 0, 0, 0x00000000, 0, 0 },
+
+#endif /* CONFIG_SOC_AU1550 */
+
+#ifdef CONFIG_SOC_AU1200
+ { DSCR_CMD0_UART0_TX, DEV_FLAGS_OUT, 0, 8, 0x11100004, 0, 0 },
+ { DSCR_CMD0_UART0_RX, DEV_FLAGS_IN, 0, 8, 0x11100000, 0, 0 },
+ { DSCR_CMD0_UART1_TX, DEV_FLAGS_OUT, 0, 8, 0x11200004, 0, 0 },
+ { DSCR_CMD0_UART1_RX, DEV_FLAGS_IN, 0, 8, 0x11200000, 0, 0 },
+
+ { DSCR_CMD0_DMA_REQ0, 0, 0, 0, 0x00000000, 0, 0 },
+ { DSCR_CMD0_DMA_REQ1, 0, 0, 0, 0x00000000, 0, 0 },
+
+ { DSCR_CMD0_MAE_BE, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
+ { DSCR_CMD0_MAE_FE, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
+ { DSCR_CMD0_MAE_BOTH, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
+ { DSCR_CMD0_LCD, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
+
+ { DSCR_CMD0_SDMS_TX0, DEV_FLAGS_OUT, 0, 0, 0x00000000, 0, 0 },
+ { DSCR_CMD0_SDMS_RX0, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 },
+ { DSCR_CMD0_SDMS_TX1, DEV_FLAGS_OUT, 0, 0, 0x00000000, 0, 0 },
+ { DSCR_CMD0_SDMS_RX1, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 },
+
+ { DSCR_CMD0_AES_TX, DEV_FLAGS_OUT, 0, 0, 0x00000000, 0, 0 },
+ { DSCR_CMD0_AES_RX, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 },
+
+ { DSCR_CMD0_PSC0_TX, DEV_FLAGS_OUT, 0, 0, 0x11a0001c, 0, 0 },
+ { DSCR_CMD0_PSC0_RX, DEV_FLAGS_IN, 0, 0, 0x11a0001c, 0, 0 },
+ { DSCR_CMD0_PSC0_SYNC, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
+
+ { DSCR_CMD0_PSC1_TX, DEV_FLAGS_OUT, 0, 0, 0x11b0001c, 0, 0 },
+ { DSCR_CMD0_PSC1_RX, DEV_FLAGS_IN, 0, 0, 0x11b0001c, 0, 0 },
+ { DSCR_CMD0_PSC1_SYNC, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
+
+ { DSCR_CMD0_CIM_RXA, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 },
+ { DSCR_CMD0_CIM_RXB, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 },
+ { DSCR_CMD0_CIM_RXC, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 },
+ { DSCR_CMD0_CIM_SYNC, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
+
+ { DSCR_CMD0_NAND_FLASH, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 },
+
+#endif // CONFIG_SOC_AU1200
+
+ { DSCR_CMD0_THROTTLE, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
+ { DSCR_CMD0_ALWAYS, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
+};
+
+#define DBDEV_TAB_SIZE (sizeof(dbdev_tab) / sizeof(dbdev_tab_t))
+
+static chan_tab_t *chan_tab_ptr[NUM_DBDMA_CHANS];
+
+static dbdev_tab_t *
+find_dbdev_id (u32 id)
+{
+ int i;
+ dbdev_tab_t *p;
+ for (i = 0; i < DBDEV_TAB_SIZE; ++i) {
+ p = &dbdev_tab[i];
+ if (p->dev_id == id)
+ return p;
+ }
+ return NULL;
+}
+
+/* Allocate a channel and return a non-zero descriptor if successful.
+*/
+u32
+au1xxx_dbdma_chan_alloc(u32 srcid, u32 destid,
+ void (*callback)(int, void *, struct pt_regs *), void *callparam)
+{
+ unsigned long flags;
+ u32 used, chan, rv;
+ u32 dcp;
+ int i;
+ dbdev_tab_t *stp, *dtp;
+ chan_tab_t *ctp;
+ volatile au1x_dma_chan_t *cp;
+
+ /* We do the intialization on the first channel allocation.
+ * We have to wait because of the interrupt handler initialization
+ * which can't be done successfully during board set up.
+ */
+ if (!dbdma_initialized)
+ au1xxx_dbdma_init();
+ dbdma_initialized = 1;
+
+ if ((srcid > DSCR_NDEV_IDS) || (destid > DSCR_NDEV_IDS))
+ return 0;
+
+ if ((stp = find_dbdev_id(srcid)) == NULL) return 0;
+ if ((dtp = find_dbdev_id(destid)) == NULL) return 0;
+
+ used = 0;
+ rv = 0;
+
+ /* Check to see if we can get both channels.
+ */
+ spin_lock_irqsave(&au1xxx_dbdma_spin_lock, flags);
+ if (!(stp->dev_flags & DEV_FLAGS_INUSE) ||
+ (stp->dev_flags & DEV_FLAGS_ANYUSE)) {
+ /* Got source */
+ stp->dev_flags |= DEV_FLAGS_INUSE;
+ if (!(dtp->dev_flags & DEV_FLAGS_INUSE) ||
+ (dtp->dev_flags & DEV_FLAGS_ANYUSE)) {
+ /* Got destination */
+ dtp->dev_flags |= DEV_FLAGS_INUSE;
+ }
+ else {
+ /* Can't get dest. Release src.
+ */
+ stp->dev_flags &= ~DEV_FLAGS_INUSE;
+ used++;
+ }
+ }
+ else {
+ used++;
+ }
+ spin_unlock_irqrestore(&au1xxx_dbdma_spin_lock, flags);
+
+ if (!used) {
+ /* Let's see if we can allocate a channel for it.
+ */
+ ctp = NULL;
+ chan = 0;
+ spin_lock_irqsave(&au1xxx_dbdma_spin_lock, flags);
+ for (i=0; i<NUM_DBDMA_CHANS; i++) {
+ if (chan_tab_ptr[i] == NULL) {
+ /* If kmalloc fails, it is caught below same
+ * as a channel not available.
+ */
+ ctp = kmalloc(sizeof(chan_tab_t), GFP_KERNEL);
+ chan_tab_ptr[i] = ctp;
+ ctp->chan_index = chan = i;
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&au1xxx_dbdma_spin_lock, flags);
+
+ if (ctp != NULL) {
+ memset(ctp, 0, sizeof(chan_tab_t));
+ dcp = DDMA_CHANNEL_BASE;
+ dcp += (0x0100 * chan);
+ ctp->chan_ptr = (au1x_dma_chan_t *)dcp;
+ cp = (volatile au1x_dma_chan_t *)dcp;
+ ctp->chan_src = stp;
+ ctp->chan_dest = dtp;
+ ctp->chan_callback = callback;
+ ctp->chan_callparam = callparam;
+
+ /* Initialize channel configuration.
+ */
+ i = 0;
+ if (stp->dev_intlevel)
+ i |= DDMA_CFG_SED;
+ if (stp->dev_intpolarity)
+ i |= DDMA_CFG_SP;
+ if (dtp->dev_intlevel)
+ i |= DDMA_CFG_DED;
+ if (dtp->dev_intpolarity)
+ i |= DDMA_CFG_DP;
+ cp->ddma_cfg = i;
+ au_sync();
+
+ /* Return a non-zero value that can be used to
+ * find the channel information in subsequent
+ * operations.
+ */
+ rv = (u32)(&chan_tab_ptr[chan]);
+ }
+ else {
+ /* Release devices.
+ */
+ stp->dev_flags &= ~DEV_FLAGS_INUSE;
+ dtp->dev_flags &= ~DEV_FLAGS_INUSE;
+ }
+ }
+ return rv;
+}
+
+/* Set the device width if source or destination is a FIFO.
+ * Should be 8, 16, or 32 bits.
+ */
+u32
+au1xxx_dbdma_set_devwidth(u32 chanid, int bits)
+{
+ u32 rv;
+ chan_tab_t *ctp;
+ dbdev_tab_t *stp, *dtp;
+
+ ctp = *((chan_tab_t **)chanid);
+ stp = ctp->chan_src;
+ dtp = ctp->chan_dest;
+ rv = 0;
+
+ if (stp->dev_flags & DEV_FLAGS_IN) { /* Source in fifo */
+ rv = stp->dev_devwidth;
+ stp->dev_devwidth = bits;
+ }
+ if (dtp->dev_flags & DEV_FLAGS_OUT) { /* Destination out fifo */
+ rv = dtp->dev_devwidth;
+ dtp->dev_devwidth = bits;
+ }
+
+ return rv;
+}
+
+/* Allocate a descriptor ring, initializing as much as possible.
+*/
+u32
+au1xxx_dbdma_ring_alloc(u32 chanid, int entries)
+{
+ int i;
+ u32 desc_base, srcid, destid;
+ u32 cmd0, cmd1, src1, dest1;
+ u32 src0, dest0;
+ chan_tab_t *ctp;
+ dbdev_tab_t *stp, *dtp;
+ au1x_ddma_desc_t *dp;
+
+ /* I guess we could check this to be within the
+ * range of the table......
+ */
+ ctp = *((chan_tab_t **)chanid);
+ stp = ctp->chan_src;
+ dtp = ctp->chan_dest;
+
+ /* The descriptors must be 32-byte aligned. There is a
+ * possibility the allocation will give us such an address,
+ * and if we try that first we are likely to not waste larger
+ * slabs of memory.
+ */
+ desc_base = (u32)kmalloc(entries * sizeof(au1x_ddma_desc_t), GFP_KERNEL);
+ if (desc_base == 0)
+ return 0;
+
+ if (desc_base & 0x1f) {
+ /* Lost....do it again, allocate extra, and round
+ * the address base.
+ */
+ kfree((const void *)desc_base);
+ i = entries * sizeof(au1x_ddma_desc_t);
+ i += (sizeof(au1x_ddma_desc_t) - 1);
+ if ((desc_base = (u32)kmalloc(i, GFP_KERNEL)) == 0)
+ return 0;
+
+ desc_base = ALIGN_ADDR(desc_base, sizeof(au1x_ddma_desc_t));
+ }
+ dp = (au1x_ddma_desc_t *)desc_base;
+
+ /* Keep track of the base descriptor.
+ */
+ ctp->chan_desc_base = dp;
+
+ /* Initialize the rings with as much information as we know.
+ */
+ srcid = stp->dev_id;
+ destid = dtp->dev_id;
+
+ cmd0 = cmd1 = src1 = dest1 = 0;
+ src0 = dest0 = 0;
+
+ cmd0 |= DSCR_CMD0_SID(srcid);
+ cmd0 |= DSCR_CMD0_DID(destid);
+ cmd0 |= DSCR_CMD0_IE | DSCR_CMD0_CV;
+ cmd0 |= DSCR_CMD0_ST(DSCR_CMD0_ST_CURRENT);
+
+ switch (stp->dev_devwidth) {
+ case 8:
+ cmd0 |= DSCR_CMD0_SW(DSCR_CMD0_BYTE);
+ break;
+ case 16:
+ cmd0 |= DSCR_CMD0_SW(DSCR_CMD0_HALFWORD);
+ break;
+ case 32:
+ default:
+ cmd0 |= DSCR_CMD0_SW(DSCR_CMD0_WORD);
+ break;
+ }
+
+ switch (dtp->dev_devwidth) {
+ case 8:
+ cmd0 |= DSCR_CMD0_DW(DSCR_CMD0_BYTE);
+ break;
+ case 16:
+ cmd0 |= DSCR_CMD0_DW(DSCR_CMD0_HALFWORD);
+ break;
+ case 32:
+ default:
+ cmd0 |= DSCR_CMD0_DW(DSCR_CMD0_WORD);
+ break;
+ }
+
+ /* If the device is marked as an in/out FIFO, ensure it is
+ * set non-coherent.
+ */
+ if (stp->dev_flags & DEV_FLAGS_IN)
+ cmd0 |= DSCR_CMD0_SN; /* Source in fifo */
+ if (dtp->dev_flags & DEV_FLAGS_OUT)
+ cmd0 |= DSCR_CMD0_DN; /* Destination out fifo */
+
+ /* Set up source1. For now, assume no stride and increment.
+ * A channel attribute update can change this later.
+ */
+ switch (stp->dev_tsize) {
+ case 1:
+ src1 |= DSCR_SRC1_STS(DSCR_xTS_SIZE1);
+ break;
+ case 2:
+ src1 |= DSCR_SRC1_STS(DSCR_xTS_SIZE2);
+ break;
+ case 4:
+ src1 |= DSCR_SRC1_STS(DSCR_xTS_SIZE4);
+ break;
+ case 8:
+ default:
+ src1 |= DSCR_SRC1_STS(DSCR_xTS_SIZE8);
+ break;
+ }
+
+ /* If source input is fifo, set static address.
+ */
+ if (stp->dev_flags & DEV_FLAGS_IN) {
+ src0 = stp->dev_physaddr;
+ src1 |= DSCR_SRC1_SAM(DSCR_xAM_STATIC);
+ }
+
+ /* Set up dest1. For now, assume no stride and increment.
+ * A channel attribute update can change this later.
+ */
+ switch (dtp->dev_tsize) {
+ case 1:
+ dest1 |= DSCR_DEST1_DTS(DSCR_xTS_SIZE1);
+ break;
+ case 2:
+ dest1 |= DSCR_DEST1_DTS(DSCR_xTS_SIZE2);
+ break;
+ case 4:
+ dest1 |= DSCR_DEST1_DTS(DSCR_xTS_SIZE4);
+ break;
+ case 8:
+ default:
+ dest1 |= DSCR_DEST1_DTS(DSCR_xTS_SIZE8);
+ break;
+ }
+
+ /* If destination output is fifo, set static address.
+ */
+ if (dtp->dev_flags & DEV_FLAGS_OUT) {
+ dest0 = dtp->dev_physaddr;
+ dest1 |= DSCR_DEST1_DAM(DSCR_xAM_STATIC);
+ }
+
+ for (i=0; i<entries; i++) {
+ dp->dscr_cmd0 = cmd0;
+ dp->dscr_cmd1 = cmd1;
+ dp->dscr_source0 = src0;
+ dp->dscr_source1 = src1;
+ dp->dscr_dest0 = dest0;
+ dp->dscr_dest1 = dest1;
+ dp->dscr_stat = 0;
+ dp->dscr_nxtptr = DSCR_NXTPTR(virt_to_phys(dp + 1));
+ dp++;
+ }
+
+ /* Make last descrptor point to the first.
+ */
+ dp--;
+ dp->dscr_nxtptr = DSCR_NXTPTR(virt_to_phys(ctp->chan_desc_base));
+ ctp->get_ptr = ctp->put_ptr = ctp->cur_ptr = ctp->chan_desc_base;
+
+ return (u32)(ctp->chan_desc_base);
+}
+
+/* Put a source buffer into the DMA ring.
+ * This updates the source pointer and byte count. Normally used
+ * for memory to fifo transfers.
+ */
+u32
+au1xxx_dbdma_put_source(u32 chanid, void *buf, int nbytes)
+{
+ chan_tab_t *ctp;
+ au1x_ddma_desc_t *dp;
+
+ /* I guess we could check this to be within the
+ * range of the table......
+ */
+ ctp = *((chan_tab_t **)chanid);
+
+ /* We should have multiple callers for a particular channel,
+ * an interrupt doesn't affect this pointer nor the descriptor,
+ * so no locking should be needed.
+ */
+ dp = ctp->put_ptr;
+
+ /* If the descriptor is valid, we are way ahead of the DMA
+ * engine, so just return an error condition.
+ */
+ if (dp->dscr_cmd0 & DSCR_CMD0_V) {
+ return 0;
+ }
+
+ /* Load up buffer address and byte count.
+ */
+ dp->dscr_source0 = virt_to_phys(buf);
+ dp->dscr_cmd1 = nbytes;
+ dp->dscr_cmd0 |= DSCR_CMD0_V; /* Let it rip */
+ ctp->chan_ptr->ddma_dbell = 0xffffffff; /* Make it go */
+
+ /* Get next descriptor pointer.
+ */
+ ctp->put_ptr = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr));
+
+ /* return something not zero.
+ */
+ return nbytes;
+}
+
+/* Put a destination buffer into the DMA ring.
+ * This updates the destination pointer and byte count. Normally used
+ * to place an empty buffer into the ring for fifo to memory transfers.
+ */
+u32
+au1xxx_dbdma_put_dest(u32 chanid, void *buf, int nbytes)
+{
+ chan_tab_t *ctp;
+ au1x_ddma_desc_t *dp;
+
+ /* I guess we could check this to be within the
+ * range of the table......
+ */
+ ctp = *((chan_tab_t **)chanid);
+
+ /* We should have multiple callers for a particular channel,
+ * an interrupt doesn't affect this pointer nor the descriptor,
+ * so no locking should be needed.
+ */
+ dp = ctp->put_ptr;
+
+ /* If the descriptor is valid, we are way ahead of the DMA
+ * engine, so just return an error condition.
+ */
+ if (dp->dscr_cmd0 & DSCR_CMD0_V)
+ return 0;
+
+ /* Load up buffer address and byte count.
+ */
+ dp->dscr_dest0 = virt_to_phys(buf);
+ dp->dscr_cmd1 = nbytes;
+ dp->dscr_cmd0 |= DSCR_CMD0_V; /* Let it rip */
+
+ /* Get next descriptor pointer.
+ */
+ ctp->put_ptr = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr));
+
+ /* return something not zero.
+ */
+ return nbytes;
+}
+
+/* Get a destination buffer into the DMA ring.
+ * Normally used to get a full buffer from the ring during fifo
+ * to memory transfers. This does not set the valid bit, you will
+ * have to put another destination buffer to keep the DMA going.
+ */
+u32
+au1xxx_dbdma_get_dest(u32 chanid, void **buf, int *nbytes)
+{
+ chan_tab_t *ctp;
+ au1x_ddma_desc_t *dp;
+ u32 rv;
+
+ /* I guess we could check this to be within the
+ * range of the table......
+ */
+ ctp = *((chan_tab_t **)chanid);
+
+ /* We should have multiple callers for a particular channel,
+ * an interrupt doesn't affect this pointer nor the descriptor,
+ * so no locking should be needed.
+ */
+ dp = ctp->get_ptr;
+
+ /* If the descriptor is valid, we are way ahead of the DMA
+ * engine, so just return an error condition.
+ */
+ if (dp->dscr_cmd0 & DSCR_CMD0_V)
+ return 0;
+
+ /* Return buffer address and byte count.
+ */
+ *buf = (void *)(phys_to_virt(dp->dscr_dest0));
+ *nbytes = dp->dscr_cmd1;
+ rv = dp->dscr_stat;
+
+ /* Get next descriptor pointer.
+ */
+ ctp->get_ptr = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr));
+
+ /* return something not zero.
+ */
+ return rv;
+}
+
+void
+au1xxx_dbdma_stop(u32 chanid)
+{
+ chan_tab_t *ctp;
+ volatile au1x_dma_chan_t *cp;
+ int halt_timeout = 0;
+
+ ctp = *((chan_tab_t **)chanid);
+
+ cp = ctp->chan_ptr;
+ cp->ddma_cfg &= ~DDMA_CFG_EN; /* Disable channel */
+ au_sync();
+ while (!(cp->ddma_stat & DDMA_STAT_H)) {
+ udelay(1);
+ halt_timeout++;
+ if (halt_timeout > 100) {
+ printk("warning: DMA channel won't halt\n");
+ break;
+ }
+ }
+ /* clear current desc valid and doorbell */
+ cp->ddma_stat |= (DDMA_STAT_DB | DDMA_STAT_V);
+ au_sync();
+}
+
+/* Start using the current descriptor pointer. If the dbdma encounters
+ * a not valid descriptor, it will stop. In this case, we can just
+ * continue by adding a buffer to the list and starting again.
+ */
+void
+au1xxx_dbdma_start(u32 chanid)
+{
+ chan_tab_t *ctp;
+ volatile au1x_dma_chan_t *cp;
+
+ ctp = *((chan_tab_t **)chanid);
+
+ cp = ctp->chan_ptr;
+ cp->ddma_desptr = virt_to_phys(ctp->cur_ptr);
+ cp->ddma_cfg |= DDMA_CFG_EN; /* Enable channel */
+ au_sync();
+ cp->ddma_dbell = 0xffffffff; /* Make it go */
+ au_sync();
+}
+
+void
+au1xxx_dbdma_reset(u32 chanid)
+{
+ chan_tab_t *ctp;
+ au1x_ddma_desc_t *dp;
+
+ au1xxx_dbdma_stop(chanid);
+
+ ctp = *((chan_tab_t **)chanid);
+ ctp->get_ptr = ctp->put_ptr = ctp->cur_ptr = ctp->chan_desc_base;
+
+ /* Run through the descriptors and reset the valid indicator.
+ */
+ dp = ctp->chan_desc_base;
+
+ do {
+ dp->dscr_cmd0 &= ~DSCR_CMD0_V;
+ dp = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr));
+ } while (dp != ctp->chan_desc_base);
+}
+
+u32
+au1xxx_get_dma_residue(u32 chanid)
+{
+ chan_tab_t *ctp;
+ volatile au1x_dma_chan_t *cp;
+ u32 rv;
+
+ ctp = *((chan_tab_t **)chanid);
+ cp = ctp->chan_ptr;
+
+ /* This is only valid if the channel is stopped.
+ */
+ rv = cp->ddma_bytecnt;
+ au_sync();
+
+ return rv;
+}
+
+void
+au1xxx_dbdma_chan_free(u32 chanid)
+{
+ chan_tab_t *ctp;
+ dbdev_tab_t *stp, *dtp;
+
+ ctp = *((chan_tab_t **)chanid);
+ stp = ctp->chan_src;
+ dtp = ctp->chan_dest;
+
+ au1xxx_dbdma_stop(chanid);
+
+ if (ctp->chan_desc_base != NULL)
+ kfree(ctp->chan_desc_base);
+
+ stp->dev_flags &= ~DEV_FLAGS_INUSE;
+ dtp->dev_flags &= ~DEV_FLAGS_INUSE;
+ chan_tab_ptr[ctp->chan_index] = NULL;
+
+ kfree(ctp);
+}
+
+static irqreturn_t
+dbdma_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ u32 intstat;
+ u32 chan_index;
+ chan_tab_t *ctp;
+ au1x_ddma_desc_t *dp;
+ volatile au1x_dma_chan_t *cp;
+
+ intstat = dbdma_gptr->ddma_intstat;
+ au_sync();
+ chan_index = au_ffs(intstat) - 1;
+
+ ctp = chan_tab_ptr[chan_index];
+ cp = ctp->chan_ptr;
+ dp = ctp->cur_ptr;
+
+ /* Reset interrupt.
+ */
+ cp->ddma_irq = 0;
+ au_sync();
+
+ if (ctp->chan_callback)
+ (ctp->chan_callback)(irq, ctp->chan_callparam, regs);
+
+ ctp->cur_ptr = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr));
+
+ return IRQ_HANDLED;
+}
+
+static void
+au1xxx_dbdma_init(void)
+{
+ dbdma_gptr->ddma_config = 0;
+ dbdma_gptr->ddma_throttle = 0;
+ dbdma_gptr->ddma_inten = 0xffff;
+ au_sync();
+
+ if (request_irq(AU1550_DDMA_INT, dbdma_interrupt, SA_INTERRUPT,
+ "Au1xxx dbdma", (void *)dbdma_gptr))
+ printk("Can't get 1550 dbdma irq");
+}
+
+void
+au1xxx_dbdma_dump(u32 chanid)
+{
+ chan_tab_t *ctp;
+ au1x_ddma_desc_t *dp;
+ dbdev_tab_t *stp, *dtp;
+ volatile au1x_dma_chan_t *cp;
+
+ ctp = *((chan_tab_t **)chanid);
+ stp = ctp->chan_src;
+ dtp = ctp->chan_dest;
+ cp = ctp->chan_ptr;
+
+ printk("Chan %x, stp %x (dev %d) dtp %x (dev %d) \n",
+ (u32)ctp, (u32)stp, stp - dbdev_tab, (u32)dtp, dtp - dbdev_tab);
+ printk("desc base %x, get %x, put %x, cur %x\n",
+ (u32)(ctp->chan_desc_base), (u32)(ctp->get_ptr),
+ (u32)(ctp->put_ptr), (u32)(ctp->cur_ptr));
+
+ printk("dbdma chan %x\n", (u32)cp);
+ printk("cfg %08x, desptr %08x, statptr %08x\n",
+ cp->ddma_cfg, cp->ddma_desptr, cp->ddma_statptr);
+ printk("dbell %08x, irq %08x, stat %08x, bytecnt %08x\n",
+ cp->ddma_dbell, cp->ddma_irq, cp->ddma_stat, cp->ddma_bytecnt);
+
+
+ /* Run through the descriptors
+ */
+ dp = ctp->chan_desc_base;
+
+ do {
+ printk("dp %08x, cmd0 %08x, cmd1 %08x\n",
+ (u32)dp, dp->dscr_cmd0, dp->dscr_cmd1);
+ printk("src0 %08x, src1 %08x, dest0 %08x\n",
+ dp->dscr_source0, dp->dscr_source1, dp->dscr_dest0);
+ printk("dest1 %08x, stat %08x, nxtptr %08x\n",
+ dp->dscr_dest1, dp->dscr_stat, dp->dscr_nxtptr);
+ dp = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr));
+ } while (dp != ctp->chan_desc_base);
+}
+
+#endif /* defined(CONFIG_SOC_AU1550) || defined(CONFIG_SOC_AU1200) */
+
diff --git a/arch/mips/au1000/common/dbg_io.c b/arch/mips/au1000/common/dbg_io.c
new file mode 100644
index 0000000..7bc768e
--- /dev/null
+++ b/arch/mips/au1000/common/dbg_io.c
@@ -0,0 +1,122 @@
+
+#include <linux/config.h>
+#include <asm/io.h>
+#include <asm/mach-au1x00/au1000.h>
+
+#ifdef CONFIG_KGDB
+
+/*
+ * FIXME the user should be able to select the
+ * uart to be used for debugging.
+ */
+#define DEBUG_BASE UART_DEBUG_BASE
+/**/
+
+/* we need uint32 uint8 */
+/* #include "types.h" */
+typedef unsigned char uint8;
+typedef unsigned int uint32;
+
+#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
+
+
+#define UART_RX 0 /* Receive buffer */
+#define UART_TX 4 /* Transmit buffer */
+#define UART_IER 8 /* Interrupt Enable Register */
+#define UART_IIR 0xC /* Interrupt ID Register */
+#define UART_FCR 0x10 /* FIFO Control Register */
+#define UART_LCR 0x14 /* Line Control Register */
+#define UART_MCR 0x18 /* Modem Control Register */
+#define UART_LSR 0x1C /* Line Status Register */
+#define UART_MSR 0x20 /* Modem Status Register */
+#define UART_CLK 0x28 /* Baud Rat4e Clock Divider */
+#define UART_MOD_CNTRL 0x100 /* Module Control */
+
+/* memory-mapped read/write of the port */
+#define UART16550_READ(y) (au_readl(DEBUG_BASE + y) & 0xff)
+#define UART16550_WRITE(y,z) (au_writel(z&0xff, DEBUG_BASE + y))
+
+extern unsigned long get_au1x00_uart_baud_base(void);
+extern unsigned long cal_r4koff(void);
+
+void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop)
+{
+
+ if (UART16550_READ(UART_MOD_CNTRL) != 0x3) {
+ UART16550_WRITE(UART_MOD_CNTRL, 3);
+ }
+ cal_r4koff();
+
+ /* disable interrupts */
+ UART16550_WRITE(UART_IER, 0);
+
+ /* set up baud rate */
+ {
+ uint32 divisor;
+
+ /* set divisor */
+ divisor = get_au1x00_uart_baud_base() / baud;
+ UART16550_WRITE(UART_CLK, divisor & 0xffff);
+ }
+
+ /* set data format */
+ UART16550_WRITE(UART_LCR, (data | parity | stop));
+}
+
+static int remoteDebugInitialized = 0;
+
+uint8 getDebugChar(void)
+{
+ if (!remoteDebugInitialized) {
+ remoteDebugInitialized = 1;
+ debugInit(UART16550_BAUD_115200,
+ UART16550_DATA_8BIT,
+ UART16550_PARITY_NONE,
+ UART16550_STOP_1BIT);
+ }
+
+ while((UART16550_READ(UART_LSR) & 0x1) == 0);
+ return UART16550_READ(UART_RX);
+}
+
+
+int putDebugChar(uint8 byte)
+{
+// int i;
+
+ if (!remoteDebugInitialized) {
+ remoteDebugInitialized = 1;
+ debugInit(UART16550_BAUD_115200,
+ UART16550_DATA_8BIT,
+ UART16550_PARITY_NONE,
+ UART16550_STOP_1BIT);
+ }
+
+ while ((UART16550_READ(UART_LSR)&0x40) == 0);
+ UART16550_WRITE(UART_TX, byte);
+ //for (i=0;i<0xfff;i++);
+
+ return 1;
+}
+
+#endif
diff --git a/arch/mips/au1000/common/dma.c b/arch/mips/au1000/common/dma.c
new file mode 100644
index 0000000..372c33f
--- /dev/null
+++ b/arch/mips/au1000/common/dma.c
@@ -0,0 +1,243 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ * A DMA channel allocator for Au1000. API is modeled loosely off of
+ * linux/kernel/dma.c.
+ *
+ * Copyright 2000 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ * stevel@mvista.com or source@mvista.com
+ * Copyright (C) 2005 Ralf Baechle (ralf@linux-mips.org)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <asm/system.h>
+#include <asm/mach-au1x00/au1000.h>
+#include <asm/mach-au1x00/au1000_dma.h>
+
+#if defined(CONFIG_SOC_AU1000) || defined(CONFIG_SOC_AU1500) || defined(CONFIG_SOC_AU1100)
+/*
+ * A note on resource allocation:
+ *
+ * All drivers needing DMA channels, should allocate and release them
+ * through the public routines `request_dma()' and `free_dma()'.
+ *
+ * In order to avoid problems, all processes should allocate resources in
+ * the same sequence and release them in the reverse order.
+ *
+ * So, when allocating DMAs and IRQs, first allocate the DMA, then the IRQ.
+ * When releasing them, first release the IRQ, then release the DMA. The
+ * main reason for this order is that, if you are requesting the DMA buffer
+ * done interrupt, you won't know the irq number until the DMA channel is
+ * returned from request_dma.
+ */
+
+
+DEFINE_SPINLOCK(au1000_dma_spin_lock);
+
+struct dma_chan au1000_dma_table[NUM_AU1000_DMA_CHANNELS] = {
+ {.dev_id = -1,},
+ {.dev_id = -1,},
+ {.dev_id = -1,},
+ {.dev_id = -1,},
+ {.dev_id = -1,},
+ {.dev_id = -1,},
+ {.dev_id = -1,},
+ {.dev_id = -1,}
+};
+EXPORT_SYMBOL(au1000_dma_table);
+
+// Device FIFO addresses and default DMA modes
+static const struct dma_dev {
+ unsigned int fifo_addr;
+ unsigned int dma_mode;
+} dma_dev_table[DMA_NUM_DEV] = {
+ {UART0_ADDR + UART_TX, 0},
+ {UART0_ADDR + UART_RX, 0},
+ {0, 0},
+ {0, 0},
+ {AC97C_DATA, DMA_DW16 }, // coherent
+ {AC97C_DATA, DMA_DR | DMA_DW16 }, // coherent
+ {UART3_ADDR + UART_TX, DMA_DW8 | DMA_NC},
+ {UART3_ADDR + UART_RX, DMA_DR | DMA_DW8 | DMA_NC},
+ {USBD_EP0RD, DMA_DR | DMA_DW8 | DMA_NC},
+ {USBD_EP0WR, DMA_DW8 | DMA_NC},
+ {USBD_EP2WR, DMA_DW8 | DMA_NC},
+ {USBD_EP3WR, DMA_DW8 | DMA_NC},
+ {USBD_EP4RD, DMA_DR | DMA_DW8 | DMA_NC},
+ {USBD_EP5RD, DMA_DR | DMA_DW8 | DMA_NC},
+ {I2S_DATA, DMA_DW32 | DMA_NC},
+ {I2S_DATA, DMA_DR | DMA_DW32 | DMA_NC}
+};
+
+int au1000_dma_read_proc(char *buf, char **start, off_t fpos,
+ int length, int *eof, void *data)
+{
+ int i, len = 0;
+ struct dma_chan *chan;
+
+ for (i = 0; i < NUM_AU1000_DMA_CHANNELS; i++) {
+ if ((chan = get_dma_chan(i)) != NULL) {
+ len += sprintf(buf + len, "%2d: %s\n",
+ i, chan->dev_str);
+ }
+ }
+
+ if (fpos >= len) {
+ *start = buf;
+ *eof = 1;
+ return 0;
+ }
+ *start = buf + fpos;
+ if ((len -= fpos) > length)
+ return length;
+ *eof = 1;
+ return len;
+}
+
+// Device FIFO addresses and default DMA modes - 2nd bank
+static const struct dma_dev dma_dev_table_bank2[DMA_NUM_DEV_BANK2] = {
+ {SD0_XMIT_FIFO, DMA_DS | DMA_DW8}, // coherent
+ {SD0_RECV_FIFO, DMA_DS | DMA_DR | DMA_DW8}, // coherent
+ {SD1_XMIT_FIFO, DMA_DS | DMA_DW8}, // coherent
+ {SD1_RECV_FIFO, DMA_DS | DMA_DR | DMA_DW8} // coherent
+};
+
+void dump_au1000_dma_channel(unsigned int dmanr)
+{
+ struct dma_chan *chan;
+
+ if (dmanr >= NUM_AU1000_DMA_CHANNELS)
+ return;
+ chan = &au1000_dma_table[dmanr];
+
+ printk(KERN_INFO "Au1000 DMA%d Register Dump:\n", dmanr);
+ printk(KERN_INFO " mode = 0x%08x\n",
+ au_readl(chan->io + DMA_MODE_SET));
+ printk(KERN_INFO " addr = 0x%08x\n",
+ au_readl(chan->io + DMA_PERIPHERAL_ADDR));
+ printk(KERN_INFO " start0 = 0x%08x\n",
+ au_readl(chan->io + DMA_BUFFER0_START));
+ printk(KERN_INFO " start1 = 0x%08x\n",
+ au_readl(chan->io + DMA_BUFFER1_START));
+ printk(KERN_INFO " count0 = 0x%08x\n",
+ au_readl(chan->io + DMA_BUFFER0_COUNT));
+ printk(KERN_INFO " count1 = 0x%08x\n",
+ au_readl(chan->io + DMA_BUFFER1_COUNT));
+}
+
+
+/*
+ * Finds a free channel, and binds the requested device to it.
+ * Returns the allocated channel number, or negative on error.
+ * Requests the DMA done IRQ if irqhandler != NULL.
+ */
+int request_au1000_dma(int dev_id, const char *dev_str,
+ irqreturn_t (*irqhandler)(int, void *, struct pt_regs *),
+ unsigned long irqflags,
+ void *irq_dev_id)
+{
+ struct dma_chan *chan;
+ const struct dma_dev *dev;
+ int i, ret;
+
+#if defined(CONFIG_SOC_AU1100)
+ if (dev_id < 0 || dev_id >= (DMA_NUM_DEV + DMA_NUM_DEV_BANK2))
+ return -EINVAL;
+#else
+ if (dev_id < 0 || dev_id >= DMA_NUM_DEV)
+ return -EINVAL;
+#endif
+
+ for (i = 0; i < NUM_AU1000_DMA_CHANNELS; i++) {
+ if (au1000_dma_table[i].dev_id < 0)
+ break;
+ }
+ if (i == NUM_AU1000_DMA_CHANNELS)
+ return -ENODEV;
+
+ chan = &au1000_dma_table[i];
+
+ if (dev_id >= DMA_NUM_DEV) {
+ dev_id -= DMA_NUM_DEV;
+ dev = &dma_dev_table_bank2[dev_id];
+ } else {
+ dev = &dma_dev_table[dev_id];
+ }
+
+ if (irqhandler) {
+ chan->irq = AU1000_DMA_INT_BASE + i;
+ chan->irq_dev = irq_dev_id;
+ if ((ret = request_irq(chan->irq, irqhandler, irqflags,
+ dev_str, chan->irq_dev))) {
+ chan->irq = 0;
+ chan->irq_dev = NULL;
+ return ret;
+ }
+ } else {
+ chan->irq = 0;
+ chan->irq_dev = NULL;
+ }
+
+ // fill it in
+ chan->io = DMA_CHANNEL_BASE + i * DMA_CHANNEL_LEN;
+ chan->dev_id = dev_id;
+ chan->dev_str = dev_str;
+ chan->fifo_addr = dev->fifo_addr;
+ chan->mode = dev->dma_mode;
+
+ /* initialize the channel before returning */
+ init_dma(i);
+
+ return i;
+}
+EXPORT_SYMBOL(request_au1000_dma);
+
+void free_au1000_dma(unsigned int dmanr)
+{
+ struct dma_chan *chan = get_dma_chan(dmanr);
+ if (!chan) {
+ printk("Trying to free DMA%d\n", dmanr);
+ return;
+ }
+
+ disable_dma(dmanr);
+ if (chan->irq)
+ free_irq(chan->irq, chan->irq_dev);
+
+ chan->irq = 0;
+ chan->irq_dev = NULL;
+ chan->dev_id = -1;
+}
+EXPORT_SYMBOL(free_au1000_dma);
+
+#endif // AU1000 AU1500 AU1100
diff --git a/arch/mips/au1000/common/int-handler.S b/arch/mips/au1000/common/int-handler.S
new file mode 100644
index 0000000..1c4ca88
--- /dev/null
+++ b/arch/mips/au1000/common/int-handler.S
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: ppopov@mvista.com
+ *
+ * Interrupt dispatcher for Au1000 boards.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+#include <asm/asm.h>
+#include <asm/mipsregs.h>
+#include <asm/addrspace.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+
+ .text
+ .set macro
+ .set noat
+ .align 5
+
+NESTED(au1000_IRQ, PT_SIZE, sp)
+ SAVE_ALL
+ CLI # Important: mark KERNEL mode !
+
+ mfc0 t0,CP0_CAUSE # get pending interrupts
+ mfc0 t1,CP0_STATUS # get enabled interrupts
+ and t0,t1 # isolate allowed ones
+
+ andi t0,0xff00 # isolate pending bits
+ beqz t0, 3f # spurious interrupt
+
+ andi a0, t0, CAUSEF_IP7
+ beq a0, zero, 1f
+ move a0, sp
+ jal mips_timer_interrupt
+ j ret_from_irq
+
+1:
+ andi a0, t0, CAUSEF_IP2 # Interrupt Controller 0, Request 0
+ beq a0, zero, 2f
+ move a0,sp
+ jal intc0_req0_irqdispatch
+ j ret_from_irq
+2:
+ andi a0, t0, CAUSEF_IP3 # Interrupt Controller 0, Request 1
+ beq a0, zero, 3f
+ move a0,sp
+ jal intc0_req1_irqdispatch
+ j ret_from_irq
+3:
+ andi a0, t0, CAUSEF_IP4 # Interrupt Controller 1, Request 0
+ beq a0, zero, 4f
+ move a0,sp
+ jal intc1_req0_irqdispatch
+ j ret_from_irq
+4:
+ andi a0, t0, CAUSEF_IP5 # Interrupt Controller 1, Request 1
+ beq a0, zero, 5f
+ move a0, sp
+ jal intc1_req1_irqdispatch
+ j ret_from_irq
+
+5:
+ move a0, sp
+ j spurious_interrupt
+END(au1000_IRQ)
diff --git a/arch/mips/au1000/common/irq.c b/arch/mips/au1000/common/irq.c
new file mode 100644
index 0000000..d1eb5a4
--- /dev/null
+++ b/arch/mips/au1000/common/irq.c
@@ -0,0 +1,654 @@
+/*
+ * BRIEF MODULE DESCRIPTION
+ * Au1000 interrupt routines.
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ * ppopov@mvista.com or source@mvista.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/kernel_stat.h>
+#include <linux/module.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/timex.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+#include <linux/delay.h>
+#include <linux/bitops.h>
+
+#include <asm/bootinfo.h>
+#include <asm/io.h>
+#include <asm/mipsregs.h>
+#include <asm/system.h>
+#include <asm/mach-au1x00/au1000.h>
+#ifdef CONFIG_MIPS_PB1000
+#include <asm/mach-pb1x00/pb1000.h>
+#endif
+
+#undef DEBUG_IRQ
+#ifdef DEBUG_IRQ
+/* note: prints function name for you */
+#define DPRINTK(fmt, args...) printk("%s: " fmt, __FUNCTION__ , ## args)
+#else
+#define DPRINTK(fmt, args...)
+#endif
+
+#define EXT_INTC0_REQ0 2 /* IP 2 */
+#define EXT_INTC0_REQ1 3 /* IP 3 */
+#define EXT_INTC1_REQ0 4 /* IP 4 */
+#define EXT_INTC1_REQ1 5 /* IP 5 */
+#define MIPS_TIMER_IP 7 /* IP 7 */
+
+extern asmlinkage void au1000_IRQ(void);
+extern void set_debug_traps(void);
+extern irq_cpustat_t irq_stat [NR_CPUS];
+
+static void setup_local_irq(unsigned int irq, int type, int int_req);
+static unsigned int startup_irq(unsigned int irq);
+static void end_irq(unsigned int irq_nr);
+static inline void mask_and_ack_level_irq(unsigned int irq_nr);
+static inline void mask_and_ack_rise_edge_irq(unsigned int irq_nr);
+static inline void mask_and_ack_fall_edge_irq(unsigned int irq_nr);
+static inline void mask_and_ack_either_edge_irq(unsigned int irq_nr);
+inline void local_enable_irq(unsigned int irq_nr);
+inline void local_disable_irq(unsigned int irq_nr);
+
+void (*board_init_irq)(void);
+
+#ifdef CONFIG_PM
+extern void counter0_irq(int irq, void *dev_id, struct pt_regs *regs);
+#endif
+
+static DEFINE_SPINLOCK(irq_lock);
+
+
+static unsigned int startup_irq(unsigned int irq_nr)
+{
+ local_enable_irq(irq_nr);
+ return 0;
+}
+
+
+static void shutdown_irq(unsigned int irq_nr)
+{
+ local_disable_irq(irq_nr);
+ return;
+}
+
+
+inline void local_enable_irq(unsigned int irq_nr)
+{
+ if (irq_nr > AU1000_LAST_INTC0_INT) {
+ au_writel(1<<(irq_nr-32), IC1_MASKSET);
+ au_writel(1<<(irq_nr-32), IC1_WAKESET);
+ }
+ else {
+ au_writel(1<<irq_nr, IC0_MASKSET);
+ au_writel(1<<irq_nr, IC0_WAKESET);
+ }
+ au_sync();
+}
+
+
+inline void local_disable_irq(unsigned int irq_nr)
+{
+ if (irq_nr > AU1000_LAST_INTC0_INT) {
+ au_writel(1<<(irq_nr-32), IC1_MASKCLR);
+ au_writel(1<<(irq_nr-32), IC1_WAKECLR);
+ }
+ else {
+ au_writel(1<<irq_nr, IC0_MASKCLR);
+ au_writel(1<<irq_nr, IC0_WAKECLR);
+ }
+ au_sync();
+}
+
+
+static inline void mask_and_ack_rise_edge_irq(unsigned int irq_nr)
+{
+ if (irq_nr > AU1000_LAST_INTC0_INT) {
+ au_writel(1<<(irq_nr-32), IC1_RISINGCLR);
+ au_writel(1<<(irq_nr-32), IC1_MASKCLR);
+ }
+ else {
+ au_writel(1<<irq_nr, IC0_RISINGCLR);
+ au_writel(1<<irq_nr, IC0_MASKCLR);
+ }
+ au_sync();
+}
+
+
+static inline void mask_and_ack_fall_edge_irq(unsigned int irq_nr)
+{
+ if (irq_nr > AU1000_LAST_INTC0_INT) {
+ au_writel(1<<(irq_nr-32), IC1_FALLINGCLR);
+ au_writel(1<<(irq_nr-32), IC1_MASKCLR);
+ }
+ else {
+ au_writel(1<<irq_nr, IC0_FALLINGCLR);
+ au_writel(1<<irq_nr, IC0_MASKCLR);
+ }
+ au_sync();
+}
+
+
+static inline void mask_and_ack_either_edge_irq(unsigned int irq_nr)
+{
+ /* This may assume that we don't get interrupts from
+ * both edges at once, or if we do, that we don't care.
+ */
+ if (irq_nr > AU1000_LAST_INTC0_INT) {
+ au_writel(1<<(irq_nr-32), IC1_FALLINGCLR);
+ au_writel(1<<(irq_nr-32), IC1_RISINGCLR);
+ au_writel(1<<(irq_nr-32), IC1_MASKCLR);
+ }
+ else {
+ au_writel(1<<irq_nr, IC0_FALLINGCLR);
+ au_writel(1<<irq_nr, IC0_RISINGCLR);
+ au_writel(1<<irq_nr, IC0_MASKCLR);
+ }
+ au_sync();
+}
+
+
+static inline void mask_and_ack_level_irq(unsigned int irq_nr)
+{
+
+ local_disable_irq(irq_nr);
+ au_sync();
+#if defined(CONFIG_MIPS_PB1000)
+ if (irq_nr == AU1000_GPIO_15) {
+ au_writel(0x8000, PB1000_MDR); /* ack int */
+ au_sync();
+ }
+#endif
+ return;
+}
+
+
+static void end_irq(unsigned int irq_nr)
+{
+ if (!(irq_desc[irq_nr].status & (IRQ_DISABLED|IRQ_INPROGRESS))) {
+ local_enable_irq(irq_nr);
+ }
+#if defined(CONFIG_MIPS_PB1000)
+ if (irq_nr == AU1000_GPIO_15) {
+ au_writel(0x4000, PB1000_MDR); /* enable int */
+ au_sync();
+ }
+#endif
+}
+
+unsigned long save_local_and_disable(int controller)
+{
+ int i;
+ unsigned long flags, mask;
+
+ spin_lock_irqsave(&irq_lock, flags);
+ if (controller) {
+ mask = au_readl(IC1_MASKSET);
+ for (i=32; i<64; i++) {
+ local_disable_irq(i);
+ }
+ }
+ else {
+ mask = au_readl(IC0_MASKSET);
+ for (i=0; i<32; i++) {
+ local_disable_irq(i);
+ }
+ }
+ spin_unlock_irqrestore(&irq_lock, flags);
+
+ return mask;
+}
+
+void restore_local_and_enable(int controller, unsigned long mask)
+{
+ int i;
+ unsigned long flags, new_mask;
+
+ spin_lock_irqsave(&irq_lock, flags);
+ for (i=0; i<32; i++) {
+ if (mask & (1<<i)) {
+ if (controller)
+ local_enable_irq(i+32);
+ else
+ local_enable_irq(i);
+ }
+ }
+ if (controller)
+ new_mask = au_readl(IC1_MASKSET);
+ else
+ new_mask = au_readl(IC0_MASKSET);
+
+ spin_unlock_irqrestore(&irq_lock, flags);
+}
+
+
+static struct hw_interrupt_type rise_edge_irq_type = {
+ "Au1000 Rise Edge",
+ startup_irq,
+ shutdown_irq,
+ local_enable_irq,
+ local_disable_irq,
+ mask_and_ack_rise_edge_irq,
+ end_irq,
+ NULL
+};
+
+static struct hw_interrupt_type fall_edge_irq_type = {
+ "Au1000 Fall Edge",
+ startup_irq,
+ shutdown_irq,
+ local_enable_irq,
+ local_disable_irq,
+ mask_and_ack_fall_edge_irq,
+ end_irq,
+ NULL
+};
+
+static struct hw_interrupt_type either_edge_irq_type = {
+ "Au1000 Rise or Fall Edge",
+ startup_irq,
+ shutdown_irq,
+ local_enable_irq,
+ local_disable_irq,
+ mask_and_ack_either_edge_irq,
+ end_irq,
+ NULL
+};
+
+static struct hw_interrupt_type level_irq_type = {
+ "Au1000 Level",
+ startup_irq,
+ shutdown_irq,
+ local_enable_irq,
+ local_disable_irq,
+ mask_and_ack_level_irq,
+ end_irq,
+ NULL
+};
+
+#ifdef CONFIG_PM
+void startup_match20_interrupt(void)
+{
+ local_enable_irq(AU1000_TOY_MATCH2_INT);
+}
+#endif
+
+static void setup_local_irq(unsigned int irq_nr, int type, int int_req)
+{
+ if (irq_nr > AU1000_MAX_INTR) return;
+ /* Config2[n], Config1[n], Config0[n] */
+ if (irq_nr > AU1000_LAST_INTC0_INT) {
+ switch (type) {
+ case INTC_INT_RISE_EDGE: /* 0:0:1 */
+ au_writel(1<<(irq_nr-32), IC1_CFG2CLR);
+ au_writel(1<<(irq_nr-32), IC1_CFG1CLR);
+ au_writel(1<<(irq_nr-32), IC1_CFG0SET);
+ irq_desc[irq_nr].handler = &rise_edge_irq_type;
+ break;
+ case INTC_INT_FALL_EDGE: /* 0:1:0 */
+ au_writel(1<<(irq_nr-32), IC1_CFG2CLR);
+ au_writel(1<<(irq_nr-32), IC1_CFG1SET);
+ au_writel(1<<(irq_nr-32), IC1_CFG0CLR);
+ irq_desc[irq_nr].handler = &fall_edge_irq_type;
+ break;
+ case INTC_INT_RISE_AND_FALL_EDGE: /* 0:1:1 */
+ au_writel(1<<(irq_nr-32), IC1_CFG2CLR);
+ au_writel(1<<(irq_nr-32), IC1_CFG1SET);
+ au_writel(1<<(irq_nr-32), IC1_CFG0SET);
+ irq_desc[irq_nr].handler = &either_edge_irq_type;
+ break;
+ case INTC_INT_HIGH_LEVEL: /* 1:0:1 */
+ au_writel(1<<(irq_nr-32), IC1_CFG2SET);
+ au_writel(1<<(irq_nr-32), IC1_CFG1CLR);
+ au_writel(1<<(irq_nr-32), IC1_CFG0SET);
+ irq_desc[irq_nr].handler = &level_irq_type;
+ break;
+ case INTC_INT_LOW_LEVEL: /* 1:1:0 */
+ au_writel(1<<(irq_nr-32), IC1_CFG2SET);
+ au_writel(1<<(irq_nr-32), IC1_CFG1SET);
+ au_writel(1<<(irq_nr-32), IC1_CFG0CLR);
+ irq_desc[irq_nr].handler = &level_irq_type;
+ break;
+ case INTC_INT_DISABLED: /* 0:0:0 */
+ au_writel(1<<(irq_nr-32), IC1_CFG0CLR);
+ au_writel(1<<(irq_nr-32), IC1_CFG1CLR);
+ au_writel(1<<(irq_nr-32), IC1_CFG2CLR);
+ break;
+ default: /* disable the interrupt */
+ printk("unexpected int type %d (irq %d)\n", type, irq_nr);
+ au_writel(1<<(irq_nr-32), IC1_CFG0CLR);
+ au_writel(1<<(irq_nr-32), IC1_CFG1CLR);
+ au_writel(1<<(irq_nr-32), IC1_CFG2CLR);
+ return;
+ }
+ if (int_req) /* assign to interrupt request 1 */
+ au_writel(1<<(irq_nr-32), IC1_ASSIGNCLR);
+ else /* assign to interrupt request 0 */
+ au_writel(1<<(irq_nr-32), IC1_ASSIGNSET);
+ au_writel(1<<(irq_nr-32), IC1_SRCSET);
+ au_writel(1<<(irq_nr-32), IC1_MASKCLR);
+ au_writel(1<<(irq_nr-32), IC1_WAKECLR);
+ }
+ else {
+ switch (type) {
+ case INTC_INT_RISE_EDGE: /* 0:0:1 */
+ au_writel(1<<irq_nr, IC0_CFG2CLR);
+ au_writel(1<<irq_nr, IC0_CFG1CLR);
+ au_writel(1<<irq_nr, IC0_CFG0SET);
+ irq_desc[irq_nr].handler = &rise_edge_irq_type;
+ break;
+ case INTC_INT_FALL_EDGE: /* 0:1:0 */
+ au_writel(1<<irq_nr, IC0_CFG2CLR);
+ au_writel(1<<irq_nr, IC0_CFG1SET);
+ au_writel(1<<irq_nr, IC0_CFG0CLR);
+ irq_desc[irq_nr].handler = &fall_edge_irq_type;
+ break;
+ case INTC_INT_RISE_AND_FALL_EDGE: /* 0:1:1 */
+ au_writel(1<<irq_nr, IC0_CFG2CLR);
+ au_writel(1<<irq_nr, IC0_CFG1SET);
+ au_writel(1<<irq_nr, IC0_CFG0SET);
+ irq_desc[irq_nr].handler = &either_edge_irq_type;
+ break;
+ case INTC_INT_HIGH_LEVEL: /* 1:0:1 */
+ au_writel(1<<irq_nr, IC0_CFG2SET);
+ au_writel(1<<irq_nr, IC0_CFG1CLR);
+ au_writel(1<<irq_nr, IC0_CFG0SET);
+ irq_desc[irq_nr].handler = &level_irq_type;
+ break;
+ case INTC_INT_LOW_LEVEL: /* 1:1:0 */
+ au_writel(1<<irq_nr, IC0_CFG2SET);
+ au_writel(1<<irq_nr, IC0_CFG1SET);
+ au_writel(1<<irq_nr, IC0_CFG0CLR);
+ irq_desc[irq_nr].handler = &level_irq_type;
+ break;
+ case INTC_INT_DISABLED: /* 0:0:0 */
+ au_writel(1<<irq_nr, IC0_CFG0CLR);
+ au_writel(1<<irq_nr, IC0_CFG1CLR);
+ au_writel(1<<irq_nr, IC0_CFG2CLR);
+ break;
+ default: /* disable the interrupt */
+ printk("unexpected int type %d (irq %d)\n", type, irq_nr);
+ au_writel(1<<irq_nr, IC0_CFG0CLR);
+ au_writel(1<<irq_nr, IC0_CFG1CLR);
+ au_writel(1<<irq_nr, IC0_CFG2CLR);
+ return;
+ }
+ if (int_req) /* assign to interrupt request 1 */
+ au_writel(1<<irq_nr, IC0_ASSIGNCLR);
+ else /* assign to interrupt request 0 */
+ au_writel(1<<irq_nr, IC0_ASSIGNSET);
+ au_writel(1<<irq_nr, IC0_SRCSET);
+ au_writel(1<<irq_nr, IC0_MASKCLR);
+ au_writel(1<<irq_nr, IC0_WAKECLR);
+ }
+ au_sync();
+}
+
+
+void __init arch_init_irq(void)
+{
+ int i;
+ unsigned long cp0_status;
+ au1xxx_irq_map_t *imp;
+ extern au1xxx_irq_map_t au1xxx_irq_map[];
+ extern au1xxx_irq_map_t au1xxx_ic0_map[];
+ extern int au1xxx_nr_irqs;
+ extern int au1xxx_ic0_nr_irqs;
+
+ cp0_status = read_c0_status();
+ memset(irq_desc, 0, sizeof(irq_desc));
+ set_except_vector(0, au1000_IRQ);
+
+ /* Initialize interrupt controllers to a safe state.
+ */
+ au_writel(0xffffffff, IC0_CFG0CLR);
+ au_writel(0xffffffff, IC0_CFG1CLR);
+ au_writel(0xffffffff, IC0_CFG2CLR);
+ au_writel(0xffffffff, IC0_MASKCLR);
+ au_writel(0xffffffff, IC0_ASSIGNSET);
+ au_writel(0xffffffff, IC0_WAKECLR);
+ au_writel(0xffffffff, IC0_SRCSET);
+ au_writel(0xffffffff, IC0_FALLINGCLR);
+ au_writel(0xffffffff, IC0_RISINGCLR);
+ au_writel(0x00000000, IC0_TESTBIT);
+
+ au_writel(0xffffffff, IC1_CFG0CLR);
+ au_writel(0xffffffff, IC1_CFG1CLR);
+ au_writel(0xffffffff, IC1_CFG2CLR);
+ au_writel(0xffffffff, IC1_MASKCLR);
+ au_writel(0xffffffff, IC1_ASSIGNSET);
+ au_writel(0xffffffff, IC1_WAKECLR);
+ au_writel(0xffffffff, IC1_SRCSET);
+ au_writel(0xffffffff, IC1_FALLINGCLR);
+ au_writel(0xffffffff, IC1_RISINGCLR);
+ au_writel(0x00000000, IC1_TESTBIT);
+
+ /* Initialize IC0, which is fixed per processor.
+ */
+ imp = au1xxx_ic0_map;
+ for (i=0; i<au1xxx_ic0_nr_irqs; i++) {
+ setup_local_irq(imp->im_irq, imp->im_type, imp->im_request);
+ imp++;
+ }
+
+ /* Now set up the irq mapping for the board.
+ */
+ imp = au1xxx_irq_map;
+ for (i=0; i<au1xxx_nr_irqs; i++) {
+ setup_local_irq(imp->im_irq, imp->im_type, imp->im_request);
+ imp++;
+ }
+
+ set_c0_status(ALLINTS);
+
+ /* Board specific IRQ initialization.
+ */
+ if (board_init_irq)
+ (*board_init_irq)();
+}
+
+
+/*
+ * Interrupts are nested. Even if an interrupt handler is registered
+ * as "fast", we might get another interrupt before we return from
+ * intcX_reqX_irqdispatch().
+ */
+
+void intc0_req0_irqdispatch(struct pt_regs *regs)
+{
+ int irq = 0;
+ static unsigned long intc0_req0 = 0;
+
+ intc0_req0 |= au_readl(IC0_REQ0INT);
+
+ if (!intc0_req0) return;
+
+ /*
+ * Because of the tight timing of SETUP token to reply
+ * transactions, the USB devices-side packet complete
+ * interrupt needs the highest priority.
+ */
+ if ((intc0_req0 & (1<<AU1000_USB_DEV_REQ_INT))) {
+ intc0_req0 &= ~(1<<AU1000_USB_DEV_REQ_INT);
+ do_IRQ(AU1000_USB_DEV_REQ_INT, regs);
+ return;
+ }
+
+ irq = au_ffs(intc0_req0) - 1;
+ intc0_req0 &= ~(1<<irq);
+ do_IRQ(irq, regs);
+}
+
+
+void intc0_req1_irqdispatch(struct pt_regs *regs)
+{
+ int irq = 0;
+ static unsigned long intc0_req1 = 0;
+
+ intc0_req1 |= au_readl(IC0_REQ1INT);
+
+ if (!intc0_req1) return;
+
+ irq = au_ffs(intc0_req1) - 1;
+ intc0_req1 &= ~(1<<irq);
+#ifdef CONFIG_PM
+ if (irq == AU1000_TOY_MATCH2_INT) {
+ mask_and_ack_rise_edge_irq(irq);
+ counter0_irq(irq, NULL, regs);
+ local_enable_irq(irq);
+ }
+ else
+#endif
+ {
+ do_IRQ(irq, regs);
+ }
+}
+
+
+/*
+ * Interrupt Controller 1:
+ * interrupts 32 - 63
+ */
+void intc1_req0_irqdispatch(struct pt_regs *regs)
+{
+ int irq = 0;
+ static unsigned long intc1_req0 = 0;
+
+ intc1_req0 |= au_readl(IC1_REQ0INT);
+
+ if (!intc1_req0) return;
+
+ irq = au_ffs(intc1_req0) - 1;
+ intc1_req0 &= ~(1<<irq);
+ irq += 32;
+ do_IRQ(irq, regs);
+}
+
+
+void intc1_req1_irqdispatch(struct pt_regs *regs)
+{
+ int irq = 0;
+ static unsigned long intc1_req1 = 0;
+
+ intc1_req1 |= au_readl(IC1_REQ1INT);
+
+ if (!intc1_req1) return;
+
+ irq = au_ffs(intc1_req1) - 1;
+ intc1_req1 &= ~(1<<irq);
+ irq += 32;
+ do_IRQ(irq, regs);
+}
+
+#ifdef CONFIG_PM
+
+/* Save/restore the interrupt controller state.
+ * Called from the save/restore core registers as part of the
+ * au_sleep function in power.c.....maybe I should just pm_register()
+ * them instead?
+ */
+static uint sleep_intctl_config0[2];
+static uint sleep_intctl_config1[2];
+static uint sleep_intctl_config2[2];
+static uint sleep_intctl_src[2];
+static uint sleep_intctl_assign[2];
+static uint sleep_intctl_wake[2];
+static uint sleep_intctl_mask[2];
+
+void
+save_au1xxx_intctl(void)
+{
+ sleep_intctl_config0[0] = au_readl(IC0_CFG0RD);
+ sleep_intctl_config1[0] = au_readl(IC0_CFG1RD);
+ sleep_intctl_config2[0] = au_readl(IC0_CFG2RD);
+ sleep_intctl_src[0] = au_readl(IC0_SRCRD);
+ sleep_intctl_assign[0] = au_readl(IC0_ASSIGNRD);
+ sleep_intctl_wake[0] = au_readl(IC0_WAKERD);
+ sleep_intctl_mask[0] = au_readl(IC0_MASKRD);
+
+ sleep_intctl_config0[1] = au_readl(IC1_CFG0RD);
+ sleep_intctl_config1[1] = au_readl(IC1_CFG1RD);
+ sleep_intctl_config2[1] = au_readl(IC1_CFG2RD);
+ sleep_intctl_src[1] = au_readl(IC1_SRCRD);
+ sleep_intctl_assign[1] = au_readl(IC1_ASSIGNRD);
+ sleep_intctl_wake[1] = au_readl(IC1_WAKERD);
+ sleep_intctl_mask[1] = au_readl(IC1_MASKRD);
+}
+
+/* For most restore operations, we clear the entire register and
+ * then set the bits we found during the save.
+ */
+void
+restore_au1xxx_intctl(void)
+{
+ au_writel(0xffffffff, IC0_MASKCLR); au_sync();
+
+ au_writel(0xffffffff, IC0_CFG0CLR); au_sync();
+ au_writel(sleep_intctl_config0[0], IC0_CFG0SET); au_sync();
+ au_writel(0xffffffff, IC0_CFG1CLR); au_sync();
+ au_writel(sleep_intctl_config1[0], IC0_CFG1SET); au_sync();
+ au_writel(0xffffffff, IC0_CFG2CLR); au_sync();
+ au_writel(sleep_intctl_config2[0], IC0_CFG2SET); au_sync();
+ au_writel(0xffffffff, IC0_SRCCLR); au_sync();
+ au_writel(sleep_intctl_src[0], IC0_SRCSET); au_sync();
+ au_writel(0xffffffff, IC0_ASSIGNCLR); au_sync();
+ au_writel(sleep_intctl_assign[0], IC0_ASSIGNSET); au_sync();
+ au_writel(0xffffffff, IC0_WAKECLR); au_sync();
+ au_writel(sleep_intctl_wake[0], IC0_WAKESET); au_sync();
+ au_writel(0xffffffff, IC0_RISINGCLR); au_sync();
+ au_writel(0xffffffff, IC0_FALLINGCLR); au_sync();
+ au_writel(0x00000000, IC0_TESTBIT); au_sync();
+
+ au_writel(0xffffffff, IC1_MASKCLR); au_sync();
+
+ au_writel(0xffffffff, IC1_CFG0CLR); au_sync();
+ au_writel(sleep_intctl_config0[1], IC1_CFG0SET); au_sync();
+ au_writel(0xffffffff, IC1_CFG1CLR); au_sync();
+ au_writel(sleep_intctl_config1[1], IC1_CFG1SET); au_sync();
+ au_writel(0xffffffff, IC1_CFG2CLR); au_sync();
+ au_writel(sleep_intctl_config2[1], IC1_CFG2SET); au_sync();
+ au_writel(0xffffffff, IC1_SRCCLR); au_sync();
+ au_writel(sleep_intctl_src[1], IC1_SRCSET); au_sync();
+ au_writel(0xffffffff, IC1_ASSIGNCLR); au_sync();
+ au_writel(sleep_intctl_assign[1], IC1_ASSIGNSET); au_sync();
+ au_writel(0xffffffff, IC1_WAKECLR); au_sync();
+ au_writel(sleep_intctl_wake[1], IC1_WAKESET); au_sync();
+ au_writel(0xffffffff, IC1_RISINGCLR); au_sync();
+ au_writel(0xffffffff, IC1_FALLINGCLR); au_sync();
+ au_writel(0x00000000, IC1_TESTBIT); au_sync();
+
+ au_writel(sleep_intctl_mask[1], IC1_MASKSET); au_sync();
+
+ au_writel(sleep_intctl_mask[0], IC0_MASKSET); au_sync();
+}
+#endif /* CONFIG_PM */
diff --git a/arch/mips/au1000/common/pci.c b/arch/mips/au1000/common/pci.c
new file mode 100644
index 0000000..533721e
--- /dev/null
+++ b/arch/mips/au1000/common/pci.c
@@ -0,0 +1,97 @@
+/*
+ * BRIEF MODULE DESCRIPTION
+ * Alchemy/AMD Au1x00 pci support.
+ *
+ * Copyright 2001,2002,2003 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ * ppopov@mvista.com or source@mvista.com
+ *
+ * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org)
+ *
+ * Support for all devices (greater than 16) added by David Gathright.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/mach-au1x00/au1000.h>
+
+/* TBD */
+static struct resource pci_io_resource = {
+ "pci IO space",
+ (u32)PCI_IO_START,
+ (u32)PCI_IO_END,
+ IORESOURCE_IO
+};
+
+static struct resource pci_mem_resource = {
+ "pci memory space",
+ (u32)PCI_MEM_START,
+ (u32)PCI_MEM_END,
+ IORESOURCE_MEM
+};
+
+extern struct pci_ops au1x_pci_ops;
+
+static struct pci_controller au1x_controller = {
+ .pci_ops = &au1x_pci_ops,
+ .io_resource = &pci_io_resource,
+ .mem_resource = &pci_mem_resource,
+};
+
+#if defined(CONFIG_SOC_AU1500) || defined(CONFIG_SOC_AU1550)
+static unsigned long virt_io_addr;
+#endif
+
+static int __init au1x_pci_setup(void)
+{
+#if defined(CONFIG_SOC_AU1500) || defined(CONFIG_SOC_AU1550)
+ virt_io_addr = (unsigned long)ioremap(Au1500_PCI_IO_START,
+ Au1500_PCI_IO_END - Au1500_PCI_IO_START + 1);
+
+ if (!virt_io_addr) {
+ printk(KERN_ERR "Unable to ioremap pci space\n");
+ return 1;
+ }
+
+#ifdef CONFIG_DMA_NONCOHERENT
+ /*
+ * Set the NC bit in controller for Au1500 pre-AC silicon
+ */
+ u32 prid = read_c0_prid();
+ if ( (prid & 0xFF000000) == 0x01000000 && prid < 0x01030202) {
+ au_writel( 1<<16 | au_readl(Au1500_PCI_CFG), Au1500_PCI_CFG);
+ printk("Non-coherent PCI accesses enabled\n");
+ }
+#endif
+
+ set_io_port_base(virt_io_addr);
+#endif
+
+ register_pci_controller(&au1x_controller);
+ return 0;
+}
+
+arch_initcall(au1x_pci_setup);
diff --git a/arch/mips/au1000/common/platform.c b/arch/mips/au1000/common/platform.c
new file mode 100644
index 0000000..0776b2d
--- /dev/null
+++ b/arch/mips/au1000/common/platform.c
@@ -0,0 +1,53 @@
+/*
+ * Platform device support for Au1x00 SoCs.
+ *
+ * Copyright 2004, Matt Porter <mporter@kernel.crashing.org>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/resource.h>
+
+#include <asm/mach-au1x00/au1000.h>
+
+static struct resource au1xxx_usb_ohci_resources[] = {
+ [0] = {
+ .start = USB_OHCI_BASE,
+ .end = USB_OHCI_BASE + USB_OHCI_LEN,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = AU1000_USB_HOST_INT,
+ .end = AU1000_USB_HOST_INT,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+/* The dmamask must be set for OHCI to work */
+static u64 ohci_dmamask = ~(u32)0;
+
+static struct platform_device au1xxx_usb_ohci_device = {
+ .name = "au1xxx-ohci",
+ .id = 0,
+ .dev = {
+ .dma_mask = &ohci_dmamask,
+ .coherent_dma_mask = 0xffffffff,
+ },
+ .num_resources = ARRAY_SIZE(au1xxx_usb_ohci_resources),
+ .resource = au1xxx_usb_ohci_resources,
+};
+
+static struct platform_device *au1xxx_platform_devices[] __initdata = {
+ &au1xxx_usb_ohci_device,
+};
+
+int au1xxx_platform_init(void)
+{
+ return platform_add_devices(au1xxx_platform_devices, ARRAY_SIZE(au1xxx_platform_devices));
+}
+
+arch_initcall(au1xxx_platform_init);
diff --git a/arch/mips/au1000/common/power.c b/arch/mips/au1000/common/power.c
new file mode 100644
index 0000000..c40dacc
--- /dev/null
+++ b/arch/mips/au1000/common/power.c
@@ -0,0 +1,493 @@
+/*
+ * BRIEF MODULE DESCRIPTION
+ * Au1000 Power Management routines.
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ * ppopov@mvista.com or source@mvista.com
+ *
+ * Some of the routines are right out of init/main.c, whose
+ * copyrights apply here.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/pm.h>
+#include <linux/slab.h>
+#include <linux/sysctl.h>
+
+#include <asm/string.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/mach-au1x00/au1000.h>
+
+#ifdef CONFIG_PM
+
+#define DEBUG 1
+#ifdef DEBUG
+# define DPRINTK(fmt, args...) printk("%s: " fmt, __FUNCTION__ , ## args)
+#else
+# define DPRINTK(fmt, args...)
+#endif
+
+static void calibrate_delay(void);
+
+extern void set_au1x00_speed(unsigned int new_freq);
+extern unsigned int get_au1x00_speed(void);
+extern unsigned long get_au1x00_uart_baud_base(void);
+extern void set_au1x00_uart_baud_base(unsigned long new_baud_base);
+extern unsigned long save_local_and_disable(int controller);
+extern void restore_local_and_enable(int controller, unsigned long mask);
+extern void local_enable_irq(unsigned int irq_nr);
+
+/* Quick acpi hack. This will have to change! */
+#define CTL_ACPI 9999
+#define ACPI_S1_SLP_TYP 19
+#define ACPI_SLEEP 21
+
+
+static DEFINE_SPINLOCK(pm_lock);
+
+/* We need to save/restore a bunch of core registers that are
+ * either volatile or reset to some state across a processor sleep.
+ * If reading a register doesn't provide a proper result for a
+ * later restore, we have to provide a function for loading that
+ * register and save a copy.
+ *
+ * We only have to save/restore registers that aren't otherwise
+ * done as part of a driver pm_* function.
+ */
+static uint sleep_aux_pll_cntrl;
+static uint sleep_cpu_pll_cntrl;
+static uint sleep_pin_function;
+static uint sleep_uart0_inten;
+static uint sleep_uart0_fifoctl;
+static uint sleep_uart0_linectl;
+static uint sleep_uart0_clkdiv;
+static uint sleep_uart0_enable;
+static uint sleep_usbhost_enable;
+static uint sleep_usbdev_enable;
+static uint sleep_static_memctlr[4][3];
+
+/* Define this to cause the value you write to /proc/sys/pm/sleep to
+ * set the TOY timer for the amount of time you want to sleep.
+ * This is done mainly for testing, but may be useful in other cases.
+ * The value is number of 32KHz ticks to sleep.
+ */
+#define SLEEP_TEST_TIMEOUT 1
+#ifdef SLEEP_TEST_TIMEOUT
+static int sleep_ticks;
+void wakeup_counter0_set(int ticks);
+#endif
+
+static void
+save_core_regs(void)
+{
+ extern void save_au1xxx_intctl(void);
+ extern void pm_eth0_shutdown(void);
+
+ /* Do the serial ports.....these really should be a pm_*
+ * registered function by the driver......but of course the
+ * standard serial driver doesn't understand our Au1xxx
+ * unique registers.
+ */
+ sleep_uart0_inten = au_readl(UART0_ADDR + UART_IER);
+ sleep_uart0_fifoctl = au_readl(UART0_ADDR + UART_FCR);
+ sleep_uart0_linectl = au_readl(UART0_ADDR + UART_LCR);
+ sleep_uart0_clkdiv = au_readl(UART0_ADDR + UART_CLK);
+ sleep_uart0_enable = au_readl(UART0_ADDR + UART_MOD_CNTRL);
+
+ /* Shutdown USB host/device.
+ */
+ sleep_usbhost_enable = au_readl(USB_HOST_CONFIG);
+
+ /* There appears to be some undocumented reset register....
+ */
+ au_writel(0, 0xb0100004); au_sync();
+ au_writel(0, USB_HOST_CONFIG); au_sync();
+
+ sleep_usbdev_enable = au_readl(USBD_ENABLE);
+ au_writel(0, USBD_ENABLE); au_sync();
+
+ /* Save interrupt controller state.
+ */
+ save_au1xxx_intctl();
+
+ /* Clocks and PLLs.
+ */
+ sleep_aux_pll_cntrl = au_readl(SYS_AUXPLL);
+
+ /* We don't really need to do this one, but unless we
+ * write it again it won't have a valid value if we
+ * happen to read it.
+ */
+ sleep_cpu_pll_cntrl = au_readl(SYS_CPUPLL);
+
+ sleep_pin_function = au_readl(SYS_PINFUNC);
+
+ /* Save the static memory controller configuration.
+ */
+ sleep_static_memctlr[0][0] = au_readl(MEM_STCFG0);
+ sleep_static_memctlr[0][1] = au_readl(MEM_STTIME0);
+ sleep_static_memctlr[0][2] = au_readl(MEM_STADDR0);
+ sleep_static_memctlr[1][0] = au_readl(MEM_STCFG1);
+ sleep_static_memctlr[1][1] = au_readl(MEM_STTIME1);
+ sleep_static_memctlr[1][2] = au_readl(MEM_STADDR1);
+ sleep_static_memctlr[2][0] = au_readl(MEM_STCFG2);
+ sleep_static_memctlr[2][1] = au_readl(MEM_STTIME2);
+ sleep_static_memctlr[2][2] = au_readl(MEM_STADDR2);
+ sleep_static_memctlr[3][0] = au_readl(MEM_STCFG3);
+ sleep_static_memctlr[3][1] = au_readl(MEM_STTIME3);
+ sleep_static_memctlr[3][2] = au_readl(MEM_STADDR3);
+}
+
+static void
+restore_core_regs(void)
+{
+ extern void restore_au1xxx_intctl(void);
+ extern void wakeup_counter0_adjust(void);
+
+ au_writel(sleep_aux_pll_cntrl, SYS_AUXPLL); au_sync();
+ au_writel(sleep_cpu_pll_cntrl, SYS_CPUPLL); au_sync();
+ au_writel(sleep_pin_function, SYS_PINFUNC); au_sync();
+
+ /* Restore the static memory controller configuration.
+ */
+ au_writel(sleep_static_memctlr[0][0], MEM_STCFG0);
+ au_writel(sleep_static_memctlr[0][1], MEM_STTIME0);
+ au_writel(sleep_static_memctlr[0][2], MEM_STADDR0);
+ au_writel(sleep_static_memctlr[1][0], MEM_STCFG1);
+ au_writel(sleep_static_memctlr[1][1], MEM_STTIME1);
+ au_writel(sleep_static_memctlr[1][2], MEM_STADDR1);
+ au_writel(sleep_static_memctlr[2][0], MEM_STCFG2);
+ au_writel(sleep_static_memctlr[2][1], MEM_STTIME2);
+ au_writel(sleep_static_memctlr[2][2], MEM_STADDR2);
+ au_writel(sleep_static_memctlr[3][0], MEM_STCFG3);
+ au_writel(sleep_static_memctlr[3][1], MEM_STTIME3);
+ au_writel(sleep_static_memctlr[3][2], MEM_STADDR3);
+
+ /* Enable the UART if it was enabled before sleep.
+ * I guess I should define module control bits........
+ */
+ if (sleep_uart0_enable & 0x02) {
+ au_writel(0, UART0_ADDR + UART_MOD_CNTRL); au_sync();
+ au_writel(1, UART0_ADDR + UART_MOD_CNTRL); au_sync();
+ au_writel(3, UART0_ADDR + UART_MOD_CNTRL); au_sync();
+ au_writel(sleep_uart0_inten, UART0_ADDR + UART_IER); au_sync();
+ au_writel(sleep_uart0_fifoctl, UART0_ADDR + UART_FCR); au_sync();
+ au_writel(sleep_uart0_linectl, UART0_ADDR + UART_LCR); au_sync();
+ au_writel(sleep_uart0_clkdiv, UART0_ADDR + UART_CLK); au_sync();
+ }
+
+ restore_au1xxx_intctl();
+ wakeup_counter0_adjust();
+}
+
+unsigned long suspend_mode;
+
+void wakeup_from_suspend(void)
+{
+ suspend_mode = 0;
+}
+
+int au_sleep(void)
+{
+ unsigned long wakeup, flags;
+ extern void save_and_sleep(void);
+
+ spin_lock_irqsave(&pm_lock,flags);
+
+ save_core_regs();
+
+ flush_cache_all();
+
+ /** The code below is all system dependent and we should probably
+ ** have a function call out of here to set this up. You need
+ ** to configure the GPIO or timer interrupts that will bring
+ ** you out of sleep.
+ ** For testing, the TOY counter wakeup is useful.
+ **/
+
+#if 0
+ au_writel(au_readl(SYS_PINSTATERD) & ~(1 << 11), SYS_PINSTATERD);
+
+ /* gpio 6 can cause a wake up event */
+ wakeup = au_readl(SYS_WAKEMSK);
+ wakeup &= ~(1 << 8); /* turn off match20 wakeup */
+ wakeup |= 1 << 6; /* turn on gpio 6 wakeup */
+#else
+ /* For testing, allow match20 to wake us up.
+ */
+#ifdef SLEEP_TEST_TIMEOUT
+ wakeup_counter0_set(sleep_ticks);
+#endif
+ wakeup = 1 << 8; /* turn on match20 wakeup */
+ wakeup = 0;
+#endif
+ au_writel(1, SYS_WAKESRC); /* clear cause */
+ au_sync();
+ au_writel(wakeup, SYS_WAKEMSK);
+ au_sync();
+
+ save_and_sleep();
+
+ /* after a wakeup, the cpu vectors back to 0x1fc00000 so
+ * it's up to the boot code to get us back here.
+ */
+ restore_core_regs();
+ spin_unlock_irqrestore(&pm_lock, flags);
+ return 0;
+}
+
+static int pm_do_sleep(ctl_table * ctl, int write, struct file *file,
+ void *buffer, size_t * len)
+{
+ int retval = 0;
+#ifdef SLEEP_TEST_TIMEOUT
+#define TMPBUFLEN2 16
+ char buf[TMPBUFLEN2], *p;
+#endif
+
+ if (!write) {
+ *len = 0;
+ } else {
+#ifdef SLEEP_TEST_TIMEOUT
+ if (*len > TMPBUFLEN2 - 1) {
+ return -EFAULT;
+ }
+ if (copy_from_user(buf, buffer, *len)) {
+ return -EFAULT;
+ }
+ buf[*len] = 0;
+ p = buf;
+ sleep_ticks = simple_strtoul(p, &p, 0);
+#endif
+ retval = pm_send_all(PM_SUSPEND, (void *) 2);
+
+ if (retval)
+ return retval;
+
+ au_sleep();
+ retval = pm_send_all(PM_RESUME, (void *) 0);
+ }
+ return retval;
+}
+
+static int pm_do_suspend(ctl_table * ctl, int write, struct file *file,
+ void *buffer, size_t * len)
+{
+ int retval = 0;
+ void au1k_wait(void);
+
+ if (!write) {
+ *len = 0;
+ } else {
+ retval = pm_send_all(PM_SUSPEND, (void *) 2);
+ if (retval)
+ return retval;
+ suspend_mode = 1;
+ au1k_wait();
+ retval = pm_send_all(PM_RESUME, (void *) 0);
+ }
+ return retval;
+}
+
+
+static int pm_do_freq(ctl_table * ctl, int write, struct file *file,
+ void *buffer, size_t * len)
+{
+ int retval = 0, i;
+ unsigned long val, pll;
+#define TMPBUFLEN 64
+#define MAX_CPU_FREQ 396
+ char buf[TMPBUFLEN], *p;
+ unsigned long flags, intc0_mask, intc1_mask;
+ unsigned long old_baud_base, old_cpu_freq, baud_rate, old_clk,
+ old_refresh;
+ unsigned long new_baud_base, new_cpu_freq, new_clk, new_refresh;
+
+ spin_lock_irqsave(&pm_lock, flags);
+ if (!write) {
+ *len = 0;
+ } else {
+ /* Parse the new frequency */
+ if (*len > TMPBUFLEN - 1) {
+ spin_unlock_irqrestore(&pm_lock, flags);
+ return -EFAULT;
+ }
+ if (copy_from_user(buf, buffer, *len)) {
+ spin_unlock_irqrestore(&pm_lock, flags);
+ return -EFAULT;
+ }
+ buf[*len] = 0;
+ p = buf;
+ val = simple_strtoul(p, &p, 0);
+ if (val > MAX_CPU_FREQ) {
+ spin_unlock_irqrestore(&pm_lock, flags);
+ return -EFAULT;
+ }
+
+ pll = val / 12;
+ if ((pll > 33) || (pll < 7)) { /* 396 MHz max, 84 MHz min */
+ /* revisit this for higher speed cpus */
+ spin_unlock_irqrestore(&pm_lock, flags);
+ return -EFAULT;
+ }
+
+ old_baud_base = get_au1x00_uart_baud_base();
+ old_cpu_freq = get_au1x00_speed();
+
+ new_cpu_freq = pll * 12 * 1000000;
+ new_baud_base = (new_cpu_freq / (2 * ((int)(au_readl(SYS_POWERCTRL)&0x03) + 2) * 16));
+ set_au1x00_speed(new_cpu_freq);
+ set_au1x00_uart_baud_base(new_baud_base);
+
+ old_refresh = au_readl(MEM_SDREFCFG) & 0x1ffffff;
+ new_refresh =
+ ((old_refresh * new_cpu_freq) /
+ old_cpu_freq) | (au_readl(MEM_SDREFCFG) & ~0x1ffffff);
+
+ au_writel(pll, SYS_CPUPLL);
+ au_sync_delay(1);
+ au_writel(new_refresh, MEM_SDREFCFG);
+ au_sync_delay(1);
+
+ for (i = 0; i < 4; i++) {
+ if (au_readl
+ (UART_BASE + UART_MOD_CNTRL +
+ i * 0x00100000) == 3) {
+ old_clk =
+ au_readl(UART_BASE + UART_CLK +
+ i * 0x00100000);
+ // baud_rate = baud_base/clk
+ baud_rate = old_baud_base / old_clk;
+ /* we won't get an exact baud rate and the error
+ * could be significant enough that our new
+ * calculation will result in a clock that will
+ * give us a baud rate that's too far off from
+ * what we really want.
+ */
+ if (baud_rate > 100000)
+ baud_rate = 115200;
+ else if (baud_rate > 50000)
+ baud_rate = 57600;
+ else if (baud_rate > 30000)
+ baud_rate = 38400;
+ else if (baud_rate > 17000)
+ baud_rate = 19200;
+ else
+ (baud_rate = 9600);
+ // new_clk = new_baud_base/baud_rate
+ new_clk = new_baud_base / baud_rate;
+ au_writel(new_clk,
+ UART_BASE + UART_CLK +
+ i * 0x00100000);
+ au_sync_delay(10);
+ }
+ }
+ }
+
+
+ /* We don't want _any_ interrupts other than
+ * match20. Otherwise our calibrate_delay()
+ * calculation will be off, potentially a lot.
+ */
+ intc0_mask = save_local_and_disable(0);
+ intc1_mask = save_local_and_disable(1);
+ local_enable_irq(AU1000_TOY_MATCH2_INT);
+ spin_unlock_irqrestore(&pm_lock, flags);
+ calibrate_delay();
+ restore_local_and_enable(0, intc0_mask);
+ restore_local_and_enable(1, intc1_mask);
+ return retval;
+}
+
+
+static struct ctl_table pm_table[] = {
+ {ACPI_S1_SLP_TYP, "suspend", NULL, 0, 0600, NULL, &pm_do_suspend},
+ {ACPI_SLEEP, "sleep", NULL, 0, 0600, NULL, &pm_do_sleep},
+ {CTL_ACPI, "freq", NULL, 0, 0600, NULL, &pm_do_freq},
+ {0}
+};
+
+static struct ctl_table pm_dir_table[] = {
+ {CTL_ACPI, "pm", NULL, 0, 0555, pm_table},
+ {0}
+};
+
+/*
+ * Initialize power interface
+ */
+static int __init pm_init(void)
+{
+ register_sysctl_table(pm_dir_table, 1);
+ return 0;
+}
+
+__initcall(pm_init);
+
+
+/*
+ * This is right out of init/main.c
+ */
+
+/* This is the number of bits of precision for the loops_per_jiffy. Each
+ bit takes on average 1.5/HZ seconds. This (like the original) is a little
+ better than 1% */
+#define LPS_PREC 8
+
+static void calibrate_delay(void)
+{
+ unsigned long ticks, loopbit;
+ int lps_precision = LPS_PREC;
+
+ loops_per_jiffy = (1 << 12);
+
+ while (loops_per_jiffy <<= 1) {
+ /* wait for "start of" clock tick */
+ ticks = jiffies;
+ while (ticks == jiffies)
+ /* nothing */ ;
+ /* Go .. */
+ ticks = jiffies;
+ __delay(loops_per_jiffy);
+ ticks = jiffies - ticks;
+ if (ticks)
+ break;
+ }
+
+/* Do a binary approximation to get loops_per_jiffy set to equal one clock
+ (up to lps_precision bits) */
+ loops_per_jiffy >>= 1;
+ loopbit = loops_per_jiffy;
+ while (lps_precision-- && (loopbit >>= 1)) {
+ loops_per_jiffy |= loopbit;
+ ticks = jiffies;
+ while (ticks == jiffies);
+ ticks = jiffies;
+ __delay(loops_per_jiffy);
+ if (jiffies != ticks) /* longer than 1 tick */
+ loops_per_jiffy &= ~loopbit;
+ }
+}
+#endif /* CONFIG_PM */
diff --git a/arch/mips/au1000/common/prom.c b/arch/mips/au1000/common/prom.c
new file mode 100644
index 0000000..22e5a85
--- /dev/null
+++ b/arch/mips/au1000/common/prom.c
@@ -0,0 +1,162 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ * PROM library initialisation code, assuming a version of
+ * pmon is the boot code.
+ *
+ * Copyright 2000,2001 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ * ppopov@mvista.com or source@mvista.com
+ *
+ * This file was derived from Carsten Langgaard's
+ * arch/mips/mips-boards/xx files.
+ *
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/string.h>
+
+#include <asm/bootinfo.h>
+
+/* #define DEBUG_CMDLINE */
+
+extern int prom_argc;
+extern char **prom_argv, **prom_envp;
+
+typedef struct
+{
+ char *name;
+/* char *val; */
+}t_env_var;
+
+
+char * prom_getcmdline(void)
+{
+ return &(arcs_cmdline[0]);
+}
+
+void prom_init_cmdline(void)
+{
+ char *cp;
+ int actr;
+
+ actr = 1; /* Always ignore argv[0] */
+
+ cp = &(arcs_cmdline[0]);
+ while(actr < prom_argc) {
+ strcpy(cp, prom_argv[actr]);
+ cp += strlen(prom_argv[actr]);
+ *cp++ = ' ';
+ actr++;
+ }
+ if (cp != &(arcs_cmdline[0])) /* get rid of trailing space */
+ --cp;
+ *cp = '\0';
+
+}
+
+
+char *prom_getenv(char *envname)
+{
+ /*
+ * Return a pointer to the given environment variable.
+ * Environment variables are stored in the form of "memsize=64".
+ */
+
+ t_env_var *env = (t_env_var *)prom_envp;
+ int i;
+
+ i = strlen(envname);
+
+ while(env->name) {
+ if(strncmp(envname, env->name, i) == 0) {
+ return(env->name + strlen(envname) + 1);
+ }
+ env++;
+ }
+ return(NULL);
+}
+
+inline unsigned char str2hexnum(unsigned char c)
+{
+ if(c >= '0' && c <= '9')
+ return c - '0';
+ if(c >= 'a' && c <= 'f')
+ return c - 'a' + 10;
+ if(c >= 'A' && c <= 'F')
+ return c - 'A' + 10;
+ return 0; /* foo */
+}
+
+inline void str2eaddr(unsigned char *ea, unsigned char *str)
+{
+ int i;
+
+ for(i = 0; i < 6; i++) {
+ unsigned char num;
+
+ if((*str == '.') || (*str == ':'))
+ str++;
+ num = str2hexnum(*str++) << 4;
+ num |= (str2hexnum(*str++));
+ ea[i] = num;
+ }
+}
+
+int get_ethernet_addr(char *ethernet_addr)
+{
+ char *ethaddr_str;
+
+ ethaddr_str = prom_getenv("ethaddr");
+ if (!ethaddr_str) {
+ printk("ethaddr not set in boot prom\n");
+ return -1;
+ }
+ str2eaddr(ethernet_addr, ethaddr_str);
+
+#if 0
+ {
+ int i;
+
+ printk("get_ethernet_addr: ");
+ for (i=0; i<5; i++)
+ printk("%02x:", (unsigned char)*(ethernet_addr+i));
+ printk("%02x\n", *(ethernet_addr+i));
+ }
+#endif
+
+ return 0;
+}
+
+unsigned long __init prom_free_prom_memory(void)
+{
+ return 0;
+}
+
+EXPORT_SYMBOL(prom_getcmdline);
+EXPORT_SYMBOL(get_ethernet_addr);
+EXPORT_SYMBOL(str2eaddr);
diff --git a/arch/mips/au1000/common/puts.c b/arch/mips/au1000/common/puts.c
new file mode 100644
index 0000000..c2ae462
--- /dev/null
+++ b/arch/mips/au1000/common/puts.c
@@ -0,0 +1,145 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ * Low level uart routines to directly access a 16550 uart.
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ * ppopov@mvista.com or source@mvista.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/types.h>
+#include <asm/mach-au1x00/au1000.h>
+
+#define SERIAL_BASE UART_BASE
+#define SER_CMD 0x7
+#define SER_DATA 0x1
+#define TX_BUSY 0x20
+
+#define TIMEOUT 0xffffff
+#define SLOW_DOWN
+
+static const char digits[16] = "0123456789abcdef";
+static volatile unsigned long * const com1 = (unsigned long *)SERIAL_BASE;
+
+
+#ifdef SLOW_DOWN
+static inline void slow_down(void)
+{
+ int k;
+ for (k=0; k<10000; k++);
+}
+#else
+#define slow_down()
+#endif
+
+void
+putch(const unsigned char c)
+{
+ unsigned char ch;
+ int i = 0;
+
+ do {
+ ch = com1[SER_CMD];
+ slow_down();
+ i++;
+ if (i>TIMEOUT) {
+ break;
+ }
+ } while (0 == (ch & TX_BUSY));
+ com1[SER_DATA] = c;
+}
+
+void
+puts(unsigned char *cp)
+{
+ unsigned char ch;
+ int i = 0;
+
+ while (*cp) {
+ do {
+ ch = com1[SER_CMD];
+ slow_down();
+ i++;
+ if (i>TIMEOUT) {
+ break;
+ }
+ } while (0 == (ch & TX_BUSY));
+ com1[SER_DATA] = *cp++;
+ }
+ putch('\r');
+ putch('\n');
+}
+
+void
+fputs(const char *cp)
+{
+ unsigned char ch;
+ int i = 0;
+
+ while (*cp) {
+
+ do {
+ ch = com1[SER_CMD];
+ slow_down();
+ i++;
+ if (i>TIMEOUT) {
+ break;
+ }
+ } while (0 == (ch & TX_BUSY));
+ com1[SER_DATA] = *cp++;
+ }
+}
+
+
+void
+put64(uint64_t ul)
+{
+ int cnt;
+ unsigned ch;
+
+ cnt = 16; /* 16 nibbles in a 64 bit long */
+ putch('0');
+ putch('x');
+ do {
+ cnt--;
+ ch = (unsigned char)(ul >> cnt * 4) & 0x0F;
+ putch(digits[ch]);
+ } while (cnt > 0);
+}
+
+void
+put32(unsigned u)
+{
+ int cnt;
+ unsigned ch;
+
+ cnt = 8; /* 8 nibbles in a 32 bit long */
+ putch('0');
+ putch('x');
+ do {
+ cnt--;
+ ch = (unsigned char)(u >> cnt * 4) & 0x0F;
+ putch(digits[ch]);
+ } while (cnt > 0);
+}
diff --git a/arch/mips/au1000/common/reset.c b/arch/mips/au1000/common/reset.c
new file mode 100644
index 0000000..65b84db
--- /dev/null
+++ b/arch/mips/au1000/common/reset.c
@@ -0,0 +1,195 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ * Au1000 reset routines.
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ * ppopov@mvista.com or source@mvista.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/config.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/reboot.h>
+#include <asm/system.h>
+#include <asm/mach-au1x00/au1000.h>
+
+extern int au_sleep(void);
+extern void (*flush_cache_all)(void);
+
+void au1000_restart(char *command)
+{
+ /* Set all integrated peripherals to disabled states */
+ extern void board_reset (void);
+ u32 prid = read_c0_prid();
+
+ printk(KERN_NOTICE "\n** Resetting Integrated Peripherals\n");
+ switch (prid & 0xFF000000)
+ {
+ case 0x00000000: /* Au1000 */
+ au_writel(0x02, 0xb0000010); /* ac97_enable */
+ au_writel(0x08, 0xb017fffc); /* usbh_enable - early errata */
+ asm("sync");
+ au_writel(0x00, 0xb017fffc); /* usbh_enable */
+ au_writel(0x00, 0xb0200058); /* usbd_enable */
+ au_writel(0x00, 0xb0300040); /* ir_enable */
+ au_writel(0x00, 0xb4004104); /* mac dma */
+ au_writel(0x00, 0xb4004114); /* mac dma */
+ au_writel(0x00, 0xb4004124); /* mac dma */
+ au_writel(0x00, 0xb4004134); /* mac dma */
+ au_writel(0x00, 0xb0520000); /* macen0 */
+ au_writel(0x00, 0xb0520004); /* macen1 */
+ au_writel(0x00, 0xb1000008); /* i2s_enable */
+ au_writel(0x00, 0xb1100100); /* uart0_enable */
+ au_writel(0x00, 0xb1200100); /* uart1_enable */
+ au_writel(0x00, 0xb1300100); /* uart2_enable */
+ au_writel(0x00, 0xb1400100); /* uart3_enable */
+ au_writel(0x02, 0xb1600100); /* ssi0_enable */
+ au_writel(0x02, 0xb1680100); /* ssi1_enable */
+ au_writel(0x00, 0xb1900020); /* sys_freqctrl0 */
+ au_writel(0x00, 0xb1900024); /* sys_freqctrl1 */
+ au_writel(0x00, 0xb1900028); /* sys_clksrc */
+ au_writel(0x10, 0xb1900060); /* sys_cpupll */
+ au_writel(0x00, 0xb1900064); /* sys_auxpll */
+ au_writel(0x00, 0xb1900100); /* sys_pininputen */
+ break;
+ case 0x01000000: /* Au1500 */
+ au_writel(0x02, 0xb0000010); /* ac97_enable */
+ au_writel(0x08, 0xb017fffc); /* usbh_enable - early errata */
+ asm("sync");
+ au_writel(0x00, 0xb017fffc); /* usbh_enable */
+ au_writel(0x00, 0xb0200058); /* usbd_enable */
+ au_writel(0x00, 0xb4004104); /* mac dma */
+ au_writel(0x00, 0xb4004114); /* mac dma */
+ au_writel(0x00, 0xb4004124); /* mac dma */
+ au_writel(0x00, 0xb4004134); /* mac dma */
+ au_writel(0x00, 0xb1520000); /* macen0 */
+ au_writel(0x00, 0xb1520004); /* macen1 */
+ au_writel(0x00, 0xb1100100); /* uart0_enable */
+ au_writel(0x00, 0xb1400100); /* uart3_enable */
+ au_writel(0x00, 0xb1900020); /* sys_freqctrl0 */
+ au_writel(0x00, 0xb1900024); /* sys_freqctrl1 */
+ au_writel(0x00, 0xb1900028); /* sys_clksrc */
+ au_writel(0x10, 0xb1900060); /* sys_cpupll */
+ au_writel(0x00, 0xb1900064); /* sys_auxpll */
+ au_writel(0x00, 0xb1900100); /* sys_pininputen */
+ break;
+ case 0x02000000: /* Au1100 */
+ au_writel(0x02, 0xb0000010); /* ac97_enable */
+ au_writel(0x08, 0xb017fffc); /* usbh_enable - early errata */
+ asm("sync");
+ au_writel(0x00, 0xb017fffc); /* usbh_enable */
+ au_writel(0x00, 0xb0200058); /* usbd_enable */
+ au_writel(0x00, 0xb0300040); /* ir_enable */
+ au_writel(0x00, 0xb4004104); /* mac dma */
+ au_writel(0x00, 0xb4004114); /* mac dma */
+ au_writel(0x00, 0xb4004124); /* mac dma */
+ au_writel(0x00, 0xb4004134); /* mac dma */
+ au_writel(0x00, 0xb0520000); /* macen0 */
+ au_writel(0x00, 0xb1000008); /* i2s_enable */
+ au_writel(0x00, 0xb1100100); /* uart0_enable */
+ au_writel(0x00, 0xb1200100); /* uart1_enable */
+ au_writel(0x00, 0xb1400100); /* uart3_enable */
+ au_writel(0x02, 0xb1600100); /* ssi0_enable */
+ au_writel(0x02, 0xb1680100); /* ssi1_enable */
+ au_writel(0x00, 0xb1900020); /* sys_freqctrl0 */
+ au_writel(0x00, 0xb1900024); /* sys_freqctrl1 */
+ au_writel(0x00, 0xb1900028); /* sys_clksrc */
+ au_writel(0x10, 0xb1900060); /* sys_cpupll */
+ au_writel(0x00, 0xb1900064); /* sys_auxpll */
+ au_writel(0x00, 0xb1900100); /* sys_pininputen */
+ break;
+ case 0x03000000: /* Au1550 */
+ au_writel(0x00, 0xb1a00004); /* psc 0 */
+ au_writel(0x00, 0xb1b00004); /* psc 1 */
+ au_writel(0x00, 0xb0a00004); /* psc 2 */
+ au_writel(0x00, 0xb0b00004); /* psc 3 */
+ au_writel(0x00, 0xb017fffc); /* usbh_enable */
+ au_writel(0x00, 0xb0200058); /* usbd_enable */
+ au_writel(0x00, 0xb4004104); /* mac dma */
+ au_writel(0x00, 0xb4004114); /* mac dma */
+ au_writel(0x00, 0xb4004124); /* mac dma */
+ au_writel(0x00, 0xb4004134); /* mac dma */
+ au_writel(0x00, 0xb1520000); /* macen0 */
+ au_writel(0x00, 0xb1520004); /* macen1 */
+ au_writel(0x00, 0xb1100100); /* uart0_enable */
+ au_writel(0x00, 0xb1200100); /* uart1_enable */
+ au_writel(0x00, 0xb1400100); /* uart3_enable */
+ au_writel(0x00, 0xb1900020); /* sys_freqctrl0 */
+ au_writel(0x00, 0xb1900024); /* sys_freqctrl1 */
+ au_writel(0x00, 0xb1900028); /* sys_clksrc */
+ au_writel(0x10, 0xb1900060); /* sys_cpupll */
+ au_writel(0x00, 0xb1900064); /* sys_auxpll */
+ au_writel(0x00, 0xb1900100); /* sys_pininputen */
+ break;
+
+ default:
+ break;
+ }
+
+ set_c0_status(ST0_BEV | ST0_ERL);
+ set_c0_config(CONF_CM_UNCACHED);
+ flush_cache_all();
+ write_c0_wired(0);
+
+ /* Give board a chance to do a hardware reset */
+ board_reset();
+
+ /* Jump to the beggining in case board_reset() is empty */
+ __asm__ __volatile__("jr\t%0"::"r"(0xbfc00000));
+}
+
+void au1000_halt(void)
+{
+#if defined(CONFIG_MIPS_PB1550)
+ /* power off system */
+ printk("\n** Powering off Pb1550\n");
+ au_writew(au_readw(0xAF00001C) | (3<<14), 0xAF00001C);
+ au_sync();
+ while(1); /* should not get here */
+#endif
+ printk(KERN_NOTICE "\n** You can safely turn off the power\n");
+#ifdef CONFIG_MIPS_MIRAGE
+ au_writel((1 << 26) | (1 << 10), GPIO2_OUTPUT);
+#endif
+#ifdef CONFIG_PM
+ au_sleep();
+
+ /* should not get here */
+ printk(KERN_ERR "Unable to put cpu in sleep mode\n");
+ while(1);
+#else
+ while (1)
+ __asm__(".set\tmips3\n\t"
+ "wait\n\t"
+ ".set\tmips0");
+#endif
+}
+
+void au1000_power_off(void)
+{
+ au1000_halt();
+}
diff --git a/arch/mips/au1000/common/setup.c b/arch/mips/au1000/common/setup.c
new file mode 100644
index 0000000..dbc8b1b
--- /dev/null
+++ b/arch/mips/au1000/common/setup.c
@@ -0,0 +1,195 @@
+/*
+ * Copyright 2000 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ * ppopov@mvista.com or source@mvista.com
+ *
+ * Updates to 2.6, Pete Popov, Embedded Alley Solutions, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/mm.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+
+#include <asm/cpu.h>
+#include <asm/bootinfo.h>
+#include <asm/irq.h>
+#include <asm/mipsregs.h>
+#include <asm/reboot.h>
+#include <asm/pgtable.h>
+#include <asm/mach-au1x00/au1000.h>
+#include <asm/time.h>
+
+extern char * __init prom_getcmdline(void);
+extern void __init board_setup(void);
+extern void au1000_restart(char *);
+extern void au1000_halt(void);
+extern void au1000_power_off(void);
+extern struct resource ioport_resource;
+extern struct resource iomem_resource;
+extern void (*board_time_init)(void);
+extern void au1x_time_init(void);
+extern void (*board_timer_setup)(struct irqaction *irq);
+extern void au1x_timer_setup(struct irqaction *irq);
+extern void au1xxx_time_init(void);
+extern void au1xxx_timer_setup(struct irqaction *irq);
+extern void set_cpuspec(void);
+
+static int __init au1x00_setup(void)
+{
+ struct cpu_spec *sp;
+ char *argptr;
+ unsigned long prid, cpupll, bclk = 1;
+
+ set_cpuspec();
+ sp = cur_cpu_spec[0];
+
+ board_setup(); /* board specific setup */
+
+ prid = read_c0_prid();
+ cpupll = (au_readl(0xB1900060) & 0x3F) * 12;
+ printk("(PRId %08lx) @ %ldMHZ\n", prid, cpupll);
+
+ bclk = sp->cpu_bclk;
+ if (bclk)
+ {
+ /* Enable BCLK switching */
+ bclk = au_readl(0xB190003C);
+ au_writel(bclk | 0x60, 0xB190003C);
+ printk("BCLK switching enabled!\n");
+ }
+
+ if (sp->cpu_od) {
+ /* Various early Au1000 Errata corrected by this */
+ set_c0_config(1<<19); /* Set Config[OD] */
+ }
+ else {
+ /* Clear to obtain best system bus performance */
+ clear_c0_config(1<<19); /* Clear Config[OD] */
+ }
+
+ argptr = prom_getcmdline();
+
+#ifdef CONFIG_SERIAL_AU1X00_CONSOLE
+ if ((argptr = strstr(argptr, "console=")) == NULL) {
+ argptr = prom_getcmdline();
+ strcat(argptr, " console=ttyS0,115200");
+ }
+#endif
+
+#ifdef CONFIG_FB_AU1100
+ if ((argptr = strstr(argptr, "video=")) == NULL) {
+ argptr = prom_getcmdline();
+ /* default panel */
+ /*strcat(argptr, " video=au1100fb:panel:Sharp_320x240_16");*/
+#ifdef CONFIG_MIPS_HYDROGEN3
+ strcat(argptr, " video=au1100fb:panel:Hydrogen_3_NEC_panel_320x240,nohwcursor");
+#else
+ strcat(argptr, " video=au1100fb:panel:s10,nohwcursor");
+#endif
+ }
+#endif
+
+#ifdef CONFIG_FB_E1356
+ if ((argptr = strstr(argptr, "video=")) == NULL) {
+ argptr = prom_getcmdline();
+#ifdef CONFIG_MIPS_PB1000
+ strcat(argptr, " video=e1356fb:system:pb1000,mmunalign:1");
+#else
+ strcat(argptr, " video=e1356fb:system:pb1500");
+#endif
+ }
+#endif
+
+#ifdef CONFIG_FB_XPERT98
+ if ((argptr = strstr(argptr, "video=")) == NULL) {
+ argptr = prom_getcmdline();
+ strcat(argptr, " video=atyfb:1024x768-8@70");
+ }
+#endif
+
+#if defined(CONFIG_SOUND_AU1X00) && !defined(CONFIG_SOC_AU1000)
+ /* au1000 does not support vra, au1500 and au1100 do */
+ strcat(argptr, " au1000_audio=vra");
+ argptr = prom_getcmdline();
+#endif
+ _machine_restart = au1000_restart;
+ _machine_halt = au1000_halt;
+ _machine_power_off = au1000_power_off;
+ board_time_init = au1xxx_time_init;
+ board_timer_setup = au1xxx_timer_setup;
+
+ /* IO/MEM resources. */
+ set_io_port_base(0);
+ ioport_resource.start = IOPORT_RESOURCE_START;
+ ioport_resource.end = IOPORT_RESOURCE_END;
+ iomem_resource.start = IOMEM_RESOURCE_START;
+ iomem_resource.end = IOMEM_RESOURCE_END;
+
+ while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_E0S);
+ au_writel(SYS_CNTRL_E0 | SYS_CNTRL_EN0, SYS_COUNTER_CNTRL);
+ au_sync();
+ while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_T0S);
+ au_writel(0, SYS_TOYTRIM);
+
+ return 0;
+}
+
+early_initcall(au1x00_setup);
+
+#if defined(CONFIG_64BIT_PHYS_ADDR)
+/* This routine should be valid for all Au1x based boards */
+phys_t fixup_bigphys_addr(phys_t phys_addr, phys_t size)
+{
+ u32 start, end;
+
+ /* Don't fixup 36 bit addresses */
+ if ((phys_addr >> 32) != 0) return phys_addr;
+
+#ifdef CONFIG_PCI
+ start = (u32)Au1500_PCI_MEM_START;
+ end = (u32)Au1500_PCI_MEM_END;
+ /* check for pci memory window */
+ if ((phys_addr >= start) && ((phys_addr + size) < end)) {
+ return (phys_t)((phys_addr - start) + Au1500_PCI_MEM_START);
+ }
+#endif
+
+ /* All Au1x SOCs have a pcmcia controller */
+ /* We setup our 32 bit pseudo addresses to be equal to the
+ * 36 bit addr >> 4, to make it easier to check the address
+ * and fix it.
+ * The Au1x socket 0 phys attribute address is 0xF 4000 0000.
+ * The pseudo address we use is 0xF400 0000. Any address over
+ * 0xF400 0000 is a pcmcia pseudo address.
+ */
+ if ((phys_addr >= 0xF4000000) && (phys_addr < 0xFFFFFFFF)) {
+ return (phys_t)(phys_addr << 4);
+ }
+
+ /* default nop */
+ return phys_addr;
+}
+#endif
diff --git a/arch/mips/au1000/common/sleeper.S b/arch/mips/au1000/common/sleeper.S
new file mode 100644
index 0000000..44dac3b
--- /dev/null
+++ b/arch/mips/au1000/common/sleeper.S
@@ -0,0 +1,149 @@
+/*
+ * Copyright 2002 Embedded Edge, LLC
+ * Author: dan@embeddededge.com
+ *
+ * Sleep helper for Au1xxx sleep mode.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+#include <asm/asm.h>
+#include <asm/mipsregs.h>
+#include <asm/addrspace.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+
+ .text
+ .set macro
+ .set noat
+ .align 5
+
+/* Save all of the processor general registers and go to sleep.
+ * A wakeup condition will get us back here to restore the registers.
+ */
+LEAF(save_and_sleep)
+
+ subu sp, PT_SIZE
+ sw $1, PT_R1(sp)
+ sw $2, PT_R2(sp)
+ sw $3, PT_R3(sp)
+ sw $4, PT_R4(sp)
+ sw $5, PT_R5(sp)
+ sw $6, PT_R6(sp)
+ sw $7, PT_R7(sp)
+ sw $8, PT_R8(sp)
+ sw $9, PT_R9(sp)
+ sw $10, PT_R10(sp)
+ sw $11, PT_R11(sp)
+ sw $12, PT_R12(sp)
+ sw $13, PT_R13(sp)
+ sw $14, PT_R14(sp)
+ sw $15, PT_R15(sp)
+ sw $16, PT_R16(sp)
+ sw $17, PT_R17(sp)
+ sw $18, PT_R18(sp)
+ sw $19, PT_R19(sp)
+ sw $20, PT_R20(sp)
+ sw $21, PT_R21(sp)
+ sw $22, PT_R22(sp)
+ sw $23, PT_R23(sp)
+ sw $24, PT_R24(sp)
+ sw $25, PT_R25(sp)
+ sw $26, PT_R26(sp)
+ sw $27, PT_R27(sp)
+ sw $28, PT_R28(sp)
+ sw $29, PT_R29(sp)
+ sw $30, PT_R30(sp)
+ sw $31, PT_R31(sp)
+ mfc0 k0, CP0_STATUS
+ sw k0, 0x20(sp)
+ mfc0 k0, CP0_CONTEXT
+ sw k0, 0x1c(sp)
+ mfc0 k0, CP0_PAGEMASK
+ sw k0, 0x18(sp)
+ mfc0 k0, CP0_CONFIG
+ sw k0, 0x14(sp)
+
+ /* Now set up the scratch registers so the boot rom will
+ * return to this point upon wakeup.
+ */
+ la k0, 1f
+ lui k1, 0xb190
+ ori k1, 0x18
+ sw sp, 0(k1)
+ ori k1, 0x1c
+ sw k0, 0(k1)
+
+/* Put SDRAM into self refresh. Preload instructions into cache,
+ * issue a precharge, then auto refresh, then sleep commands to it.
+ */
+ la t0, sdsleep
+ .set mips3
+ cache 0x14, 0(t0)
+ cache 0x14, 32(t0)
+ cache 0x14, 64(t0)
+ cache 0x14, 96(t0)
+ .set mips0
+
+sdsleep:
+ lui k0, 0xb400
+ sw zero, 0x001c(k0) /* Precharge */
+ sw zero, 0x0020(k0) /* Auto refresh */
+ sw zero, 0x0030(k0) /* SDRAM sleep */
+ sync
+
+ lui k1, 0xb190
+ sw zero, 0x0078(k1) /* get ready to sleep */
+ sync
+ sw zero, 0x007c(k1) /* Put processor to sleep */
+ sync
+
+ /* This is where we return upon wakeup.
+ * Reload all of the registers and return.
+ */
+1: nop
+ lw k0, 0x20(sp)
+ mtc0 k0, CP0_STATUS
+ lw k0, 0x1c(sp)
+ mtc0 k0, CP0_CONTEXT
+ lw k0, 0x18(sp)
+ mtc0 k0, CP0_PAGEMASK
+ lw k0, 0x14(sp)
+ mtc0 k0, CP0_CONFIG
+ lw $1, PT_R1(sp)
+ lw $2, PT_R2(sp)
+ lw $3, PT_R3(sp)
+ lw $4, PT_R4(sp)
+ lw $5, PT_R5(sp)
+ lw $6, PT_R6(sp)
+ lw $7, PT_R7(sp)
+ lw $8, PT_R8(sp)
+ lw $9, PT_R9(sp)
+ lw $10, PT_R10(sp)
+ lw $11, PT_R11(sp)
+ lw $12, PT_R12(sp)
+ lw $13, PT_R13(sp)
+ lw $14, PT_R14(sp)
+ lw $15, PT_R15(sp)
+ lw $16, PT_R16(sp)
+ lw $17, PT_R17(sp)
+ lw $18, PT_R18(sp)
+ lw $19, PT_R19(sp)
+ lw $20, PT_R20(sp)
+ lw $21, PT_R21(sp)
+ lw $22, PT_R22(sp)
+ lw $23, PT_R23(sp)
+ lw $24, PT_R24(sp)
+ lw $25, PT_R25(sp)
+ lw $26, PT_R26(sp)
+ lw $27, PT_R27(sp)
+ lw $28, PT_R28(sp)
+ lw $29, PT_R29(sp)
+ lw $30, PT_R30(sp)
+ lw $31, PT_R31(sp)
+ addiu sp, PT_SIZE
+
+ jr ra
+END(save_and_sleep)
diff --git a/arch/mips/au1000/common/time.c b/arch/mips/au1000/common/time.c
new file mode 100644
index 0000000..fe418f1
--- /dev/null
+++ b/arch/mips/au1000/common/time.c
@@ -0,0 +1,469 @@
+/*
+ *
+ * Copyright (C) 2001 MontaVista Software, ppopov@mvista.com
+ * Copied and modified Carsten Langgaard's time.c
+ *
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
+ *
+ * ########################################################################
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ *
+ * Setting up the clock on the MIPS boards.
+ *
+ * Update. Always configure the kernel with CONFIG_NEW_TIME_C. This
+ * will use the user interface gettimeofday() functions from the
+ * arch/mips/kernel/time.c, and we provide the clock interrupt processing
+ * and the timer offset compute functions. If CONFIG_PM is selected,
+ * we also ensure the 32KHz timer is available. -- Dan
+ */
+
+#include <linux/types.h>
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/kernel_stat.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/hardirq.h>
+
+#include <asm/compiler.h>
+#include <asm/mipsregs.h>
+#include <asm/ptrace.h>
+#include <asm/time.h>
+#include <asm/div64.h>
+#include <asm/mach-au1x00/au1000.h>
+
+#include <linux/mc146818rtc.h>
+#include <linux/timex.h>
+
+extern void startup_match20_interrupt(void);
+extern void do_softirq(void);
+extern volatile unsigned long wall_jiffies;
+unsigned long missed_heart_beats = 0;
+
+static unsigned long r4k_offset; /* Amount to increment compare reg each time */
+static unsigned long r4k_cur; /* What counter should be at next timer irq */
+int no_au1xxx_32khz;
+void (*au1k_wait_ptr)(void);
+
+/* Cycle counter value at the previous timer interrupt.. */
+static unsigned int timerhi = 0, timerlo = 0;
+
+#ifdef CONFIG_PM
+#define MATCH20_INC 328
+extern void startup_match20_interrupt(void);
+static unsigned long last_pc0, last_match20;
+#endif
+
+static DEFINE_SPINLOCK(time_lock);
+
+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.
+ */
+unsigned long wtimer;
+void mips_timer_interrupt(struct pt_regs *regs)
+{
+ int irq = 63;
+ unsigned long count;
+
+ irq_enter();
+ kstat_this_cpu.irqs[irq]++;
+
+ if (r4k_offset == 0)
+ goto null;
+
+ do {
+ count = read_c0_count();
+ timerhi += (count < timerlo); /* Wrap around */
+ timerlo = count;
+
+ kstat_this_cpu.irqs[irq]++;
+ do_timer(regs);
+#ifndef CONFIG_SMP
+ update_process_times(user_mode(regs));
+#endif
+ r4k_cur += r4k_offset;
+ ack_r4ktimer(r4k_cur);
+
+ } while (((unsigned long)read_c0_count()
+ - r4k_cur) < 0x7fffffff);
+
+ irq_exit();
+ return;
+
+null:
+ ack_r4ktimer(0);
+}
+
+#ifdef CONFIG_PM
+void counter0_irq(int irq, void *dev_id, struct pt_regs *regs)
+{
+ unsigned long pc0;
+ int time_elapsed;
+ static int jiffie_drift = 0;
+
+ kstat.irqs[0][irq]++;
+ if (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20) {
+ /* should never happen! */
+ printk(KERN_WARNING "counter 0 w status eror\n");
+ return;
+ }
+
+ pc0 = au_readl(SYS_TOYREAD);
+ if (pc0 < last_match20) {
+ /* counter overflowed */
+ time_elapsed = (0xffffffff - last_match20) + pc0;
+ }
+ else {
+ time_elapsed = pc0 - last_match20;
+ }
+
+ while (time_elapsed > 0) {
+ do_timer(regs);
+#ifndef CONFIG_SMP
+ update_process_times(user_mode(regs));
+#endif
+ time_elapsed -= MATCH20_INC;
+ last_match20 += MATCH20_INC;
+ jiffie_drift++;
+ }
+
+ last_pc0 = pc0;
+ au_writel(last_match20 + MATCH20_INC, SYS_TOYMATCH2);
+ au_sync();
+
+ /* our counter ticks at 10.009765625 ms/tick, we we're running
+ * almost 10uS too slow per tick.
+ */
+
+ if (jiffie_drift >= 999) {
+ jiffie_drift -= 999;
+ do_timer(regs); /* increment jiffies by one */
+#ifndef CONFIG_SMP
+ update_process_times(user_mode(regs));
+#endif
+ }
+}
+
+/* When we wakeup from sleep, we have to "catch up" on all of the
+ * timer ticks we have missed.
+ */
+void
+wakeup_counter0_adjust(void)
+{
+ unsigned long pc0;
+ int time_elapsed;
+
+ pc0 = au_readl(SYS_TOYREAD);
+ if (pc0 < last_match20) {
+ /* counter overflowed */
+ time_elapsed = (0xffffffff - last_match20) + pc0;
+ }
+ else {
+ time_elapsed = pc0 - last_match20;
+ }
+
+ while (time_elapsed > 0) {
+ time_elapsed -= MATCH20_INC;
+ last_match20 += MATCH20_INC;
+ }
+
+ last_pc0 = pc0;
+ au_writel(last_match20 + MATCH20_INC, SYS_TOYMATCH2);
+ au_sync();
+
+}
+
+/* This is just for debugging to set the timer for a sleep delay.
+*/
+void
+wakeup_counter0_set(int ticks)
+{
+ unsigned long pc0;
+
+ pc0 = au_readl(SYS_TOYREAD);
+ last_pc0 = pc0;
+ au_writel(last_match20 + (MATCH20_INC * ticks), SYS_TOYMATCH2);
+ au_sync();
+}
+#endif
+
+/* I haven't found anyone that doesn't use a 12 MHz source clock,
+ * but just in case.....
+ */
+#ifdef CONFIG_AU1000_SRC_CLK
+#define AU1000_SRC_CLK CONFIG_AU1000_SRC_CLK
+#else
+#define AU1000_SRC_CLK 12000000
+#endif
+
+/*
+ * We read the real processor speed from the PLL. This is important
+ * because it is more accurate than computing it from the 32KHz
+ * counter, if it exists. If we don't have an accurate processor
+ * speed, all of the peripherals that derive their clocks based on
+ * this advertised speed will introduce error and sometimes not work
+ * properly. This function is futher convoluted to still allow configurations
+ * to do that in case they have really, really old silicon with a
+ * write-only PLL register, that we need the 32KHz when power management
+ * "wait" is enabled, and we need to detect if the 32KHz isn't present
+ * but requested......got it? :-) -- Dan
+ */
+unsigned long cal_r4koff(void)
+{
+ unsigned long count;
+ unsigned long cpu_speed;
+ unsigned long flags;
+ unsigned long counter;
+
+ spin_lock_irqsave(&time_lock, flags);
+
+ /* Power management cares if we don't have a 32KHz counter.
+ */
+ no_au1xxx_32khz = 0;
+ counter = au_readl(SYS_COUNTER_CNTRL);
+ if (counter & SYS_CNTRL_E0) {
+ int trim_divide = 16;
+
+ au_writel(counter | SYS_CNTRL_EN1, SYS_COUNTER_CNTRL);
+
+ while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_T1S);
+ /* RTC now ticks at 32.768/16 kHz */
+ au_writel(trim_divide-1, SYS_RTCTRIM);
+ while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_T1S);
+
+ while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C1S);
+ au_writel (0, SYS_TOYWRITE);
+ while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C1S);
+
+#if defined(CONFIG_AU1000_USE32K)
+ {
+ unsigned long start, end;
+
+ start = au_readl(SYS_RTCREAD);
+ start += 2;
+ /* wait for the beginning of a new tick
+ */
+ while (au_readl(SYS_RTCREAD) < start);
+
+ /* Start r4k counter.
+ */
+ write_c0_count(0);
+
+ /* Wait 0.5 seconds.
+ */
+ end = start + (32768 / trim_divide)/2;
+
+ while (end > au_readl(SYS_RTCREAD));
+
+ count = read_c0_count();
+ cpu_speed = count * 2;
+ }
+#else
+ cpu_speed = (au_readl(SYS_CPUPLL) & 0x0000003f) *
+ AU1000_SRC_CLK;
+ count = cpu_speed / 2;
+#endif
+ }
+ else {
+ /* The 32KHz oscillator isn't running, so assume there
+ * isn't one and grab the processor speed from the PLL.
+ * NOTE: some old silicon doesn't allow reading the PLL.
+ */
+ cpu_speed = (au_readl(SYS_CPUPLL) & 0x0000003f) * AU1000_SRC_CLK;
+ count = cpu_speed / 2;
+ no_au1xxx_32khz = 1;
+ }
+ mips_hpt_frequency = count;
+ // Equation: Baudrate = CPU / (SD * 2 * CLKDIV * 16)
+ set_au1x00_uart_baud_base(cpu_speed / (2 * ((int)(au_readl(SYS_POWERCTRL)&0x03) + 2) * 16));
+ spin_unlock_irqrestore(&time_lock, flags);
+ return (cpu_speed / HZ);
+}
+
+/* This is for machines which generate the exact clock. */
+#define USECS_PER_JIFFY (1000000/HZ)
+#define USECS_PER_JIFFY_FRAC (0x100000000LL*1000000/HZ&0xffffffff)
+
+static unsigned long
+div64_32(unsigned long v1, unsigned long v2, unsigned long v3)
+{
+ unsigned long r0;
+ do_div64_32(r0, v1, v2, v3);
+ return r0;
+}
+
+static unsigned long do_fast_cp0_gettimeoffset(void)
+{
+ u32 count;
+ unsigned long res, tmp;
+ unsigned long r0;
+
+ /* 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;
+ if (last_jiffies != 0) {
+ r0 = div64_32(timerhi, timerlo, tmp);
+ quotient = div64_32(USECS_PER_JIFFY, USECS_PER_JIFFY_FRAC, r0);
+ cached_quotient = quotient;
+ }
+ }
+
+ /* 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)
+ : "hi", "lo", GCC_REG_ACCUM);
+
+ /*
+ * 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;
+}
+
+#ifdef CONFIG_PM
+static unsigned long do_fast_pm_gettimeoffset(void)
+{
+ unsigned long pc0;
+ unsigned long offset;
+
+ pc0 = au_readl(SYS_TOYREAD);
+ au_sync();
+ offset = pc0 - last_pc0;
+ if (offset > 2*MATCH20_INC) {
+ printk("huge offset %x, last_pc0 %x last_match20 %x pc0 %x\n",
+ (unsigned)offset, (unsigned)last_pc0,
+ (unsigned)last_match20, (unsigned)pc0);
+ }
+ offset = (unsigned long)((offset * 305) / 10);
+ return offset;
+}
+#endif
+
+void au1xxx_timer_setup(struct irqaction *irq)
+{
+ unsigned int est_freq;
+ extern unsigned long (*do_gettimeoffset)(void);
+ extern void au1k_wait(void);
+
+ printk("calculating r4koff... ");
+ r4k_offset = cal_r4koff();
+ printk("%08lx(%d)\n", r4k_offset, (int) r4k_offset);
+
+ //est_freq = 2*r4k_offset*HZ;
+ est_freq = r4k_offset*HZ;
+ est_freq += 5000; /* round */
+ est_freq -= est_freq%10000;
+ printk("CPU frequency %d.%02d MHz\n", est_freq/1000000,
+ (est_freq%1000000)*100/1000000);
+ set_au1x00_speed(est_freq);
+ set_au1x00_lcd_clock(); // program the LCD clock
+
+ r4k_cur = (read_c0_count() + r4k_offset);
+ write_c0_compare(r4k_cur);
+
+#ifdef CONFIG_PM
+ /*
+ * setup counter 0, since it keeps ticking after a
+ * 'wait' instruction has been executed. The CP0 timer and
+ * counter 1 do NOT continue running after 'wait'
+ *
+ * It's too early to call request_irq() here, so we handle
+ * counter 0 interrupt as a special irq and it doesn't show
+ * up under /proc/interrupts.
+ *
+ * Check to ensure we really have a 32KHz oscillator before
+ * we do this.
+ */
+ if (no_au1xxx_32khz) {
+ unsigned int c0_status;
+
+ printk("WARNING: no 32KHz clock found.\n");
+ do_gettimeoffset = do_fast_cp0_gettimeoffset;
+
+ /* Ensure we get CPO_COUNTER interrupts.
+ */
+ c0_status = read_c0_status();
+ c0_status |= IE_IRQ5;
+ write_c0_status(c0_status);
+ }
+ else {
+ while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C0S);
+ au_writel(0, SYS_TOYWRITE);
+ while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C0S);
+
+ au_writel(au_readl(SYS_WAKEMSK) | (1<<8), SYS_WAKEMSK);
+ au_writel(~0, SYS_WAKESRC);
+ au_sync();
+ while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20);
+
+ /* setup match20 to interrupt once every 10ms */
+ last_pc0 = last_match20 = au_readl(SYS_TOYREAD);
+ au_writel(last_match20 + MATCH20_INC, SYS_TOYMATCH2);
+ au_sync();
+ while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20);
+ startup_match20_interrupt();
+
+ do_gettimeoffset = do_fast_pm_gettimeoffset;
+
+ /* We can use the real 'wait' instruction.
+ */
+ au1k_wait_ptr = au1k_wait;
+ }
+
+#else
+ /* We have to do this here instead of in timer_init because
+ * the generic code in arch/mips/kernel/time.c will write
+ * over our function pointer.
+ */
+ do_gettimeoffset = do_fast_cp0_gettimeoffset;
+#endif
+}
+
+void __init au1xxx_time_init(void)
+{
+}
diff --git a/arch/mips/au1000/common/usbdev.c b/arch/mips/au1000/common/usbdev.c
new file mode 100644
index 0000000..447a9a4
--- /dev/null
+++ b/arch/mips/au1000/common/usbdev.c
@@ -0,0 +1,1557 @@
+/*
+ * BRIEF MODULE DESCRIPTION
+ * Au1000 USB Device-Side (device layer)
+ *
+ * Copyright 2001-2002 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ * stevel@mvista.com or source@mvista.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/kernel.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/errno.h>
+#include <linux/poll.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/fcntl.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/list.h>
+#include <linux/smp_lock.h>
+#define DEBUG
+#include <linux/usb.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/irq.h>
+#include <asm/mipsregs.h>
+#include <asm/au1000.h>
+#include <asm/au1000_dma.h>
+#include <asm/au1000_usbdev.h>
+
+#ifdef DEBUG
+#undef VDEBUG
+#ifdef VDEBUG
+#define vdbg(fmt, arg...) printk(KERN_DEBUG __FILE__ ": " fmt "\n" , ## arg)
+#else
+#define vdbg(fmt, arg...) do {} while (0)
+#endif
+#else
+#define vdbg(fmt, arg...) do {} while (0)
+#endif
+
+#define ALLOC_FLAGS (in_interrupt () ? GFP_ATOMIC : GFP_KERNEL)
+
+#define EP_FIFO_DEPTH 8
+
+typedef enum {
+ SETUP_STAGE = 0,
+ DATA_STAGE,
+ STATUS_STAGE
+} ep0_stage_t;
+
+typedef struct {
+ int read_fifo;
+ int write_fifo;
+ int ctrl_stat;
+ int read_fifo_status;
+ int write_fifo_status;
+} endpoint_reg_t;
+
+typedef struct {
+ usbdev_pkt_t *head;
+ usbdev_pkt_t *tail;
+ int count;
+} pkt_list_t;
+
+typedef struct {
+ int active;
+ struct usb_endpoint_descriptor *desc;
+ endpoint_reg_t *reg;
+ /* Only one of these are used, unless this is the control ep */
+ pkt_list_t inlist;
+ pkt_list_t outlist;
+ unsigned int indma, outdma; /* DMA channel numbers for IN, OUT */
+ /* following are extracted from endpoint descriptor for easy access */
+ int max_pkt_size;
+ int type;
+ int direction;
+ /* WE assign endpoint addresses! */
+ int address;
+ spinlock_t lock;
+} endpoint_t;
+
+
+static struct usb_dev {
+ endpoint_t ep[6];
+ ep0_stage_t ep0_stage;
+
+ struct usb_device_descriptor * dev_desc;
+ struct usb_interface_descriptor* if_desc;
+ struct usb_config_descriptor * conf_desc;
+ u8 * full_conf_desc;
+ struct usb_string_descriptor * str_desc[6];
+
+ /* callback to function layer */
+ void (*func_cb)(usbdev_cb_type_t type, unsigned long arg,
+ void *cb_data);
+ void* cb_data;
+
+ usbdev_state_t state; // device state
+ int suspended; // suspended flag
+ int address; // device address
+ int interface;
+ int num_ep;
+ u8 alternate_setting;
+ u8 configuration; // configuration value
+ int remote_wakeup_en;
+} usbdev;
+
+
+static endpoint_reg_t ep_reg[] = {
+ // FIFO's 0 and 1 are EP0 default control
+ {USBD_EP0RD, USBD_EP0WR, USBD_EP0CS, USBD_EP0RDSTAT, USBD_EP0WRSTAT },
+ {0},
+ // FIFO 2 is EP2, IN
+ { -1, USBD_EP2WR, USBD_EP2CS, -1, USBD_EP2WRSTAT },
+ // FIFO 3 is EP3, IN
+ { -1, USBD_EP3WR, USBD_EP3CS, -1, USBD_EP3WRSTAT },
+ // FIFO 4 is EP4, OUT
+ {USBD_EP4RD, -1, USBD_EP4CS, USBD_EP4RDSTAT, -1 },
+ // FIFO 5 is EP5, OUT
+ {USBD_EP5RD, -1, USBD_EP5CS, USBD_EP5RDSTAT, -1 }
+};
+
+static struct {
+ unsigned int id;
+ const char *str;
+} ep_dma_id[] = {
+ { DMA_ID_USBDEV_EP0_TX, "USBDev EP0 IN" },
+ { DMA_ID_USBDEV_EP0_RX, "USBDev EP0 OUT" },
+ { DMA_ID_USBDEV_EP2_TX, "USBDev EP2 IN" },
+ { DMA_ID_USBDEV_EP3_TX, "USBDev EP3 IN" },
+ { DMA_ID_USBDEV_EP4_RX, "USBDev EP4 OUT" },
+ { DMA_ID_USBDEV_EP5_RX, "USBDev EP5 OUT" }
+};
+
+#define DIR_OUT 0
+#define DIR_IN (1<<3)
+
+#define CONTROL_EP USB_ENDPOINT_XFER_CONTROL
+#define BULK_EP USB_ENDPOINT_XFER_BULK
+
+static inline endpoint_t *
+epaddr_to_ep(struct usb_dev* dev, int ep_addr)
+{
+ if (ep_addr >= 0 && ep_addr < 2)
+ return &dev->ep[0];
+ if (ep_addr < 6)
+ return &dev->ep[ep_addr];
+ return NULL;
+}
+
+static const char* std_req_name[] = {
+ "GET_STATUS",
+ "CLEAR_FEATURE",
+ "RESERVED",
+ "SET_FEATURE",
+ "RESERVED",
+ "SET_ADDRESS",
+ "GET_DESCRIPTOR",
+ "SET_DESCRIPTOR",
+ "GET_CONFIGURATION",
+ "SET_CONFIGURATION",
+ "GET_INTERFACE",
+ "SET_INTERFACE",
+ "SYNCH_FRAME"
+};
+
+static inline const char*
+get_std_req_name(int req)
+{
+ return (req >= 0 && req <= 12) ? std_req_name[req] : "UNKNOWN";
+}
+
+#if 0
+static void
+dump_setup(struct usb_ctrlrequest* s)
+{
+ dbg("%s: requesttype=%d", __FUNCTION__, s->requesttype);
+ dbg("%s: request=%d %s", __FUNCTION__, s->request,
+ get_std_req_name(s->request));
+ dbg("%s: value=0x%04x", __FUNCTION__, s->wValue);
+ dbg("%s: index=%d", __FUNCTION__, s->index);
+ dbg("%s: length=%d", __FUNCTION__, s->length);
+}
+#endif
+
+static inline usbdev_pkt_t *
+alloc_packet(endpoint_t * ep, int data_size, void* data)
+{
+ usbdev_pkt_t* pkt = kmalloc(sizeof(usbdev_pkt_t) + data_size,
+ ALLOC_FLAGS);
+ if (!pkt)
+ return NULL;
+ pkt->ep_addr = ep->address;
+ pkt->size = data_size;
+ pkt->status = 0;
+ pkt->next = NULL;
+ if (data)
+ memcpy(pkt->payload, data, data_size);
+
+ return pkt;
+}
+
+
+/*
+ * Link a packet to the tail of the enpoint's packet list.
+ * EP spinlock must be held when calling.
+ */
+static void
+link_tail(endpoint_t * ep, pkt_list_t * list, usbdev_pkt_t * pkt)
+{
+ if (!list->tail) {
+ list->head = list->tail = pkt;
+ list->count = 1;
+ } else {
+ list->tail->next = pkt;
+ list->tail = pkt;
+ list->count++;
+ }
+}
+
+/*
+ * Unlink and return a packet from the head of the given packet
+ * list. It is the responsibility of the caller to free the packet.
+ * EP spinlock must be held when calling.
+ */
+static usbdev_pkt_t *
+unlink_head(pkt_list_t * list)
+{
+ usbdev_pkt_t *pkt;
+
+ pkt = list->head;
+ if (!pkt || !list->count) {
+ return NULL;
+ }
+
+ list->head = pkt->next;
+ if (!list->head) {
+ list->head = list->tail = NULL;
+ list->count = 0;
+ } else
+ list->count--;
+
+ return pkt;
+}
+
+/*
+ * Create and attach a new packet to the tail of the enpoint's
+ * packet list. EP spinlock must be held when calling.
+ */
+static usbdev_pkt_t *
+add_packet(endpoint_t * ep, pkt_list_t * list, int size)
+{
+ usbdev_pkt_t *pkt = alloc_packet(ep, size, NULL);
+ if (!pkt)
+ return NULL;
+
+ link_tail(ep, list, pkt);
+ return pkt;
+}
+
+
+/*
+ * Unlink and free a packet from the head of the enpoint's
+ * packet list. EP spinlock must be held when calling.
+ */
+static inline void
+free_packet(pkt_list_t * list)
+{
+ kfree(unlink_head(list));
+}
+
+/* EP spinlock must be held when calling. */
+static inline void
+flush_pkt_list(pkt_list_t * list)
+{
+ while (list->count)
+ free_packet(list);
+}
+
+/* EP spinlock must be held when calling */
+static inline void
+flush_write_fifo(endpoint_t * ep)
+{
+ if (ep->reg->write_fifo_status >= 0) {
+ au_writel(USBDEV_FSTAT_FLUSH | USBDEV_FSTAT_UF |
+ USBDEV_FSTAT_OF,
+ ep->reg->write_fifo_status);
+ //udelay(100);
+ //au_writel(USBDEV_FSTAT_UF | USBDEV_FSTAT_OF,
+ // ep->reg->write_fifo_status);
+ }
+}
+
+/* EP spinlock must be held when calling */
+static inline void
+flush_read_fifo(endpoint_t * ep)
+{
+ if (ep->reg->read_fifo_status >= 0) {
+ au_writel(USBDEV_FSTAT_FLUSH | USBDEV_FSTAT_UF |
+ USBDEV_FSTAT_OF,
+ ep->reg->read_fifo_status);
+ //udelay(100);
+ //au_writel(USBDEV_FSTAT_UF | USBDEV_FSTAT_OF,
+ // ep->reg->read_fifo_status);
+ }
+}
+
+
+/* EP spinlock must be held when calling. */
+static void
+endpoint_flush(endpoint_t * ep)
+{
+ // First, flush all packets
+ flush_pkt_list(&ep->inlist);
+ flush_pkt_list(&ep->outlist);
+
+ // Now flush the endpoint's h/w FIFO(s)
+ flush_write_fifo(ep);
+ flush_read_fifo(ep);
+}
+
+/* EP spinlock must be held when calling. */
+static void
+endpoint_stall(endpoint_t * ep)
+{
+ u32 cs;
+
+ warn(__FUNCTION__);
+
+ cs = au_readl(ep->reg->ctrl_stat) | USBDEV_CS_STALL;
+ au_writel(cs, ep->reg->ctrl_stat);
+}
+
+/* EP spinlock must be held when calling. */
+static void
+endpoint_unstall(endpoint_t * ep)
+{
+ u32 cs;
+
+ warn(__FUNCTION__);
+
+ cs = au_readl(ep->reg->ctrl_stat) & ~USBDEV_CS_STALL;
+ au_writel(cs, ep->reg->ctrl_stat);
+}
+
+static void
+endpoint_reset_datatoggle(endpoint_t * ep)
+{
+ // FIXME: is this possible?
+}
+
+
+/* EP spinlock must be held when calling. */
+static int
+endpoint_fifo_read(endpoint_t * ep)
+{
+ int read_count = 0;
+ u8 *bufptr;
+ usbdev_pkt_t *pkt = ep->outlist.tail;
+
+ if (!pkt)
+ return -EINVAL;
+
+ bufptr = &pkt->payload[pkt->size];
+ while (au_readl(ep->reg->read_fifo_status) & USBDEV_FSTAT_FCNT_MASK) {
+ *bufptr++ = au_readl(ep->reg->read_fifo) & 0xff;
+ read_count++;
+ pkt->size++;
+ }
+
+ return read_count;
+}
+
+#if 0
+/* EP spinlock must be held when calling. */
+static int
+endpoint_fifo_write(endpoint_t * ep, int index)
+{
+ int write_count = 0;
+ u8 *bufptr;
+ usbdev_pkt_t *pkt = ep->inlist.head;
+
+ if (!pkt)
+ return -EINVAL;
+
+ bufptr = &pkt->payload[index];
+ while ((au_readl(ep->reg->write_fifo_status) &
+ USBDEV_FSTAT_FCNT_MASK) < EP_FIFO_DEPTH) {
+ if (bufptr < pkt->payload + pkt->size) {
+ au_writel(*bufptr++, ep->reg->write_fifo);
+ write_count++;
+ } else {
+ break;
+ }
+ }
+
+ return write_count;
+}
+#endif
+
+/*
+ * This routine is called to restart transmission of a packet.
+ * The endpoint's TSIZE must be set to the new packet's size,
+ * and DMA to the write FIFO needs to be restarted.
+ * EP spinlock must be held when calling.
+ */
+static void
+kickstart_send_packet(endpoint_t * ep)
+{
+ u32 cs;
+ usbdev_pkt_t *pkt = ep->inlist.head;
+
+ vdbg("%s: ep%d, pkt=%p", __FUNCTION__, ep->address, pkt);
+
+ if (!pkt) {
+ err("%s: head=NULL! list->count=%d", __FUNCTION__,
+ ep->inlist.count);
+ return;
+ }
+
+ dma_cache_wback_inv((unsigned long)pkt->payload, pkt->size);
+
+ /*
+ * make sure FIFO is empty
+ */
+ flush_write_fifo(ep);
+
+ cs = au_readl(ep->reg->ctrl_stat) & USBDEV_CS_STALL;
+ cs |= (pkt->size << USBDEV_CS_TSIZE_BIT);
+ au_writel(cs, ep->reg->ctrl_stat);
+
+ if (get_dma_active_buffer(ep->indma) == 1) {
+ set_dma_count1(ep->indma, pkt->size);
+ set_dma_addr1(ep->indma, virt_to_phys(pkt->payload));
+ enable_dma_buffer1(ep->indma); // reenable
+ } else {
+ set_dma_count0(ep->indma, pkt->size);
+ set_dma_addr0(ep->indma, virt_to_phys(pkt->payload));
+ enable_dma_buffer0(ep->indma); // reenable
+ }
+ if (dma_halted(ep->indma))
+ start_dma(ep->indma);
+}
+
+
+/*
+ * This routine is called when a packet in the inlist has been
+ * completed. Frees the completed packet and starts sending the
+ * next. EP spinlock must be held when calling.
+ */
+static usbdev_pkt_t *
+send_packet_complete(endpoint_t * ep)
+{
+ usbdev_pkt_t *pkt = unlink_head(&ep->inlist);
+
+ if (pkt) {
+ pkt->status =
+ (au_readl(ep->reg->ctrl_stat) & USBDEV_CS_NAK) ?
+ PKT_STATUS_NAK : PKT_STATUS_ACK;
+
+ vdbg("%s: ep%d, %s pkt=%p, list count=%d", __FUNCTION__,
+ ep->address, (pkt->status & PKT_STATUS_NAK) ?
+ "NAK" : "ACK", pkt, ep->inlist.count);
+ }
+
+ /*
+ * The write fifo should already be drained if things are
+ * working right, but flush it anyway just in case.
+ */
+ flush_write_fifo(ep);
+
+ // begin transmitting next packet in the inlist
+ if (ep->inlist.count) {
+ kickstart_send_packet(ep);
+ }
+
+ return pkt;
+}
+
+/*
+ * Add a new packet to the tail of the given ep's packet
+ * inlist. The transmit complete interrupt frees packets from
+ * the head of this list. EP spinlock must be held when calling.
+ */
+static int
+send_packet(struct usb_dev* dev, usbdev_pkt_t *pkt, int async)
+{
+ pkt_list_t *list;
+ endpoint_t* ep;
+
+ if (!pkt || !(ep = epaddr_to_ep(dev, pkt->ep_addr)))
+ return -EINVAL;
+
+ if (!pkt->size)
+ return 0;
+
+ list = &ep->inlist;
+
+ if (!async && list->count) {
+ halt_dma(ep->indma);
+ flush_pkt_list(list);
+ }
+
+ link_tail(ep, list, pkt);
+
+ vdbg("%s: ep%d, pkt=%p, size=%d, list count=%d", __FUNCTION__,
+ ep->address, pkt, pkt->size, list->count);
+
+ if (list->count == 1) {
+ /*
+ * if the packet count is one, it means the list was empty,
+ * and no more data will go out this ep until we kick-start
+ * it again.
+ */
+ kickstart_send_packet(ep);
+ }
+
+ return pkt->size;
+}
+
+/*
+ * This routine is called to restart reception of a packet.
+ * EP spinlock must be held when calling.
+ */
+static void
+kickstart_receive_packet(endpoint_t * ep)
+{
+ usbdev_pkt_t *pkt;
+
+ // get and link a new packet for next reception
+ if (!(pkt = add_packet(ep, &ep->outlist, ep->max_pkt_size))) {
+ err("%s: could not alloc new packet", __FUNCTION__);
+ return;
+ }
+
+ if (get_dma_active_buffer(ep->outdma) == 1) {
+ clear_dma_done1(ep->outdma);
+ set_dma_count1(ep->outdma, ep->max_pkt_size);
+ set_dma_count0(ep->outdma, 0);
+ set_dma_addr1(ep->outdma, virt_to_phys(pkt->payload));
+ enable_dma_buffer1(ep->outdma); // reenable
+ } else {
+ clear_dma_done0(ep->outdma);
+ set_dma_count0(ep->outdma, ep->max_pkt_size);
+ set_dma_count1(ep->outdma, 0);
+ set_dma_addr0(ep->outdma, virt_to_phys(pkt->payload));
+ enable_dma_buffer0(ep->outdma); // reenable
+ }
+ if (dma_halted(ep->outdma))
+ start_dma(ep->outdma);
+}
+
+
+/*
+ * This routine is called when a packet in the outlist has been
+ * completed (received) and we need to prepare for a new packet
+ * to be received. Halts DMA and computes the packet size from the
+ * remaining DMA counter. Then prepares a new packet for reception
+ * and restarts DMA. FIXME: what if another packet comes in
+ * on top of the completed packet? Counter would be wrong.
+ * EP spinlock must be held when calling.
+ */
+static usbdev_pkt_t *
+receive_packet_complete(endpoint_t * ep)
+{
+ usbdev_pkt_t *pkt = ep->outlist.tail;
+ u32 cs;
+
+ halt_dma(ep->outdma);
+
+ cs = au_readl(ep->reg->ctrl_stat);
+
+ if (!pkt)
+ return NULL;
+
+ pkt->size = ep->max_pkt_size - get_dma_residue(ep->outdma);
+ if (pkt->size)
+ dma_cache_inv((unsigned long)pkt->payload, pkt->size);
+ /*
+ * need to pull out any remaining bytes in the FIFO.
+ */
+ endpoint_fifo_read(ep);
+ /*
+ * should be drained now, but flush anyway just in case.
+ */
+ flush_read_fifo(ep);
+
+ pkt->status = (cs & USBDEV_CS_NAK) ? PKT_STATUS_NAK : PKT_STATUS_ACK;
+ if (ep->address == 0 && (cs & USBDEV_CS_SU))
+ pkt->status |= PKT_STATUS_SU;
+
+ vdbg("%s: ep%d, %s pkt=%p, size=%d", __FUNCTION__,
+ ep->address, (pkt->status & PKT_STATUS_NAK) ?
+ "NAK" : "ACK", pkt, pkt->size);
+
+ kickstart_receive_packet(ep);
+
+ return pkt;
+}
+
+
+/*
+ ****************************************************************************
+ * Here starts the standard device request handlers. They are
+ * all called by do_setup() via a table of function pointers.
+ ****************************************************************************
+ */
+
+static ep0_stage_t
+do_get_status(struct usb_dev* dev, struct usb_ctrlrequest* setup)
+{
+ switch (setup->bRequestType) {
+ case 0x80: // Device
+ // FIXME: send device status
+ break;
+ case 0x81: // Interface
+ // FIXME: send interface status
+ break;
+ case 0x82: // End Point
+ // FIXME: send endpoint status
+ break;
+ default:
+ // Invalid Command
+ endpoint_stall(&dev->ep[0]); // Stall End Point 0
+ break;
+ }
+
+ return STATUS_STAGE;
+}
+
+static ep0_stage_t
+do_clear_feature(struct usb_dev* dev, struct usb_ctrlrequest* setup)
+{
+ switch (setup->bRequestType) {
+ case 0x00: // Device
+ if ((le16_to_cpu(setup->wValue) & 0xff) == 1)
+ dev->remote_wakeup_en = 0;
+ else
+ endpoint_stall(&dev->ep[0]);
+ break;
+ case 0x02: // End Point
+ if ((le16_to_cpu(setup->wValue) & 0xff) == 0) {
+ endpoint_t *ep =
+ epaddr_to_ep(dev,
+ le16_to_cpu(setup->wIndex) & 0xff);
+
+ endpoint_unstall(ep);
+ endpoint_reset_datatoggle(ep);
+ } else
+ endpoint_stall(&dev->ep[0]);
+ break;
+ }
+
+ return SETUP_STAGE;
+}
+
+static ep0_stage_t
+do_reserved(struct usb_dev* dev, struct usb_ctrlrequest* setup)
+{
+ // Invalid request, stall End Point 0
+ endpoint_stall(&dev->ep[0]);
+ return SETUP_STAGE;
+}
+
+static ep0_stage_t
+do_set_feature(struct usb_dev* dev, struct usb_ctrlrequest* setup)
+{
+ switch (setup->bRequestType) {
+ case 0x00: // Device
+ if ((le16_to_cpu(setup->wValue) & 0xff) == 1)
+ dev->remote_wakeup_en = 1;
+ else
+ endpoint_stall(&dev->ep[0]);
+ break;
+ case 0x02: // End Point
+ if ((le16_to_cpu(setup->wValue) & 0xff) == 0) {
+ endpoint_t *ep =
+ epaddr_to_ep(dev,
+ le16_to_cpu(setup->wIndex) & 0xff);
+
+ endpoint_stall(ep);
+ } else
+ endpoint_stall(&dev->ep[0]);
+ break;
+ }
+
+ return SETUP_STAGE;
+}
+
+static ep0_stage_t
+do_set_address(struct usb_dev* dev, struct usb_ctrlrequest* setup)
+{
+ int new_state = dev->state;
+ int new_addr = le16_to_cpu(setup->wValue);
+
+ dbg("%s: our address=%d", __FUNCTION__, new_addr);
+
+ if (new_addr > 127) {
+ // usb spec doesn't tell us what to do, so just go to
+ // default state
+ new_state = DEFAULT;
+ dev->address = 0;
+ } else if (dev->address != new_addr) {
+ dev->address = new_addr;
+ new_state = ADDRESS;
+ }
+
+ if (dev->state != new_state) {
+ dev->state = new_state;
+ /* inform function layer of usbdev state change */
+ dev->func_cb(CB_NEW_STATE, dev->state, dev->cb_data);
+ }
+
+ return SETUP_STAGE;
+}
+
+static ep0_stage_t
+do_get_descriptor(struct usb_dev* dev, struct usb_ctrlrequest* setup)
+{
+ int strnum, desc_len = le16_to_cpu(setup->wLength);
+
+ switch (le16_to_cpu(setup->wValue) >> 8) {
+ case USB_DT_DEVICE:
+ // send device descriptor!
+ desc_len = desc_len > dev->dev_desc->bLength ?
+ dev->dev_desc->bLength : desc_len;
+ dbg("sending device desc, size=%d", desc_len);
+ send_packet(dev, alloc_packet(&dev->ep[0], desc_len,
+ dev->dev_desc), 0);
+ break;
+ case USB_DT_CONFIG:
+ // If the config descr index in low-byte of
+ // setup->wValue is valid, send config descr,
+ // otherwise stall ep0.
+ if ((le16_to_cpu(setup->wValue) & 0xff) == 0) {
+ // send config descriptor!
+ if (desc_len <= USB_DT_CONFIG_SIZE) {
+ dbg("sending partial config desc, size=%d",
+ desc_len);
+ send_packet(dev,
+ alloc_packet(&dev->ep[0],
+ desc_len,
+ dev->conf_desc),
+ 0);
+ } else {
+ int len = le16_to_cpu(dev->conf_desc->wTotalLength);
+ dbg("sending whole config desc,"
+ " size=%d, our size=%d", desc_len, len);
+ desc_len = desc_len > len ? len : desc_len;
+ send_packet(dev,
+ alloc_packet(&dev->ep[0],
+ desc_len,
+ dev->full_conf_desc),
+ 0);
+ }
+ } else
+ endpoint_stall(&dev->ep[0]);
+ break;
+ case USB_DT_STRING:
+ // If the string descr index in low-byte of setup->wValue
+ // is valid, send string descr, otherwise stall ep0.
+ strnum = le16_to_cpu(setup->wValue) & 0xff;
+ if (strnum >= 0 && strnum < 6) {
+ struct usb_string_descriptor *desc =
+ dev->str_desc[strnum];
+ desc_len = desc_len > desc->bLength ?
+ desc->bLength : desc_len;
+ dbg("sending string desc %d", strnum);
+ send_packet(dev,
+ alloc_packet(&dev->ep[0], desc_len,
+ desc), 0);
+ } else
+ endpoint_stall(&dev->ep[0]);
+ break;
+ default:
+ // Invalid request
+ err("invalid get desc=%d, stalled",
+ le16_to_cpu(setup->wValue) >> 8);
+ endpoint_stall(&dev->ep[0]); // Stall endpoint 0
+ break;
+ }
+
+ return STATUS_STAGE;
+}
+
+static ep0_stage_t
+do_set_descriptor(struct usb_dev* dev, struct usb_ctrlrequest* setup)
+{
+ // TODO: implement
+ // there will be an OUT data stage (the descriptor to set)
+ return DATA_STAGE;
+}
+
+static ep0_stage_t
+do_get_configuration(struct usb_dev* dev, struct usb_ctrlrequest* setup)
+{
+ // send dev->configuration
+ dbg("sending config");
+ send_packet(dev, alloc_packet(&dev->ep[0], 1, &dev->configuration),
+ 0);
+ return STATUS_STAGE;
+}
+
+static ep0_stage_t
+do_set_configuration(struct usb_dev* dev, struct usb_ctrlrequest* setup)
+{
+ // set active config to low-byte of setup->wValue
+ dev->configuration = le16_to_cpu(setup->wValue) & 0xff;
+ dbg("set config, config=%d", dev->configuration);
+ if (!dev->configuration && dev->state > DEFAULT) {
+ dev->state = ADDRESS;
+ /* inform function layer of usbdev state change */
+ dev->func_cb(CB_NEW_STATE, dev->state, dev->cb_data);
+ } else if (dev->configuration == 1) {
+ dev->state = CONFIGURED;
+ /* inform function layer of usbdev state change */
+ dev->func_cb(CB_NEW_STATE, dev->state, dev->cb_data);
+ } else {
+ // FIXME: "respond with request error" - how?
+ }
+
+ return SETUP_STAGE;
+}
+
+static ep0_stage_t
+do_get_interface(struct usb_dev* dev, struct usb_ctrlrequest* setup)
+{
+ // interface must be zero.
+ if ((le16_to_cpu(setup->wIndex) & 0xff) || dev->state == ADDRESS) {
+ // FIXME: respond with "request error". how?
+ } else if (dev->state == CONFIGURED) {
+ // send dev->alternate_setting
+ dbg("sending alt setting");
+ send_packet(dev, alloc_packet(&dev->ep[0], 1,
+ &dev->alternate_setting), 0);
+ }
+
+ return STATUS_STAGE;
+
+}
+
+static ep0_stage_t
+do_set_interface(struct usb_dev* dev, struct usb_ctrlrequest* setup)
+{
+ if (dev->state == ADDRESS) {
+ // FIXME: respond with "request error". how?
+ } else if (dev->state == CONFIGURED) {
+ dev->interface = le16_to_cpu(setup->wIndex) & 0xff;
+ dev->alternate_setting =
+ le16_to_cpu(setup->wValue) & 0xff;
+ // interface and alternate_setting must be zero
+ if (dev->interface || dev->alternate_setting) {
+ // FIXME: respond with "request error". how?
+ }
+ }
+
+ return SETUP_STAGE;
+}
+
+static ep0_stage_t
+do_synch_frame(struct usb_dev* dev, struct usb_ctrlrequest* setup)
+{
+ // TODO
+ return SETUP_STAGE;
+}
+
+typedef ep0_stage_t (*req_method_t)(struct usb_dev* dev,
+ struct usb_ctrlrequest* setup);
+
+
+/* Table of the standard device request handlers */
+static const req_method_t req_method[] = {
+ do_get_status,
+ do_clear_feature,
+ do_reserved,
+ do_set_feature,
+ do_reserved,
+ do_set_address,
+ do_get_descriptor,
+ do_set_descriptor,
+ do_get_configuration,
+ do_set_configuration,
+ do_get_interface,
+ do_set_interface,
+ do_synch_frame
+};
+
+
+// SETUP packet request dispatcher
+static void
+do_setup (struct usb_dev* dev, struct usb_ctrlrequest* setup)
+{
+ req_method_t m;
+
+ dbg("%s: req %d %s", __FUNCTION__, setup->bRequestType,
+ get_std_req_name(setup->bRequestType));
+
+ if ((setup->bRequestType & USB_TYPE_MASK) != USB_TYPE_STANDARD ||
+ (setup->bRequestType & USB_RECIP_MASK) != USB_RECIP_DEVICE) {
+ err("%s: invalid requesttype 0x%02x", __FUNCTION__,
+ setup->bRequestType);
+ return;
+ }
+
+ if ((setup->bRequestType & 0x80) == USB_DIR_OUT && setup->wLength)
+ dbg("%s: OUT phase! length=%d", __FUNCTION__, setup->wLength);
+
+ if (setup->bRequestType < sizeof(req_method)/sizeof(req_method_t))
+ m = req_method[setup->bRequestType];
+ else
+ m = do_reserved;
+
+ dev->ep0_stage = (*m)(dev, setup);
+}
+
+/*
+ * A SETUP, DATA0, or DATA1 packet has been received
+ * on the default control endpoint's fifo.
+ */
+static void
+process_ep0_receive (struct usb_dev* dev)
+{
+ endpoint_t *ep0 = &dev->ep[0];
+ usbdev_pkt_t *pkt;
+
+ spin_lock(&ep0->lock);
+
+ // complete packet and prepare a new packet
+ pkt = receive_packet_complete(ep0);
+ if (!pkt) {
+ // FIXME: should put a warn/err here.
+ spin_unlock(&ep0->lock);
+ return;
+ }
+
+ // unlink immediately from endpoint.
+ unlink_head(&ep0->outlist);
+
+ // override current stage if h/w says it's a setup packet
+ if (pkt->status & PKT_STATUS_SU)
+ dev->ep0_stage = SETUP_STAGE;
+
+ switch (dev->ep0_stage) {
+ case SETUP_STAGE:
+ vdbg("SU bit is %s in setup stage",
+ (pkt->status & PKT_STATUS_SU) ? "set" : "not set");
+
+ if (pkt->size == sizeof(struct usb_ctrlrequest)) {
+#ifdef VDEBUG
+ if (pkt->status & PKT_STATUS_ACK)
+ vdbg("received SETUP");
+ else
+ vdbg("received NAK SETUP");
+#endif
+ do_setup(dev, (struct usb_ctrlrequest*)pkt->payload);
+ } else
+ err("%s: wrong size SETUP received", __FUNCTION__);
+ break;
+ case DATA_STAGE:
+ /*
+ * this setup has an OUT data stage. Of the standard
+ * device requests, only set_descriptor has this stage,
+ * so this packet is that descriptor. TODO: drop it for
+ * now, set_descriptor not implemented.
+ *
+ * Need to place a byte in the write FIFO here, to prepare
+ * to send a zero-length DATA ack packet to the host in the
+ * STATUS stage.
+ */
+ au_writel(0, ep0->reg->write_fifo);
+ dbg("received OUT stage DATAx on EP0, size=%d", pkt->size);
+ dev->ep0_stage = SETUP_STAGE;
+ break;
+ case STATUS_STAGE:
+ // this setup had an IN data stage, and host is ACK'ing
+ // the packet we sent during that stage.
+ if (pkt->size != 0)
+ warn("received non-zero ACK on EP0??");
+#ifdef VDEBUG
+ else
+ vdbg("received ACK on EP0");
+#endif
+ dev->ep0_stage = SETUP_STAGE;
+ break;
+ }
+
+ spin_unlock(&ep0->lock);
+ // we're done processing the packet, free it
+ kfree(pkt);
+}
+
+
+/*
+ * A DATA0/1 packet has been received on one of the OUT endpoints (4 or 5)
+ */
+static void
+process_ep_receive (struct usb_dev* dev, endpoint_t *ep)
+{
+ usbdev_pkt_t *pkt;
+
+ spin_lock(&ep->lock);
+ pkt = receive_packet_complete(ep);
+ spin_unlock(&ep->lock);
+
+ dev->func_cb(CB_PKT_COMPLETE, (unsigned long)pkt, dev->cb_data);
+}
+
+
+
+/* This ISR handles the receive complete and suspend events */
+static void
+req_sus_intr (int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct usb_dev *dev = (struct usb_dev *) dev_id;
+ u32 status;
+
+ status = au_readl(USBD_INTSTAT);
+ au_writel(status, USBD_INTSTAT); // ack'em
+
+ if (status & (1<<0))
+ process_ep0_receive(dev);
+ if (status & (1<<4))
+ process_ep_receive(dev, &dev->ep[4]);
+ if (status & (1<<5))
+ process_ep_receive(dev, &dev->ep[5]);
+}
+
+
+/* This ISR handles the DMA done events on EP0 */
+static void
+dma_done_ep0_intr(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct usb_dev *dev = (struct usb_dev *) dev_id;
+ usbdev_pkt_t* pkt;
+ endpoint_t *ep0 = &dev->ep[0];
+ u32 cs0, buff_done;
+
+ spin_lock(&ep0->lock);
+ cs0 = au_readl(ep0->reg->ctrl_stat);
+
+ // first check packet transmit done
+ if ((buff_done = get_dma_buffer_done(ep0->indma)) != 0) {
+ // transmitted a DATAx packet during DATA stage
+ // on control endpoint 0
+ // clear DMA done bit
+ if (buff_done & DMA_D0)
+ clear_dma_done0(ep0->indma);
+ if (buff_done & DMA_D1)
+ clear_dma_done1(ep0->indma);
+
+ pkt = send_packet_complete(ep0);
+ if (pkt)
+ kfree(pkt);
+ }
+
+ /*
+ * Now check packet receive done. Shouldn't get these,
+ * the receive packet complete intr should happen
+ * before the DMA done intr occurs.
+ */
+ if ((buff_done = get_dma_buffer_done(ep0->outdma)) != 0) {
+ // clear DMA done bit
+ if (buff_done & DMA_D0)
+ clear_dma_done0(ep0->outdma);
+ if (buff_done & DMA_D1)
+ clear_dma_done1(ep0->outdma);
+
+ //process_ep0_receive(dev);
+ }
+
+ spin_unlock(&ep0->lock);
+}
+
+/* This ISR handles the DMA done events on endpoints 2,3,4,5 */
+static void
+dma_done_ep_intr(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct usb_dev *dev = (struct usb_dev *) dev_id;
+ int i;
+
+ for (i = 2; i < 6; i++) {
+ u32 buff_done;
+ usbdev_pkt_t* pkt;
+ endpoint_t *ep = &dev->ep[i];
+
+ if (!ep->active) continue;
+
+ spin_lock(&ep->lock);
+
+ if (ep->direction == USB_DIR_IN) {
+ buff_done = get_dma_buffer_done(ep->indma);
+ if (buff_done != 0) {
+ // transmitted a DATAx pkt on the IN ep
+ // clear DMA done bit
+ if (buff_done & DMA_D0)
+ clear_dma_done0(ep->indma);
+ if (buff_done & DMA_D1)
+ clear_dma_done1(ep->indma);
+
+ pkt = send_packet_complete(ep);
+
+ spin_unlock(&ep->lock);
+ dev->func_cb(CB_PKT_COMPLETE,
+ (unsigned long)pkt,
+ dev->cb_data);
+ spin_lock(&ep->lock);
+ }
+ } else {
+ /*
+ * Check packet receive done (OUT ep). Shouldn't get
+ * these, the rx packet complete intr should happen
+ * before the DMA done intr occurs.
+ */
+ buff_done = get_dma_buffer_done(ep->outdma);
+ if (buff_done != 0) {
+ // received a DATAx pkt on the OUT ep
+ // clear DMA done bit
+ if (buff_done & DMA_D0)
+ clear_dma_done0(ep->outdma);
+ if (buff_done & DMA_D1)
+ clear_dma_done1(ep->outdma);
+
+ //process_ep_receive(dev, ep);
+ }
+ }
+
+ spin_unlock(&ep->lock);
+ }
+}
+
+
+/***************************************************************************
+ * Here begins the external interface functions
+ ***************************************************************************
+ */
+
+/*
+ * allocate a new packet
+ */
+int
+usbdev_alloc_packet(int ep_addr, int data_size, usbdev_pkt_t** pkt)
+{
+ endpoint_t * ep = epaddr_to_ep(&usbdev, ep_addr);
+ usbdev_pkt_t* lpkt = NULL;
+
+ if (!ep || !ep->active || ep->address < 2)
+ return -ENODEV;
+ if (data_size > ep->max_pkt_size)
+ return -EINVAL;
+
+ lpkt = *pkt = alloc_packet(ep, data_size, NULL);
+ if (!lpkt)
+ return -ENOMEM;
+ return 0;
+}
+
+
+/*
+ * packet send
+ */
+int
+usbdev_send_packet(int ep_addr, usbdev_pkt_t * pkt)
+{
+ unsigned long flags;
+ int count;
+ endpoint_t * ep;
+
+ if (!pkt || !(ep = epaddr_to_ep(&usbdev, pkt->ep_addr)) ||
+ !ep->active || ep->address < 2)
+ return -ENODEV;
+ if (ep->direction != USB_DIR_IN)
+ return -EINVAL;
+
+ spin_lock_irqsave(&ep->lock, flags);
+ count = send_packet(&usbdev, pkt, 1);
+ spin_unlock_irqrestore(&ep->lock, flags);
+
+ return count;
+}
+
+/*
+ * packet receive
+ */
+int
+usbdev_receive_packet(int ep_addr, usbdev_pkt_t** pkt)
+{
+ unsigned long flags;
+ usbdev_pkt_t* lpkt = NULL;
+ endpoint_t *ep = epaddr_to_ep(&usbdev, ep_addr);
+
+ if (!ep || !ep->active || ep->address < 2)
+ return -ENODEV;
+ if (ep->direction != USB_DIR_OUT)
+ return -EINVAL;
+
+ spin_lock_irqsave(&ep->lock, flags);
+ if (ep->outlist.count > 1)
+ lpkt = unlink_head(&ep->outlist);
+ spin_unlock_irqrestore(&ep->lock, flags);
+
+ if (!lpkt) {
+ /* no packet available */
+ *pkt = NULL;
+ return -ENODATA;
+ }
+
+ *pkt = lpkt;
+
+ return lpkt->size;
+}
+
+
+/*
+ * return total queued byte count on the endpoint.
+ */
+int
+usbdev_get_byte_count(int ep_addr)
+{
+ unsigned long flags;
+ pkt_list_t *list;
+ usbdev_pkt_t *scan;
+ int count = 0;
+ endpoint_t * ep = epaddr_to_ep(&usbdev, ep_addr);
+
+ if (!ep || !ep->active || ep->address < 2)
+ return -ENODEV;
+
+ if (ep->direction == USB_DIR_IN) {
+ list = &ep->inlist;
+
+ spin_lock_irqsave(&ep->lock, flags);
+ for (scan = list->head; scan; scan = scan->next)
+ count += scan->size;
+ spin_unlock_irqrestore(&ep->lock, flags);
+ } else {
+ list = &ep->outlist;
+
+ spin_lock_irqsave(&ep->lock, flags);
+ if (list->count > 1) {
+ for (scan = list->head; scan != list->tail;
+ scan = scan->next)
+ count += scan->size;
+ }
+ spin_unlock_irqrestore(&ep->lock, flags);
+ }
+
+ return count;
+}
+
+
+void
+usbdev_exit(void)
+{
+ endpoint_t *ep;
+ int i;
+
+ au_writel(0, USBD_INTEN); // disable usb dev ints
+ au_writel(0, USBD_ENABLE); // disable usb dev
+
+ free_irq(AU1000_USB_DEV_REQ_INT, &usbdev);
+ free_irq(AU1000_USB_DEV_SUS_INT, &usbdev);
+
+ // free all control endpoint resources
+ ep = &usbdev.ep[0];
+ free_au1000_dma(ep->indma);
+ free_au1000_dma(ep->outdma);
+ endpoint_flush(ep);
+
+ // free ep resources
+ for (i = 2; i < 6; i++) {
+ ep = &usbdev.ep[i];
+ if (!ep->active) continue;
+
+ if (ep->direction == USB_DIR_IN) {
+ free_au1000_dma(ep->indma);
+ } else {
+ free_au1000_dma(ep->outdma);
+ }
+ endpoint_flush(ep);
+ }
+
+ if (usbdev.full_conf_desc)
+ kfree(usbdev.full_conf_desc);
+}
+
+int
+usbdev_init(struct usb_device_descriptor* dev_desc,
+ struct usb_config_descriptor* config_desc,
+ struct usb_interface_descriptor* if_desc,
+ struct usb_endpoint_descriptor* ep_desc,
+ struct usb_string_descriptor* str_desc[],
+ void (*cb)(usbdev_cb_type_t, unsigned long, void *),
+ void* cb_data)
+{
+ endpoint_t *ep0;
+ int i, ret=0;
+ u8* fcd;
+
+ if (dev_desc->bNumConfigurations > 1 ||
+ config_desc->bNumInterfaces > 1 ||
+ if_desc->bNumEndpoints > 4) {
+ err("Only one config, one i/f, and no more "
+ "than 4 ep's allowed");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (!cb) {
+ err("Function-layer callback required");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (dev_desc->bMaxPacketSize0 != USBDEV_EP0_MAX_PACKET_SIZE) {
+ warn("EP0 Max Packet size must be %d",
+ USBDEV_EP0_MAX_PACKET_SIZE);
+ dev_desc->bMaxPacketSize0 = USBDEV_EP0_MAX_PACKET_SIZE;
+ }
+
+ memset(&usbdev, 0, sizeof(struct usb_dev));
+
+ usbdev.state = DEFAULT;
+ usbdev.dev_desc = dev_desc;
+ usbdev.if_desc = if_desc;
+ usbdev.conf_desc = config_desc;
+ for (i=0; i<6; i++)
+ usbdev.str_desc[i] = str_desc[i];
+ usbdev.func_cb = cb;
+ usbdev.cb_data = cb_data;
+
+ /* Initialize default control endpoint */
+ ep0 = &usbdev.ep[0];
+ ep0->active = 1;
+ ep0->type = CONTROL_EP;
+ ep0->max_pkt_size = USBDEV_EP0_MAX_PACKET_SIZE;
+ spin_lock_init(&ep0->lock);
+ ep0->desc = NULL; // ep0 has no descriptor
+ ep0->address = 0;
+ ep0->direction = 0;
+ ep0->reg = &ep_reg[0];
+
+ /* Initialize the other requested endpoints */
+ for (i = 0; i < if_desc->bNumEndpoints; i++) {
+ struct usb_endpoint_descriptor* epd = &ep_desc[i];
+ endpoint_t *ep;
+
+ if ((epd->bEndpointAddress & 0x80) == USB_DIR_IN) {
+ ep = &usbdev.ep[2];
+ ep->address = 2;
+ if (ep->active) {
+ ep = &usbdev.ep[3];
+ ep->address = 3;
+ if (ep->active) {
+ err("too many IN ep's requested");
+ ret = -ENODEV;
+ goto out;
+ }
+ }
+ } else {
+ ep = &usbdev.ep[4];
+ ep->address = 4;
+ if (ep->active) {
+ ep = &usbdev.ep[5];
+ ep->address = 5;
+ if (ep->active) {
+ err("too many OUT ep's requested");
+ ret = -ENODEV;
+ goto out;
+ }
+ }
+ }
+
+ ep->active = 1;
+ epd->bEndpointAddress &= ~0x0f;
+ epd->bEndpointAddress |= (u8)ep->address;
+ ep->direction = epd->bEndpointAddress & 0x80;
+ ep->type = epd->bmAttributes & 0x03;
+ ep->max_pkt_size = le16_to_cpu(epd->wMaxPacketSize);
+ spin_lock_init(&ep->lock);
+ ep->desc = epd;
+ ep->reg = &ep_reg[ep->address];
+ }
+
+ /*
+ * initialize the full config descriptor
+ */
+ usbdev.full_conf_desc = fcd = kmalloc(le16_to_cpu(config_desc->wTotalLength),
+ ALLOC_FLAGS);
+ if (!fcd) {
+ err("failed to alloc full config descriptor");
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ memcpy(fcd, config_desc, USB_DT_CONFIG_SIZE);
+ fcd += USB_DT_CONFIG_SIZE;
+ memcpy(fcd, if_desc, USB_DT_INTERFACE_SIZE);
+ fcd += USB_DT_INTERFACE_SIZE;
+ for (i = 0; i < if_desc->bNumEndpoints; i++) {
+ memcpy(fcd, &ep_desc[i], USB_DT_ENDPOINT_SIZE);
+ fcd += USB_DT_ENDPOINT_SIZE;
+ }
+
+ /* Now we're ready to enable the controller */
+ au_writel(0x0002, USBD_ENABLE);
+ udelay(100);
+ au_writel(0x0003, USBD_ENABLE);
+ udelay(100);
+
+ /* build and send config table based on ep descriptors */
+ for (i = 0; i < 6; i++) {
+ endpoint_t *ep;
+ if (i == 1)
+ continue; // skip dummy ep
+ ep = &usbdev.ep[i];
+ if (ep->active) {
+ au_writel((ep->address << 4) | 0x04, USBD_CONFIG);
+ au_writel(((ep->max_pkt_size & 0x380) >> 7) |
+ (ep->direction >> 4) | (ep->type << 4),
+ USBD_CONFIG);
+ au_writel((ep->max_pkt_size & 0x7f) << 1, USBD_CONFIG);
+ au_writel(0x00, USBD_CONFIG);
+ au_writel(ep->address, USBD_CONFIG);
+ } else {
+ u8 dir = (i==2 || i==3) ? DIR_IN : DIR_OUT;
+ au_writel((i << 4) | 0x04, USBD_CONFIG);
+ au_writel(((16 & 0x380) >> 7) | dir |
+ (BULK_EP << 4), USBD_CONFIG);
+ au_writel((16 & 0x7f) << 1, USBD_CONFIG);
+ au_writel(0x00, USBD_CONFIG);
+ au_writel(i, USBD_CONFIG);
+ }
+ }
+
+ /*
+ * Enable Receive FIFO Complete interrupts only. Transmit
+ * complete is being handled by the DMA done interrupts.
+ */
+ au_writel(0x31, USBD_INTEN);
+
+ /*
+ * Controller is now enabled, request DMA and IRQ
+ * resources.
+ */
+
+ /* request the USB device transfer complete interrupt */
+ if (request_irq(AU1000_USB_DEV_REQ_INT, req_sus_intr, SA_INTERRUPT,
+ "USBdev req", &usbdev)) {
+ err("Can't get device request intr");
+ ret = -ENXIO;
+ goto out;
+ }
+ /* request the USB device suspend interrupt */
+ if (request_irq(AU1000_USB_DEV_SUS_INT, req_sus_intr, SA_INTERRUPT,
+ "USBdev sus", &usbdev)) {
+ err("Can't get device suspend intr");
+ ret = -ENXIO;
+ goto out;
+ }
+
+ /* Request EP0 DMA and IRQ */
+ if ((ep0->indma = request_au1000_dma(ep_dma_id[0].id,
+ ep_dma_id[0].str,
+ dma_done_ep0_intr,
+ SA_INTERRUPT,
+ &usbdev)) < 0) {
+ err("Can't get %s DMA", ep_dma_id[0].str);
+ ret = -ENXIO;
+ goto out;
+ }
+ if ((ep0->outdma = request_au1000_dma(ep_dma_id[1].id,
+ ep_dma_id[1].str,
+ NULL, 0, NULL)) < 0) {
+ err("Can't get %s DMA", ep_dma_id[1].str);
+ ret = -ENXIO;
+ goto out;
+ }
+
+ // Flush the ep0 buffers and FIFOs
+ endpoint_flush(ep0);
+ // start packet reception on ep0
+ kickstart_receive_packet(ep0);
+
+ /* Request DMA and IRQ for the other endpoints */
+ for (i = 2; i < 6; i++) {
+ endpoint_t *ep = &usbdev.ep[i];
+ if (!ep->active)
+ continue;
+
+ // Flush the endpoint buffers and FIFOs
+ endpoint_flush(ep);
+
+ if (ep->direction == USB_DIR_IN) {
+ ep->indma =
+ request_au1000_dma(ep_dma_id[ep->address].id,
+ ep_dma_id[ep->address].str,
+ dma_done_ep_intr,
+ SA_INTERRUPT,
+ &usbdev);
+ if (ep->indma < 0) {
+ err("Can't get %s DMA",
+ ep_dma_id[ep->address].str);
+ ret = -ENXIO;
+ goto out;
+ }
+ } else {
+ ep->outdma =
+ request_au1000_dma(ep_dma_id[ep->address].id,
+ ep_dma_id[ep->address].str,
+ NULL, 0, NULL);
+ if (ep->outdma < 0) {
+ err("Can't get %s DMA",
+ ep_dma_id[ep->address].str);
+ ret = -ENXIO;
+ goto out;
+ }
+
+ // start packet reception on OUT endpoint
+ kickstart_receive_packet(ep);
+ }
+ }
+
+ out:
+ if (ret)
+ usbdev_exit();
+ return ret;
+}
+
+EXPORT_SYMBOL(usbdev_init);
+EXPORT_SYMBOL(usbdev_exit);
+EXPORT_SYMBOL(usbdev_alloc_packet);
+EXPORT_SYMBOL(usbdev_receive_packet);
+EXPORT_SYMBOL(usbdev_send_packet);
+EXPORT_SYMBOL(usbdev_get_byte_count);
diff --git a/arch/mips/au1000/csb250/Makefile b/arch/mips/au1000/csb250/Makefile
new file mode 100644
index 0000000..c0c4dcd
--- /dev/null
+++ b/arch/mips/au1000/csb250/Makefile
@@ -0,0 +1,8 @@
+#
+# Copyright 2002 Cogent Computer Systems
+# dan@embeddededge.com
+#
+# Makefile for the Cogent CSB250 Au1500 board. Copied from Pb1500.
+#
+
+obj-y := init.o board_setup.o irqmap.o
diff --git a/arch/mips/au1000/csb250/board_setup.c b/arch/mips/au1000/csb250/board_setup.c
new file mode 100644
index 0000000..90426ea
--- /dev/null
+++ b/arch/mips/au1000/csb250/board_setup.c
@@ -0,0 +1,239 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ * Cogent CSB250 board setup.
+ *
+ * Copyright 2002 Cogent Computer Systems, Inc.
+ * dan@embeddededge.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/mm.h>
+#include <linux/console.h>
+#include <linux/mc146818rtc.h>
+#include <linux/delay.h>
+
+#include <asm/cpu.h>
+#include <asm/bootinfo.h>
+#include <asm/irq.h>
+#include <asm/keyboard.h>
+#include <asm/mipsregs.h>
+#include <asm/reboot.h>
+#include <asm/pgtable.h>
+#include <asm/au1000.h>
+#include <asm/csb250.h>
+
+extern int (*board_pci_idsel)(unsigned int devsel, int assert);
+int csb250_pci_idsel(unsigned int devsel, int assert);
+
+void __init board_setup(void)
+{
+ u32 pin_func, pin_val;
+ u32 sys_freqctrl, sys_clksrc;
+
+
+ // set AUX clock to 12MHz * 8 = 96 MHz
+ au_writel(8, SYS_AUXPLL);
+ au_writel(0, SYS_PINSTATERD);
+ udelay(100);
+
+#if defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE)
+
+ /* GPIO201 is input for PCMCIA card detect */
+ /* GPIO203 is input for PCMCIA interrupt request */
+ au_writel(au_readl(GPIO2_DIR) & (u32)(~((1<<1)|(1<<3))), GPIO2_DIR);
+
+ /* zero and disable FREQ2 */
+ sys_freqctrl = au_readl(SYS_FREQCTRL0);
+ sys_freqctrl &= ~0xFFF00000;
+ au_writel(sys_freqctrl, SYS_FREQCTRL0);
+
+ /* zero and disable USBH/USBD clocks */
+ sys_clksrc = au_readl(SYS_CLKSRC);
+ sys_clksrc &= ~0x00007FE0;
+ au_writel(sys_clksrc, SYS_CLKSRC);
+
+ sys_freqctrl = au_readl(SYS_FREQCTRL0);
+ sys_freqctrl &= ~0xFFF00000;
+
+ sys_clksrc = au_readl(SYS_CLKSRC);
+ sys_clksrc &= ~0x00007FE0;
+
+ // FREQ2 = aux/2 = 48 MHz
+ sys_freqctrl |= ((0<<22) | (1<<21) | (1<<20));
+ au_writel(sys_freqctrl, SYS_FREQCTRL0);
+
+ /*
+ * Route 48MHz FREQ2 into USB Host and/or Device
+ */
+#ifdef CONFIG_USB_OHCI
+ sys_clksrc |= ((4<<12) | (0<<11) | (0<<10));
+#endif
+#ifdef CONFIG_AU1X00_USB_DEVICE
+ sys_clksrc |= ((4<<7) | (0<<6) | (0<<5));
+#endif
+ au_writel(sys_clksrc, SYS_CLKSRC);
+
+
+ pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x8000);
+#ifndef CONFIG_AU1X00_USB_DEVICE
+ // 2nd USB port is USB host
+ pin_func |= 0x8000;
+#endif
+ au_writel(pin_func, SYS_PINFUNC);
+#endif // defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE)
+
+ /* Configure GPIO2....it's used by PCI among other things.
+ */
+
+ /* Make everything but GP200 (PCI RST) an input until we get
+ * the pins set correctly.
+ */
+ au_writel(0x00000001, GPIO2_DIR);
+
+ /* Set the pins used for output.
+ * A zero bit will leave PCI reset, LEDs off, power up USB,
+ * IDSEL disabled.
+ */
+ pin_val = ((3 << 30) | (7 << 19) | (1 << 17) | (1 << 16));
+ au_writel(pin_val, GPIO2_OUTPUT);
+
+ /* Set the output direction.
+ */
+ pin_val = ((3 << 14) | (7 << 3) | (1 << 1) | (1 << 0));
+ au_writel(pin_val, GPIO2_DIR);
+
+#ifdef CONFIG_PCI
+ /* Use FREQ1 for the PCI output clock. We use the
+ * CPU clock of 384 MHz divided by 12 to get 32 MHz PCI.
+ * If Michael changes the CPU speed, we need to adjust
+ * that here as well :-).
+ */
+
+ /* zero and disable FREQ1
+ */
+ sys_freqctrl = au_readl(SYS_FREQCTRL0);
+ sys_freqctrl &= ~0x000ffc00;
+ au_writel(sys_freqctrl, SYS_FREQCTRL0);
+
+ /* zero and disable PCI clock
+ */
+ sys_clksrc = au_readl(SYS_CLKSRC);
+ sys_clksrc &= ~0x000f8000;
+ au_writel(sys_clksrc, SYS_CLKSRC);
+
+ /* Get current values (which really should match above).
+ */
+ sys_freqctrl = au_readl(SYS_FREQCTRL0);
+ sys_freqctrl &= ~0x000ffc00;
+
+ sys_clksrc = au_readl(SYS_CLKSRC);
+ sys_clksrc &= ~0x000f8000;
+
+ /* FREQ1 = cpu/12 = 32 MHz
+ */
+ sys_freqctrl |= ((5<<12) | (1<<11) | (0<<10));
+ au_writel(sys_freqctrl, SYS_FREQCTRL0);
+
+ /* Just connect the clock without further dividing.
+ */
+ sys_clksrc |= ((3<<17) | (0<<16) | (0<<15));
+ au_writel(sys_clksrc, SYS_CLKSRC);
+
+ udelay(1);
+
+ /* Now that clocks should be running, take PCI out of reset.
+ */
+ pin_val = au_readl(GPIO2_OUTPUT);
+ pin_val |= ((1 << 16) | 1);
+ au_writel(pin_val, GPIO2_OUTPUT);
+
+ // Setup PCI bus controller
+ au_writel(0, Au1500_PCI_CMEM);
+ au_writel(0x00003fff, Au1500_CFG_BASE);
+
+ /* We run big endian without any of the software byte swapping,
+ * so configure the PCI bridge to help us out.
+ */
+ au_writel(0xf | (2<<6) | (1<<5) | (1<<4), Au1500_PCI_CFG);
+
+ au_writel(0xf0000000, Au1500_PCI_MWMASK_DEV);
+ au_writel(0, Au1500_PCI_MWBASE_REV_CCL);
+ au_writel(0x02a00356, Au1500_PCI_STATCMD);
+ au_writel(0x00003c04, Au1500_PCI_HDRTYPE);
+ au_writel(0x00000008, Au1500_PCI_MBAR);
+ au_sync();
+
+ board_pci_idsel = csb250_pci_idsel;
+#endif
+
+ /* Enable sys bus clock divider when IDLE state or no bus activity. */
+ au_writel(au_readl(SYS_POWERCTRL) | (0x3 << 5), SYS_POWERCTRL);
+
+#ifdef CONFIG_RTC
+ // Enable the RTC if not already enabled
+ if (!(au_readl(0xac000028) & 0x20)) {
+ printk("enabling clock ...\n");
+ au_writel((au_readl(0xac000028) | 0x20), 0xac000028);
+ }
+ // Put the clock in BCD mode
+ if (readl(0xac00002C) & 0x4) { /* reg B */
+ au_writel(au_readl(0xac00002c) & ~0x4, 0xac00002c);
+ au_sync();
+ }
+#endif
+}
+
+/* The IDSEL is selected in the GPIO2 register. We will make device
+ * 12 appear in slot 0 and device 13 appear in slot 1.
+ */
+int
+csb250_pci_idsel(unsigned int devsel, int assert)
+{
+ int retval;
+ unsigned int gpio2_pins;
+
+ retval = 1;
+
+ /* First, disable both selects, then assert the one requested.
+ */
+ au_writel(0xc000c000, GPIO2_OUTPUT);
+ au_sync();
+
+ if (assert) {
+ if (devsel == 12)
+ gpio2_pins = 0x40000000;
+ else if (devsel == 13)
+ gpio2_pins = 0x80000000;
+ else {
+ gpio2_pins = 0xc000c000;
+ retval = 0;
+ }
+ au_writel(gpio2_pins, GPIO2_OUTPUT);
+ }
+ au_sync();
+
+ return retval;
+}
diff --git a/arch/mips/au1000/csb250/init.c b/arch/mips/au1000/csb250/init.c
new file mode 100644
index 0000000..4320057
--- /dev/null
+++ b/arch/mips/au1000/csb250/init.c
@@ -0,0 +1,95 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ * Cogent CSB250 board setup
+ *
+ * Copyright 2002 Cogent Computer Systems, Inc.
+ * dan@embeddededge.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/bootmem.h>
+#include <asm/addrspace.h>
+#include <asm/bootinfo.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+
+int prom_argc;
+char **prom_argv, **prom_envp;
+extern void __init prom_init_cmdline(void);
+extern char *prom_getenv(char *envname);
+
+/* When we get initrd working someday.........
+*/
+int my_initrd_start, my_initrd_size;
+
+/* Start arguments and environment.
+*/
+static char *csb_env[2];
+static char *csb_arg[4];
+static char *arg1 = "console=ttyS3,38400";
+static char *arg2 = "root=/dev/nfs rw ip=any";
+static char *env1 = "ethaddr=00:30:23:50:00:00";
+
+const char *get_system_type(void)
+{
+ return "Cogent CSB250";
+}
+
+int __init prom_init(int argc, char **argv, char **envp, int *prom_vec)
+{
+ unsigned char *memsize_str;
+ unsigned long memsize;
+
+ /* We use a0 and a1 to pass initrd start and size.
+ */
+ if (((uint) argc > 0) && ((uint)argv > 0)) {
+ my_initrd_start = (uint)argc;
+ my_initrd_size = (uint)argv;
+ }
+
+ /* First argv is ignored.
+ */
+ prom_argc = 3;
+ prom_argv = csb_arg;
+ prom_envp = csb_env;
+ csb_arg[1] = arg1;
+ csb_arg[2] = arg2;
+ csb_env[0] = env1;
+
+ mips_machgroup = MACH_GROUP_ALCHEMY;
+ mips_machtype = MACH_CSB250;
+
+ prom_init_cmdline();
+ memsize_str = prom_getenv("memsize");
+ if (!memsize_str) {
+ memsize = 0x02000000;
+ } else {
+ memsize = simple_strtol(memsize_str, NULL, 0);
+ }
+ add_memory_region(0, memsize, BOOT_MEM_RAM);
+ return 0;
+}
diff --git a/arch/mips/au1000/csb250/irqmap.c b/arch/mips/au1000/csb250/irqmap.c
new file mode 100644
index 0000000..5cb1166
--- /dev/null
+++ b/arch/mips/au1000/csb250/irqmap.c
@@ -0,0 +1,60 @@
+/*
+ * BRIEF MODULE DESCRIPTION
+ * Au1xxx irq map table
+ *
+ * Copyright 2003 Embedded Edge, LLC
+ * dan@embeddededge.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/kernel_stat.h>
+#include <linux/module.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/timex.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+#include <linux/delay.h>
+#include <linux/bitops.h>
+
+#include <asm/bootinfo.h>
+#include <asm/io.h>
+#include <asm/mipsregs.h>
+#include <asm/system.h>
+#include <asm/au1000.h>
+
+au1xxx_irq_map_t au1xxx_irq_map[] = {
+
+ { AU1500_GPIO_204, INTC_INT_HIGH_LEVEL, 0},
+ { AU1500_GPIO_201, INTC_INT_LOW_LEVEL, 0 },
+ { AU1500_GPIO_202, INTC_INT_LOW_LEVEL, 0 },
+ { AU1500_GPIO_203, INTC_INT_LOW_LEVEL, 0 },
+ { AU1500_GPIO_205, INTC_INT_LOW_LEVEL, 0 },
+ { AU1500_GPIO_207, INTC_INT_LOW_LEVEL, 0 },
+};
+
+int au1xxx_nr_irqs = sizeof(au1xxx_irq_map)/sizeof(au1xxx_irq_map_t);
diff --git a/arch/mips/au1000/db1x00/Makefile b/arch/mips/au1000/db1x00/Makefile
new file mode 100644
index 0000000..4c7d763
--- /dev/null
+++ b/arch/mips/au1000/db1x00/Makefile
@@ -0,0 +1,9 @@
+#
+# Copyright 2000 MontaVista Software Inc.
+# Author: MontaVista Software, Inc.
+# ppopov@mvista.com or source@mvista.com
+#
+# Makefile for the Alchemy Semiconductor Db1x00 board.
+
+lib-y := init.o board_setup.o irqmap.o
+obj-$(CONFIG_WM97XX_COMODULE) += mirage_ts.o
diff --git a/arch/mips/au1000/db1x00/board_setup.c b/arch/mips/au1000/db1x00/board_setup.c
new file mode 100644
index 0000000..ac05ba0
--- /dev/null
+++ b/arch/mips/au1000/db1x00/board_setup.c
@@ -0,0 +1,127 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ * Alchemy Db1x00 board setup.
+ *
+ * Copyright 2000 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ * ppopov@mvista.com or source@mvista.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/mm.h>
+#include <linux/console.h>
+#include <linux/mc146818rtc.h>
+#include <linux/delay.h>
+
+#include <asm/cpu.h>
+#include <asm/bootinfo.h>
+#include <asm/irq.h>
+#include <asm/mipsregs.h>
+#include <asm/reboot.h>
+#include <asm/pgtable.h>
+#include <asm/mach-au1x00/au1000.h>
+#include <asm/mach-db1x00/db1x00.h>
+
+/* not correct for db1550 */
+static BCSR * const bcsr = (BCSR *)0xAE000000;
+
+void board_reset (void)
+{
+ /* Hit BCSR.SYSTEM_CONTROL[SW_RST] */
+ au_writel(0x00000000, 0xAE00001C);
+}
+
+void __init board_setup(void)
+{
+ u32 pin_func;
+
+ pin_func = 0;
+ /* not valid for 1550 */
+#ifdef CONFIG_AU1X00_USB_DEVICE
+ // 2nd USB port is USB device
+ pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x8000);
+ au_writel(pin_func, SYS_PINFUNC);
+#endif
+
+#if defined(CONFIG_IRDA) && (defined(CONFIG_SOC_AU1000) || defined(CONFIG_SOC_AU1100))
+ /* set IRFIRSEL instead of GPIO15 */
+ pin_func = au_readl(SYS_PINFUNC) | (u32)((1<<8));
+ au_writel(pin_func, SYS_PINFUNC);
+ /* power off until the driver is in use */
+ bcsr->resets &= ~BCSR_RESETS_IRDA_MODE_MASK;
+ bcsr->resets |= BCSR_RESETS_IRDA_MODE_OFF;
+ au_sync();
+#endif
+ au_writel(0, 0xAE000010); /* turn off pcmcia power */
+
+#ifdef CONFIG_MIPS_MIRAGE
+ /* enable GPIO[31:0] inputs */
+ au_writel(0, SYS_PININPUTEN);
+
+ /* GPIO[20] is output, tristate the other input primary GPIO's */
+ au_writel((u32)(~(1<<20)), SYS_TRIOUTCLR);
+
+ /* set GPIO[210:208] instead of SSI_0 */
+ pin_func = au_readl(SYS_PINFUNC) | (u32)(1);
+
+ /* set GPIO[215:211] for LED's */
+ pin_func |= (u32)((5<<2));
+
+ /* set GPIO[214:213] for more LED's */
+ pin_func |= (u32)((5<<12));
+
+ /* set GPIO[207:200] instead of PCMCIA/LCD */
+ pin_func |= (u32)((3<<17));
+ au_writel(pin_func, SYS_PINFUNC);
+
+ /* Enable speaker amplifier. This should
+ * be part of the audio driver.
+ */
+ au_writel(au_readl(GPIO2_DIR) | 0x200, GPIO2_DIR);
+ au_writel(0x02000200, GPIO2_OUTPUT);
+#endif
+
+ au_sync();
+
+#ifdef CONFIG_MIPS_DB1000
+ printk("AMD Alchemy Au1000/Db1000 Board\n");
+#endif
+#ifdef CONFIG_MIPS_DB1500
+ printk("AMD Alchemy Au1500/Db1500 Board\n");
+#endif
+#ifdef CONFIG_MIPS_DB1100
+ printk("AMD Alchemy Au1100/Db1100 Board\n");
+#endif
+#ifdef CONFIG_MIPS_BOSPORUS
+ printk("AMD Alchemy Bosporus Board\n");
+#endif
+#ifdef CONFIG_MIPS_MIRAGE
+ printk("AMD Alchemy Mirage Board\n");
+#endif
+#ifdef CONFIG_MIPS_DB1550
+ printk("AMD Alchemy Au1550/Db1550 Board\n");
+#endif
+}
diff --git a/arch/mips/au1000/db1x00/init.c b/arch/mips/au1000/db1x00/init.c
new file mode 100644
index 0000000..51eee94
--- /dev/null
+++ b/arch/mips/au1000/db1x00/init.c
@@ -0,0 +1,74 @@
+/*
+ * BRIEF MODULE DESCRIPTION
+ * PB1000 board setup
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ * ppopov@mvista.com or source@mvista.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/bootmem.h>
+#include <asm/addrspace.h>
+#include <asm/bootinfo.h>
+#include <linux/config.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+
+int prom_argc;
+char **prom_argv, **prom_envp;
+extern void __init prom_init_cmdline(void);
+extern char *prom_getenv(char *envname);
+
+const char *get_system_type(void)
+{
+#ifdef CONFIG_MIPS_BOSPORUS
+ return "Alchemy Bosporus Gateway Reference";
+#else
+ return "Alchemy Db1x00";
+#endif
+}
+
+void __init prom_init(void)
+{
+ unsigned char *memsize_str;
+ unsigned long memsize;
+
+ prom_argc = fw_arg0;
+ prom_argv = (char **) fw_arg1;
+ prom_envp = (char **) fw_arg2;
+
+ mips_machgroup = MACH_GROUP_ALCHEMY;
+ mips_machtype = MACH_DB1000; /* set the platform # */
+
+ prom_init_cmdline();
+
+ memsize_str = prom_getenv("memsize");
+ if (!memsize_str)
+ memsize = 0x04000000;
+ else
+ memsize = simple_strtol(memsize_str, NULL, 0);
+ add_memory_region(0, memsize, BOOT_MEM_RAM);
+}
diff --git a/arch/mips/au1000/db1x00/irqmap.c b/arch/mips/au1000/db1x00/irqmap.c
new file mode 100644
index 0000000..8f6ef0d
--- /dev/null
+++ b/arch/mips/au1000/db1x00/irqmap.c
@@ -0,0 +1,72 @@
+/*
+ * BRIEF MODULE DESCRIPTION
+ * Au1xxx irq map table
+ *
+ * Copyright 2003 Embedded Edge, LLC
+ * dan@embeddededge.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/kernel_stat.h>
+#include <linux/module.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/timex.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+#include <linux/delay.h>
+#include <linux/bitops.h>
+
+#include <asm/bootinfo.h>
+#include <asm/io.h>
+#include <asm/mipsregs.h>
+#include <asm/system.h>
+#include <asm/mach-au1x00/au1000.h>
+
+au1xxx_irq_map_t au1xxx_irq_map[] = {
+
+#ifndef CONFIG_MIPS_MIRAGE
+#ifdef CONFIG_MIPS_DB1550
+ { AU1000_GPIO_3, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 0 IRQ# */
+ { AU1000_GPIO_5, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 1 IRQ# */
+#else
+ { AU1000_GPIO_0, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 0 Fully_Interted# */
+ { AU1000_GPIO_1, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 0 STSCHG# */
+ { AU1000_GPIO_2, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 0 IRQ# */
+
+ { AU1000_GPIO_3, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 1 Fully_Interted# */
+ { AU1000_GPIO_4, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 1 STSCHG# */
+ { AU1000_GPIO_5, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 1 IRQ# */
+#endif
+#else
+ { AU1000_GPIO_7, INTC_INT_RISE_EDGE, 0 }, /* touchscreen pen down */
+#endif
+
+};
+
+int au1xxx_nr_irqs = sizeof(au1xxx_irq_map)/sizeof(au1xxx_irq_map_t);
diff --git a/arch/mips/au1000/db1x00/mirage_ts.c b/arch/mips/au1000/db1x00/mirage_ts.c
new file mode 100644
index 0000000..ade35e4
--- /dev/null
+++ b/arch/mips/au1000/db1x00/mirage_ts.c
@@ -0,0 +1,261 @@
+/*
+ * linux/arch/mips/au1000/db1x00/mirage_ts.c
+ *
+ * BRIEF MODULE DESCRIPTION
+ * Glue between Mirage board-specific touchscreen pieces
+ * and generic Wolfson Codec touchscreen support.
+ *
+ * Based on pb1100_ts.c used in Hydrogen II.
+ *
+ * Copyright (c) 2003 Embedded Edge, LLC
+ * dan@embeddededge.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/poll.h>
+#include <linux/proc_fs.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/wait.h>
+
+#include <asm/segment.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+#include <asm/delay.h>
+#include <asm/au1000.h>
+
+/*
+ * Imported interface to Wolfson Codec driver.
+ */
+extern void *wm97xx_ts_get_handle(int which);
+extern int wm97xx_ts_ready(void* ts_handle);
+extern void wm97xx_ts_set_cal(void* ts_handle, int xscale, int xtrans, int yscale, int ytrans);
+extern u16 wm97xx_ts_get_ac97(void* ts_handle, u8 reg);
+extern void wm97xx_ts_set_ac97(void* ts_handle, u8 reg, u16 val);
+extern int wm97xx_ts_read_data(void* ts_handle, long* x, long* y, long* pressure);
+extern void wm97xx_ts_send_data(void* ts_handle, long x, long y, long z);
+
+int wm97xx_comodule_present = 1;
+
+
+#define TS_NAME "mirage_ts"
+
+#define err(format, arg...) printk(KERN_ERR TS_NAME ": " format "\n" , ## arg)
+#define info(format, arg...) printk(KERN_INFO TS_NAME ": " format "\n" , ## arg)
+#define warn(format, arg...) printk(KERN_WARNING TS_NAME ": " format "\n" , ## arg)
+#define DPRINTK(format, arg...) printk("%s: " format "\n", __FUNCTION__ , ## arg)
+
+
+#define PEN_DOWN_IRQ AU1000_GPIO_7
+
+static struct task_struct *ts_task = 0;
+static DECLARE_COMPLETION(ts_complete);
+static DECLARE_WAIT_QUEUE_HEAD(pendown_wait);
+
+#ifdef CONFIG_WM97XX_FIVEWIRETS
+static int release_pressure = 1;
+#else
+static int release_pressure = 50;
+#endif
+
+typedef struct {
+ long x;
+ long y;
+} DOWN_EVENT;
+
+#define SAMPLE_RATE 50 /* samples per second */
+#define PEN_DEBOUNCE 5 /* samples for settling - fn of SAMPLE_RATE */
+#define PEN_UP_TIMEOUT 10 /* in seconds */
+#define PEN_UP_SETTLE 5 /* samples per second */
+
+static struct {
+ int xscale;
+ int xtrans;
+ int yscale;
+ int ytrans;
+} mirage_ts_cal =
+{
+#if 0
+ xscale: 84,
+ xtrans: -157,
+ yscale: 66,
+ ytrans: -150,
+#else
+ xscale: 84,
+ xtrans: -150,
+ yscale: 66,
+ ytrans: -146,
+#endif
+};
+
+
+static void pendown_irq(int irqnr, void *devid, struct pt_regs *regs)
+{
+//DPRINTK("got one 0x%x", au_readl(SYS_PINSTATERD));
+ wake_up(&pendown_wait);
+}
+
+static int ts_thread(void *id)
+{
+ static int pen_was_down = 0;
+ static DOWN_EVENT pen_xy;
+ long x, y, z;
+ void *ts; /* handle */
+ struct task_struct *tsk = current;
+ int timeout = HZ / SAMPLE_RATE;
+
+ ts_task = tsk;
+
+ daemonize();
+ tsk->tty = NULL;
+ tsk->policy = SCHED_FIFO;
+ tsk->rt_priority = 1;
+ strcpy(tsk->comm, "touchscreen");
+
+ /* only want to receive SIGKILL */
+ spin_lock_irq(&tsk->sigmask_lock);
+ siginitsetinv(&tsk->blocked, sigmask(SIGKILL));
+ recalc_sigpending(tsk);
+ spin_unlock_irq(&tsk->sigmask_lock);
+
+ /* get handle for codec */
+ ts = wm97xx_ts_get_handle(0);
+
+ /* proceed only after everybody is ready */
+ wait_event_timeout(pendown_wait, wm97xx_ts_ready(ts), HZ/4);
+
+ /* board-specific calibration */
+ wm97xx_ts_set_cal(ts,
+ mirage_ts_cal.xscale,
+ mirage_ts_cal.xtrans,
+ mirage_ts_cal.yscale,
+ mirage_ts_cal.ytrans);
+
+ /* route Wolfson pendown interrupts to our GPIO */
+ au_sync();
+ wm97xx_ts_set_ac97(ts, 0x4c, wm97xx_ts_get_ac97(ts, 0x4c) & ~0x0008);
+ au_sync();
+ wm97xx_ts_set_ac97(ts, 0x56, wm97xx_ts_get_ac97(ts, 0x56) & ~0x0008);
+ au_sync();
+ wm97xx_ts_set_ac97(ts, 0x52, wm97xx_ts_get_ac97(ts, 0x52) | 0x2008);
+ au_sync();
+
+ for (;;) {
+ interruptible_sleep_on_timeout(&pendown_wait, timeout);
+ disable_irq(PEN_DOWN_IRQ);
+ if (signal_pending(tsk)) {
+ break;
+ }
+
+ /* read codec */
+ if (!wm97xx_ts_read_data(ts, &x, &y, &z))
+ z = 0; /* treat no-data and pen-up the same */
+
+ if (signal_pending(tsk)) {
+ break;
+ }
+
+ if (z >= release_pressure) {
+ y = ~y; /* top to bottom */
+ if (pen_was_down > 1 /*&& pen_was_down < PEN_DEBOUNCE*/) {//THXXX
+ /* bounce ? */
+ x = pen_xy.x;
+ y = pen_xy.y;
+ --pen_was_down;
+ } else if (pen_was_down <= 1) {
+ pen_xy.x = x;
+ pen_xy.y = y;
+ if (pen_was_down)
+ wm97xx_ts_send_data(ts, x, y, z);
+ pen_was_down = PEN_DEBOUNCE;
+ }
+ //wm97xx_ts_send_data(ts, x, y, z);
+ timeout = HZ / SAMPLE_RATE;
+ } else {
+ if (pen_was_down) {
+ if (--pen_was_down)
+ z = release_pressure;
+ else //THXXX
+ wm97xx_ts_send_data(ts, pen_xy.x, pen_xy.y, z);
+ }
+ /* The pendown signal takes some time to settle after
+ * reading the pen pressure so wait a little
+ * before enabling the pen.
+ */
+ if (! pen_was_down) {
+// interruptible_sleep_on_timeout(&pendown_wait, HZ / PEN_UP_SETTLE);
+ timeout = HZ * PEN_UP_TIMEOUT;
+ }
+ }
+ enable_irq(PEN_DOWN_IRQ);
+ }
+ enable_irq(PEN_DOWN_IRQ);
+ ts_task = NULL;
+ complete(&ts_complete);
+ return 0;
+}
+
+static int __init ts_mirage_init(void)
+{
+ int ret;
+
+ /* pen down signal is connected to GPIO 7 */
+
+ ret = request_irq(PEN_DOWN_IRQ, pendown_irq, 0, "ts-pendown", NULL);
+ if (ret) {
+ err("unable to get pendown irq%d: [%d]", PEN_DOWN_IRQ, ret);
+ return ret;
+ }
+
+ lock_kernel();
+ ret = kernel_thread(ts_thread, NULL, CLONE_FS | CLONE_FILES);
+ if (ret < 0) {
+ unlock_kernel();
+ return ret;
+ }
+ unlock_kernel();
+
+ info("Mirage touchscreen IRQ initialized.");
+
+ return 0;
+}
+
+static void __exit ts_mirage_exit(void)
+{
+ if (ts_task) {
+ send_sig(SIGKILL, ts_task, 1);
+ wait_for_completion(&ts_complete);
+ }
+
+ free_irq(PEN_DOWN_IRQ, NULL);
+}
+
+module_init(ts_mirage_init);
+module_exit(ts_mirage_exit);
+
diff --git a/arch/mips/au1000/hydrogen3/Makefile b/arch/mips/au1000/hydrogen3/Makefile
new file mode 100644
index 0000000..974f792
--- /dev/null
+++ b/arch/mips/au1000/hydrogen3/Makefile
@@ -0,0 +1,9 @@
+#
+# Copyright 2000 MontaVista Software Inc.
+# Author: MontaVista Software, Inc.
+# ppopov@mvista.com or source@mvista.com
+#
+# Makefile for the Alchemy Semiconductor PB1000 board.
+#
+
+obj-y := init.o board_setup.o irqmap.o
diff --git a/arch/mips/au1000/hydrogen3/board_setup.c b/arch/mips/au1000/hydrogen3/board_setup.c
new file mode 100644
index 0000000..2efae10
--- /dev/null
+++ b/arch/mips/au1000/hydrogen3/board_setup.c
@@ -0,0 +1,70 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ * Alchemy Db1x00 board setup.
+ *
+ * Copyright 2000 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ * ppopov@mvista.com or source@mvista.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/mm.h>
+#include <linux/console.h>
+#include <linux/mc146818rtc.h>
+#include <linux/delay.h>
+
+#include <asm/cpu.h>
+#include <asm/bootinfo.h>
+#include <asm/irq.h>
+#include <asm/keyboard.h>
+#include <asm/mipsregs.h>
+#include <asm/reboot.h>
+#include <asm/pgtable.h>
+#include <asm/au1000.h>
+
+void board_reset (void)
+{
+}
+
+void __init board_setup(void)
+{
+ u32 pin_func;
+
+#ifdef CONFIG_AU1X00_USB_DEVICE
+ // 2nd USB port is USB device
+ pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x8000);
+ au_writel(pin_func, SYS_PINFUNC);
+#endif
+
+#if defined(CONFIG_IRDA) && (defined(CONFIG_SOC_AU1000) || defined(CONFIG_SOC_AU1100))
+ /* set IRFIRSEL instead of GPIO15 */
+ pin_func = au_readl(SYS_PINFUNC) | (u32)((1<<8));
+ au_writel(pin_func, SYS_PINFUNC);
+ au_sync();
+#endif
+
+ printk("AMD Alchemy Hydrogen3 Board\n");
+}
diff --git a/arch/mips/au1000/hydrogen3/init.c b/arch/mips/au1000/hydrogen3/init.c
new file mode 100644
index 0000000..eee4adf
--- /dev/null
+++ b/arch/mips/au1000/hydrogen3/init.c
@@ -0,0 +1,77 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ * PB1000 board setup
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ * ppopov@mvista.com or source@mvista.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/bootmem.h>
+#include <asm/addrspace.h>
+#include <asm/bootinfo.h>
+#include <linux/config.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+
+int prom_argc;
+char **prom_argv, **prom_envp;
+extern void __init prom_init_cmdline(void);
+extern char *prom_getenv(char *envname);
+
+const char *get_system_type(void)
+{
+#ifdef CONFIG_MIPS_BOSPORUS
+ return "Alchemy Bosporus Gateway Reference";
+#else
+ return "Alchemy Db1x00";
+#endif
+}
+
+int __init prom_init(int argc, char **argv, char **envp, int *prom_vec)
+{
+ unsigned char *memsize_str;
+ unsigned long memsize;
+
+ prom_argc = argc;
+ prom_argv = argv;
+ prom_envp = envp;
+
+ mips_machgroup = MACH_GROUP_ALCHEMY;
+ mips_machtype = MACH_DB1000; /* set the platform # */
+ prom_init_cmdline();
+
+ memsize_str = prom_getenv("memsize");
+ if (!memsize_str) {
+ memsize = 0x04000000;
+ } else {
+ memsize = simple_strtol(memsize_str, NULL, 0);
+ }
+ add_memory_region(0, memsize, BOOT_MEM_RAM);
+ return 0;
+}
diff --git a/arch/mips/au1000/hydrogen3/irqmap.c b/arch/mips/au1000/hydrogen3/irqmap.c
new file mode 100644
index 0000000..6eacaa0
--- /dev/null
+++ b/arch/mips/au1000/hydrogen3/irqmap.c
@@ -0,0 +1,56 @@
+/*
+ * BRIEF MODULE DESCRIPTION
+ * Au1xxx irq map table
+ *
+ * Copyright 2003 Embedded Edge, LLC
+ * dan@embeddededge.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/kernel_stat.h>
+#include <linux/module.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/timex.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+#include <linux/delay.h>
+#include <linux/bitops.h>
+
+#include <asm/bootinfo.h>
+#include <asm/io.h>
+#include <asm/mipsregs.h>
+#include <asm/system.h>
+#include <asm/au1000.h>
+
+au1xxx_irq_map_t au1xxx_irq_map[] = {
+
+ /* { AU1500_GPIO_205, INTC_INT_LOW_LEVEL, 0 }, */
+ { AU1000_GPIO_21, INTC_INT_LOW_LEVEL, 0 },
+};
+
+int au1xxx_nr_irqs = sizeof(au1xxx_irq_map)/sizeof(au1xxx_irq_map_t);
diff --git a/arch/mips/au1000/mtx-1/Makefile b/arch/mips/au1000/mtx-1/Makefile
new file mode 100644
index 0000000..764bf9f
--- /dev/null
+++ b/arch/mips/au1000/mtx-1/Makefile
@@ -0,0 +1,10 @@
+#
+# Copyright 2003 MontaVista Software Inc.
+# Author: MontaVista Software, Inc.
+# ppopov@mvista.com or source@mvista.com
+# Bruno Randolf <bruno.randolf@4g-systems.biz>
+#
+# Makefile for 4G Systems MTX-1 board.
+#
+
+lib-y := init.o board_setup.o irqmap.o
diff --git a/arch/mips/au1000/mtx-1/board_setup.c b/arch/mips/au1000/mtx-1/board_setup.c
new file mode 100644
index 0000000..638de7b
--- /dev/null
+++ b/arch/mips/au1000/mtx-1/board_setup.c
@@ -0,0 +1,89 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ * 4G Systems MTX-1 board setup.
+ *
+ * Copyright 2003 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ * ppopov@mvista.com or source@mvista.com
+ * Bruno Randolf <bruno.randolf@4g-systems.biz>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/mm.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+
+#include <asm/cpu.h>
+#include <asm/bootinfo.h>
+#include <asm/irq.h>
+#include <asm/mipsregs.h>
+#include <asm/reboot.h>
+#include <asm/pgtable.h>
+#include <asm/mach-au1x00/au1000.h>
+
+void board_reset (void)
+{
+ /* Hit BCSR.SYSTEM_CONTROL[SW_RST] */
+ au_writel(0x00000000, 0xAE00001C);
+}
+
+void __init board_setup(void)
+{
+#if defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE)
+#ifdef CONFIG_AU1X00_USB_DEVICE
+ // 2nd USB port is USB device
+ au_writel(au_readl(SYS_PINFUNC) & (u32)(~0x8000), SYS_PINFUNC);
+#endif
+ // enable USB power switch
+ au_writel( au_readl(GPIO2_DIR) | 0x10, GPIO2_DIR );
+ au_writel( 0x100000, GPIO2_OUTPUT );
+#endif // defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE)
+
+#ifdef CONFIG_PCI
+#if defined(__MIPSEB__)
+ au_writel(0xf | (2<<6) | (1<<4), Au1500_PCI_CFG);
+#else
+ au_writel(0xf, Au1500_PCI_CFG);
+#endif
+#endif
+
+ // initialize sys_pinfunc:
+ // disable second ethernet port (SYS_PF_NI2)
+ // set U3/GPIO23 to GPIO23 (SYS_PF_U3)
+ au_writel( SYS_PF_NI2 | SYS_PF_U3, SYS_PINFUNC );
+
+ // initialize GPIO
+ au_writel( 0xFFFFFFFF, SYS_TRIOUTCLR );
+ au_writel( 0x00000001, SYS_OUTPUTCLR ); // set M66EN (PCI 66MHz) to OFF
+ au_writel( 0x00000008, SYS_OUTPUTSET ); // set PCI CLKRUN# to OFF
+ au_writel( 0x00000020, SYS_OUTPUTCLR ); // set eth PHY TX_ER to OFF
+
+ // enable LED and set it to green
+ au_writel( au_readl(GPIO2_DIR) | 0x1800, GPIO2_DIR );
+ au_writel( 0x18000800, GPIO2_OUTPUT );
+
+ printk("4G Systems MTX-1 Board\n");
+}
diff --git a/arch/mips/au1000/mtx-1/init.c b/arch/mips/au1000/mtx-1/init.c
new file mode 100644
index 0000000..02e7dbc
--- /dev/null
+++ b/arch/mips/au1000/mtx-1/init.c
@@ -0,0 +1,71 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ * 4G Systems MTX-1 board setup
+ *
+ * Copyright 2003 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ * ppopov@mvista.com or source@mvista.com
+ * Bruno Randolf <bruno.randolf@4g-systems.biz>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/bootmem.h>
+#include <asm/addrspace.h>
+#include <asm/bootinfo.h>
+
+int prom_argc;
+char **prom_argv, **prom_envp;
+extern void __init prom_init_cmdline(void);
+extern char *prom_getenv(char *envname);
+
+const char *get_system_type(void)
+{
+ return "MTX-1";
+}
+
+void __init prom_init(void)
+{
+ unsigned char *memsize_str;
+ unsigned long memsize;
+
+ prom_argc = fw_arg0;
+ prom_argv = (char **) fw_arg1;
+ prom_envp = (char **) fw_arg2;
+
+ mips_machgroup = MACH_GROUP_ALCHEMY;
+ mips_machtype = MACH_MTX1; /* set the platform # */
+
+ prom_init_cmdline();
+
+ memsize_str = prom_getenv("memsize");
+ if (!memsize_str)
+ memsize = 0x04000000;
+ else
+ memsize = simple_strtol(memsize_str, NULL, 0);
+ add_memory_region(0, memsize, BOOT_MEM_RAM);
+}
diff --git a/arch/mips/au1000/mtx-1/irqmap.c b/arch/mips/au1000/mtx-1/irqmap.c
new file mode 100644
index 0000000..ddcb9d0
--- /dev/null
+++ b/arch/mips/au1000/mtx-1/irqmap.c
@@ -0,0 +1,58 @@
+/*
+ * BRIEF MODULE DESCRIPTION
+ * Au1xxx irq map table
+ *
+ * Copyright 2003 Embedded Edge, LLC
+ * dan@embeddededge.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/kernel_stat.h>
+#include <linux/module.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/timex.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+#include <linux/delay.h>
+#include <linux/bitops.h>
+
+#include <asm/bootinfo.h>
+#include <asm/io.h>
+#include <asm/mipsregs.h>
+#include <asm/system.h>
+#include <asm/mach-au1x00/au1000.h>
+
+au1xxx_irq_map_t au1xxx_irq_map[] = {
+ { AU1500_GPIO_204, INTC_INT_HIGH_LEVEL, 0},
+ { AU1500_GPIO_201, INTC_INT_LOW_LEVEL, 0 },
+ { AU1500_GPIO_202, INTC_INT_LOW_LEVEL, 0 },
+ { AU1500_GPIO_203, INTC_INT_LOW_LEVEL, 0 },
+ { AU1500_GPIO_205, INTC_INT_LOW_LEVEL, 0 },
+};
+
+int au1xxx_nr_irqs = sizeof(au1xxx_irq_map)/sizeof(au1xxx_irq_map_t);
diff --git a/arch/mips/au1000/pb1000/Makefile b/arch/mips/au1000/pb1000/Makefile
new file mode 100644
index 0000000..daa1a50
--- /dev/null
+++ b/arch/mips/au1000/pb1000/Makefile
@@ -0,0 +1,8 @@
+#
+# Copyright 2000 MontaVista Software Inc.
+# Author: MontaVista Software, Inc.
+# ppopov@mvista.com or source@mvista.com
+#
+# Makefile for the Alchemy Semiconductor PB1000 board.
+
+lib-y := init.o board_setup.o irqmap.o
diff --git a/arch/mips/au1000/pb1000/board_setup.c b/arch/mips/au1000/pb1000/board_setup.c
new file mode 100644
index 0000000..2fa211b
--- /dev/null
+++ b/arch/mips/au1000/pb1000/board_setup.c
@@ -0,0 +1,182 @@
+/*
+ * Copyright 2000 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ * ppopov@mvista.com or source@mvista.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/mm.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+
+#include <asm/cpu.h>
+#include <asm/bootinfo.h>
+#include <asm/irq.h>
+#include <asm/mipsregs.h>
+#include <asm/reboot.h>
+#include <asm/pgtable.h>
+#include <asm/mach-au1x00/au1000.h>
+#include <asm/mach-pb1x00/pb1000.h>
+
+void board_reset (void)
+{
+}
+
+void __init board_setup(void)
+{
+ u32 pin_func, static_cfg0;
+ u32 sys_freqctrl, sys_clksrc;
+ u32 prid = read_c0_prid();
+
+ // set AUX clock to 12MHz * 8 = 96 MHz
+ au_writel(8, SYS_AUXPLL);
+ au_writel(0, SYS_PINSTATERD);
+ udelay(100);
+
+#if defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE)
+ /* zero and disable FREQ2 */
+ sys_freqctrl = au_readl(SYS_FREQCTRL0);
+ sys_freqctrl &= ~0xFFF00000;
+ au_writel(sys_freqctrl, SYS_FREQCTRL0);
+
+ /* zero and disable USBH/USBD clocks */
+ sys_clksrc = au_readl(SYS_CLKSRC);
+ sys_clksrc &= ~0x00007FE0;
+ au_writel(sys_clksrc, SYS_CLKSRC);
+
+ sys_freqctrl = au_readl(SYS_FREQCTRL0);
+ sys_freqctrl &= ~0xFFF00000;
+
+ sys_clksrc = au_readl(SYS_CLKSRC);
+ sys_clksrc &= ~0x00007FE0;
+
+ switch (prid & 0x000000FF)
+ {
+ case 0x00: /* DA */
+ case 0x01: /* HA */
+ case 0x02: /* HB */
+ /* CPU core freq to 48MHz to slow it way down... */
+ au_writel(4, SYS_CPUPLL);
+
+ /*
+ * Setup 48MHz FREQ2 from CPUPLL for USB Host
+ */
+ /* FRDIV2=3 -> div by 8 of 384MHz -> 48MHz */
+ sys_freqctrl |= ((3<<22) | (1<<21) | (0<<20));
+ au_writel(sys_freqctrl, SYS_FREQCTRL0);
+
+ /* CPU core freq to 384MHz */
+ au_writel(0x20, SYS_CPUPLL);
+
+ printk("Au1000: 48MHz OHCI workaround enabled\n");
+ break;
+
+ default: /* HC and newer */
+ // FREQ2 = aux/2 = 48 MHz
+ sys_freqctrl |= ((0<<22) | (1<<21) | (1<<20));
+ au_writel(sys_freqctrl, SYS_FREQCTRL0);
+ break;
+ }
+
+ /*
+ * Route 48MHz FREQ2 into USB Host and/or Device
+ */
+#ifdef CONFIG_USB_OHCI
+ sys_clksrc |= ((4<<12) | (0<<11) | (0<<10));
+#endif
+#ifdef CONFIG_AU1X00_USB_DEVICE
+ sys_clksrc |= ((4<<7) | (0<<6) | (0<<5));
+#endif
+ au_writel(sys_clksrc, SYS_CLKSRC);
+
+ // configure pins GPIO[14:9] as GPIO
+ pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x8080);
+
+#ifndef CONFIG_AU1X00_USB_DEVICE
+ // 2nd USB port is USB host
+ pin_func |= 0x8000;
+#endif
+ au_writel(pin_func, SYS_PINFUNC);
+ au_writel(0x2800, SYS_TRIOUTCLR);
+ au_writel(0x0030, SYS_OUTPUTCLR);
+#endif // defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE)
+
+ // make gpio 15 an input (for interrupt line)
+ pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x100);
+ // we don't need I2S, so make it available for GPIO[31:29]
+ pin_func |= (1<<5);
+ au_writel(pin_func, SYS_PINFUNC);
+
+ au_writel(0x8000, SYS_TRIOUTCLR);
+
+ static_cfg0 = au_readl(MEM_STCFG0) & (u32)(~0xc00);
+ au_writel(static_cfg0, MEM_STCFG0);
+
+ // configure RCE2* for LCD
+ au_writel(0x00000004, MEM_STCFG2);
+
+ // MEM_STTIME2
+ au_writel(0x09000000, MEM_STTIME2);
+
+ // Set 32-bit base address decoding for RCE2*
+ au_writel(0x10003ff0, MEM_STADDR2);
+
+ // PCI CPLD setup
+ // expand CE0 to cover PCI
+ au_writel(0x11803e40, MEM_STADDR1);
+
+ // burst visibility on
+ au_writel(au_readl(MEM_STCFG0) | 0x1000, MEM_STCFG0);
+
+ au_writel(0x83, MEM_STCFG1); // ewait enabled, flash timing
+ au_writel(0x33030a10, MEM_STTIME1); // slower timing for FPGA
+
+ /* setup the static bus controller */
+ au_writel(0x00000002, MEM_STCFG3); /* type = PCMCIA */
+ au_writel(0x280E3D07, MEM_STTIME3); /* 250ns cycle time */
+ au_writel(0x10000000, MEM_STADDR3); /* any PCMCIA select */
+
+#ifdef CONFIG_PCI
+ au_writel(0, PCI_BRIDGE_CONFIG); // set extend byte to 0
+ au_writel(0, SDRAM_MBAR); // set mbar to 0
+ au_writel(0x2, SDRAM_CMD); // enable memory accesses
+ au_sync_delay(1);
+#endif
+
+ /* Enable Au1000 BCLK switching - note: sed1356 must not use
+ * its BCLK (Au1000 LCLK) for any timings */
+ switch (prid & 0x000000FF)
+ {
+ case 0x00: /* DA */
+ case 0x01: /* HA */
+ case 0x02: /* HB */
+ break;
+ default: /* HC and newer */
+ /* Enable sys bus clock divider when IDLE state or no bus
+ activity. */
+ au_writel(au_readl(SYS_POWERCTRL) | (0x3 << 5), SYS_POWERCTRL);
+ break;
+ }
+}
diff --git a/arch/mips/au1000/pb1000/init.c b/arch/mips/au1000/pb1000/init.c
new file mode 100644
index 0000000..34713c5
--- /dev/null
+++ b/arch/mips/au1000/pb1000/init.c
@@ -0,0 +1,69 @@
+/*
+ * BRIEF MODULE DESCRIPTION
+ * PB1000 board setup
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ * ppopov@mvista.com or source@mvista.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/bootmem.h>
+#include <asm/addrspace.h>
+#include <asm/bootinfo.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+
+int prom_argc;
+char **prom_argv, **prom_envp;
+extern void __init prom_init_cmdline(void);
+extern char *prom_getenv(char *envname);
+
+const char *get_system_type(void)
+{
+ return "Alchemy Pb1000";
+}
+
+void __init prom_init(void)
+{
+ unsigned char *memsize_str;
+ unsigned long memsize;
+
+ prom_argc = (int) fw_arg0;
+ prom_argv = (char **) fw_arg1;
+ prom_envp = (char **) fw_arg2;
+
+ mips_machgroup = MACH_GROUP_ALCHEMY;
+ mips_machtype = MACH_PB1000;
+
+ prom_init_cmdline();
+ memsize_str = prom_getenv("memsize");
+ if (!memsize_str) {
+ memsize = 0x04000000;
+ } else {
+ memsize = simple_strtol(memsize_str, NULL, 0);
+ }
+ add_memory_region(0, memsize, BOOT_MEM_RAM);
+ return 0;
+}
diff --git a/arch/mips/au1000/pb1000/irqmap.c b/arch/mips/au1000/pb1000/irqmap.c
new file mode 100644
index 0000000..a3c460e
--- /dev/null
+++ b/arch/mips/au1000/pb1000/irqmap.c
@@ -0,0 +1,54 @@
+/*
+ * BRIEF MODULE DESCRIPTION
+ * Au1xxx irq map table
+ *
+ * Copyright 2003 Embedded Edge, LLC
+ * dan@embeddededge.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/kernel_stat.h>
+#include <linux/module.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/timex.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+#include <linux/delay.h>
+#include <linux/bitops.h>
+
+#include <asm/bootinfo.h>
+#include <asm/io.h>
+#include <asm/mipsregs.h>
+#include <asm/system.h>
+#include <asm/mach-au1x00/au1000.h>
+
+au1xxx_irq_map_t au1xxx_irq_map[] = {
+ { AU1000_GPIO_15, INTC_INT_LOW_LEVEL, 0 },
+};
+
+int au1xxx_nr_irqs = sizeof(au1xxx_irq_map)/sizeof(au1xxx_irq_map_t);
diff --git a/arch/mips/au1000/pb1100/Makefile b/arch/mips/au1000/pb1100/Makefile
new file mode 100644
index 0000000..996236d
--- /dev/null
+++ b/arch/mips/au1000/pb1100/Makefile
@@ -0,0 +1,8 @@
+#
+# Copyright 2000,2001 MontaVista Software Inc.
+# Author: MontaVista Software, Inc.
+# ppopov@mvista.com or source@mvista.com
+#
+# Makefile for the Alchemy Semiconductor Pb1100 board.
+
+lib-y := init.o board_setup.o irqmap.o
diff --git a/arch/mips/au1000/pb1100/board_setup.c b/arch/mips/au1000/pb1100/board_setup.c
new file mode 100644
index 0000000..13c2f6c
--- /dev/null
+++ b/arch/mips/au1000/pb1100/board_setup.c
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2002 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ * ppopov@mvista.com or source@mvista.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/mm.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+
+#include <asm/cpu.h>
+#include <asm/bootinfo.h>
+#include <asm/irq.h>
+#include <asm/mipsregs.h>
+#include <asm/reboot.h>
+#include <asm/pgtable.h>
+#include <asm/mach-au1x00/au1000.h>
+#include <asm/mach-pb1x00/pb1100.h>
+
+void board_reset (void)
+{
+ /* Hit BCSR.SYSTEM_CONTROL[SW_RST] */
+ au_writel(0x00000000, 0xAE00001C);
+}
+
+void __init board_setup(void)
+{
+ u32 pin_func;
+ u32 sys_freqctrl, sys_clksrc;
+
+ // set AUX clock to 12MHz * 8 = 96 MHz
+ au_writel(8, SYS_AUXPLL);
+ au_writel(0, SYS_PININPUTEN);
+ udelay(100);
+
+#if defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE)
+ // configure pins GPIO[14:9] as GPIO
+ pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x80);
+
+ /* zero and disable FREQ2 */
+ sys_freqctrl = au_readl(SYS_FREQCTRL0);
+ sys_freqctrl &= ~0xFFF00000;
+ au_writel(sys_freqctrl, SYS_FREQCTRL0);
+
+ /* zero and disable USBH/USBD/IrDA clock */
+ sys_clksrc = au_readl(SYS_CLKSRC);
+ sys_clksrc &= ~0x0000001F;
+ au_writel(sys_clksrc, SYS_CLKSRC);
+
+ sys_freqctrl = au_readl(SYS_FREQCTRL0);
+ sys_freqctrl &= ~0xFFF00000;
+
+ sys_clksrc = au_readl(SYS_CLKSRC);
+ sys_clksrc &= ~0x0000001F;
+
+ // FREQ2 = aux/2 = 48 MHz
+ sys_freqctrl |= ((0<<22) | (1<<21) | (1<<20));
+ au_writel(sys_freqctrl, SYS_FREQCTRL0);
+
+ /*
+ * Route 48MHz FREQ2 into USBH/USBD/IrDA
+ */
+ sys_clksrc |= ((4<<2) | (0<<1) | 0 );
+ au_writel(sys_clksrc, SYS_CLKSRC);
+
+ /* setup the static bus controller */
+ au_writel(0x00000002, MEM_STCFG3); /* type = PCMCIA */
+ au_writel(0x280E3D07, MEM_STTIME3); /* 250ns cycle time */
+ au_writel(0x10000000, MEM_STADDR3); /* any PCMCIA select */
+
+ // get USB Functionality pin state (device vs host drive pins)
+ pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x8000);
+#ifndef CONFIG_AU1X00_USB_DEVICE
+ // 2nd USB port is USB host
+ pin_func |= 0x8000;
+#endif
+ au_writel(pin_func, SYS_PINFUNC);
+#endif // defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE)
+
+ /* Enable sys bus clock divider when IDLE state or no bus activity. */
+ au_writel(au_readl(SYS_POWERCTRL) | (0x3 << 5), SYS_POWERCTRL);
+
+ // Enable the RTC if not already enabled
+ if (!(readb(0xac000028) & 0x20)) {
+ writeb(readb(0xac000028) | 0x20, 0xac000028);
+ au_sync();
+ }
+ // Put the clock in BCD mode
+ if (readb(0xac00002C) & 0x4) { /* reg B */
+ writeb(readb(0xac00002c) & ~0x4, 0xac00002c);
+ au_sync();
+ }
+}
diff --git a/arch/mips/au1000/pb1100/init.c b/arch/mips/au1000/pb1100/init.c
new file mode 100644
index 0000000..1fae39a
--- /dev/null
+++ b/arch/mips/au1000/pb1100/init.c
@@ -0,0 +1,70 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ * Pb1100 board setup
+ *
+ * Copyright 2002 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ * ppopov@mvista.com or source@mvista.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/bootmem.h>
+#include <asm/addrspace.h>
+#include <asm/bootinfo.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+
+int prom_argc;
+char **prom_argv, **prom_envp;
+extern void __init prom_init_cmdline(void);
+extern char *prom_getenv(char *envname);
+
+const char *get_system_type(void)
+{
+ return "Alchemy Pb1100";
+}
+
+void __init prom_init(void)
+{
+ unsigned char *memsize_str;
+ unsigned long memsize;
+
+ prom_argc = fw_arg0;
+ prom_argv = (char **) fw_arg1;
+ prom_envp = (int *) fw_arg3;
+
+ mips_machgroup = MACH_GROUP_ALCHEMY;
+ mips_machtype = MACH_PB1100;
+
+ prom_init_cmdline();
+
+ memsize_str = prom_getenv("memsize");
+ if (!memsize_str)
+ memsize = 0x04000000;
+ else
+ memsize = simple_strtol(memsize_str, NULL, 0);
+
+ add_memory_region(0, memsize, BOOT_MEM_RAM);
+}
diff --git a/arch/mips/au1000/pb1100/irqmap.c b/arch/mips/au1000/pb1100/irqmap.c
new file mode 100644
index 0000000..43be715
--- /dev/null
+++ b/arch/mips/au1000/pb1100/irqmap.c
@@ -0,0 +1,57 @@
+/*
+ * BRIEF MODULE DESCRIPTION
+ * Au1xxx irq map table
+ *
+ * Copyright 2003 Embedded Edge, LLC
+ * dan@embeddededge.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/kernel_stat.h>
+#include <linux/module.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/timex.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+#include <linux/delay.h>
+#include <linux/bitops.h>
+
+#include <asm/bootinfo.h>
+#include <asm/io.h>
+#include <asm/mipsregs.h>
+#include <asm/system.h>
+#include <asm/mach-au1x00/au1000.h>
+
+au1xxx_irq_map_t au1xxx_irq_map[] = {
+ { AU1000_GPIO_9, INTC_INT_LOW_LEVEL, 0 }, // PCMCIA Card Fully_Interted#
+ { AU1000_GPIO_10, INTC_INT_LOW_LEVEL, 0 }, // PCMCIA Card STSCHG#
+ { AU1000_GPIO_11, INTC_INT_LOW_LEVEL, 0 }, // PCMCIA Card IRQ#
+ { AU1000_GPIO_13, INTC_INT_LOW_LEVEL, 0 }, // DC_IRQ#
+};
+
+int au1xxx_nr_irqs = sizeof(au1xxx_irq_map)/sizeof(au1xxx_irq_map_t);
diff --git a/arch/mips/au1000/pb1500/Makefile b/arch/mips/au1000/pb1500/Makefile
new file mode 100644
index 0000000..97a7308
--- /dev/null
+++ b/arch/mips/au1000/pb1500/Makefile
@@ -0,0 +1,8 @@
+#
+# Copyright 2000,2001 MontaVista Software Inc.
+# Author: MontaVista Software, Inc.
+# ppopov@mvista.com or source@mvista.com
+#
+# Makefile for the Alchemy Semiconductor Pb1500 board.
+
+lib-y := init.o board_setup.o irqmap.o
diff --git a/arch/mips/au1000/pb1500/board_setup.c b/arch/mips/au1000/pb1500/board_setup.c
new file mode 100644
index 0000000..30bb872
--- /dev/null
+++ b/arch/mips/au1000/pb1500/board_setup.c
@@ -0,0 +1,138 @@
+/*
+ * Copyright 2000 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ * ppopov@mvista.com or source@mvista.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/mm.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+
+#include <asm/cpu.h>
+#include <asm/bootinfo.h>
+#include <asm/irq.h>
+#include <asm/mipsregs.h>
+#include <asm/reboot.h>
+#include <asm/pgtable.h>
+#include <asm/mach-au1x00/au1000.h>
+#include <asm/mach-pb1x00/pb1500.h>
+
+void board_reset (void)
+{
+ /* Hit BCSR.SYSTEM_CONTROL[SW_RST] */
+ au_writel(0x00000000, 0xAE00001C);
+}
+
+void __init board_setup(void)
+{
+ u32 pin_func;
+ u32 sys_freqctrl, sys_clksrc;
+
+ sys_clksrc = sys_freqctrl = pin_func = 0;
+ // set AUX clock to 12MHz * 8 = 96 MHz
+ au_writel(8, SYS_AUXPLL);
+ au_writel(0, SYS_PINSTATERD);
+ udelay(100);
+
+#if defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE)
+
+ /* GPIO201 is input for PCMCIA card detect */
+ /* GPIO203 is input for PCMCIA interrupt request */
+ au_writel(au_readl(GPIO2_DIR) & (u32)(~((1<<1)|(1<<3))), GPIO2_DIR);
+
+ /* zero and disable FREQ2 */
+ sys_freqctrl = au_readl(SYS_FREQCTRL0);
+ sys_freqctrl &= ~0xFFF00000;
+ au_writel(sys_freqctrl, SYS_FREQCTRL0);
+
+ /* zero and disable USBH/USBD clocks */
+ sys_clksrc = au_readl(SYS_CLKSRC);
+ sys_clksrc &= ~0x00007FE0;
+ au_writel(sys_clksrc, SYS_CLKSRC);
+
+ sys_freqctrl = au_readl(SYS_FREQCTRL0);
+ sys_freqctrl &= ~0xFFF00000;
+
+ sys_clksrc = au_readl(SYS_CLKSRC);
+ sys_clksrc &= ~0x00007FE0;
+
+ // FREQ2 = aux/2 = 48 MHz
+ sys_freqctrl |= ((0<<22) | (1<<21) | (1<<20));
+ au_writel(sys_freqctrl, SYS_FREQCTRL0);
+
+ /*
+ * Route 48MHz FREQ2 into USB Host and/or Device
+ */
+#ifdef CONFIG_USB_OHCI
+ sys_clksrc |= ((4<<12) | (0<<11) | (0<<10));
+#endif
+#ifdef CONFIG_AU1X00_USB_DEVICE
+ sys_clksrc |= ((4<<7) | (0<<6) | (0<<5));
+#endif
+ au_writel(sys_clksrc, SYS_CLKSRC);
+
+
+ pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x8000);
+#ifndef CONFIG_AU1X00_USB_DEVICE
+ // 2nd USB port is USB host
+ pin_func |= 0x8000;
+#endif
+ au_writel(pin_func, SYS_PINFUNC);
+#endif // defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE)
+
+
+
+#ifdef CONFIG_PCI
+ // Setup PCI bus controller
+ au_writel(0, Au1500_PCI_CMEM);
+ au_writel(0x00003fff, Au1500_CFG_BASE);
+#if defined(__MIPSEB__)
+ au_writel(0xf | (2<<6) | (1<<4), Au1500_PCI_CFG);
+#else
+ au_writel(0xf, Au1500_PCI_CFG);
+#endif
+ au_writel(0xf0000000, Au1500_PCI_MWMASK_DEV);
+ au_writel(0, Au1500_PCI_MWBASE_REV_CCL);
+ au_writel(0x02a00356, Au1500_PCI_STATCMD);
+ au_writel(0x00003c04, Au1500_PCI_HDRTYPE);
+ au_writel(0x00000008, Au1500_PCI_MBAR);
+ au_sync();
+#endif
+
+ /* Enable sys bus clock divider when IDLE state or no bus activity. */
+ au_writel(au_readl(SYS_POWERCTRL) | (0x3 << 5), SYS_POWERCTRL);
+
+ /* Enable the RTC if not already enabled */
+ if (!(au_readl(0xac000028) & 0x20)) {
+ printk("enabling clock ...\n");
+ au_writel((au_readl(0xac000028) | 0x20), 0xac000028);
+ }
+ /* Put the clock in BCD mode */
+ if (readl(0xac00002C) & 0x4) { /* reg B */
+ au_writel(au_readl(0xac00002c) & ~0x4, 0xac00002c);
+ au_sync();
+ }
+}
diff --git a/arch/mips/au1000/pb1500/init.c b/arch/mips/au1000/pb1500/init.c
new file mode 100644
index 0000000..733d2e4
--- /dev/null
+++ b/arch/mips/au1000/pb1500/init.c
@@ -0,0 +1,69 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ * PB1500 board setup
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ * ppopov@mvista.com or source@mvista.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/bootmem.h>
+#include <asm/addrspace.h>
+#include <asm/bootinfo.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+
+int prom_argc;
+char **prom_argv, **prom_envp;
+extern void __init prom_init_cmdline(void);
+extern char *prom_getenv(char *envname);
+
+const char *get_system_type(void)
+{
+ return "Alchemy Pb1500";
+}
+
+void __init prom_init(void)
+{
+ unsigned char *memsize_str;
+ unsigned long memsize;
+
+ prom_argc = (int) fw_arg0;
+ prom_argv = (char **) fw_arg1;
+ prom_envp = (char **) fw_arg2;
+
+ mips_machgroup = MACH_GROUP_ALCHEMY;
+ mips_machtype = MACH_PB1500;
+
+ prom_init_cmdline();
+ memsize_str = prom_getenv("memsize");
+ if (!memsize_str) {
+ memsize = 0x04000000;
+ } else {
+ memsize = simple_strtol(memsize_str, NULL, 0);
+ }
+ add_memory_region(0, memsize, BOOT_MEM_RAM);
+}
diff --git a/arch/mips/au1000/pb1500/irqmap.c b/arch/mips/au1000/pb1500/irqmap.c
new file mode 100644
index 0000000..476e250
--- /dev/null
+++ b/arch/mips/au1000/pb1500/irqmap.c
@@ -0,0 +1,58 @@
+/*
+ * BRIEF MODULE DESCRIPTION
+ * Au1xxx irq map table
+ *
+ * Copyright 2003 Embedded Edge, LLC
+ * dan@embeddededge.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/kernel_stat.h>
+#include <linux/module.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/timex.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+#include <linux/delay.h>
+#include <linux/bitops.h>
+
+#include <asm/bootinfo.h>
+#include <asm/io.h>
+#include <asm/mipsregs.h>
+#include <asm/system.h>
+#include <asm/mach-au1x00/au1000.h>
+
+au1xxx_irq_map_t au1xxx_irq_map[] = {
+ { AU1500_GPIO_204, INTC_INT_HIGH_LEVEL, 0},
+ { AU1500_GPIO_201, INTC_INT_LOW_LEVEL, 0 },
+ { AU1500_GPIO_202, INTC_INT_LOW_LEVEL, 0 },
+ { AU1500_GPIO_203, INTC_INT_LOW_LEVEL, 0 },
+ { AU1500_GPIO_205, INTC_INT_LOW_LEVEL, 0 },
+};
+
+int au1xxx_nr_irqs = sizeof(au1xxx_irq_map)/sizeof(au1xxx_irq_map_t);
diff --git a/arch/mips/au1000/pb1550/Makefile b/arch/mips/au1000/pb1550/Makefile
new file mode 100644
index 0000000..aa35bc6
--- /dev/null
+++ b/arch/mips/au1000/pb1550/Makefile
@@ -0,0 +1,9 @@
+#
+# Copyright 2000 MontaVista Software Inc.
+# Author: MontaVista Software, Inc.
+# ppopov@mvista.com or source@mvista.com
+#
+# Makefile for the Alchemy Semiconductor PB1000 board.
+#
+
+lib-y := init.o board_setup.o irqmap.o
diff --git a/arch/mips/au1000/pb1550/board_setup.c b/arch/mips/au1000/pb1550/board_setup.c
new file mode 100644
index 0000000..05fd27d
--- /dev/null
+++ b/arch/mips/au1000/pb1550/board_setup.c
@@ -0,0 +1,69 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ * Alchemy Pb1550 board setup.
+ *
+ * Copyright 2000 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ * ppopov@mvista.com or source@mvista.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/mm.h>
+#include <linux/console.h>
+#include <linux/mc146818rtc.h>
+#include <linux/delay.h>
+
+#include <asm/cpu.h>
+#include <asm/bootinfo.h>
+#include <asm/irq.h>
+#include <asm/mipsregs.h>
+#include <asm/reboot.h>
+#include <asm/pgtable.h>
+#include <asm/mach-au1x00/au1000.h>
+#include <asm/mach-pb1x00/pb1550.h>
+
+void board_reset (void)
+{
+ /* Hit BCSR.SYSTEM_CONTROL[SW_RST] */
+ au_writew(au_readw(0xAF00001C) & ~(1<<15), 0xAF00001C);
+}
+
+void __init board_setup(void)
+{
+ u32 pin_func;
+
+ /* Enable PSC1 SYNC for AC97. Normaly done in audio driver,
+ * but it is board specific code, so put it here.
+ */
+ pin_func = au_readl(SYS_PINFUNC);
+ au_sync();
+ pin_func |= SYS_PF_MUST_BE_SET | SYS_PF_PSC1_S1;
+ au_writel(pin_func, SYS_PINFUNC);
+
+ au_writel(0, (u32)bcsr|0x10); /* turn off pcmcia power */
+ au_sync();
+
+ printk("AMD Alchemy Pb1550 Board\n");
+}
diff --git a/arch/mips/au1000/pb1550/init.c b/arch/mips/au1000/pb1550/init.c
new file mode 100644
index 0000000..41daa33
--- /dev/null
+++ b/arch/mips/au1000/pb1550/init.c
@@ -0,0 +1,69 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ * PB1550 board setup
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ * ppopov@mvista.com or source@mvista.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/bootmem.h>
+#include <asm/addrspace.h>
+#include <asm/bootinfo.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+
+int prom_argc;
+char **prom_argv, **prom_envp;
+extern void __init prom_init_cmdline(void);
+extern char *prom_getenv(char *envname);
+
+const char *get_system_type(void)
+{
+ return "Alchemy Pb1550";
+}
+
+void __init prom_init(void)
+{
+ unsigned char *memsize_str;
+ unsigned long memsize;
+
+ prom_argc = (int) fw_arg0;
+ prom_argv = (char **) fw_arg1;
+ prom_envp = (char **) fw_arg2;
+
+ mips_machgroup = MACH_GROUP_ALCHEMY;
+ mips_machtype = MACH_PB1550;
+
+ prom_init_cmdline();
+ memsize_str = prom_getenv("memsize");
+ if (!memsize_str) {
+ memsize = 0x08000000;
+ } else {
+ memsize = simple_strtol(memsize_str, NULL, 0);
+ }
+ add_memory_region(0, memsize, BOOT_MEM_RAM);
+}
diff --git a/arch/mips/au1000/pb1550/irqmap.c b/arch/mips/au1000/pb1550/irqmap.c
new file mode 100644
index 0000000..889d494
--- /dev/null
+++ b/arch/mips/au1000/pb1550/irqmap.c
@@ -0,0 +1,55 @@
+/*
+ * BRIEF MODULE DESCRIPTION
+ * Au1xxx irq map table
+ *
+ * Copyright 2003 Embedded Edge, LLC
+ * dan@embeddededge.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/kernel_stat.h>
+#include <linux/module.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/timex.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+#include <linux/delay.h>
+#include <linux/bitops.h>
+
+#include <asm/bootinfo.h>
+#include <asm/io.h>
+#include <asm/mipsregs.h>
+#include <asm/system.h>
+#include <asm/mach-au1x00/au1000.h>
+
+au1xxx_irq_map_t au1xxx_irq_map[] = {
+ { AU1000_GPIO_0, INTC_INT_LOW_LEVEL, 0 },
+ { AU1000_GPIO_1, INTC_INT_LOW_LEVEL, 0 },
+};
+
+int au1xxx_nr_irqs = sizeof(au1xxx_irq_map)/sizeof(au1xxx_irq_map_t);
diff --git a/arch/mips/au1000/xxs1500/Makefile b/arch/mips/au1000/xxs1500/Makefile
new file mode 100644
index 0000000..44d7f70
--- /dev/null
+++ b/arch/mips/au1000/xxs1500/Makefile
@@ -0,0 +1,9 @@
+#
+# Copyright 2003 MontaVista Software Inc.
+# Author: MontaVista Software, Inc.
+# ppopov@mvista.com or source@mvista.com
+#
+# Makefile for MyCable XXS1500 board.
+#
+
+lib-y := init.o board_setup.o irqmap.o
diff --git a/arch/mips/au1000/xxs1500/board_setup.c b/arch/mips/au1000/xxs1500/board_setup.c
new file mode 100644
index 0000000..9dadc82
--- /dev/null
+++ b/arch/mips/au1000/xxs1500/board_setup.c
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2000-2003 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ * ppopov@mvista.com or source@mvista.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/mm.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+
+#include <asm/cpu.h>
+#include <asm/bootinfo.h>
+#include <asm/irq.h>
+#include <asm/keyboard.h>
+#include <asm/mipsregs.h>
+#include <asm/reboot.h>
+#include <asm/pgtable.h>
+#include <asm/au1000.h>
+
+void board_reset (void)
+{
+ /* Hit BCSR.SYSTEM_CONTROL[SW_RST] */
+ au_writel(0x00000000, 0xAE00001C);
+}
+
+void __init board_setup(void)
+{
+ u32 pin_func;
+
+ // set multiple use pins (UART3/GPIO) to UART (it's used as UART too)
+ pin_func = au_readl(SYS_PINFUNC) & (u32)(~SYS_PF_UR3);
+ pin_func |= SYS_PF_UR3;
+ au_writel(pin_func, SYS_PINFUNC);
+
+ // enable UART
+ au_writel(0x01, UART3_ADDR+UART_MOD_CNTRL); // clock enable (CE)
+ mdelay(10);
+ au_writel(0x03, UART3_ADDR+UART_MOD_CNTRL); // CE and "enable"
+ mdelay(10);
+
+ // enable DTR = USB power up
+ au_writel(0x01, UART3_ADDR+UART_MCR); //? UART_MCR_DTR is 0x01???
+
+#ifdef CONFIG_PCMCIA_XXS1500
+ /* setup pcmcia signals */
+ au_writel(0, SYS_PININPUTEN);
+
+ /* gpio 0, 1, and 4 are inputs */
+ au_writel(1 | (1<<1) | (1<<4), SYS_TRIOUTCLR);
+
+ /* enable GPIO2 if not already enabled */
+ au_writel(1, GPIO2_ENABLE);
+ /* gpio2 208/9/10/11 are inputs */
+ au_writel((1<<8) | (1<<9) | (1<<10) | (1<<11), GPIO2_DIR);
+
+ /* turn off power */
+ au_writel((au_readl(GPIO2_PINSTATE) & ~(1<<14))|(1<<30), GPIO2_OUTPUT);
+#endif
+
+
+#ifdef CONFIG_PCI
+#if defined(__MIPSEB__)
+ au_writel(0xf | (2<<6) | (1<<4), Au1500_PCI_CFG);
+#else
+ au_writel(0xf, Au1500_PCI_CFG);
+#endif
+#endif
+}
diff --git a/arch/mips/au1000/xxs1500/init.c b/arch/mips/au1000/xxs1500/init.c
new file mode 100644
index 0000000..03f7552
--- /dev/null
+++ b/arch/mips/au1000/xxs1500/init.c
@@ -0,0 +1,68 @@
+/*
+ * BRIEF MODULE DESCRIPTION
+ * XXS1500 board setup
+ *
+ * Copyright 2003 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ * ppopov@mvista.com or source@mvista.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/bootmem.h>
+#include <asm/addrspace.h>
+#include <asm/bootinfo.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+
+int prom_argc;
+char **prom_argv, **prom_envp;
+extern void __init prom_init_cmdline(void);
+extern char *prom_getenv(char *envname);
+
+const char *get_system_type(void)
+{
+ return "XXS1500";
+}
+
+void __init prom_init(void)
+{
+ unsigned char *memsize_str;
+ unsigned long memsize;
+
+ prom_argc = fw_arg0;
+ prom_argv = (char **) fw_arg1;
+ prom_envp = (char **) fw_arg2;
+
+ mips_machgroup = MACH_GROUP_ALCHEMY;
+ mips_machtype = MACH_XXS1500; /* set the platform # */
+
+ prom_init_cmdline();
+
+ memsize_str = prom_getenv("memsize");
+ if (!memsize_str)
+ memsize = 0x04000000;
+ else
+ memsize = simple_strtol(memsize_str, NULL, 0);
+ add_memory_region(0, memsize, BOOT_MEM_RAM);
+}
diff --git a/arch/mips/au1000/xxs1500/irqmap.c b/arch/mips/au1000/xxs1500/irqmap.c
new file mode 100644
index 0000000..954800a
--- /dev/null
+++ b/arch/mips/au1000/xxs1500/irqmap.c
@@ -0,0 +1,66 @@
+/*
+ * BRIEF MODULE DESCRIPTION
+ * Au1xxx irq map table
+ *
+ * Copyright 2003 Embedded Edge, LLC
+ * dan@embeddededge.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/kernel_stat.h>
+#include <linux/module.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/timex.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+#include <linux/delay.h>
+#include <linux/bitops.h>
+
+#include <asm/bootinfo.h>
+#include <asm/io.h>
+#include <asm/mipsregs.h>
+#include <asm/system.h>
+#include <asm/au1000.h>
+
+au1xxx_irq_map_t au1xxx_irq_map[] = {
+ { AU1500_GPIO_204, INTC_INT_HIGH_LEVEL, 0},
+ { AU1500_GPIO_201, INTC_INT_LOW_LEVEL, 0 },
+ { AU1500_GPIO_202, INTC_INT_LOW_LEVEL, 0 },
+ { AU1500_GPIO_203, INTC_INT_LOW_LEVEL, 0 },
+ { AU1500_GPIO_205, INTC_INT_LOW_LEVEL, 0 },
+ { AU1500_GPIO_207, INTC_INT_LOW_LEVEL, 0 },
+
+ { AU1000_GPIO_0, INTC_INT_LOW_LEVEL, 0 },
+ { AU1000_GPIO_1, INTC_INT_LOW_LEVEL, 0 },
+ { AU1000_GPIO_2, INTC_INT_LOW_LEVEL, 0 },
+ { AU1000_GPIO_3, INTC_INT_LOW_LEVEL, 0 },
+ { AU1000_GPIO_4, INTC_INT_LOW_LEVEL, 0 }, /* CF interrupt */
+ { AU1000_GPIO_5, INTC_INT_LOW_LEVEL, 0 },
+};
+
+int au1xxx_nr_irqs = sizeof(au1xxx_irq_map)/sizeof(au1xxx_irq_map_t);
diff --git a/arch/mips/boot/Makefile b/arch/mips/boot/Makefile
new file mode 100644
index 0000000..efbeac3
--- /dev/null
+++ b/arch/mips/boot/Makefile
@@ -0,0 +1,49 @@
+#
+# 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, 1998, 2001, 2002 by Ralf Baechle
+# Copyright (C) 2004 Maciej W. Rozycki
+#
+
+#
+# Some DECstations need all possible sections of an ECOFF executable
+#
+ifdef CONFIG_MACH_DECSTATION
+ E2EFLAGS = -a
+else
+ E2EFLAGS =
+endif
+
+#
+# Drop some uninteresting sections in the kernel.
+# This is only relevant for ELF kernels but doesn't hurt a.out
+#
+drop-sections = .reginfo .mdebug .comment .note .pdr .options .MIPS.options
+strip-flags = $(addprefix --remove-section=,$(drop-sections))
+
+VMLINUX = vmlinux
+
+all: vmlinux.ecoff vmlinux.srec addinitrd
+
+vmlinux.ecoff: $(obj)/elf2ecoff $(VMLINUX)
+ $(obj)/elf2ecoff $(VMLINUX) vmlinux.ecoff $(E2EFLAGS)
+
+$(obj)/elf2ecoff: $(obj)/elf2ecoff.c
+ $(HOSTCC) -o $@ $^
+
+vmlinux.srec: $(VMLINUX)
+ $(OBJCOPY) -S -O srec $(strip-flags) $(VMLINUX) $(obj)/vmlinux.srec
+
+$(obj)/addinitrd: $(obj)/addinitrd.c
+ $(HOSTCC) -o $@ $^
+
+archhelp:
+ @echo '* vmlinux.ecoff - ECOFF boot image'
+ @echo '* vmlinux.srec - SREC boot image'
+
+clean-files += addinitrd \
+ elf2ecoff \
+ vmlinux.ecoff \
+ vmlinux.srec
diff --git a/arch/mips/boot/addinitrd.c b/arch/mips/boot/addinitrd.c
new file mode 100644
index 0000000..8b30333
--- /dev/null
+++ b/arch/mips/boot/addinitrd.c
@@ -0,0 +1,131 @@
+/*
+ * addinitrd - program to add a initrd image to an ecoff kernel
+ *
+ * (C) 1999 Thomas Bogendoerfer
+ * minor modifications, cleanup: Guido Guenther <agx@sigxcpu.org>
+ * further cleanup: Maciej W. Rozycki
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <netinet/in.h>
+
+#include "ecoff.h"
+
+#define MIPS_PAGE_SIZE 4096
+#define MIPS_PAGE_MASK (MIPS_PAGE_SIZE-1)
+
+#define swab16(x) \
+ ((unsigned short)( \
+ (((unsigned short)(x) & (unsigned short)0x00ffU) << 8) | \
+ (((unsigned short)(x) & (unsigned short)0xff00U) >> 8) ))
+
+#define swab32(x) \
+ ((unsigned int)( \
+ (((unsigned int)(x) & (unsigned int)0x000000ffUL) << 24) | \
+ (((unsigned int)(x) & (unsigned int)0x0000ff00UL) << 8) | \
+ (((unsigned int)(x) & (unsigned int)0x00ff0000UL) >> 8) | \
+ (((unsigned int)(x) & (unsigned int)0xff000000UL) >> 24) ))
+
+#define SWAB(a) (swab ? swab32(a) : (a))
+
+void die (char *s)
+{
+ perror (s);
+ exit (1);
+}
+
+int main (int argc, char *argv[])
+{
+ int fd_vmlinux,fd_initrd,fd_outfile;
+ FILHDR efile;
+ AOUTHDR eaout;
+ SCNHDR esecs[3];
+ struct stat st;
+ char buf[1024];
+ unsigned long loadaddr;
+ unsigned long initrd_header[2];
+ int i,cnt;
+ int swab = 0;
+
+ if (argc != 4) {
+ printf ("Usage: %s <vmlinux> <initrd> <outfile>\n",argv[0]);
+ exit (1);
+ }
+
+ if ((fd_vmlinux = open (argv[1],O_RDONLY)) < 0)
+ die ("open vmlinux");
+ if (read (fd_vmlinux, &efile, sizeof efile) != sizeof efile)
+ die ("read file header");
+ if (read (fd_vmlinux, &eaout, sizeof eaout) != sizeof eaout)
+ die ("read aout header");
+ if (read (fd_vmlinux, esecs, sizeof esecs) != sizeof esecs)
+ die ("read section headers");
+ /*
+ * check whether the file is good for us
+ */
+ /* TBD */
+
+ /*
+ * check, if we have to swab words
+ */
+ if (ntohs(0xaa55) == 0xaa55) {
+ if (efile.f_magic == swab16(MIPSELMAGIC))
+ swab = 1;
+ } else {
+ if (efile.f_magic == swab16(MIPSEBMAGIC))
+ swab = 1;
+ }
+
+ /* make sure we have an empty data segment for the initrd */
+ if (eaout.dsize || esecs[1].s_size) {
+ fprintf (stderr, "Data segment not empty. Giving up!\n");
+ exit (1);
+ }
+ if ((fd_initrd = open (argv[2], O_RDONLY)) < 0)
+ die ("open initrd");
+ if (fstat (fd_initrd, &st) < 0)
+ die ("fstat initrd");
+ loadaddr = ((SWAB(esecs[2].s_vaddr) + SWAB(esecs[2].s_size)
+ + MIPS_PAGE_SIZE-1) & ~MIPS_PAGE_MASK) - 8;
+ if (loadaddr < (SWAB(esecs[2].s_vaddr) + SWAB(esecs[2].s_size)))
+ loadaddr += MIPS_PAGE_SIZE;
+ initrd_header[0] = SWAB(0x494E5244);
+ initrd_header[1] = SWAB(st.st_size);
+ eaout.dsize = esecs[1].s_size = initrd_header[1] = SWAB(st.st_size+8);
+ eaout.data_start = esecs[1].s_vaddr = esecs[1].s_paddr = SWAB(loadaddr);
+
+ if ((fd_outfile = open (argv[3], O_RDWR|O_CREAT|O_TRUNC,0666)) < 0)
+ die ("open outfile");
+ if (write (fd_outfile, &efile, sizeof efile) != sizeof efile)
+ die ("write file header");
+ if (write (fd_outfile, &eaout, sizeof eaout) != sizeof eaout)
+ die ("write aout header");
+ if (write (fd_outfile, esecs, sizeof esecs) != sizeof esecs)
+ die ("write section headers");
+ /* skip padding */
+ if(lseek(fd_vmlinux, SWAB(esecs[0].s_scnptr), SEEK_SET) == (off_t)-1)
+ die ("lseek vmlinux");
+ if(lseek(fd_outfile, SWAB(esecs[0].s_scnptr), SEEK_SET) == (off_t)-1)
+ die ("lseek outfile");
+ /* copy text segment */
+ cnt = SWAB(eaout.tsize);
+ while (cnt) {
+ if ((i = read (fd_vmlinux, buf, sizeof buf)) <= 0)
+ die ("read vmlinux");
+ if (write (fd_outfile, buf, i) != i)
+ die ("write vmlinux");
+ cnt -= i;
+ }
+ if (write (fd_outfile, initrd_header, sizeof initrd_header) != sizeof initrd_header)
+ die ("write initrd header");
+ while ((i = read (fd_initrd, buf, sizeof buf)) > 0)
+ if (write (fd_outfile, buf, i) != i)
+ die ("write initrd");
+ close (fd_vmlinux);
+ close (fd_initrd);
+ return 0;
+}
diff --git a/arch/mips/boot/ecoff.h b/arch/mips/boot/ecoff.h
new file mode 100644
index 0000000..8c3eed2
--- /dev/null
+++ b/arch/mips/boot/ecoff.h
@@ -0,0 +1,62 @@
+/*
+ * Some ECOFF definitions.
+ */
+typedef struct filehdr {
+ unsigned short f_magic; /* magic number */
+ unsigned short f_nscns; /* number of sections */
+ long f_timdat; /* time & date stamp */
+ long f_symptr; /* file pointer to symbolic header */
+ long f_nsyms; /* sizeof(symbolic hdr) */
+ unsigned short f_opthdr; /* sizeof(optional hdr) */
+ unsigned short f_flags; /* flags */
+} FILHDR;
+#define FILHSZ sizeof(FILHDR)
+
+#define OMAGIC 0407
+#define MIPSEBMAGIC 0x160
+#define MIPSELMAGIC 0x162
+
+typedef struct scnhdr {
+ char s_name[8]; /* section name */
+ long s_paddr; /* physical address, aliased s_nlib */
+ long s_vaddr; /* virtual address */
+ long s_size; /* section size */
+ long s_scnptr; /* file ptr to raw data for section */
+ long s_relptr; /* file ptr to relocation */
+ long s_lnnoptr; /* file ptr to gp histogram */
+ unsigned short s_nreloc; /* number of relocation entries */
+ unsigned short s_nlnno; /* number of gp histogram entries */
+ long s_flags; /* flags */
+} SCNHDR;
+#define SCNHSZ sizeof(SCNHDR)
+#define SCNROUND ((long)16)
+
+typedef struct aouthdr {
+ short magic; /* see above */
+ short vstamp; /* version stamp */
+ long tsize; /* text size in bytes, padded to DW bdry*/
+ long dsize; /* initialized data " " */
+ long bsize; /* uninitialized data " " */
+ long entry; /* entry pt. */
+ long text_start; /* base of text used for this file */
+ long data_start; /* base of data used for this file */
+ long bss_start; /* base of bss used for this file */
+ long gprmask; /* general purpose register mask */
+ long cprmask[4]; /* co-processor register masks */
+ long gp_value; /* the gp value used for this object */
+} AOUTHDR;
+#define AOUTHSZ sizeof(AOUTHDR)
+
+#define OMAGIC 0407
+#define NMAGIC 0410
+#define ZMAGIC 0413
+#define SMAGIC 0411
+#define LIBMAGIC 0443
+
+#define N_TXTOFF(f, a) \
+ ((a).magic == ZMAGIC || (a).magic == LIBMAGIC ? 0 : \
+ ((a).vstamp < 23 ? \
+ ((FILHSZ + AOUTHSZ + (f).f_nscns * SCNHSZ + 7) & 0xfffffff8) : \
+ ((FILHSZ + AOUTHSZ + (f).f_nscns * SCNHSZ + SCNROUND-1) & ~(SCNROUND-1)) ) )
+#define N_DATOFF(f, a) \
+ N_TXTOFF(f, a) + (a).tsize;
diff --git a/arch/mips/boot/elf2ecoff.c b/arch/mips/boot/elf2ecoff.c
new file mode 100644
index 0000000..c3543d9
--- /dev/null
+++ b/arch/mips/boot/elf2ecoff.c
@@ -0,0 +1,616 @@
+/*
+ * Copyright (c) 1995
+ * Ted Lemon (hereinafter referred to as the author)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* elf2ecoff.c
+
+ This program converts an elf executable to an ECOFF executable.
+ No symbol table is retained. This is useful primarily in building
+ net-bootable kernels for machines (e.g., DECstation and Alpha) which
+ only support the ECOFF object file format. */
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <elf.h>
+#include <limits.h>
+#include <netinet/in.h>
+#include <stdlib.h>
+
+#include "ecoff.h"
+
+/*
+ * Some extra ELF definitions
+ */
+#define PT_MIPS_REGINFO 0x70000000 /* Register usage information */
+
+/* -------------------------------------------------------------------- */
+
+struct sect {
+ unsigned long vaddr;
+ unsigned long len;
+};
+
+int *symTypeTable;
+int must_convert_endian = 0;
+int format_bigendian = 0;
+
+static void copy(int out, int in, off_t offset, off_t size)
+{
+ char ibuf[4096];
+ int remaining, cur, count;
+
+ /* Go to the start of the ELF symbol table... */
+ if (lseek(in, offset, SEEK_SET) < 0) {
+ perror("copy: lseek");
+ exit(1);
+ }
+
+ remaining = size;
+ while (remaining) {
+ cur = remaining;
+ if (cur > sizeof ibuf)
+ cur = sizeof ibuf;
+ remaining -= cur;
+ if ((count = read(in, ibuf, cur)) != cur) {
+ fprintf(stderr, "copy: read: %s\n",
+ count ? strerror(errno) :
+ "premature end of file");
+ exit(1);
+ }
+ if ((count = write(out, ibuf, cur)) != cur) {
+ perror("copy: write");
+ exit(1);
+ }
+ }
+}
+
+/*
+ * Combine two segments, which must be contiguous. If pad is true, it's
+ * okay for there to be padding between.
+ */
+static void combine(struct sect *base, struct sect *new, int pad)
+{
+ if (!base->len)
+ *base = *new;
+ else if (new->len) {
+ if (base->vaddr + base->len != new->vaddr) {
+ if (pad)
+ base->len = new->vaddr - base->vaddr;
+ else {
+ fprintf(stderr,
+ "Non-contiguous data can't be converted.\n");
+ exit(1);
+ }
+ }
+ base->len += new->len;
+ }
+}
+
+static int phcmp(const void *v1, const void *v2)
+{
+ const Elf32_Phdr *h1 = v1;
+ const Elf32_Phdr *h2 = v2;
+
+ if (h1->p_vaddr > h2->p_vaddr)
+ return 1;
+ else if (h1->p_vaddr < h2->p_vaddr)
+ return -1;
+ else
+ return 0;
+}
+
+static char *saveRead(int file, off_t offset, off_t len, char *name)
+{
+ char *tmp;
+ int count;
+ off_t off;
+ if ((off = lseek(file, offset, SEEK_SET)) < 0) {
+ fprintf(stderr, "%s: fseek: %s\n", name, strerror(errno));
+ exit(1);
+ }
+ if (!(tmp = (char *) malloc(len))) {
+ fprintf(stderr, "%s: Can't allocate %ld bytes.\n", name,
+ len);
+ exit(1);
+ }
+ count = read(file, tmp, len);
+ if (count != len) {
+ fprintf(stderr, "%s: read: %s.\n",
+ name,
+ count ? strerror(errno) : "End of file reached");
+ exit(1);
+ }
+ return tmp;
+}
+
+#define swab16(x) \
+ ((unsigned short)( \
+ (((unsigned short)(x) & (unsigned short)0x00ffU) << 8) | \
+ (((unsigned short)(x) & (unsigned short)0xff00U) >> 8) ))
+
+#define swab32(x) \
+ ((unsigned int)( \
+ (((unsigned int)(x) & (unsigned int)0x000000ffUL) << 24) | \
+ (((unsigned int)(x) & (unsigned int)0x0000ff00UL) << 8) | \
+ (((unsigned int)(x) & (unsigned int)0x00ff0000UL) >> 8) | \
+ (((unsigned int)(x) & (unsigned int)0xff000000UL) >> 24) ))
+
+static void convert_elf_hdr(Elf32_Ehdr * e)
+{
+ e->e_type = swab16(e->e_type);
+ e->e_machine = swab16(e->e_machine);
+ e->e_version = swab32(e->e_version);
+ e->e_entry = swab32(e->e_entry);
+ e->e_phoff = swab32(e->e_phoff);
+ e->e_shoff = swab32(e->e_shoff);
+ e->e_flags = swab32(e->e_flags);
+ e->e_ehsize = swab16(e->e_ehsize);
+ e->e_phentsize = swab16(e->e_phentsize);
+ e->e_phnum = swab16(e->e_phnum);
+ e->e_shentsize = swab16(e->e_shentsize);
+ e->e_shnum = swab16(e->e_shnum);
+ e->e_shstrndx = swab16(e->e_shstrndx);
+}
+
+static void convert_elf_phdrs(Elf32_Phdr * p, int num)
+{
+ int i;
+
+ for (i = 0; i < num; i++, p++) {
+ p->p_type = swab32(p->p_type);
+ p->p_offset = swab32(p->p_offset);
+ p->p_vaddr = swab32(p->p_vaddr);
+ p->p_paddr = swab32(p->p_paddr);
+ p->p_filesz = swab32(p->p_filesz);
+ p->p_memsz = swab32(p->p_memsz);
+ p->p_flags = swab32(p->p_flags);
+ p->p_align = swab32(p->p_align);
+ }
+
+}
+
+static void convert_elf_shdrs(Elf32_Shdr * s, int num)
+{
+ int i;
+
+ for (i = 0; i < num; i++, s++) {
+ s->sh_name = swab32(s->sh_name);
+ s->sh_type = swab32(s->sh_type);
+ s->sh_flags = swab32(s->sh_flags);
+ s->sh_addr = swab32(s->sh_addr);
+ s->sh_offset = swab32(s->sh_offset);
+ s->sh_size = swab32(s->sh_size);
+ s->sh_link = swab32(s->sh_link);
+ s->sh_info = swab32(s->sh_info);
+ s->sh_addralign = swab32(s->sh_addralign);
+ s->sh_entsize = swab32(s->sh_entsize);
+ }
+}
+
+static void convert_ecoff_filehdr(struct filehdr *f)
+{
+ f->f_magic = swab16(f->f_magic);
+ f->f_nscns = swab16(f->f_nscns);
+ f->f_timdat = swab32(f->f_timdat);
+ f->f_symptr = swab32(f->f_symptr);
+ f->f_nsyms = swab32(f->f_nsyms);
+ f->f_opthdr = swab16(f->f_opthdr);
+ f->f_flags = swab16(f->f_flags);
+}
+
+static void convert_ecoff_aouthdr(struct aouthdr *a)
+{
+ a->magic = swab16(a->magic);
+ a->vstamp = swab16(a->vstamp);
+ a->tsize = swab32(a->tsize);
+ a->dsize = swab32(a->dsize);
+ a->bsize = swab32(a->bsize);
+ a->entry = swab32(a->entry);
+ a->text_start = swab32(a->text_start);
+ a->data_start = swab32(a->data_start);
+ a->bss_start = swab32(a->bss_start);
+ a->gprmask = swab32(a->gprmask);
+ a->cprmask[0] = swab32(a->cprmask[0]);
+ a->cprmask[1] = swab32(a->cprmask[1]);
+ a->cprmask[2] = swab32(a->cprmask[2]);
+ a->cprmask[3] = swab32(a->cprmask[3]);
+ a->gp_value = swab32(a->gp_value);
+}
+
+static void convert_ecoff_esecs(struct scnhdr *s, int num)
+{
+ int i;
+
+ for (i = 0; i < num; i++, s++) {
+ s->s_paddr = swab32(s->s_paddr);
+ s->s_vaddr = swab32(s->s_vaddr);
+ s->s_size = swab32(s->s_size);
+ s->s_scnptr = swab32(s->s_scnptr);
+ s->s_relptr = swab32(s->s_relptr);
+ s->s_lnnoptr = swab32(s->s_lnnoptr);
+ s->s_nreloc = swab16(s->s_nreloc);
+ s->s_nlnno = swab16(s->s_nlnno);
+ s->s_flags = swab32(s->s_flags);
+ }
+}
+
+int main(int argc, char *argv[])
+{
+ Elf32_Ehdr ex;
+ Elf32_Phdr *ph;
+ Elf32_Shdr *sh;
+ char *shstrtab;
+ int i, pad;
+ struct sect text, data, bss;
+ struct filehdr efh;
+ struct aouthdr eah;
+ struct scnhdr esecs[6];
+ int infile, outfile;
+ unsigned long cur_vma = ULONG_MAX;
+ int addflag = 0;
+ int nosecs;
+
+ text.len = data.len = bss.len = 0;
+ text.vaddr = data.vaddr = bss.vaddr = 0;
+
+ /* Check args... */
+ if (argc < 3 || argc > 4) {
+ usage:
+ fprintf(stderr,
+ "usage: elf2ecoff <elf executable> <ecoff executable> [-a]\n");
+ exit(1);
+ }
+ if (argc == 4) {
+ if (strcmp(argv[3], "-a"))
+ goto usage;
+ addflag = 1;
+ }
+
+ /* Try the input file... */
+ if ((infile = open(argv[1], O_RDONLY)) < 0) {
+ fprintf(stderr, "Can't open %s for read: %s\n",
+ argv[1], strerror(errno));
+ exit(1);
+ }
+
+ /* Read the header, which is at the beginning of the file... */
+ i = read(infile, &ex, sizeof ex);
+ if (i != sizeof ex) {
+ fprintf(stderr, "ex: %s: %s.\n",
+ argv[1],
+ i ? strerror(errno) : "End of file reached");
+ exit(1);
+ }
+
+ if (ex.e_ident[EI_DATA] == ELFDATA2MSB)
+ format_bigendian = 1;
+
+ if (ntohs(0xaa55) == 0xaa55) {
+ if (!format_bigendian)
+ must_convert_endian = 1;
+ } else {
+ if (format_bigendian)
+ must_convert_endian = 1;
+ }
+ if (must_convert_endian)
+ convert_elf_hdr(&ex);
+
+ /* Read the program headers... */
+ ph = (Elf32_Phdr *) saveRead(infile, ex.e_phoff,
+ ex.e_phnum * sizeof(Elf32_Phdr),
+ "ph");
+ if (must_convert_endian)
+ convert_elf_phdrs(ph, ex.e_phnum);
+ /* Read the section headers... */
+ sh = (Elf32_Shdr *) saveRead(infile, ex.e_shoff,
+ ex.e_shnum * sizeof(Elf32_Shdr),
+ "sh");
+ if (must_convert_endian)
+ convert_elf_shdrs(sh, ex.e_shnum);
+ /* Read in the section string table. */
+ shstrtab = saveRead(infile, sh[ex.e_shstrndx].sh_offset,
+ sh[ex.e_shstrndx].sh_size, "shstrtab");
+
+ /* Figure out if we can cram the program header into an ECOFF
+ header... Basically, we can't handle anything but loadable
+ segments, but we can ignore some kinds of segments. We can't
+ handle holes in the address space. Segments may be out of order,
+ so we sort them first. */
+
+ qsort(ph, ex.e_phnum, sizeof(Elf32_Phdr), phcmp);
+
+ for (i = 0; i < ex.e_phnum; i++) {
+ /* Section types we can ignore... */
+ if (ph[i].p_type == PT_NULL || ph[i].p_type == PT_NOTE ||
+ ph[i].p_type == PT_PHDR
+ || ph[i].p_type == PT_MIPS_REGINFO)
+ continue;
+ /* Section types we can't handle... */
+ else if (ph[i].p_type != PT_LOAD) {
+ fprintf(stderr,
+ "Program header %d type %d can't be converted.\n",
+ ex.e_phnum, ph[i].p_type);
+ exit(1);
+ }
+ /* Writable (data) segment? */
+ if (ph[i].p_flags & PF_W) {
+ struct sect ndata, nbss;
+
+ ndata.vaddr = ph[i].p_vaddr;
+ ndata.len = ph[i].p_filesz;
+ nbss.vaddr = ph[i].p_vaddr + ph[i].p_filesz;
+ nbss.len = ph[i].p_memsz - ph[i].p_filesz;
+
+ combine(&data, &ndata, 0);
+ combine(&bss, &nbss, 1);
+ } else {
+ struct sect ntxt;
+
+ ntxt.vaddr = ph[i].p_vaddr;
+ ntxt.len = ph[i].p_filesz;
+
+ combine(&text, &ntxt, 0);
+ }
+ /* Remember the lowest segment start address. */
+ if (ph[i].p_vaddr < cur_vma)
+ cur_vma = ph[i].p_vaddr;
+ }
+
+ /* Sections must be in order to be converted... */
+ if (text.vaddr > data.vaddr || data.vaddr > bss.vaddr ||
+ text.vaddr + text.len > data.vaddr
+ || data.vaddr + data.len > bss.vaddr) {
+ fprintf(stderr,
+ "Sections ordering prevents a.out conversion.\n");
+ exit(1);
+ }
+
+ /* If there's a data section but no text section, then the loader
+ combined everything into one section. That needs to be the
+ text section, so just make the data section zero length following
+ text. */
+ if (data.len && !text.len) {
+ text = data;
+ data.vaddr = text.vaddr + text.len;
+ data.len = 0;
+ }
+
+ /* If there is a gap between text and data, we'll fill it when we copy
+ the data, so update the length of the text segment as represented in
+ a.out to reflect that, since a.out doesn't allow gaps in the program
+ address space. */
+ if (text.vaddr + text.len < data.vaddr)
+ text.len = data.vaddr - text.vaddr;
+
+ /* We now have enough information to cons up an a.out header... */
+ eah.magic = OMAGIC;
+ eah.vstamp = 200;
+ eah.tsize = text.len;
+ eah.dsize = data.len;
+ eah.bsize = bss.len;
+ eah.entry = ex.e_entry;
+ eah.text_start = text.vaddr;
+ eah.data_start = data.vaddr;
+ eah.bss_start = bss.vaddr;
+ eah.gprmask = 0xf3fffffe;
+ memset(&eah.cprmask, '\0', sizeof eah.cprmask);
+ eah.gp_value = 0; /* unused. */
+
+ if (format_bigendian)
+ efh.f_magic = MIPSEBMAGIC;
+ else
+ efh.f_magic = MIPSELMAGIC;
+ if (addflag)
+ nosecs = 6;
+ else
+ nosecs = 3;
+ efh.f_nscns = nosecs;
+ efh.f_timdat = 0; /* bogus */
+ efh.f_symptr = 0;
+ efh.f_nsyms = 0;
+ efh.f_opthdr = sizeof eah;
+ efh.f_flags = 0x100f; /* Stripped, not sharable. */
+
+ memset(esecs, 0, sizeof esecs);
+ strcpy(esecs[0].s_name, ".text");
+ strcpy(esecs[1].s_name, ".data");
+ strcpy(esecs[2].s_name, ".bss");
+ if (addflag) {
+ strcpy(esecs[3].s_name, ".rdata");
+ strcpy(esecs[4].s_name, ".sdata");
+ strcpy(esecs[5].s_name, ".sbss");
+ }
+ esecs[0].s_paddr = esecs[0].s_vaddr = eah.text_start;
+ esecs[1].s_paddr = esecs[1].s_vaddr = eah.data_start;
+ esecs[2].s_paddr = esecs[2].s_vaddr = eah.bss_start;
+ if (addflag) {
+ esecs[3].s_paddr = esecs[3].s_vaddr = 0;
+ esecs[4].s_paddr = esecs[4].s_vaddr = 0;
+ esecs[5].s_paddr = esecs[5].s_vaddr = 0;
+ }
+ esecs[0].s_size = eah.tsize;
+ esecs[1].s_size = eah.dsize;
+ esecs[2].s_size = eah.bsize;
+ if (addflag) {
+ esecs[3].s_size = 0;
+ esecs[4].s_size = 0;
+ esecs[5].s_size = 0;
+ }
+ esecs[0].s_scnptr = N_TXTOFF(efh, eah);
+ esecs[1].s_scnptr = N_DATOFF(efh, eah);
+#define ECOFF_SEGMENT_ALIGNMENT(a) 0x10
+#define ECOFF_ROUND(s,a) (((s)+(a)-1)&~((a)-1))
+ esecs[2].s_scnptr = esecs[1].s_scnptr +
+ ECOFF_ROUND(esecs[1].s_size, ECOFF_SEGMENT_ALIGNMENT(&eah));
+ if (addflag) {
+ esecs[3].s_scnptr = 0;
+ esecs[4].s_scnptr = 0;
+ esecs[5].s_scnptr = 0;
+ }
+ esecs[0].s_relptr = esecs[1].s_relptr = esecs[2].s_relptr = 0;
+ esecs[0].s_lnnoptr = esecs[1].s_lnnoptr = esecs[2].s_lnnoptr = 0;
+ esecs[0].s_nreloc = esecs[1].s_nreloc = esecs[2].s_nreloc = 0;
+ esecs[0].s_nlnno = esecs[1].s_nlnno = esecs[2].s_nlnno = 0;
+ if (addflag) {
+ esecs[3].s_relptr = esecs[4].s_relptr
+ = esecs[5].s_relptr = 0;
+ esecs[3].s_lnnoptr = esecs[4].s_lnnoptr
+ = esecs[5].s_lnnoptr = 0;
+ esecs[3].s_nreloc = esecs[4].s_nreloc = esecs[5].s_nreloc =
+ 0;
+ esecs[3].s_nlnno = esecs[4].s_nlnno = esecs[5].s_nlnno = 0;
+ }
+ esecs[0].s_flags = 0x20;
+ esecs[1].s_flags = 0x40;
+ esecs[2].s_flags = 0x82;
+ if (addflag) {
+ esecs[3].s_flags = 0x100;
+ esecs[4].s_flags = 0x200;
+ esecs[5].s_flags = 0x400;
+ }
+
+ /* Make the output file... */
+ if ((outfile = open(argv[2], O_WRONLY | O_CREAT, 0777)) < 0) {
+ fprintf(stderr, "Unable to create %s: %s\n", argv[2],
+ strerror(errno));
+ exit(1);
+ }
+
+ if (must_convert_endian)
+ convert_ecoff_filehdr(&efh);
+ /* Write the headers... */
+ i = write(outfile, &efh, sizeof efh);
+ if (i != sizeof efh) {
+ perror("efh: write");
+ exit(1);
+
+ for (i = 0; i < nosecs; i++) {
+ printf
+ ("Section %d: %s phys %lx size %lx file offset %lx\n",
+ i, esecs[i].s_name, esecs[i].s_paddr,
+ esecs[i].s_size, esecs[i].s_scnptr);
+ }
+ }
+ fprintf(stderr, "wrote %d byte file header.\n", i);
+
+ if (must_convert_endian)
+ convert_ecoff_aouthdr(&eah);
+ i = write(outfile, &eah, sizeof eah);
+ if (i != sizeof eah) {
+ perror("eah: write");
+ exit(1);
+ }
+ fprintf(stderr, "wrote %d byte a.out header.\n", i);
+
+ if (must_convert_endian)
+ convert_ecoff_esecs(&esecs[0], nosecs);
+ i = write(outfile, &esecs, nosecs * sizeof(struct scnhdr));
+ if (i != nosecs * sizeof(struct scnhdr)) {
+ perror("esecs: write");
+ exit(1);
+ }
+ fprintf(stderr, "wrote %d bytes of section headers.\n", i);
+
+ pad = (sizeof(efh) + sizeof(eah) + nosecs * sizeof(struct scnhdr)) & 15;
+ if (pad) {
+ pad = 16 - pad;
+ i = write(outfile, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0", pad);
+ if (i < 0) {
+ perror("ipad: write");
+ exit(1);
+ }
+ fprintf(stderr, "wrote %d byte pad.\n", i);
+ }
+
+ /*
+ * Copy the loadable sections. Zero-fill any gaps less than 64k;
+ * complain about any zero-filling, and die if we're asked to zero-fill
+ * more than 64k.
+ */
+ for (i = 0; i < ex.e_phnum; i++) {
+ /* Unprocessable sections were handled above, so just verify that
+ the section can be loaded before copying. */
+ if (ph[i].p_type == PT_LOAD && ph[i].p_filesz) {
+ if (cur_vma != ph[i].p_vaddr) {
+ unsigned long gap =
+ ph[i].p_vaddr - cur_vma;
+ char obuf[1024];
+ if (gap > 65536) {
+ fprintf(stderr,
+ "Intersegment gap (%ld bytes) too large.\n",
+ gap);
+ exit(1);
+ }
+ fprintf(stderr,
+ "Warning: %ld byte intersegment gap.\n",
+ gap);
+ memset(obuf, 0, sizeof obuf);
+ while (gap) {
+ int count =
+ write(outfile, obuf,
+ (gap >
+ sizeof obuf ? sizeof
+ obuf : gap));
+ if (count < 0) {
+ fprintf(stderr,
+ "Error writing gap: %s\n",
+ strerror(errno));
+ exit(1);
+ }
+ gap -= count;
+ }
+ }
+ fprintf(stderr, "writing %d bytes...\n",
+ ph[i].p_filesz);
+ copy(outfile, infile, ph[i].p_offset,
+ ph[i].p_filesz);
+ cur_vma = ph[i].p_vaddr + ph[i].p_filesz;
+ }
+ }
+
+ /*
+ * Write a page of padding for boot PROMS that read entire pages.
+ * Without this, they may attempt to read past the end of the
+ * data section, incur an error, and refuse to boot.
+ */
+ {
+ char obuf[4096];
+ memset(obuf, 0, sizeof obuf);
+ if (write(outfile, obuf, sizeof(obuf)) != sizeof(obuf)) {
+ fprintf(stderr, "Error writing PROM padding: %s\n",
+ strerror(errno));
+ exit(1);
+ }
+ }
+
+ /* Looks like we won... */
+ exit(0);
+}
diff --git a/arch/mips/cobalt/Makefile b/arch/mips/cobalt/Makefile
new file mode 100644
index 0000000..a5e6554
--- /dev/null
+++ b/arch/mips/cobalt/Makefile
@@ -0,0 +1,7 @@
+#
+# Makefile for the Cobalt micro systems family specific parts of the kernel
+#
+
+obj-y := irq.o int-handler.o reset.o setup.o promcon.o
+
+EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/cobalt/int-handler.S b/arch/mips/cobalt/int-handler.S
new file mode 100644
index 0000000..1a21dec
--- /dev/null
+++ b/arch/mips/cobalt/int-handler.S
@@ -0,0 +1,25 @@
+/*
+ * 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, 1996, 1997, 2003 by Ralf Baechle
+ * Copyright (C) 2001, 2002, 2003 by Liam Davies (ldavies@agile.tv)
+ */
+#include <asm/asm.h>
+#include <asm/mipsregs.h>
+#include <asm/cobalt/cobalt.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+
+ .text
+ .align 5
+ NESTED(cobalt_handle_int, PT_SIZE, sp)
+ SAVE_ALL
+ CLI
+
+ la ra, ret_from_irq
+ move a1, sp
+ j cobalt_irq
+
+ END(cobalt_handle_int)
diff --git a/arch/mips/cobalt/irq.c b/arch/mips/cobalt/irq.c
new file mode 100644
index 0000000..6d2a815
--- /dev/null
+++ b/arch/mips/cobalt/irq.c
@@ -0,0 +1,102 @@
+/*
+ * IRQ vector handles
+ *
+ * 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, 1996, 1997, 2003 by Ralf Baechle
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+
+#include <asm/i8259.h>
+#include <asm/irq_cpu.h>
+#include <asm/gt64120.h>
+#include <asm/ptrace.h>
+
+#include <asm/cobalt/cobalt.h>
+
+extern void cobalt_handle_int(void);
+
+/*
+ * We have two types of interrupts that we handle, ones that come in through
+ * the CPU interrupt lines, and ones that come in on the via chip. The CPU
+ * mappings are:
+ *
+ * 16, - Software interrupt 0 (unused) IE_SW0
+ * 17 - Software interrupt 1 (unused) IE_SW0
+ * 18 - Galileo chip (timer) IE_IRQ0
+ * 19 - Tulip 0 + NCR SCSI IE_IRQ1
+ * 20 - Tulip 1 IE_IRQ2
+ * 21 - 16550 UART IE_IRQ3
+ * 22 - VIA southbridge PIC IE_IRQ4
+ * 23 - unused IE_IRQ5
+ *
+ * The VIA chip is a master/slave 8259 setup and has the following interrupts:
+ *
+ * 8 - RTC
+ * 9 - PCI
+ * 14 - IDE0
+ * 15 - IDE1
+ */
+
+asmlinkage void cobalt_irq(struct pt_regs *regs)
+{
+ unsigned int pending = read_c0_status() & read_c0_cause();
+
+ if (pending & CAUSEF_IP2) { /* int 18 */
+ unsigned long irq_src = GALILEO_INL(GT_INTRCAUSE_OFS);
+
+ /* Check for timer irq ... */
+ if (irq_src & GALILEO_T0EXP) {
+ /* Clear the int line */
+ GALILEO_OUTL(0, GT_INTRCAUSE_OFS);
+ do_IRQ(COBALT_TIMER_IRQ, regs);
+ }
+ return;
+ }
+
+ if (pending & CAUSEF_IP6) { /* int 22 */
+ int irq = i8259_irq();
+
+ if (irq >= 0)
+ do_IRQ(irq, regs);
+ return;
+ }
+
+ if (pending & CAUSEF_IP3) { /* int 19 */
+ do_IRQ(COBALT_ETH0_IRQ, regs);
+ return;
+ }
+
+ if (pending & CAUSEF_IP4) { /* int 20 */
+ do_IRQ(COBALT_ETH1_IRQ, regs);
+ return;
+ }
+
+ if (pending & CAUSEF_IP5) { /* int 21 */
+ do_IRQ(COBALT_SERIAL_IRQ, regs);
+ return;
+ }
+
+ if (pending & CAUSEF_IP7) { /* int 23 */
+ do_IRQ(COBALT_QUBE_SLOT_IRQ, regs);
+ return;
+ }
+}
+
+void __init arch_init_irq(void)
+{
+ set_except_vector(0, cobalt_handle_int);
+
+ init_i8259_irqs(); /* 0 ... 15 */
+ mips_cpu_irq_init(16); /* 16 ... 23 */
+
+ /*
+ * Mask all cpu interrupts
+ * (except IE4, we already masked those at VIA level)
+ */
+ change_c0_status(ST0_IM, IE_IRQ4);
+}
diff --git a/arch/mips/cobalt/promcon.c b/arch/mips/cobalt/promcon.c
new file mode 100644
index 0000000..f03df76
--- /dev/null
+++ b/arch/mips/cobalt/promcon.c
@@ -0,0 +1,87 @@
+/*
+ * PROM console for Cobalt Raq2
+ *
+ * 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, 1996, 1997 by Ralf Baechle
+ * Copyright (C) 2001 by Liam Davies (ldavies@agile.tv)
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/console.h>
+#include <linux/kdev_t.h>
+#include <linux/serial_reg.h>
+
+#include <asm/delay.h>
+#include <asm/serial.h>
+#include <asm/io.h>
+
+static unsigned long port = 0xc800000;
+
+static __inline__ void ns16550_cons_put_char(char ch, unsigned long ioaddr)
+{
+ char lsr;
+
+ do {
+ lsr = inb(ioaddr + UART_LSR);
+ } while ((lsr & (UART_LSR_TEMT | UART_LSR_THRE)) != (UART_LSR_TEMT | UART_LSR_THRE));
+ outb(ch, ioaddr + UART_TX);
+}
+
+static __inline__ char ns16550_cons_get_char(unsigned long ioaddr)
+{
+ while ((inb(ioaddr + UART_LSR) & UART_LSR_DR) == 0)
+ udelay(1);
+ return inb(ioaddr + UART_RX);
+}
+
+void ns16550_console_write(struct console *co, const char *s, unsigned count)
+{
+ char lsr, ier;
+ unsigned i;
+
+ ier = inb(port + UART_IER);
+ outb(0x00, port + UART_IER);
+ for (i=0; i < count; i++, s++) {
+
+ if(*s == '\n')
+ ns16550_cons_put_char('\r', port);
+ ns16550_cons_put_char(*s, port);
+ }
+
+ do {
+ lsr = inb(port + UART_LSR);
+ } while ((lsr & (UART_LSR_TEMT | UART_LSR_THRE)) != (UART_LSR_TEMT | UART_LSR_THRE));
+
+ outb(ier, port + UART_IER);
+}
+
+char getDebugChar(void)
+{
+ return ns16550_cons_get_char(port);
+}
+
+void putDebugChar(char kgdb_char)
+{
+ ns16550_cons_put_char(kgdb_char, port);
+}
+
+static struct console ns16550_console = {
+ .name = "prom",
+ .setup = NULL,
+ .write = ns16550_console_write,
+ .flags = CON_PRINTBUFFER,
+ .index = -1,
+};
+
+static int __init ns16550_setup_console(void)
+{
+ register_console(&ns16550_console);
+
+ return 0;
+}
+
+console_initcall(ns16550_setup_console);
diff --git a/arch/mips/cobalt/reset.c b/arch/mips/cobalt/reset.c
new file mode 100644
index 0000000..084c8e5
--- /dev/null
+++ b/arch/mips/cobalt/reset.c
@@ -0,0 +1,68 @@
+/*
+ * Cobalt Reset operations
+ *
+ * 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, 1996, 1997 by Ralf Baechle
+ * Copyright (C) 2001 by Liam Davies (ldavies@agile.tv)
+ */
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <asm/cacheflush.h>
+#include <asm/io.h>
+#include <asm/processor.h>
+#include <asm/reboot.h>
+#include <asm/system.h>
+#include <asm/mipsregs.h>
+
+void cobalt_machine_restart(char *command)
+{
+ *(volatile char *)0xbc000000 = 0x0f;
+
+ /*
+ * Ouch, we're still alive ... This time we take the silver bullet ...
+ * ... and find that we leave the hardware in a state in which the
+ * kernel in the flush locks up somewhen during of after the PCI
+ * detection stuff.
+ */
+ set_c0_status(ST0_BEV | ST0_ERL);
+ change_c0_config(CONF_CM_CMASK, CONF_CM_UNCACHED);
+ flush_cache_all();
+ write_c0_wired(0);
+ __asm__ __volatile__(
+ "jr\t%0"
+ :
+ : "r" (0xbfc00000));
+}
+
+extern int led_state;
+#define kLED 0xBC000000
+#define LEDSet(x) (*(volatile unsigned char *) kLED) = (( unsigned char)x)
+
+void cobalt_machine_halt(void)
+{
+ int mark;
+
+ /* Blink our cute? little LED (number 3)... */
+ while (1) {
+ led_state = led_state | ( 1 << 3 );
+ LEDSet(led_state);
+ mark = jiffies;
+ while (jiffies<(mark+HZ));
+ led_state = led_state & ~( 1 << 3 );
+ LEDSet(led_state);
+ mark = jiffies;
+ while (jiffies<(mark+HZ));
+ }
+}
+
+/*
+ * This triggers the luser mode device driver for the power switch ;-)
+ */
+void cobalt_machine_power_off(void)
+{
+ printk("You can switch the machine off now.\n");
+ cobalt_machine_halt();
+}
diff --git a/arch/mips/cobalt/setup.c b/arch/mips/cobalt/setup.c
new file mode 100644
index 0000000..6b4737e
--- /dev/null
+++ b/arch/mips/cobalt/setup.c
@@ -0,0 +1,150 @@
+/*
+ * Setup pointers to hardware dependent routines.
+ *
+ * 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) 1996, 1997, 2004 by Ralf Baechle (ralf@linux-mips.org)
+ * Copyright (C) 2001, 2002, 2003 by Liam Davies (ldavies@agile.tv)
+ *
+ */
+#include <linux/config.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+
+#include <asm/bootinfo.h>
+#include <asm/time.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/processor.h>
+#include <asm/reboot.h>
+#include <asm/gt64120.h>
+
+#include <asm/cobalt/cobalt.h>
+
+extern void cobalt_machine_restart(char *command);
+extern void cobalt_machine_halt(void);
+extern void cobalt_machine_power_off(void);
+
+int cobalt_board_id;
+
+static char my_cmdline[CL_SIZE] = {
+ "console=ttyS0,115200 "
+#ifdef CONFIG_IP_PNP
+ "ip=on "
+#endif
+#ifdef CONFIG_ROOT_NFS
+ "root=/dev/nfs "
+#else
+ "root=/dev/hda1 "
+#endif
+ };
+
+const char *get_system_type(void)
+{
+ return "MIPS Cobalt";
+}
+
+static void __init cobalt_timer_setup(struct irqaction *irq)
+{
+ /* Load timer value for 150 Hz */
+ GALILEO_OUTL(500000, GT_TC0_OFS);
+
+ /* Register our timer interrupt */
+ setup_irq(COBALT_TIMER_IRQ, irq);
+
+ /* Enable timer ints */
+ GALILEO_OUTL((GALILEO_ENTC0 | GALILEO_SELTC0), GT_TC_CONTROL_OFS);
+ /* Unmask timer int */
+ GALILEO_OUTL(0x100, GT_INTRMASK_OFS);
+}
+
+extern struct pci_ops gt64111_pci_ops;
+
+static struct resource cobalt_mem_resource = {
+ "GT64111 PCI MEM", GT64111_IO_BASE, 0xffffffffUL, IORESOURCE_MEM
+};
+
+static struct resource cobalt_io_resource = {
+ "GT64111 IO MEM", 0x00001000UL, 0x0fffffffUL, IORESOURCE_IO
+};
+
+static struct resource cobalt_io_resources[] = {
+ { "dma1", 0x00, 0x1f, IORESOURCE_BUSY },
+ { "timer", 0x40, 0x5f, IORESOURCE_BUSY },
+ { "keyboard", 0x60, 0x6f, IORESOURCE_BUSY },
+ { "dma page reg", 0x80, 0x8f, IORESOURCE_BUSY },
+ { "dma2", 0xc0, 0xdf, IORESOURCE_BUSY },
+};
+
+#define COBALT_IO_RESOURCES (sizeof(cobalt_io_resources)/sizeof(struct resource))
+
+static struct pci_controller cobalt_pci_controller = {
+ .pci_ops = >64111_pci_ops,
+ .mem_resource = &cobalt_mem_resource,
+ .mem_offset = 0,
+ .io_resource = &cobalt_io_resource,
+ .io_offset = 0x00001000UL - GT64111_IO_BASE
+};
+
+static void __init cobalt_setup(void)
+{
+ unsigned int devfn = PCI_DEVFN(COBALT_PCICONF_VIA, 0);
+ int i;
+
+ _machine_restart = cobalt_machine_restart;
+ _machine_halt = cobalt_machine_halt;
+ _machine_power_off = cobalt_machine_power_off;
+
+ board_timer_setup = cobalt_timer_setup;
+
+ set_io_port_base(KSEG1ADDR(GT64111_IO_BASE));
+
+ /*
+ * This is a prom style console. We just poke at the
+ * UART to make it talk.
+ * Only use this console if you really screw up and can't
+ * get to the stage of setting up a real serial console.
+ */
+ /*ns16550_setup_console();*/
+
+ /* request I/O space for devices used on all i[345]86 PCs */
+ for (i = 0; i < COBALT_IO_RESOURCES; i++)
+ request_resource(&ioport_resource, cobalt_io_resources + i);
+
+ /* Read the cobalt id register out of the PCI config space */
+ PCI_CFG_SET(devfn, (VIA_COBALT_BRD_ID_REG & ~0x3));
+ cobalt_board_id = GALILEO_INL(GT_PCI0_CFGDATA_OFS);
+ cobalt_board_id >>= ((VIA_COBALT_BRD_ID_REG & 3) * 8);
+ cobalt_board_id = VIA_COBALT_BRD_REG_to_ID(cobalt_board_id);
+
+#ifdef CONFIG_PCI
+ register_pci_controller(&cobalt_pci_controller);
+#endif
+}
+
+early_initcall(cobalt_setup);
+
+/*
+ * Prom init. We read our one and only communication with the firmware.
+ * Grab the amount of installed memory
+ */
+
+void __init prom_init(void)
+{
+ int argc = fw_arg0;
+
+ strcpy(arcs_cmdline, my_cmdline);
+
+ mips_machgroup = MACH_GROUP_COBALT;
+
+ add_memory_region(0x0, argc & 0x7fffffff, BOOT_MEM_RAM);
+}
+
+unsigned long __init prom_free_prom_memory(void)
+{
+ /* Nothing to do! */
+ return 0;
+}
diff --git a/arch/mips/configs/atlas_defconfig b/arch/mips/configs/atlas_defconfig
new file mode 100644
index 0000000..caad7ca
--- /dev/null
+++ b/arch/mips/configs/atlas_defconfig
@@ -0,0 +1,1104 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-rc2
+# Wed Jan 26 02:49:00 2005
+#
+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_LOCALVERSION=""
+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=y
+CONFIG_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM 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_MODULE_SRCVERSION_ALL=y
+CONFIG_KMOD=y
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ 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=y
+# 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_OCELOT_3 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 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_GENERIC_CALIBRATE_DELAY=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_MIPS_BONITO64=y
+CONFIG_MIPS_MSC=y
+# CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_MIPS_BOARDS_GEN=y
+CONFIG_MIPS_GT64120=y
+CONFIG_SWAP_IO_SPACE=y
+CONFIG_BOOT_ELF32=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+
+#
+# CPU selection
+#
+CONFIG_CPU_MIPS32=y
+# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_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_CPU_HAS_PREFETCH=y
+# CONFIG_64BIT_PHYS_ADDR is not set
+# CONFIG_CPU_ADVANCED is not set
+CONFIG_CPU_HAS_LLSC=y
+CONFIG_CPU_HAS_SYNC=y
+# CONFIG_PREEMPT is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_HW_HAS_PCI=y
+CONFIG_PCI=y
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+CONFIG_MMU=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=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_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+CONFIG_BLK_DEV_UMEM=m
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=m
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+CONFIG_BLK_DEV_NBD=m
+# CONFIG_BLK_DEV_SX8 is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_INITRD is not set
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_ATA_OVER_ETH=m
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+CONFIG_BLK_DEV_IDECD=y
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_BLK_DEV_IDESCSI is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+# CONFIG_BLK_DEV_IDEPCI is not set
+# CONFIG_IDE_ARM is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD 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=m
+CONFIG_CHR_DEV_OSST=m
+CONFIG_BLK_DEV_SR=m
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=m
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+
+#
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=y
+CONFIG_SCSI_FC_ATTRS=m
+CONFIG_SCSI_ISCSI_ATTRS=m
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_EATA_PIO is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+CONFIG_SCSI_SYM53C8XX_2=y
+CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0
+CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
+CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
+# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_ISP is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+CONFIG_SCSI_QLA2XXX=y
+# CONFIG_SCSI_QLA21XX is not set
+# CONFIG_SCSI_QLA22XX is not set
+# CONFIG_SCSI_QLA2300 is not set
+# CONFIG_SCSI_QLA2322 is not set
+# CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=m
+CONFIG_MD_LINEAR=m
+CONFIG_MD_RAID0=m
+CONFIG_MD_RAID1=m
+CONFIG_MD_RAID10=m
+CONFIG_MD_RAID5=m
+CONFIG_MD_RAID6=m
+CONFIG_MD_MULTIPATH=m
+CONFIG_MD_FAULTY=m
+CONFIG_BLK_DEV_DM=m
+CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# 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=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_FWMARK=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE=m
+CONFIG_NET_IPGRE_BROADCAST=y
+CONFIG_IP_MROUTE=y
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
+CONFIG_INET_IPCOMP=m
+CONFIG_INET_TUNNEL=m
+CONFIG_IP_TCPDIAG=m
+CONFIG_IP_TCPDIAG_IPV6=y
+
+#
+# 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_INET6_TUNNEL=m
+CONFIG_IPV6_TUNNEL=m
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_BRIDGE_NETFILTER=y
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+CONFIG_IP_NF_CT_ACCT=y
+CONFIG_IP_NF_CONNTRACK_MARK=y
+CONFIG_IP_NF_CT_PROTO_SCTP=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_MATCH_PHYSDEV=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_REALM=m
+CONFIG_IP_NF_MATCH_SCTP=m
+CONFIG_IP_NF_MATCH_COMMENT=m
+CONFIG_IP_NF_MATCH_CONNMARK=m
+CONFIG_IP_NF_MATCH_HASHLIMIT=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_TARGET_TCPMSS=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_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_CONNMARK=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_TARGET_NOTRACK=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=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_MATCH_PHYSDEV=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
+
+#
+# Bridge: Netfilter Configuration
+#
+CONFIG_BRIDGE_NF_EBTABLES=m
+CONFIG_BRIDGE_EBT_BROUTE=m
+CONFIG_BRIDGE_EBT_T_FILTER=m
+CONFIG_BRIDGE_EBT_T_NAT=m
+CONFIG_BRIDGE_EBT_802_3=m
+CONFIG_BRIDGE_EBT_AMONG=m
+CONFIG_BRIDGE_EBT_ARP=m
+CONFIG_BRIDGE_EBT_IP=m
+CONFIG_BRIDGE_EBT_LIMIT=m
+CONFIG_BRIDGE_EBT_MARK=m
+CONFIG_BRIDGE_EBT_PKTTYPE=m
+CONFIG_BRIDGE_EBT_STP=m
+CONFIG_BRIDGE_EBT_VLAN=m
+CONFIG_BRIDGE_EBT_ARPREPLY=m
+CONFIG_BRIDGE_EBT_DNAT=m
+CONFIG_BRIDGE_EBT_MARK_T=m
+CONFIG_BRIDGE_EBT_REDIRECT=m
+CONFIG_BRIDGE_EBT_SNAT=m
+CONFIG_BRIDGE_EBT_LOG=m
+CONFIG_BRIDGE_EBT_ULOG=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=m
+CONFIG_VLAN_8021Q=m
+# CONFIG_DECNET is not set
+CONFIG_LLC=m
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+CONFIG_ATALK=m
+CONFIG_DEV_APPLETALK=y
+CONFIG_IPDDP=m
+CONFIG_IPDDP_ENCAP=y
+CONFIG_IPDDP_DECAP=y
+# 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
+
+#
+# QoS and/or fair queueing
+#
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_CLK_JIFFIES=y
+# CONFIG_NET_SCH_CLK_GETTIMEOFDAY is not set
+# 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=y
+# CONFIG_CLS_U32_MARK 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 is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=y
+CONFIG_PCNET32=y
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+# CONFIG_E100 is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+CONFIG_LAN_SAA9730=y
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC 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=m
+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 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIO_RAW=y
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+CONFIG_INPUT_MOUSE=y
+# CONFIG_MOUSE_PS2 is not set
+CONFIG_MOUSE_SERIAL=m
+# CONFIG_MOUSE_VSXXXAA 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=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# 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
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+CONFIG_REISERFS_PROC_INFO=y
+CONFIG_REISERFS_FS_XATTR=y
+CONFIG_REISERFS_FS_POSIX_ACL=y
+CONFIG_REISERFS_FS_SECURITY=y
+CONFIG_JFS_FS=m
+CONFIG_JFS_POSIX_ACL=y
+CONFIG_JFS_SECURITY=y
+# CONFIG_JFS_DEBUG is not set
+# CONFIG_JFS_STATISTICS 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=y
+CONFIG_MINIX_FS=m
+CONFIG_ROMFS_FS=m
+CONFIG_QUOTA=y
+# CONFIG_QFMT_V1 is not set
+CONFIG_QFMT_V2=y
+CONFIG_QUOTACTL=y
+CONFIG_DNOTIFY=y
+CONFIG_AUTOFS_FS=y
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# 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=m
+CONFIG_HFS_FS=m
+CONFIG_HFSPLUS_FS=m
+CONFIG_BEFS_FS=m
+# CONFIG_BEFS_DEBUG is not set
+CONFIG_BFS_FS=m
+CONFIG_EFS_FS=m
+CONFIG_CRAMFS=m
+CONFIG_VXFS_FS=m
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+CONFIG_SYSV_FS=m
+CONFIG_UFS_FS=m
+# CONFIG_UFS_FS_WRITE is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=y
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V4 is not set
+# CONFIG_NFSD_TCP is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# 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
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
+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_ANUBIS=m
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=m
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
diff --git a/arch/mips/configs/capcella_defconfig b/arch/mips/configs/capcella_defconfig
new file mode 100644
index 0000000..1b7f8a7
--- /dev/null
+++ b/arch/mips/configs/capcella_defconfig
@@ -0,0 +1,705 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-rc2
+# Wed Jan 26 02:49:00 2005
+#
+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_LOCALVERSION=""
+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_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM 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_MODULE_SRCVERSION_ALL=y
+CONFIG_KMOD=y
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ is not set
+CONFIG_MACH_VR41XX=y
+# CONFIG_NEC_CMBVR4133 is not set
+# CONFIG_CASIO_E55 is not set
+# CONFIG_IBM_WORKPAD is not set
+# CONFIG_TANBAC_TB0226 is not set
+# CONFIG_TANBAC_TB0229 is not set
+# CONFIG_VICTOR_MPC30X is not set
+CONFIG_ZAO_CAPCELLA=y
+CONFIG_PCI_VR41XX=y
+CONFIG_VRC4173=y
+# 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_OCELOT_3 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 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_GENERIC_CALIBRATE_DELAY=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_IRQ_CPU=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+
+#
+# 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=y
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_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_CPU_ADVANCED is not set
+CONFIG_CPU_HAS_SYNC=y
+# CONFIG_PREEMPT is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_HW_HAS_PCI=y
+CONFIG_PCI=y
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+CONFIG_MMU=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# 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_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_RAM is not set
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_ATA_OVER_ETH=m
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+# CONFIG_BLK_DEV_IDEPCI is not set
+# CONFIG_IDE_ARM is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# 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 is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+CONFIG_INET_TUNNEL=m
+CONFIG_IP_TCPDIAG=m
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# 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 is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# 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 is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_PCI is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI 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
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=m
+CONFIG_SERIO_RAW=m
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD 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=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# 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
+
+#
+# PCI-based Watchdog Cards
+#
+# CONFIG_PCIPCWATCHDOG is not set
+# CONFIG_WDTPCI is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# 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
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+CONFIG_AUTOFS_FS=y
+CONFIG_AUTOFS4_FS=y
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# 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 is not set
+# 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 is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=y
+# CONFIG_NFSD_V3 is not set
+# CONFIG_NFSD_TCP is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_EXPORTFS=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC32 is not set
+CONFIG_LIBCRC32C=m
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
diff --git a/arch/mips/configs/cobalt_defconfig b/arch/mips/configs/cobalt_defconfig
new file mode 100644
index 0000000..8861854
--- /dev/null
+++ b/arch/mips/configs/cobalt_defconfig
@@ -0,0 +1,680 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-rc2
+# Wed Jan 26 02:49:00 2005
+#
+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_LOCALVERSION=""
+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=y
+CONFIG_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+CONFIG_MIPS_COBALT=y
+# 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_OCELOT_3 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 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_GENERIC_CALIBRATE_DELAY=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_I8259=y
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_IRQ_CPU=y
+CONFIG_MIPS_GT64111=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+
+#
+# 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 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+CONFIG_CPU_NEVADA=y
+# 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_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
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_HW_HAS_PCI=y
+CONFIG_PCI=y
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+CONFIG_MMU=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=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_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_RAM is not set
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
+CONFIG_CDROM_PKTCDVD=y
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_ATA_OVER_ETH=y
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+# CONFIG_BLK_DEV_IDEPCI is not set
+# CONFIG_IDE_ARM is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_NETLINK_DEV=y
+CONFIG_UNIX=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+CONFIG_INET_TUNNEL=y
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=y
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# 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 is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# 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 is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_PCI is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI 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 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_LIBPS2 is not set
+CONFIG_SERIO_RAW=y
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD 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=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+CONFIG_RTC=y
+CONFIG_COBALT_LCD=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# 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
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD 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 is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# 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 is not set
+# 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 is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC32 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
diff --git a/arch/mips/configs/db1000_defconfig b/arch/mips/configs/db1000_defconfig
new file mode 100644
index 0000000..19cac1b
--- /dev/null
+++ b/arch/mips/configs/db1000_defconfig
@@ -0,0 +1,763 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-rc2
+# Wed Jan 26 02:49:01 2005
+#
+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_LOCALVERSION=""
+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=y
+CONFIG_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM 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_MODULE_SRCVERSION_ALL=y
+CONFIG_KMOD=y
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ 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_OCELOT_3 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 is not set
+CONFIG_SOC_AU1X00=y
+CONFIG_SOC_AU1000=y
+# CONFIG_SOC_AU1100 is not set
+# CONFIG_SOC_AU1500 is not set
+# CONFIG_SOC_AU1550 is not set
+# CONFIG_MIPS_PB1000 is not set
+# CONFIG_MIPS_PB1100 is not set
+# CONFIG_MIPS_PB1500 is not set
+# CONFIG_MIPS_PB1550 is not set
+CONFIG_MIPS_DB1000=y
+# CONFIG_MIPS_DB1100 is not set
+# CONFIG_MIPS_DB1500 is not set
+# CONFIG_MIPS_DB1550 is not set
+# CONFIG_MIPS_BOSPORUS is not set
+# CONFIG_MIPS_MIRAGE is not set
+# CONFIG_MIPS_XXS1500 is not set
+# CONFIG_MIPS_MTX1 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_GENERIC_CALIBRATE_DELAY=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+
+#
+# CPU selection
+#
+CONFIG_CPU_MIPS32=y
+# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_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_CPU_HAS_PREFETCH=y
+CONFIG_64BIT_PHYS_ADDR=y
+# CONFIG_CPU_ADVANCED is not set
+CONFIG_CPU_HAS_LLSC=y
+CONFIG_CPU_HAS_SYNC=y
+# CONFIG_PREEMPT is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_HW_HAS_PCI=y
+# CONFIG_PCI is not set
+CONFIG_MMU=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+CONFIG_PCCARD=m
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=m
+
+#
+# PC-card bridges
+#
+# CONFIG_TCIC is not set
+# CONFIG_PCMCIA_AU1X00 is not set
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# 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_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_ATA_OVER_ETH=m
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI 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 is not set
+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 is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+CONFIG_INET_TUNNEL=m
+CONFIG_IP_TCPDIAG=m
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+# CONFIG_IPV6 is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+
+#
+# IP: Netfilter Configuration
+#
+# CONFIG_IP_NF_CONNTRACK is not set
+CONFIG_IP_NF_CONNTRACK_MARK=y
+# CONFIG_IP_NF_QUEUE is not set
+# CONFIG_IP_NF_IPTABLES is not set
+# CONFIG_IP_NF_ARPTABLES is not set
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# 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 is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# 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 is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=m
+CONFIG_MIPS_AU1X00_ENET=y
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# PCMCIA network device support
+#
+CONFIG_NET_PCMCIA=y
+CONFIG_PCMCIA_3C589=m
+CONFIG_PCMCIA_3C574=m
+CONFIG_PCMCIA_FMVJ18X=m
+CONFIG_PCMCIA_PCNET=m
+CONFIG_PCMCIA_NMCLAN=m
+CONFIG_PCMCIA_SMC91C92=m
+CONFIG_PCMCIA_XIRC2PS=m
+CONFIG_PCMCIA_AXNET=m
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+CONFIG_PPP=m
+CONFIG_PPP_MULTILINK=y
+# CONFIG_PPP_FILTER is not set
+CONFIG_PPP_ASYNC=m
+# CONFIG_PPP_SYNC_TTY is not set
+CONFIG_PPP_DEFLATE=m
+# CONFIG_PPP_BSDCOMP is not set
+CONFIG_PPPOE=m
+# 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=y
+# 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 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_LIBPS2 is not set
+CONFIG_SERIO_RAW=m
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD 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
+# CONFIG_AU1X00_GPIO is not set
+# CONFIG_TS_AU1X00_ADS7846 is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_AU1X00=y
+CONFIG_SERIAL_AU1X00_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+CONFIG_RTC=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+
+#
+# PCMCIA character devices
+#
+CONFIG_SYNCLINK_CS=m
+# CONFIG_RAW_DRIVER is not set
+
+#
+# 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
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB_ARCH_HAS_HCD is not set
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+# CONFIG_EXT2_FS_SECURITY 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=m
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+CONFIG_REISERFS_FS_XATTR=y
+CONFIG_REISERFS_FS_POSIX_ACL=y
+CONFIG_REISERFS_FS_SECURITY=y
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+CONFIG_AUTOFS_FS=m
+CONFIG_AUTOFS4_FS=m
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# 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=y
+# CONFIG_TMPFS_XATTR 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 is not set
+CONFIG_CRAMFS=m
+# 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 is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=m
+# CONFIG_NFSD_V3 is not set
+# CONFIG_NFSD_TCP is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_EXPORTFS=m
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=m
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=y
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+CONFIG_CRYPTO_SHA512=y
+CONFIG_CRYPTO_WP512=m
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+CONFIG_CRYPTO_TWOFISH=y
+# CONFIG_CRYPTO_SERPENT is not set
+CONFIG_CRYPTO_AES=m
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_TEA=m
+# CONFIG_CRYPTO_ARC4 is not set
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_DEFLATE=y
+CONFIG_CRYPTO_MICHAEL_MIC=y
+CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=m
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
diff --git a/arch/mips/configs/db1100_defconfig b/arch/mips/configs/db1100_defconfig
new file mode 100644
index 0000000..035ac95
--- /dev/null
+++ b/arch/mips/configs/db1100_defconfig
@@ -0,0 +1,758 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-rc2
+# Wed Jan 26 02:49:01 2005
+#
+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_LOCALVERSION=""
+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=y
+CONFIG_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM 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_MODULE_SRCVERSION_ALL=y
+CONFIG_KMOD=y
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ 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_OCELOT_3 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 is not set
+CONFIG_SOC_AU1X00=y
+# CONFIG_SOC_AU1000 is not set
+CONFIG_SOC_AU1100=y
+# CONFIG_SOC_AU1500 is not set
+# CONFIG_SOC_AU1550 is not set
+# CONFIG_MIPS_PB1000 is not set
+# CONFIG_MIPS_PB1100 is not set
+# CONFIG_MIPS_PB1500 is not set
+# CONFIG_MIPS_PB1550 is not set
+# CONFIG_MIPS_DB1000 is not set
+CONFIG_MIPS_DB1100=y
+# CONFIG_MIPS_DB1500 is not set
+# CONFIG_MIPS_DB1550 is not set
+# CONFIG_MIPS_BOSPORUS is not set
+# CONFIG_MIPS_MIRAGE is not set
+# CONFIG_MIPS_XXS1500 is not set
+# CONFIG_MIPS_MTX1 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_GENERIC_CALIBRATE_DELAY=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+
+#
+# CPU selection
+#
+CONFIG_CPU_MIPS32=y
+# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_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_CPU_HAS_PREFETCH=y
+# CONFIG_64BIT_PHYS_ADDR is not set
+# CONFIG_CPU_ADVANCED is not set
+CONFIG_CPU_HAS_LLSC=y
+CONFIG_CPU_HAS_SYNC=y
+# CONFIG_PREEMPT is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_MMU=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+CONFIG_PCCARD=m
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=m
+
+#
+# PC-card bridges
+#
+# CONFIG_TCIC is not set
+# CONFIG_PCMCIA_AU1X00 is not set
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# 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_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_ATA_OVER_ETH=m
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI 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 is not set
+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 is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+CONFIG_INET_TUNNEL=m
+CONFIG_IP_TCPDIAG=m
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+# CONFIG_IPV6 is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+
+#
+# IP: Netfilter Configuration
+#
+# CONFIG_IP_NF_CONNTRACK is not set
+CONFIG_IP_NF_CONNTRACK_MARK=y
+# CONFIG_IP_NF_QUEUE is not set
+# CONFIG_IP_NF_IPTABLES is not set
+# CONFIG_IP_NF_ARPTABLES is not set
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# 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 is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# 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 is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=m
+# CONFIG_MIPS_AU1X00_ENET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# PCMCIA network device support
+#
+CONFIG_NET_PCMCIA=y
+CONFIG_PCMCIA_3C589=m
+CONFIG_PCMCIA_3C574=m
+CONFIG_PCMCIA_FMVJ18X=m
+CONFIG_PCMCIA_PCNET=m
+CONFIG_PCMCIA_NMCLAN=m
+CONFIG_PCMCIA_SMC91C92=m
+CONFIG_PCMCIA_XIRC2PS=m
+CONFIG_PCMCIA_AXNET=m
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+CONFIG_PPP=m
+CONFIG_PPP_MULTILINK=y
+# CONFIG_PPP_FILTER is not set
+CONFIG_PPP_ASYNC=m
+# CONFIG_PPP_SYNC_TTY is not set
+CONFIG_PPP_DEFLATE=m
+# CONFIG_PPP_BSDCOMP is not set
+CONFIG_PPPOE=m
+# 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=y
+# 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 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+CONFIG_SERIO_LIBPS2=m
+CONFIG_SERIO_RAW=m
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD 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
+# CONFIG_AU1X00_GPIO is not set
+# CONFIG_TS_AU1X00_ADS7846 is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_AU1X00 is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+CONFIG_RTC=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+
+#
+# PCMCIA character devices
+#
+CONFIG_SYNCLINK_CS=m
+# CONFIG_RAW_DRIVER is not set
+
+#
+# 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
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB_ARCH_HAS_HCD is not set
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+# CONFIG_EXT2_FS_SECURITY 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=m
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+CONFIG_REISERFS_FS_XATTR=y
+CONFIG_REISERFS_FS_POSIX_ACL=y
+CONFIG_REISERFS_FS_SECURITY=y
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+CONFIG_AUTOFS_FS=m
+CONFIG_AUTOFS4_FS=m
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# 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=y
+# CONFIG_TMPFS_XATTR 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 is not set
+CONFIG_CRAMFS=m
+# 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 is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=m
+# CONFIG_NFSD_V3 is not set
+# CONFIG_NFSD_TCP is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_EXPORTFS=m
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=m
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=y
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+CONFIG_CRYPTO_SHA512=y
+CONFIG_CRYPTO_WP512=m
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+CONFIG_CRYPTO_TWOFISH=y
+# CONFIG_CRYPTO_SERPENT is not set
+CONFIG_CRYPTO_AES=m
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_TEA=m
+# CONFIG_CRYPTO_ARC4 is not set
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_DEFLATE=y
+CONFIG_CRYPTO_MICHAEL_MIC=y
+CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=m
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
diff --git a/arch/mips/configs/db1500_defconfig b/arch/mips/configs/db1500_defconfig
new file mode 100644
index 0000000..c38c4ed
--- /dev/null
+++ b/arch/mips/configs/db1500_defconfig
@@ -0,0 +1,1018 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-rc2
+# Wed Jan 26 02:49:01 2005
+#
+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_LOCALVERSION=""
+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=y
+CONFIG_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM 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_MODULE_SRCVERSION_ALL=y
+CONFIG_KMOD=y
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ 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_OCELOT_3 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 is not set
+CONFIG_SOC_AU1X00=y
+# CONFIG_SOC_AU1000 is not set
+# CONFIG_SOC_AU1100 is not set
+CONFIG_SOC_AU1500=y
+# CONFIG_SOC_AU1550 is not set
+# CONFIG_MIPS_PB1000 is not set
+# CONFIG_MIPS_PB1100 is not set
+# CONFIG_MIPS_PB1500 is not set
+# CONFIG_MIPS_PB1550 is not set
+# CONFIG_MIPS_DB1000 is not set
+# CONFIG_MIPS_DB1100 is not set
+CONFIG_MIPS_DB1500=y
+# CONFIG_MIPS_DB1550 is not set
+# CONFIG_MIPS_BOSPORUS is not set
+# CONFIG_MIPS_MIRAGE is not set
+# CONFIG_MIPS_XXS1500 is not set
+# CONFIG_MIPS_MTX1 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_GENERIC_CALIBRATE_DELAY=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_DMA_COHERENT=y
+CONFIG_MIPS_DISABLE_OBSOLETE_IDE=y
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+
+#
+# CPU selection
+#
+CONFIG_CPU_MIPS32=y
+# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_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_CPU_HAS_PREFETCH=y
+CONFIG_64BIT_PHYS_ADDR=y
+# CONFIG_CPU_ADVANCED is not set
+CONFIG_CPU_HAS_LLSC=y
+CONFIG_CPU_HAS_SYNC=y
+# CONFIG_PREEMPT is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_HW_HAS_PCI=y
+CONFIG_PCI=y
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+CONFIG_MMU=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+CONFIG_PCCARD=m
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=m
+CONFIG_CARDBUS=y
+
+#
+# PC-card bridges
+#
+# CONFIG_YENTA is not set
+# CONFIG_PD6729 is not set
+# CONFIG_I82092 is not set
+# CONFIG_TCIC is not set
+CONFIG_PCMCIA_AU1X00=m
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_CONCAT is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_CFI_AMDSTD_RETRY=0
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_XIP is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+CONFIG_MTD_DB1X00=y
+CONFIG_MTD_DB1X00_BOOT=y
+CONFIG_MTD_DB1X00_USER=y
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLKMTD is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND 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_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
+# CONFIG_BLK_DEV_RAM is not set
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_ATA_OVER_ETH=m
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+CONFIG_BLK_DEV_IDECS=m
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+# CONFIG_IDE_GENERIC is not set
+# CONFIG_BLK_DEV_IDEPCI is not set
+# CONFIG_IDE_ARM is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+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 is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+CONFIG_INET_TUNNEL=m
+CONFIG_IP_TCPDIAG=m
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+# CONFIG_IPV6 is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+
+#
+# IP: Netfilter Configuration
+#
+# CONFIG_IP_NF_CONNTRACK is not set
+CONFIG_IP_NF_CONNTRACK_MARK=y
+# CONFIG_IP_NF_QUEUE is not set
+# CONFIG_IP_NF_IPTABLES is not set
+# CONFIG_IP_NF_ARPTABLES is not set
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# 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 is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# 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 is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+CONFIG_MIPS_AU1X00_ENET=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_PCI is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# PCMCIA network device support
+#
+# CONFIG_NET_PCMCIA is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+CONFIG_PPP=m
+CONFIG_PPP_MULTILINK=y
+# CONFIG_PPP_FILTER is not set
+CONFIG_PPP_ASYNC=m
+# CONFIG_PPP_SYNC_TTY is not set
+CONFIG_PPP_DEFLATE=m
+# CONFIG_PPP_BSDCOMP is not set
+CONFIG_PPPOE=m
+# 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=y
+# 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 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_LIBPS2 is not set
+CONFIG_SERIO_RAW=m
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD 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 is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_AU1X00_GPIO is not set
+# CONFIG_TS_AU1X00_ADS7846 is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_AU1X00=y
+CONFIG_SERIAL_AU1X00_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+CONFIG_RTC=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+
+#
+# PCMCIA character devices
+#
+CONFIG_SYNCLINK_CS=m
+# CONFIG_RAW_DRIVER is not set
+
+#
+# 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
+#
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+CONFIG_SOUND=y
+
+#
+# Advanced Linux Sound Architecture
+#
+# CONFIG_SND is not set
+
+#
+# Open Sound System
+#
+CONFIG_SOUND_PRIME=y
+# CONFIG_SOUND_BT878 is not set
+# CONFIG_SOUND_CMPCI is not set
+# CONFIG_SOUND_EMU10K1 is not set
+# CONFIG_SOUND_FUSION is not set
+# CONFIG_SOUND_CS4281 is not set
+# CONFIG_SOUND_ES1370 is not set
+# CONFIG_SOUND_ES1371 is not set
+# CONFIG_SOUND_ESSSOLO1 is not set
+# CONFIG_SOUND_MAESTRO is not set
+# CONFIG_SOUND_MAESTRO3 is not set
+# CONFIG_SOUND_ICH is not set
+# CONFIG_SOUND_SONICVIBES is not set
+CONFIG_SOUND_AU1000=y
+# CONFIG_SOUND_TRIDENT is not set
+# CONFIG_SOUND_MSNDCLAS is not set
+# CONFIG_SOUND_MSNDPIN is not set
+# CONFIG_SOUND_VIA82CXXX is not set
+# CONFIG_SOUND_OSS is not set
+# CONFIG_SOUND_ALI5455 is not set
+# CONFIG_SOUND_FORTE is not set
+# CONFIG_SOUND_RME96XX is not set
+# CONFIG_SOUND_AD1980 is not set
+
+#
+# USB support
+#
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+# CONFIG_USB_DEVICEFS is not set
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_EHCI_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_UHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_AUDIO is not set
+# CONFIG_USB_BLUETOOTH_TTY is not set
+# CONFIG_USB_MIDI is not set
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+# CONFIG_USB_STORAGE is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+CONFIG_USB_HIDINPUT=y
+# CONFIG_HID_FF is not set
+# CONFIG_USB_HIDDEV is not set
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_MTOUCH is not set
+# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+
+#
+# USB Multimedia devices
+#
+# CONFIG_USB_DABUSB is not set
+
+#
+# Video4Linux support is needed for USB Multimedia device support
+#
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETKIT is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_IDMOUSE is not set
+
+#
+# USB ATM/DSL drivers
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+# CONFIG_EXT2_FS_SECURITY 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=m
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+CONFIG_REISERFS_FS_XATTR=y
+CONFIG_REISERFS_FS_POSIX_ACL=y
+CONFIG_REISERFS_FS_SECURITY=y
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+CONFIG_AUTOFS_FS=m
+CONFIG_AUTOFS4_FS=m
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# 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=y
+# CONFIG_TMPFS_XATTR 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 is not set
+# CONFIG_JFFS_FS is not set
+# CONFIG_JFFS2_FS is not set
+CONFIG_CRAMFS=m
+# 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 is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=m
+# CONFIG_NFSD_V3 is not set
+# CONFIG_NFSD_TCP is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_EXPORTFS=m
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=m
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=y
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+CONFIG_CRYPTO_SHA512=y
+CONFIG_CRYPTO_WP512=m
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+CONFIG_CRYPTO_TWOFISH=y
+# CONFIG_CRYPTO_SERPENT is not set
+CONFIG_CRYPTO_AES=m
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_TEA=m
+# CONFIG_CRYPTO_ARC4 is not set
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_DEFLATE=y
+CONFIG_CRYPTO_MICHAEL_MIC=y
+CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=m
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
diff --git a/arch/mips/configs/db1550_defconfig b/arch/mips/configs/db1550_defconfig
new file mode 100644
index 0000000..ee81309
--- /dev/null
+++ b/arch/mips/configs/db1550_defconfig
@@ -0,0 +1,932 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-rc2
+# Wed Jan 26 02:49:02 2005
+#
+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_LOCALVERSION=""
+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=y
+CONFIG_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM 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_MODULE_SRCVERSION_ALL=y
+CONFIG_KMOD=y
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ 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_OCELOT_3 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 is not set
+CONFIG_SOC_AU1X00=y
+# CONFIG_SOC_AU1000 is not set
+# CONFIG_SOC_AU1100 is not set
+# CONFIG_SOC_AU1500 is not set
+CONFIG_SOC_AU1550=y
+# CONFIG_MIPS_PB1000 is not set
+# CONFIG_MIPS_PB1100 is not set
+# CONFIG_MIPS_PB1500 is not set
+# CONFIG_MIPS_PB1550 is not set
+# CONFIG_MIPS_DB1000 is not set
+# CONFIG_MIPS_DB1100 is not set
+# CONFIG_MIPS_DB1500 is not set
+CONFIG_MIPS_DB1550=y
+# CONFIG_MIPS_BOSPORUS is not set
+# CONFIG_MIPS_MIRAGE is not set
+# CONFIG_MIPS_XXS1500 is not set
+# CONFIG_MIPS_MTX1 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_GENERIC_CALIBRATE_DELAY=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_DMA_COHERENT=y
+CONFIG_MIPS_DISABLE_OBSOLETE_IDE=y
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+
+#
+# CPU selection
+#
+CONFIG_CPU_MIPS32=y
+# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_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_CPU_HAS_PREFETCH=y
+CONFIG_64BIT_PHYS_ADDR=y
+# CONFIG_CPU_ADVANCED is not set
+CONFIG_CPU_HAS_LLSC=y
+CONFIG_CPU_HAS_SYNC=y
+# CONFIG_PREEMPT is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_HW_HAS_PCI=y
+CONFIG_PCI=y
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+CONFIG_MMU=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+CONFIG_PCCARD=m
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=m
+CONFIG_CARDBUS=y
+
+#
+# PC-card bridges
+#
+# CONFIG_YENTA is not set
+# CONFIG_PD6729 is not set
+# CONFIG_I82092 is not set
+# CONFIG_TCIC is not set
+CONFIG_PCMCIA_AU1X00=m
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_CONCAT is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_CFI_AMDSTD_RETRY=0
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+CONFIG_MTD_DB1550=y
+CONFIG_MTD_DB1550_BOOT=y
+CONFIG_MTD_DB1550_USER=y
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLKMTD is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+CONFIG_MTD_NAND=m
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+CONFIG_MTD_NAND_IDS=m
+CONFIG_MTD_NAND_AU1550=m
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_NANDSIM 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_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_RAM is not set
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_ATA_OVER_ETH=m
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+CONFIG_BLK_DEV_IDECS=m
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_IDEPCI=y
+# CONFIG_IDEPCI_SHARE_IRQ is not set
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+# CONFIG_IDEDMA_PCI_AUTO is not set
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD74XX is not set
+# CONFIG_BLK_DEV_CMD64X is not set
+# CONFIG_BLK_DEV_TRIFLEX is not set
+# CONFIG_BLK_DEV_CY82C693 is not set
+# CONFIG_BLK_DEV_CS5520 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT34X is not set
+# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_SC1200 is not set
+# CONFIG_BLK_DEV_PIIX is not set
+# CONFIG_BLK_DEV_NS87415 is not set
+# CONFIG_BLK_DEV_PDC202XX_OLD is not set
+# CONFIG_BLK_DEV_PDC202XX_NEW is not set
+# CONFIG_BLK_DEV_SVWKS is not set
+# CONFIG_BLK_DEV_SIIMAGE is not set
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+# CONFIG_BLK_DEV_VIA82CXXX is not set
+# CONFIG_IDE_ARM is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+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 is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+CONFIG_INET_TUNNEL=m
+CONFIG_IP_TCPDIAG=m
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+# CONFIG_IPV6 is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+
+#
+# IP: Netfilter Configuration
+#
+# CONFIG_IP_NF_CONNTRACK is not set
+CONFIG_IP_NF_CONNTRACK_MARK=y
+# CONFIG_IP_NF_QUEUE is not set
+# CONFIG_IP_NF_IPTABLES is not set
+# CONFIG_IP_NF_ARPTABLES is not set
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# 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 is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# 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 is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=m
+CONFIG_MIPS_AU1X00_ENET=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_PCI is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# PCMCIA network device support
+#
+CONFIG_NET_PCMCIA=y
+CONFIG_PCMCIA_3C589=m
+CONFIG_PCMCIA_3C574=m
+CONFIG_PCMCIA_FMVJ18X=m
+CONFIG_PCMCIA_PCNET=m
+CONFIG_PCMCIA_NMCLAN=m
+CONFIG_PCMCIA_SMC91C92=m
+CONFIG_PCMCIA_XIRC2PS=m
+CONFIG_PCMCIA_AXNET=m
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+CONFIG_PPP=m
+CONFIG_PPP_MULTILINK=y
+# CONFIG_PPP_FILTER is not set
+CONFIG_PPP_ASYNC=m
+# CONFIG_PPP_SYNC_TTY is not set
+CONFIG_PPP_DEFLATE=m
+# CONFIG_PPP_BSDCOMP is not set
+CONFIG_PPPOE=m
+# 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=y
+# 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 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_LIBPS2 is not set
+CONFIG_SERIO_RAW=m
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD 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 is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_AU1X00_GPIO is not set
+# CONFIG_TS_AU1X00_ADS7846 is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_AU1X00=y
+CONFIG_SERIAL_AU1X00_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+
+#
+# PCMCIA character devices
+#
+CONFIG_SYNCLINK_CS=m
+# CONFIG_RAW_DRIVER is not set
+
+#
+# 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
+#
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+# CONFIG_EXT2_FS_SECURITY 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=m
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+CONFIG_REISERFS_FS_XATTR=y
+CONFIG_REISERFS_FS_POSIX_ACL=y
+CONFIG_REISERFS_FS_SECURITY=y
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+CONFIG_AUTOFS_FS=m
+CONFIG_AUTOFS4_FS=m
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# 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=y
+# CONFIG_TMPFS_XATTR 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 is not set
+# CONFIG_JFFS_FS is not set
+# CONFIG_JFFS2_FS is not set
+CONFIG_CRAMFS=m
+# 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 is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=m
+# CONFIG_NFSD_V3 is not set
+# CONFIG_NFSD_TCP is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_EXPORTFS=m
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=m
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=y
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+CONFIG_CRYPTO_SHA512=y
+CONFIG_CRYPTO_WP512=m
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+CONFIG_CRYPTO_TWOFISH=y
+# CONFIG_CRYPTO_SERPENT is not set
+CONFIG_CRYPTO_AES=m
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_TEA=m
+# CONFIG_CRYPTO_ARC4 is not set
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_DEFLATE=y
+CONFIG_CRYPTO_MICHAEL_MIC=y
+CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=m
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
diff --git a/arch/mips/configs/ddb5476_defconfig b/arch/mips/configs/ddb5476_defconfig
new file mode 100644
index 0000000..d43ed57
--- /dev/null
+++ b/arch/mips/configs/ddb5476_defconfig
@@ -0,0 +1,726 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-rc2
+# Wed Jan 26 02:49:02 2005
+#
+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_LOCALVERSION=""
+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_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ 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_OCELOT_3 is not set
+# CONFIG_MOMENCO_JAGUAR_ATX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_DDB5074 is not set
+CONFIG_DDB5476=y
+# CONFIG_DDB5477 is not set
+# CONFIG_NEC_OSPREY is not set
+# CONFIG_SGI_IP22 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_GENERIC_CALIBRATE_DELAY=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_I8259=y
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_IRQ_CPU=y
+CONFIG_DDB5XXX_COMMON=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+CONFIG_HAVE_STD_PC_SERIAL_PORT=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 is not set
+CONFIG_CPU_R5432=y
+# 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_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
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_HW_HAS_PCI=y
+CONFIG_PCI=y
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+CONFIG_ISA=y
+CONFIG_MMU=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+CONFIG_PCMCIA_PROBE=y
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+# CONFIG_PNP is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_XD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_RAM is not set
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
+CONFIG_CDROM_PKTCDVD=y
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_ATA_OVER_ETH=y
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+# CONFIG_BLK_DEV_IDEPCI is not set
+# CONFIG_IDE_ARM is not set
+# CONFIG_IDE_CHIPSETS is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Old CD-ROM drivers (not SCSI, not IDE)
+#
+# CONFIG_CD_NO_IDESCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_NETLINK_DEV=y
+CONFIG_UNIX=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# 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_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+CONFIG_INET_TUNNEL=y
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=y
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# 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 is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# 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 is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_LANCE is not set
+# CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_NET_VENDOR_RACAL is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_AT1700 is not set
+# CONFIG_DEPCA is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_ISA is not set
+# CONFIG_NET_PCI is not set
+# CONFIG_NET_POCKET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI 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 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_LIBPS2 is not set
+CONFIG_SERIO_RAW=y
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD 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=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# 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
+#
+CONFIG_FB=y
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_CIRRUS is not set
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT is not set
+# CONFIG_FB_RIVA is not set
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_RADEON_OLD is not set
+# CONFIG_FB_RADEON is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_SAVAGE is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_KYRO is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_E1356 is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE is not set
+
+#
+# Logo configuration
+#
+# CONFIG_LOGO is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# 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 is not set
+# 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 is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE="ip=any"
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC32 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
diff --git a/arch/mips/configs/ddb5477_defconfig b/arch/mips/configs/ddb5477_defconfig
new file mode 100644
index 0000000..5a032cd
--- /dev/null
+++ b/arch/mips/configs/ddb5477_defconfig
@@ -0,0 +1,680 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-rc2
+# Wed Jan 26 02:49:02 2005
+#
+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_LOCALVERSION=""
+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_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ 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_OCELOT_3 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=y
+CONFIG_DDB5477_BUS_FREQUENCY=0
+# CONFIG_NEC_OSPREY is not set
+# CONFIG_SGI_IP22 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_GENERIC_CALIBRATE_DELAY=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_I8259=y
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_IRQ_CPU=y
+CONFIG_DDB5XXX_COMMON=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+
+#
+# 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 is not set
+CONFIG_CPU_R5432=y
+# 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_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
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_HW_HAS_PCI=y
+CONFIG_PCI=y
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+CONFIG_MMU=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# 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_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_RAM is not set
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
+CONFIG_CDROM_PKTCDVD=y
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_ATA_OVER_ETH=y
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_NETLINK_DEV=y
+CONFIG_UNIX=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# 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_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+CONFIG_INET_TUNNEL=y
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=y
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# 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 is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# 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 is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=y
+CONFIG_PCNET32=y
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+# CONFIG_E100 is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+# CONFIG_LAN_SAA9730 is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI 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 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_LIBPS2 is not set
+CONFIG_SERIO_RAW=y
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD 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=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# 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
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+CONFIG_AUTOFS_FS=y
+CONFIG_AUTOFS4_FS=y
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# 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 is not set
+# 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 is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=y
+# CONFIG_NFSD_V3 is not set
+# CONFIG_NFSD_TCP is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_EXPORTFS=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE="ip=any"
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
diff --git a/arch/mips/configs/decstation_defconfig b/arch/mips/configs/decstation_defconfig
new file mode 100644
index 0000000..32ada79
--- /dev/null
+++ b/arch/mips/configs/decstation_defconfig
@@ -0,0 +1,660 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-rc2
+# Wed Jan 26 02:49:03 2005
+#
+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_LOCALVERSION=""
+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_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM 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_MODULE_SRCVERSION_ALL=y
+CONFIG_KMOD=y
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_MIPS_COBALT is not set
+CONFIG_MACH_DECSTATION=y
+# 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_OCELOT_3 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 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_GENERIC_CALIBRATE_DELAY=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_IRQ_CPU=y
+CONFIG_BOOT_ELF32=y
+CONFIG_MIPS_L1_CACHE_SHIFT=4
+
+#
+# CPU selection
+#
+# CONFIG_CPU_MIPS32 is not set
+# CONFIG_CPU_MIPS64 is not set
+CONFIG_CPU_R3000=y
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_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_CPU_ADVANCED is not set
+CONFIG_CPU_HAS_WB=y
+# CONFIG_PREEMPT is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_TC=y
+CONFIG_MMU=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# 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_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_ATA_OVER_ETH=m
+
+#
+# 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 is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR 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 is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+CONFIG_SCSI_DECNCR=y
+# CONFIG_SCSI_DECSII is not set
+# CONFIG_SCSI_SATA 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 is not set
+CONFIG_NETLINK_DEV=y
+CONFIG_UNIX=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# 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_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+CONFIG_INET_TUNNEL=m
+CONFIG_IP_TCPDIAG=m
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# 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 is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# 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 is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+CONFIG_DECLANCE=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 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_LIBPS2 is not set
+CONFIG_SERIO_RAW=m
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD 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_DZ=y
+CONFIG_SERIAL_DZ_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# 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
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB_ARCH_HAS_HCD is not set
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD 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 is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# 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 is not set
+# 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 is not set
+
+#
+# Network File Systems
+#
+# CONFIG_NFS_FS is not set
+# CONFIG_NFSD is not set
+# CONFIG_EXPORTFS is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+CONFIG_OSF_PARTITION=y
+# 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 is not set
+CONFIG_ULTRIX_PARTITION=y
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=m
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
diff --git a/arch/mips/configs/e55_defconfig b/arch/mips/configs/e55_defconfig
new file mode 100644
index 0000000..52074a20
--- /dev/null
+++ b/arch/mips/configs/e55_defconfig
@@ -0,0 +1,683 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-rc2
+# Wed Jan 26 02:49:03 2005
+#
+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_LOCALVERSION=""
+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_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM 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_MODULE_SRCVERSION_ALL=y
+CONFIG_KMOD=y
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ is not set
+CONFIG_MACH_VR41XX=y
+# CONFIG_NEC_CMBVR4133 is not set
+CONFIG_CASIO_E55=y
+# CONFIG_IBM_WORKPAD is not set
+# CONFIG_TANBAC_TB0226 is not set
+# CONFIG_TANBAC_TB0229 is not set
+# CONFIG_VICTOR_MPC30X is not set
+# CONFIG_ZAO_CAPCELLA is not set
+# CONFIG_VRC4171 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_OCELOT_3 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 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_GENERIC_CALIBRATE_DELAY=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_IRQ_CPU=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+
+#
+# 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=y
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_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_CPU_ADVANCED is not set
+CONFIG_CPU_HAS_SYNC=y
+# CONFIG_PREEMPT is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_ISA=y
+CONFIG_MMU=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+CONFIG_PCMCIA_PROBE=y
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+# CONFIG_PNP is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_XD is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_ATA_OVER_ETH=m
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+# CONFIG_IDE_ARM is not set
+# CONFIG_IDE_CHIPSETS is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Old CD-ROM drivers (not SCSI, not IDE)
+#
+# CONFIG_CD_NO_IDESCSI 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 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 is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+CONFIG_INET_TUNNEL=m
+CONFIG_IP_TCPDIAG=m
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# 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 is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# 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 is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_LANCE is not set
+# CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_NET_VENDOR_RACAL is not set
+# CONFIG_AT1700 is not set
+# CONFIG_DEPCA is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_ISA is not set
+# CONFIG_NET_PCI is not set
+# CONFIG_NET_POCKET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# 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
+# CONFIG_SERIO_LIBPS2 is not set
+CONFIG_SERIO_RAW=m
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD 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=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# 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
+
+#
+# ISA-based Watchdog Cards
+#
+# CONFIG_PCWATCHDOG is not set
+# CONFIG_MIXCOMWD is not set
+# CONFIG_WDT is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# 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
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB_ARCH_HAS_HCD is not set
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+CONFIG_AUTOFS_FS=y
+CONFIG_AUTOFS4_FS=y
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# 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 is not set
+# 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 is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=y
+# CONFIG_NFSD_V3 is not set
+# CONFIG_NFSD_TCP is not set
+CONFIG_LOCKD=y
+CONFIG_EXPORTFS=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC32 is not set
+CONFIG_LIBCRC32C=m
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
diff --git a/arch/mips/configs/ev64120_defconfig b/arch/mips/configs/ev64120_defconfig
new file mode 100644
index 0000000..360e842
--- /dev/null
+++ b/arch/mips/configs/ev64120_defconfig
@@ -0,0 +1,672 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-rc2
+# Wed Jan 26 02:49:03 2005
+#
+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_LOCALVERSION=""
+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_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM 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_MODULE_SRCVERSION_ALL=y
+# CONFIG_KMOD is not set
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ 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=y
+# CONFIG_EVB_PCI1 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_OCELOT_3 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 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_GENERIC_CALIBRATE_DELAY=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_DMA_NONCOHERENT=y
+# CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_MIPS_GT64120=y
+# CONFIG_SYSCLK_75 is not set
+# CONFIG_SYSCLK_83 is not set
+CONFIG_SYSCLK_100=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+
+#
+# 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_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
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_HW_HAS_PCI=y
+CONFIG_PCI=y
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+CONFIG_MMU=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# 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_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_RAM is not set
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_ATA_OVER_ETH=m
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_PACKET is not set
+CONFIG_NETLINK_DEV=y
+CONFIG_UNIX=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+CONFIG_INET_TUNNEL=m
+CONFIG_IP_TCPDIAG=m
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# 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 is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# 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 is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_PCI is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+CONFIG_PPP=y
+# CONFIG_PPP_MULTILINK is not set
+# CONFIG_PPP_FILTER is not set
+CONFIG_PPP_ASYNC=y
+# CONFIG_PPP_SYNC_TTY is not set
+# CONFIG_PPP_DEFLATE is not set
+# CONFIG_PPP_BSDCOMP is not set
+# CONFIG_PPPOE 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 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_LIBPS2 is not set
+CONFIG_SERIO_RAW=m
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD 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=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# 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
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# 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 is not set
+# 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 is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE="console=ttyS0,115200 root=/dev/nfs rw nfsroot=192.168.1.1:/mnt/disk2/fs.gal ip=192.168.1.211:192.168.1.1:::gt::"
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=y
+# CONFIG_CRC32 is not set
+CONFIG_LIBCRC32C=m
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
diff --git a/arch/mips/configs/ev96100_defconfig b/arch/mips/configs/ev96100_defconfig
new file mode 100644
index 0000000..657a950
--- /dev/null
+++ b/arch/mips/configs/ev96100_defconfig
@@ -0,0 +1,626 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-rc2
+# Wed Jan 26 02:49:03 2005
+#
+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_LOCALVERSION=""
+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_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM 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_MODULE_SRCVERSION_ALL=y
+# CONFIG_KMOD is not set
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ 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=y
+# 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_OCELOT_3 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 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_GENERIC_CALIBRATE_DELAY=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_DMA_NONCOHERENT=y
+# CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_IRQ_CPU=y
+CONFIG_MIPS_GT64120=y
+CONFIG_SWAP_IO_SPACE=y
+CONFIG_MIPS_GT96100=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+
+#
+# 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 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+CONFIG_CPU_RM7000=y
+# 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_RM7000_CPU_SCACHE=y
+CONFIG_CPU_HAS_PREFETCH=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
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_HW_HAS_PCI=y
+# CONFIG_PCI is not set
+CONFIG_MMU=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# 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_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_ATA_OVER_ETH=m
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI 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 is not set
+CONFIG_NETLINK_DEV=y
+CONFIG_UNIX=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# 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_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+CONFIG_INET_TUNNEL=m
+CONFIG_IP_TCPDIAG=m
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# 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 is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# 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 is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+CONFIG_MIPS_GT96100ETH=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 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_LIBPS2 is not set
+CONFIG_SERIO_RAW=m
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD 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=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# 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
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB_ARCH_HAS_HCD is not set
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# 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 is not set
+# 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 is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC32 is not set
+CONFIG_LIBCRC32C=m
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
diff --git a/arch/mips/configs/ip22_defconfig b/arch/mips/configs/ip22_defconfig
new file mode 100644
index 0000000..3fb102e
--- /dev/null
+++ b/arch/mips/configs/ip22_defconfig
@@ -0,0 +1,962 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-rc2
+# Wed Jan 26 02:49:04 2005
+#
+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_LOCALVERSION=""
+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_KOBJECT_UEVENT=y
+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_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM 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_MODULE_SRCVERSION_ALL=y
+CONFIG_KMOD=y
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ 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_OCELOT_3 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_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_GENERIC_CALIBRATE_DELAY=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_ARC32=y
+CONFIG_BOOT_ELF32=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+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
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+# CONFIG_EISA is not set
+CONFIG_MMU=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=m
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# 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_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_ATA_OVER_ETH=m
+
+#
+# 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
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+CONFIG_SGIWD93_SCSI=y
+# CONFIG_SCSI_SATA 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
+CONFIG_INET_TUNNEL=m
+CONFIG_IP_TCPDIAG=m
+CONFIG_IP_TCPDIAG_IPV6=y
+
+#
+# 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_INET6_TUNNEL=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_CT_ACCT=y
+CONFIG_IP_NF_CONNTRACK_MARK=y
+# CONFIG_IP_NF_CT_PROTO_SCTP is not set
+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_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_REALM=m
+CONFIG_IP_NF_MATCH_SCTP=m
+CONFIG_IP_NF_MATCH_COMMENT=m
+CONFIG_IP_NF_MATCH_CONNMARK=m
+CONFIG_IP_NF_MATCH_HASHLIMIT=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_TARGET_TCPMSS=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_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_CONNMARK=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_TARGET_NOTRACK=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=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
+
+#
+# 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_CLS_U32_MARK 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=m
+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
+CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIO_RAW=m
+
+#
+# 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=y
+CONFIG_MOUSE_PS2=m
+CONFIG_MOUSE_SERIAL=m
+# CONFIG_MOUSE_VSXXXAA 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
+
+#
+# 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_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
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_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
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB_ARCH_HAS_HCD is not set
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND 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_DNOTIFY=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_RPCSEC_GSS_SPKM3 is not set
+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_EXPERIMENTAL 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
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
+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_ANUBIS=m
+CONFIG_CRYPTO_DEFLATE=y
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
+CONFIG_CRYPTO_TEST=m
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=m
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
diff --git a/arch/mips/configs/ip27_defconfig b/arch/mips/configs/ip27_defconfig
new file mode 100644
index 0000000..1347229
--- /dev/null
+++ b/arch/mips/configs/ip27_defconfig
@@ -0,0 +1,827 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-rc2
+# Wed Jan 26 02:49:04 2005
+#
+CONFIG_MIPS=y
+CONFIG_MIPS64=y
+CONFIG_64BIT=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_LOCK_KERNEL=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=15
+# CONFIG_HOTPLUG is not set
+CONFIG_KOBJECT_UEVENT=y
+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_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM 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 is not set
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_KMOD=y
+CONFIG_STOP_MACHINE=y
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_MACH_VR41XX 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_OCELOT_3 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 is not set
+CONFIG_SGI_IP27=y
+# CONFIG_SGI_SN0_N_MODE is not set
+CONFIG_DISCONTIGMEM=y
+CONFIG_NUMA=y
+# CONFIG_MAPPED_KERNEL is not set
+# CONFIG_REPLICATE_KTEXT is not set
+# CONFIG_REPLICATE_EXHANDLERS is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_SB1xxx_SOC is not set
+# CONFIG_SNI_RM200_PCI is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_ARC=y
+CONFIG_DMA_IP27=y
+# CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_MIPS_L1_CACHE_SHIFT=7
+CONFIG_ARC64=y
+CONFIG_BOOT_ELF64=y
+CONFIG_QL_ISP_A64=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 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+CONFIG_CPU_R10000=y
+# 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_CPU_HAS_PREFETCH=y
+CONFIG_CPU_HAS_LLSC=y
+CONFIG_CPU_HAS_LLDSCD=y
+CONFIG_CPU_HAS_SYNC=y
+CONFIG_SMP=y
+CONFIG_NR_CPUS=64
+# CONFIG_PREEMPT is not set
+# CONFIG_MIPS_INSANE_LARGE is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_HW_HAS_PCI=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+CONFIG_MMU=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_BUILD_ELF64 is not set
+CONFIG_MIPS32_COMPAT=y
+CONFIG_COMPAT=y
+CONFIG_MIPS32_O32=y
+# CONFIG_MIPS32_N32 is not set
+CONFIG_BINFMT_ELF32=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# 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_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_RAM is not set
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_ATA_OVER_ETH=m
+
+#
+# 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 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=y
+
+#
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=y
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_EATA_PIO is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
+CONFIG_SCSI_QLOGIC_ISP=y
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+CONFIG_SCSI_QLA2XXX=y
+# CONFIG_SCSI_QLA21XX is not set
+# CONFIG_SCSI_QLA22XX is not set
+# CONFIG_SCSI_QLA2300 is not set
+# CONFIG_SCSI_QLA2322 is not set
+# CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=y
+CONFIG_MD_LINEAR=m
+CONFIG_MD_RAID0=y
+CONFIG_MD_RAID1=y
+CONFIG_MD_RAID10=m
+CONFIG_MD_RAID5=y
+CONFIG_MD_RAID6=m
+CONFIG_MD_MULTIPATH=m
+CONFIG_MD_FAULTY=m
+CONFIG_BLK_DEV_DM=m
+CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# 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 is not set
+# 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 is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+CONFIG_INET_TUNNEL=m
+CONFIG_IP_TCPDIAG=m
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# 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 is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER 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 is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_SGI_IOC3_ETH=y
+CONFIG_SGI_IOC3_ETH_HW_RX_CSUM=y
+CONFIG_SGI_IOC3_ETH_HW_TX_CSUM=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_PCI is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC 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 is not set
+
+#
+# Userland interfaces
+#
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_LIBPS2 is not set
+CONFIG_SERIO_RAW=m
+
+#
+# Input Device Drivers
+#
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+# CONFIG_SERIAL_8250_MULTIPORT is not set
+# CONFIG_SERIAL_8250_RSA is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+CONFIG_SGI_IP27_RTC=y
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# 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
+#
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+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=y
+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=y
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_QUOTACTL=y
+CONFIG_DNOTIFY=y
+CONFIG_AUTOFS_FS=m
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# 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 is not set
+# 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 is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+# CONFIG_ROOT_NFS is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS 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 is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
+# 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_WP512=m
+CONFIG_CRYPTO_DES=y
+CONFIG_CRYPTO_BLOWFISH=y
+CONFIG_CRYPTO_TWOFISH=y
+CONFIG_CRYPTO_SERPENT=y
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_CAST5=y
+CONFIG_CRYPTO_CAST6=y
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_ARC4=y
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_DEFLATE=y
+CONFIG_CRYPTO_MICHAEL_MIC=y
+CONFIG_CRYPTO_CRC32C=m
+CONFIG_CRYPTO_TEST=m
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
diff --git a/arch/mips/configs/ip32_defconfig b/arch/mips/configs/ip32_defconfig
new file mode 100644
index 0000000..bdf1415
--- /dev/null
+++ b/arch/mips/configs/ip32_defconfig
@@ -0,0 +1,750 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-rc2
+# Wed Jan 26 02:49:04 2005
+#
+CONFIG_MIPS=y
+CONFIG_MIPS64=y
+CONFIG_64BIT=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+CONFIG_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_MACH_VR41XX 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_OCELOT_3 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 is not set
+# CONFIG_SGI_IP27 is not set
+CONFIG_SGI_IP32=y
+# CONFIG_SIBYTE_SB1xxx_SOC is not set
+# CONFIG_SNI_RM200_PCI is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_ARC=y
+CONFIG_DMA_IP32=y
+CONFIG_OWN_DMA=y
+CONFIG_DMA_NONCOHERENT=y
+# CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_ARC32=y
+CONFIG_BOOT_ELF32=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+CONFIG_ARC_MEMORY=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_R5000_CPU_SCACHE=y
+CONFIG_RM7000_CPU_SCACHE=y
+CONFIG_CPU_HAS_LLSC=y
+CONFIG_CPU_HAS_LLDSCD=y
+CONFIG_CPU_HAS_SYNC=y
+# CONFIG_PREEMPT is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_HW_HAS_PCI=y
+CONFIG_PCI=y
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+CONFIG_MMU=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=y
+# CONFIG_BUILD_ELF64 is not set
+CONFIG_MIPS32_COMPAT=y
+CONFIG_COMPAT=y
+CONFIG_MIPS32_O32=y
+# CONFIG_MIPS32_N32 is not set
+CONFIG_BINFMT_ELF32=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# 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_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_RAM is not set
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CDROM_PKTCDVD=y
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_ATA_OVER_ETH=y
+
+#
+# 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=y
+CONFIG_BLK_DEV_SR=y
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=y
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+CONFIG_SCSI_AIC7XXX=y
+CONFIG_AIC7XXX_CMDS_PER_DEVICE=8
+CONFIG_AIC7XXX_RESET_DELAY_MS=15000
+CONFIG_AIC7XXX_DEBUG_ENABLE=y
+CONFIG_AIC7XXX_DEBUG_MASK=0
+CONFIG_AIC7XXX_REG_PRETTY_PRINT=y
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_EATA_PIO is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_ISP is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+CONFIG_SCSI_QLA2XXX=y
+# CONFIG_SCSI_QLA21XX is not set
+# CONFIG_SCSI_QLA22XX is not set
+# CONFIG_SCSI_QLA2300 is not set
+# CONFIG_SCSI_QLA2322 is not set
+# CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# 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 is not set
+# 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_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+CONFIG_INET_TUNNEL=y
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=y
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# 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 is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# 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 is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+CONFIG_SGI_O2MACE_ETH=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_PCI is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC 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 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_MACEPS2 is not set
+# CONFIG_SERIO_LIBPS2 is not set
+CONFIG_SERIO_RAW=y
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD 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=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# 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
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# 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=y
+# CONFIG_TMPFS_XATTR 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 is not set
+# 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 is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS 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 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 is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC32 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
diff --git a/arch/mips/configs/it8172_defconfig b/arch/mips/configs/it8172_defconfig
new file mode 100644
index 0000000..1ca7746
--- /dev/null
+++ b/arch/mips/configs/it8172_defconfig
@@ -0,0 +1,740 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-rc2
+# Wed Jan 26 02:49:05 2005
+#
+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_LOCALVERSION=""
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+CONFIG_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM 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_MODULE_SRCVERSION_ALL=y
+CONFIG_KMOD=y
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ 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=y
+# CONFIG_IT8172_REVC 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_OCELOT_3 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 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_GENERIC_CALIBRATE_DELAY=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_ITE_BOARD_GEN=y
+CONFIG_IT8172_CIR=y
+CONFIG_IT8712=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+
+#
+# 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 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+CONFIG_CPU_NEVADA=y
+# 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_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
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_HW_HAS_PCI=y
+# CONFIG_PCI is not set
+CONFIG_MMU=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_PARTITIONS is not set
+# CONFIG_MTD_CONCAT is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+# CONFIG_MTD_BLOCK is not set
+# CONFIG_MTD_BLOCK_RO is not set
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_XIP is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_PHYSMAP_START=0x8000000
+CONFIG_MTD_PHYSMAP_LEN=0x2000000
+CONFIG_MTD_PHYSMAP_BANKWIDTH=2
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLKMTD is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND 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_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_ATA_OVER_ETH=m
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+# CONFIG_IDE_ARM is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI 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 is not set
+# 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_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+CONFIG_INET_TUNNEL=m
+CONFIG_IP_TCPDIAG=m
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# 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 is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# 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 is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+
+#
+# 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 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_LIBPS2 is not set
+CONFIG_SERIO_RAW=m
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD 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
+# CONFIG_QTRONIX_KEYBOARD is not set
+# CONFIG_IT8172_SCR0 is not set
+# CONFIG_IT8172_SCR1 is not set
+# CONFIG_ITE_GPIO is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# 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
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+CONFIG_SOUND=y
+
+#
+# Advanced Linux Sound Architecture
+#
+# CONFIG_SND is not set
+
+#
+# Open Sound System
+#
+CONFIG_SOUND_PRIME=y
+# CONFIG_SOUND_BT878 is not set
+# CONFIG_SOUND_FUSION is not set
+# CONFIG_SOUND_CS4281 is not set
+# CONFIG_SOUND_SONICVIBES is not set
+CONFIG_SOUND_IT8172=y
+# CONFIG_SOUND_TRIDENT is not set
+# CONFIG_SOUND_MSNDCLAS is not set
+# CONFIG_SOUND_MSNDPIN is not set
+# CONFIG_SOUND_OSS is not set
+# CONFIG_SOUND_AD1980 is not set
+
+#
+# USB support
+#
+# CONFIG_USB_ARCH_HAS_HCD is not set
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# 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 is not set
+# CONFIG_JFFS_FS is not set
+# CONFIG_JFFS2_FS is not set
+# 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 is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC32 is not set
+CONFIG_LIBCRC32C=m
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
diff --git a/arch/mips/configs/ivr_defconfig b/arch/mips/configs/ivr_defconfig
new file mode 100644
index 0000000..c6eef70
--- /dev/null
+++ b/arch/mips/configs/ivr_defconfig
@@ -0,0 +1,686 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-rc2
+# Wed Jan 26 02:49:05 2005
+#
+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_LOCALVERSION=""
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+CONFIG_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM 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_MODULE_SRCVERSION_ALL=y
+CONFIG_KMOD=y
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ 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=y
+# 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_OCELOT_3 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 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_GENERIC_CALIBRATE_DELAY=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_ITE_BOARD_GEN=y
+CONFIG_IT8172_CIR=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+
+#
+# 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 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+CONFIG_CPU_NEVADA=y
+# 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_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
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_HW_HAS_PCI=y
+CONFIG_PCI=y
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+CONFIG_MMU=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# 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_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_RAM is not set
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_ATA_OVER_ETH=m
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+# CONFIG_BLK_DEV_IDEPCI is not set
+# CONFIG_IDE_ARM is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# 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 is not set
+# 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_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+CONFIG_INET_TUNNEL=m
+CONFIG_IP_TCPDIAG=m
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# 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 is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# 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 is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_PCI is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI 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 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_LIBPS2 is not set
+CONFIG_SERIO_RAW=m
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD 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
+CONFIG_QTRONIX_KEYBOARD=y
+# CONFIG_IT8172_SCR0 is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+CONFIG_RTC=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# 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
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# 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 is not set
+# 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 is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC32 is not set
+CONFIG_LIBCRC32C=m
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
diff --git a/arch/mips/configs/jaguar-atx_defconfig b/arch/mips/configs/jaguar-atx_defconfig
new file mode 100644
index 0000000..757c4e8
--- /dev/null
+++ b/arch/mips/configs/jaguar-atx_defconfig
@@ -0,0 +1,620 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-rc2
+# Wed Jan 26 02:49:05 2005
+#
+CONFIG_MIPS=y
+# CONFIG_MIPS64 is not set
+# CONFIG_64BIT is not set
+CONFIG_MIPS32=y
+
+#
+# Code maturity level options
+#
+# CONFIG_EXPERIMENTAL is not set
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# 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_KOBJECT_UEVENT=y
+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_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_OBSOLETE_MODPARM=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_KMOD=y
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_MACH_DECSTATION 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_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_OCELOT_3 is not set
+CONFIG_MOMENCO_JAGUAR_ATX=y
+CONFIG_JAGUAR_DMALOW=y
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_DDB5476 is not set
+# CONFIG_DDB5477 is not set
+# CONFIG_NEC_OSPREY is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SOC_AU1X00 is not set
+# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_RBTX4927 is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_LIMITED_DMA=y
+# CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_IRQ_CPU=y
+CONFIG_IRQ_CPU_RM7K=y
+CONFIG_IRQ_MV64340=y
+CONFIG_PCI_MARVELL=y
+CONFIG_SWAP_IO_SPACE=y
+CONFIG_BOOT_ELF32=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+
+#
+# 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 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+CONFIG_CPU_RM9000=y
+# 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_RM7000_CPU_SCACHE=y
+CONFIG_CPU_HAS_PREFETCH=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_HIGHMEM=y
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_HW_HAS_PCI=y
+CONFIG_PCI=y
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+CONFIG_MMU=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# 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_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_RAM is not set
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_ATA_OVER_ETH=m
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_PACKET is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# 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_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+CONFIG_INET_TUNNEL=m
+CONFIG_IP_TCPDIAG=m
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+# 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
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# 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 is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_DGRS is not set
+CONFIG_EEPRO100=y
+# CONFIG_E100 is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139TOO is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+CONFIG_MV643XX_ETH=y
+CONFIG_MV643XX_ETH_0=y
+CONFIG_MV643XX_ETH_1=y
+CONFIG_MV643XX_ETH_2=y
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+# CONFIG_INPUT is not set
+
+#
+# Userland interfaces
+#
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+# CONFIG_SERIO is not set
+# CONFIG_SERIO_I8042 is not set
+
+#
+# Input Device Drivers
+#
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# 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
+#
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+# CONFIG_DEVPTS_FS_XATTR is not set
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_HFSPLUS_FS is not set
+# 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 is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC32 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
diff --git a/arch/mips/configs/jmr3927_defconfig b/arch/mips/configs/jmr3927_defconfig
new file mode 100644
index 0000000..e5a6139
--- /dev/null
+++ b/arch/mips/configs/jmr3927_defconfig
@@ -0,0 +1,696 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-rc2
+# Wed Jan 26 02:49:06 2005
+#
+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_LOCALVERSION=""
+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_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_MACH_VR41XX is not set
+CONFIG_TOSHIBA_JMR3927=y
+# 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_OCELOT_3 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 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_GENERIC_CALIBRATE_DELAY=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_DMA_NONCOHERENT=y
+# CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_MIPS_TX3927=y
+CONFIG_SWAP_IO_SPACE=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+CONFIG_TOSHIBA_BOARDS=y
+
+#
+# CPU selection
+#
+# CONFIG_CPU_MIPS32 is not set
+# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_R3000 is not set
+CONFIG_CPU_TX39XX=y
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_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_CPU_ADVANCED is not set
+CONFIG_CPU_HAS_SYNC=y
+# CONFIG_PREEMPT is not set
+CONFIG_RTC_DS1742=y
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_HW_HAS_PCI=y
+CONFIG_PCI=y
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+CONFIG_MMU=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# 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_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_RAM is not set
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
+CONFIG_CDROM_PKTCDVD=y
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_ATA_OVER_ETH=y
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_NETLINK_DEV=y
+CONFIG_UNIX=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# 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_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+CONFIG_INET_TUNNEL=y
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=y
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# 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 is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# 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 is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_PCI is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI 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 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_LIBPS2 is not set
+CONFIG_SERIO_RAW=y
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD 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=y
+# CONFIG_COMPUTONE is not set
+# CONFIG_ROCKETPORT is not set
+# CONFIG_CYCLADES is not set
+# CONFIG_DIGIEPCA is not set
+# CONFIG_DIGI is not set
+# CONFIG_MOXA_INTELLIO is not set
+# CONFIG_MOXA_SMARTIO is not set
+# CONFIG_ISI is not set
+# CONFIG_SYNCLINK is not set
+# CONFIG_SYNCLINKMP is not set
+# CONFIG_N_HDLC is not set
+# CONFIG_RISCOM8 is not set
+# CONFIG_SPECIALIX is not set
+# CONFIG_SX is not set
+# CONFIG_RIO is not set
+# CONFIG_STALDRV is not set
+# CONFIG_SERIAL_TX3912 is not set
+CONFIG_TXX927_SERIAL=y
+CONFIG_TXX927_SERIAL_CONSOLE=y
+# CONFIG_SERIAL_TXX9 is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_UNIX98_PTYS is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# 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
+#
+CONFIG_FB=y
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_CIRRUS is not set
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT is not set
+# CONFIG_FB_RIVA is not set
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_RADEON_OLD is not set
+# CONFIG_FB_RADEON is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_SAVAGE is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_KYRO is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_E1356 is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE is not set
+
+#
+# Logo configuration
+#
+# CONFIG_LOGO is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# 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_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 is not set
+# 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 is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC32 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
diff --git a/arch/mips/configs/lasat200_defconfig b/arch/mips/configs/lasat200_defconfig
new file mode 100644
index 0000000..1e76978
--- /dev/null
+++ b/arch/mips/configs/lasat200_defconfig
@@ -0,0 +1,791 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-rc2
+# Wed Jan 26 02:49:06 2005
+#
+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_LOCALVERSION=""
+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_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM 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_MODULE_SRCVERSION_ALL=y
+CONFIG_KMOD=y
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ 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=y
+CONFIG_PICVUE=y
+CONFIG_PICVUE_PROC=y
+CONFIG_DS1603=y
+CONFIG_LASAT_SYSCTL=y
+# 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_OCELOT_3 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 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_GENERIC_CALIBRATE_DELAY=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_MIPS_NILE4=y
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_MIPS_GT64120=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+
+#
+# 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_R5000_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
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_HW_HAS_PCI=y
+CONFIG_PCI=y
+CONFIG_PCI_LEGACY_PROC=y
+# CONFIG_PCI_NAMES is not set
+CONFIG_MMU=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_CONCAT is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_CFI_AMDSTD_RETRY=0
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+CONFIG_MTD_LASAT=y
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLKMTD is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND 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_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_RAM is not set
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_ATA_OVER_ETH=m
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+CONFIG_IDEDISK_MULTI_MODE=y
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_IDEPCI=y
+# CONFIG_IDEPCI_SHARE_IRQ is not set
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+CONFIG_IDEDMA_PCI_AUTO=y
+# CONFIG_IDEDMA_ONLYDISK is not set
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD74XX is not set
+CONFIG_BLK_DEV_CMD64X=y
+# CONFIG_BLK_DEV_TRIFLEX is not set
+# CONFIG_BLK_DEV_CY82C693 is not set
+# CONFIG_BLK_DEV_CS5520 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT34X is not set
+# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_SC1200 is not set
+# CONFIG_BLK_DEV_PIIX is not set
+# CONFIG_BLK_DEV_NS87415 is not set
+# CONFIG_BLK_DEV_PDC202XX_OLD is not set
+# CONFIG_BLK_DEV_PDC202XX_NEW is not set
+# CONFIG_BLK_DEV_SVWKS is not set
+# CONFIG_BLK_DEV_SIIMAGE is not set
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+# CONFIG_BLK_DEV_VIA82CXXX is not set
+# CONFIG_IDE_ARM is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+CONFIG_IDEDMA_AUTO=y
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_PACKET is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+CONFIG_INET_TUNNEL=m
+CONFIG_IP_TCPDIAG=m
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# 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 is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# 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 is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_PCI is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI 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
+# CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_LIBPS2 is not set
+CONFIG_SERIO_RAW=m
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD 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=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# 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
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+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_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# 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 is not set
+# CONFIG_JFFS_FS is not set
+# CONFIG_JFFS2_FS is not set
+# 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 is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=m
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
diff --git a/arch/mips/configs/malta_defconfig b/arch/mips/configs/malta_defconfig
new file mode 100644
index 0000000..61fb9fb
--- /dev/null
+++ b/arch/mips/configs/malta_defconfig
@@ -0,0 +1,1132 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-rc2
+# Wed Jan 26 02:53:14 2005
+#
+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_LOCALVERSION=""
+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=y
+CONFIG_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM 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_MODULE_SRCVERSION_ALL=y
+CONFIG_KMOD=y
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ 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=y
+# 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_OCELOT_3 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 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_GENERIC_CALIBRATE_DELAY=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_I8259=y
+CONFIG_MIPS_BONITO64=y
+CONFIG_MIPS_MSC=y
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_MIPS_BOARDS_GEN=y
+CONFIG_MIPS_GT64120=y
+CONFIG_SWAP_IO_SPACE=y
+CONFIG_BOOT_ELF32=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+CONFIG_HAVE_STD_PC_SERIAL_PORT=y
+
+#
+# CPU selection
+#
+CONFIG_CPU_MIPS32=y
+# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_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_64BIT_PHYS_ADDR is not set
+# CONFIG_CPU_ADVANCED is not set
+CONFIG_CPU_HAS_LLSC=y
+CONFIG_CPU_HAS_SYNC=y
+# CONFIG_PREEMPT is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_HW_HAS_PCI=y
+CONFIG_PCI=y
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+CONFIG_MMU=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=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=m
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+CONFIG_BLK_DEV_UMEM=m
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=m
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+CONFIG_BLK_DEV_NBD=m
+# CONFIG_BLK_DEV_SX8 is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_INITRD is not set
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_ATA_OVER_ETH=m
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+CONFIG_BLK_DEV_IDECD=y
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_BLK_DEV_IDESCSI is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_IDEPCI=y
+# CONFIG_IDEPCI_SHARE_IRQ is not set
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+CONFIG_IDEDMA_PCI_AUTO=y
+# CONFIG_IDEDMA_ONLYDISK is not set
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD74XX is not set
+# CONFIG_BLK_DEV_CMD64X is not set
+# CONFIG_BLK_DEV_TRIFLEX is not set
+# CONFIG_BLK_DEV_CY82C693 is not set
+# CONFIG_BLK_DEV_CS5520 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT34X is not set
+# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_SC1200 is not set
+CONFIG_BLK_DEV_PIIX=y
+# CONFIG_BLK_DEV_NS87415 is not set
+# CONFIG_BLK_DEV_PDC202XX_OLD is not set
+# CONFIG_BLK_DEV_PDC202XX_NEW is not set
+# CONFIG_BLK_DEV_SVWKS is not set
+# CONFIG_BLK_DEV_SIIMAGE is not set
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+# CONFIG_BLK_DEV_VIA82CXXX is not set
+# CONFIG_IDE_ARM is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+CONFIG_IDEDMA_AUTO=y
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI=m
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+CONFIG_CHR_DEV_ST=m
+CONFIG_CHR_DEV_OSST=m
+CONFIG_BLK_DEV_SR=m
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=m
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+
+#
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=m
+CONFIG_SCSI_FC_ATTRS=m
+CONFIG_SCSI_ISCSI_ATTRS=m
+
+#
+# SCSI low-level drivers
+#
+CONFIG_BLK_DEV_3W_XXXX_RAID=m
+CONFIG_SCSI_3W_9XXX=m
+CONFIG_SCSI_ACARD=m
+CONFIG_SCSI_AACRAID=m
+CONFIG_SCSI_AIC7XXX=m
+CONFIG_AIC7XXX_CMDS_PER_DEVICE=32
+CONFIG_AIC7XXX_RESET_DELAY_MS=15000
+# CONFIG_AIC7XXX_DEBUG_ENABLE is not set
+CONFIG_AIC7XXX_DEBUG_MASK=0
+CONFIG_AIC7XXX_REG_PRETTY_PRINT=y
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_EATA_PIO is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_ISP is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+CONFIG_SCSI_QLA2XXX=m
+# CONFIG_SCSI_QLA21XX is not set
+# CONFIG_SCSI_QLA22XX is not set
+# CONFIG_SCSI_QLA2300 is not set
+# CONFIG_SCSI_QLA2322 is not set
+# CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=m
+CONFIG_MD_LINEAR=m
+CONFIG_MD_RAID0=m
+CONFIG_MD_RAID1=m
+CONFIG_MD_RAID10=m
+CONFIG_MD_RAID5=m
+CONFIG_MD_RAID6=m
+CONFIG_MD_MULTIPATH=m
+CONFIG_MD_FAULTY=m
+CONFIG_BLK_DEV_DM=m
+CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# 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=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_FWMARK=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE=m
+CONFIG_NET_IPGRE_BROADCAST=y
+CONFIG_IP_MROUTE=y
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
+CONFIG_INET_IPCOMP=m
+CONFIG_INET_TUNNEL=m
+CONFIG_IP_TCPDIAG=m
+CONFIG_IP_TCPDIAG_IPV6=y
+
+#
+# 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_INET6_TUNNEL=m
+CONFIG_IPV6_TUNNEL=m
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_BRIDGE_NETFILTER=y
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+CONFIG_IP_NF_CT_ACCT=y
+CONFIG_IP_NF_CONNTRACK_MARK=y
+CONFIG_IP_NF_CT_PROTO_SCTP=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_MATCH_PHYSDEV=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_REALM=m
+CONFIG_IP_NF_MATCH_SCTP=m
+CONFIG_IP_NF_MATCH_COMMENT=m
+CONFIG_IP_NF_MATCH_CONNMARK=m
+CONFIG_IP_NF_MATCH_HASHLIMIT=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_TARGET_TCPMSS=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_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_CONNMARK=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_TARGET_NOTRACK=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=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_MATCH_PHYSDEV=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
+
+#
+# Bridge: Netfilter Configuration
+#
+CONFIG_BRIDGE_NF_EBTABLES=m
+CONFIG_BRIDGE_EBT_BROUTE=m
+CONFIG_BRIDGE_EBT_T_FILTER=m
+CONFIG_BRIDGE_EBT_T_NAT=m
+CONFIG_BRIDGE_EBT_802_3=m
+CONFIG_BRIDGE_EBT_AMONG=m
+CONFIG_BRIDGE_EBT_ARP=m
+CONFIG_BRIDGE_EBT_IP=m
+CONFIG_BRIDGE_EBT_LIMIT=m
+CONFIG_BRIDGE_EBT_MARK=m
+CONFIG_BRIDGE_EBT_PKTTYPE=m
+CONFIG_BRIDGE_EBT_STP=m
+CONFIG_BRIDGE_EBT_VLAN=m
+CONFIG_BRIDGE_EBT_ARPREPLY=m
+CONFIG_BRIDGE_EBT_DNAT=m
+CONFIG_BRIDGE_EBT_MARK_T=m
+CONFIG_BRIDGE_EBT_REDIRECT=m
+CONFIG_BRIDGE_EBT_SNAT=m
+CONFIG_BRIDGE_EBT_LOG=m
+CONFIG_BRIDGE_EBT_ULOG=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=m
+CONFIG_VLAN_8021Q=m
+# CONFIG_DECNET is not set
+CONFIG_LLC=m
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+CONFIG_ATALK=m
+CONFIG_DEV_APPLETALK=y
+CONFIG_IPDDP=m
+CONFIG_IPDDP_ENCAP=y
+CONFIG_IPDDP_DECAP=y
+# 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
+
+#
+# QoS and/or fair queueing
+#
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_CLK_JIFFIES=y
+# CONFIG_NET_SCH_CLK_GETTIMEOFDAY is not set
+# 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=y
+# CONFIG_CLS_U32_MARK 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 is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=y
+CONFIG_PCNET32=y
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+# CONFIG_E100 is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+# CONFIG_LAN_SAA9730 is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC 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 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_LIBPS2 is not set
+# CONFIG_SERIO_RAW is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD 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=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+CONFIG_RTC=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# 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
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+CONFIG_REISERFS_PROC_INFO=y
+CONFIG_REISERFS_FS_XATTR=y
+CONFIG_REISERFS_FS_POSIX_ACL=y
+CONFIG_REISERFS_FS_SECURITY=y
+CONFIG_JFS_FS=m
+CONFIG_JFS_POSIX_ACL=y
+CONFIG_JFS_SECURITY=y
+# CONFIG_JFS_DEBUG is not set
+# CONFIG_JFS_STATISTICS 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=y
+CONFIG_MINIX_FS=m
+CONFIG_ROMFS_FS=m
+CONFIG_QUOTA=y
+# CONFIG_QFMT_V1 is not set
+CONFIG_QFMT_V2=y
+CONFIG_QUOTACTL=y
+CONFIG_DNOTIFY=y
+CONFIG_AUTOFS_FS=y
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# 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=m
+CONFIG_HFS_FS=m
+CONFIG_HFSPLUS_FS=m
+CONFIG_BEFS_FS=m
+# CONFIG_BEFS_DEBUG is not set
+CONFIG_BFS_FS=m
+CONFIG_EFS_FS=m
+CONFIG_CRAMFS=m
+CONFIG_VXFS_FS=m
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+CONFIG_SYSV_FS=m
+CONFIG_UFS_FS=m
+# CONFIG_UFS_FS_WRITE is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=y
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V4 is not set
+# CONFIG_NFSD_TCP is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# 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
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
+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_ANUBIS=m
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=m
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
diff --git a/arch/mips/configs/mpc30x_defconfig b/arch/mips/configs/mpc30x_defconfig
new file mode 100644
index 0000000..31b8f2a
--- /dev/null
+++ b/arch/mips/configs/mpc30x_defconfig
@@ -0,0 +1,694 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-rc2
+# Wed Jan 26 02:49:07 2005
+#
+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_LOCALVERSION=""
+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_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM 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_MODULE_SRCVERSION_ALL=y
+CONFIG_KMOD=y
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ is not set
+CONFIG_MACH_VR41XX=y
+# CONFIG_NEC_CMBVR4133 is not set
+# CONFIG_CASIO_E55 is not set
+# CONFIG_IBM_WORKPAD is not set
+# CONFIG_TANBAC_TB0226 is not set
+# CONFIG_TANBAC_TB0229 is not set
+CONFIG_VICTOR_MPC30X=y
+# CONFIG_ZAO_CAPCELLA is not set
+CONFIG_PCI_VR41XX=y
+CONFIG_VRC4173=y
+# 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_OCELOT_3 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 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_GENERIC_CALIBRATE_DELAY=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_IRQ_CPU=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+
+#
+# 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=y
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_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_CPU_ADVANCED is not set
+CONFIG_CPU_HAS_SYNC=y
+# CONFIG_PREEMPT is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_HW_HAS_PCI=y
+CONFIG_PCI=y
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+CONFIG_MMU=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# 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_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_RAM is not set
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_ATA_OVER_ETH=m
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# 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 is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+CONFIG_INET_TUNNEL=m
+CONFIG_IP_TCPDIAG=m
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# 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 is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# 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 is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_PCI is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI 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
+# CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_LIBPS2 is not set
+CONFIG_SERIO_RAW=m
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD 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=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# 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
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+CONFIG_AUTOFS_FS=y
+CONFIG_AUTOFS4_FS=y
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# 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 is not set
+# 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 is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=y
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+CONFIG_CRYPTO_SHA512=y
+CONFIG_CRYPTO_WP512=m
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+CONFIG_CRYPTO_TWOFISH=y
+# CONFIG_CRYPTO_SERPENT is not set
+CONFIG_CRYPTO_AES=m
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_TEA=m
+# CONFIG_CRYPTO_ARC4 is not set
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_DEFLATE=y
+CONFIG_CRYPTO_MICHAEL_MIC=y
+CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC32 is not set
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
diff --git a/arch/mips/configs/ocelot_3_defconfig b/arch/mips/configs/ocelot_3_defconfig
new file mode 100644
index 0000000..2cce682
--- /dev/null
+++ b/arch/mips/configs/ocelot_3_defconfig
@@ -0,0 +1,886 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-rc2
+# Wed Jan 26 02:49:07 2005
+#
+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_LOCALVERSION=""
+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_KOBJECT_UEVENT=y
+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_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM 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_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ 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_OCELOT_3=y
+# 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 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_GENERIC_CALIBRATE_DELAY=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_DMA_NONCOHERENT=y
+# CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_IRQ_CPU=y
+CONFIG_IRQ_CPU_RM7K=y
+CONFIG_IRQ_MV64340=y
+CONFIG_PCI_MARVELL=y
+CONFIG_SWAP_IO_SPACE=y
+CONFIG_BOOT_ELF32=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+
+#
+# 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 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+CONFIG_CPU_RM9000=y
+# 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_RM7000_CPU_SCACHE=y
+CONFIG_CPU_HAS_PREFETCH=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_HIGHMEM is not set
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_HW_HAS_PCI=y
+CONFIG_PCI=y
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+CONFIG_MMU=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# 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_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_RAM is not set
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_ATA_OVER_ETH=m
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI=m
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+# CONFIG_BLK_DEV_SD is not set
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR 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 is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_EATA_PIO is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_ISP is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+CONFIG_SCSI_QLA2XXX=m
+# CONFIG_SCSI_QLA21XX is not set
+# CONFIG_SCSI_QLA22XX is not set
+# CONFIG_SCSI_QLA2300 is not set
+# CONFIG_SCSI_QLA2322 is not set
+# CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_NETLINK_DEV=y
+CONFIG_UNIX=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+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_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_IP_TCPDIAG=m
+CONFIG_IP_TCPDIAG_IPV6=y
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+CONFIG_IPV6=m
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_IPV6_TUNNEL is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+
+#
+# IP: Netfilter Configuration
+#
+# CONFIG_IP_NF_CONNTRACK is not set
+# CONFIG_IP_NF_CONNTRACK_MARK is not set
+# CONFIG_IP_NF_QUEUE is not set
+# CONFIG_IP_NF_IPTABLES is not set
+# CONFIG_IP_NF_ARPTABLES is not set
+
+#
+# IPv6: Netfilter Configuration
+#
+# CONFIG_IP6_NF_QUEUE is not set
+# CONFIG_IP6_NF_IPTABLES is not set
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# 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 is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# 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 is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_TUN=m
+# CONFIG_ETHERTAP is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+CONFIG_E100=y
+# CONFIG_E100_NAPI is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+# CONFIG_LAN_SAA9730 is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+CONFIG_MV643XX_ETH=y
+CONFIG_MV643XX_ETH_0=y
+CONFIG_MV643XX_ETH_1=y
+CONFIG_MV643XX_ETH_2=y
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+CONFIG_PPP=m
+# CONFIG_PPP_MULTILINK is not set
+# CONFIG_PPP_FILTER is not set
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+# CONFIG_PPP_BSDCOMP is not set
+CONFIG_PPPOE=m
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC 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 is not set
+# 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 is not set
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_LIBPS2 is not set
+# CONFIG_SERIO_RAW is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD 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=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+CONFIG_RTC=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# 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
+#
+CONFIG_FB=y
+CONFIG_FB_MODE_HELPERS=y
+# CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_CIRRUS is not set
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT is not set
+# CONFIG_FB_RIVA is not set
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_RADEON_OLD is not set
+# CONFIG_FB_RADEON is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_SAVAGE is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_KYRO is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_E1356 is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+CONFIG_LOGO_LINUX_MONO=y
+CONFIG_LOGO_LINUX_VGA16=y
+CONFIG_LOGO_LINUX_CLUT224=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT3_FS=m
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=m
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+# CONFIG_REISERFS_FS_XATTR is not set
+# CONFIG_JFS_FS is not set
+CONFIG_XFS_FS=m
+# CONFIG_XFS_RT is not set
+# CONFIG_XFS_QUOTA is not set
+# CONFIG_XFS_SECURITY is not set
+# CONFIG_XFS_POSIX_ACL is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+CONFIG_AUTOFS_FS=y
+CONFIG_AUTOFS4_FS=m
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+CONFIG_DEVFS_FS=y
+CONFIG_DEVFS_MOUNT=y
+# CONFIG_DEVFS_DEBUG is not set
+CONFIG_DEVPTS_FS_XATTR=y
+CONFIG_DEVPTS_FS_SECURITY=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_XATTR 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=y
+CONFIG_CRAMFS=y
+# 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 is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=y
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V4 is not set
+# CONFIG_NFSD_TCP is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=m
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE="ip=any root=nfs"
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=m
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
diff --git a/arch/mips/configs/ocelot_c_defconfig b/arch/mips/configs/ocelot_c_defconfig
new file mode 100644
index 0000000..0cbf48a
--- /dev/null
+++ b/arch/mips/configs/ocelot_c_defconfig
@@ -0,0 +1,664 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-rc2
+# Wed Jan 26 02:49:07 2005
+#
+CONFIG_MIPS=y
+CONFIG_MIPS64=y
+CONFIG_64BIT=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+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_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_MACH_VR41XX 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=y
+# CONFIG_MOMENCO_OCELOT_3 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 is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_SB1xxx_SOC is not set
+# CONFIG_SNI_RM200_PCI is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_DMA_NONCOHERENT=y
+# CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_IRQ_CPU=y
+CONFIG_IRQ_MV64340=y
+CONFIG_PCI_MARVELL=y
+CONFIG_SWAP_IO_SPACE=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+
+#
+# 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 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+CONFIG_CPU_RM7000=y
+# 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_RM7000_CPU_SCACHE=y
+CONFIG_CPU_HAS_PREFETCH=y
+CONFIG_CPU_HAS_LLSC=y
+CONFIG_CPU_HAS_LLDSCD=y
+CONFIG_CPU_HAS_SYNC=y
+# CONFIG_PREEMPT is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_HW_HAS_PCI=y
+CONFIG_PCI=y
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+CONFIG_MMU=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_BUILD_ELF64 is not set
+CONFIG_MIPS32_COMPAT=y
+CONFIG_COMPAT=y
+CONFIG_MIPS32_O32=y
+CONFIG_MIPS32_N32=y
+CONFIG_BINFMT_ELF32=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# 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_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_RAM is not set
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CDROM_PKTCDVD=y
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_ATA_OVER_ETH=y
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_PACKET is not set
+CONFIG_NETLINK_DEV=y
+CONFIG_UNIX=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+CONFIG_INET_TUNNEL=y
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=y
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# 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 is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# 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 is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_PCI is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_MV643XX_ETH is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI 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 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_LIBPS2 is not set
+CONFIG_SERIO_RAW=y
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD 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=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# 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
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# 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 is not set
+# 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 is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=y
+# CONFIG_NFSD_V3 is not set
+# CONFIG_NFSD_TCP is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_EXPORTFS=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC32 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
diff --git a/arch/mips/configs/ocelot_defconfig b/arch/mips/configs/ocelot_defconfig
new file mode 100644
index 0000000..4043950
--- /dev/null
+++ b/arch/mips/configs/ocelot_defconfig
@@ -0,0 +1,624 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-rc2
+# Wed Jan 26 02:49:08 2005
+#
+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_LOCALVERSION=""
+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_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ 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=y
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_OCELOT_3 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 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_GENERIC_CALIBRATE_DELAY=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_DMA_NONCOHERENT=y
+# CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_IRQ_CPU=y
+CONFIG_IRQ_CPU_RM7K=y
+CONFIG_MIPS_GT64120=y
+CONFIG_SWAP_IO_SPACE=y
+# CONFIG_SYSCLK_75 is not set
+# CONFIG_SYSCLK_83 is not set
+CONFIG_SYSCLK_100=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+
+#
+# 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 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+CONFIG_CPU_RM7000=y
+# 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_RM7000_CPU_SCACHE=y
+CONFIG_CPU_HAS_PREFETCH=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
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_HW_HAS_PCI=y
+# CONFIG_PCI is not set
+CONFIG_MMU=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# 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_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
+CONFIG_CDROM_PKTCDVD=y
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_ATA_OVER_ETH=y
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI 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 is not set
+CONFIG_NETLINK_DEV=y
+CONFIG_UNIX=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# 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_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+CONFIG_INET_TUNNEL=y
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=y
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# 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 is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# 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 is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+
+#
+# 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 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_LIBPS2 is not set
+CONFIG_SERIO_RAW=y
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD 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=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# 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
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB_ARCH_HAS_HCD is not set
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# 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 is not set
+# 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 is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=y
+# CONFIG_NFSD_V3 is not set
+# CONFIG_NFSD_TCP is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_EXPORTFS=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC32 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
diff --git a/arch/mips/configs/ocelot_g_defconfig b/arch/mips/configs/ocelot_g_defconfig
new file mode 100644
index 0000000..3870af4
--- /dev/null
+++ b/arch/mips/configs/ocelot_g_defconfig
@@ -0,0 +1,667 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-rc2
+# Wed Jan 26 02:49:08 2005
+#
+CONFIG_MIPS=y
+CONFIG_MIPS64=y
+CONFIG_64BIT=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+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_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_MACH_VR41XX 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=y
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_OCELOT_3 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 is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_SB1xxx_SOC is not set
+# CONFIG_SNI_RM200_PCI is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_DMA_NONCOHERENT=y
+# CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_IRQ_CPU=y
+CONFIG_IRQ_CPU_RM7K=y
+CONFIG_PCI_MARVELL=y
+CONFIG_SWAP_IO_SPACE=y
+# CONFIG_SYSCLK_75 is not set
+# CONFIG_SYSCLK_83 is not set
+CONFIG_SYSCLK_100=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+
+#
+# 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 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+CONFIG_CPU_RM7000=y
+# 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_RM7000_CPU_SCACHE=y
+CONFIG_CPU_HAS_PREFETCH=y
+CONFIG_CPU_HAS_LLSC=y
+CONFIG_CPU_HAS_LLDSCD=y
+CONFIG_CPU_HAS_SYNC=y
+# CONFIG_PREEMPT is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_HW_HAS_PCI=y
+CONFIG_PCI=y
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+CONFIG_MMU=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_BUILD_ELF64 is not set
+CONFIG_MIPS32_COMPAT=y
+CONFIG_COMPAT=y
+CONFIG_MIPS32_O32=y
+CONFIG_MIPS32_N32=y
+CONFIG_BINFMT_ELF32=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# 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_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_RAM is not set
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CDROM_PKTCDVD=y
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_ATA_OVER_ETH=y
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_PACKET is not set
+CONFIG_NETLINK_DEV=y
+CONFIG_UNIX=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+CONFIG_INET_TUNNEL=y
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=y
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# 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 is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# 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 is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_GALILEO_64240_ETH=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_PCI is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI 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 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_LIBPS2 is not set
+CONFIG_SERIO_RAW=y
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD 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=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# 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
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# 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 is not set
+# 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 is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=y
+# CONFIG_NFSD_V3 is not set
+# CONFIG_NFSD_TCP is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_EXPORTFS=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC32 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
diff --git a/arch/mips/configs/osprey_defconfig b/arch/mips/configs/osprey_defconfig
new file mode 100644
index 0000000..989cb9e
--- /dev/null
+++ b/arch/mips/configs/osprey_defconfig
@@ -0,0 +1,618 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-rc2
+# Wed Jan 26 02:49:08 2005
+#
+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_LOCALVERSION=""
+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_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM 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_MODULE_SRCVERSION_ALL=y
+CONFIG_KMOD=y
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ 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_OCELOT_3 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=y
+# CONFIG_SGI_IP22 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_GENERIC_CALIBRATE_DELAY=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_IRQ_CPU=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+CONFIG_VR4181=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=y
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_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_CPU_ADVANCED is not set
+CONFIG_CPU_HAS_SYNC=y
+# CONFIG_PREEMPT is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_MMU=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# 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_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_ATA_OVER_ETH=m
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI 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 is not set
+CONFIG_NETLINK_DEV=y
+CONFIG_UNIX=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# 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_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+CONFIG_INET_TUNNEL=m
+CONFIG_IP_TCPDIAG=m
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# 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 is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# 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 is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+
+#
+# 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 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_LIBPS2 is not set
+CONFIG_SERIO_RAW=m
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD 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=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# 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
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB_ARCH_HAS_HCD is not set
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# 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 is not set
+# 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 is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=y
+# CONFIG_NFSD_V3 is not set
+# CONFIG_NFSD_TCP is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_EXPORTFS=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE="ip=bootp ether=46,0x03fe0300,eth0"
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC32 is not set
+CONFIG_LIBCRC32C=m
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
diff --git a/arch/mips/configs/pb1100_defconfig b/arch/mips/configs/pb1100_defconfig
new file mode 100644
index 0000000..6cdabd5
--- /dev/null
+++ b/arch/mips/configs/pb1100_defconfig
@@ -0,0 +1,826 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-rc2
+# Wed Jan 26 02:49:08 2005
+#
+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_LOCALVERSION=""
+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=y
+CONFIG_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM 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_MODULE_SRCVERSION_ALL=y
+CONFIG_KMOD=y
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ 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_OCELOT_3 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 is not set
+CONFIG_SOC_AU1X00=y
+# CONFIG_SOC_AU1000 is not set
+CONFIG_SOC_AU1100=y
+# CONFIG_SOC_AU1500 is not set
+# CONFIG_SOC_AU1550 is not set
+# CONFIG_MIPS_PB1000 is not set
+CONFIG_MIPS_PB1100=y
+# CONFIG_MIPS_PB1500 is not set
+# CONFIG_MIPS_PB1550 is not set
+# CONFIG_MIPS_DB1000 is not set
+# CONFIG_MIPS_DB1100 is not set
+# CONFIG_MIPS_DB1500 is not set
+# CONFIG_MIPS_DB1550 is not set
+# CONFIG_MIPS_BOSPORUS is not set
+# CONFIG_MIPS_MIRAGE is not set
+# CONFIG_MIPS_XXS1500 is not set
+# CONFIG_MIPS_MTX1 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_GENERIC_CALIBRATE_DELAY=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_SWAP_IO_SPACE=y
+# CONFIG_AU1X00_USB_DEVICE is not set
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+
+#
+# CPU selection
+#
+CONFIG_CPU_MIPS32=y
+# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_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_CPU_HAS_PREFETCH=y
+# CONFIG_64BIT_PHYS_ADDR is not set
+# CONFIG_CPU_ADVANCED is not set
+CONFIG_CPU_HAS_LLSC=y
+CONFIG_CPU_HAS_SYNC=y
+# CONFIG_PREEMPT is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_HW_HAS_PCI=y
+# CONFIG_PCI is not set
+CONFIG_MMU=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+CONFIG_PCCARD=m
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=m
+
+#
+# PC-card bridges
+#
+# CONFIG_TCIC is not set
+# CONFIG_PCMCIA_AU1X00 is not set
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_CONCAT is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_CFI_AMDSTD_RETRY=0
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+CONFIG_MTD_PB1100=y
+CONFIG_MTD_PB1500_BOOT=y
+CONFIG_MTD_PB1500_USER=y
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLKMTD is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND 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_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_ATA_OVER_ETH=m
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI 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 is not set
+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 is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+CONFIG_INET_TUNNEL=m
+CONFIG_IP_TCPDIAG=m
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+# CONFIG_IPV6 is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+
+#
+# IP: Netfilter Configuration
+#
+# CONFIG_IP_NF_CONNTRACK is not set
+CONFIG_IP_NF_CONNTRACK_MARK=y
+# CONFIG_IP_NF_QUEUE is not set
+# CONFIG_IP_NF_IPTABLES is not set
+# CONFIG_IP_NF_ARPTABLES is not set
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# 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 is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# 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 is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+# CONFIG_MIPS_AU1X00_ENET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# PCMCIA network device support
+#
+# CONFIG_NET_PCMCIA is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+CONFIG_PPP=m
+CONFIG_PPP_MULTILINK=y
+# CONFIG_PPP_FILTER is not set
+CONFIG_PPP_ASYNC=m
+# CONFIG_PPP_SYNC_TTY is not set
+CONFIG_PPP_DEFLATE=m
+# CONFIG_PPP_BSDCOMP is not set
+CONFIG_PPPOE=m
+# 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=y
+# 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 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_LIBPS2 is not set
+CONFIG_SERIO_RAW=m
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD 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
+# CONFIG_AU1X00_GPIO is not set
+# CONFIG_TS_AU1X00_ADS7846 is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_AU1X00 is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+CONFIG_RTC=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+
+#
+# PCMCIA character devices
+#
+CONFIG_SYNCLINK_CS=m
+# CONFIG_RAW_DRIVER is not set
+
+#
+# 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
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB_ARCH_HAS_HCD is not set
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+# CONFIG_EXT2_FS_SECURITY 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=m
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+CONFIG_REISERFS_FS_XATTR=y
+CONFIG_REISERFS_FS_POSIX_ACL=y
+CONFIG_REISERFS_FS_SECURITY=y
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+CONFIG_AUTOFS_FS=m
+CONFIG_AUTOFS4_FS=m
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# 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=y
+# CONFIG_TMPFS_XATTR 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 is not set
+# CONFIG_JFFS_FS is not set
+# CONFIG_JFFS2_FS is not set
+CONFIG_CRAMFS=m
+# 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 is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=m
+# CONFIG_NFSD_V3 is not set
+# CONFIG_NFSD_TCP is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_EXPORTFS=m
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=m
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=y
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+CONFIG_CRYPTO_SHA512=y
+CONFIG_CRYPTO_WP512=m
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+CONFIG_CRYPTO_TWOFISH=y
+# CONFIG_CRYPTO_SERPENT is not set
+CONFIG_CRYPTO_AES=m
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_TEA=m
+# CONFIG_CRYPTO_ARC4 is not set
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_DEFLATE=y
+CONFIG_CRYPTO_MICHAEL_MIC=y
+CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=m
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
diff --git a/arch/mips/configs/pb1500_defconfig b/arch/mips/configs/pb1500_defconfig
new file mode 100644
index 0000000..2aebbd2
--- /dev/null
+++ b/arch/mips/configs/pb1500_defconfig
@@ -0,0 +1,855 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-rc2
+# Wed Jan 26 02:49:09 2005
+#
+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_LOCALVERSION=""
+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=y
+CONFIG_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM 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_MODULE_SRCVERSION_ALL=y
+CONFIG_KMOD=y
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ 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_OCELOT_3 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 is not set
+CONFIG_SOC_AU1X00=y
+# CONFIG_SOC_AU1000 is not set
+# CONFIG_SOC_AU1100 is not set
+CONFIG_SOC_AU1500=y
+# CONFIG_SOC_AU1550 is not set
+# CONFIG_MIPS_PB1000 is not set
+# CONFIG_MIPS_PB1100 is not set
+CONFIG_MIPS_PB1500=y
+# CONFIG_MIPS_PB1550 is not set
+# CONFIG_MIPS_DB1000 is not set
+# CONFIG_MIPS_DB1100 is not set
+# CONFIG_MIPS_DB1500 is not set
+# CONFIG_MIPS_DB1550 is not set
+# CONFIG_MIPS_BOSPORUS is not set
+# CONFIG_MIPS_MIRAGE is not set
+# CONFIG_MIPS_XXS1500 is not set
+# CONFIG_MIPS_MTX1 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_GENERIC_CALIBRATE_DELAY=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_DMA_COHERENT=y
+CONFIG_CPU_LITTLE_ENDIAN=y
+# CONFIG_AU1X00_USB_DEVICE is not set
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+
+#
+# CPU selection
+#
+CONFIG_CPU_MIPS32=y
+# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_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_CPU_HAS_PREFETCH=y
+CONFIG_64BIT_PHYS_ADDR=y
+# CONFIG_CPU_ADVANCED is not set
+CONFIG_CPU_HAS_LLSC=y
+CONFIG_CPU_HAS_SYNC=y
+# CONFIG_PREEMPT is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_HW_HAS_PCI=y
+CONFIG_PCI=y
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+CONFIG_MMU=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+CONFIG_PCCARD=m
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=m
+CONFIG_CARDBUS=y
+
+#
+# PC-card bridges
+#
+# CONFIG_YENTA is not set
+CONFIG_PD6729=m
+# CONFIG_I82092 is not set
+# CONFIG_TCIC is not set
+# CONFIG_PCMCIA_AU1X00 is not set
+CONFIG_PCCARD_NONSTATIC=m
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# 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_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_RAM is not set
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_ATA_OVER_ETH=m
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+CONFIG_BLK_DEV_IDECS=m
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_IDEPCI=y
+# CONFIG_IDEPCI_SHARE_IRQ is not set
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+# CONFIG_IDEDMA_PCI_AUTO is not set
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD74XX is not set
+# CONFIG_BLK_DEV_CMD64X is not set
+# CONFIG_BLK_DEV_TRIFLEX is not set
+# CONFIG_BLK_DEV_CY82C693 is not set
+# CONFIG_BLK_DEV_CS5520 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT34X is not set
+CONFIG_BLK_DEV_HPT366=y
+# CONFIG_BLK_DEV_SC1200 is not set
+# CONFIG_BLK_DEV_PIIX is not set
+# CONFIG_BLK_DEV_NS87415 is not set
+# CONFIG_BLK_DEV_PDC202XX_OLD is not set
+# CONFIG_BLK_DEV_PDC202XX_NEW is not set
+# CONFIG_BLK_DEV_SVWKS is not set
+# CONFIG_BLK_DEV_SIIMAGE is not set
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+# CONFIG_BLK_DEV_VIA82CXXX is not set
+# CONFIG_IDE_ARM is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+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 is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+CONFIG_INET_TUNNEL=m
+CONFIG_IP_TCPDIAG=m
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+# CONFIG_IPV6 is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+
+#
+# IP: Netfilter Configuration
+#
+# CONFIG_IP_NF_CONNTRACK is not set
+CONFIG_IP_NF_CONNTRACK_MARK=y
+# CONFIG_IP_NF_QUEUE is not set
+# CONFIG_IP_NF_IPTABLES is not set
+# CONFIG_IP_NF_ARPTABLES is not set
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# 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 is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# 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 is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=m
+CONFIG_MIPS_AU1X00_ENET=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_PCI is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# PCMCIA network device support
+#
+CONFIG_NET_PCMCIA=y
+CONFIG_PCMCIA_3C589=m
+CONFIG_PCMCIA_3C574=m
+CONFIG_PCMCIA_FMVJ18X=m
+CONFIG_PCMCIA_PCNET=m
+CONFIG_PCMCIA_NMCLAN=m
+CONFIG_PCMCIA_SMC91C92=m
+CONFIG_PCMCIA_XIRC2PS=m
+CONFIG_PCMCIA_AXNET=m
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+CONFIG_PPP=m
+CONFIG_PPP_MULTILINK=y
+# CONFIG_PPP_FILTER is not set
+CONFIG_PPP_ASYNC=m
+# CONFIG_PPP_SYNC_TTY is not set
+CONFIG_PPP_DEFLATE=m
+# CONFIG_PPP_BSDCOMP is not set
+CONFIG_PPPOE=m
+# 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=y
+# 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 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_LIBPS2 is not set
+CONFIG_SERIO_RAW=m
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD 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 is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_AU1X00_GPIO is not set
+# CONFIG_TS_AU1X00_ADS7846 is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_AU1X00=y
+CONFIG_SERIAL_AU1X00_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+
+#
+# PCMCIA character devices
+#
+CONFIG_SYNCLINK_CS=m
+# CONFIG_RAW_DRIVER is not set
+
+#
+# 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
+#
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+# CONFIG_EXT2_FS_SECURITY 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=m
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+CONFIG_REISERFS_FS_XATTR=y
+CONFIG_REISERFS_FS_POSIX_ACL=y
+CONFIG_REISERFS_FS_SECURITY=y
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+CONFIG_AUTOFS_FS=m
+CONFIG_AUTOFS4_FS=m
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# 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=y
+# CONFIG_TMPFS_XATTR 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 is not set
+CONFIG_CRAMFS=m
+# 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 is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=m
+# CONFIG_NFSD_V3 is not set
+# CONFIG_NFSD_TCP is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_EXPORTFS=m
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=m
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=y
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+CONFIG_CRYPTO_SHA512=y
+CONFIG_CRYPTO_WP512=m
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+CONFIG_CRYPTO_TWOFISH=y
+# CONFIG_CRYPTO_SERPENT is not set
+CONFIG_CRYPTO_AES=m
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_TEA=m
+# CONFIG_CRYPTO_ARC4 is not set
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_DEFLATE=y
+CONFIG_CRYPTO_MICHAEL_MIC=y
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=m
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
diff --git a/arch/mips/configs/pb1550_defconfig b/arch/mips/configs/pb1550_defconfig
new file mode 100644
index 0000000..9e21edc
--- /dev/null
+++ b/arch/mips/configs/pb1550_defconfig
@@ -0,0 +1,847 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-rc2
+# Wed Jan 26 02:49:09 2005
+#
+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_LOCALVERSION=""
+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=y
+CONFIG_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM 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_MODULE_SRCVERSION_ALL=y
+CONFIG_KMOD=y
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ 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_OCELOT_3 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 is not set
+CONFIG_SOC_AU1X00=y
+# CONFIG_SOC_AU1000 is not set
+# CONFIG_SOC_AU1100 is not set
+# CONFIG_SOC_AU1500 is not set
+CONFIG_SOC_AU1550=y
+# CONFIG_MIPS_PB1000 is not set
+# CONFIG_MIPS_PB1100 is not set
+# CONFIG_MIPS_PB1500 is not set
+CONFIG_MIPS_PB1550=y
+# CONFIG_MIPS_DB1000 is not set
+# CONFIG_MIPS_DB1100 is not set
+# CONFIG_MIPS_DB1500 is not set
+# CONFIG_MIPS_DB1550 is not set
+# CONFIG_MIPS_BOSPORUS is not set
+# CONFIG_MIPS_MIRAGE is not set
+# CONFIG_MIPS_XXS1500 is not set
+# CONFIG_MIPS_MTX1 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_GENERIC_CALIBRATE_DELAY=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_DMA_COHERENT=y
+CONFIG_MIPS_DISABLE_OBSOLETE_IDE=y
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+
+#
+# CPU selection
+#
+CONFIG_CPU_MIPS32=y
+# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_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_CPU_HAS_PREFETCH=y
+CONFIG_64BIT_PHYS_ADDR=y
+# CONFIG_CPU_ADVANCED is not set
+CONFIG_CPU_HAS_LLSC=y
+CONFIG_CPU_HAS_SYNC=y
+# CONFIG_PREEMPT is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_HW_HAS_PCI=y
+CONFIG_PCI=y
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+CONFIG_MMU=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+CONFIG_PCCARD=m
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=m
+CONFIG_CARDBUS=y
+
+#
+# PC-card bridges
+#
+# CONFIG_YENTA is not set
+CONFIG_PD6729=m
+# CONFIG_I82092 is not set
+# CONFIG_TCIC is not set
+# CONFIG_PCMCIA_AU1X00 is not set
+CONFIG_PCCARD_NONSTATIC=m
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# 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_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_RAM is not set
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_ATA_OVER_ETH=m
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+CONFIG_BLK_DEV_IDECS=m
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_IDEPCI=y
+# CONFIG_IDEPCI_SHARE_IRQ is not set
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+# CONFIG_IDEDMA_PCI_AUTO is not set
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD74XX is not set
+# CONFIG_BLK_DEV_CMD64X is not set
+# CONFIG_BLK_DEV_TRIFLEX is not set
+# CONFIG_BLK_DEV_CY82C693 is not set
+# CONFIG_BLK_DEV_CS5520 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT34X is not set
+CONFIG_BLK_DEV_HPT366=y
+# CONFIG_BLK_DEV_SC1200 is not set
+# CONFIG_BLK_DEV_PIIX is not set
+# CONFIG_BLK_DEV_NS87415 is not set
+# CONFIG_BLK_DEV_PDC202XX_OLD is not set
+# CONFIG_BLK_DEV_PDC202XX_NEW is not set
+# CONFIG_BLK_DEV_SVWKS is not set
+# CONFIG_BLK_DEV_SIIMAGE is not set
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+# CONFIG_BLK_DEV_VIA82CXXX is not set
+# CONFIG_IDE_ARM is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+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 is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+CONFIG_INET_TUNNEL=m
+CONFIG_IP_TCPDIAG=m
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+# CONFIG_IPV6 is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+
+#
+# IP: Netfilter Configuration
+#
+# CONFIG_IP_NF_CONNTRACK is not set
+CONFIG_IP_NF_CONNTRACK_MARK=y
+# CONFIG_IP_NF_QUEUE is not set
+# CONFIG_IP_NF_IPTABLES is not set
+# CONFIG_IP_NF_ARPTABLES is not set
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# 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 is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# 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 is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+CONFIG_MIPS_AU1X00_ENET=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_PCI is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# PCMCIA network device support
+#
+# CONFIG_NET_PCMCIA is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+CONFIG_PPP=m
+CONFIG_PPP_MULTILINK=y
+# CONFIG_PPP_FILTER is not set
+CONFIG_PPP_ASYNC=m
+# CONFIG_PPP_SYNC_TTY is not set
+CONFIG_PPP_DEFLATE=m
+# CONFIG_PPP_BSDCOMP is not set
+CONFIG_PPPOE=m
+# 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=y
+# 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 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_LIBPS2 is not set
+CONFIG_SERIO_RAW=m
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD 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 is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_AU1X00_GPIO is not set
+# CONFIG_TS_AU1X00_ADS7846 is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_AU1X00=y
+CONFIG_SERIAL_AU1X00_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+
+#
+# PCMCIA character devices
+#
+CONFIG_SYNCLINK_CS=m
+# CONFIG_RAW_DRIVER is not set
+
+#
+# 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
+#
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+# CONFIG_EXT2_FS_SECURITY 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=m
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+CONFIG_REISERFS_FS_XATTR=y
+CONFIG_REISERFS_FS_POSIX_ACL=y
+CONFIG_REISERFS_FS_SECURITY=y
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+CONFIG_AUTOFS_FS=m
+CONFIG_AUTOFS4_FS=m
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# 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=y
+# CONFIG_TMPFS_XATTR 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 is not set
+CONFIG_CRAMFS=m
+# 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 is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=m
+# CONFIG_NFSD_V3 is not set
+# CONFIG_NFSD_TCP is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_EXPORTFS=m
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=m
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=y
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+CONFIG_CRYPTO_SHA512=y
+CONFIG_CRYPTO_WP512=m
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+CONFIG_CRYPTO_TWOFISH=y
+# CONFIG_CRYPTO_SERPENT is not set
+CONFIG_CRYPTO_AES=m
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_TEA=m
+# CONFIG_CRYPTO_ARC4 is not set
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_DEFLATE=y
+CONFIG_CRYPTO_MICHAEL_MIC=y
+CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=m
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
diff --git a/arch/mips/configs/rm200_defconfig b/arch/mips/configs/rm200_defconfig
new file mode 100644
index 0000000..d0c85a4
--- /dev/null
+++ b/arch/mips/configs/rm200_defconfig
@@ -0,0 +1,1383 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-rc2
+# Wed Jan 26 02:49:09 2005
+#
+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_LOCALVERSION=""
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+CONFIG_KOBJECT_UEVENT=y
+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_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM 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_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ 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_OCELOT_3 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 is not set
+# CONFIG_SOC_AU1X00 is not set
+# CONFIG_SIBYTE_SB1xxx_SOC is not set
+CONFIG_SNI_RM200_PCI=y
+# CONFIG_TOSHIBA_RBTX4927 is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_ARC=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_I8259=y
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_ARC32=y
+CONFIG_BOOT_ELF32=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+CONFIG_HAVE_STD_PC_SERIAL_PORT=y
+CONFIG_ARC_CONSOLE=y
+CONFIG_ARC_MEMORY=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=y
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_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_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
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_HW_HAS_PCI=y
+CONFIG_PCI=y
+CONFIG_PCI_LEGACY_PROC=y
+# CONFIG_PCI_NAMES is not set
+CONFIG_ISA=y
+# CONFIG_EISA is not set
+CONFIG_MMU=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+CONFIG_PCMCIA_PROBE=y
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=m
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+CONFIG_PARPORT=m
+CONFIG_PARPORT_PC=m
+CONFIG_PARPORT_PC_CML1=m
+CONFIG_PARPORT_SERIAL=m
+# CONFIG_PARPORT_PC_FIFO is not set
+# CONFIG_PARPORT_PC_SUPERIO is not set
+# CONFIG_PARPORT_OTHER is not set
+CONFIG_PARPORT_1284=y
+
+#
+# Plug and Play support
+#
+# CONFIG_PNP is not set
+
+#
+# Block devices
+#
+CONFIG_BLK_DEV_FD=m
+# CONFIG_BLK_DEV_XD is not set
+CONFIG_PARIDE=m
+CONFIG_PARIDE_PARPORT=m
+
+#
+# Parallel IDE high-level drivers
+#
+CONFIG_PARIDE_PD=m
+CONFIG_PARIDE_PCD=m
+CONFIG_PARIDE_PF=m
+CONFIG_PARIDE_PT=m
+CONFIG_PARIDE_PG=m
+
+#
+# Parallel IDE protocol modules
+#
+CONFIG_PARIDE_ATEN=m
+CONFIG_PARIDE_BPCK=m
+CONFIG_PARIDE_BPCK6=m
+CONFIG_PARIDE_COMM=m
+CONFIG_PARIDE_DSTR=m
+CONFIG_PARIDE_FIT2=m
+CONFIG_PARIDE_FIT3=m
+CONFIG_PARIDE_EPAT=m
+# CONFIG_PARIDE_EPATC8 is not set
+CONFIG_PARIDE_EPIA=m
+CONFIG_PARIDE_FRIQ=m
+CONFIG_PARIDE_FRPW=m
+CONFIG_PARIDE_KBIC=m
+CONFIG_PARIDE_KTTI=m
+CONFIG_PARIDE_ON20=m
+CONFIG_PARIDE_ON26=m
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=m
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+CONFIG_BLK_DEV_NBD=m
+CONFIG_BLK_DEV_SX8=m
+CONFIG_BLK_DEV_UB=m
+CONFIG_BLK_DEV_RAM=m
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_ATA_OVER_ETH=m
+
+#
+# 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=m
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=m
+CONFIG_BLK_DEV_SR_VENDOR=y
+# 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=y
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_7000FASST is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AHA152X is not set
+# CONFIG_SCSI_AHA1542 is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_IN2000 is not set
+CONFIG_MEGARAID_NEWGEN=y
+CONFIG_MEGARAID_MM=m
+CONFIG_MEGARAID_MAILBOX=m
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_DTC3280 is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_EATA_PIO is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_GENERIC_NCR5380 is not set
+# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+CONFIG_SCSI_PPA=m
+CONFIG_SCSI_IMM=m
+# CONFIG_SCSI_IZIP_EPP16 is not set
+# CONFIG_SCSI_IZIP_SLOW_CTR is not set
+# CONFIG_SCSI_NCR53C406A is not set
+CONFIG_SCSI_SYM53C8XX_2=y
+CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
+CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
+CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
+# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_PAS16 is not set
+# CONFIG_SCSI_PSI240I is not set
+# CONFIG_SCSI_QLOGIC_FAS is not set
+# CONFIG_SCSI_QLOGIC_ISP is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+CONFIG_SCSI_QLA2XXX=y
+# CONFIG_SCSI_QLA21XX is not set
+# CONFIG_SCSI_QLA22XX is not set
+# CONFIG_SCSI_QLA2300 is not set
+# CONFIG_SCSI_QLA2322 is not set
+# CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_SYM53C416 is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_T128 is not set
+# CONFIG_SCSI_U14_34F is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Old CD-ROM drivers (not SCSI, not IDE)
+#
+# CONFIG_CD_NO_IDESCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=m
+CONFIG_MD_LINEAR=m
+CONFIG_MD_RAID0=m
+CONFIG_MD_RAID1=m
+CONFIG_MD_RAID10=m
+CONFIG_MD_RAID5=m
+# CONFIG_MD_RAID6 is not set
+CONFIG_MD_MULTIPATH=m
+CONFIG_MD_FAULTY=m
+CONFIG_BLK_DEV_DM=m
+# CONFIG_DM_CRYPT is not set
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=m
+CONFIG_PACKET_MMAP=y
+CONFIG_NETLINK_DEV=m
+CONFIG_UNIX=y
+CONFIG_NET_KEY=m
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+# CONFIG_IP_PNP is not set
+CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE=m
+CONFIG_NET_IPGRE_BROADCAST=y
+CONFIG_IP_MROUTE=y
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+CONFIG_INET_TUNNEL=m
+CONFIG_IP_TCPDIAG=m
+CONFIG_IP_TCPDIAG_IPV6=y
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+CONFIG_IPV6=m
+CONFIG_IPV6_PRIVACY=y
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_IPV6_TUNNEL=m
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_BRIDGE_NETFILTER=y
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+# CONFIG_IP_NF_CT_ACCT is not set
+CONFIG_IP_NF_CONNTRACK_MARK=y
+CONFIG_IP_NF_CT_PROTO_SCTP=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_MATCH_PHYSDEV=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_REALM=m
+CONFIG_IP_NF_MATCH_SCTP=m
+CONFIG_IP_NF_MATCH_COMMENT=m
+CONFIG_IP_NF_MATCH_CONNMARK=m
+CONFIG_IP_NF_MATCH_HASHLIMIT=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_TARGET_TCPMSS=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_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_CONNMARK=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_TARGET_NOTRACK=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=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_MATCH_PHYSDEV=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
+
+#
+# DECnet: Netfilter Configuration
+#
+CONFIG_DECNET_NF_GRABULATOR=m
+
+#
+# Bridge: Netfilter Configuration
+#
+CONFIG_BRIDGE_NF_EBTABLES=m
+CONFIG_BRIDGE_EBT_BROUTE=m
+CONFIG_BRIDGE_EBT_T_FILTER=m
+CONFIG_BRIDGE_EBT_T_NAT=m
+CONFIG_BRIDGE_EBT_802_3=m
+CONFIG_BRIDGE_EBT_AMONG=m
+CONFIG_BRIDGE_EBT_ARP=m
+CONFIG_BRIDGE_EBT_IP=m
+CONFIG_BRIDGE_EBT_LIMIT=m
+CONFIG_BRIDGE_EBT_MARK=m
+CONFIG_BRIDGE_EBT_PKTTYPE=m
+CONFIG_BRIDGE_EBT_STP=m
+CONFIG_BRIDGE_EBT_VLAN=m
+CONFIG_BRIDGE_EBT_ARPREPLY=m
+CONFIG_BRIDGE_EBT_DNAT=m
+CONFIG_BRIDGE_EBT_MARK_T=m
+CONFIG_BRIDGE_EBT_REDIRECT=m
+CONFIG_BRIDGE_EBT_SNAT=m
+CONFIG_BRIDGE_EBT_LOG=m
+# CONFIG_BRIDGE_EBT_ULOG is not set
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+CONFIG_BRIDGE=m
+# CONFIG_VLAN_8021Q is not set
+CONFIG_DECNET=m
+# CONFIG_DECNET_ROUTER 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 is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_CLK_JIFFIES=y
+# CONFIG_NET_SCH_CLK_GETTIMEOFDAY is not set
+# 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_CLS_U32_MARK 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=y
+
+#
+# Packet Radio protocols
+#
+CONFIG_AX25=m
+CONFIG_AX25_DAMA_SLAVE=y
+CONFIG_NETROM=m
+CONFIG_ROSE=m
+
+#
+# AX.25 network device drivers
+#
+CONFIG_MKISS=m
+CONFIG_6PACK=m
+CONFIG_BPQETHER=m
+# CONFIG_DMASCC is not set
+# CONFIG_SCC is not set
+# CONFIG_BAYCOM_SER_FDX is not set
+# CONFIG_BAYCOM_SER_HDX is not set
+# CONFIG_BAYCOM_PAR is not set
+# CONFIG_BAYCOM_EPP is not set
+# CONFIG_YAM 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
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_LANCE is not set
+# CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_NET_VENDOR_RACAL is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_AT1700 is not set
+# CONFIG_DEPCA is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_ISA=y
+# CONFIG_E2100 is not set
+# CONFIG_EWRK3 is not set
+# CONFIG_EEXPRESS is not set
+# CONFIG_EEXPRESS_PRO is not set
+# CONFIG_HPLAN_PLUS is not set
+# CONFIG_HPLAN is not set
+# CONFIG_LP486E is not set
+# CONFIG_ETH16I is not set
+CONFIG_NE2000=m
+# CONFIG_ZNET is not set
+# CONFIG_SEEQ8005 is not set
+CONFIG_NET_PCI=y
+CONFIG_PCNET32=y
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_AC3200 is not set
+# CONFIG_APRICOT is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_CS89x0 is not set
+# CONFIG_DGRS is not set
+CONFIG_EEPRO100=m
+# CONFIG_E100 is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+# CONFIG_LAN_SAA9730 is not set
+# CONFIG_NET_POCKET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+CONFIG_VIA_VELOCITY=m
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+CONFIG_PLIP=m
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC 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
+CONFIG_SERIO_PARKBD=m
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIO_RAW=m
+
+#
+# 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=y
+CONFIG_MOUSE_PS2=y
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_INPORT is not set
+# CONFIG_MOUSE_LOGIBM is not set
+# CONFIG_MOUSE_PC110PAD is not set
+# CONFIG_MOUSE_VSXXXAA 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=m
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+# CONFIG_SERIAL_8250_MANY_PORTS is not set
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_8250_DETECT_IRQ=y
+CONFIG_SERIAL_8250_MULTIPORT=y
+CONFIG_SERIAL_8250_RSA=y
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=m
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+CONFIG_PRINTER=m
+# CONFIG_LP_CONSOLE is not set
+CONFIG_PPDEV=m
+CONFIG_TIPAR=m
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+CONFIG_RTC=m
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Dallas's 1-wire bus
+#
+CONFIG_W1=m
+CONFIG_W1_MATROX=m
+CONFIG_W1_DS9490=m
+CONFIG_W1_DS9490_BRIDGE=m
+CONFIG_W1_THERM=m
+CONFIG_W1_SMEM=m
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB=m
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_EHCI_HCD=m
+# CONFIG_USB_EHCI_SPLIT_ISO is not set
+# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+CONFIG_USB_OHCI_HCD=m
+CONFIG_USB_UHCI_HCD=m
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_BLUETOOTH_TTY=m
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_RW_DETECT is not set
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_DPCM=y
+CONFIG_USB_STORAGE_HP8200e=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=m
+CONFIG_USB_HIDINPUT=y
+CONFIG_HID_FF=y
+CONFIG_HID_PID=y
+CONFIG_LOGITECH_FF=y
+CONFIG_THRUSTMASTER_FF=y
+CONFIG_USB_HIDDEV=y
+
+#
+# USB HID Boot Protocol drivers
+#
+CONFIG_USB_KBD=m
+CONFIG_USB_MOUSE=m
+CONFIG_USB_AIPTEK=m
+CONFIG_USB_WACOM=m
+CONFIG_USB_KBTAB=m
+CONFIG_USB_POWERMATE=m
+# CONFIG_USB_MTOUCH is not set
+CONFIG_USB_EGALAX=m
+CONFIG_USB_XPAD=m
+# CONFIG_USB_ATI_REMOTE is not set
+
+#
+# USB Imaging devices
+#
+CONFIG_USB_MDC800=m
+CONFIG_USB_MICROTEK=m
+
+#
+# USB Multimedia devices
+#
+CONFIG_USB_DABUSB=m
+
+#
+# Video4Linux support is needed for USB Multimedia device support
+#
+
+#
+# USB Network Adapters
+#
+CONFIG_USB_CATC=m
+CONFIG_USB_KAWETH=m
+CONFIG_USB_PEGASUS=m
+CONFIG_USB_RTL8150=m
+CONFIG_USB_USBNET=m
+
+#
+# USB Host-to-Host Cables
+#
+CONFIG_USB_ALI_M5632=y
+CONFIG_USB_AN2720=y
+CONFIG_USB_BELKIN=y
+CONFIG_USB_GENESYS=y
+CONFIG_USB_NET1080=y
+CONFIG_USB_PL2301=y
+CONFIG_USB_KC2190=y
+
+#
+# Intelligent USB Devices/Gadgets
+#
+CONFIG_USB_ARMLINUX=y
+CONFIG_USB_EPSON2888=y
+CONFIG_USB_ZAURUS=y
+CONFIG_USB_CDCETHER=y
+
+#
+# USB Network Adapters
+#
+CONFIG_USB_AX8817X=y
+
+#
+# USB port drivers
+#
+CONFIG_USB_USS720=m
+
+#
+# USB Serial Converter support
+#
+CONFIG_USB_SERIAL=m
+CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_BELKIN=m
+CONFIG_USB_SERIAL_WHITEHEAT=m
+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
+CONFIG_USB_SERIAL_CYPRESS_M8=m
+CONFIG_USB_SERIAL_EMPEG=m
+CONFIG_USB_SERIAL_FTDI_SIO=m
+CONFIG_USB_SERIAL_VISOR=m
+CONFIG_USB_SERIAL_IPAQ=m
+CONFIG_USB_SERIAL_IR=m
+CONFIG_USB_SERIAL_EDGEPORT=m
+CONFIG_USB_SERIAL_EDGEPORT_TI=m
+# CONFIG_USB_SERIAL_GARMIN is not set
+# CONFIG_USB_SERIAL_IPW is not set
+CONFIG_USB_SERIAL_KEYSPAN_PDA=m
+CONFIG_USB_SERIAL_KEYSPAN=m
+CONFIG_USB_SERIAL_KEYSPAN_MPR=y
+# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set
+CONFIG_USB_SERIAL_KEYSPAN_USA28X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y
+# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set
+CONFIG_USB_SERIAL_KEYSPAN_USA19W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y
+CONFIG_USB_SERIAL_KLSI=m
+CONFIG_USB_SERIAL_KOBIL_SCT=m
+CONFIG_USB_SERIAL_MCT_U232=m
+CONFIG_USB_SERIAL_PL2303=m
+CONFIG_USB_SERIAL_SAFE=m
+CONFIG_USB_SERIAL_SAFE_PADDED=y
+# CONFIG_USB_SERIAL_TI is not set
+CONFIG_USB_SERIAL_CYBERJACK=m
+CONFIG_USB_SERIAL_XIRCOM=m
+CONFIG_USB_SERIAL_OMNINET=m
+CONFIG_USB_EZUSB=y
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+CONFIG_USB_AUERSWALD=m
+CONFIG_USB_RIO500=m
+CONFIG_USB_LEGOTOWER=m
+CONFIG_USB_LCD=m
+CONFIG_USB_LED=m
+CONFIG_USB_CYTHERM=m
+CONFIG_USB_PHIDGETKIT=m
+CONFIG_USB_PHIDGETSERVO=m
+# CONFIG_USB_IDMOUSE is not set
+CONFIG_USB_TEST=m
+
+#
+# USB ATM/DSL drivers
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND 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 is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+CONFIG_REISERFS_FS_XATTR=y
+CONFIG_REISERFS_FS_POSIX_ACL=y
+CONFIG_REISERFS_FS_SECURITY=y
+# 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=m
+# CONFIG_QUOTA is not set
+CONFIG_QUOTACTL=y
+CONFIG_DNOTIFY=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=m
+# CONFIG_NTFS_DEBUG is not set
+# CONFIG_NTFS_RW 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=m
+# CONFIG_ADFS_FS_RW is not set
+CONFIG_AFFS_FS=m
+CONFIG_HFS_FS=m
+# CONFIG_HFSPLUS_FS is not set
+CONFIG_BEFS_FS=m
+# CONFIG_BEFS_DEBUG is not set
+CONFIG_BFS_FS=m
+CONFIG_EFS_FS=m
+CONFIG_CRAMFS=m
+CONFIG_VXFS_FS=m
+CONFIG_HPFS_FS=m
+CONFIG_QNX4FS_FS=m
+CONFIG_SYSV_FS=m
+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_RPCSEC_GSS_SPKM3=m
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+# CONFIG_CIFS_XATTR is not set
+# CONFIG_CIFS_EXPERIMENTAL is not set
+CONFIG_NCP_FS=m
+CONFIG_NCPFS_PACKET_SIGNING=y
+CONFIG_NCPFS_IOCTL_LOCKING=y
+CONFIG_NCPFS_STRONG=y
+CONFIG_NCPFS_NFS_NS=y
+CONFIG_NCPFS_OS2_NS=y
+CONFIG_NCPFS_SMALLDOS=y
+CONFIG_NCPFS_NLS=y
+CONFIG_NCPFS_EXTRAS=y
+CONFIG_CODA_FS=m
+CONFIG_CODA_FS_OLD_API=y
+CONFIG_AFS_FS=m
+CONFIG_RXRPC=m
+
+#
+# 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 is not set
+# 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
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_TEA=m
+# CONFIG_CRYPTO_ARC4 is not set
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+# CONFIG_CRYPTO_CRC32C is not set
+CONFIG_CRYPTO_TEST=m
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=m
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=m
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
diff --git a/arch/mips/configs/sb1250-swarm_defconfig b/arch/mips/configs/sb1250-swarm_defconfig
new file mode 100644
index 0000000..84978b7
--- /dev/null
+++ b/arch/mips/configs/sb1250-swarm_defconfig
@@ -0,0 +1,734 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-rc2
+# Wed Jan 26 02:49:10 2005
+#
+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_LOCK_KERNEL=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+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=15
+# CONFIG_HOTPLUG is not set
+CONFIG_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM 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_MODULE_SRCVERSION_ALL=y
+CONFIG_KMOD=y
+CONFIG_STOP_MACHINE=y
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ 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_OCELOT_3 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 is not set
+# CONFIG_SOC_AU1X00 is not set
+CONFIG_SIBYTE_SB1xxx_SOC=y
+CONFIG_SIBYTE_SWARM=y
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_PTSWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CRHONE is not set
+# CONFIG_SIBYTE_UNKNOWN is not set
+CONFIG_SIBYTE_BOARD=y
+CONFIG_SIBYTE_SB1250=y
+CONFIG_CPU_SB1_PASS_1=y
+# CONFIG_CPU_SB1_PASS_2_1250 is not set
+# CONFIG_CPU_SB1_PASS_2_2 is not set
+# CONFIG_CPU_SB1_PASS_4 is not set
+# CONFIG_CPU_SB1_PASS_2_112x is not set
+# CONFIG_CPU_SB1_PASS_3 is not set
+CONFIG_SIBYTE_HAS_LDT=y
+# CONFIG_SIMULATION is not set
+CONFIG_SIBYTE_CFE=y
+# CONFIG_SIBYTE_CFE_CONSOLE is not set
+# CONFIG_SIBYTE_BUS_WATCHER is not set
+# CONFIG_SIBYTE_SB1250_PROF is not set
+# CONFIG_SIBYTE_TBPROF is not set
+# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_RBTX4927 is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_DMA_COHERENT=y
+# CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_SWAP_IO_SPACE=y
+CONFIG_BOOT_ELF32=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+
+#
+# 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 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_RM9000 is not set
+CONFIG_CPU_SB1=y
+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_SIBYTE_DMA_PAGEOPS is not set
+CONFIG_CPU_HAS_PREFETCH=y
+CONFIG_SB1_PASS_1_WORKAROUNDS=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_HIGHMEM is not set
+CONFIG_SMP=y
+CONFIG_NR_CPUS=2
+# CONFIG_PREEMPT is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_HW_HAS_PCI=y
+CONFIG_PCI=y
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+CONFIG_MMU=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# 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_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=9220
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_ATA_OVER_ETH=m
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+CONFIG_BLK_DEV_IDECD=y
+CONFIG_BLK_DEV_IDETAPE=y
+CONFIG_BLK_DEV_IDEFLOPPY=y
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+# CONFIG_BLK_DEV_IDEPCI is not set
+CONFIG_BLK_DEV_IDE_SWARM=y
+# CONFIG_IDE_ARM is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# 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 is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+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_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+CONFIG_INET_TUNNEL=m
+CONFIG_IP_TCPDIAG=m
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# 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 is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# 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 is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_PCI is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+CONFIG_NET_SB1250_MAC=y
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI 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 is not set
+
+#
+# Userland interfaces
+#
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_LIBPS2 is not set
+CONFIG_SERIO_RAW=m
+
+#
+# Input Device Drivers
+#
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+CONFIG_SERIAL_NONSTANDARD=y
+# CONFIG_ROCKETPORT is not set
+# CONFIG_CYCLADES is not set
+# CONFIG_MOXA_SMARTIO is not set
+# CONFIG_ISI is not set
+# CONFIG_SYNCLINK is not set
+# CONFIG_SYNCLINKMP is not set
+# CONFIG_N_HDLC is not set
+# CONFIG_STALDRV is not set
+CONFIG_SIBYTE_SB1250_DUART=y
+CONFIG_SIBYTE_SB1250_DUART_CONSOLE=y
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# 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
+#
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD 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 is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# 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 is not set
+# 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 is not set
+# 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 is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+# CONFIG_SB1XXX_CORELIS is not set
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
+# 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_WP512=m
+CONFIG_CRYPTO_DES=y
+CONFIG_CRYPTO_BLOWFISH=y
+CONFIG_CRYPTO_TWOFISH=y
+CONFIG_CRYPTO_SERPENT=y
+CONFIG_CRYPTO_AES=m
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_TEA=m
+# CONFIG_CRYPTO_ARC4 is not set
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_DEFLATE=y
+CONFIG_CRYPTO_MICHAEL_MIC=y
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
diff --git a/arch/mips/configs/sead_defconfig b/arch/mips/configs/sead_defconfig
new file mode 100644
index 0000000..7c718a4
--- /dev/null
+++ b/arch/mips/configs/sead_defconfig
@@ -0,0 +1,493 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-rc2
+# Wed Jan 26 02:49:10 2005
+#
+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_LOCALVERSION=""
+CONFIG_SWAP=y
+# CONFIG_SYSVIPC 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 is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ 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=y
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_OCELOT_3 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 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_GENERIC_CALIBRATE_DELAY=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_IRQ_CPU=y
+CONFIG_MIPS_BOARDS_GEN=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+
+#
+# CPU selection
+#
+CONFIG_CPU_MIPS32=y
+# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_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_CPU_HAS_PREFETCH=y
+# CONFIG_64BIT_PHYS_ADDR is not set
+# CONFIG_CPU_ADVANCED is not set
+CONFIG_CPU_HAS_LLSC=y
+CONFIG_CPU_HAS_SYNC=y
+# CONFIG_PREEMPT is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_MMU=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# 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_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=18432
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
+CONFIG_CDROM_PKTCDVD=y
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI 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 is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+
+#
+# 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 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_LIBPS2 is not set
+CONFIG_SERIO_RAW=y
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD 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=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_UNIX98_PTYS is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# 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
+#
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB_ARCH_HAS_HCD is not set
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD 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 is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# 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_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 is not set
+# 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 is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC32 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
diff --git a/arch/mips/configs/tb0226_defconfig b/arch/mips/configs/tb0226_defconfig
new file mode 100644
index 0000000..e01727c
--- /dev/null
+++ b/arch/mips/configs/tb0226_defconfig
@@ -0,0 +1,763 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-rc2
+# Wed Jan 26 02:49:12 2005
+#
+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_LOCALVERSION=""
+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_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM 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_MODULE_SRCVERSION_ALL=y
+CONFIG_KMOD=y
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ is not set
+CONFIG_MACH_VR41XX=y
+# CONFIG_NEC_CMBVR4133 is not set
+# CONFIG_CASIO_E55 is not set
+# CONFIG_IBM_WORKPAD is not set
+CONFIG_TANBAC_TB0226=y
+# CONFIG_TANBAC_TB0229 is not set
+# CONFIG_VICTOR_MPC30X is not set
+# CONFIG_ZAO_CAPCELLA 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_OCELOT_3 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 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_GENERIC_CALIBRATE_DELAY=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_IRQ_CPU=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+
+#
+# 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=y
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_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_CPU_ADVANCED is not set
+CONFIG_CPU_HAS_SYNC=y
+# CONFIG_PREEMPT is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_HW_HAS_PCI=y
+# CONFIG_PCI is not set
+CONFIG_MMU=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# 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_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=m
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+CONFIG_BLK_DEV_NBD=m
+CONFIG_BLK_DEV_RAM=m
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_ATA_OVER_ETH=m
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+CONFIG_IDEDISK_MULTI_MODE=y
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+CONFIG_BLK_DEV_IDESCSI=y
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+# CONFIG_IDE_ARM is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD 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 is not set
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=y
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+CONFIG_CHR_DEV_SG=y
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_SCSI_SATA 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 is not set
+CONFIG_NETLINK_DEV=m
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+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=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+CONFIG_INET_TUNNEL=m
+CONFIG_IP_TCPDIAG=m
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# 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 is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# 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 is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+
+#
+# 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=m
+CONFIG_PPP_MULTILINK=y
+# CONFIG_PPP_FILTER is not set
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPPOE=m
+# 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
+# CONFIG_SERIO_LIBPS2 is not set
+CONFIG_SERIO_RAW=m
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD 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=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# 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
+#
+CONFIG_FB=y
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE is not set
+
+#
+# Logo configuration
+#
+# CONFIG_LOGO is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+CONFIG_SOUND=y
+
+#
+# Advanced Linux Sound Architecture
+#
+# CONFIG_SND is not set
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+
+#
+# USB support
+#
+# CONFIG_USB_ARCH_HAS_HCD is not set
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+CONFIG_ROMFS_FS=m
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+CONFIG_AUTOFS4_FS=y
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_ZISOFS_FS=y
+# CONFIG_UDF_FS is not set
+
+#
+# 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=y
+# CONFIG_TMPFS_XATTR 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 is not set
+CONFIG_CRAMFS=m
+# 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 is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+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 is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=m
+CONFIG_SMB_NLS_DEFAULT=y
+CONFIG_SMB_NLS_REMOTE="cp932"
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=m
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+CONFIG_NLS_CODEPAGE_932=m
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=m
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=m
+# CONFIG_CRC32 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
diff --git a/arch/mips/configs/tb0229_defconfig b/arch/mips/configs/tb0229_defconfig
new file mode 100644
index 0000000..c6ba3de2
--- /dev/null
+++ b/arch/mips/configs/tb0229_defconfig
@@ -0,0 +1,775 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-rc2
+# Wed Jan 26 02:49:12 2005
+#
+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_LOCALVERSION=""
+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_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM 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_MODULE_SRCVERSION_ALL=y
+CONFIG_KMOD=y
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ is not set
+CONFIG_MACH_VR41XX=y
+# CONFIG_NEC_CMBVR4133 is not set
+# CONFIG_CASIO_E55 is not set
+# CONFIG_IBM_WORKPAD is not set
+# CONFIG_TANBAC_TB0226 is not set
+CONFIG_TANBAC_TB0229=y
+CONFIG_TANBAC_TB0219=y
+# CONFIG_VICTOR_MPC30X is not set
+# CONFIG_ZAO_CAPCELLA is not set
+CONFIG_PCI_VR41XX=y
+# CONFIG_VRC4173 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_OCELOT_3 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 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_GENERIC_CALIBRATE_DELAY=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_IRQ_CPU=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+
+#
+# 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=y
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_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_CPU_ADVANCED is not set
+CONFIG_CPU_HAS_SYNC=y
+# CONFIG_PREEMPT is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_HW_HAS_PCI=y
+CONFIG_PCI=y
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+CONFIG_MMU=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# 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_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=m
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+CONFIG_BLK_DEV_NBD=m
+# CONFIG_BLK_DEV_SX8 is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_INITRD is not set
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_ATA_OVER_ETH=m
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_NETLINK_DEV=m
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+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=m
+CONFIG_NET_IPGRE=m
+# CONFIG_NET_IPGRE_BROADCAST is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+CONFIG_INET_TUNNEL=m
+CONFIG_IP_TCPDIAG=m
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# 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 is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# 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 is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=y
+CONFIG_PCNET32=y
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_DGRS is not set
+CONFIG_EEPRO100=y
+# CONFIG_E100 is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+# CONFIG_LAN_SAA9730 is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+CONFIG_PPP=m
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPPOE=m
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLIP_SMART=y
+CONFIG_SLIP_MODE_SLIP6=y
+# 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
+# CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_LIBPS2 is not set
+CONFIG_SERIO_RAW=m
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD 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=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# 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
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT3_FS=m
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_JBD=m
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+CONFIG_JFS_FS=m
+# CONFIG_JFS_POSIX_ACL is not set
+# CONFIG_JFS_SECURITY is not set
+# CONFIG_JFS_DEBUG is not set
+# CONFIG_JFS_STATISTICS is not set
+CONFIG_XFS_FS=y
+# CONFIG_XFS_RT is not set
+CONFIG_XFS_QUOTA=y
+# CONFIG_XFS_SECURITY is not set
+CONFIG_XFS_POSIX_ACL=y
+# CONFIG_MINIX_FS is not set
+CONFIG_ROMFS_FS=m
+# CONFIG_QUOTA is not set
+CONFIG_QUOTACTL=y
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+CONFIG_AUTOFS4_FS=y
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_ZISOFS_FS=y
+# CONFIG_UDF_FS is not set
+
+#
+# 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=y
+# CONFIG_TMPFS_XATTR 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 is not set
+CONFIG_CRAMFS=m
+# 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 is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=y
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V4 is not set
+CONFIG_NFSD_TCP=y
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=m
+CONFIG_SMB_NLS_DEFAULT=y
+CONFIG_SMB_NLS_REMOTE="cp932"
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=m
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+CONFIG_NLS_CODEPAGE_932=m
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=m
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE="mem=64M console=ttyS0,38400 ip=bootp root=/dev/nfs"
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=m
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
diff --git a/arch/mips/configs/workpad_defconfig b/arch/mips/configs/workpad_defconfig
new file mode 100644
index 0000000..915c43b
--- /dev/null
+++ b/arch/mips/configs/workpad_defconfig
@@ -0,0 +1,687 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-rc2
+# Wed Jan 26 02:49:12 2005
+#
+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_LOCALVERSION=""
+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_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM 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_MODULE_SRCVERSION_ALL=y
+CONFIG_KMOD=y
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ is not set
+CONFIG_MACH_VR41XX=y
+# CONFIG_NEC_CMBVR4133 is not set
+# CONFIG_CASIO_E55 is not set
+CONFIG_IBM_WORKPAD=y
+# CONFIG_TANBAC_TB0226 is not set
+# CONFIG_TANBAC_TB0229 is not set
+# CONFIG_VICTOR_MPC30X is not set
+# CONFIG_ZAO_CAPCELLA is not set
+CONFIG_VRC4171=y
+# 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_OCELOT_3 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 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_GENERIC_CALIBRATE_DELAY=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_IRQ_CPU=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+
+#
+# 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=y
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_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_CPU_ADVANCED is not set
+CONFIG_CPU_HAS_SYNC=y
+# CONFIG_PREEMPT is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_ISA=y
+CONFIG_MMU=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+CONFIG_PCMCIA_PROBE=y
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+# CONFIG_PNP is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_XD is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_ATA_OVER_ETH=m
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+# CONFIG_IDE_ARM is not set
+# CONFIG_IDE_CHIPSETS is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Old CD-ROM drivers (not SCSI, not IDE)
+#
+# CONFIG_CD_NO_IDESCSI 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 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 is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+CONFIG_INET_TUNNEL=m
+CONFIG_IP_TCPDIAG=m
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# 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 is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# 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 is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_LANCE is not set
+# CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_NET_VENDOR_RACAL is not set
+# CONFIG_AT1700 is not set
+# CONFIG_DEPCA is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_ISA is not set
+# CONFIG_NET_PCI is not set
+# CONFIG_NET_POCKET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# 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
+# CONFIG_SERIO_LIBPS2 is not set
+CONFIG_SERIO_RAW=m
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD 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=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# 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
+
+#
+# ISA-based Watchdog Cards
+#
+# CONFIG_PCWATCHDOG is not set
+# CONFIG_MIXCOMWD is not set
+# CONFIG_WDT is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# 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
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB_ARCH_HAS_HCD is not set
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD 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 is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+CONFIG_AUTOFS_FS=y
+CONFIG_AUTOFS4_FS=y
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# 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 is not set
+# 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 is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=y
+# CONFIG_NFSD_V3 is not set
+# CONFIG_NFSD_TCP is not set
+CONFIG_LOCKD=y
+CONFIG_EXPORTFS=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC32 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
diff --git a/arch/mips/configs/yosemite_defconfig b/arch/mips/configs/yosemite_defconfig
new file mode 100644
index 0000000..562f2b8
--- /dev/null
+++ b/arch/mips/configs/yosemite_defconfig
@@ -0,0 +1,615 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-rc2
+# Wed Jan 26 02:49:13 2005
+#
+CONFIG_MIPS=y
+# CONFIG_MIPS64 is not set
+# CONFIG_64BIT is not set
+CONFIG_MIPS32=y
+
+#
+# Code maturity level options
+#
+# CONFIG_EXPERIMENTAL is not set
+CONFIG_CLEAN_COMPILE=y
+CONFIG_LOCK_KERNEL=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# 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_KOBJECT_UEVENT=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+CONFIG_STOP_MACHINE=y
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_MACH_DECSTATION 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_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MOMENCO_JAGUAR_ATX is not set
+CONFIG_PMC_YOSEMITE=y
+# CONFIG_HYPERTRANSPORT is not set
+# CONFIG_DDB5476 is not set
+# CONFIG_DDB5477 is not set
+# CONFIG_NEC_OSPREY is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SOC_AU1X00 is not set
+# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_RBTX4927 is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_DMA_COHERENT=y
+# CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_IRQ_CPU=y
+CONFIG_IRQ_CPU_RM7K=y
+CONFIG_IRQ_CPU_RM9K=y
+CONFIG_SWAP_IO_SPACE=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+
+#
+# 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 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+CONFIG_CPU_RM9000=y
+# 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_CPU_HAS_PREFETCH=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_HIGHMEM=y
+CONFIG_SMP=y
+CONFIG_NR_CPUS=2
+# CONFIG_PREEMPT is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_HW_HAS_PCI=y
+CONFIG_PCI=y
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+CONFIG_MMU=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# 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_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_RAM is not set
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_ATA_OVER_ETH=m
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=m
+CONFIG_PACKET_MMAP=y
+CONFIG_NETLINK_DEV=m
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# 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_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+CONFIG_INET_TUNNEL=m
+CONFIG_IP_TCPDIAG=m
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+# 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
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# 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 is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_PCI is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+CONFIG_TITAN_GE=y
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+# CONFIG_INPUT is not set
+
+#
+# Userland interfaces
+#
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+# CONFIG_SERIO is not set
+# CONFIG_SERIO_I8042 is not set
+
+#
+# Input Device Drivers
+#
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+CONFIG_GEN_RTC=y
+CONFIG_GEN_RTC_X=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# 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
+#
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_XATTR is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_HFSPLUS_FS is not set
+# 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 is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Kernel hacking
+#
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_HIGHMEM is not set
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_FS is not set
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_KGDB is not set
+# CONFIG_RUNTIME_DEBUG is not set
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC32 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
diff --git a/arch/mips/ddb5xxx/common/Makefile b/arch/mips/ddb5xxx/common/Makefile
new file mode 100644
index 0000000..bc44e30
--- /dev/null
+++ b/arch/mips/ddb5xxx/common/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for the common code of NEC DDB-Vrc5xxx board
+#
+
+obj-y += nile4.o prom.o rtc_ds1386.o
diff --git a/arch/mips/ddb5xxx/common/nile4.c b/arch/mips/ddb5xxx/common/nile4.c
new file mode 100644
index 0000000..7ec7d90
--- /dev/null
+++ b/arch/mips/ddb5xxx/common/nile4.c
@@ -0,0 +1,130 @@
+/*
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: jsun@mvista.com or jsun@junsun.net
+ *
+ * arch/mips/ddb5xxx/common/nile4.c
+ * misc low-level routines for vrc-5xxx controllers.
+ *
+ * derived from original code by Geert Uytterhoeven <geert@sonycom.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+#include <linux/types.h>
+#include <linux/kernel.h>
+
+#include <asm/ddb5xxx/ddb5xxx.h>
+
+u32
+ddb_calc_pdar(u32 phys, u32 size, int width,
+ int on_memory_bus, int pci_visible)
+{
+ u32 maskbits;
+ u32 widthbits;
+
+ switch (size) {
+#if 0 /* We don't support 4 GB yet */
+ case 0x100000000: /* 4 GB */
+ maskbits = 4;
+ break;
+#endif
+ case 0x80000000: /* 2 GB */
+ maskbits = 5;
+ break;
+ case 0x40000000: /* 1 GB */
+ maskbits = 6;
+ break;
+ case 0x20000000: /* 512 MB */
+ maskbits = 7;
+ break;
+ case 0x10000000: /* 256 MB */
+ maskbits = 8;
+ break;
+ case 0x08000000: /* 128 MB */
+ maskbits = 9;
+ break;
+ case 0x04000000: /* 64 MB */
+ maskbits = 10;
+ break;
+ case 0x02000000: /* 32 MB */
+ maskbits = 11;
+ break;
+ case 0x01000000: /* 16 MB */
+ maskbits = 12;
+ break;
+ case 0x00800000: /* 8 MB */
+ maskbits = 13;
+ break;
+ case 0x00400000: /* 4 MB */
+ maskbits = 14;
+ break;
+ case 0x00200000: /* 2 MB */
+ maskbits = 15;
+ break;
+ case 0: /* OFF */
+ maskbits = 0;
+ break;
+ default:
+ panic("nile4_set_pdar: unsupported size %p", (void *) size);
+ }
+ switch (width) {
+ case 8:
+ widthbits = 0;
+ break;
+ case 16:
+ widthbits = 1;
+ break;
+ case 32:
+ widthbits = 2;
+ break;
+ case 64:
+ widthbits = 3;
+ break;
+ default:
+ panic("nile4_set_pdar: unsupported width %d", width);
+ }
+
+ return maskbits | (on_memory_bus ? 0x10 : 0) |
+ (pci_visible ? 0x20 : 0) | (widthbits << 6) |
+ (phys & 0xffe00000);
+}
+
+void
+ddb_set_pdar(u32 pdar, u32 phys, u32 size, int width,
+ int on_memory_bus, int pci_visible)
+{
+ u32 temp= ddb_calc_pdar(phys, size, width, on_memory_bus, pci_visible);
+ ddb_out32(pdar, temp);
+ ddb_out32(pdar + 4, 0);
+
+ /*
+ * When programming a PDAR, the register should be read immediately
+ * after writing it. This ensures that address decoders are properly
+ * configured.
+ * [jsun] is this really necessary?
+ */
+ ddb_in32(pdar);
+ ddb_in32(pdar + 4);
+}
+
+/*
+ * routines that mess with PCIINITx registers
+ */
+
+void ddb_set_pmr(u32 pmr, u32 type, u32 addr, u32 options)
+{
+ switch (type) {
+ case DDB_PCICMD_IACK: /* PCI Interrupt Acknowledge */
+ case DDB_PCICMD_IO: /* PCI I/O Space */
+ case DDB_PCICMD_MEM: /* PCI Memory Space */
+ case DDB_PCICMD_CFG: /* PCI Configuration Space */
+ break;
+ default:
+ panic("nile4_set_pmr: invalid type %d", type);
+ }
+ ddb_out32(pmr, (type << 1) | (addr & 0xffe00000) | options );
+ ddb_out32(pmr + 4, 0);
+}
diff --git a/arch/mips/ddb5xxx/common/prom.c b/arch/mips/ddb5xxx/common/prom.c
new file mode 100644
index 0000000..b8d1f74
--- /dev/null
+++ b/arch/mips/ddb5xxx/common/prom.c
@@ -0,0 +1,142 @@
+/*
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: jsun@mvista.com or jsun@junsun.net
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/bootmem.h>
+
+#include <asm/addrspace.h>
+#include <asm/bootinfo.h>
+#include <asm/ddb5xxx/ddb5xxx.h>
+#include <asm/debug.h>
+
+const char *get_system_type(void)
+{
+ switch (mips_machtype) {
+ case MACH_NEC_DDB5074: return "NEC DDB Vrc-5074";
+ case MACH_NEC_DDB5476: return "NEC DDB Vrc-5476";
+ case MACH_NEC_DDB5477: return "NEC DDB Vrc-5477";
+ case MACH_NEC_ROCKHOPPER: return "NEC Rockhopper";
+ case MACH_NEC_ROCKHOPPERII: return "NEC RockhopperII";
+ default: return "Unknown NEC board";
+ }
+}
+
+#if defined(CONFIG_DDB5477)
+void ddb5477_runtime_detection(void);
+#endif
+
+/* [jsun@junsun.net] PMON passes arguments in C main() style */
+void __init prom_init(void)
+{
+ int argc = fw_arg0;
+ char **arg = (char**) fw_arg1;
+ int i;
+
+ /* if user passes kernel args, ignore the default one */
+ if (argc > 1)
+ arcs_cmdline[0] = '\0';
+
+ /* arg[0] is "g", the rest is boot parameters */
+ for (i = 1; i < argc; i++) {
+ if (strlen(arcs_cmdline) + strlen(arg[i] + 1)
+ >= sizeof(arcs_cmdline))
+ break;
+ strcat(arcs_cmdline, arg[i]);
+ strcat(arcs_cmdline, " ");
+ }
+
+ mips_machgroup = MACH_GROUP_NEC_DDB;
+
+#if defined(CONFIG_DDB5074)
+ mips_machtype = MACH_NEC_DDB5074;
+ add_memory_region(0, DDB_SDRAM_SIZE, BOOT_MEM_RAM);
+#elif defined(CONFIG_DDB5476)
+ mips_machtype = MACH_NEC_DDB5476;
+ add_memory_region(0, DDB_SDRAM_SIZE, BOOT_MEM_RAM);
+#elif defined(CONFIG_DDB5477)
+ ddb5477_runtime_detection();
+ add_memory_region(0, board_ram_size, BOOT_MEM_RAM);
+#endif
+}
+
+unsigned long __init prom_free_prom_memory(void)
+{
+ return 0;
+}
+
+#if defined(CONFIG_DDB5477)
+
+#define DEFAULT_LCS1_BASE 0x19000000
+#define TESTVAL1 'K'
+#define TESTVAL2 'S'
+
+int board_ram_size;
+void ddb5477_runtime_detection(void)
+{
+ volatile char *test_offset;
+ char saved_test_byte;
+
+ /* Determine if this is a DDB5477 board, or a BSB-VR0300
+ base board. We can tell by checking for the location of
+ the NVRAM. It lives at the beginning of LCS1 on the DDB5477,
+ and the beginning of LCS1 on the BSB-VR0300 is flash memory.
+ The first 2K of the NVRAM are reserved, so don't we'll poke
+ around just after that.
+ */
+
+ /* We can only use the PCI bus to distinquish between
+ the Rockhopper and RockhopperII backplanes and this must
+ wait until ddb5477_board_init() in setup.c after the 5477
+ is initialized. So, until then handle
+ both Rockhopper and RockhopperII backplanes as Rockhopper 1
+ */
+
+ test_offset = (char *)KSEG1ADDR(DEFAULT_LCS1_BASE + 0x800);
+ saved_test_byte = *test_offset;
+
+ *test_offset = TESTVAL1;
+ if (*test_offset != TESTVAL1) {
+ /* We couldn't set our test value, so it must not be NVRAM,
+ so it's a BSB_VR0300 */
+ mips_machtype = MACH_NEC_ROCKHOPPER;
+ } else {
+ /* We may have gotten lucky, and the TESTVAL1 was already
+ stored at the test location, so we must check a second
+ test value */
+ *test_offset = TESTVAL2;
+ if (*test_offset != TESTVAL2) {
+ /* OK, we couldn't set this value either, so it must
+ definately be a BSB_VR0300 */
+ mips_machtype = MACH_NEC_ROCKHOPPER;
+ } else {
+ /* We could change the value twice, so it must be
+ NVRAM, so it's a DDB_VRC5477 */
+ mips_machtype = MACH_NEC_DDB5477;
+ }
+ }
+ /* Restore the original byte */
+ *test_offset = saved_test_byte;
+
+ /* before we know a better way, we will trust PMON for getting
+ * RAM size
+ */
+ board_ram_size = 1 << (36 - (ddb_in32(DDB_SDRAM0) & 0xf));
+
+ db_run(printk("DDB run-time detection : %s, %d MB RAM\n",
+ mips_machtype == MACH_NEC_DDB5477 ?
+ "DDB5477" : "Rockhopper",
+ board_ram_size >> 20));
+
+ /* we can't handle ram size > 128 MB */
+ db_assert(board_ram_size <= (128 << 20));
+}
+#endif
diff --git a/arch/mips/ddb5xxx/common/rtc_ds1386.c b/arch/mips/ddb5xxx/common/rtc_ds1386.c
new file mode 100644
index 0000000..f5b1150
--- /dev/null
+++ b/arch/mips/ddb5xxx/common/rtc_ds1386.c
@@ -0,0 +1,164 @@
+/*
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: jsun@mvista.com or jsun@junsun.net
+ *
+ * arch/mips/ddb5xxx/common/rtc_ds1386.c
+ * low-level RTC hookups for s for Dallas 1396 chip.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+
+/*
+ * This file exports a function, rtc_ds1386_init(), which expects an
+ * uncached base address as the argument. It will set the two function
+ * pointers expected by the MIPS generic timer code.
+ */
+
+#include <linux/types.h>
+#include <linux/time.h>
+#include <linux/bcd.h>
+
+#include <asm/time.h>
+#include <asm/addrspace.h>
+
+#include <asm/mc146818rtc.h>
+#include <asm/debug.h>
+
+#define EPOCH 2000
+
+#define READ_RTC(x) *(volatile unsigned char*)(rtc_base+x)
+#define WRITE_RTC(x, y) *(volatile unsigned char*)(rtc_base+x) = y
+
+static unsigned long rtc_base;
+
+static unsigned long
+rtc_ds1386_get_time(void)
+{
+ u8 byte;
+ u8 temp;
+ unsigned int year, month, day, hour, minute, second;
+
+ /* let us freeze external registers */
+ byte = READ_RTC(0xB);
+ byte &= 0x3f;
+ WRITE_RTC(0xB, byte);
+
+ /* read time data */
+ year = BCD2BIN(READ_RTC(0xA)) + EPOCH;
+ month = BCD2BIN(READ_RTC(0x9) & 0x1f);
+ day = BCD2BIN(READ_RTC(0x8));
+ minute = BCD2BIN(READ_RTC(0x2));
+ second = BCD2BIN(READ_RTC(0x1));
+
+ /* hour is special - deal with it later */
+ temp = READ_RTC(0x4);
+
+ /* enable time transfer */
+ byte |= 0x80;
+ WRITE_RTC(0xB, byte);
+
+ /* calc hour */
+ if (temp & 0x40) {
+ /* 12 hour format */
+ hour = BCD2BIN(temp & 0x1f);
+ if (temp & 0x20) hour += 12; /* PM */
+ } else {
+ /* 24 hour format */
+ hour = BCD2BIN(temp & 0x3f);
+ }
+
+ return mktime(year, month, day, hour, minute, second);
+}
+
+static int
+rtc_ds1386_set_time(unsigned long t)
+{
+ struct rtc_time tm;
+ u8 byte;
+ u8 temp;
+ u8 year, month, day, hour, minute, second;
+
+ /* let us freeze external registers */
+ byte = READ_RTC(0xB);
+ byte &= 0x3f;
+ WRITE_RTC(0xB, byte);
+
+ /* convert */
+ to_tm(t, &tm);
+
+
+ /* check each field one by one */
+ year = BIN2BCD(tm.tm_year - EPOCH);
+ if (year != READ_RTC(0xA)) {
+ WRITE_RTC(0xA, year);
+ }
+
+ temp = READ_RTC(0x9);
+ month = BIN2BCD(tm.tm_mon+1); /* tm_mon starts from 0 to 11 */
+ if (month != (temp & 0x1f)) {
+ WRITE_RTC( 0x9,
+ (month & 0x1f) | (temp & ~0x1f) );
+ }
+
+ day = BIN2BCD(tm.tm_mday);
+ if (day != READ_RTC(0x8)) {
+ WRITE_RTC(0x8, day);
+ }
+
+ temp = READ_RTC(0x4);
+ if (temp & 0x40) {
+ /* 12 hour format */
+ hour = 0x40;
+ if (tm.tm_hour > 12) {
+ hour |= 0x20 | (BIN2BCD(hour-12) & 0x1f);
+ } else {
+ hour |= BIN2BCD(tm.tm_hour);
+ }
+ } else {
+ /* 24 hour format */
+ hour = BIN2BCD(tm.tm_hour) & 0x3f;
+ }
+ if (hour != temp) WRITE_RTC(0x4, hour);
+
+ minute = BIN2BCD(tm.tm_min);
+ if (minute != READ_RTC(0x2)) {
+ WRITE_RTC(0x2, minute);
+ }
+
+ second = BIN2BCD(tm.tm_sec);
+ if (second != READ_RTC(0x1)) {
+ WRITE_RTC(0x1, second);
+ }
+
+ return 0;
+}
+
+void
+rtc_ds1386_init(unsigned long base)
+{
+ unsigned char byte;
+
+ /* remember the base */
+ rtc_base = base;
+ db_assert((rtc_base & 0xe0000000) == KSEG1);
+
+ /* turn on RTC if it is not on */
+ byte = READ_RTC(0x9);
+ if (byte & 0x80) {
+ byte &= 0x7f;
+ WRITE_RTC(0x9, byte);
+ }
+
+ /* enable time transfer */
+ byte = READ_RTC(0xB);
+ byte |= 0x80;
+ WRITE_RTC(0xB, byte);
+
+ /* set the function pointers */
+ rtc_get_time = rtc_ds1386_get_time;
+ rtc_set_time = rtc_ds1386_set_time;
+}
diff --git a/arch/mips/ddb5xxx/ddb5074/Makefile b/arch/mips/ddb5xxx/ddb5074/Makefile
new file mode 100644
index 0000000..488206b
--- /dev/null
+++ b/arch/mips/ddb5xxx/ddb5074/Makefile
@@ -0,0 +1,8 @@
+#
+# Makefile for the NEC DDB Vrc-5074 specific kernel interface routines
+# under Linux.
+#
+
+obj-y += setup.o irq.o int-handler.o nile4_pic.o
+
+EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/ddb5xxx/ddb5074/int-handler.S b/arch/mips/ddb5xxx/ddb5074/int-handler.S
new file mode 100644
index 0000000..a786441
--- /dev/null
+++ b/arch/mips/ddb5xxx/ddb5074/int-handler.S
@@ -0,0 +1,120 @@
+/*
+ * arch/mips/ddb5074/int-handler.S -- NEC DDB Vrc-5074 interrupt handler
+ *
+ * Based on arch/mips/sgi/kernel/indyIRQ.S
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ *
+ * Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
+ * Sony Software Development Center Europe (SDCE), Brussels
+ */
+#include <asm/asm.h>
+#include <asm/mipsregs.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+
+/* A lot of complication here is taken away because:
+ *
+ * 1) We handle one interrupt and return, sitting in a loop and moving across
+ * all the pending IRQ bits in the cause register is _NOT_ the answer, the
+ * common case is one pending IRQ so optimize in that direction.
+ *
+ * 2) We need not check against bits in the status register IRQ mask, that
+ * would make this routine slow as hell.
+ *
+ * 3) Linux only thinks in terms of all IRQs on or all IRQs off, nothing in
+ * between like BSD spl() brain-damage.
+ *
+ * Furthermore, the IRQs on the INDY look basically (barring software IRQs
+ * which we don't use at all) like:
+ *
+ * MIPS IRQ Source
+ * -------- ------
+ * 0 Software (ignored)
+ * 1 Software (ignored)
+ * 2 Local IRQ level zero
+ * 3 Local IRQ level one
+ * 4 8254 Timer zero
+ * 5 8254 Timer one
+ * 6 Bus Error
+ * 7 R4k timer (what we use)
+ *
+ * We handle the IRQ according to _our_ priority which is:
+ *
+ * Highest ---- R4k Timer
+ * Local IRQ zero
+ * Local IRQ one
+ * Bus Error
+ * 8254 Timer zero
+ * Lowest ---- 8254 Timer one
+ *
+ * then we just return, if multiple IRQs are pending then we will just take
+ * another exception, big deal.
+ */
+
+ .text
+ .set noreorder
+ .set noat
+ .align 5
+ NESTED(ddbIRQ, PT_SIZE, sp)
+ SAVE_ALL
+ CLI
+ .set at
+ mfc0 s0, CP0_CAUSE # get irq mask
+
+#if 1
+ mfc0 t2,CP0_STATUS # get enabled interrupts
+ and s0,t2 # isolate allowed ones
+#endif
+ /* First we check for r4k counter/timer IRQ. */
+ andi a0, s0, CAUSEF_IP2 # delay slot, check local level zero
+ beq a0, zero, 1f
+ andi a0, s0, CAUSEF_IP3 # delay slot, check local level one
+
+ /* Wheee, local level zero interrupt. */
+ jal ddb_local0_irqdispatch
+ move a0, sp # delay slot
+
+ j ret_from_irq
+ nop # delay slot
+
+1:
+ beq a0, zero, 1f
+ andi a0, s0, CAUSEF_IP6 # delay slot, check bus error
+
+ /* Wheee, local level one interrupt. */
+ move a0, sp
+ jal ddb_local1_irqdispatch
+ nop
+
+ j ret_from_irq
+ nop
+
+1:
+ beq a0, zero, 1f
+ nop
+
+ /* Wheee, an asynchronous bus error... */
+ move a0, sp
+ jal ddb_buserror_irq
+ nop
+
+ j ret_from_irq
+ nop
+
+1:
+ /* Here by mistake? This is possible, what can happen
+ * is that by the time we take the exception the IRQ
+ * pin goes low, so just leave if this is the case.
+ */
+ andi a0, s0, (CAUSEF_IP4 | CAUSEF_IP5)
+ beq a0, zero, 1f
+
+ /* Must be one of the 8254 timers... */
+ move a0, sp
+ jal ddb_8254timer_irq
+ nop
+1:
+ j ret_from_irq
+ nop
+ END(ddbIRQ)
diff --git a/arch/mips/ddb5xxx/ddb5074/irq.c b/arch/mips/ddb5xxx/ddb5074/irq.c
new file mode 100644
index 0000000..45088a1
--- /dev/null
+++ b/arch/mips/ddb5xxx/ddb5074/irq.c
@@ -0,0 +1,159 @@
+/*
+ * arch/mips/ddb5074/irq.c -- NEC DDB Vrc-5074 interrupt routines
+ *
+ * Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
+ * Sony Software Development Center Europe (SDCE), Brussels
+ */
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+
+#include <asm/i8259.h>
+#include <asm/io.h>
+#include <asm/irq_cpu.h>
+#include <asm/ptrace.h>
+#include <asm/nile4.h>
+#include <asm/ddb5xxx/ddb5xxx.h>
+#include <asm/ddb5xxx/ddb5074.h>
+
+
+extern asmlinkage void ddbIRQ(void);
+
+static struct irqaction irq_cascade = { no_action, 0, CPU_MASK_NONE, "cascade", NULL, NULL };
+
+#define M1543_PNP_CONFIG 0x03f0 /* PnP Config Port */
+#define M1543_PNP_INDEX 0x03f0 /* PnP Index Port */
+#define M1543_PNP_DATA 0x03f1 /* PnP Data Port */
+
+#define M1543_PNP_ALT_CONFIG 0x0370 /* Alternative PnP Config Port */
+#define M1543_PNP_ALT_INDEX 0x0370 /* Alternative PnP Index Port */
+#define M1543_PNP_ALT_DATA 0x0371 /* Alternative PnP Data Port */
+
+#define M1543_INT1_MASTER_CTRL 0x0020 /* INT_1 (master) Control Register */
+#define M1543_INT1_MASTER_MASK 0x0021 /* INT_1 (master) Mask Register */
+
+#define M1543_INT1_SLAVE_CTRL 0x00a0 /* INT_1 (slave) Control Register */
+#define M1543_INT1_SLAVE_MASK 0x00a1 /* INT_1 (slave) Mask Register */
+
+#define M1543_INT1_MASTER_ELCR 0x04d0 /* INT_1 (master) Edge/Level Control */
+#define M1543_INT1_SLAVE_ELCR 0x04d1 /* INT_1 (slave) Edge/Level Control */
+
+
+static void m1543_irq_setup(void)
+{
+ /*
+ * The ALI M1543 has 13 interrupt inputs, IRQ1..IRQ13. Not all
+ * the possible IO sources in the M1543 are in use by us. We will
+ * use the following mapping:
+ *
+ * IRQ1 - keyboard (default set by M1543)
+ * IRQ3 - reserved for UART B (default set by M1543) (note that
+ * the schematics for the DDB Vrc-5074 board seem to
+ * indicate that IRQ3 is connected to the DS1386
+ * watchdog timer interrupt output so we might have
+ * a conflict)
+ * IRQ4 - reserved for UART A (default set by M1543)
+ * IRQ5 - parallel (default set by M1543)
+ * IRQ8 - DS1386 time of day (RTC) interrupt
+ * IRQ12 - mouse
+ */
+
+ /*
+ * Assing mouse interrupt to IRQ12
+ */
+
+ /* Enter configuration mode */
+ outb(0x51, M1543_PNP_CONFIG);
+ outb(0x23, M1543_PNP_CONFIG);
+
+ /* Select logical device 7 (Keyboard) */
+ outb(0x07, M1543_PNP_INDEX);
+ outb(0x07, M1543_PNP_DATA);
+
+ /* Select IRQ12 */
+ outb(0x72, M1543_PNP_INDEX);
+ outb(0x0c, M1543_PNP_DATA);
+
+ outb(0x30, M1543_PNP_INDEX);
+ printk("device 7, 0x30: %02x\n",inb(M1543_PNP_DATA));
+
+ outb(0x70, M1543_PNP_INDEX);
+ printk("device 7, 0x70: %02x\n",inb(M1543_PNP_DATA));
+
+ /* Leave configration mode */
+ outb(0xbb, M1543_PNP_CONFIG);
+
+
+}
+
+void ddb_local0_irqdispatch(struct pt_regs *regs)
+{
+ u32 mask;
+ int nile4_irq;
+
+ mask = nile4_get_irq_stat(0);
+
+ /* Handle the timer interrupt first */
+#if 0
+ if (mask & (1 << NILE4_INT_GPT)) {
+ do_IRQ(nile4_to_irq(NILE4_INT_GPT), regs);
+ mask &= ~(1 << NILE4_INT_GPT);
+ }
+#endif
+ for (nile4_irq = 0; mask; nile4_irq++, mask >>= 1)
+ if (mask & 1) {
+ if (nile4_irq == NILE4_INT_INTE) {
+ int i8259_irq;
+
+ nile4_clear_irq(NILE4_INT_INTE);
+ i8259_irq = nile4_i8259_iack();
+ do_IRQ(i8259_irq, regs);
+ } else
+ do_IRQ(nile4_to_irq(nile4_irq), regs);
+
+ }
+}
+
+void ddb_local1_irqdispatch(void)
+{
+ printk("ddb_local1_irqdispatch called\n");
+}
+
+void ddb_buserror_irq(void)
+{
+ printk("ddb_buserror_irq called\n");
+}
+
+void ddb_8254timer_irq(void)
+{
+ printk("ddb_8254timer_irq called\n");
+}
+
+void __init arch_init_irq(void)
+{
+ /* setup cascade interrupts */
+ setup_irq(NILE4_IRQ_BASE + NILE4_INT_INTE, &irq_cascade);
+ setup_irq(CPU_IRQ_BASE + CPU_NILE4_CASCADE, &irq_cascade);
+
+ set_except_vector(0, ddbIRQ);
+
+ nile4_irq_setup(NILE4_IRQ_BASE);
+ m1543_irq_setup();
+ init_i8259_irqs();
+
+
+ printk("CPU_IRQ_BASE: %d\n",CPU_IRQ_BASE);
+
+ mips_cpu_irq_init(CPU_IRQ_BASE);
+
+ printk("enabling 8259 cascade\n");
+
+ ddb5074_led_hex(0);
+
+ /* Enable the interrupt cascade */
+ nile4_enable_irq(NILE4_IRQ_BASE+IRQ_I8259_CASCADE);
+}
diff --git a/arch/mips/ddb5xxx/ddb5074/nile4_pic.c b/arch/mips/ddb5xxx/ddb5074/nile4_pic.c
new file mode 100644
index 0000000..68c127c
--- /dev/null
+++ b/arch/mips/ddb5xxx/ddb5074/nile4_pic.c
@@ -0,0 +1,287 @@
+/*
+ * arch/mips/ddb5476/nile4.c --
+ * low-level PIC code for NEC Vrc-5476 (Nile 4)
+ *
+ * Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
+ * Sony Software Development Center Europe (SDCE), Brussels
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: jsun@mvista.com or jsun@junsun.net
+ *
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+
+#include <asm/addrspace.h>
+
+#include <asm/ddb5xxx/ddb5xxx.h>
+
+static int irq_base;
+
+/*
+ * Interrupt Programming
+ */
+void nile4_map_irq(int nile4_irq, int cpu_irq)
+{
+ u32 offset, t;
+
+ offset = DDB_INTCTRL;
+ if (nile4_irq >= 8) {
+ offset += 4;
+ nile4_irq -= 8;
+ }
+ t = ddb_in32(offset);
+ t &= ~(7 << (nile4_irq * 4));
+ t |= cpu_irq << (nile4_irq * 4);
+ ddb_out32(offset, t);
+}
+
+void nile4_map_irq_all(int cpu_irq)
+{
+ u32 all, t;
+
+ all = cpu_irq;
+ all |= all << 4;
+ all |= all << 8;
+ all |= all << 16;
+ t = ddb_in32(DDB_INTCTRL);
+ t &= 0x88888888;
+ t |= all;
+ ddb_out32(DDB_INTCTRL, t);
+ t = ddb_in32(DDB_INTCTRL + 4);
+ t &= 0x88888888;
+ t |= all;
+ ddb_out32(DDB_INTCTRL + 4, t);
+}
+
+void nile4_enable_irq(unsigned int nile4_irq)
+{
+ u32 offset, t;
+
+ nile4_irq-=irq_base;
+
+ ddb5074_led_hex(8);
+
+ offset = DDB_INTCTRL;
+ if (nile4_irq >= 8) {
+ offset += 4;
+ nile4_irq -= 8;
+ }
+ ddb5074_led_hex(9);
+ t = ddb_in32(offset);
+ ddb5074_led_hex(0xa);
+ t |= 8 << (nile4_irq * 4);
+ ddb_out32(offset, t);
+ ddb5074_led_hex(0xb);
+}
+
+void nile4_disable_irq(unsigned int nile4_irq)
+{
+ u32 offset, t;
+
+ nile4_irq-=irq_base;
+
+ offset = DDB_INTCTRL;
+ if (nile4_irq >= 8) {
+ offset += 4;
+ nile4_irq -= 8;
+ }
+ t = ddb_in32(offset);
+ t &= ~(8 << (nile4_irq * 4));
+ ddb_out32(offset, t);
+}
+
+void nile4_disable_irq_all(void)
+{
+ ddb_out32(DDB_INTCTRL, 0);
+ ddb_out32(DDB_INTCTRL + 4, 0);
+}
+
+u16 nile4_get_irq_stat(int cpu_irq)
+{
+ return ddb_in16(DDB_INTSTAT0 + cpu_irq * 2);
+}
+
+void nile4_enable_irq_output(int cpu_irq)
+{
+ u32 t;
+
+ t = ddb_in32(DDB_INTSTAT1 + 4);
+ t |= 1 << (16 + cpu_irq);
+ ddb_out32(DDB_INTSTAT1, t);
+}
+
+void nile4_disable_irq_output(int cpu_irq)
+{
+ u32 t;
+
+ t = ddb_in32(DDB_INTSTAT1 + 4);
+ t &= ~(1 << (16 + cpu_irq));
+ ddb_out32(DDB_INTSTAT1, t);
+}
+
+void nile4_set_pci_irq_polarity(int pci_irq, int high)
+{
+ u32 t;
+
+ t = ddb_in32(DDB_INTPPES);
+ if (high)
+ t &= ~(1 << (pci_irq * 2));
+ else
+ t |= 1 << (pci_irq * 2);
+ ddb_out32(DDB_INTPPES, t);
+}
+
+void nile4_set_pci_irq_level_or_edge(int pci_irq, int level)
+{
+ u32 t;
+
+ t = ddb_in32(DDB_INTPPES);
+ if (level)
+ t |= 2 << (pci_irq * 2);
+ else
+ t &= ~(2 << (pci_irq * 2));
+ ddb_out32(DDB_INTPPES, t);
+}
+
+void nile4_clear_irq(int nile4_irq)
+{
+ nile4_irq-=irq_base;
+ ddb_out32(DDB_INTCLR, 1 << nile4_irq);
+}
+
+void nile4_clear_irq_mask(u32 mask)
+{
+ ddb_out32(DDB_INTCLR, mask);
+}
+
+u8 nile4_i8259_iack(void)
+{
+ u8 irq;
+ u32 reg;
+
+ /* Set window 0 for interrupt acknowledge */
+ reg = ddb_in32(DDB_PCIINIT0);
+
+ ddb_set_pmr(DDB_PCIINIT0, DDB_PCICMD_IACK, 0, DDB_PCI_ACCESS_32);
+ irq = *(volatile u8 *) KSEG1ADDR(DDB_PCI_IACK_BASE);
+ /* restore window 0 for PCI I/O space */
+ // ddb_set_pmr(DDB_PCIINIT0, DDB_PCICMD_IO, 0, DDB_PCI_ACCESS_32);
+ ddb_out32(DDB_PCIINIT0, reg);
+
+ /* i8269.c set the base vector to be 0x0 */
+ return irq ;
+}
+
+static unsigned int nile4_irq_startup(unsigned int irq) {
+
+ nile4_enable_irq(irq);
+ return 0;
+
+}
+
+static void nile4_ack_irq(unsigned int irq) {
+
+ ddb5074_led_hex(4);
+
+ nile4_clear_irq(irq);
+ ddb5074_led_hex(2);
+ nile4_disable_irq(irq);
+
+ ddb5074_led_hex(0);
+}
+
+static void nile4_irq_end(unsigned int irq) {
+
+ ddb5074_led_hex(3);
+ if(!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
+ ddb5074_led_hex(5);
+ nile4_enable_irq(irq);
+ ddb5074_led_hex(7);
+ }
+
+ ddb5074_led_hex(1);
+}
+
+#define nile4_irq_shutdown nile4_disable_irq
+
+static hw_irq_controller nile4_irq_controller = {
+ "nile4",
+ nile4_irq_startup,
+ nile4_irq_shutdown,
+ nile4_enable_irq,
+ nile4_disable_irq,
+ nile4_ack_irq,
+ nile4_irq_end,
+ NULL
+};
+
+void nile4_irq_setup(u32 base) {
+
+ int i;
+
+ irq_base=base;
+
+ /* Map all interrupts to CPU int #0 */
+ nile4_map_irq_all(0);
+
+ /* PCI INTA#-E# must be level triggered */
+ nile4_set_pci_irq_level_or_edge(0, 1);
+ nile4_set_pci_irq_level_or_edge(1, 1);
+ nile4_set_pci_irq_level_or_edge(2, 1);
+ nile4_set_pci_irq_level_or_edge(3, 1);
+ nile4_set_pci_irq_level_or_edge(4, 1);
+
+ /* PCI INTA#-D# must be active low, INTE# must be active high */
+ nile4_set_pci_irq_polarity(0, 0);
+ nile4_set_pci_irq_polarity(1, 0);
+ nile4_set_pci_irq_polarity(2, 0);
+ nile4_set_pci_irq_polarity(3, 0);
+ nile4_set_pci_irq_polarity(4, 1);
+
+
+ for (i = 0; i < 16; i++) {
+ nile4_clear_irq(i);
+ nile4_disable_irq(i);
+ }
+
+ /* Enable CPU int #0 */
+ nile4_enable_irq_output(0);
+
+ for (i= base; i< base + NUM_NILE4_INTERRUPTS; i++) {
+ irq_desc[i].status = IRQ_DISABLED;
+ irq_desc[i].action = NULL;
+ irq_desc[i].depth = 1;
+ irq_desc[i].handler = &nile4_irq_controller;
+ }
+}
+
+#if defined(CONFIG_RUNTIME_DEBUG)
+void nile4_dump_irq_status(void)
+{
+ printk(KERN_DEBUG "
+ CPUSTAT = %p:%p\n", (void *) ddb_in32(DDB_CPUSTAT + 4),
+ (void *) ddb_in32(DDB_CPUSTAT));
+ printk(KERN_DEBUG "
+ INTCTRL = %p:%p\n", (void *) ddb_in32(DDB_INTCTRL + 4),
+ (void *) ddb_in32(DDB_INTCTRL));
+ printk(KERN_DEBUG
+ "INTSTAT0 = %p:%p\n",
+ (void *) ddb_in32(DDB_INTSTAT0 + 4),
+ (void *) ddb_in32(DDB_INTSTAT0));
+ printk(KERN_DEBUG
+ "INTSTAT1 = %p:%p\n",
+ (void *) ddb_in32(DDB_INTSTAT1 + 4),
+ (void *) ddb_in32(DDB_INTSTAT1));
+ printk(KERN_DEBUG
+ "INTCLR = %p:%p\n", (void *) ddb_in32(DDB_INTCLR + 4),
+ (void *) ddb_in32(DDB_INTCLR));
+ printk(KERN_DEBUG
+ "INTPPES = %p:%p\n", (void *) ddb_in32(DDB_INTPPES + 4),
+ (void *) ddb_in32(DDB_INTPPES));
+}
+
+#endif
diff --git a/arch/mips/ddb5xxx/ddb5074/setup.c b/arch/mips/ddb5xxx/ddb5074/setup.c
new file mode 100644
index 0000000..a73a597
--- /dev/null
+++ b/arch/mips/ddb5xxx/ddb5074/setup.c
@@ -0,0 +1,235 @@
+/*
+ * arch/mips/ddb5074/setup.c -- NEC DDB Vrc-5074 setup routines
+ *
+ * Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
+ * Sony Software Development Center Europe (SDCE), Brussels
+ */
+#include <linux/init.h>
+#include <linux/kbd_ll.h>
+#include <linux/kernel.h>
+#include <linux/kdev_t.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/pci.h>
+#include <linux/ide.h>
+#include <linux/ioport.h>
+#include <linux/irq.h>
+
+#include <asm/addrspace.h>
+#include <asm/bcache.h>
+#include <asm/irq.h>
+#include <asm/reboot.h>
+#include <asm/gdb-stub.h>
+#include <asm/time.h>
+#include <asm/nile4.h>
+#include <asm/ddb5xxx/ddb5074.h>
+#include <asm/ddb5xxx/ddb5xxx.h>
+
+static void (*back_to_prom) (void) = (void (*)(void)) 0xbfc00000;
+
+static void ddb_machine_restart(char *command)
+{
+ u32 t;
+
+ /* PCI cold reset */
+ t = nile4_in32(NILE4_PCICTRL + 4);
+ t |= 0x40000000;
+ nile4_out32(NILE4_PCICTRL + 4, t);
+ /* CPU cold reset */
+ t = nile4_in32(NILE4_CPUSTAT);
+ t |= 1;
+ nile4_out32(NILE4_CPUSTAT, t);
+ /* Call the PROM */
+ back_to_prom();
+}
+
+static void ddb_machine_halt(void)
+{
+ printk("DDB Vrc-5074 halted.\n");
+ do {
+ } while (1);
+}
+
+static void ddb_machine_power_off(void)
+{
+ printk("DDB Vrc-5074 halted. Please turn off the power.\n");
+ do {
+ } while (1);
+}
+
+extern void rtc_ds1386_init(unsigned long base);
+
+extern void (*board_timer_setup) (struct irqaction * irq);
+
+static void __init ddb_timer_init(struct irqaction *irq)
+{
+ /* set the clock to 1 Hz */
+ nile4_out32(NILE4_T2CTRL, 1000000);
+ /* enable the General-Purpose Timer */
+ nile4_out32(NILE4_T2CTRL + 4, 0x00000001);
+ /* reset timer */
+ nile4_out32(NILE4_T2CNTR, 0);
+ /* enable interrupt */
+ setup_irq(nile4_to_irq(NILE4_INT_GPT), irq);
+ nile4_enable_irq(nile4_to_irq(NILE4_INT_GPT));
+ change_c0_status(ST0_IM,
+ IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4);
+
+}
+
+static void __init ddb_time_init(void)
+{
+ /* we have ds1396 RTC chip */
+ rtc_ds1386_init(KSEG1ADDR(DDB_PCI_MEM_BASE));
+}
+
+
+
+static void __init ddb5074_setup(void)
+{
+ set_io_port_base(NILE4_PCI_IO_BASE);
+ isa_slot_offset = NILE4_PCI_MEM_BASE;
+ board_timer_setup = ddb_timer_init;
+ board_time_init = ddb_time_init;
+
+
+ _machine_restart = ddb_machine_restart;
+ _machine_halt = ddb_machine_halt;
+ _machine_power_off = ddb_machine_power_off;
+
+ ddb_out32(DDB_BAR0, 0);
+
+ ddb_set_pmr(DDB_PCIINIT0, DDB_PCICMD_IO, 0, 0x10);
+ ddb_set_pmr(DDB_PCIINIT1, DDB_PCICMD_MEM, DDB_PCI_MEM_BASE , 0x10);
+
+ /* Reboot on panic */
+ panic_timeout = 180;
+}
+
+early_initcall(ddb5074_setup);
+
+#define USE_NILE4_SERIAL 0
+
+#if USE_NILE4_SERIAL
+#define ns16550_in(reg) nile4_in8((reg)*8)
+#define ns16550_out(reg, val) nile4_out8((reg)*8, (val))
+#else
+#define NS16550_BASE (NILE4_PCI_IO_BASE+0x03f8)
+static inline u8 ns16550_in(u32 reg)
+{
+ return *(volatile u8 *) (NS16550_BASE + reg);
+}
+
+static inline void ns16550_out(u32 reg, u8 val)
+{
+ *(volatile u8 *) (NS16550_BASE + reg) = val;
+}
+#endif
+
+#define NS16550_RBR 0
+#define NS16550_THR 0
+#define NS16550_DLL 0
+#define NS16550_IER 1
+#define NS16550_DLM 1
+#define NS16550_FCR 2
+#define NS16550_IIR 2
+#define NS16550_LCR 3
+#define NS16550_MCR 4
+#define NS16550_LSR 5
+#define NS16550_MSR 6
+#define NS16550_SCR 7
+
+#define NS16550_LSR_DR 0x01 /* Data ready */
+#define NS16550_LSR_OE 0x02 /* Overrun */
+#define NS16550_LSR_PE 0x04 /* Parity error */
+#define NS16550_LSR_FE 0x08 /* Framing error */
+#define NS16550_LSR_BI 0x10 /* Break */
+#define NS16550_LSR_THRE 0x20 /* Xmit holding register empty */
+#define NS16550_LSR_TEMT 0x40 /* Xmitter empty */
+#define NS16550_LSR_ERR 0x80 /* Error */
+
+
+void _serinit(void)
+{
+#if USE_NILE4_SERIAL
+ ns16550_out(NS16550_LCR, 0x80);
+ ns16550_out(NS16550_DLM, 0x00);
+ ns16550_out(NS16550_DLL, 0x36); /* 9600 baud */
+ ns16550_out(NS16550_LCR, 0x00);
+ ns16550_out(NS16550_LCR, 0x03);
+ ns16550_out(NS16550_FCR, 0x47);
+#else
+ /* done by PMON */
+#endif
+}
+
+void _putc(char c)
+{
+ while (!(ns16550_in(NS16550_LSR) & NS16550_LSR_THRE));
+ ns16550_out(NS16550_THR, c);
+ if (c == '\n') {
+ while (!(ns16550_in(NS16550_LSR) & NS16550_LSR_THRE));
+ ns16550_out(NS16550_THR, '\r');
+ }
+}
+
+void _puts(const char *s)
+{
+ char c;
+ while ((c = *s++))
+ _putc(c);
+}
+
+char _getc(void)
+{
+ while (!(ns16550_in(NS16550_LSR) & NS16550_LSR_DR));
+ return ns16550_in(NS16550_RBR);
+}
+
+int _testc(void)
+{
+ return (ns16550_in(NS16550_LSR) & NS16550_LSR_DR) != 0;
+}
+
+
+/*
+ * Hexadecimal 7-segment LED
+ */
+void ddb5074_led_hex(int hex)
+{
+ outb(hex, 0x80);
+}
+
+
+/*
+ * LEDs D2 and D3, connected to the GPIO pins of the PMU in the ALi M1543
+ */
+struct pci_dev *pci_pmu = NULL;
+
+void ddb5074_led_d2(int on)
+{
+ u8 t;
+
+ if (pci_pmu) {
+ pci_read_config_byte(pci_pmu, 0x7e, &t);
+ if (on)
+ t &= 0x7f;
+ else
+ t |= 0x80;
+ pci_write_config_byte(pci_pmu, 0x7e, t);
+ }
+}
+
+void ddb5074_led_d3(int on)
+{
+ u8 t;
+
+ if (pci_pmu) {
+ pci_read_config_byte(pci_pmu, 0x7e, &t);
+ if (on)
+ t &= 0xbf;
+ else
+ t |= 0x40;
+ pci_write_config_byte(pci_pmu, 0x7e, t);
+ }
+}
diff --git a/arch/mips/ddb5xxx/ddb5476/Makefile b/arch/mips/ddb5xxx/ddb5476/Makefile
new file mode 100644
index 0000000..61eec36
--- /dev/null
+++ b/arch/mips/ddb5xxx/ddb5476/Makefile
@@ -0,0 +1,9 @@
+#
+# Makefile for the NEC DDB Vrc-5476 specific kernel interface routines
+# under Linux.
+#
+
+obj-y += setup.o irq.o int-handler.o nile4_pic.o vrc5476_irq.o
+obj-$(CONFIG_KGDB) += dbg_io.o
+
+EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/ddb5xxx/ddb5476/dbg_io.c b/arch/mips/ddb5xxx/ddb5476/dbg_io.c
new file mode 100644
index 0000000..85e9e50
--- /dev/null
+++ b/arch/mips/ddb5xxx/ddb5476/dbg_io.c
@@ -0,0 +1,136 @@
+/*
+ * kgdb io functions for DDB5476. We use the second serial port.
+ *
+ * Copyright (C) 2001 MontaVista Software Inc.
+ * Author: jsun@mvista.com or jsun@junsun.net
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+
+/* ======================= CONFIG ======================== */
+
+/* [jsun] we use the second serial port for kdb */
+#define BASE 0xa60002f8
+#define MAX_BAUD 115200
+
+/* distance in bytes between two serial registers */
+#define REG_OFFSET 1
+
+/*
+ * 0 - kgdb does serial init
+ * 1 - kgdb skip serial init
+ */
+static int remoteDebugInitialized = 0;
+
+/*
+ * the default baud rate *if* kgdb does serial init
+ */
+#define BAUD_DEFAULT UART16550_BAUD_38400
+
+/* ======================= END OF CONFIG ======================== */
+
+typedef unsigned char uint8;
+typedef unsigned int uint32;
+
+#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
+
+/* register offset */
+#define OFS_RCV_BUFFER 0
+#define OFS_TRANS_HOLD 0
+#define OFS_SEND_BUFFER 0
+#define OFS_INTR_ENABLE (1*REG_OFFSET)
+#define OFS_INTR_ID (2*REG_OFFSET)
+#define OFS_DATA_FORMAT (3*REG_OFFSET)
+#define OFS_LINE_CONTROL (3*REG_OFFSET)
+#define OFS_MODEM_CONTROL (4*REG_OFFSET)
+#define OFS_RS232_OUTPUT (4*REG_OFFSET)
+#define OFS_LINE_STATUS (5*REG_OFFSET)
+#define OFS_MODEM_STATUS (6*REG_OFFSET)
+#define OFS_RS232_INPUT (6*REG_OFFSET)
+#define OFS_SCRATCH_PAD (7*REG_OFFSET)
+
+#define OFS_DIVISOR_LSB (0*REG_OFFSET)
+#define OFS_DIVISOR_MSB (1*REG_OFFSET)
+
+
+/* memory-mapped read/write of the port */
+#define UART16550_READ(y) (*((volatile uint8*)(BASE + y)))
+#define UART16550_WRITE(y, z) ((*((volatile uint8*)(BASE + y))) = z)
+
+void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop)
+{
+ /* disable interrupts */
+ UART16550_WRITE(OFS_INTR_ENABLE, 0);
+
+ /* set up buad rate */
+ {
+ uint32 divisor;
+
+ /* set DIAB bit */
+ UART16550_WRITE(OFS_LINE_CONTROL, 0x80);
+
+ /* set divisor */
+ divisor = MAX_BAUD / baud;
+ UART16550_WRITE(OFS_DIVISOR_LSB, divisor & 0xff);
+ UART16550_WRITE(OFS_DIVISOR_MSB, (divisor & 0xff00) >> 8);
+
+ /* clear DIAB bit */
+ UART16550_WRITE(OFS_LINE_CONTROL, 0x0);
+ }
+
+ /* set data format */
+ UART16550_WRITE(OFS_DATA_FORMAT, data | parity | stop);
+}
+
+
+uint8 getDebugChar(void)
+{
+ if (!remoteDebugInitialized) {
+ remoteDebugInitialized = 1;
+ debugInit(BAUD_DEFAULT,
+ UART16550_DATA_8BIT,
+ UART16550_PARITY_NONE, UART16550_STOP_1BIT);
+ }
+
+ while ((UART16550_READ(OFS_LINE_STATUS) & 0x1) == 0);
+ return UART16550_READ(OFS_RCV_BUFFER);
+}
+
+
+int putDebugChar(uint8 byte)
+{
+ if (!remoteDebugInitialized) {
+ remoteDebugInitialized = 1;
+ debugInit(BAUD_DEFAULT,
+ UART16550_DATA_8BIT,
+ UART16550_PARITY_NONE, UART16550_STOP_1BIT);
+ }
+
+ while ((UART16550_READ(OFS_LINE_STATUS) & 0x20) == 0);
+ UART16550_WRITE(OFS_SEND_BUFFER, byte);
+ return 1;
+}
diff --git a/arch/mips/ddb5xxx/ddb5476/int-handler.S b/arch/mips/ddb5xxx/ddb5476/int-handler.S
new file mode 100644
index 0000000..12c292e
--- /dev/null
+++ b/arch/mips/ddb5xxx/ddb5476/int-handler.S
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: jsun@mvista.com or jsun@junsun.net
+ *
+ * First-level interrupt dispatcher for ddb5476
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+#include <asm/asm.h>
+#include <asm/mipsregs.h>
+#include <asm/addrspace.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+
+#include <asm/ddb5xxx/ddb5476.h>
+
+/*
+ * first level interrupt dispatcher for ocelot board -
+ * We check for the timer first, then check PCI ints A and D.
+ * Then check for serial IRQ and fall through.
+ */
+ .align 5
+ NESTED(ddb5476_handle_int, PT_SIZE, sp)
+ SAVE_ALL
+ CLI
+ .set at
+ .set noreorder
+ mfc0 t0, CP0_CAUSE
+ mfc0 t2, CP0_STATUS
+
+ and t0, t2
+
+ andi t1, t0, STATUSF_IP7 /* cpu timer */
+ bnez t1, ll_cpu_ip7
+ andi t1, t0, STATUSF_IP2 /* vrc5476 & i8259 */
+ bnez t1, ll_cpu_ip2
+ andi t1, t0, STATUSF_IP3
+ bnez t1, ll_cpu_ip3
+ andi t1, t0, STATUSF_IP4
+ bnez t1, ll_cpu_ip4
+ andi t1, t0, STATUSF_IP5
+ bnez t1, ll_cpu_ip5
+ andi t1, t0, STATUSF_IP6
+ bnez t1, ll_cpu_ip6
+ andi t1, t0, STATUSF_IP0 /* software int 0 */
+ bnez t1, ll_cpu_ip0
+ andi t1, t0, STATUSF_IP1 /* software int 1 */
+ bnez t1, ll_cpu_ip1
+ nop
+
+ .set reorder
+
+ /* wrong alarm or masked ... */
+ // j spurious_interrupt
+ move a0, sp
+ jal vrc5476_irq_dispatch
+ j ret_from_irq
+ nop
+
+ .align 5
+
+ll_cpu_ip0:
+ li a0, CPU_IRQ_BASE + 0
+ move a1, sp
+ jal do_IRQ
+ j ret_from_irq
+
+ll_cpu_ip1:
+ li a0, CPU_IRQ_BASE + 1
+ move a1, sp
+ jal do_IRQ
+ j ret_from_irq
+
+ll_cpu_ip2: /* jump to second-level dispatching */
+ move a0, sp
+ jal vrc5476_irq_dispatch
+ j ret_from_irq
+
+ll_cpu_ip3:
+ li a0, CPU_IRQ_BASE + 3
+ move a1, sp
+ jal do_IRQ
+ j ret_from_irq
+
+ll_cpu_ip4:
+ li a0, CPU_IRQ_BASE + 4
+ move a1, sp
+ jal do_IRQ
+ j ret_from_irq
+
+ll_cpu_ip5:
+ li a0, CPU_IRQ_BASE + 5
+ move a1, sp
+ jal do_IRQ
+ j ret_from_irq
+
+ll_cpu_ip6:
+ li a0, CPU_IRQ_BASE + 6
+ move a1, sp
+ jal do_IRQ
+ j ret_from_irq
+
+ll_cpu_ip7:
+ li a0, CPU_IRQ_BASE + 7
+ move a1, sp
+ jal do_IRQ
+ j ret_from_irq
+
+ END(ddb5476_handle_int)
diff --git a/arch/mips/ddb5xxx/ddb5476/irq.c b/arch/mips/ddb5xxx/ddb5476/irq.c
new file mode 100644
index 0000000..5388b58
--- /dev/null
+++ b/arch/mips/ddb5xxx/ddb5476/irq.c
@@ -0,0 +1,143 @@
+/*
+ * arch/mips/ddb5476/irq.c -- NEC DDB Vrc-5476 interrupt routines
+ *
+ * Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
+ * Sony Software Development Center Europe (SDCE), Brussels
+ *
+ * Re-write the whole thing to use new irq.c file.
+ * Copyright (C) 2001 MontaVista Software Inc.
+ * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
+ *
+ */
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+
+#include <asm/i8259.h>
+#include <asm/io.h>
+#include <asm/ptrace.h>
+
+#include <asm/ddb5xxx/ddb5xxx.h>
+
+#define M1543_PNP_CONFIG 0x03f0 /* PnP Config Port */
+#define M1543_PNP_INDEX 0x03f0 /* PnP Index Port */
+#define M1543_PNP_DATA 0x03f1 /* PnP Data Port */
+
+#define M1543_PNP_ALT_CONFIG 0x0370 /* Alternative PnP Config Port */
+#define M1543_PNP_ALT_INDEX 0x0370 /* Alternative PnP Index Port */
+#define M1543_PNP_ALT_DATA 0x0371 /* Alternative PnP Data Port */
+
+#define M1543_INT1_MASTER_CTRL 0x0020 /* INT_1 (master) Control Register */
+#define M1543_INT1_MASTER_MASK 0x0021 /* INT_1 (master) Mask Register */
+
+#define M1543_INT1_SLAVE_CTRL 0x00a0 /* INT_1 (slave) Control Register */
+#define M1543_INT1_SLAVE_MASK 0x00a1 /* INT_1 (slave) Mask Register */
+
+#define M1543_INT1_MASTER_ELCR 0x04d0 /* INT_1 (master) Edge/Level Control */
+#define M1543_INT1_SLAVE_ELCR 0x04d1 /* INT_1 (slave) Edge/Level Control */
+
+static void m1543_irq_setup(void)
+{
+ /*
+ * The ALI M1543 has 13 interrupt inputs, IRQ1..IRQ13. Not all
+ * the possible IO sources in the M1543 are in use by us. We will
+ * use the following mapping:
+ *
+ * IRQ1 - keyboard (default set by M1543)
+ * IRQ3 - reserved for UART B (default set by M1543) (note that
+ * the schematics for the DDB Vrc-5476 board seem to
+ * indicate that IRQ3 is connected to the DS1386
+ * watchdog timer interrupt output so we might have
+ * a conflict)
+ * IRQ4 - reserved for UART A (default set by M1543)
+ * IRQ5 - parallel (default set by M1543)
+ * IRQ8 - DS1386 time of day (RTC) interrupt
+ * IRQ9 - USB (hardwired in ddb_setup)
+ * IRQ10 - PMU (hardwired in ddb_setup)
+ * IRQ12 - mouse
+ * IRQ14,15 - IDE controller (need to be confirmed, jsun)
+ */
+
+ /*
+ * Assing mouse interrupt to IRQ12
+ */
+
+ /* Enter configuration mode */
+ outb(0x51, M1543_PNP_CONFIG);
+ outb(0x23, M1543_PNP_CONFIG);
+
+ /* Select logical device 7 (Keyboard) */
+ outb(0x07, M1543_PNP_INDEX);
+ outb(0x07, M1543_PNP_DATA);
+
+ /* Select IRQ12 */
+ outb(0x72, M1543_PNP_INDEX);
+ outb(0x0c, M1543_PNP_DATA);
+
+ /* Leave configration mode */
+ outb(0xbb, M1543_PNP_CONFIG);
+}
+
+static void nile4_irq_setup(void)
+{
+ int i;
+
+ /* Map all interrupts to CPU int #0 (IP2) */
+ nile4_map_irq_all(0);
+
+ /* PCI INTA#-E# must be level triggered */
+ nile4_set_pci_irq_level_or_edge(0, 1);
+ nile4_set_pci_irq_level_or_edge(1, 1);
+ nile4_set_pci_irq_level_or_edge(2, 1);
+ nile4_set_pci_irq_level_or_edge(3, 1);
+
+ /* PCI INTA#, B#, D# must be active low, INTC# must be active high */
+ nile4_set_pci_irq_polarity(0, 0);
+ nile4_set_pci_irq_polarity(1, 0);
+ nile4_set_pci_irq_polarity(2, 1);
+ nile4_set_pci_irq_polarity(3, 0);
+
+ for (i = 0; i < 16; i++)
+ nile4_clear_irq(i);
+
+ /* Enable CPU int #0 */
+ nile4_enable_irq_output(0);
+
+ /* memory resource acquire in ddb_setup */
+}
+
+static struct irqaction irq_cascade = { no_action, 0, CPU_MASK_NONE, "cascade", NULL, NULL };
+static struct irqaction irq_error = { no_action, 0, CPU_MASK_NONE, "error", NULL, NULL };
+
+extern asmlinkage void ddb5476_handle_int(void);
+extern int setup_irq(unsigned int irq, struct irqaction *irqaction);
+extern void mips_cpu_irq_init(u32 irq_base);
+extern void vrc5476_irq_init(u32 irq_base);
+
+void __init arch_init_irq(void)
+{
+ /* hardware initialization */
+ nile4_irq_setup();
+ m1543_irq_setup();
+
+ /* controller setup */
+ init_i8259_irqs();
+ vrc5476_irq_init(VRC5476_IRQ_BASE);
+ mips_cpu_irq_init(CPU_IRQ_BASE);
+
+ /* setup cascade interrupts */
+ setup_irq(VRC5476_IRQ_BASE + VRC5476_I8259_CASCADE, &irq_cascade);
+ setup_irq(CPU_IRQ_BASE + CPU_VRC5476_CASCADE, &irq_cascade);
+
+ /* setup error interrupts for debugging */
+ setup_irq(VRC5476_IRQ_BASE + VRC5476_IRQ_CPCE, &irq_error);
+ setup_irq(VRC5476_IRQ_BASE + VRC5476_IRQ_CNTD, &irq_error);
+ setup_irq(VRC5476_IRQ_BASE + VRC5476_IRQ_MCE, &irq_error);
+ setup_irq(VRC5476_IRQ_BASE + VRC5476_IRQ_LBRT, &irq_error);
+ setup_irq(VRC5476_IRQ_BASE + VRC5476_IRQ_PCIS, &irq_error);
+ setup_irq(VRC5476_IRQ_BASE + VRC5476_IRQ_PCI, &irq_error);
+
+ /* setup the grandpa intr vector */
+ set_except_vector(0, ddb5476_handle_int);
+}
diff --git a/arch/mips/ddb5xxx/ddb5476/nile4_pic.c b/arch/mips/ddb5xxx/ddb5476/nile4_pic.c
new file mode 100644
index 0000000..e930cee
--- /dev/null
+++ b/arch/mips/ddb5xxx/ddb5476/nile4_pic.c
@@ -0,0 +1,190 @@
+/*
+ * arch/mips/ddb5476/nile4.c --
+ * low-level PIC code for NEC Vrc-5476 (Nile 4)
+ *
+ * Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
+ * Sony Software Development Center Europe (SDCE), Brussels
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: jsun@mvista.com or jsun@junsun.net
+ *
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+
+#include <asm/addrspace.h>
+
+#include <asm/ddb5xxx/ddb5xxx.h>
+
+
+/*
+ * Interrupt Programming
+ */
+void nile4_map_irq(int nile4_irq, int cpu_irq)
+{
+ u32 offset, t;
+
+ offset = DDB_INTCTRL;
+ if (nile4_irq >= 8) {
+ offset += 4;
+ nile4_irq -= 8;
+ }
+ t = ddb_in32(offset);
+ t &= ~(7 << (nile4_irq * 4));
+ t |= cpu_irq << (nile4_irq * 4);
+ ddb_out32(offset, t);
+}
+
+void nile4_map_irq_all(int cpu_irq)
+{
+ u32 all, t;
+
+ all = cpu_irq;
+ all |= all << 4;
+ all |= all << 8;
+ all |= all << 16;
+ t = ddb_in32(DDB_INTCTRL);
+ t &= 0x88888888;
+ t |= all;
+ ddb_out32(DDB_INTCTRL, t);
+ t = ddb_in32(DDB_INTCTRL + 4);
+ t &= 0x88888888;
+ t |= all;
+ ddb_out32(DDB_INTCTRL + 4, t);
+}
+
+void nile4_enable_irq(int nile4_irq)
+{
+ u32 offset, t;
+
+ offset = DDB_INTCTRL;
+ if (nile4_irq >= 8) {
+ offset += 4;
+ nile4_irq -= 8;
+ }
+ t = ddb_in32(offset);
+ t |= 8 << (nile4_irq * 4);
+ ddb_out32(offset, t);
+}
+
+void nile4_disable_irq(int nile4_irq)
+{
+ u32 offset, t;
+
+ offset = DDB_INTCTRL;
+ if (nile4_irq >= 8) {
+ offset += 4;
+ nile4_irq -= 8;
+ }
+ t = ddb_in32(offset);
+ t &= ~(8 << (nile4_irq * 4));
+ ddb_out32(offset, t);
+}
+
+void nile4_disable_irq_all(void)
+{
+ ddb_out32(DDB_INTCTRL, 0);
+ ddb_out32(DDB_INTCTRL + 4, 0);
+}
+
+u16 nile4_get_irq_stat(int cpu_irq)
+{
+ return ddb_in16(DDB_INTSTAT0 + cpu_irq * 2);
+}
+
+void nile4_enable_irq_output(int cpu_irq)
+{
+ u32 t;
+
+ t = ddb_in32(DDB_INTSTAT1 + 4);
+ t |= 1 << (16 + cpu_irq);
+ ddb_out32(DDB_INTSTAT1, t);
+}
+
+void nile4_disable_irq_output(int cpu_irq)
+{
+ u32 t;
+
+ t = ddb_in32(DDB_INTSTAT1 + 4);
+ t &= ~(1 << (16 + cpu_irq));
+ ddb_out32(DDB_INTSTAT1, t);
+}
+
+void nile4_set_pci_irq_polarity(int pci_irq, int high)
+{
+ u32 t;
+
+ t = ddb_in32(DDB_INTPPES);
+ if (high)
+ t &= ~(1 << (pci_irq * 2));
+ else
+ t |= 1 << (pci_irq * 2);
+ ddb_out32(DDB_INTPPES, t);
+}
+
+void nile4_set_pci_irq_level_or_edge(int pci_irq, int level)
+{
+ u32 t;
+
+ t = ddb_in32(DDB_INTPPES);
+ if (level)
+ t |= 2 << (pci_irq * 2);
+ else
+ t &= ~(2 << (pci_irq * 2));
+ ddb_out32(DDB_INTPPES, t);
+}
+
+void nile4_clear_irq(int nile4_irq)
+{
+ ddb_out32(DDB_INTCLR, 1 << nile4_irq);
+}
+
+void nile4_clear_irq_mask(u32 mask)
+{
+ ddb_out32(DDB_INTCLR, mask);
+}
+
+u8 nile4_i8259_iack(void)
+{
+ u8 irq;
+ u32 reg;
+
+ /* Set window 0 for interrupt acknowledge */
+ reg = ddb_in32(DDB_PCIINIT0);
+
+ ddb_set_pmr(DDB_PCIINIT0, DDB_PCICMD_IACK, 0, DDB_PCI_ACCESS_32);
+ irq = *(volatile u8 *) KSEG1ADDR(DDB_PCI_IACK_BASE);
+ /* restore window 0 for PCI I/O space */
+ // ddb_set_pmr(DDB_PCIINIT0, DDB_PCICMD_IO, 0, DDB_PCI_ACCESS_32);
+ ddb_out32(DDB_PCIINIT0, reg);
+
+ /* i8269.c set the base vector to be 0x0 */
+ return irq + I8259_IRQ_BASE;
+}
+
+#if defined(CONFIG_RUNTIME_DEBUG)
+void nile4_dump_irq_status(void)
+{
+ printk(KERN_DEBUG "
+ CPUSTAT = %p:%p\n", (void *) ddb_in32(DDB_CPUSTAT + 4),
+ (void *) ddb_in32(DDB_CPUSTAT));
+ printk(KERN_DEBUG "
+ INTCTRL = %p:%p\n", (void *) ddb_in32(DDB_INTCTRL + 4),
+ (void *) ddb_in32(DDB_INTCTRL));
+ printk(KERN_DEBUG
+ "INTSTAT0 = %p:%p\n",
+ (void *) ddb_in32(DDB_INTSTAT0 + 4),
+ (void *) ddb_in32(DDB_INTSTAT0));
+ printk(KERN_DEBUG
+ "INTSTAT1 = %p:%p\n",
+ (void *) ddb_in32(DDB_INTSTAT1 + 4),
+ (void *) ddb_in32(DDB_INTSTAT1));
+ printk(KERN_DEBUG
+ "INTCLR = %p:%p\n", (void *) ddb_in32(DDB_INTCLR + 4),
+ (void *) ddb_in32(DDB_INTCLR));
+ printk(KERN_DEBUG
+ "INTPPES = %p:%p\n", (void *) ddb_in32(DDB_INTPPES + 4),
+ (void *) ddb_in32(DDB_INTPPES));
+}
+#endif
diff --git a/arch/mips/ddb5xxx/ddb5476/setup.c b/arch/mips/ddb5xxx/ddb5476/setup.c
new file mode 100644
index 0000000..71531f8
--- /dev/null
+++ b/arch/mips/ddb5xxx/ddb5476/setup.c
@@ -0,0 +1,297 @@
+/*
+ * arch/mips/ddb5476/setup.c -- NEC DDB Vrc-5476 setup routines
+ *
+ * Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
+ * Sony Software Development Center Europe (SDCE), Brussels
+ */
+#include <linux/init.h>
+#include <linux/kbd_ll.h>
+#include <linux/kernel.h>
+#include <linux/kdev_t.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/pci.h>
+
+#include <asm/addrspace.h>
+#include <asm/bcache.h>
+#include <asm/irq.h>
+#include <asm/reboot.h>
+#include <asm/gdb-stub.h>
+#include <asm/time.h>
+#include <asm/debug.h>
+#include <asm/traps.h>
+
+#include <asm/ddb5xxx/ddb5xxx.h>
+
+// #define USE_CPU_COUNTER_TIMER /* whether we use cpu counter */
+
+#ifdef USE_CPU_COUNTER_TIMER
+
+#define CPU_COUNTER_FREQUENCY 83000000
+#else
+/* otherwise we use general purpose timer */
+#define TIMER_FREQUENCY 83000000
+#define TIMER_BASE DDB_T2CTRL
+#define TIMER_IRQ (VRC5476_IRQ_BASE + VRC5476_IRQ_GPT)
+#endif
+
+static void (*back_to_prom) (void) = (void (*)(void)) 0xbfc00000;
+
+static void ddb_machine_restart(char *command)
+{
+ u32 t;
+
+ /* PCI cold reset */
+ t = ddb_in32(DDB_PCICTRL + 4);
+ t |= 0x40000000;
+ ddb_out32(DDB_PCICTRL + 4, t);
+ /* CPU cold reset */
+ t = ddb_in32(DDB_CPUSTAT);
+ t |= 1;
+ ddb_out32(DDB_CPUSTAT, t);
+ /* Call the PROM */
+ back_to_prom();
+}
+
+static void ddb_machine_halt(void)
+{
+ printk(KERN_NOTICE "DDB Vrc-5476 halted.\n");
+ while (1);
+}
+
+static void ddb_machine_power_off(void)
+{
+ printk(KERN_NOTICE "DDB Vrc-5476 halted. Please turn off the power.\n");
+ while (1);
+}
+
+extern void rtc_ds1386_init(unsigned long base);
+
+static void __init ddb_time_init(void)
+{
+#if defined(USE_CPU_COUNTER_TIMER)
+ mips_hpt_frequency = CPU_COUNTER_FREQUENCY;
+#endif
+
+ /* we have ds1396 RTC chip */
+ rtc_ds1386_init(KSEG1ADDR(DDB_PCI_MEM_BASE));
+}
+
+
+extern int setup_irq(unsigned int irq, struct irqaction *irqaction);
+static void __init ddb_timer_setup(struct irqaction *irq)
+{
+#if defined(USE_CPU_COUNTER_TIMER)
+
+ unsigned int count;
+
+ /* we are using the cpu counter for timer interrupts */
+ setup_irq(CPU_IRQ_BASE + 7, irq);
+
+ /* to generate the first timer interrupt */
+ count = read_c0_count();
+ write_c0_compare(count + 1000);
+
+#else
+
+ ddb_out32(TIMER_BASE, TIMER_FREQUENCY/HZ);
+ ddb_out32(TIMER_BASE+4, 0x1); /* enable timer */
+ setup_irq(TIMER_IRQ, irq);
+#endif
+}
+
+static struct {
+ struct resource dma1;
+ struct resource timer;
+ struct resource rtc;
+ struct resource dma_page_reg;
+ struct resource dma2;
+} ddb5476_ioport = {
+ {
+ "dma1", 0x00, 0x1f, IORESOURCE_BUSY}, {
+ "timer", 0x40, 0x5f, IORESOURCE_BUSY}, {
+ "rtc", 0x70, 0x7f, IORESOURCE_BUSY}, {
+ "dma page reg", 0x80, 0x8f, IORESOURCE_BUSY}, {
+ "dma2", 0xc0, 0xdf, IORESOURCE_BUSY}
+};
+
+static struct {
+ struct resource nile4;
+} ddb5476_iomem = {
+ { "Nile 4", DDB_BASE, DDB_BASE + DDB_SIZE - 1, IORESOURCE_BUSY}
+};
+
+
+static void ddb5476_board_init(void);
+
+static void __init ddb5476_setup(void)
+{
+ set_io_port_base(KSEG1ADDR(DDB_PCI_IO_BASE));
+
+ board_time_init = ddb_time_init;
+ board_timer_setup = ddb_timer_setup;
+
+ _machine_restart = ddb_machine_restart;
+ _machine_halt = ddb_machine_halt;
+ _machine_power_off = ddb_machine_power_off;
+
+ /* request io port/mem resources */
+ if (request_resource(&ioport_resource, &ddb5476_ioport.dma1) ||
+ request_resource(&ioport_resource, &ddb5476_ioport.timer) ||
+ request_resource(&ioport_resource, &ddb5476_ioport.rtc) ||
+ request_resource(&ioport_resource,
+ &ddb5476_ioport.dma_page_reg)
+ || request_resource(&ioport_resource, &ddb5476_ioport.dma2)
+ || request_resource(&iomem_resource, &ddb5476_iomem.nile4)) {
+ printk
+ ("ddb_setup - requesting oo port resources failed.\n");
+ for (;;);
+ }
+
+ /* Reboot on panic */
+ panic_timeout = 180;
+
+ /* [jsun] we need to set BAR0 so that SDRAM 0 appears at 0x0 in PCI */
+ /* *(long*)0xbfa00218 = 0x8; */
+
+ /* board initialization stuff */
+ ddb5476_board_init();
+}
+
+early_initcall(ddb5476_setup);
+
+/*
+ * We don't trust bios. We essentially does hardware re-initialization
+ * as complete as possible, as far as we know we can safely do.
+ */
+static void ddb5476_board_init(void)
+{
+ /* ----------- setup PDARs ------------ */
+ /* check SDRAM0, whether we are on MEM bus does not matter */
+ db_assert((ddb_in32(DDB_SDRAM0) & 0xffffffef) ==
+ ddb_calc_pdar(DDB_SDRAM_BASE, DDB_SDRAM_SIZE, 32, 0, 1));
+
+ /* SDRAM1 should be turned off. What is this for anyway ? */
+ db_assert( (ddb_in32(DDB_SDRAM1) & 0xf) == 0);
+
+ /* flash 1&2, DDB status, DDB control */
+ ddb_set_pdar(DDB_DCS2, DDB_DCS2_BASE, DDB_DCS2_SIZE, 16, 0, 0);
+ ddb_set_pdar(DDB_DCS3, DDB_DCS3_BASE, DDB_DCS3_SIZE, 16, 0, 0);
+ ddb_set_pdar(DDB_DCS4, DDB_DCS4_BASE, DDB_DCS4_SIZE, 8, 0, 0);
+ ddb_set_pdar(DDB_DCS5, DDB_DCS5_BASE, DDB_DCS5_SIZE, 8, 0, 0);
+
+ /* shut off other pdar so they don't accidentally get into the way */
+ ddb_set_pdar(DDB_DCS6, 0xffffffff, 0, 32, 0, 0);
+ ddb_set_pdar(DDB_DCS7, 0xffffffff, 0, 32, 0, 0);
+ ddb_set_pdar(DDB_DCS8, 0xffffffff, 0, 32, 0, 0);
+
+ /* verify VRC5477 base addr */
+ /* don't care about some details */
+ db_assert((ddb_in32(DDB_INTCS) & 0xffffff0f) ==
+ ddb_calc_pdar(DDB_INTCS_BASE, DDB_INTCS_SIZE, 8, 0, 0));
+
+ /* verify BOOT ROM addr */
+ /* don't care about some details */
+ db_assert((ddb_in32(DDB_BOOTCS) & 0xffffff0f) ==
+ ddb_calc_pdar(DDB_BOOTCS_BASE, DDB_BOOTCS_SIZE, 8, 0, 0));
+
+ /* setup PCI windows - window1 for MEM/config, window0 for IO */
+ ddb_set_pdar(DDB_PCIW0, DDB_PCI_IO_BASE, DDB_PCI_IO_SIZE, 32, 0, 1);
+ ddb_set_pmr(DDB_PCIINIT0, DDB_PCICMD_IO, 0, DDB_PCI_ACCESS_32);
+
+ ddb_set_pdar(DDB_PCIW1, DDB_PCI_MEM_BASE, DDB_PCI_MEM_SIZE, 32, 0, 1);
+ ddb_set_pmr(DDB_PCIINIT1, DDB_PCICMD_MEM, DDB_PCI_MEM_BASE, DDB_PCI_ACCESS_32);
+
+ /* ----------- setup PDARs ------------ */
+ /* this is problematic - it will reset Aladin which cause we loose
+ * serial port, and we don't know how to set up Aladin chip again.
+ */
+ // ddb_pci_reset_bus();
+
+ ddb_out32(DDB_BAR0, 0x00000008);
+
+ ddb_out32(DDB_BARC, 0xffffffff);
+ ddb_out32(DDB_BARB, 0xffffffff);
+ ddb_out32(DDB_BAR1, 0xffffffff);
+ ddb_out32(DDB_BAR2, 0xffffffff);
+ ddb_out32(DDB_BAR3, 0xffffffff);
+ ddb_out32(DDB_BAR4, 0xffffffff);
+ ddb_out32(DDB_BAR5, 0xffffffff);
+ ddb_out32(DDB_BAR6, 0xffffffff);
+ ddb_out32(DDB_BAR7, 0xffffffff);
+ ddb_out32(DDB_BAR8, 0xffffffff);
+
+ /* ----------- switch PCI1 to PCI CONFIG space ------------ */
+ ddb_set_pdar(DDB_PCIW1, DDB_PCI_CONFIG_BASE, DDB_PCI_CONFIG_SIZE, 32, 0, 1);
+ ddb_set_pmr(DDB_PCIINIT1, DDB_PCICMD_CFG, 0x0, DDB_PCI_ACCESS_32);
+
+ /* ----- M1543 PCI setup ------ */
+
+ /* we know M1543 PCI-ISA controller is at addr:18 */
+ /* xxxx1010 makes USB at addr:13 and PMU at addr:14 */
+ *(volatile unsigned char *) 0xa8040072 &= 0xf0;
+ *(volatile unsigned char *) 0xa8040072 |= 0xa;
+
+ /* setup USB interrupt to IRQ 9, (bit 0:3 - 0001)
+ * no IOCHRDY signal, (bit 7 - 1)
+ * M1543C & M7101 VID and Subsys Device ID are read-only (bit 6 - 1)
+ * Make USB Master INTAJ level to edge conversion (bit 4 - 1)
+ */
+ *(unsigned char *) 0xa8040074 = 0xd1;
+
+ /* setup PMU(SCI to IRQ 10 (bit 0:3 - 0011)
+ * SCI routing to IRQ 13 disabled (bit 7 - 1)
+ * SCI interrupt level to edge conversion bypassed (bit 4 - 0)
+ */
+ *(unsigned char *) 0xa8040076 = 0x83;
+
+ /* setup IDE controller
+ * enable IDE controller (bit 6 - 1)
+ * IDE IDSEL to be addr:24 (bit 4:5 - 11)
+ * no IDE ATA Secondary Bus Signal Pad Control (bit 3 - 0)
+ * no IDE ATA Primary Bus Signal Pad Control (bit 2 - 0)
+ * primary IRQ is 14, secondary is 15 (bit 1:0 - 01
+ */
+ // *(unsigned char*)0xa8040058 = 0x71;
+ // *(unsigned char*)0xa8040058 = 0x79;
+ // *(unsigned char*)0xa8040058 = 0x74; // use SIRQ, primary tri-state
+ *(unsigned char *) 0xa8040058 = 0x75; // primary tri-state
+
+#if 0
+ /* this is not necessary if M5229 does not use SIRQ */
+ *(unsigned char *) 0xa8040044 = 0x0d; // primary to IRQ 14
+ *(unsigned char *) 0xa8040075 = 0x0d; // secondary to IRQ 14
+#endif
+
+ /* enable IDE in the M5229 config register 0x50 (bit 0 - 1) */
+ /* M5229 IDSEL is addr:24; see above setting */
+ *(unsigned char *) 0xa9000050 |= 0x1;
+
+ /* enable bus master (bit 2) and IO decoding (bit 0) */
+ *(unsigned char *) 0xa9000004 |= 0x5;
+
+ /* enable native, copied from arch/ppc/k2boot/head.S */
+ /* TODO - need volatile, need to be portable */
+ *(unsigned char *) 0xa9000009 = 0xff;
+
+ /* ----- end of M1543 PCI setup ------ */
+
+ /* ----- reset on-board ether chip ------ */
+ *((volatile u32 *) 0xa8020004) |= 1; /* decode I/O */
+ *((volatile u32 *) 0xa8020010) = 0; /* set BAR address */
+
+ /* send reset command */
+ *((volatile u32 *) 0xa6000000) = 1; /* do a soft reset */
+
+ /* disable ether chip */
+ *((volatile u32 *) 0xa8020004) = 0; /* disable any decoding */
+
+ /* put it into sleep */
+ *((volatile u32 *) 0xa8020040) = 0x80000000;
+
+ /* ----- end of reset on-board ether chip ------ */
+
+ /* ----------- switch PCI1 back to PCI MEM space ------------ */
+ ddb_set_pdar(DDB_PCIW1, DDB_PCI_MEM_BASE, DDB_PCI_MEM_SIZE, 32, 0, 1);
+ ddb_set_pmr(DDB_PCIINIT1, DDB_PCICMD_MEM, DDB_PCI_MEM_BASE, DDB_PCI_ACCESS_32);
+}
diff --git a/arch/mips/ddb5xxx/ddb5476/vrc5476_irq.c b/arch/mips/ddb5xxx/ddb5476/vrc5476_irq.c
new file mode 100644
index 0000000..a77682b
--- /dev/null
+++ b/arch/mips/ddb5xxx/ddb5476/vrc5476_irq.c
@@ -0,0 +1,112 @@
+/*
+ * The irq controller for vrc5476.
+ *
+ * Copyright (C) 2001 MontaVista Software Inc.
+ * Author: jsun@mvista.com or jsun@junsun.net
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/types.h>
+#include <linux/ptrace.h>
+
+#include <asm/system.h>
+
+#include <asm/ddb5xxx/ddb5xxx.h>
+
+static int irq_base;
+
+static void vrc5476_irq_enable(uint irq)
+{
+ nile4_enable_irq(irq - irq_base);
+}
+
+static void vrc5476_irq_disable(uint irq)
+{
+ nile4_disable_irq(irq - irq_base);
+}
+
+static unsigned int vrc5476_irq_startup(uint irq)
+{
+ nile4_enable_irq(irq - irq_base);
+ return 0;
+}
+
+#define vrc5476_irq_shutdown vrc5476_irq_disable
+
+static void vrc5476_irq_ack(uint irq)
+{
+ nile4_clear_irq(irq - irq_base);
+ nile4_disable_irq(irq - irq_base);
+}
+
+static void vrc5476_irq_end(uint irq)
+{
+ if(!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
+ vrc5476_irq_enable(irq);
+}
+
+static hw_irq_controller vrc5476_irq_controller = {
+ "vrc5476",
+ vrc5476_irq_startup,
+ vrc5476_irq_shutdown,
+ vrc5476_irq_enable,
+ vrc5476_irq_disable,
+ vrc5476_irq_ack,
+ vrc5476_irq_end,
+ NULL /* no affinity stuff for UP */
+};
+
+void __init
+vrc5476_irq_init(u32 base)
+{
+ u32 i;
+
+ irq_base = base;
+ for (i= base; i< base + NUM_VRC5476_IRQ; i++) {
+ irq_desc[i].status = IRQ_DISABLED;
+ irq_desc[i].action = NULL;
+ irq_desc[i].depth = 1;
+ irq_desc[i].handler = &vrc5476_irq_controller;
+ }
+}
+
+
+asmlinkage void
+vrc5476_irq_dispatch(struct pt_regs *regs)
+{
+ extern void spurious_interrupt(void);
+
+ u32 mask;
+ int nile4_irq;
+
+ mask = nile4_get_irq_stat(0);
+
+ /* quick check for possible time interrupt */
+ if (mask & (1 << VRC5476_IRQ_GPT)) {
+ do_IRQ(VRC5476_IRQ_BASE + VRC5476_IRQ_GPT, regs);
+ return;
+ }
+
+ /* check for i8259 interrupts */
+ if (mask & (1 << VRC5476_I8259_CASCADE)) {
+ int i8259_irq = nile4_i8259_iack();
+ do_IRQ(I8259_IRQ_BASE + i8259_irq, regs);
+ return;
+ }
+
+ /* regular nile4 interrupts (we should not really have any */
+ for (nile4_irq = 0; mask; nile4_irq++, mask >>= 1) {
+ if (mask & 1) {
+ do_IRQ(VRC5476_IRQ_BASE + nile4_irq, regs);
+ return;
+ }
+ }
+ spurious_interrupt();
+}
diff --git a/arch/mips/ddb5xxx/ddb5477/Makefile b/arch/mips/ddb5xxx/ddb5477/Makefile
new file mode 100644
index 0000000..b79b43c
--- /dev/null
+++ b/arch/mips/ddb5xxx/ddb5477/Makefile
@@ -0,0 +1,10 @@
+#
+# Makefile for NEC DDB-Vrc5477 board
+#
+
+obj-y += int-handler.o irq.o irq_5477.o setup.o lcd44780.o
+
+obj-$(CONFIG_RUNTIME_DEBUG) += debug.o
+obj-$(CONFIG_KGDB) += kgdb_io.o
+
+EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/ddb5xxx/ddb5477/debug.c b/arch/mips/ddb5xxx/ddb5477/debug.c
new file mode 100644
index 0000000..68919d5
--- /dev/null
+++ b/arch/mips/ddb5xxx/ddb5477/debug.c
@@ -0,0 +1,160 @@
+/***********************************************************************
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: jsun@mvista.com or jsun@junsun.net
+ *
+ * arch/mips/ddb5xxx/ddb5477/debug.c
+ * vrc5477 specific debug routines.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ ***********************************************************************
+ */
+
+#include <linux/kernel.h>
+
+#include <asm/mipsregs.h>
+#include <asm/ddb5xxx/ddb5xxx.h>
+
+typedef struct {
+ const char *regname;
+ unsigned regaddr;
+} Register;
+
+void jsun_show_regs(char *name, Register *regs)
+{
+ int i;
+
+ printk("\nshow regs: %s\n", name);
+ for(i=0;regs[i].regname!= NULL; i++) {
+ printk("%-16s= %08x\t\t(@%08x)\n",
+ regs[i].regname,
+ *(unsigned *)(regs[i].regaddr),
+ regs[i].regaddr);
+ }
+}
+
+static Register int_regs[] = {
+ {"DDB_INTCTRL0", DDB_BASE + DDB_INTCTRL0},
+ {"DDB_INTCTRL1", DDB_BASE + DDB_INTCTRL1},
+ {"DDB_INTCTRL2", DDB_BASE + DDB_INTCTRL2},
+ {"DDB_INTCTRL3", DDB_BASE + DDB_INTCTRL3},
+ {"DDB_INT0STAT", DDB_BASE + DDB_INT0STAT},
+ {"DDB_INT1STAT", DDB_BASE + DDB_INT1STAT},
+ {"DDB_INT2STAT", DDB_BASE + DDB_INT2STAT},
+ {"DDB_INT3STAT", DDB_BASE + DDB_INT3STAT},
+ {"DDB_INT4STAT", DDB_BASE + DDB_INT4STAT},
+ {"DDB_NMISTAT", DDB_BASE + DDB_NMISTAT},
+ {"DDB_INTPPES0", DDB_BASE + DDB_INTPPES0},
+ {"DDB_INTPPES1", DDB_BASE + DDB_INTPPES1},
+ {NULL, 0x0}
+};
+
+void vrc5477_show_int_regs()
+{
+ jsun_show_regs("interrupt registers", int_regs);
+ printk("CPU CAUSE = %08x\n", read_c0_cause());
+ printk("CPU STATUS = %08x\n", read_c0_status());
+}
+static Register pdar_regs[] = {
+ {"DDB_SDRAM0", DDB_BASE + DDB_SDRAM0},
+ {"DDB_SDRAM1", DDB_BASE + DDB_SDRAM1},
+ {"DDB_LCS0", DDB_BASE + DDB_LCS0},
+ {"DDB_LCS1", DDB_BASE + DDB_LCS1},
+ {"DDB_LCS2", DDB_BASE + DDB_LCS2},
+ {"DDB_INTCS", DDB_BASE + DDB_INTCS},
+ {"DDB_BOOTCS", DDB_BASE + DDB_BOOTCS},
+ {"DDB_PCIW0", DDB_BASE + DDB_PCIW0},
+ {"DDB_PCIW1", DDB_BASE + DDB_PCIW1},
+ {"DDB_IOPCIW0", DDB_BASE + DDB_IOPCIW0},
+ {"DDB_IOPCIW1", DDB_BASE + DDB_IOPCIW1},
+ {NULL, 0x0}
+};
+void vrc5477_show_pdar_regs(void)
+{
+ jsun_show_regs("PDAR regs", pdar_regs);
+}
+
+static Register bar_regs[] = {
+ {"DDB_BARC0", DDB_BASE + DDB_BARC0},
+ {"DDB_BARM010", DDB_BASE + DDB_BARM010},
+ {"DDB_BARM230", DDB_BASE + DDB_BARM230},
+ {"DDB_BAR00", DDB_BASE + DDB_BAR00},
+ {"DDB_BAR10", DDB_BASE + DDB_BAR10},
+ {"DDB_BAR20", DDB_BASE + DDB_BAR20},
+ {"DDB_BAR30", DDB_BASE + DDB_BAR30},
+ {"DDB_BAR40", DDB_BASE + DDB_BAR40},
+ {"DDB_BAR50", DDB_BASE + DDB_BAR50},
+ {"DDB_BARB0", DDB_BASE + DDB_BARB0},
+ {"DDB_BARC1", DDB_BASE + DDB_BARC1},
+ {"DDB_BARM011", DDB_BASE + DDB_BARM011},
+ {"DDB_BARM231", DDB_BASE + DDB_BARM231},
+ {"DDB_BAR01", DDB_BASE + DDB_BAR01},
+ {"DDB_BAR11", DDB_BASE + DDB_BAR11},
+ {"DDB_BAR21", DDB_BASE + DDB_BAR21},
+ {"DDB_BAR31", DDB_BASE + DDB_BAR31},
+ {"DDB_BAR41", DDB_BASE + DDB_BAR41},
+ {"DDB_BAR51", DDB_BASE + DDB_BAR51},
+ {"DDB_BARB1", DDB_BASE + DDB_BARB1},
+ {NULL, 0x0}
+};
+void vrc5477_show_bar_regs(void)
+{
+ jsun_show_regs("BAR regs", bar_regs);
+}
+
+static Register pci_regs[] = {
+ {"DDB_PCIW0", DDB_BASE + DDB_PCIW0},
+ {"DDB_PCIW1", DDB_BASE + DDB_PCIW1},
+ {"DDB_PCIINIT00", DDB_BASE + DDB_PCIINIT00},
+ {"DDB_PCIINIT10", DDB_BASE + DDB_PCIINIT10},
+ {"DDB_PCICTL0_L", DDB_BASE + DDB_PCICTL0_L},
+ {"DDB_PCICTL0_H", DDB_BASE + DDB_PCICTL0_H},
+ {"DDB_PCIARB0_L", DDB_BASE + DDB_PCIARB0_L},
+ {"DDB_PCIARB0_H", DDB_BASE + DDB_PCIARB0_H},
+ {"DDB_PCISWP0", DDB_BASE + DDB_PCISWP0},
+ {"DDB_PCIERR0", DDB_BASE + DDB_PCIERR0},
+ {"DDB_IOPCIW0", DDB_BASE + DDB_IOPCIW0},
+ {"DDB_IOPCIW1", DDB_BASE + DDB_IOPCIW1},
+ {"DDB_PCIINIT01", DDB_BASE + DDB_PCIINIT01},
+ {"DDB_PCIINIT11", DDB_BASE + DDB_PCIINIT11},
+ {"DDB_PCICTL1_L", DDB_BASE + DDB_PCICTL1_L},
+ {"DDB_PCICTL1_H", DDB_BASE + DDB_PCICTL1_H},
+ {"DDB_PCIARB1_L", DDB_BASE + DDB_PCIARB1_L},
+ {"DDB_PCIARB1_H", DDB_BASE + DDB_PCIARB1_H},
+ {"DDB_PCISWP1", DDB_BASE + DDB_PCISWP1},
+ {"DDB_PCIERR1", DDB_BASE + DDB_PCIERR1},
+ {NULL, 0x0}
+};
+void vrc5477_show_pci_regs(void)
+{
+ jsun_show_regs("PCI regs", pci_regs);
+}
+
+static Register lb_regs[] = {
+ {"DDB_LCNFG", DDB_BASE + DDB_LCNFG},
+ {"DDB_LCST0", DDB_BASE + DDB_LCST0},
+ {"DDB_LCST1", DDB_BASE + DDB_LCST1},
+ {"DDB_LCST2", DDB_BASE + DDB_LCST2},
+ {"DDB_ERRADR", DDB_BASE + DDB_ERRADR},
+ {"DDB_ERRCS", DDB_BASE + DDB_ERRCS},
+ {"DDB_BTM", DDB_BASE + DDB_BTM},
+ {"DDB_BCST", DDB_BASE + DDB_BCST},
+ {NULL, 0x0}
+};
+void vrc5477_show_lb_regs(void)
+{
+ jsun_show_regs("Local Bus regs", lb_regs);
+}
+
+void vrc5477_show_all_regs(void)
+{
+ vrc5477_show_pdar_regs();
+ vrc5477_show_pci_regs();
+ vrc5477_show_bar_regs();
+ vrc5477_show_int_regs();
+ vrc5477_show_lb_regs();
+}
diff --git a/arch/mips/ddb5xxx/ddb5477/int-handler.S b/arch/mips/ddb5xxx/ddb5477/int-handler.S
new file mode 100644
index 0000000..a2502a1
--- /dev/null
+++ b/arch/mips/ddb5xxx/ddb5477/int-handler.S
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: jsun@mvista.com or jsun@junsun.net
+ *
+ * First-level interrupt dispatcher for ddb5477
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+#include <asm/asm.h>
+#include <asm/mipsregs.h>
+#include <asm/addrspace.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+#include <asm/ddb5xxx/ddb5477.h>
+
+/*
+ * first level interrupt dispatcher for ocelot board -
+ * We check for the timer first, then check PCI ints A and D.
+ * Then check for serial IRQ and fall through.
+ */
+ .align 5
+ NESTED(ddb5477_handle_int, PT_SIZE, sp)
+ SAVE_ALL
+ CLI
+ .set at
+ .set noreorder
+ mfc0 t0, CP0_CAUSE
+ mfc0 t2, CP0_STATUS
+
+ and t0, t2
+
+ andi t1, t0, STATUSF_IP7 /* cpu timer */
+ bnez t1, ll_cputimer_irq
+ andi t1, t0, (STATUSF_IP2 | STATUSF_IP3 | STATUSF_IP4 | STATUSF_IP5 | STATUSF_IP6 )
+ bnez t1, ll_vrc5477_irq
+ andi t1, t0, STATUSF_IP0 /* software int 0 */
+ bnez t1, ll_cpu_ip0
+ andi t1, t0, STATUSF_IP1 /* software int 1 */
+ bnez t1, ll_cpu_ip1
+ nop
+ .set reorder
+
+ /* wrong alarm or masked ... */
+ j spurious_interrupt
+ nop
+ END(ddb5477_handle_int)
+
+ .align 5
+
+ll_vrc5477_irq:
+ move a0, sp
+ jal vrc5477_irq_dispatch
+ j ret_from_irq
+
+ll_cputimer_irq:
+ li a0, CPU_IRQ_BASE + 7
+ move a1, sp
+ jal do_IRQ
+ j ret_from_irq
+
+
+ll_cpu_ip0:
+ li a0, CPU_IRQ_BASE + 0
+ move a1, sp
+ jal do_IRQ
+ j ret_from_irq
+
+ll_cpu_ip1:
+ li a0, CPU_IRQ_BASE + 1
+ move a1, sp
+ jal do_IRQ
+ j ret_from_irq
diff --git a/arch/mips/ddb5xxx/ddb5477/irq.c b/arch/mips/ddb5xxx/ddb5477/irq.c
new file mode 100644
index 0000000..5f027bf
--- /dev/null
+++ b/arch/mips/ddb5xxx/ddb5477/irq.c
@@ -0,0 +1,199 @@
+/*
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
+ *
+ * arch/mips/ddb5xxx/ddb5477/irq.c
+ * The irq setup and misc routines for DDB5476.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/types.h>
+#include <linux/ptrace.h>
+
+#include <asm/i8259.h>
+#include <asm/system.h>
+#include <asm/mipsregs.h>
+#include <asm/debug.h>
+#include <asm/addrspace.h>
+#include <asm/bootinfo.h>
+
+#include <asm/ddb5xxx/ddb5xxx.h>
+
+
+/*
+ * IRQ mapping
+ *
+ * 0-7: 8 CPU interrupts
+ * 0 - software interrupt 0
+ * 1 - software interrupt 1
+ * 2 - most Vrc5477 interrupts are routed to this pin
+ * 3 - (optional) some other interrupts routed to this pin for debugg
+ * 4 - not used
+ * 5 - not used
+ * 6 - not used
+ * 7 - cpu timer (used by default)
+ *
+ * 8-39: 32 Vrc5477 interrupt sources
+ * (refer to the Vrc5477 manual)
+ */
+
+#define PCI0 DDB_INTPPES0
+#define PCI1 DDB_INTPPES1
+
+#define ACTIVE_LOW 1
+#define ACTIVE_HIGH 0
+
+#define LEVEL_SENSE 2
+#define EDGE_TRIGGER 0
+
+#define INTA 0
+#define INTB 1
+#define INTC 2
+#define INTD 3
+#define INTE 4
+
+static inline void
+set_pci_int_attr(u32 pci, u32 intn, u32 active, u32 trigger)
+{
+ u32 reg_value;
+ u32 reg_bitmask;
+
+ reg_value = ddb_in32(pci);
+ reg_bitmask = 0x3 << (intn * 2);
+
+ reg_value &= ~reg_bitmask;
+ reg_value |= (active | trigger) << (intn * 2);
+ ddb_out32(pci, reg_value);
+}
+
+extern void vrc5477_irq_init(u32 base);
+extern void mips_cpu_irq_init(u32 base);
+extern asmlinkage void ddb5477_handle_int(void);
+extern int setup_irq(unsigned int irq, struct irqaction *irqaction);
+static struct irqaction irq_cascade = { no_action, 0, CPU_MASK_NONE, "cascade", NULL, NULL };
+
+void __init arch_init_irq(void)
+{
+ /* by default, we disable all interrupts and route all vrc5477
+ * interrupts to pin 0 (irq 2) */
+ ddb_out32(DDB_INTCTRL0, 0);
+ ddb_out32(DDB_INTCTRL1, 0);
+ ddb_out32(DDB_INTCTRL2, 0);
+ ddb_out32(DDB_INTCTRL3, 0);
+
+ clear_c0_status(0xff00);
+ set_c0_status(0x0400);
+
+ /* setup PCI interrupt attributes */
+ set_pci_int_attr(PCI0, INTA, ACTIVE_LOW, LEVEL_SENSE);
+ set_pci_int_attr(PCI0, INTB, ACTIVE_LOW, LEVEL_SENSE);
+ if (mips_machtype == MACH_NEC_ROCKHOPPERII)
+ set_pci_int_attr(PCI0, INTC, ACTIVE_HIGH, LEVEL_SENSE);
+ else
+ set_pci_int_attr(PCI0, INTC, ACTIVE_LOW, LEVEL_SENSE);
+ set_pci_int_attr(PCI0, INTD, ACTIVE_LOW, LEVEL_SENSE);
+ set_pci_int_attr(PCI0, INTE, ACTIVE_LOW, LEVEL_SENSE);
+
+ set_pci_int_attr(PCI1, INTA, ACTIVE_LOW, LEVEL_SENSE);
+ set_pci_int_attr(PCI1, INTB, ACTIVE_LOW, LEVEL_SENSE);
+ set_pci_int_attr(PCI1, INTC, ACTIVE_LOW, LEVEL_SENSE);
+ set_pci_int_attr(PCI1, INTD, ACTIVE_LOW, LEVEL_SENSE);
+ set_pci_int_attr(PCI1, INTE, ACTIVE_LOW, LEVEL_SENSE);
+
+ /*
+ * for debugging purpose, we enable several error interrupts
+ * and route them to pin 1. (IP3)
+ */
+ /* cpu parity check - 0 */
+ ll_vrc5477_irq_route(0, 1); ll_vrc5477_irq_enable(0);
+ /* cpu no-target decode - 1 */
+ ll_vrc5477_irq_route(1, 1); ll_vrc5477_irq_enable(1);
+ /* local bus read time-out - 7 */
+ ll_vrc5477_irq_route(7, 1); ll_vrc5477_irq_enable(7);
+ /* PCI SERR# - 14 */
+ ll_vrc5477_irq_route(14, 1); ll_vrc5477_irq_enable(14);
+ /* PCI internal error - 15 */
+ ll_vrc5477_irq_route(15, 1); ll_vrc5477_irq_enable(15);
+ /* IOPCI SERR# - 30 */
+ ll_vrc5477_irq_route(30, 1); ll_vrc5477_irq_enable(30);
+ /* IOPCI internal error - 31 */
+ ll_vrc5477_irq_route(31, 1); ll_vrc5477_irq_enable(31);
+
+ /* init all controllers */
+ init_i8259_irqs();
+ mips_cpu_irq_init(CPU_IRQ_BASE);
+ vrc5477_irq_init(VRC5477_IRQ_BASE);
+
+
+ /* setup cascade interrupts */
+ setup_irq(VRC5477_IRQ_BASE + VRC5477_I8259_CASCADE, &irq_cascade);
+ setup_irq(CPU_IRQ_BASE + CPU_VRC5477_CASCADE, &irq_cascade);
+
+ /* hook up the first-level interrupt handler */
+ set_except_vector(0, ddb5477_handle_int);
+}
+
+u8 i8259_interrupt_ack(void)
+{
+ u8 irq;
+ u32 reg;
+
+ /* Set window 0 for interrupt acknowledge */
+ reg = ddb_in32(DDB_PCIINIT10);
+
+ ddb_set_pmr(DDB_PCIINIT10, DDB_PCICMD_IACK, 0, DDB_PCI_ACCESS_32);
+ irq = *(volatile u8 *) KSEG1ADDR(DDB_PCI_IACK_BASE);
+ ddb_out32(DDB_PCIINIT10, reg);
+
+ /* i8259.c set the base vector to be 0x0 */
+ return irq + I8259_IRQ_BASE;
+}
+/*
+ * the first level int-handler will jump here if it is a vrc5477 irq
+ */
+#define NUM_5477_IRQS 32
+asmlinkage void
+vrc5477_irq_dispatch(struct pt_regs *regs)
+{
+ u32 intStatus;
+ u32 bitmask;
+ u32 i;
+
+ db_assert(ddb_in32(DDB_INT2STAT) == 0);
+ db_assert(ddb_in32(DDB_INT3STAT) == 0);
+ db_assert(ddb_in32(DDB_INT4STAT) == 0);
+ db_assert(ddb_in32(DDB_NMISTAT) == 0);
+
+ if (ddb_in32(DDB_INT1STAT) != 0) {
+#if defined(CONFIG_RUNTIME_DEBUG)
+ vrc5477_show_int_regs();
+#endif
+ panic("error interrupt has happened.");
+ }
+
+ intStatus = ddb_in32(DDB_INT0STAT);
+
+ if (mips_machtype == MACH_NEC_ROCKHOPPERII) {
+ /* check for i8259 interrupts */
+ if (intStatus & (1 << VRC5477_I8259_CASCADE)) {
+ int i8259_irq = i8259_interrupt_ack();
+ do_IRQ(I8259_IRQ_BASE + i8259_irq, regs);
+ return;
+ }
+ }
+
+ for (i=0, bitmask=1; i<= NUM_5477_IRQS; bitmask <<=1, i++) {
+ /* do we need to "and" with the int mask? */
+ if (intStatus & bitmask) {
+ do_IRQ(VRC5477_IRQ_BASE + i, regs);
+ return;
+ }
+ }
+}
diff --git a/arch/mips/ddb5xxx/ddb5477/irq_5477.c b/arch/mips/ddb5xxx/ddb5477/irq_5477.c
new file mode 100644
index 0000000..0d5e706
--- /dev/null
+++ b/arch/mips/ddb5xxx/ddb5477/irq_5477.c
@@ -0,0 +1,168 @@
+/*
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
+ *
+ * arch/mips/ddb5xxx/ddb5477/irq_5477.c
+ * This file defines the irq handler for Vrc5477.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+
+/*
+ * Vrc5477 defines 32 IRQs.
+ *
+ * This file exports one function:
+ * vrc5477_irq_init(u32 irq_base);
+ */
+
+#include <linux/interrupt.h>
+#include <linux/types.h>
+#include <linux/ptrace.h>
+
+#include <asm/debug.h>
+
+#include <asm/ddb5xxx/ddb5xxx.h>
+
+/* number of total irqs supported by Vrc5477 */
+#define NUM_5477_IRQ 32
+
+static int vrc5477_irq_base = -1;
+
+
+static void
+vrc5477_irq_enable(unsigned int irq)
+{
+ db_assert(vrc5477_irq_base != -1);
+ db_assert(irq >= vrc5477_irq_base);
+ db_assert(irq < vrc5477_irq_base+ NUM_5477_IRQ);
+
+ ll_vrc5477_irq_enable(irq - vrc5477_irq_base);
+}
+
+static void
+vrc5477_irq_disable(unsigned int irq)
+{
+ db_assert(vrc5477_irq_base != -1);
+ db_assert(irq >= vrc5477_irq_base);
+ db_assert(irq < vrc5477_irq_base + NUM_5477_IRQ);
+
+ ll_vrc5477_irq_disable(irq - vrc5477_irq_base);
+}
+
+static unsigned int vrc5477_irq_startup(unsigned int irq)
+{
+ vrc5477_irq_enable(irq);
+ return 0;
+}
+
+#define vrc5477_irq_shutdown vrc5477_irq_disable
+
+static void
+vrc5477_irq_ack(unsigned int irq)
+{
+ db_assert(vrc5477_irq_base != -1);
+ db_assert(irq >= vrc5477_irq_base);
+ db_assert(irq < vrc5477_irq_base+ NUM_5477_IRQ);
+
+ /* clear the interrupt bit */
+ /* some irqs require the driver to clear the sources */
+ ddb_out32(DDB_INTCLR32, 1 << (irq - vrc5477_irq_base));
+
+ /* disable interrupt - some handler will re-enable the irq
+ * and if the interrupt is leveled, we will have infinite loop
+ */
+ ll_vrc5477_irq_disable(irq - vrc5477_irq_base);
+}
+
+static void
+vrc5477_irq_end(unsigned int irq)
+{
+ db_assert(vrc5477_irq_base != -1);
+ db_assert(irq >= vrc5477_irq_base);
+ db_assert(irq < vrc5477_irq_base + NUM_5477_IRQ);
+
+ if(!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
+ ll_vrc5477_irq_enable( irq - vrc5477_irq_base);
+}
+
+hw_irq_controller vrc5477_irq_controller = {
+ "vrc5477_irq",
+ vrc5477_irq_startup,
+ vrc5477_irq_shutdown,
+ vrc5477_irq_enable,
+ vrc5477_irq_disable,
+ vrc5477_irq_ack,
+ vrc5477_irq_end,
+ NULL /* no affinity stuff for UP */
+};
+
+void __init vrc5477_irq_init(u32 irq_base)
+{
+ u32 i;
+
+ for (i= irq_base; i< irq_base+ NUM_5477_IRQ; i++) {
+ irq_desc[i].status = IRQ_DISABLED;
+ irq_desc[i].action = NULL;
+ irq_desc[i].depth = 1;
+ irq_desc[i].handler = &vrc5477_irq_controller;
+ }
+
+ vrc5477_irq_base = irq_base;
+}
+
+void ll_vrc5477_irq_route(int vrc5477_irq, int ip)
+{
+ u32 reg_value;
+ u32 reg_bitmask;
+ u32 reg_index;
+
+ db_assert(vrc5477_irq >= 0);
+ db_assert(vrc5477_irq < NUM_5477_IRQ);
+ db_assert(ip >= 0);
+ db_assert((ip < 5) || (ip == 6));
+
+ reg_index = DDB_INTCTRL0 + vrc5477_irq/8*4;
+ reg_value = ddb_in32(reg_index);
+ reg_bitmask = 7 << (vrc5477_irq % 8 * 4);
+ reg_value &= ~reg_bitmask;
+ reg_value |= ip << (vrc5477_irq % 8 * 4);
+ ddb_out32(reg_index, reg_value);
+}
+
+void ll_vrc5477_irq_enable(int vrc5477_irq)
+{
+ u32 reg_value;
+ u32 reg_bitmask;
+ u32 reg_index;
+
+ db_assert(vrc5477_irq >= 0);
+ db_assert(vrc5477_irq < NUM_5477_IRQ);
+
+ reg_index = DDB_INTCTRL0 + vrc5477_irq/8*4;
+ reg_value = ddb_in32(reg_index);
+ reg_bitmask = 8 << (vrc5477_irq % 8 * 4);
+ db_assert((reg_value & reg_bitmask) == 0);
+ ddb_out32(reg_index, reg_value | reg_bitmask);
+}
+
+void ll_vrc5477_irq_disable(int vrc5477_irq)
+{
+ u32 reg_value;
+ u32 reg_bitmask;
+ u32 reg_index;
+
+ db_assert(vrc5477_irq >= 0);
+ db_assert(vrc5477_irq < NUM_5477_IRQ);
+
+ reg_index = DDB_INTCTRL0 + vrc5477_irq/8*4;
+ reg_value = ddb_in32(reg_index);
+ reg_bitmask = 8 << (vrc5477_irq % 8 * 4);
+
+ /* we assert that the interrupt is enabled (perhaps over-zealous) */
+ db_assert( (reg_value & reg_bitmask) != 0);
+ ddb_out32(reg_index, reg_value & ~reg_bitmask);
+}
diff --git a/arch/mips/ddb5xxx/ddb5477/kgdb_io.c b/arch/mips/ddb5xxx/ddb5477/kgdb_io.c
new file mode 100644
index 0000000..1d18d59
--- /dev/null
+++ b/arch/mips/ddb5xxx/ddb5477/kgdb_io.c
@@ -0,0 +1,136 @@
+/*
+ * kgdb io functions for DDB5477. We use the second serial port (upper one).
+ *
+ * Copyright (C) 2001 MontaVista Software Inc.
+ * Author: jsun@mvista.com or jsun@junsun.net
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+
+/* ======================= CONFIG ======================== */
+
+/* [jsun] we use the second serial port for kdb */
+#define BASE 0xbfa04240
+#define MAX_BAUD 115200
+
+/* distance in bytes between two serial registers */
+#define REG_OFFSET 8
+
+/*
+ * 0 - kgdb does serial init
+ * 1 - kgdb skip serial init
+ */
+static int remoteDebugInitialized = 0;
+
+/*
+ * the default baud rate *if* kgdb does serial init
+ */
+#define BAUD_DEFAULT UART16550_BAUD_38400
+
+/* ======================= END OF CONFIG ======================== */
+
+typedef unsigned char uint8;
+typedef unsigned int uint32;
+
+#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
+
+/* register offset */
+#define OFS_RCV_BUFFER 0
+#define OFS_TRANS_HOLD 0
+#define OFS_SEND_BUFFER 0
+#define OFS_INTR_ENABLE (1*REG_OFFSET)
+#define OFS_INTR_ID (2*REG_OFFSET)
+#define OFS_DATA_FORMAT (3*REG_OFFSET)
+#define OFS_LINE_CONTROL (3*REG_OFFSET)
+#define OFS_MODEM_CONTROL (4*REG_OFFSET)
+#define OFS_RS232_OUTPUT (4*REG_OFFSET)
+#define OFS_LINE_STATUS (5*REG_OFFSET)
+#define OFS_MODEM_STATUS (6*REG_OFFSET)
+#define OFS_RS232_INPUT (6*REG_OFFSET)
+#define OFS_SCRATCH_PAD (7*REG_OFFSET)
+
+#define OFS_DIVISOR_LSB (0*REG_OFFSET)
+#define OFS_DIVISOR_MSB (1*REG_OFFSET)
+
+
+/* memory-mapped read/write of the port */
+#define UART16550_READ(y) (*((volatile uint8*)(BASE + y)))
+#define UART16550_WRITE(y, z) ((*((volatile uint8*)(BASE + y))) = z)
+
+void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop)
+{
+ /* disable interrupts */
+ UART16550_WRITE(OFS_INTR_ENABLE, 0);
+
+ /* set up buad rate */
+ {
+ uint32 divisor;
+
+ /* set DIAB bit */
+ UART16550_WRITE(OFS_LINE_CONTROL, 0x80);
+
+ /* set divisor */
+ divisor = MAX_BAUD / baud;
+ UART16550_WRITE(OFS_DIVISOR_LSB, divisor & 0xff);
+ UART16550_WRITE(OFS_DIVISOR_MSB, (divisor & 0xff00) >> 8);
+
+ /* clear DIAB bit */
+ UART16550_WRITE(OFS_LINE_CONTROL, 0x0);
+ }
+
+ /* set data format */
+ UART16550_WRITE(OFS_DATA_FORMAT, data | parity | stop);
+}
+
+
+uint8 getDebugChar(void)
+{
+ if (!remoteDebugInitialized) {
+ remoteDebugInitialized = 1;
+ debugInit(BAUD_DEFAULT,
+ UART16550_DATA_8BIT,
+ UART16550_PARITY_NONE, UART16550_STOP_1BIT);
+ }
+
+ while ((UART16550_READ(OFS_LINE_STATUS) & 0x1) == 0);
+ return UART16550_READ(OFS_RCV_BUFFER);
+}
+
+
+int putDebugChar(uint8 byte)
+{
+ if (!remoteDebugInitialized) {
+ remoteDebugInitialized = 1;
+ debugInit(BAUD_DEFAULT,
+ UART16550_DATA_8BIT,
+ UART16550_PARITY_NONE, UART16550_STOP_1BIT);
+ }
+
+ while ((UART16550_READ(OFS_LINE_STATUS) & 0x20) == 0);
+ UART16550_WRITE(OFS_SEND_BUFFER, byte);
+ return 1;
+}
diff --git a/arch/mips/ddb5xxx/ddb5477/lcd44780.c b/arch/mips/ddb5xxx/ddb5477/lcd44780.c
new file mode 100644
index 0000000..35c6c22
--- /dev/null
+++ b/arch/mips/ddb5xxx/ddb5477/lcd44780.c
@@ -0,0 +1,92 @@
+/*
+ * lcd44780.c
+ * Simple "driver" for a memory-mapped 44780-style LCD display.
+ *
+ * Copyright 2001 Bradley D. LaRonde <brad@ltc.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+
+#define LCD44780_COMMAND ((volatile unsigned char *)0xbe020000)
+#define LCD44780_DATA ((volatile unsigned char *)0xbe020001)
+
+#define LCD44780_4BIT_1LINE 0x20
+#define LCD44780_4BIT_2LINE 0x28
+#define LCD44780_8BIT_1LINE 0x30
+#define LCD44780_8BIT_2LINE 0x38
+#define LCD44780_MODE_DEC 0x04
+#define LCD44780_MODE_DEC_SHIFT 0x05
+#define LCD44780_MODE_INC 0x06
+#define LCD44780_MODE_INC_SHIFT 0x07
+#define LCD44780_SCROLL_LEFT 0x18
+#define LCD44780_SCROLL_RIGHT 0x1e
+#define LCD44780_CURSOR_UNDERLINE 0x0e
+#define LCD44780_CURSOR_BLOCK 0x0f
+#define LCD44780_CURSOR_OFF 0x0c
+#define LCD44780_CLEAR 0x01
+#define LCD44780_BLANK 0x08
+#define LCD44780_RESTORE 0x0c // Same as CURSOR_OFF
+#define LCD44780_HOME 0x02
+#define LCD44780_LEFT 0x10
+#define LCD44780_RIGHT 0x14
+
+void lcd44780_wait(void)
+{
+ int i, j;
+ for(i=0; i < 400; i++)
+ for(j=0; j < 10000; j++);
+}
+
+void lcd44780_command(unsigned char c)
+{
+ *LCD44780_COMMAND = c;
+ lcd44780_wait();
+}
+
+void lcd44780_data(unsigned char c)
+{
+ *LCD44780_DATA = c;
+ lcd44780_wait();
+}
+
+void lcd44780_puts(const char* s)
+{
+ int i,j;
+ int pos = 0;
+
+ lcd44780_command(LCD44780_CLEAR);
+ while(*s) {
+ lcd44780_data(*s);
+ s++;
+ pos++;
+ if (pos == 8) {
+ /* We must write 32 of spaces to get cursor to 2nd line */
+ for (j=0; j<32; j++) {
+ lcd44780_data(' ');
+ }
+ }
+ if (pos == 16) {
+ /* We have filled all 16 character positions, so stop
+ outputing data */
+ break;
+ }
+ }
+#ifdef LCD44780_PUTS_PAUSE
+ for(i = 1; i < 2000; i++)
+ lcd44780_wait();
+#endif
+}
+
+void lcd44780_init(void)
+{
+ // The display on the RockHopper is physically a single
+ // 16 char line (two 8 char lines concatenated). bdl
+ lcd44780_command(LCD44780_8BIT_2LINE);
+ lcd44780_command(LCD44780_MODE_INC);
+ lcd44780_command(LCD44780_CURSOR_BLOCK);
+ lcd44780_command(LCD44780_CLEAR);
+}
diff --git a/arch/mips/ddb5xxx/ddb5477/lcd44780.h b/arch/mips/ddb5xxx/ddb5477/lcd44780.h
new file mode 100644
index 0000000..cf2f0f7
--- /dev/null
+++ b/arch/mips/ddb5xxx/ddb5477/lcd44780.h
@@ -0,0 +1,15 @@
+/*
+ * lcd44780.h
+ * Simple "driver" for a memory-mapped 44780-style LCD display.
+ *
+ * Copyright 2001 Bradley D. LaRonde <brad@ltc.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+
+void lcd44780_puts(const char* s);
+void lcd44780_init(void);
diff --git a/arch/mips/ddb5xxx/ddb5477/setup.c b/arch/mips/ddb5xxx/ddb5477/setup.c
new file mode 100644
index 0000000..15c6e54
--- /dev/null
+++ b/arch/mips/ddb5xxx/ddb5477/setup.c
@@ -0,0 +1,405 @@
+/*
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: jsun@mvista.com or jsun@junsun.net
+ *
+ * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org)
+ *
+ * arch/mips/ddb5xxx/ddb5477/setup.c
+ * Setup file for DDB5477.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/pci.h>
+#include <linux/ide.h>
+#include <linux/fs.h>
+#include <linux/ioport.h>
+#include <linux/param.h> /* for HZ */
+#include <linux/major.h>
+#include <linux/kdev_t.h>
+#include <linux/root_dev.h>
+
+#include <asm/cpu.h>
+#include <asm/bootinfo.h>
+#include <asm/addrspace.h>
+#include <asm/time.h>
+#include <asm/bcache.h>
+#include <asm/irq.h>
+#include <asm/reboot.h>
+#include <asm/gdb-stub.h>
+#include <asm/traps.h>
+#include <asm/debug.h>
+
+#include <asm/ddb5xxx/ddb5xxx.h>
+
+#include "lcd44780.h"
+
+
+#define USE_CPU_COUNTER_TIMER /* whether we use cpu counter */
+
+#define SP_TIMER_BASE DDB_SPT1CTRL_L
+#define SP_TIMER_IRQ VRC5477_IRQ_SPT1
+
+static int bus_frequency = CONFIG_DDB5477_BUS_FREQUENCY*1000;
+
+static void ddb_machine_restart(char *command)
+{
+ static void (*back_to_prom) (void) = (void (*)(void)) 0xbfc00000;
+
+ u32 t;
+
+ /* PCI cold reset */
+ ddb_pci_reset_bus();
+
+ /* CPU cold reset */
+ t = ddb_in32(DDB_CPUSTAT);
+ db_assert((t&1));
+ ddb_out32(DDB_CPUSTAT, t);
+
+ /* Call the PROM */
+ back_to_prom();
+}
+
+static void ddb_machine_halt(void)
+{
+ printk("DDB Vrc-5477 halted.\n");
+ while (1);
+}
+
+static void ddb_machine_power_off(void)
+{
+ printk("DDB Vrc-5477 halted. Please turn off the power.\n");
+ while (1);
+}
+
+extern void rtc_ds1386_init(unsigned long base);
+
+static unsigned int __init detect_bus_frequency(unsigned long rtc_base)
+{
+ unsigned int freq;
+ unsigned char c;
+ unsigned int t1, t2;
+ unsigned i;
+
+ ddb_out32(SP_TIMER_BASE, 0xffffffff);
+ ddb_out32(SP_TIMER_BASE+4, 0x1);
+ ddb_out32(SP_TIMER_BASE+8, 0xffffffff);
+
+ /* check if rtc is running */
+ c= *(volatile unsigned char*)rtc_base;
+ for(i=0; (c == *(volatile unsigned char*)rtc_base) && (i<100000000); i++);
+ if (c == *(volatile unsigned char*)rtc_base) {
+ printk("Failed to detect bus frequency. Use default 83.3MHz.\n");
+ return 83333000;
+ }
+
+ c= *(volatile unsigned char*)rtc_base;
+ while (c == *(volatile unsigned char*)rtc_base);
+ /* we are now at the turn of 1/100th second, if no error. */
+ t1 = ddb_in32(SP_TIMER_BASE+8);
+
+ for (i=0; i< 10; i++) {
+ c= *(volatile unsigned char*)rtc_base;
+ while (c == *(volatile unsigned char*)rtc_base);
+ /* we are now at the turn of another 1/100th second */
+ t2 = ddb_in32(SP_TIMER_BASE+8);
+ }
+
+ ddb_out32(SP_TIMER_BASE+4, 0x0); /* disable it again */
+
+ freq = (t1 - t2)*10;
+ printk("DDB bus frequency detection : %u \n", freq);
+ return freq;
+}
+
+static void __init ddb_time_init(void)
+{
+ unsigned long rtc_base;
+ unsigned int i;
+
+ /* we have ds1396 RTC chip */
+ if (mips_machtype == MACH_NEC_ROCKHOPPER
+ || mips_machtype == MACH_NEC_ROCKHOPPERII) {
+ rtc_base = KSEG1ADDR(DDB_LCS2_BASE);
+ } else {
+ rtc_base = KSEG1ADDR(DDB_LCS1_BASE);
+ }
+ rtc_ds1386_init(rtc_base);
+
+ /* do we need to do run-time detection of bus speed? */
+ if (bus_frequency == 0) {
+ bus_frequency = detect_bus_frequency(rtc_base);
+ }
+
+ /* mips_hpt_frequency is 1/2 of the cpu core freq */
+ i = (read_c0_config() >> 28 ) & 7;
+ if ((current_cpu_data.cputype == CPU_R5432) && (i == 3))
+ i = 4;
+ mips_hpt_frequency = bus_frequency*(i+4)/4;
+}
+
+extern int setup_irq(unsigned int irq, struct irqaction *irqaction);
+
+static void __init ddb_timer_setup(struct irqaction *irq)
+{
+#if defined(USE_CPU_COUNTER_TIMER)
+
+ /* we are using the cpu counter for timer interrupts */
+ setup_irq(CPU_IRQ_BASE + 7, irq);
+
+#else
+
+ /* if we use Special purpose timer 1 */
+ ddb_out32(SP_TIMER_BASE, bus_frequency/HZ);
+ ddb_out32(SP_TIMER_BASE+4, 0x1);
+ setup_irq(SP_TIMER_IRQ, irq);
+
+#endif
+}
+
+static void ddb5477_board_init(void);
+
+extern struct pci_controller ddb5477_ext_controller;
+extern struct pci_controller ddb5477_io_controller;
+
+static int ddb5477_setup(void)
+{
+ /* initialize board - we don't trust the loader */
+ ddb5477_board_init();
+
+ set_io_port_base(KSEG1ADDR(DDB_PCI_IO_BASE));
+
+ board_time_init = ddb_time_init;
+ board_timer_setup = ddb_timer_setup;
+
+ _machine_restart = ddb_machine_restart;
+ _machine_halt = ddb_machine_halt;
+ _machine_power_off = ddb_machine_power_off;
+
+ /* setup resource limits */
+ ioport_resource.end = DDB_PCI0_IO_SIZE + DDB_PCI1_IO_SIZE - 1;
+ iomem_resource.end = 0xffffffff;
+
+ /* Reboot on panic */
+ panic_timeout = 180;
+
+ register_pci_controller (&ddb5477_ext_controller);
+ register_pci_controller (&ddb5477_io_controller);
+
+ return 0;
+}
+
+early_initcall(ddb5477_setup);
+
+static void __init ddb5477_board_init(void)
+{
+ /* ----------- setup PDARs ------------ */
+
+ /* SDRAM should have been set */
+ db_assert(ddb_in32(DDB_SDRAM0) ==
+ ddb_calc_pdar(DDB_SDRAM_BASE, board_ram_size, 32, 0, 1));
+
+ /* SDRAM1 should be turned off. What is this for anyway ? */
+ db_assert( (ddb_in32(DDB_SDRAM1) & 0xf) == 0);
+
+ /* Setup local bus. */
+
+ /* Flash U12 PDAR and timing. */
+ ddb_set_pdar(DDB_LCS0, DDB_LCS0_BASE, DDB_LCS0_SIZE, 16, 0, 0);
+ ddb_out32(DDB_LCST0, 0x00090842);
+
+ /* We need to setup LCS1 and LCS2 differently based on the
+ board_version */
+ if (mips_machtype == MACH_NEC_ROCKHOPPER) {
+ /* Flash U13 PDAR and timing. */
+ ddb_set_pdar(DDB_LCS1, DDB_LCS1_BASE, DDB_LCS1_SIZE, 16, 0, 0);
+ ddb_out32(DDB_LCST1, 0x00090842);
+
+ /* EPLD (NVRAM, switch, LCD, and mezzanie). */
+ ddb_set_pdar(DDB_LCS2, DDB_LCS2_BASE, DDB_LCS2_SIZE, 8, 0, 0);
+ } else {
+ /* misc */
+ ddb_set_pdar(DDB_LCS1, DDB_LCS1_BASE, DDB_LCS1_SIZE, 8, 0, 0);
+ /* mezzanie (?) */
+ ddb_set_pdar(DDB_LCS2, DDB_LCS2_BASE, DDB_LCS2_SIZE, 16, 0, 0);
+ }
+
+ /* verify VRC5477 base addr */
+ db_assert(ddb_in32(DDB_VRC5477) ==
+ ddb_calc_pdar(DDB_VRC5477_BASE, DDB_VRC5477_SIZE, 32, 0, 1));
+
+ /* verify BOOT ROM addr */
+ db_assert(ddb_in32(DDB_BOOTCS) ==
+ ddb_calc_pdar(DDB_BOOTCS_BASE, DDB_BOOTCS_SIZE, 8, 0, 0));
+
+ /* setup PCI windows - window0 for MEM/config, window1 for IO */
+ ddb_set_pdar(DDB_PCIW0, DDB_PCI0_MEM_BASE, DDB_PCI0_MEM_SIZE, 32, 0, 1);
+ ddb_set_pdar(DDB_PCIW1, DDB_PCI0_IO_BASE, DDB_PCI0_IO_SIZE, 32, 0, 1);
+ ddb_set_pdar(DDB_IOPCIW0, DDB_PCI1_MEM_BASE, DDB_PCI1_MEM_SIZE, 32, 0, 1);
+ ddb_set_pdar(DDB_IOPCIW1, DDB_PCI1_IO_BASE, DDB_PCI1_IO_SIZE, 32, 0, 1);
+
+ /* ------------ reset PCI bus and BARs ----------------- */
+ ddb_pci_reset_bus();
+
+ ddb_out32(DDB_BARM010, 0x00000008);
+ ddb_out32(DDB_BARM011, 0x00000008);
+
+ ddb_out32(DDB_BARC0, 0xffffffff);
+ ddb_out32(DDB_BARM230, 0xffffffff);
+ ddb_out32(DDB_BAR00, 0xffffffff);
+ ddb_out32(DDB_BAR10, 0xffffffff);
+ ddb_out32(DDB_BAR20, 0xffffffff);
+ ddb_out32(DDB_BAR30, 0xffffffff);
+ ddb_out32(DDB_BAR40, 0xffffffff);
+ ddb_out32(DDB_BAR50, 0xffffffff);
+ ddb_out32(DDB_BARB0, 0xffffffff);
+
+ ddb_out32(DDB_BARC1, 0xffffffff);
+ ddb_out32(DDB_BARM231, 0xffffffff);
+ ddb_out32(DDB_BAR01, 0xffffffff);
+ ddb_out32(DDB_BAR11, 0xffffffff);
+ ddb_out32(DDB_BAR21, 0xffffffff);
+ ddb_out32(DDB_BAR31, 0xffffffff);
+ ddb_out32(DDB_BAR41, 0xffffffff);
+ ddb_out32(DDB_BAR51, 0xffffffff);
+ ddb_out32(DDB_BARB1, 0xffffffff);
+
+ /*
+ * We use pci master register 0 for memory space / config space
+ * And we use register 1 for IO space.
+ * Note that for memory space, we bump up the pci base address
+ * so that we have 1:1 mapping between PCI memory and cpu physical.
+ * For PCI IO space, it starts from 0 in PCI IO space but with
+ * DDB_xx_IO_BASE in CPU physical address space.
+ */
+ ddb_set_pmr(DDB_PCIINIT00, DDB_PCICMD_MEM, DDB_PCI0_MEM_BASE,
+ DDB_PCI_ACCESS_32);
+ ddb_set_pmr(DDB_PCIINIT10, DDB_PCICMD_IO, 0, DDB_PCI_ACCESS_32);
+
+ ddb_set_pmr(DDB_PCIINIT01, DDB_PCICMD_MEM, DDB_PCI1_MEM_BASE,
+ DDB_PCI_ACCESS_32);
+ ddb_set_pmr(DDB_PCIINIT11, DDB_PCICMD_IO, DDB_PCI0_IO_SIZE,
+ DDB_PCI_ACCESS_32);
+
+
+ /* PCI cross window should be set properly */
+ ddb_set_pdar(DDB_BARP00, DDB_PCI1_MEM_BASE, DDB_PCI1_MEM_SIZE, 32, 0, 1);
+ ddb_set_pdar(DDB_BARP10, DDB_PCI1_IO_BASE, DDB_PCI1_IO_SIZE, 32, 0, 1);
+ ddb_set_pdar(DDB_BARP01, DDB_PCI0_MEM_BASE, DDB_PCI0_MEM_SIZE, 32, 0, 1);
+ ddb_set_pdar(DDB_BARP11, DDB_PCI0_IO_BASE, DDB_PCI0_IO_SIZE, 32, 0, 1);
+
+ if (mips_machtype == MACH_NEC_ROCKHOPPER
+ || mips_machtype == MACH_NEC_ROCKHOPPERII) {
+ /* Disable bus diagnostics. */
+ ddb_out32(DDB_PCICTL0_L, 0);
+ ddb_out32(DDB_PCICTL0_H, 0);
+ ddb_out32(DDB_PCICTL1_L, 0);
+ ddb_out32(DDB_PCICTL1_H, 0);
+ }
+
+ if (mips_machtype == MACH_NEC_ROCKHOPPER) {
+ u16 vid;
+ struct pci_bus bus;
+ struct pci_dev dev_m1533;
+ extern struct pci_ops ddb5477_ext_pci_ops;
+
+ bus.parent = NULL; /* we scan the top level only */
+ bus.ops = &ddb5477_ext_pci_ops;
+ dev_m1533.bus = &bus;
+ dev_m1533.sysdata = NULL;
+ dev_m1533.devfn = 7*8; // slot 7: M1533 SouthBridge.
+ pci_read_config_word(&dev_m1533, 0, &vid);
+ if (vid == PCI_VENDOR_ID_AL) {
+ printk("Changing mips_machtype to MACH_NEC_ROCKHOPPERII\n");
+ mips_machtype = MACH_NEC_ROCKHOPPERII;
+ }
+ }
+
+ /* enable USB input buffers */
+ ddb_out32(DDB_PIBMISC, 0x00000007);
+
+ /* For dual-function pins, make them all non-GPIO */
+ ddb_out32(DDB_GIUFUNSEL, 0x0);
+ // ddb_out32(DDB_GIUFUNSEL, 0xfe0fcfff); /* NEC recommanded value */
+
+ if (mips_machtype == MACH_NEC_ROCKHOPPERII) {
+
+ /* enable IDE controller on Ali chip (south bridge) */
+ u8 temp8;
+ struct pci_bus bus;
+ struct pci_dev dev_m1533;
+ struct pci_dev dev_m5229;
+ extern struct pci_ops ddb5477_ext_pci_ops;
+
+ /* Setup M1535 registers */
+ bus.parent = NULL; /* we scan the top level only */
+ bus.ops = &ddb5477_ext_pci_ops;
+ dev_m1533.bus = &bus;
+ dev_m1533.sysdata = NULL;
+ dev_m1533.devfn = 7*8; // slot 7: M1533 SouthBridge.
+
+ /* setup IDE controller
+ * enable IDE controller (bit 6 - 1)
+ * IDE IDSEL to be addr:A15 (bit 4:5 - 11)
+ * disable IDE ATA Secondary Bus Signal Pad Control (bit 3 - 0)
+ * enable IDE ATA Primary Bus Signal Pad Control (bit 2 - 1)
+ */
+ pci_write_config_byte(&dev_m1533, 0x58, 0x74);
+
+ /*
+ * positive decode (bit6 -0)
+ * enable IDE controler interrupt (bit 4 -1)
+ * setup SIRQ to point to IRQ 14 (bit 3:0 - 1101)
+ */
+ pci_write_config_byte(&dev_m1533, 0x44, 0x1d);
+
+ /* Setup M5229 registers */
+ dev_m5229.bus = &bus;
+ dev_m5229.sysdata = NULL;
+ dev_m5229.devfn = 4*8; // slot 4 (AD15): M5229 IDE
+
+ /*
+ * enable IDE in the M5229 config register 0x50 (bit 0 - 1)
+ * M5229 IDSEL is addr:15; see above setting
+ */
+ pci_read_config_byte(&dev_m5229, 0x50, &temp8);
+ pci_write_config_byte(&dev_m5229, 0x50, temp8 | 0x1);
+
+ /*
+ * enable bus master (bit 2) and IO decoding (bit 0)
+ */
+ pci_read_config_byte(&dev_m5229, 0x04, &temp8);
+ pci_write_config_byte(&dev_m5229, 0x04, temp8 | 0x5);
+
+ /*
+ * enable native, copied from arch/ppc/k2boot/head.S
+ * TODO - need volatile, need to be portable
+ */
+ pci_write_config_byte(&dev_m5229, 0x09, 0xef);
+
+ /* Set Primary Channel Command Block Timing */
+ pci_write_config_byte(&dev_m5229, 0x59, 0x31);
+
+ /*
+ * Enable primary channel 40-pin cable
+ * M5229 register 0x4a (bit 0)
+ */
+ pci_read_config_byte(&dev_m5229, 0x4a, &temp8);
+ pci_write_config_byte(&dev_m5229, 0x4a, temp8 | 0x1);
+ }
+
+ if (mips_machtype == MACH_NEC_ROCKHOPPER
+ || mips_machtype == MACH_NEC_ROCKHOPPERII) {
+ printk("lcd44780: initializing\n");
+ lcd44780_init();
+ lcd44780_puts("MontaVista Linux");
+ }
+}
diff --git a/arch/mips/dec/Makefile b/arch/mips/dec/Makefile
new file mode 100644
index 0000000..688757a
--- /dev/null
+++ b/arch/mips/dec/Makefile
@@ -0,0 +1,11 @@
+#
+# Makefile for the DECstation family specific parts of the kernel
+#
+
+obj-y := ecc-berr.o int-handler.o ioasic-irq.o kn02-irq.o reset.o \
+ setup.o time.o
+
+obj-$(CONFIG_PROM_CONSOLE) += promcon.o
+obj-$(CONFIG_CPU_HAS_WB) += wbflush.o
+
+EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/dec/boot/Makefile b/arch/mips/dec/boot/Makefile
new file mode 100644
index 0000000..bcea416
--- /dev/null
+++ b/arch/mips/dec/boot/Makefile
@@ -0,0 +1,12 @@
+#
+# Makefile for the DECstation family specific parts of the kernel
+#
+
+netboot: all
+ $(LD) -N -G 0 -T ld.ecoff ../../boot/zImage \
+ dec_boot.o ramdisk.img -o nbImage
+
+obj-y := decstation.o
+
+clean:
+ rm -f nbImage
diff --git a/arch/mips/dec/boot/decstation.c b/arch/mips/dec/boot/decstation.c
new file mode 100644
index 0000000..56fd427
--- /dev/null
+++ b/arch/mips/dec/boot/decstation.c
@@ -0,0 +1,83 @@
+/*
+ * arch/mips/dec/decstation.c
+ */
+
+#define RELOC
+#define INITRD
+#define DEBUG_BOOT
+
+/*
+ * Magic number indicating REX PROM available on DECSTATION.
+ */
+#define REX_PROM_MAGIC 0x30464354
+
+#define REX_PROM_CLEARCACHE 0x7c/4
+#define REX_PROM_PRINTF 0x30/4
+
+#define VEC_RESET 0xBFC00000 /* Prom base address */
+#define PMAX_PROM_ENTRY(x) (VEC_RESET+((x)*8)) /* Prom jump table */
+#define PMAX_PROM_PRINTF PMAX_PROM_ENTRY(17)
+
+#define PARAM (k_start + 0x2000)
+
+#define LOADER_TYPE (*(unsigned char *) (PARAM+0x210))
+#define INITRD_START (*(unsigned long *) (PARAM+0x218))
+#define INITRD_SIZE (*(unsigned long *) (PARAM+0x21c))
+
+extern int _ftext, _end; /* begin and end of kernel image */
+extern void kernel_entry(int, char **, unsigned long, int *);
+
+void * memcpy(void * dest, const void *src, unsigned int count)
+{
+ unsigned long *tmp = (unsigned long *) dest, *s = (unsigned long *) src;
+
+ count >>= 2;
+ while (count--)
+ *tmp++ = *s++;
+
+ return dest;
+}
+
+void dec_entry(int argc, char **argv,
+ unsigned long magic, int *prom_vec)
+{
+ void (*rex_clear_cache)(void);
+ int (*prom_printf)(char *, ...);
+ unsigned long k_start, len;
+
+ /*
+ * The DS5100 leaves cpu with BEV enabled, clear it.
+ */
+ asm( "lui\t$8,0x3000\n\t"
+ "mtc0\t$8,$12\n\t"
+ ".section\t.sdata\n\t"
+ ".section\t.sbss\n\t"
+ ".section\t.text"
+ : : : "$8");
+
+#ifdef DEBUG_BOOT
+ if (magic == REX_PROM_MAGIC) {
+ prom_printf = (int (*)(char *, ...)) *(prom_vec + REX_PROM_PRINTF);
+ } else {
+ prom_printf = (int (*)(char *, ...)) PMAX_PROM_PRINTF;
+ }
+ prom_printf("Launching kernel...\n");
+#endif
+
+ k_start = (unsigned long) (&kernel_entry) & 0xffff0000;
+
+#ifdef RELOC
+ /*
+ * Now copy kernel image to its destination.
+ */
+ len = ((unsigned long) (&_end) - k_start);
+ memcpy((void *)k_start, &_ftext, len);
+#endif
+
+ if (magic == REX_PROM_MAGIC) {
+ rex_clear_cache = (void (*)(void)) * (prom_vec + REX_PROM_CLEARCACHE);
+ rex_clear_cache();
+ }
+
+ kernel_entry(argc, argv, magic, prom_vec);
+}
diff --git a/arch/mips/dec/boot/ld.ecoff b/arch/mips/dec/boot/ld.ecoff
new file mode 100644
index 0000000..aaa633d
--- /dev/null
+++ b/arch/mips/dec/boot/ld.ecoff
@@ -0,0 +1,43 @@
+OUTPUT_FORMAT("ecoff-littlemips")
+OUTPUT_ARCH(mips)
+ENTRY(dec_entry)
+SECTIONS
+{
+ . = 0x80200000;
+
+ .text :
+ {
+ _ftext = .;
+ *(.text)
+ *(.fixup)
+ }
+ .rdata :
+ {
+ *(.rodata .rodata.* .rdata)
+ }
+ .data :
+ {
+ . = ALIGN(0x1000);
+ ramdisk.img (.data)
+ *(.data)
+ }
+ .sdata :
+ {
+ *(.sdata)
+ }
+ _gp = .;
+ .sbss :
+ {
+ *(.sbss)
+ *(.scommon)
+ }
+ .bss :
+ {
+ *(.dynbss)
+ *(.bss)
+ *(COMMON)
+ }
+ /DISCARD/ : {
+ *(.reginfo .mdebug .note)
+ }
+}
diff --git a/arch/mips/dec/ecc-berr.c b/arch/mips/dec/ecc-berr.c
new file mode 100644
index 0000000..133fb7c
--- /dev/null
+++ b/arch/mips/dec/ecc-berr.c
@@ -0,0 +1,280 @@
+/*
+ * linux/arch/mips/dec/ecc-berr.c
+ *
+ * Bus error event handling code for systems equipped with ECC
+ * handling logic, i.e. DECstation/DECsystem 5000/200 (KN02),
+ * 5000/240 (KN03), 5000/260 (KN05) and DECsystem 5900 (KN03),
+ * 5900/260 (KN05) systems.
+ *
+ * Copyright (c) 2003 Maciej W. Rozycki
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+
+#include <asm/addrspace.h>
+#include <asm/bootinfo.h>
+#include <asm/cpu.h>
+#include <asm/processor.h>
+#include <asm/system.h>
+#include <asm/traps.h>
+
+#include <asm/dec/ecc.h>
+#include <asm/dec/kn02.h>
+#include <asm/dec/kn03.h>
+#include <asm/dec/kn05.h>
+
+static volatile u32 *kn0x_erraddr;
+static volatile u32 *kn0x_chksyn;
+
+static inline void dec_ecc_be_ack(void)
+{
+ *kn0x_erraddr = 0; /* any write clears the IRQ */
+ iob();
+}
+
+static int dec_ecc_be_backend(struct pt_regs *regs, int is_fixup, int invoker)
+{
+ static const char excstr[] = "exception";
+ static const char intstr[] = "interrupt";
+ static const char cpustr[] = "CPU";
+ static const char dmastr[] = "DMA";
+ static const char readstr[] = "read";
+ static const char mreadstr[] = "memory read";
+ static const char writestr[] = "write";
+ static const char mwritstr[] = "partial memory write";
+ static const char timestr[] = "timeout";
+ static const char overstr[] = "overrun";
+ static const char eccstr[] = "ECC error";
+
+ const char *kind, *agent, *cycle, *event;
+ const char *status = "", *xbit = "", *fmt = "";
+ dma_addr_t address;
+ u16 syn = 0, sngl;
+
+ int i = 0;
+
+ u32 erraddr = *kn0x_erraddr;
+ u32 chksyn = *kn0x_chksyn;
+ int action = MIPS_BE_FATAL;
+
+ /* For non-ECC ack ASAP, so any subsequent errors get caught. */
+ if ((erraddr & (KN0X_EAR_VALID | KN0X_EAR_ECCERR)) == KN0X_EAR_VALID)
+ dec_ecc_be_ack();
+
+ kind = invoker ? intstr : excstr;
+
+ if (!(erraddr & KN0X_EAR_VALID)) {
+ /* No idea what happened. */
+ printk(KERN_ALERT "Unidentified bus error %s.\n", kind);
+ return action;
+ }
+
+ agent = (erraddr & KN0X_EAR_CPU) ? cpustr : dmastr;
+
+ if (erraddr & KN0X_EAR_ECCERR) {
+ /* An ECC error on a CPU or DMA transaction. */
+ cycle = (erraddr & KN0X_EAR_WRITE) ? mwritstr : mreadstr;
+ event = eccstr;
+ } else {
+ /* A CPU timeout or a DMA overrun. */
+ cycle = (erraddr & KN0X_EAR_WRITE) ? writestr : readstr;
+ event = (erraddr & KN0X_EAR_CPU) ? timestr : overstr;
+ }
+
+ address = erraddr & KN0X_EAR_ADDRESS;
+ /* For ECC errors on reads adjust for MT pipelining. */
+ if ((erraddr & (KN0X_EAR_WRITE | KN0X_EAR_ECCERR)) == KN0X_EAR_ECCERR)
+ address = (address & ~0xfffLL) | ((address - 5) & 0xfffLL);
+ address <<= 2;
+
+ /* Only CPU errors are fixable. */
+ if (erraddr & KN0X_EAR_CPU && is_fixup)
+ action = MIPS_BE_FIXUP;
+
+ if (erraddr & KN0X_EAR_ECCERR) {
+ static const u8 data_sbit[32] = {
+ 0x4f, 0x4a, 0x52, 0x54, 0x57, 0x58, 0x5b, 0x5d,
+ 0x23, 0x25, 0x26, 0x29, 0x2a, 0x2c, 0x31, 0x34,
+ 0x0e, 0x0b, 0x13, 0x15, 0x16, 0x19, 0x1a, 0x1c,
+ 0x62, 0x64, 0x67, 0x68, 0x6b, 0x6d, 0x70, 0x75,
+ };
+ static const u8 data_mbit[25] = {
+ 0x07, 0x0d, 0x1f,
+ 0x2f, 0x32, 0x37, 0x38, 0x3b, 0x3d, 0x3e,
+ 0x43, 0x45, 0x46, 0x49, 0x4c, 0x51, 0x5e,
+ 0x61, 0x6e, 0x73, 0x76, 0x79, 0x7a, 0x7c, 0x7f,
+ };
+ static const char sbestr[] = "corrected single";
+ static const char dbestr[] = "uncorrectable double";
+ static const char mbestr[] = "uncorrectable multiple";
+
+ if (!(address & 0x4))
+ syn = chksyn; /* Low bank. */
+ else
+ syn = chksyn >> 16; /* High bank. */
+
+ if (!(syn & KN0X_ESR_VLDLO)) {
+ /* Ack now, no rewrite will happen. */
+ dec_ecc_be_ack();
+
+ fmt = KERN_ALERT "%s" "invalid.\n";
+ } else {
+ sngl = syn & KN0X_ESR_SNGLO;
+ syn &= KN0X_ESR_SYNLO;
+
+ /*
+ * Multibit errors may be tagged incorrectly;
+ * check the syndrome explicitly.
+ */
+ for (i = 0; i < 25; i++)
+ if (syn == data_mbit[i])
+ break;
+
+ if (i < 25) {
+ status = mbestr;
+ } else if (!sngl) {
+ status = dbestr;
+ } else {
+ volatile u32 *ptr = (void *)KSEG1ADDR(address);
+
+ *ptr = *ptr; /* Rewrite. */
+ iob();
+
+ status = sbestr;
+ action = MIPS_BE_DISCARD;
+ }
+
+ /* Ack now, now we've rewritten (or not). */
+ dec_ecc_be_ack();
+
+ if (syn && syn == (syn & -syn)) {
+ if (syn == 0x01) {
+ fmt = KERN_ALERT "%s"
+ "%#04x -- %s bit error "
+ "at check bit C%s.\n";
+ xbit = "X";
+ } else {
+ fmt = KERN_ALERT "%s"
+ "%#04x -- %s bit error "
+ "at check bit C%s%u.\n";
+ }
+ i = syn >> 2;
+ } else {
+ for (i = 0; i < 32; i++)
+ if (syn == data_sbit[i])
+ break;
+ if (i < 32)
+ fmt = KERN_ALERT "%s"
+ "%#04x -- %s bit error "
+ "at data bit D%s%u.\n";
+ else
+ fmt = KERN_ALERT "%s"
+ "%#04x -- %s bit error.\n";
+ }
+ }
+ }
+
+ if (action != MIPS_BE_FIXUP)
+ printk(KERN_ALERT "Bus error %s: %s %s %s at %#010lx.\n",
+ kind, agent, cycle, event, address);
+
+ if (action != MIPS_BE_FIXUP && erraddr & KN0X_EAR_ECCERR)
+ printk(fmt, " ECC syndrome ", syn, status, xbit, i);
+
+ return action;
+}
+
+int dec_ecc_be_handler(struct pt_regs *regs, int is_fixup)
+{
+ return dec_ecc_be_backend(regs, is_fixup, 0);
+}
+
+irqreturn_t dec_ecc_be_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ int action = dec_ecc_be_backend(regs, 0, 1);
+
+ if (action == MIPS_BE_DISCARD)
+ return IRQ_NONE;
+
+ /*
+ * FIXME: Find affected processes and kill them, otherwise we
+ * must die.
+ *
+ * The interrupt is asynchronously delivered thus EPC and RA
+ * may be irrelevant, but are printed for a reference.
+ */
+ printk(KERN_ALERT "Fatal bus interrupt, epc == %08lx, ra == %08lx\n",
+ regs->cp0_epc, regs->regs[31]);
+ die("Unrecoverable bus error", regs);
+}
+
+
+/*
+ * Initialization differs a bit between KN02 and KN03/KN05, so we
+ * need two variants. Once set up, all systems can be handled the
+ * same way.
+ */
+static inline void dec_kn02_be_init(void)
+{
+ volatile u32 *csr = (void *)KN02_CSR_BASE;
+ unsigned long flags;
+
+ kn0x_erraddr = (void *)(KN02_SLOT_BASE + KN02_ERRADDR);
+ kn0x_chksyn = (void *)(KN02_SLOT_BASE + KN02_CHKSYN);
+
+ spin_lock_irqsave(&kn02_lock, flags);
+
+ /* Preset write-only bits of the Control Register cache. */
+ cached_kn02_csr = *csr | KN03_CSR_LEDS;
+
+ /* Set normal ECC detection and generation. */
+ cached_kn02_csr &= ~(KN02_CSR_DIAGCHK | KN02_CSR_DIAGGEN);
+ /* Enable ECC correction. */
+ cached_kn02_csr |= KN02_CSR_CORRECT;
+ *csr = cached_kn02_csr;
+ iob();
+
+ spin_unlock_irqrestore(&kn02_lock, flags);
+}
+
+static inline void dec_kn03_be_init(void)
+{
+ volatile u32 *mcr = (void *)(KN03_SLOT_BASE + IOASIC_MCR);
+ volatile u32 *mbcs = (void *)(KN03_SLOT_BASE + KN05_MB_CSR);
+
+ kn0x_erraddr = (void *)(KN03_SLOT_BASE + IOASIC_ERRADDR);
+ kn0x_chksyn = (void *)(KN03_SLOT_BASE + IOASIC_CHKSYN);
+
+ /*
+ * Set normal ECC detection and generation, enable ECC correction.
+ * For KN05 we also need to make sure EE (?) is enabled in the MB.
+ * Otherwise DBE/IBE exceptions would be masked but bus error
+ * interrupts would still arrive, resulting in an inevitable crash
+ * if get_dbe() triggers one.
+ */
+ *mcr = (*mcr & ~(KN03_MCR_DIAGCHK | KN03_MCR_DIAGGEN)) |
+ KN03_MCR_CORRECT;
+ if (current_cpu_data.cputype == CPU_R4400SC)
+ *mbcs |= KN05_MB_CSR_EE;
+ fast_iob();
+}
+
+void __init dec_ecc_be_init(void)
+{
+ if (mips_machtype == MACH_DS5000_200)
+ dec_kn02_be_init();
+ else
+ dec_kn03_be_init();
+
+ /* Clear any leftover errors from the firmware. */
+ dec_ecc_be_ack();
+}
diff --git a/arch/mips/dec/int-handler.S b/arch/mips/dec/int-handler.S
new file mode 100644
index 0000000..3b37909
--- /dev/null
+++ b/arch/mips/dec/int-handler.S
@@ -0,0 +1,297 @@
+/*
+ * arch/mips/dec/int-handler.S
+ *
+ * Copyright (C) 1995, 1996, 1997 Paul M. Antoine and Harald Koerfgen
+ * Copyright (C) 2000, 2001, 2002, 2003 Maciej W. Rozycki
+ *
+ * Written by Ralf Baechle and Andreas Busse, modified for DECStation
+ * support by Paul Antoine and Harald Koerfgen.
+ *
+ * completly rewritten:
+ * Copyright (C) 1998 Harald Koerfgen
+ *
+ * Rewritten extensively for controller-driven IRQ support
+ * by Maciej W. Rozycki.
+ */
+#include <linux/config.h>
+#include <asm/asm.h>
+#include <asm/regdef.h>
+#include <asm/mipsregs.h>
+#include <asm/stackframe.h>
+#include <asm/addrspace.h>
+
+#include <asm/dec/interrupts.h>
+#include <asm/dec/ioasic_addrs.h>
+#include <asm/dec/ioasic_ints.h>
+#include <asm/dec/kn01.h>
+#include <asm/dec/kn02.h>
+#include <asm/dec/kn02xa.h>
+#include <asm/dec/kn03.h>
+
+
+ .text
+ .set noreorder
+/*
+ * decstation_handle_int: Interrupt handler for DECStations
+ *
+ * We follow the model in the Indy interrupt code by David Miller, where he
+ * says: a lot of complication here is taken away because:
+ *
+ * 1) We handle one interrupt and return, sitting in a loop
+ * and moving across all the pending IRQ bits in the cause
+ * register is _NOT_ the answer, the common case is one
+ * pending IRQ so optimize in that direction.
+ *
+ * 2) We need not check against bits in the status register
+ * IRQ mask, that would make this routine slow as hell.
+ *
+ * 3) Linux only thinks in terms of all IRQs on or all IRQs
+ * off, nothing in between like BSD spl() brain-damage.
+ *
+ * Furthermore, the IRQs on the DECStations look basically (barring
+ * software IRQs which we don't use at all) like...
+ *
+ * DS2100/3100's, aka kn01, aka Pmax:
+ *
+ * MIPS IRQ Source
+ * -------- ------
+ * 0 Software (ignored)
+ * 1 Software (ignored)
+ * 2 SCSI
+ * 3 Lance Ethernet
+ * 4 DZ11 serial
+ * 5 RTC
+ * 6 Memory Controller
+ * 7 FPU
+ *
+ * DS5000/200, aka kn02, aka 3max:
+ *
+ * MIPS IRQ Source
+ * -------- ------
+ * 0 Software (ignored)
+ * 1 Software (ignored)
+ * 2 TurboChannel
+ * 3 RTC
+ * 4 Reserved
+ * 5 Memory Controller
+ * 6 Reserved
+ * 7 FPU
+ *
+ * DS5000/1xx's, aka kn02ba, aka 3min:
+ *
+ * MIPS IRQ Source
+ * -------- ------
+ * 0 Software (ignored)
+ * 1 Software (ignored)
+ * 2 TurboChannel Slot 0
+ * 3 TurboChannel Slot 1
+ * 4 TurboChannel Slot 2
+ * 5 TurboChannel Slot 3 (ASIC)
+ * 6 Halt button
+ * 7 FPU/R4k timer
+ *
+ * DS5000/2x's, aka kn02ca, aka maxine:
+ *
+ * MIPS IRQ Source
+ * -------- ------
+ * 0 Software (ignored)
+ * 1 Software (ignored)
+ * 2 Periodic Interrupt (100usec)
+ * 3 RTC
+ * 4 I/O write timeout
+ * 5 TurboChannel (ASIC)
+ * 6 Halt Keycode from Access.Bus keyboard (CTRL-ALT-ENTER)
+ * 7 FPU/R4k timer
+ *
+ * DS5000/2xx's, aka kn03, aka 3maxplus:
+ *
+ * MIPS IRQ Source
+ * -------- ------
+ * 0 Software (ignored)
+ * 1 Software (ignored)
+ * 2 System Board (ASIC)
+ * 3 RTC
+ * 4 Reserved
+ * 5 Memory
+ * 6 Halt Button
+ * 7 FPU/R4k timer
+ *
+ * We handle the IRQ according to _our_ priority (see setup.c),
+ * then we just return. If multiple IRQs are pending then we will
+ * just take another exception, big deal.
+ */
+ .align 5
+ NESTED(decstation_handle_int, PT_SIZE, ra)
+ .set noat
+ SAVE_ALL
+ CLI # TEST: interrupts should be off
+ .set at
+ .set noreorder
+
+ /*
+ * Get pending Interrupts
+ */
+ mfc0 t0,CP0_CAUSE # get pending interrupts
+ mfc0 t1,CP0_STATUS
+#ifdef CONFIG_MIPS32
+ lw t2,cpu_fpu_mask
+#endif
+ andi t0,ST0_IM # CAUSE.CE may be non-zero!
+ and t0,t1 # isolate allowed ones
+
+ beqz t0,spurious
+
+#ifdef CONFIG_MIPS32
+ and t2,t0
+ bnez t2,fpu # handle FPU immediately
+#endif
+
+ /*
+ * Find irq with highest priority
+ */
+ PTR_LA t1,cpu_mask_nr_tbl
+1: lw t2,(t1)
+ nop
+ and t2,t0
+ beqz t2,1b
+ addu t1,2*PTRSIZE # delay slot
+
+ /*
+ * Do the low-level stuff
+ */
+ lw a0,(-PTRSIZE)(t1)
+ nop
+ bgez a0,handle_it # irq_nr >= 0?
+ # irq_nr < 0: it is an address
+ nop
+ jr a0
+ # a trick to save a branch:
+ lui t2,(KN03_IOASIC_BASE>>16)&0xffff
+ # upper part of IOASIC Address
+
+/*
+ * Handle "IRQ Controller" Interrupts
+ * Masked Interrupts are still visible and have to be masked "by hand".
+ */
+ FEXPORT(kn02_io_int) # 3max
+ lui t0,(KN02_CSR_BASE>>16)&0xffff
+ # get interrupt status and mask
+ lw t0,(t0)
+ nop
+ andi t1,t0,KN02_IRQ_ALL
+ b 1f
+ srl t0,16 # shift interrupt mask
+
+ FEXPORT(kn02xa_io_int) # 3min/maxine
+ lui t2,(KN02XA_IOASIC_BASE>>16)&0xffff
+ # upper part of IOASIC Address
+
+ FEXPORT(kn03_io_int) # 3max+ (t2 loaded earlier)
+ lw t0,IO_REG_SIR(t2) # get status: IOASIC sir
+ lw t1,IO_REG_SIMR(t2) # get mask: IOASIC simr
+ nop
+
+1: and t0,t1 # mask out allowed ones
+
+ beqz t0,spurious
+
+ /*
+ * Find irq with highest priority
+ */
+ PTR_LA t1,asic_mask_nr_tbl
+2: lw t2,(t1)
+ nop
+ and t2,t0
+ beq zero,t2,2b
+ addu t1,2*PTRSIZE # delay slot
+
+ /*
+ * Do the low-level stuff
+ */
+ lw a0,%lo(-PTRSIZE)(t1)
+ nop
+ bgez a0,handle_it # irq_nr >= 0?
+ # irq_nr < 0: it is an address
+ nop
+ jr a0
+ nop # delay slot
+
+/*
+ * Dispatch low-priority interrupts. We reconsider all status
+ * bits again, which looks like a lose, but it makes the code
+ * simple and O(log n), so it gets compensated.
+ */
+ FEXPORT(cpu_all_int) # HALT, timers, software junk
+ li a0,DEC_CPU_IRQ_BASE
+ srl t0,CAUSEB_IP
+ li t1,CAUSEF_IP>>CAUSEB_IP # mask
+ b 1f
+ li t2,4 # nr of bits / 2
+
+ FEXPORT(kn02_all_int) # impossible ?
+ li a0,KN02_IRQ_BASE
+ li t1,KN02_IRQ_ALL # mask
+ b 1f
+ li t2,4 # nr of bits / 2
+
+ FEXPORT(asic_all_int) # various I/O ASIC junk
+ li a0,IO_IRQ_BASE
+ li t1,IO_IRQ_ALL # mask
+ b 1f
+ li t2,8 # nr of bits / 2
+
+/*
+ * Dispatch DMA interrupts -- O(log n).
+ */
+ FEXPORT(asic_dma_int) # I/O ASIC DMA events
+ li a0,IO_IRQ_BASE+IO_INR_DMA
+ srl t0,IO_INR_DMA
+ li t1,IO_IRQ_DMA>>IO_INR_DMA # mask
+ li t2,8 # nr of bits / 2
+
+ /*
+ * Find irq with highest priority.
+ * Highest irq number takes precedence.
+ */
+1: srlv t3,t1,t2
+2: xor t1,t3
+ and t3,t0,t1
+ beqz t3,3f
+ nop
+ move t0,t3
+ addu a0,t2
+3: srl t2,1
+ bnez t2,2b
+ srlv t3,t1,t2
+
+handle_it:
+ jal do_IRQ
+ move a1,sp
+
+ j ret_from_irq
+ nop
+
+#ifdef CONFIG_MIPS32
+fpu:
+ j handle_fpe_int
+ nop
+#endif
+
+spurious:
+ j spurious_interrupt
+ nop
+ END(decstation_handle_int)
+
+/*
+ * Generic unimplemented interrupt routines -- cpu_mask_nr_tbl
+ * and asic_mask_nr_tbl are initialized to point all interrupts here.
+ * The tables are then filled in by machine-specific initialisation
+ * in dec_setup().
+ */
+ FEXPORT(dec_intr_unimplemented)
+ move a1,t0 # cheats way of printing an arg!
+ PANIC("Unimplemented cpu interrupt! CP0_CAUSE: 0x%08x");
+
+ FEXPORT(asic_intr_unimplemented)
+ move a1,t0 # cheats way of printing an arg!
+ PANIC("Unimplemented asic interrupt! ASIC ISR: 0x%08x");
diff --git a/arch/mips/dec/ioasic-irq.c b/arch/mips/dec/ioasic-irq.c
new file mode 100644
index 0000000..d5bca5d
--- /dev/null
+++ b/arch/mips/dec/ioasic-irq.c
@@ -0,0 +1,157 @@
+/*
+ * linux/arch/mips/dec/ioasic-irq.c
+ *
+ * DEC I/O ASIC interrupts.
+ *
+ * Copyright (c) 2002, 2003 Maciej W. Rozycki
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+
+#include <asm/dec/ioasic.h>
+#include <asm/dec/ioasic_addrs.h>
+#include <asm/dec/ioasic_ints.h>
+
+
+static DEFINE_SPINLOCK(ioasic_lock);
+
+static int ioasic_irq_base;
+
+
+static inline void unmask_ioasic_irq(unsigned int irq)
+{
+ u32 simr;
+
+ simr = ioasic_read(IO_REG_SIMR);
+ simr |= (1 << (irq - ioasic_irq_base));
+ ioasic_write(IO_REG_SIMR, simr);
+}
+
+static inline void mask_ioasic_irq(unsigned int irq)
+{
+ u32 simr;
+
+ simr = ioasic_read(IO_REG_SIMR);
+ simr &= ~(1 << (irq - ioasic_irq_base));
+ ioasic_write(IO_REG_SIMR, simr);
+}
+
+static inline void clear_ioasic_irq(unsigned int irq)
+{
+ u32 sir;
+
+ sir = ~(1 << (irq - ioasic_irq_base));
+ ioasic_write(IO_REG_SIR, sir);
+}
+
+static inline void enable_ioasic_irq(unsigned int irq)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&ioasic_lock, flags);
+ unmask_ioasic_irq(irq);
+ spin_unlock_irqrestore(&ioasic_lock, flags);
+}
+
+static inline void disable_ioasic_irq(unsigned int irq)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&ioasic_lock, flags);
+ mask_ioasic_irq(irq);
+ spin_unlock_irqrestore(&ioasic_lock, flags);
+}
+
+
+static inline unsigned int startup_ioasic_irq(unsigned int irq)
+{
+ enable_ioasic_irq(irq);
+ return 0;
+}
+
+#define shutdown_ioasic_irq disable_ioasic_irq
+
+static inline void ack_ioasic_irq(unsigned int irq)
+{
+ spin_lock(&ioasic_lock);
+ mask_ioasic_irq(irq);
+ spin_unlock(&ioasic_lock);
+ fast_iob();
+}
+
+static inline void end_ioasic_irq(unsigned int irq)
+{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
+ enable_ioasic_irq(irq);
+}
+
+static struct hw_interrupt_type ioasic_irq_type = {
+ .typename = "IO-ASIC",
+ .startup = startup_ioasic_irq,
+ .shutdown = shutdown_ioasic_irq,
+ .enable = enable_ioasic_irq,
+ .disable = disable_ioasic_irq,
+ .ack = ack_ioasic_irq,
+ .end = end_ioasic_irq,
+};
+
+
+#define startup_ioasic_dma_irq startup_ioasic_irq
+
+#define shutdown_ioasic_dma_irq shutdown_ioasic_irq
+
+#define enable_ioasic_dma_irq enable_ioasic_irq
+
+#define disable_ioasic_dma_irq disable_ioasic_irq
+
+#define ack_ioasic_dma_irq ack_ioasic_irq
+
+static inline void end_ioasic_dma_irq(unsigned int irq)
+{
+ clear_ioasic_irq(irq);
+ fast_iob();
+ end_ioasic_irq(irq);
+}
+
+static struct hw_interrupt_type ioasic_dma_irq_type = {
+ .typename = "IO-ASIC-DMA",
+ .startup = startup_ioasic_dma_irq,
+ .shutdown = shutdown_ioasic_dma_irq,
+ .enable = enable_ioasic_dma_irq,
+ .disable = disable_ioasic_dma_irq,
+ .ack = ack_ioasic_dma_irq,
+ .end = end_ioasic_dma_irq,
+};
+
+
+void __init init_ioasic_irqs(int base)
+{
+ int i;
+
+ /* Mask interrupts. */
+ ioasic_write(IO_REG_SIMR, 0);
+ fast_iob();
+
+ for (i = base; i < base + IO_INR_DMA; i++) {
+ irq_desc[i].status = IRQ_DISABLED;
+ irq_desc[i].action = 0;
+ irq_desc[i].depth = 1;
+ irq_desc[i].handler = &ioasic_irq_type;
+ }
+ for (; i < base + IO_IRQ_LINES; i++) {
+ irq_desc[i].status = IRQ_DISABLED;
+ irq_desc[i].action = 0;
+ irq_desc[i].depth = 1;
+ irq_desc[i].handler = &ioasic_dma_irq_type;
+ }
+
+ ioasic_irq_base = base;
+}
diff --git a/arch/mips/dec/kn02-irq.c b/arch/mips/dec/kn02-irq.c
new file mode 100644
index 0000000..e0bfcd1
--- /dev/null
+++ b/arch/mips/dec/kn02-irq.c
@@ -0,0 +1,127 @@
+/*
+ * linux/arch/mips/dec/kn02-irq.c
+ *
+ * DECstation 5000/200 (KN02) Control and Status Register
+ * interrupts.
+ *
+ * Copyright (c) 2002, 2003 Maciej W. Rozycki
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+
+#include <asm/dec/kn02.h>
+
+
+/*
+ * Bits 7:0 of the Control Register are write-only -- the
+ * corresponding bits of the Status Register have a different
+ * meaning. Hence we use a cache. It speeds up things a bit
+ * as well.
+ *
+ * There is no default value -- it has to be initialized.
+ */
+u32 cached_kn02_csr;
+DEFINE_SPINLOCK(kn02_lock);
+
+
+static int kn02_irq_base;
+
+
+static inline void unmask_kn02_irq(unsigned int irq)
+{
+ volatile u32 *csr = (volatile u32 *)KN02_CSR_BASE;
+
+ cached_kn02_csr |= (1 << (irq - kn02_irq_base + 16));
+ *csr = cached_kn02_csr;
+}
+
+static inline void mask_kn02_irq(unsigned int irq)
+{
+ volatile u32 *csr = (volatile u32 *)KN02_CSR_BASE;
+
+ cached_kn02_csr &= ~(1 << (irq - kn02_irq_base + 16));
+ *csr = cached_kn02_csr;
+}
+
+static inline void enable_kn02_irq(unsigned int irq)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&kn02_lock, flags);
+ unmask_kn02_irq(irq);
+ spin_unlock_irqrestore(&kn02_lock, flags);
+}
+
+static inline void disable_kn02_irq(unsigned int irq)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&kn02_lock, flags);
+ mask_kn02_irq(irq);
+ spin_unlock_irqrestore(&kn02_lock, flags);
+}
+
+
+static unsigned int startup_kn02_irq(unsigned int irq)
+{
+ enable_kn02_irq(irq);
+ return 0;
+}
+
+#define shutdown_kn02_irq disable_kn02_irq
+
+static void ack_kn02_irq(unsigned int irq)
+{
+ spin_lock(&kn02_lock);
+ mask_kn02_irq(irq);
+ spin_unlock(&kn02_lock);
+ iob();
+}
+
+static void end_kn02_irq(unsigned int irq)
+{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
+ enable_kn02_irq(irq);
+}
+
+static struct hw_interrupt_type kn02_irq_type = {
+ .typename = "KN02-CSR",
+ .startup = startup_kn02_irq,
+ .shutdown = shutdown_kn02_irq,
+ .enable = enable_kn02_irq,
+ .disable = disable_kn02_irq,
+ .ack = ack_kn02_irq,
+ .end = end_kn02_irq,
+};
+
+
+void __init init_kn02_irqs(int base)
+{
+ volatile u32 *csr = (volatile u32 *)KN02_CSR_BASE;
+ unsigned long flags;
+ int i;
+
+ /* Mask interrupts. */
+ spin_lock_irqsave(&kn02_lock, flags);
+ cached_kn02_csr &= ~KN03_CSR_IOINTEN;
+ *csr = cached_kn02_csr;
+ iob();
+ spin_unlock_irqrestore(&kn02_lock, flags);
+
+ for (i = base; i < base + KN02_IRQ_LINES; i++) {
+ irq_desc[i].status = IRQ_DISABLED;
+ irq_desc[i].action = 0;
+ irq_desc[i].depth = 1;
+ irq_desc[i].handler = &kn02_irq_type;
+ }
+
+ kn02_irq_base = base;
+}
diff --git a/arch/mips/dec/prom/Makefile b/arch/mips/dec/prom/Makefile
new file mode 100644
index 0000000..373822e
--- /dev/null
+++ b/arch/mips/dec/prom/Makefile
@@ -0,0 +1,11 @@
+#
+# Makefile for the DECstation prom monitor library routines
+# under Linux.
+#
+
+lib-y += init.o memory.o cmdline.o identify.o console.o
+
+lib-$(CONFIG_MIPS32) += locore.o
+lib-$(CONFIG_MIPS64) += call_o32.o
+
+EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/dec/prom/call_o32.S b/arch/mips/dec/prom/call_o32.S
new file mode 100644
index 0000000..0dd56db
--- /dev/null
+++ b/arch/mips/dec/prom/call_o32.S
@@ -0,0 +1,91 @@
+/*
+ * arch/mips/dec/call_o32.S
+ *
+ * O32 interface for the 64 (or N32) ABI.
+ *
+ * Copyright (C) 2002 Maciej W. Rozycki
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <asm/asm.h>
+#include <asm/regdef.h>
+
+/* Maximum number of arguments supported. Must be even! */
+#define O32_ARGC 32
+/* Number of static registers we save. */
+#define O32_STATC 11
+/* Frame size for both of the above. */
+#define O32_FRAMESZ (4 * O32_ARGC + SZREG * O32_STATC)
+
+ .text
+
+/*
+ * O32 function call dispatcher, for interfacing 32-bit ROM routines.
+ *
+ * The standard 64 (N32) calling sequence is supported, with a0
+ * holding a function pointer, a1-a7 -- its first seven arguments
+ * and the stack -- remaining ones (up to O32_ARGC, including a1-a7).
+ * Static registers, gp and fp are preserved, v0 holds a result.
+ * This code relies on the called o32 function for sp and ra
+ * restoration and thus both this dispatcher and the current stack
+ * have to be placed in a KSEGx (or KUSEG) address space. Any
+ * pointers passed have to point to addresses within one of these
+ * spaces as well.
+ */
+NESTED(call_o32, O32_FRAMESZ, ra)
+ REG_SUBU sp,O32_FRAMESZ
+
+ REG_S ra,O32_FRAMESZ-1*SZREG(sp)
+ REG_S fp,O32_FRAMESZ-2*SZREG(sp)
+ REG_S gp,O32_FRAMESZ-3*SZREG(sp)
+ REG_S s7,O32_FRAMESZ-4*SZREG(sp)
+ REG_S s6,O32_FRAMESZ-5*SZREG(sp)
+ REG_S s5,O32_FRAMESZ-6*SZREG(sp)
+ REG_S s4,O32_FRAMESZ-7*SZREG(sp)
+ REG_S s3,O32_FRAMESZ-8*SZREG(sp)
+ REG_S s2,O32_FRAMESZ-9*SZREG(sp)
+ REG_S s1,O32_FRAMESZ-10*SZREG(sp)
+ REG_S s0,O32_FRAMESZ-11*SZREG(sp)
+
+ move jp,a0
+
+ sll a0,a1,zero
+ sll a1,a2,zero
+ sll a2,a3,zero
+ sll a3,a4,zero
+ sw a5,0x10(sp)
+ sw a6,0x14(sp)
+ sw a7,0x18(sp)
+
+ PTR_LA t0,O32_FRAMESZ(sp)
+ PTR_LA t1,0x1c(sp)
+ li t2,O32_ARGC-7
+1:
+ lw t3,(t0)
+ REG_ADDU t0,SZREG
+ sw t3,(t1)
+ REG_SUBU t2,1
+ REG_ADDU t1,4
+ bnez t2,1b
+
+ jalr jp
+
+ REG_L s0,O32_FRAMESZ-11*SZREG(sp)
+ REG_L s1,O32_FRAMESZ-10*SZREG(sp)
+ REG_L s2,O32_FRAMESZ-9*SZREG(sp)
+ REG_L s3,O32_FRAMESZ-8*SZREG(sp)
+ REG_L s4,O32_FRAMESZ-7*SZREG(sp)
+ REG_L s5,O32_FRAMESZ-6*SZREG(sp)
+ REG_L s6,O32_FRAMESZ-5*SZREG(sp)
+ REG_L s7,O32_FRAMESZ-4*SZREG(sp)
+ REG_L gp,O32_FRAMESZ-3*SZREG(sp)
+ REG_L fp,O32_FRAMESZ-2*SZREG(sp)
+ REG_L ra,O32_FRAMESZ-1*SZREG(sp)
+
+ REG_ADDU sp,O32_FRAMESZ
+ jr ra
+END(call_o32)
diff --git a/arch/mips/dec/prom/cmdline.c b/arch/mips/dec/prom/cmdline.c
new file mode 100644
index 0000000..c3490be
--- /dev/null
+++ b/arch/mips/dec/prom/cmdline.c
@@ -0,0 +1,39 @@
+/*
+ * cmdline.c: read the command line passed to us by the PROM.
+ *
+ * Copyright (C) 1998 Harald Koerfgen
+ * Copyright (C) 2002, 2004 Maciej W. Rozycki
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/types.h>
+
+#include <asm/bootinfo.h>
+#include <asm/dec/prom.h>
+
+#undef PROM_DEBUG
+
+void __init prom_init_cmdline(s32 argc, s32 *argv, u32 magic)
+{
+ char *arg;
+ int start_arg, i;
+
+ /*
+ * collect args and prepare cmd_line
+ */
+ if (!prom_is_rex(magic))
+ start_arg = 1;
+ else
+ start_arg = 2;
+ for (i = start_arg; i < argc; i++) {
+ arg = (void *)(long)(argv[i]);
+ strcat(arcs_cmdline, arg);
+ if (i < (argc - 1))
+ strcat(arcs_cmdline, " ");
+ }
+
+#ifdef PROM_DEBUG
+ printk("arcs_cmdline: %s\n", &(arcs_cmdline[0]));
+#endif
+}
diff --git a/arch/mips/dec/prom/console.c b/arch/mips/dec/prom/console.c
new file mode 100644
index 0000000..cade16e
--- /dev/null
+++ b/arch/mips/dec/prom/console.c
@@ -0,0 +1,55 @@
+/*
+ * arch/mips/dec/prom/console.c
+ *
+ * DECstation PROM-based early console support.
+ *
+ * Copyright (C) 2004 Maciej W. Rozycki
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#include <linux/console.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+
+#include <asm/dec/prom.h>
+
+static void __init prom_console_write(struct console *con, const char *s,
+ unsigned int c)
+{
+ static char sfmt[] __initdata = "%%%us";
+ char fmt[13];
+
+ snprintf(fmt, sizeof(fmt), sfmt, c);
+ prom_printf(fmt, s);
+}
+
+static struct console promcons __initdata = {
+ .name = "prom",
+ .write = prom_console_write,
+ .flags = CON_PRINTBUFFER,
+ .index = -1,
+};
+
+static int promcons_output __initdata = 0;
+
+void __init register_prom_console(void)
+{
+ if (!promcons_output) {
+ promcons_output = 1;
+ register_console(&promcons);
+ }
+}
+
+void __init unregister_prom_console(void)
+{
+ if (promcons_output) {
+ unregister_console(&promcons);
+ promcons_output = 0;
+ }
+}
+
+void disable_early_printk(void)
+ __attribute__((alias("unregister_prom_console")));
diff --git a/arch/mips/dec/prom/dectypes.h b/arch/mips/dec/prom/dectypes.h
new file mode 100644
index 0000000..707b6f1
--- /dev/null
+++ b/arch/mips/dec/prom/dectypes.h
@@ -0,0 +1,14 @@
+#ifndef DECTYPES
+#define DECTYPES
+
+#define DS2100_3100 1 /* DS2100/3100 Pmax */
+#define DS5000_200 2 /* DS5000/200 3max */
+#define DS5000_1XX 3 /* DS5000/1xx kmin */
+#define DS5000_2X0 4 /* DS5000/2x0 3max+ */
+#define DS5800 5 /* DS5800 Isis */
+#define DS5400 6 /* DS5400 MIPSfair */
+#define DS5000_XX 7 /* DS5000/xx maxine */
+#define DS5500 11 /* DS5500 MIPSfair-2 */
+#define DS5100 12 /* DS5100 MIPSmate */
+
+#endif
diff --git a/arch/mips/dec/prom/identify.c b/arch/mips/dec/prom/identify.c
new file mode 100644
index 0000000..9380588
--- /dev/null
+++ b/arch/mips/dec/prom/identify.c
@@ -0,0 +1,177 @@
+/*
+ * identify.c: machine identification code.
+ *
+ * Copyright (C) 1998 Harald Koerfgen and Paul M. Antoine
+ * Copyright (C) 2002, 2003, 2004 Maciej W. Rozycki
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/mc146818rtc.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/types.h>
+
+#include <asm/bootinfo.h>
+#include <asm/dec/ioasic.h>
+#include <asm/dec/ioasic_addrs.h>
+#include <asm/dec/kn01.h>
+#include <asm/dec/kn02.h>
+#include <asm/dec/kn02ba.h>
+#include <asm/dec/kn02ca.h>
+#include <asm/dec/kn03.h>
+#include <asm/dec/kn230.h>
+#include <asm/dec/prom.h>
+
+#include "dectypes.h"
+
+extern unsigned long mips_machgroup;
+extern unsigned long mips_machtype;
+
+static const char *dec_system_strings[] = {
+ [MACH_DSUNKNOWN] "unknown DECstation",
+ [MACH_DS23100] "DECstation 2100/3100",
+ [MACH_DS5100] "DECsystem 5100",
+ [MACH_DS5000_200] "DECstation 5000/200",
+ [MACH_DS5000_1XX] "DECstation 5000/1xx",
+ [MACH_DS5000_XX] "Personal DECstation 5000/xx",
+ [MACH_DS5000_2X0] "DECstation 5000/2x0",
+ [MACH_DS5400] "DECsystem 5400",
+ [MACH_DS5500] "DECsystem 5500",
+ [MACH_DS5800] "DECsystem 5800",
+ [MACH_DS5900] "DECsystem 5900",
+};
+
+const char *get_system_type(void)
+{
+#define STR_BUF_LEN 64
+ static char system[STR_BUF_LEN];
+ static int called = 0;
+
+ if (called == 0) {
+ called = 1;
+ snprintf(system, STR_BUF_LEN, "Digital %s",
+ dec_system_strings[mips_machtype]);
+ }
+
+ return system;
+}
+
+
+/*
+ * Setup essential system-specific memory addresses. We need them
+ * early. Semantically the functions belong to prom/init.c, but they
+ * are compact enough we want them inlined. --macro
+ */
+volatile u8 *dec_rtc_base;
+
+EXPORT_SYMBOL(dec_rtc_base);
+
+static inline void prom_init_kn01(void)
+{
+ dec_rtc_base = (void *)KN01_RTC_BASE;
+ dec_kn_slot_size = KN01_SLOT_SIZE;
+}
+
+static inline void prom_init_kn230(void)
+{
+ dec_rtc_base = (void *)KN01_RTC_BASE;
+ dec_kn_slot_size = KN01_SLOT_SIZE;
+}
+
+static inline void prom_init_kn02(void)
+{
+ dec_rtc_base = (void *)KN02_RTC_BASE;
+ dec_kn_slot_size = KN02_SLOT_SIZE;
+}
+
+static inline void prom_init_kn02xa(void)
+{
+ ioasic_base = (void *)KN02XA_IOASIC_BASE;
+ dec_rtc_base = (void *)KN02XA_RTC_BASE;
+ dec_kn_slot_size = IOASIC_SLOT_SIZE;
+}
+
+static inline void prom_init_kn03(void)
+{
+ ioasic_base = (void *)KN03_IOASIC_BASE;
+ dec_rtc_base = (void *)KN03_RTC_BASE;
+ dec_kn_slot_size = IOASIC_SLOT_SIZE;
+}
+
+
+void __init prom_identify_arch(u32 magic)
+{
+ unsigned char dec_cpunum, dec_firmrev, dec_etc, dec_systype;
+ u32 dec_sysid;
+
+ if (!prom_is_rex(magic)) {
+ dec_sysid = simple_strtoul(prom_getenv("systype"),
+ (char **)0, 0);
+ } else {
+ dec_sysid = rex_getsysid();
+ if (dec_sysid == 0) {
+ printk("Zero sysid returned from PROM! "
+ "Assuming a PMAX-like machine.\n");
+ dec_sysid = 1;
+ }
+ }
+
+ dec_cpunum = (dec_sysid & 0xff000000) >> 24;
+ dec_systype = (dec_sysid & 0xff0000) >> 16;
+ dec_firmrev = (dec_sysid & 0xff00) >> 8;
+ dec_etc = dec_sysid & 0xff;
+
+ /* We're obviously one of the DEC machines */
+ mips_machgroup = MACH_GROUP_DEC;
+
+ /*
+ * FIXME: This may not be an exhaustive list of DECStations/Servers!
+ * Put all model-specific initialisation calls here.
+ */
+ switch (dec_systype) {
+ case DS2100_3100:
+ mips_machtype = MACH_DS23100;
+ prom_init_kn01();
+ break;
+ case DS5100: /* DS5100 MIPSMATE */
+ mips_machtype = MACH_DS5100;
+ prom_init_kn230();
+ break;
+ case DS5000_200: /* DS5000 3max */
+ mips_machtype = MACH_DS5000_200;
+ prom_init_kn02();
+ break;
+ case DS5000_1XX: /* DS5000/100 3min */
+ mips_machtype = MACH_DS5000_1XX;
+ prom_init_kn02xa();
+ break;
+ case DS5000_2X0: /* DS5000/240 3max+ or DS5900 bigmax */
+ mips_machtype = MACH_DS5000_2X0;
+ prom_init_kn03();
+ if (!(ioasic_read(IO_REG_SIR) & KN03_IO_INR_3MAXP))
+ mips_machtype = MACH_DS5900;
+ break;
+ case DS5000_XX: /* Personal DS5000/xx maxine */
+ mips_machtype = MACH_DS5000_XX;
+ prom_init_kn02xa();
+ break;
+ case DS5800: /* DS5800 Isis */
+ mips_machtype = MACH_DS5800;
+ break;
+ case DS5400: /* DS5400 MIPSfair */
+ mips_machtype = MACH_DS5400;
+ break;
+ case DS5500: /* DS5500 MIPSfair-2 */
+ mips_machtype = MACH_DS5500;
+ break;
+ default:
+ mips_machtype = MACH_DSUNKNOWN;
+ break;
+ }
+
+ if (mips_machtype == MACH_DSUNKNOWN)
+ printk("This is an %s, id is %x\n",
+ dec_system_strings[mips_machtype], dec_systype);
+ else
+ printk("This is a %s\n", dec_system_strings[mips_machtype]);
+}
diff --git a/arch/mips/dec/prom/init.c b/arch/mips/dec/prom/init.c
new file mode 100644
index 0000000..60f7425
--- /dev/null
+++ b/arch/mips/dec/prom/init.c
@@ -0,0 +1,134 @@
+/*
+ * init.c: PROM library initialisation code.
+ *
+ * Copyright (C) 1998 Harald Koerfgen
+ * Copyright (C) 2002, 2004 Maciej W. Rozycki
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <linux/string.h>
+#include <linux/types.h>
+
+#include <asm/bootinfo.h>
+#include <asm/cpu.h>
+#include <asm/processor.h>
+
+#include <asm/dec/prom.h>
+
+
+int (*__rex_bootinit)(void);
+int (*__rex_bootread)(void);
+int (*__rex_getbitmap)(memmap *);
+unsigned long *(*__rex_slot_address)(int);
+void *(*__rex_gettcinfo)(void);
+int (*__rex_getsysid)(void);
+void (*__rex_clear_cache)(void);
+
+int (*__prom_getchar)(void);
+char *(*__prom_getenv)(char *);
+int (*__prom_printf)(char *, ...);
+
+int (*__pmax_open)(char*, int);
+int (*__pmax_lseek)(int, long, int);
+int (*__pmax_read)(int, void *, int);
+int (*__pmax_close)(int);
+
+
+/*
+ * Detect which PROM the DECSTATION has, and set the callback vectors
+ * appropriately.
+ */
+void __init which_prom(s32 magic, s32 *prom_vec)
+{
+ /*
+ * No sign of the REX PROM's magic number means we assume a non-REX
+ * machine (i.e. we're on a DS2100/3100, DS5100 or DS5000/2xx)
+ */
+ if (prom_is_rex(magic)) {
+ /*
+ * Set up prom abstraction structure with REX entry points.
+ */
+ __rex_bootinit =
+ (void *)(long)*(prom_vec + REX_PROM_BOOTINIT);
+ __rex_bootread =
+ (void *)(long)*(prom_vec + REX_PROM_BOOTREAD);
+ __rex_getbitmap =
+ (void *)(long)*(prom_vec + REX_PROM_GETBITMAP);
+ __prom_getchar =
+ (void *)(long)*(prom_vec + REX_PROM_GETCHAR);
+ __prom_getenv =
+ (void *)(long)*(prom_vec + REX_PROM_GETENV);
+ __rex_getsysid =
+ (void *)(long)*(prom_vec + REX_PROM_GETSYSID);
+ __rex_gettcinfo =
+ (void *)(long)*(prom_vec + REX_PROM_GETTCINFO);
+ __prom_printf =
+ (void *)(long)*(prom_vec + REX_PROM_PRINTF);
+ __rex_slot_address =
+ (void *)(long)*(prom_vec + REX_PROM_SLOTADDR);
+ __rex_clear_cache =
+ (void *)(long)*(prom_vec + REX_PROM_CLEARCACHE);
+ } else {
+ /*
+ * Set up prom abstraction structure with non-REX entry points.
+ */
+ __prom_getchar = (void *)PMAX_PROM_GETCHAR;
+ __prom_getenv = (void *)PMAX_PROM_GETENV;
+ __prom_printf = (void *)PMAX_PROM_PRINTF;
+ __pmax_open = (void *)PMAX_PROM_OPEN;
+ __pmax_lseek = (void *)PMAX_PROM_LSEEK;
+ __pmax_read = (void *)PMAX_PROM_READ;
+ __pmax_close = (void *)PMAX_PROM_CLOSE;
+ }
+}
+
+void __init prom_init(void)
+{
+ extern void dec_machine_halt(void);
+ static char cpu_msg[] __initdata =
+ "Sorry, this kernel is compiled for a wrong CPU type!\n";
+ static char r3k_msg[] __initdata =
+ "Please recompile with \"CONFIG_CPU_R3000 = y\".\n";
+ static char r4k_msg[] __initdata =
+ "Please recompile with \"CONFIG_CPU_R4x00 = y\".\n";
+ s32 argc = fw_arg0;
+ s32 argv = fw_arg1;
+ u32 magic = fw_arg2;
+ s32 prom_vec = fw_arg3;
+
+ /*
+ * Determine which PROM we have
+ * (and therefore which machine we're on!)
+ */
+ which_prom(magic, prom_vec);
+
+ if (prom_is_rex(magic))
+ rex_clear_cache();
+
+ /* Register the early console. */
+ register_prom_console();
+
+ /* Were we compiled with the right CPU option? */
+#if defined(CONFIG_CPU_R3000)
+ if ((current_cpu_data.cputype == CPU_R4000SC) ||
+ (current_cpu_data.cputype == CPU_R4400SC)) {
+ printk(cpu_msg);
+ printk(r4k_msg);
+ dec_machine_halt();
+ }
+#endif
+
+#if defined(CONFIG_CPU_R4X00)
+ if ((current_cpu_data.cputype == CPU_R3000) ||
+ (current_cpu_data.cputype == CPU_R3000A)) {
+ printk(cpu_msg);
+ printk(r3k_msg);
+ dec_machine_halt();
+ }
+#endif
+
+ prom_meminit(magic);
+ prom_identify_arch(magic);
+ prom_init_cmdline(argc, argv, magic);
+}
diff --git a/arch/mips/dec/prom/locore.S b/arch/mips/dec/prom/locore.S
new file mode 100644
index 0000000..d9acdce
--- /dev/null
+++ b/arch/mips/dec/prom/locore.S
@@ -0,0 +1,30 @@
+/*
+ * locore.S
+ */
+#include <asm/asm.h>
+#include <asm/regdef.h>
+#include <asm/mipsregs.h>
+
+ .text
+
+/*
+ * Simple general exception handling routine. This one is used for the
+ * Memory sizing routine for pmax machines. HK
+ */
+
+NESTED(genexcept_early, 0, sp)
+ .set noat
+ .set noreorder
+
+ mfc0 k0, CP0_STATUS
+ la k1, mem_err
+
+ sw k0, 0(k1)
+
+ mfc0 k0, CP0_EPC
+ nop
+ addiu k0, 4 # skip the causing instruction
+ jr k0
+ rfe
+END(genexcept_early)
+
diff --git a/arch/mips/dec/prom/memory.c b/arch/mips/dec/prom/memory.c
new file mode 100644
index 0000000..e4f6f26
--- /dev/null
+++ b/arch/mips/dec/prom/memory.c
@@ -0,0 +1,130 @@
+/*
+ * memory.c: memory initialisation code.
+ *
+ * Copyright (C) 1998 Harald Koerfgen, Frieder Streffer and Paul M. Antoine
+ * Copyright (C) 2000, 2002 Maciej W. Rozycki
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/bootmem.h>
+#include <linux/types.h>
+
+#include <asm/addrspace.h>
+#include <asm/bootinfo.h>
+#include <asm/dec/machtype.h>
+#include <asm/dec/prom.h>
+#include <asm/page.h>
+#include <asm/sections.h>
+
+
+volatile unsigned long mem_err = 0; /* So we know an error occurred */
+
+/*
+ * Probe memory in 4MB chunks, waiting for an error to tell us we've fallen
+ * off the end of real memory. Only suitable for the 2100/3100's (PMAX).
+ */
+
+#define CHUNK_SIZE 0x400000
+
+static inline void pmax_setup_memory_region(void)
+{
+ volatile unsigned char *memory_page, dummy;
+ char old_handler[0x80];
+ extern char genexcept_early;
+
+ /* Install exception handler */
+ memcpy(&old_handler, (void *)(KSEG0 + 0x80), 0x80);
+ memcpy((void *)(KSEG0 + 0x80), &genexcept_early, 0x80);
+
+ /* read unmapped and uncached (KSEG1)
+ * DECstations have at least 4MB RAM
+ * Assume less than 480MB of RAM, as this is max for 5000/2xx
+ * FIXME this should be replaced by the first free page!
+ */
+ for (memory_page = (unsigned char *) KSEG1 + CHUNK_SIZE;
+ (mem_err== 0) && (memory_page < ((unsigned char *) KSEG1+0x1E000000));
+ memory_page += CHUNK_SIZE) {
+ dummy = *memory_page;
+ }
+ memcpy((void *)(KSEG0 + 0x80), &old_handler, 0x80);
+
+ add_memory_region(0, (unsigned long)memory_page - KSEG1 - CHUNK_SIZE,
+ BOOT_MEM_RAM);
+}
+
+/*
+ * Use the REX prom calls to get hold of the memory bitmap, and thence
+ * determine memory size.
+ */
+static inline void rex_setup_memory_region(void)
+{
+ int i, bitmap_size;
+ unsigned long mem_start = 0, mem_size = 0;
+ memmap *bm;
+
+ /* some free 64k */
+ bm = (memmap *)KSEG0ADDR(0x28000);
+
+ bitmap_size = rex_getbitmap(bm);
+
+ for (i = 0; i < bitmap_size; i++) {
+ /* FIXME: very simplistically only add full sets of pages */
+ if (bm->bitmap[i] == 0xff)
+ mem_size += (8 * bm->pagesize);
+ else if (!mem_size)
+ mem_start += (8 * bm->pagesize);
+ else {
+ add_memory_region(mem_start, mem_size, BOOT_MEM_RAM);
+ mem_start += mem_size + (8 * bm->pagesize);
+ mem_size = 0;
+ }
+ }
+ if (mem_size)
+ add_memory_region(mem_start, mem_size, BOOT_MEM_RAM);
+}
+
+void __init prom_meminit(u32 magic)
+{
+ if (!prom_is_rex(magic))
+ pmax_setup_memory_region();
+ else
+ rex_setup_memory_region();
+}
+
+unsigned long __init prom_free_prom_memory(void)
+{
+ unsigned long addr, end;
+
+ /*
+ * Free everything below the kernel itself but leave
+ * the first page reserved for the exception handlers.
+ */
+
+#if defined(CONFIG_DECLANCE) || defined(CONFIG_DECLANCE_MODULE)
+ /*
+ * Leave 128 KB reserved for Lance memory for
+ * IOASIC DECstations.
+ *
+ * XXX: save this address for use in dec_lance.c?
+ */
+ if (IOASIC)
+ end = __pa(&_text) - 0x00020000;
+ else
+#endif
+ end = __pa(&_text);
+
+ addr = PAGE_SIZE;
+ while (addr < end) {
+ ClearPageReserved(virt_to_page(__va(addr)));
+ set_page_count(virt_to_page(__va(addr)), 1);
+ free_page((unsigned long)__va(addr));
+ addr += PAGE_SIZE;
+ }
+
+ printk("Freeing unused PROM memory: %ldk freed\n",
+ (end - PAGE_SIZE) >> 10);
+
+ return end - PAGE_SIZE;
+}
diff --git a/arch/mips/dec/promcon.c b/arch/mips/dec/promcon.c
new file mode 100644
index 0000000..9f0972f
--- /dev/null
+++ b/arch/mips/dec/promcon.c
@@ -0,0 +1,55 @@
+/*
+ * Wrap-around code for a console using the
+ * DECstation PROM io-routines.
+ *
+ * Copyright (c) 1998 Harald Koerfgen
+ */
+
+#include <linux/tty.h>
+#include <linux/ptrace.h>
+#include <linux/init.h>
+#include <linux/console.h>
+#include <linux/fs.h>
+
+#include <asm/dec/prom.h>
+
+static void prom_console_write(struct console *co, const char *s,
+ unsigned count)
+{
+ unsigned i;
+
+ /*
+ * Now, do each character
+ */
+ for (i = 0; i < count; i++) {
+ if (*s == 10)
+ prom_printf("%c", 13);
+ prom_printf("%c", *s++);
+ }
+}
+
+static int __init prom_console_setup(struct console *co, char *options)
+{
+ return 0;
+}
+
+static struct console sercons =
+{
+ .name = "ttyS",
+ .write = prom_console_write,
+ .setup = prom_console_setup,
+ .flags = CON_PRINTBUFFER,
+ .index = -1,
+};
+
+/*
+ * Register console.
+ */
+
+static int __init prom_console_init(void)
+{
+ register_console(&sercons);
+
+ return 0;
+}
+console_initcall(prom_console_init);
diff --git a/arch/mips/dec/reset.c b/arch/mips/dec/reset.c
new file mode 100644
index 0000000..7e4d34d
--- /dev/null
+++ b/arch/mips/dec/reset.c
@@ -0,0 +1,41 @@
+/*
+ * Reset a DECstation machine.
+ *
+ * Copyright (C) 199x the Anonymous
+ * Copyright (C) 2001, 2002, 2003 Maciej W. Rozycki
+ */
+#include <linux/interrupt.h>
+#include <linux/linkage.h>
+
+#include <asm/addrspace.h>
+#include <asm/ptrace.h>
+
+typedef void ATTRIB_NORET (* noret_func_t)(void);
+
+static inline void ATTRIB_NORET back_to_prom(void)
+{
+ noret_func_t func = (void *) KSEG1ADDR(0x1fc00000);
+
+ func();
+}
+
+void ATTRIB_NORET dec_machine_restart(char *command)
+{
+ back_to_prom();
+}
+
+void ATTRIB_NORET dec_machine_halt(void)
+{
+ back_to_prom();
+}
+
+void ATTRIB_NORET dec_machine_power_off(void)
+{
+ /* DECstations don't have a software power switch */
+ back_to_prom();
+}
+
+irqreturn_t dec_intr_halt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ dec_machine_halt();
+}
diff --git a/arch/mips/dec/setup.c b/arch/mips/dec/setup.c
new file mode 100644
index 0000000..6a69309
--- /dev/null
+++ b/arch/mips/dec/setup.c
@@ -0,0 +1,750 @@
+/*
+ * Setup the interrupt stuff.
+ *
+ * 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) 1998 Harald Koerfgen
+ * Copyright (C) 2000, 2001, 2002, 2003 Maciej W. Rozycki
+ */
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/param.h>
+#include <linux/console.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+
+#include <asm/bootinfo.h>
+#include <asm/cpu.h>
+#include <asm/cpu-features.h>
+#include <asm/irq.h>
+#include <asm/irq_cpu.h>
+#include <asm/mipsregs.h>
+#include <asm/reboot.h>
+#include <asm/time.h>
+#include <asm/traps.h>
+#include <asm/wbflush.h>
+
+#include <asm/dec/interrupts.h>
+#include <asm/dec/ioasic.h>
+#include <asm/dec/ioasic_addrs.h>
+#include <asm/dec/ioasic_ints.h>
+#include <asm/dec/kn01.h>
+#include <asm/dec/kn02.h>
+#include <asm/dec/kn02ba.h>
+#include <asm/dec/kn02ca.h>
+#include <asm/dec/kn03.h>
+#include <asm/dec/kn230.h>
+
+
+extern void dec_machine_restart(char *command);
+extern void dec_machine_halt(void);
+extern void dec_machine_power_off(void);
+extern irqreturn_t dec_intr_halt(int irq, void *dev_id, struct pt_regs *regs);
+
+extern asmlinkage void decstation_handle_int(void);
+
+spinlock_t ioasic_ssr_lock;
+
+volatile u32 *ioasic_base;
+unsigned long dec_kn_slot_size;
+
+/*
+ * IRQ routing and priority tables. Priorites are set as follows:
+ *
+ * KN01 KN230 KN02 KN02-BA KN02-CA KN03
+ *
+ * MEMORY CPU CPU CPU ASIC CPU CPU
+ * RTC CPU CPU CPU ASIC CPU CPU
+ * DMA - - - ASIC ASIC ASIC
+ * SERIAL0 CPU CPU CSR ASIC ASIC ASIC
+ * SERIAL1 - - - ASIC - ASIC
+ * SCSI CPU CPU CSR ASIC ASIC ASIC
+ * ETHERNET CPU * CSR ASIC ASIC ASIC
+ * other - - - ASIC - -
+ * TC2 - - CSR CPU ASIC ASIC
+ * TC1 - - CSR CPU ASIC ASIC
+ * TC0 - - CSR CPU ASIC ASIC
+ * other - CPU - CPU ASIC ASIC
+ * other - - - - CPU CPU
+ *
+ * * -- shared with SCSI
+ */
+
+int dec_interrupt[DEC_NR_INTS] = {
+ [0 ... DEC_NR_INTS - 1] = -1
+};
+int_ptr cpu_mask_nr_tbl[DEC_MAX_CPU_INTS][2] = {
+ { { .i = ~0 }, { .p = dec_intr_unimplemented } },
+};
+int_ptr asic_mask_nr_tbl[DEC_MAX_ASIC_INTS][2] = {
+ { { .i = ~0 }, { .p = asic_intr_unimplemented } },
+};
+int cpu_fpu_mask = DEC_CPU_IRQ_MASK(DEC_CPU_INR_FPU);
+
+static struct irqaction ioirq = {
+ .handler = no_action,
+ .name = "cascade",
+};
+static struct irqaction fpuirq = {
+ .handler = no_action,
+ .name = "fpu",
+};
+
+static struct irqaction busirq = {
+ .flags = SA_INTERRUPT,
+ .name = "bus error",
+};
+
+static struct irqaction haltirq = {
+ .handler = dec_intr_halt,
+ .name = "halt",
+};
+
+
+/*
+ * Bus error (DBE/IBE exceptions and bus interrupts) handling setup.
+ */
+void __init dec_be_init(void)
+{
+ switch (mips_machtype) {
+ case MACH_DS23100: /* DS2100/DS3100 Pmin/Pmax */
+ busirq.flags |= SA_SHIRQ;
+ break;
+ case MACH_DS5000_200: /* DS5000/200 3max */
+ case MACH_DS5000_2X0: /* DS5000/240 3max+ */
+ case MACH_DS5900: /* DS5900 bigmax */
+ board_be_handler = dec_ecc_be_handler;
+ busirq.handler = dec_ecc_be_interrupt;
+ dec_ecc_be_init();
+ break;
+ }
+}
+
+
+extern void dec_time_init(void);
+extern void dec_timer_setup(struct irqaction *);
+
+static void __init decstation_setup(void)
+{
+ board_be_init = dec_be_init;
+ board_time_init = dec_time_init;
+ board_timer_setup = dec_timer_setup;
+
+ wbflush_setup();
+
+ _machine_restart = dec_machine_restart;
+ _machine_halt = dec_machine_halt;
+ _machine_power_off = dec_machine_power_off;
+}
+
+early_initcall(decstation_setup);
+
+/*
+ * Machine-specific initialisation for KN01, aka DS2100 (aka Pmin)
+ * or DS3100 (aka Pmax).
+ */
+static int kn01_interrupt[DEC_NR_INTS] __initdata = {
+ [DEC_IRQ_CASCADE] = -1,
+ [DEC_IRQ_AB_RECV] = -1,
+ [DEC_IRQ_AB_XMIT] = -1,
+ [DEC_IRQ_DZ11] = DEC_CPU_IRQ_NR(KN01_CPU_INR_DZ11),
+ [DEC_IRQ_ASC] = -1,
+ [DEC_IRQ_FLOPPY] = -1,
+ [DEC_IRQ_FPU] = DEC_CPU_IRQ_NR(DEC_CPU_INR_FPU),
+ [DEC_IRQ_HALT] = -1,
+ [DEC_IRQ_ISDN] = -1,
+ [DEC_IRQ_LANCE] = DEC_CPU_IRQ_NR(KN01_CPU_INR_LANCE),
+ [DEC_IRQ_BUS] = DEC_CPU_IRQ_NR(KN01_CPU_INR_BUS),
+ [DEC_IRQ_PSU] = -1,
+ [DEC_IRQ_RTC] = DEC_CPU_IRQ_NR(KN01_CPU_INR_RTC),
+ [DEC_IRQ_SCC0] = -1,
+ [DEC_IRQ_SCC1] = -1,
+ [DEC_IRQ_SII] = DEC_CPU_IRQ_NR(KN01_CPU_INR_SII),
+ [DEC_IRQ_TC0] = -1,
+ [DEC_IRQ_TC1] = -1,
+ [DEC_IRQ_TC2] = -1,
+ [DEC_IRQ_TIMER] = -1,
+ [DEC_IRQ_VIDEO] = DEC_CPU_IRQ_NR(KN01_CPU_INR_VIDEO),
+ [DEC_IRQ_ASC_MERR] = -1,
+ [DEC_IRQ_ASC_ERR] = -1,
+ [DEC_IRQ_ASC_DMA] = -1,
+ [DEC_IRQ_FLOPPY_ERR] = -1,
+ [DEC_IRQ_ISDN_ERR] = -1,
+ [DEC_IRQ_ISDN_RXDMA] = -1,
+ [DEC_IRQ_ISDN_TXDMA] = -1,
+ [DEC_IRQ_LANCE_MERR] = -1,
+ [DEC_IRQ_SCC0A_RXERR] = -1,
+ [DEC_IRQ_SCC0A_RXDMA] = -1,
+ [DEC_IRQ_SCC0A_TXERR] = -1,
+ [DEC_IRQ_SCC0A_TXDMA] = -1,
+ [DEC_IRQ_AB_RXERR] = -1,
+ [DEC_IRQ_AB_RXDMA] = -1,
+ [DEC_IRQ_AB_TXERR] = -1,
+ [DEC_IRQ_AB_TXDMA] = -1,
+ [DEC_IRQ_SCC1A_RXERR] = -1,
+ [DEC_IRQ_SCC1A_RXDMA] = -1,
+ [DEC_IRQ_SCC1A_TXERR] = -1,
+ [DEC_IRQ_SCC1A_TXDMA] = -1,
+};
+
+static int_ptr kn01_cpu_mask_nr_tbl[][2] __initdata = {
+ { { .i = DEC_CPU_IRQ_MASK(KN01_CPU_INR_BUS) },
+ { .i = DEC_CPU_IRQ_NR(KN01_CPU_INR_BUS) } },
+ { { .i = DEC_CPU_IRQ_MASK(KN01_CPU_INR_RTC) },
+ { .i = DEC_CPU_IRQ_NR(KN01_CPU_INR_RTC) } },
+ { { .i = DEC_CPU_IRQ_MASK(KN01_CPU_INR_DZ11) },
+ { .i = DEC_CPU_IRQ_NR(KN01_CPU_INR_DZ11) } },
+ { { .i = DEC_CPU_IRQ_MASK(KN01_CPU_INR_SII) },
+ { .i = DEC_CPU_IRQ_NR(KN01_CPU_INR_SII) } },
+ { { .i = DEC_CPU_IRQ_MASK(KN01_CPU_INR_LANCE) },
+ { .i = DEC_CPU_IRQ_NR(KN01_CPU_INR_LANCE) } },
+ { { .i = DEC_CPU_IRQ_ALL },
+ { .p = cpu_all_int } },
+};
+
+void __init dec_init_kn01(void)
+{
+ /* IRQ routing. */
+ memcpy(&dec_interrupt, &kn01_interrupt,
+ sizeof(kn01_interrupt));
+
+ /* CPU IRQ priorities. */
+ memcpy(&cpu_mask_nr_tbl, &kn01_cpu_mask_nr_tbl,
+ sizeof(kn01_cpu_mask_nr_tbl));
+
+ mips_cpu_irq_init(DEC_CPU_IRQ_BASE);
+
+} /* dec_init_kn01 */
+
+
+/*
+ * Machine-specific initialisation for KN230, aka DS5100, aka MIPSmate.
+ */
+static int kn230_interrupt[DEC_NR_INTS] __initdata = {
+ [DEC_IRQ_CASCADE] = -1,
+ [DEC_IRQ_AB_RECV] = -1,
+ [DEC_IRQ_AB_XMIT] = -1,
+ [DEC_IRQ_DZ11] = DEC_CPU_IRQ_NR(KN230_CPU_INR_DZ11),
+ [DEC_IRQ_ASC] = -1,
+ [DEC_IRQ_FLOPPY] = -1,
+ [DEC_IRQ_FPU] = DEC_CPU_IRQ_NR(DEC_CPU_INR_FPU),
+ [DEC_IRQ_HALT] = DEC_CPU_IRQ_NR(KN230_CPU_INR_HALT),
+ [DEC_IRQ_ISDN] = -1,
+ [DEC_IRQ_LANCE] = DEC_CPU_IRQ_NR(KN230_CPU_INR_LANCE),
+ [DEC_IRQ_BUS] = DEC_CPU_IRQ_NR(KN230_CPU_INR_BUS),
+ [DEC_IRQ_PSU] = -1,
+ [DEC_IRQ_RTC] = DEC_CPU_IRQ_NR(KN230_CPU_INR_RTC),
+ [DEC_IRQ_SCC0] = -1,
+ [DEC_IRQ_SCC1] = -1,
+ [DEC_IRQ_SII] = DEC_CPU_IRQ_NR(KN230_CPU_INR_SII),
+ [DEC_IRQ_TC0] = -1,
+ [DEC_IRQ_TC1] = -1,
+ [DEC_IRQ_TC2] = -1,
+ [DEC_IRQ_TIMER] = -1,
+ [DEC_IRQ_VIDEO] = -1,
+ [DEC_IRQ_ASC_MERR] = -1,
+ [DEC_IRQ_ASC_ERR] = -1,
+ [DEC_IRQ_ASC_DMA] = -1,
+ [DEC_IRQ_FLOPPY_ERR] = -1,
+ [DEC_IRQ_ISDN_ERR] = -1,
+ [DEC_IRQ_ISDN_RXDMA] = -1,
+ [DEC_IRQ_ISDN_TXDMA] = -1,
+ [DEC_IRQ_LANCE_MERR] = -1,
+ [DEC_IRQ_SCC0A_RXERR] = -1,
+ [DEC_IRQ_SCC0A_RXDMA] = -1,
+ [DEC_IRQ_SCC0A_TXERR] = -1,
+ [DEC_IRQ_SCC0A_TXDMA] = -1,
+ [DEC_IRQ_AB_RXERR] = -1,
+ [DEC_IRQ_AB_RXDMA] = -1,
+ [DEC_IRQ_AB_TXERR] = -1,
+ [DEC_IRQ_AB_TXDMA] = -1,
+ [DEC_IRQ_SCC1A_RXERR] = -1,
+ [DEC_IRQ_SCC1A_RXDMA] = -1,
+ [DEC_IRQ_SCC1A_TXERR] = -1,
+ [DEC_IRQ_SCC1A_TXDMA] = -1,
+};
+
+static int_ptr kn230_cpu_mask_nr_tbl[][2] __initdata = {
+ { { .i = DEC_CPU_IRQ_MASK(KN230_CPU_INR_BUS) },
+ { .i = DEC_CPU_IRQ_NR(KN230_CPU_INR_BUS) } },
+ { { .i = DEC_CPU_IRQ_MASK(KN230_CPU_INR_RTC) },
+ { .i = DEC_CPU_IRQ_NR(KN230_CPU_INR_RTC) } },
+ { { .i = DEC_CPU_IRQ_MASK(KN230_CPU_INR_DZ11) },
+ { .i = DEC_CPU_IRQ_NR(KN230_CPU_INR_DZ11) } },
+ { { .i = DEC_CPU_IRQ_MASK(KN230_CPU_INR_SII) },
+ { .i = DEC_CPU_IRQ_NR(KN230_CPU_INR_SII) } },
+ { { .i = DEC_CPU_IRQ_ALL },
+ { .p = cpu_all_int } },
+};
+
+void __init dec_init_kn230(void)
+{
+ /* IRQ routing. */
+ memcpy(&dec_interrupt, &kn230_interrupt,
+ sizeof(kn230_interrupt));
+
+ /* CPU IRQ priorities. */
+ memcpy(&cpu_mask_nr_tbl, &kn230_cpu_mask_nr_tbl,
+ sizeof(kn230_cpu_mask_nr_tbl));
+
+ mips_cpu_irq_init(DEC_CPU_IRQ_BASE);
+
+} /* dec_init_kn230 */
+
+
+/*
+ * Machine-specific initialisation for KN02, aka DS5000/200, aka 3max.
+ */
+static int kn02_interrupt[DEC_NR_INTS] __initdata = {
+ [DEC_IRQ_CASCADE] = DEC_CPU_IRQ_NR(KN02_CPU_INR_CASCADE),
+ [DEC_IRQ_AB_RECV] = -1,
+ [DEC_IRQ_AB_XMIT] = -1,
+ [DEC_IRQ_DZ11] = KN02_IRQ_NR(KN02_CSR_INR_DZ11),
+ [DEC_IRQ_ASC] = KN02_IRQ_NR(KN02_CSR_INR_ASC),
+ [DEC_IRQ_FLOPPY] = -1,
+ [DEC_IRQ_FPU] = DEC_CPU_IRQ_NR(DEC_CPU_INR_FPU),
+ [DEC_IRQ_HALT] = -1,
+ [DEC_IRQ_ISDN] = -1,
+ [DEC_IRQ_LANCE] = KN02_IRQ_NR(KN02_CSR_INR_LANCE),
+ [DEC_IRQ_BUS] = DEC_CPU_IRQ_NR(KN02_CPU_INR_BUS),
+ [DEC_IRQ_PSU] = -1,
+ [DEC_IRQ_RTC] = DEC_CPU_IRQ_NR(KN02_CPU_INR_RTC),
+ [DEC_IRQ_SCC0] = -1,
+ [DEC_IRQ_SCC1] = -1,
+ [DEC_IRQ_SII] = -1,
+ [DEC_IRQ_TC0] = KN02_IRQ_NR(KN02_CSR_INR_TC0),
+ [DEC_IRQ_TC1] = KN02_IRQ_NR(KN02_CSR_INR_TC1),
+ [DEC_IRQ_TC2] = KN02_IRQ_NR(KN02_CSR_INR_TC2),
+ [DEC_IRQ_TIMER] = -1,
+ [DEC_IRQ_VIDEO] = -1,
+ [DEC_IRQ_ASC_MERR] = -1,
+ [DEC_IRQ_ASC_ERR] = -1,
+ [DEC_IRQ_ASC_DMA] = -1,
+ [DEC_IRQ_FLOPPY_ERR] = -1,
+ [DEC_IRQ_ISDN_ERR] = -1,
+ [DEC_IRQ_ISDN_RXDMA] = -1,
+ [DEC_IRQ_ISDN_TXDMA] = -1,
+ [DEC_IRQ_LANCE_MERR] = -1,
+ [DEC_IRQ_SCC0A_RXERR] = -1,
+ [DEC_IRQ_SCC0A_RXDMA] = -1,
+ [DEC_IRQ_SCC0A_TXERR] = -1,
+ [DEC_IRQ_SCC0A_TXDMA] = -1,
+ [DEC_IRQ_AB_RXERR] = -1,
+ [DEC_IRQ_AB_RXDMA] = -1,
+ [DEC_IRQ_AB_TXERR] = -1,
+ [DEC_IRQ_AB_TXDMA] = -1,
+ [DEC_IRQ_SCC1A_RXERR] = -1,
+ [DEC_IRQ_SCC1A_RXDMA] = -1,
+ [DEC_IRQ_SCC1A_TXERR] = -1,
+ [DEC_IRQ_SCC1A_TXDMA] = -1,
+};
+
+static int_ptr kn02_cpu_mask_nr_tbl[][2] __initdata = {
+ { { .i = DEC_CPU_IRQ_MASK(KN02_CPU_INR_BUS) },
+ { .i = DEC_CPU_IRQ_NR(KN02_CPU_INR_BUS) } },
+ { { .i = DEC_CPU_IRQ_MASK(KN02_CPU_INR_RTC) },
+ { .i = DEC_CPU_IRQ_NR(KN02_CPU_INR_RTC) } },
+ { { .i = DEC_CPU_IRQ_MASK(KN02_CPU_INR_CASCADE) },
+ { .p = kn02_io_int } },
+ { { .i = DEC_CPU_IRQ_ALL },
+ { .p = cpu_all_int } },
+};
+
+static int_ptr kn02_asic_mask_nr_tbl[][2] __initdata = {
+ { { .i = KN02_IRQ_MASK(KN02_CSR_INR_DZ11) },
+ { .i = KN02_IRQ_NR(KN02_CSR_INR_DZ11) } },
+ { { .i = KN02_IRQ_MASK(KN02_CSR_INR_ASC) },
+ { .i = KN02_IRQ_NR(KN02_CSR_INR_ASC) } },
+ { { .i = KN02_IRQ_MASK(KN02_CSR_INR_LANCE) },
+ { .i = KN02_IRQ_NR(KN02_CSR_INR_LANCE) } },
+ { { .i = KN02_IRQ_MASK(KN02_CSR_INR_TC2) },
+ { .i = KN02_IRQ_NR(KN02_CSR_INR_TC2) } },
+ { { .i = KN02_IRQ_MASK(KN02_CSR_INR_TC1) },
+ { .i = KN02_IRQ_NR(KN02_CSR_INR_TC1) } },
+ { { .i = KN02_IRQ_MASK(KN02_CSR_INR_TC0) },
+ { .i = KN02_IRQ_NR(KN02_CSR_INR_TC0) } },
+ { { .i = KN02_IRQ_ALL },
+ { .p = kn02_all_int } },
+};
+
+void __init dec_init_kn02(void)
+{
+ /* IRQ routing. */
+ memcpy(&dec_interrupt, &kn02_interrupt,
+ sizeof(kn02_interrupt));
+
+ /* CPU IRQ priorities. */
+ memcpy(&cpu_mask_nr_tbl, &kn02_cpu_mask_nr_tbl,
+ sizeof(kn02_cpu_mask_nr_tbl));
+
+ /* KN02 CSR IRQ priorities. */
+ memcpy(&asic_mask_nr_tbl, &kn02_asic_mask_nr_tbl,
+ sizeof(kn02_asic_mask_nr_tbl));
+
+ mips_cpu_irq_init(DEC_CPU_IRQ_BASE);
+ init_kn02_irqs(KN02_IRQ_BASE);
+
+} /* dec_init_kn02 */
+
+
+/*
+ * Machine-specific initialisation for KN02-BA, aka DS5000/1xx
+ * (xx = 20, 25, 33), aka 3min. Also applies to KN04(-BA), aka
+ * DS5000/150, aka 4min.
+ */
+static int kn02ba_interrupt[DEC_NR_INTS] __initdata = {
+ [DEC_IRQ_CASCADE] = DEC_CPU_IRQ_NR(KN02BA_CPU_INR_CASCADE),
+ [DEC_IRQ_AB_RECV] = -1,
+ [DEC_IRQ_AB_XMIT] = -1,
+ [DEC_IRQ_DZ11] = -1,
+ [DEC_IRQ_ASC] = IO_IRQ_NR(KN02BA_IO_INR_ASC),
+ [DEC_IRQ_FLOPPY] = -1,
+ [DEC_IRQ_FPU] = DEC_CPU_IRQ_NR(DEC_CPU_INR_FPU),
+ [DEC_IRQ_HALT] = DEC_CPU_IRQ_NR(KN02BA_CPU_INR_HALT),
+ [DEC_IRQ_ISDN] = -1,
+ [DEC_IRQ_LANCE] = IO_IRQ_NR(KN02BA_IO_INR_LANCE),
+ [DEC_IRQ_BUS] = IO_IRQ_NR(KN02BA_IO_INR_BUS),
+ [DEC_IRQ_PSU] = IO_IRQ_NR(KN02BA_IO_INR_PSU),
+ [DEC_IRQ_RTC] = IO_IRQ_NR(KN02BA_IO_INR_RTC),
+ [DEC_IRQ_SCC0] = IO_IRQ_NR(KN02BA_IO_INR_SCC0),
+ [DEC_IRQ_SCC1] = IO_IRQ_NR(KN02BA_IO_INR_SCC1),
+ [DEC_IRQ_SII] = -1,
+ [DEC_IRQ_TC0] = DEC_CPU_IRQ_NR(KN02BA_CPU_INR_TC0),
+ [DEC_IRQ_TC1] = DEC_CPU_IRQ_NR(KN02BA_CPU_INR_TC1),
+ [DEC_IRQ_TC2] = DEC_CPU_IRQ_NR(KN02BA_CPU_INR_TC2),
+ [DEC_IRQ_TIMER] = -1,
+ [DEC_IRQ_VIDEO] = -1,
+ [DEC_IRQ_ASC_MERR] = IO_IRQ_NR(IO_INR_ASC_MERR),
+ [DEC_IRQ_ASC_ERR] = IO_IRQ_NR(IO_INR_ASC_ERR),
+ [DEC_IRQ_ASC_DMA] = IO_IRQ_NR(IO_INR_ASC_DMA),
+ [DEC_IRQ_FLOPPY_ERR] = -1,
+ [DEC_IRQ_ISDN_ERR] = -1,
+ [DEC_IRQ_ISDN_RXDMA] = -1,
+ [DEC_IRQ_ISDN_TXDMA] = -1,
+ [DEC_IRQ_LANCE_MERR] = IO_IRQ_NR(IO_INR_LANCE_MERR),
+ [DEC_IRQ_SCC0A_RXERR] = IO_IRQ_NR(IO_INR_SCC0A_RXERR),
+ [DEC_IRQ_SCC0A_RXDMA] = IO_IRQ_NR(IO_INR_SCC0A_RXDMA),
+ [DEC_IRQ_SCC0A_TXERR] = IO_IRQ_NR(IO_INR_SCC0A_TXERR),
+ [DEC_IRQ_SCC0A_TXDMA] = IO_IRQ_NR(IO_INR_SCC0A_TXDMA),
+ [DEC_IRQ_AB_RXERR] = -1,
+ [DEC_IRQ_AB_RXDMA] = -1,
+ [DEC_IRQ_AB_TXERR] = -1,
+ [DEC_IRQ_AB_TXDMA] = -1,
+ [DEC_IRQ_SCC1A_RXERR] = IO_IRQ_NR(IO_INR_SCC1A_RXERR),
+ [DEC_IRQ_SCC1A_RXDMA] = IO_IRQ_NR(IO_INR_SCC1A_RXDMA),
+ [DEC_IRQ_SCC1A_TXERR] = IO_IRQ_NR(IO_INR_SCC1A_TXERR),
+ [DEC_IRQ_SCC1A_TXDMA] = IO_IRQ_NR(IO_INR_SCC1A_TXDMA),
+};
+
+static int_ptr kn02ba_cpu_mask_nr_tbl[][2] __initdata = {
+ { { .i = DEC_CPU_IRQ_MASK(KN02BA_CPU_INR_CASCADE) },
+ { .p = kn02xa_io_int } },
+ { { .i = DEC_CPU_IRQ_MASK(KN02BA_CPU_INR_TC2) },
+ { .i = DEC_CPU_IRQ_NR(KN02BA_CPU_INR_TC2) } },
+ { { .i = DEC_CPU_IRQ_MASK(KN02BA_CPU_INR_TC1) },
+ { .i = DEC_CPU_IRQ_NR(KN02BA_CPU_INR_TC1) } },
+ { { .i = DEC_CPU_IRQ_MASK(KN02BA_CPU_INR_TC0) },
+ { .i = DEC_CPU_IRQ_NR(KN02BA_CPU_INR_TC0) } },
+ { { .i = DEC_CPU_IRQ_ALL },
+ { .p = cpu_all_int } },
+};
+
+static int_ptr kn02ba_asic_mask_nr_tbl[][2] __initdata = {
+ { { .i = IO_IRQ_MASK(KN02BA_IO_INR_BUS) },
+ { .i = IO_IRQ_NR(KN02BA_IO_INR_BUS) } },
+ { { .i = IO_IRQ_MASK(KN02BA_IO_INR_RTC) },
+ { .i = IO_IRQ_NR(KN02BA_IO_INR_RTC) } },
+ { { .i = IO_IRQ_DMA },
+ { .p = asic_dma_int } },
+ { { .i = IO_IRQ_MASK(KN02BA_IO_INR_SCC0) },
+ { .i = IO_IRQ_NR(KN02BA_IO_INR_SCC0) } },
+ { { .i = IO_IRQ_MASK(KN02BA_IO_INR_SCC1) },
+ { .i = IO_IRQ_NR(KN02BA_IO_INR_SCC1) } },
+ { { .i = IO_IRQ_MASK(KN02BA_IO_INR_ASC) },
+ { .i = IO_IRQ_NR(KN02BA_IO_INR_ASC) } },
+ { { .i = IO_IRQ_MASK(KN02BA_IO_INR_LANCE) },
+ { .i = IO_IRQ_NR(KN02BA_IO_INR_LANCE) } },
+ { { .i = IO_IRQ_ALL },
+ { .p = asic_all_int } },
+};
+
+void __init dec_init_kn02ba(void)
+{
+ /* IRQ routing. */
+ memcpy(&dec_interrupt, &kn02ba_interrupt,
+ sizeof(kn02ba_interrupt));
+
+ /* CPU IRQ priorities. */
+ memcpy(&cpu_mask_nr_tbl, &kn02ba_cpu_mask_nr_tbl,
+ sizeof(kn02ba_cpu_mask_nr_tbl));
+
+ /* I/O ASIC IRQ priorities. */
+ memcpy(&asic_mask_nr_tbl, &kn02ba_asic_mask_nr_tbl,
+ sizeof(kn02ba_asic_mask_nr_tbl));
+
+ mips_cpu_irq_init(DEC_CPU_IRQ_BASE);
+ init_ioasic_irqs(IO_IRQ_BASE);
+
+} /* dec_init_kn02ba */
+
+
+/*
+ * Machine-specific initialisation for KN02-CA, aka DS5000/xx,
+ * (xx = 20, 25, 33), aka MAXine. Also applies to KN04(-CA), aka
+ * DS5000/50, aka 4MAXine.
+ */
+static int kn02ca_interrupt[DEC_NR_INTS] __initdata = {
+ [DEC_IRQ_CASCADE] = DEC_CPU_IRQ_NR(KN02CA_CPU_INR_CASCADE),
+ [DEC_IRQ_AB_RECV] = IO_IRQ_NR(KN02CA_IO_INR_AB_RECV),
+ [DEC_IRQ_AB_XMIT] = IO_IRQ_NR(KN02CA_IO_INR_AB_XMIT),
+ [DEC_IRQ_DZ11] = -1,
+ [DEC_IRQ_ASC] = IO_IRQ_NR(KN02CA_IO_INR_ASC),
+ [DEC_IRQ_FLOPPY] = IO_IRQ_NR(KN02CA_IO_INR_FLOPPY),
+ [DEC_IRQ_FPU] = DEC_CPU_IRQ_NR(DEC_CPU_INR_FPU),
+ [DEC_IRQ_HALT] = DEC_CPU_IRQ_NR(KN02CA_CPU_INR_HALT),
+ [DEC_IRQ_ISDN] = IO_IRQ_NR(KN02CA_IO_INR_ISDN),
+ [DEC_IRQ_LANCE] = IO_IRQ_NR(KN02CA_IO_INR_LANCE),
+ [DEC_IRQ_BUS] = DEC_CPU_IRQ_NR(KN02CA_CPU_INR_BUS),
+ [DEC_IRQ_PSU] = -1,
+ [DEC_IRQ_RTC] = DEC_CPU_IRQ_NR(KN02CA_CPU_INR_RTC),
+ [DEC_IRQ_SCC0] = IO_IRQ_NR(KN02CA_IO_INR_SCC0),
+ [DEC_IRQ_SCC1] = -1,
+ [DEC_IRQ_SII] = -1,
+ [DEC_IRQ_TC0] = IO_IRQ_NR(KN02CA_IO_INR_TC0),
+ [DEC_IRQ_TC1] = IO_IRQ_NR(KN02CA_IO_INR_TC1),
+ [DEC_IRQ_TC2] = -1,
+ [DEC_IRQ_TIMER] = DEC_CPU_IRQ_NR(KN02CA_CPU_INR_TIMER),
+ [DEC_IRQ_VIDEO] = IO_IRQ_NR(KN02CA_IO_INR_VIDEO),
+ [DEC_IRQ_ASC_MERR] = IO_IRQ_NR(IO_INR_ASC_MERR),
+ [DEC_IRQ_ASC_ERR] = IO_IRQ_NR(IO_INR_ASC_ERR),
+ [DEC_IRQ_ASC_DMA] = IO_IRQ_NR(IO_INR_ASC_DMA),
+ [DEC_IRQ_FLOPPY_ERR] = IO_IRQ_NR(IO_INR_FLOPPY_ERR),
+ [DEC_IRQ_ISDN_ERR] = IO_IRQ_NR(IO_INR_ISDN_ERR),
+ [DEC_IRQ_ISDN_RXDMA] = IO_IRQ_NR(IO_INR_ISDN_RXDMA),
+ [DEC_IRQ_ISDN_TXDMA] = IO_IRQ_NR(IO_INR_ISDN_TXDMA),
+ [DEC_IRQ_LANCE_MERR] = IO_IRQ_NR(IO_INR_LANCE_MERR),
+ [DEC_IRQ_SCC0A_RXERR] = IO_IRQ_NR(IO_INR_SCC0A_RXERR),
+ [DEC_IRQ_SCC0A_RXDMA] = IO_IRQ_NR(IO_INR_SCC0A_RXDMA),
+ [DEC_IRQ_SCC0A_TXERR] = IO_IRQ_NR(IO_INR_SCC0A_TXERR),
+ [DEC_IRQ_SCC0A_TXDMA] = IO_IRQ_NR(IO_INR_SCC0A_TXDMA),
+ [DEC_IRQ_AB_RXERR] = IO_IRQ_NR(IO_INR_AB_RXERR),
+ [DEC_IRQ_AB_RXDMA] = IO_IRQ_NR(IO_INR_AB_RXDMA),
+ [DEC_IRQ_AB_TXERR] = IO_IRQ_NR(IO_INR_AB_TXERR),
+ [DEC_IRQ_AB_TXDMA] = IO_IRQ_NR(IO_INR_AB_TXDMA),
+ [DEC_IRQ_SCC1A_RXERR] = -1,
+ [DEC_IRQ_SCC1A_RXDMA] = -1,
+ [DEC_IRQ_SCC1A_TXERR] = -1,
+ [DEC_IRQ_SCC1A_TXDMA] = -1,
+};
+
+static int_ptr kn02ca_cpu_mask_nr_tbl[][2] __initdata = {
+ { { .i = DEC_CPU_IRQ_MASK(KN02CA_CPU_INR_BUS) },
+ { .i = DEC_CPU_IRQ_NR(KN02CA_CPU_INR_BUS) } },
+ { { .i = DEC_CPU_IRQ_MASK(KN02CA_CPU_INR_RTC) },
+ { .i = DEC_CPU_IRQ_NR(KN02CA_CPU_INR_RTC) } },
+ { { .i = DEC_CPU_IRQ_MASK(KN02CA_CPU_INR_CASCADE) },
+ { .p = kn02xa_io_int } },
+ { { .i = DEC_CPU_IRQ_ALL },
+ { .p = cpu_all_int } },
+};
+
+static int_ptr kn02ca_asic_mask_nr_tbl[][2] __initdata = {
+ { { .i = IO_IRQ_DMA },
+ { .p = asic_dma_int } },
+ { { .i = IO_IRQ_MASK(KN02CA_IO_INR_SCC0) },
+ { .i = IO_IRQ_NR(KN02CA_IO_INR_SCC0) } },
+ { { .i = IO_IRQ_MASK(KN02CA_IO_INR_ASC) },
+ { .i = IO_IRQ_NR(KN02CA_IO_INR_ASC) } },
+ { { .i = IO_IRQ_MASK(KN02CA_IO_INR_LANCE) },
+ { .i = IO_IRQ_NR(KN02CA_IO_INR_LANCE) } },
+ { { .i = IO_IRQ_MASK(KN02CA_IO_INR_TC1) },
+ { .i = IO_IRQ_NR(KN02CA_IO_INR_TC1) } },
+ { { .i = IO_IRQ_MASK(KN02CA_IO_INR_TC0) },
+ { .i = IO_IRQ_NR(KN02CA_IO_INR_TC0) } },
+ { { .i = IO_IRQ_ALL },
+ { .p = asic_all_int } },
+};
+
+void __init dec_init_kn02ca(void)
+{
+ /* IRQ routing. */
+ memcpy(&dec_interrupt, &kn02ca_interrupt,
+ sizeof(kn02ca_interrupt));
+
+ /* CPU IRQ priorities. */
+ memcpy(&cpu_mask_nr_tbl, &kn02ca_cpu_mask_nr_tbl,
+ sizeof(kn02ca_cpu_mask_nr_tbl));
+
+ /* I/O ASIC IRQ priorities. */
+ memcpy(&asic_mask_nr_tbl, &kn02ca_asic_mask_nr_tbl,
+ sizeof(kn02ca_asic_mask_nr_tbl));
+
+ mips_cpu_irq_init(DEC_CPU_IRQ_BASE);
+ init_ioasic_irqs(IO_IRQ_BASE);
+
+} /* dec_init_kn02ca */
+
+
+/*
+ * Machine-specific initialisation for KN03, aka DS5000/240,
+ * aka 3max+ and DS5900, aka BIGmax. Also applies to KN05, aka
+ * DS5000/260, aka 4max+ and DS5900/260.
+ */
+static int kn03_interrupt[DEC_NR_INTS] __initdata = {
+ [DEC_IRQ_CASCADE] = DEC_CPU_IRQ_NR(KN03_CPU_INR_CASCADE),
+ [DEC_IRQ_AB_RECV] = -1,
+ [DEC_IRQ_AB_XMIT] = -1,
+ [DEC_IRQ_DZ11] = -1,
+ [DEC_IRQ_ASC] = IO_IRQ_NR(KN03_IO_INR_ASC),
+ [DEC_IRQ_FLOPPY] = -1,
+ [DEC_IRQ_FPU] = DEC_CPU_IRQ_NR(DEC_CPU_INR_FPU),
+ [DEC_IRQ_HALT] = DEC_CPU_IRQ_NR(KN03_CPU_INR_HALT),
+ [DEC_IRQ_ISDN] = -1,
+ [DEC_IRQ_LANCE] = IO_IRQ_NR(KN03_IO_INR_LANCE),
+ [DEC_IRQ_BUS] = DEC_CPU_IRQ_NR(KN03_CPU_INR_BUS),
+ [DEC_IRQ_PSU] = IO_IRQ_NR(KN03_IO_INR_PSU),
+ [DEC_IRQ_RTC] = DEC_CPU_IRQ_NR(KN03_CPU_INR_RTC),
+ [DEC_IRQ_SCC0] = IO_IRQ_NR(KN03_IO_INR_SCC0),
+ [DEC_IRQ_SCC1] = IO_IRQ_NR(KN03_IO_INR_SCC1),
+ [DEC_IRQ_SII] = -1,
+ [DEC_IRQ_TC0] = IO_IRQ_NR(KN03_IO_INR_TC0),
+ [DEC_IRQ_TC1] = IO_IRQ_NR(KN03_IO_INR_TC1),
+ [DEC_IRQ_TC2] = IO_IRQ_NR(KN03_IO_INR_TC2),
+ [DEC_IRQ_TIMER] = -1,
+ [DEC_IRQ_VIDEO] = -1,
+ [DEC_IRQ_ASC_MERR] = IO_IRQ_NR(IO_INR_ASC_MERR),
+ [DEC_IRQ_ASC_ERR] = IO_IRQ_NR(IO_INR_ASC_ERR),
+ [DEC_IRQ_ASC_DMA] = IO_IRQ_NR(IO_INR_ASC_DMA),
+ [DEC_IRQ_FLOPPY_ERR] = -1,
+ [DEC_IRQ_ISDN_ERR] = -1,
+ [DEC_IRQ_ISDN_RXDMA] = -1,
+ [DEC_IRQ_ISDN_TXDMA] = -1,
+ [DEC_IRQ_LANCE_MERR] = IO_IRQ_NR(IO_INR_LANCE_MERR),
+ [DEC_IRQ_SCC0A_RXERR] = IO_IRQ_NR(IO_INR_SCC0A_RXERR),
+ [DEC_IRQ_SCC0A_RXDMA] = IO_IRQ_NR(IO_INR_SCC0A_RXDMA),
+ [DEC_IRQ_SCC0A_TXERR] = IO_IRQ_NR(IO_INR_SCC0A_TXERR),
+ [DEC_IRQ_SCC0A_TXDMA] = IO_IRQ_NR(IO_INR_SCC0A_TXDMA),
+ [DEC_IRQ_AB_RXERR] = -1,
+ [DEC_IRQ_AB_RXDMA] = -1,
+ [DEC_IRQ_AB_TXERR] = -1,
+ [DEC_IRQ_AB_TXDMA] = -1,
+ [DEC_IRQ_SCC1A_RXERR] = IO_IRQ_NR(IO_INR_SCC1A_RXERR),
+ [DEC_IRQ_SCC1A_RXDMA] = IO_IRQ_NR(IO_INR_SCC1A_RXDMA),
+ [DEC_IRQ_SCC1A_TXERR] = IO_IRQ_NR(IO_INR_SCC1A_TXERR),
+ [DEC_IRQ_SCC1A_TXDMA] = IO_IRQ_NR(IO_INR_SCC1A_TXDMA),
+};
+
+static int_ptr kn03_cpu_mask_nr_tbl[][2] __initdata = {
+ { { .i = DEC_CPU_IRQ_MASK(KN03_CPU_INR_BUS) },
+ { .i = DEC_CPU_IRQ_NR(KN03_CPU_INR_BUS) } },
+ { { .i = DEC_CPU_IRQ_MASK(KN03_CPU_INR_RTC) },
+ { .i = DEC_CPU_IRQ_NR(KN03_CPU_INR_RTC) } },
+ { { .i = DEC_CPU_IRQ_MASK(KN03_CPU_INR_CASCADE) },
+ { .p = kn03_io_int } },
+ { { .i = DEC_CPU_IRQ_ALL },
+ { .p = cpu_all_int } },
+};
+
+static int_ptr kn03_asic_mask_nr_tbl[][2] __initdata = {
+ { { .i = IO_IRQ_DMA },
+ { .p = asic_dma_int } },
+ { { .i = IO_IRQ_MASK(KN03_IO_INR_SCC0) },
+ { .i = IO_IRQ_NR(KN03_IO_INR_SCC0) } },
+ { { .i = IO_IRQ_MASK(KN03_IO_INR_SCC1) },
+ { .i = IO_IRQ_NR(KN03_IO_INR_SCC1) } },
+ { { .i = IO_IRQ_MASK(KN03_IO_INR_ASC) },
+ { .i = IO_IRQ_NR(KN03_IO_INR_ASC) } },
+ { { .i = IO_IRQ_MASK(KN03_IO_INR_LANCE) },
+ { .i = IO_IRQ_NR(KN03_IO_INR_LANCE) } },
+ { { .i = IO_IRQ_MASK(KN03_IO_INR_TC2) },
+ { .i = IO_IRQ_NR(KN03_IO_INR_TC2) } },
+ { { .i = IO_IRQ_MASK(KN03_IO_INR_TC1) },
+ { .i = IO_IRQ_NR(KN03_IO_INR_TC1) } },
+ { { .i = IO_IRQ_MASK(KN03_IO_INR_TC0) },
+ { .i = IO_IRQ_NR(KN03_IO_INR_TC0) } },
+ { { .i = IO_IRQ_ALL },
+ { .p = asic_all_int } },
+};
+
+void __init dec_init_kn03(void)
+{
+ /* IRQ routing. */
+ memcpy(&dec_interrupt, &kn03_interrupt,
+ sizeof(kn03_interrupt));
+
+ /* CPU IRQ priorities. */
+ memcpy(&cpu_mask_nr_tbl, &kn03_cpu_mask_nr_tbl,
+ sizeof(kn03_cpu_mask_nr_tbl));
+
+ /* I/O ASIC IRQ priorities. */
+ memcpy(&asic_mask_nr_tbl, &kn03_asic_mask_nr_tbl,
+ sizeof(kn03_asic_mask_nr_tbl));
+
+ mips_cpu_irq_init(DEC_CPU_IRQ_BASE);
+ init_ioasic_irqs(IO_IRQ_BASE);
+
+} /* dec_init_kn03 */
+
+
+void __init arch_init_irq(void)
+{
+ switch (mips_machtype) {
+ case MACH_DS23100: /* DS2100/DS3100 Pmin/Pmax */
+ dec_init_kn01();
+ break;
+ case MACH_DS5100: /* DS5100 MIPSmate */
+ dec_init_kn230();
+ break;
+ case MACH_DS5000_200: /* DS5000/200 3max */
+ dec_init_kn02();
+ break;
+ case MACH_DS5000_1XX: /* DS5000/1xx 3min */
+ dec_init_kn02ba();
+ break;
+ case MACH_DS5000_2X0: /* DS5000/240 3max+ */
+ case MACH_DS5900: /* DS5900 bigmax */
+ dec_init_kn03();
+ break;
+ case MACH_DS5000_XX: /* Personal DS5000/xx */
+ dec_init_kn02ca();
+ break;
+ case MACH_DS5800: /* DS5800 Isis */
+ panic("Don't know how to set this up!");
+ break;
+ case MACH_DS5400: /* DS5400 MIPSfair */
+ panic("Don't know how to set this up!");
+ break;
+ case MACH_DS5500: /* DS5500 MIPSfair-2 */
+ panic("Don't know how to set this up!");
+ break;
+ }
+ set_except_vector(0, decstation_handle_int);
+
+ /* Free the FPU interrupt if the exception is present. */
+ if (!cpu_has_nofpuex) {
+ cpu_fpu_mask = 0;
+ dec_interrupt[DEC_IRQ_FPU] = -1;
+ }
+
+ /* Register board interrupts: FPU and cascade. */
+ if (dec_interrupt[DEC_IRQ_FPU] >= 0)
+ setup_irq(dec_interrupt[DEC_IRQ_FPU], &fpuirq);
+ if (dec_interrupt[DEC_IRQ_CASCADE] >= 0)
+ setup_irq(dec_interrupt[DEC_IRQ_CASCADE], &ioirq);
+
+ /* Register the bus error interrupt. */
+ if (dec_interrupt[DEC_IRQ_BUS] >= 0 && busirq.handler)
+ setup_irq(dec_interrupt[DEC_IRQ_BUS], &busirq);
+
+ /* Register the HALT interrupt. */
+ if (dec_interrupt[DEC_IRQ_HALT] >= 0)
+ setup_irq(dec_interrupt[DEC_IRQ_HALT], &haltirq);
+}
+
+EXPORT_SYMBOL(ioasic_base);
+EXPORT_SYMBOL(dec_kn_slot_size);
+EXPORT_SYMBOL(dec_interrupt);
diff --git a/arch/mips/dec/time.c b/arch/mips/dec/time.c
new file mode 100644
index 0000000..dc7091c
--- /dev/null
+++ b/arch/mips/dec/time.c
@@ -0,0 +1,200 @@
+/*
+ * linux/arch/mips/dec/time.c
+ *
+ * Copyright (C) 1991, 1992, 1995 Linus Torvalds
+ * Copyright (C) 2000, 2003 Maciej W. Rozycki
+ *
+ * This file contains the time handling details for PC-style clocks as
+ * found in some MIPS systems.
+ *
+ */
+#include <linux/bcd.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/mc146818rtc.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/param.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/time.h>
+#include <linux/types.h>
+
+#include <asm/bootinfo.h>
+#include <asm/cpu.h>
+#include <asm/div64.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mipsregs.h>
+#include <asm/sections.h>
+#include <asm/time.h>
+
+#include <asm/dec/interrupts.h>
+#include <asm/dec/ioasic.h>
+#include <asm/dec/ioasic_addrs.h>
+#include <asm/dec/machtype.h>
+
+
+static unsigned long dec_rtc_get_time(void)
+{
+ unsigned int year, mon, day, hour, min, sec, real_year;
+ int i;
+
+ /* The Linux interpretation of the DS1287 clock register contents:
+ * When the Update-In-Progress (UIP) flag goes from 1 to 0, the
+ * RTC registers show the second which has precisely just started.
+ * Let's hope other operating systems interpret the RTC the same way.
+ */
+ /* read RTC exactly on falling edge of update flag */
+ for (i = 0; i < 1000000; i++) /* may take up to 1 second... */
+ if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)
+ break;
+ for (i = 0; i < 1000000; i++) /* must try at least 2.228 ms */
+ if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP))
+ break;
+ /* Isn't this overkill? UIP above should guarantee consistency */
+ do {
+ sec = CMOS_READ(RTC_SECONDS);
+ min = CMOS_READ(RTC_MINUTES);
+ hour = CMOS_READ(RTC_HOURS);
+ day = CMOS_READ(RTC_DAY_OF_MONTH);
+ mon = CMOS_READ(RTC_MONTH);
+ year = CMOS_READ(RTC_YEAR);
+ } while (sec != CMOS_READ(RTC_SECONDS));
+ if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
+ sec = BCD2BIN(sec);
+ min = BCD2BIN(min);
+ hour = BCD2BIN(hour);
+ day = BCD2BIN(day);
+ mon = BCD2BIN(mon);
+ year = BCD2BIN(year);
+ }
+ /*
+ * The PROM will reset the year to either '72 or '73.
+ * Therefore we store the real year separately, in one
+ * of unused BBU RAM locations.
+ */
+ real_year = CMOS_READ(RTC_DEC_YEAR);
+ year += real_year - 72 + 2000;
+
+ return mktime(year, mon, day, hour, min, sec);
+}
+
+/*
+ * In order to set the CMOS clock precisely, dec_rtc_set_mmss has to
+ * be called 500 ms after the second nowtime has started, because when
+ * nowtime is written into the registers of the CMOS clock, it will
+ * jump to the next second precisely 500 ms later. Check the Dallas
+ * DS1287 data sheet for details.
+ */
+static int dec_rtc_set_mmss(unsigned long nowtime)
+{
+ int retval = 0;
+ int real_seconds, real_minutes, cmos_minutes;
+ unsigned char save_control, save_freq_select;
+
+ /* tell the clock it's being set */
+ save_control = CMOS_READ(RTC_CONTROL);
+ CMOS_WRITE((save_control | RTC_SET), RTC_CONTROL);
+
+ /* stop and reset prescaler */
+ save_freq_select = CMOS_READ(RTC_FREQ_SELECT);
+ CMOS_WRITE((save_freq_select | RTC_DIV_RESET2), RTC_FREQ_SELECT);
+
+ cmos_minutes = CMOS_READ(RTC_MINUTES);
+ if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
+ cmos_minutes = BCD2BIN(cmos_minutes);
+
+ /*
+ * since we're only adjusting minutes and seconds,
+ * don't interfere with hour overflow. This avoids
+ * messing with unknown time zones but requires your
+ * RTC not to be off by more than 15 minutes
+ */
+ real_seconds = nowtime % 60;
+ real_minutes = nowtime / 60;
+ if (((abs(real_minutes - cmos_minutes) + 15) / 30) & 1)
+ real_minutes += 30; /* correct for half hour time zone */
+ real_minutes %= 60;
+
+ if (abs(real_minutes - cmos_minutes) < 30) {
+ if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
+ real_seconds = BIN2BCD(real_seconds);
+ real_minutes = BIN2BCD(real_minutes);
+ }
+ CMOS_WRITE(real_seconds, RTC_SECONDS);
+ CMOS_WRITE(real_minutes, RTC_MINUTES);
+ } else {
+ printk(KERN_WARNING
+ "set_rtc_mmss: can't update from %d to %d\n",
+ cmos_minutes, real_minutes);
+ retval = -1;
+ }
+
+ /* The following flags have to be released exactly in this order,
+ * otherwise the DS1287 will not reset the oscillator and will not
+ * update precisely 500 ms later. You won't find this mentioned
+ * in the Dallas Semiconductor data sheets, but who believes data
+ * sheets anyway ... -- Markus Kuhn
+ */
+ CMOS_WRITE(save_control, RTC_CONTROL);
+ CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
+
+ return retval;
+}
+
+
+static int dec_timer_state(void)
+{
+ return (CMOS_READ(RTC_REG_C) & RTC_PF) != 0;
+}
+
+static void dec_timer_ack(void)
+{
+ CMOS_READ(RTC_REG_C); /* Ack the RTC interrupt. */
+}
+
+static unsigned int dec_ioasic_hpt_read(void)
+{
+ /*
+ * The free-running counter is 32-bit which is good for about
+ * 2 minutes, 50 seconds at possible count rates of up to 25MHz.
+ */
+ return ioasic_read(IO_REG_FCTR);
+}
+
+static void dec_ioasic_hpt_init(unsigned int count)
+{
+ ioasic_write(IO_REG_FCTR, ioasic_read(IO_REG_FCTR) - count);
+}
+
+
+void __init dec_time_init(void)
+{
+ rtc_get_time = dec_rtc_get_time;
+ rtc_set_mmss = dec_rtc_set_mmss;
+
+ mips_timer_state = dec_timer_state;
+ mips_timer_ack = dec_timer_ack;
+
+ if (!cpu_has_counter && IOASIC) {
+ /* For pre-R4k systems we use the I/O ASIC's counter. */
+ mips_hpt_read = dec_ioasic_hpt_read;
+ mips_hpt_init = dec_ioasic_hpt_init;
+ }
+
+ /* Set up the rate of periodic DS1287 interrupts. */
+ CMOS_WRITE(RTC_REF_CLCK_32KHZ | (16 - LOG_2_HZ), RTC_REG_A);
+}
+
+EXPORT_SYMBOL(do_settimeofday);
+
+void __init dec_timer_setup(struct irqaction *irq)
+{
+ setup_irq(dec_interrupt[DEC_IRQ_RTC], irq);
+
+ /* Enable periodic DS1287 interrupts. */
+ CMOS_WRITE(CMOS_READ(RTC_REG_B) | RTC_PIE, RTC_REG_B);
+}
diff --git a/arch/mips/dec/wbflush.c b/arch/mips/dec/wbflush.c
new file mode 100644
index 0000000..925c052
--- /dev/null
+++ b/arch/mips/dec/wbflush.c
@@ -0,0 +1,94 @@
+/*
+ * Setup the right wbflush routine for the different DECstations.
+ *
+ * Created with information from:
+ * DECstation 3100 Desktop Workstation Functional Specification
+ * DECstation 5000/200 KN02 System Module Functional Specification
+ * mipsel-linux-objdump --disassemble vmunix | grep "wbflush" :-)
+ *
+ * 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) 1998 Harald Koerfgen
+ * Copyright (C) 2002 Maciej W. Rozycki
+ */
+
+#include <linux/init.h>
+
+#include <asm/bootinfo.h>
+#include <asm/system.h>
+#include <asm/wbflush.h>
+
+static void wbflush_kn01(void);
+static void wbflush_kn210(void);
+static void wbflush_mips(void);
+
+void (*__wbflush) (void);
+
+void __init wbflush_setup(void)
+{
+ switch (mips_machtype) {
+ case MACH_DS23100:
+ case MACH_DS5000_200: /* DS5000 3max */
+ __wbflush = wbflush_kn01;
+ break;
+ case MACH_DS5100: /* DS5100 MIPSMATE */
+ __wbflush = wbflush_kn210;
+ break;
+ case MACH_DS5000_1XX: /* DS5000/100 3min */
+ case MACH_DS5000_XX: /* Personal DS5000/2x */
+ case MACH_DS5000_2X0: /* DS5000/240 3max+ */
+ case MACH_DS5900: /* DS5900 bigmax */
+ default:
+ __wbflush = wbflush_mips;
+ break;
+ }
+}
+
+/*
+ * For the DS3100 and DS5000/200 the R2020/R3220 writeback buffer functions
+ * as part of Coprocessor 0.
+ */
+static void wbflush_kn01(void)
+{
+ asm(".set\tpush\n\t"
+ ".set\tnoreorder\n\t"
+ "1:\tbc0f\t1b\n\t"
+ "nop\n\t"
+ ".set\tpop");
+}
+
+/*
+ * For the DS5100 the writeback buffer seems to be a part of Coprocessor 3.
+ * But CP3 has to enabled first.
+ */
+static void wbflush_kn210(void)
+{
+ asm(".set\tpush\n\t"
+ ".set\tnoreorder\n\t"
+ "mfc0\t$2,$12\n\t"
+ "lui\t$3,0x8000\n\t"
+ "or\t$3,$2,$3\n\t"
+ "mtc0\t$3,$12\n\t"
+ "nop\n"
+ "1:\tbc3f\t1b\n\t"
+ "nop\n\t"
+ "mtc0\t$2,$12\n\t"
+ "nop\n\t"
+ ".set\tpop"
+ : : : "$2", "$3");
+}
+
+/*
+ * I/O ASIC systems use a standard writeback buffer that gets flushed
+ * upon an uncached read.
+ */
+static void wbflush_mips(void)
+{
+ __fast_iob();
+}
+
+#include <linux/module.h>
+
+EXPORT_SYMBOL(__wbflush);
diff --git a/arch/mips/defconfig b/arch/mips/defconfig
new file mode 100644
index 0000000..d55fe66
--- /dev/null
+++ b/arch/mips/defconfig
@@ -0,0 +1,962 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-rc2
+# Wed Jan 26 02:48:59 2005
+#
+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_LOCALVERSION=""
+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_KOBJECT_UEVENT=y
+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_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM 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_MODULE_SRCVERSION_ALL=y
+CONFIG_KMOD=y
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ 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_OCELOT_3 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_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_GENERIC_CALIBRATE_DELAY=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_ARC32=y
+CONFIG_BOOT_ELF32=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+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
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+# CONFIG_EISA is not set
+CONFIG_MMU=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=m
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# 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_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_ATA_OVER_ETH=m
+
+#
+# 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
+CONFIG_SCSI_ISCSI_ATTRS=m
+
+#
+# SCSI low-level drivers
+#
+CONFIG_SGIWD93_SCSI=y
+# CONFIG_SCSI_SATA 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
+CONFIG_INET_TUNNEL=m
+CONFIG_IP_TCPDIAG=m
+CONFIG_IP_TCPDIAG_IPV6=y
+
+#
+# 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_INET6_TUNNEL=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_CT_ACCT=y
+CONFIG_IP_NF_CONNTRACK_MARK=y
+# CONFIG_IP_NF_CT_PROTO_SCTP is not set
+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_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_REALM=m
+CONFIG_IP_NF_MATCH_SCTP=m
+CONFIG_IP_NF_MATCH_COMMENT=m
+CONFIG_IP_NF_MATCH_CONNMARK=m
+CONFIG_IP_NF_MATCH_HASHLIMIT=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_TARGET_TCPMSS=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_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_CONNMARK=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_TARGET_NOTRACK=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=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
+
+#
+# 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_CLS_U32_MARK 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=m
+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
+CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIO_RAW=m
+
+#
+# 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=y
+CONFIG_MOUSE_PS2=m
+CONFIG_MOUSE_SERIAL=m
+# CONFIG_MOUSE_VSXXXAA 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
+
+#
+# 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_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
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_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
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB_ARCH_HAS_HCD is not set
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND 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_DNOTIFY=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_RPCSEC_GSS_SPKM3 is not set
+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_EXPERIMENTAL 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
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
+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_ANUBIS=m
+CONFIG_CRYPTO_DEFLATE=y
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
+CONFIG_CRYPTO_TEST=m
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=m
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
diff --git a/arch/mips/galileo-boards/ev96100/Makefile b/arch/mips/galileo-boards/ev96100/Makefile
new file mode 100644
index 0000000..58c02f9
--- /dev/null
+++ b/arch/mips/galileo-boards/ev96100/Makefile
@@ -0,0 +1,9 @@
+#
+# Copyright 2000 MontaVista Software Inc.
+# Author: MontaVista Software, Inc.
+# ppopov@mvista.com or source@mvista.com
+#
+# Makefile for the Galileo EV96100 board.
+#
+
+obj-y += init.o irq.o puts.o reset.o time.o int-handler.o setup.o
diff --git a/arch/mips/galileo-boards/ev96100/init.c b/arch/mips/galileo-boards/ev96100/init.c
new file mode 100644
index 0000000..a01fe9b
--- /dev/null
+++ b/arch/mips/galileo-boards/ev96100/init.c
@@ -0,0 +1,173 @@
+/*
+ * Copyright 2000 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ * ppopov@mvista.com or source@mvista.com
+ *
+ * This file was derived from Carsten Langgaard's
+ * arch/mips/mips-boards/generic/generic.c
+ *
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/bootmem.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+
+#include <asm/addrspace.h>
+#include <asm/bootinfo.h>
+#include <asm/gt64120.h>
+
+
+/* Environment variable */
+
+typedef struct {
+ char *name;
+ char *val;
+} t_env_var;
+
+int prom_argc;
+char **prom_argv, **prom_envp;
+
+int init_debug = 0;
+
+char * __init prom_getcmdline(void)
+{
+ return &(arcs_cmdline[0]);
+}
+
+unsigned long __init prom_free_prom_memory(void)
+{
+ return 0;
+}
+
+void __init prom_init_cmdline(void)
+{
+ char *cp;
+ int actr;
+
+ actr = 1; /* Always ignore argv[0] */
+
+ cp = &(arcs_cmdline[0]);
+ while(actr < prom_argc) {
+ strcpy(cp, prom_argv[actr]);
+ cp += strlen(prom_argv[actr]);
+ *cp++ = ' ';
+ actr++;
+ }
+ if (cp != &(arcs_cmdline[0])) /* get rid of trailing space */
+ --cp;
+ *cp = '\0';
+}
+
+char *prom_getenv(char *envname)
+{
+ /*
+ * Return a pointer to the given environment variable.
+ */
+
+ t_env_var *env = (t_env_var *) prom_envp;
+ int i;
+
+ i = strlen(envname);
+
+ while (env->name) {
+ if (strncmp(envname, env->name, i) == 0) {
+ return (env->val);
+ }
+ env++;
+ }
+ return (NULL);
+}
+
+static inline unsigned char str2hexnum(unsigned char c)
+{
+ if (c >= '0' && c <= '9')
+ return c - '0';
+ if (c >= 'a' && c <= 'f')
+ return c - 'a' + 10;
+ return 0; /* foo */
+}
+
+static inline void str2eaddr(unsigned char *ea, unsigned char *str)
+{
+ int i;
+
+ for (i = 0; i < 6; i++) {
+ unsigned char num;
+
+ if ((*str == '.') || (*str == ':'))
+ str++;
+ num = str2hexnum(*str++) << 4;
+ num |= (str2hexnum(*str++));
+ ea[i] = num;
+ }
+}
+
+int get_ethernet_addr(char *ethernet_addr)
+{
+ char *ethaddr_str;
+
+ ethaddr_str = prom_getenv("ethaddr");
+ if (!ethaddr_str) {
+ printk("ethaddr not set in boot prom\n");
+ return -1;
+ }
+ str2eaddr(ethernet_addr, ethaddr_str);
+
+ if (init_debug > 1) {
+ int i;
+ printk("get_ethernet_addr: ");
+ for (i = 0; i < 5; i++)
+ printk("%02x:",
+ (unsigned char) *(ethernet_addr + i));
+ printk("%02x\n", *(ethernet_addr + i));
+ }
+
+ return 0;
+}
+
+const char *get_system_type(void)
+{
+ return "Galileo EV96100";
+}
+
+void __init prom_init(void)
+{
+ volatile unsigned char *uart;
+ char ppbuf[8];
+
+ prom_argc = fw_arg0;
+ prom_argv = (char **) fw_arg1;
+ prom_envp = (char **) fw_arg2;
+
+ mips_machgroup = MACH_GROUP_GALILEO;
+ mips_machtype = MACH_EV96100;
+
+ prom_init_cmdline();
+
+ /* 32 MB upgradable */
+ add_memory_region(0, 32 << 20, BOOT_MEM_RAM);
+}
diff --git a/arch/mips/galileo-boards/ev96100/int-handler.S b/arch/mips/galileo-boards/ev96100/int-handler.S
new file mode 100644
index 0000000..ff4d10a
--- /dev/null
+++ b/arch/mips/galileo-boards/ev96100/int-handler.S
@@ -0,0 +1,33 @@
+#include <asm/asm.h>
+#include <asm/mipsregs.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+
+ .set noat
+ .align 5
+
+NESTED(ev96100IRQ, PT_SIZE, sp)
+ SAVE_ALL
+ CLI # Important: mark KERNEL mode !
+
+ mfc0 t0, CP0_CAUSE # get pending interrupts
+ mfc0 t1, CP0_STATUS # get enabled interrupts
+ and t0, t1 # isolate allowed ones
+
+ # FIX ME add R7000 extensions
+ andi t0,0xff00 # isolate pending bits
+ andi a0, t0, CAUSEF_IP7
+ beq a0, zero, 1f
+ move a0, sp
+ jal mips_timer_interrupt
+ j ret_from_irq
+
+1: beqz t0, 3f # spurious interrupt
+
+ move a0, t0
+ move a1, sp
+ jal ev96100_cpu_irq
+ j ret_from_irq
+
+3: j spurious_interrupt
+ END(ev96100IRQ)
diff --git a/arch/mips/galileo-boards/ev96100/irq.c b/arch/mips/galileo-boards/ev96100/irq.c
new file mode 100644
index 0000000..97bf094
--- /dev/null
+++ b/arch/mips/galileo-boards/ev96100/irq.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2000 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ * ppopov@mvista.com or source@mvista.com
+ *
+ * This file was derived from Carsten Langgaard's
+ * arch/mips/mips-boards/atlas/atlas_int.c.
+ *
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel_stat.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <asm/irq_cpu.h>
+
+extern asmlinkage void ev96100IRQ(void);
+
+static inline unsigned int ffz8(unsigned int word)
+{
+ unsigned long k;
+
+ k = 7;
+ if (word & 0x0fUL) { k -= 4; word <<= 4; }
+ if (word & 0x30UL) { k -= 2; word <<= 2; }
+ if (word & 0x40UL) { k -= 1; }
+
+ return k;
+}
+
+asmlinkage void ev96100_cpu_irq(unsigned int pendin)
+{
+ do_IRQ(ffz8(pending >> 8), regs);
+}
+
+void __init arch_init_irq(void)
+{
+ set_except_vector(0, ev96100IRQ);
+ mips_cpu_irq_init(0);
+}
diff --git a/arch/mips/galileo-boards/ev96100/puts.c b/arch/mips/galileo-boards/ev96100/puts.c
new file mode 100644
index 0000000..49dc6d1
--- /dev/null
+++ b/arch/mips/galileo-boards/ev96100/puts.c
@@ -0,0 +1,138 @@
+
+/*
+ * Debug routines which directly access the uart.
+ */
+
+#include <linux/types.h>
+#include <asm/gt64120.h>
+
+
+//#define SERIAL_BASE EV96100_UART0_REGS_BASE
+#define SERIAL_BASE 0xBD000020
+#define NS16550_BASE SERIAL_BASE
+
+#define SERA_CMD 0x0D
+#define SERA_DATA 0x08
+//#define SERB_CMD 0x05
+#define SERB_CMD 20
+#define SERB_DATA 0x00
+#define TX_BUSY 0x20
+
+#define TIMEOUT 0xffff
+#undef SLOW_DOWN
+
+static const char digits[16] = "0123456789abcdef";
+static volatile unsigned char *const com1 = (unsigned char *) SERIAL_BASE;
+
+
+#ifdef SLOW_DOWN
+static inline void slow_down()
+{
+ int k;
+ for (k = 0; k < 10000; k++);
+}
+#else
+#define slow_down()
+#endif
+
+void putch(const unsigned char c)
+{
+ unsigned char ch;
+ int i = 0;
+
+ do {
+ ch = com1[SERB_CMD];
+ slow_down();
+ i++;
+ if (i > TIMEOUT) {
+ break;
+ }
+ } while (0 == (ch & TX_BUSY));
+ com1[SERB_DATA] = c;
+}
+
+void putchar(const unsigned char c)
+{
+ unsigned char ch;
+ int i = 0;
+
+ do {
+ ch = com1[SERB_CMD];
+ slow_down();
+ i++;
+ if (i > TIMEOUT) {
+ break;
+ }
+ } while (0 == (ch & TX_BUSY));
+ com1[SERB_DATA] = c;
+}
+
+void puts(unsigned char *cp)
+{
+ unsigned char ch;
+ int i = 0;
+
+ while (*cp) {
+ do {
+ ch = com1[SERB_CMD];
+ slow_down();
+ i++;
+ if (i > TIMEOUT) {
+ break;
+ }
+ } while (0 == (ch & TX_BUSY));
+ com1[SERB_DATA] = *cp++;
+ }
+ putch('\r');
+ putch('\n');
+}
+
+void fputs(unsigned char *cp)
+{
+ unsigned char ch;
+ int i = 0;
+
+ while (*cp) {
+
+ do {
+ ch = com1[SERB_CMD];
+ slow_down();
+ i++;
+ if (i > TIMEOUT) {
+ break;
+ }
+ } while (0 == (ch & TX_BUSY));
+ com1[SERB_DATA] = *cp++;
+ }
+}
+
+
+void put64(uint64_t ul)
+{
+ int cnt;
+ unsigned ch;
+
+ cnt = 16; /* 16 nibbles in a 64 bit long */
+ putch('0');
+ putch('x');
+ do {
+ cnt--;
+ ch = (unsigned char) (ul >> cnt * 4) & 0x0F;
+ putch(digits[ch]);
+ } while (cnt > 0);
+}
+
+void put32(unsigned u)
+{
+ int cnt;
+ unsigned ch;
+
+ cnt = 8; /* 8 nibbles in a 32 bit long */
+ putch('0');
+ putch('x');
+ do {
+ cnt--;
+ ch = (unsigned char) (u >> cnt * 4) & 0x0F;
+ putch(digits[ch]);
+ } while (cnt > 0);
+}
diff --git a/arch/mips/galileo-boards/ev96100/reset.c b/arch/mips/galileo-boards/ev96100/reset.c
new file mode 100644
index 0000000..5ef9b7f
--- /dev/null
+++ b/arch/mips/galileo-boards/ev96100/reset.c
@@ -0,0 +1,70 @@
+/*
+ * BRIEF MODULE DESCRIPTION
+ * Galileo EV96100 reset routines.
+ *
+ * Copyright 2000 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ * ppopov@mvista.com or source@mvista.com
+ *
+ * This file was derived from Carsten Langgaard's
+ * arch/mips/mips-boards/generic/reset.c
+ *
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/reboot.h>
+#include <asm/system.h>
+#include <asm/gt64120.h>
+
+static void mips_machine_restart(char *command);
+static void mips_machine_halt(void);
+
+static void mips_machine_restart(char *command)
+{
+ set_c0_status(ST0_BEV | ST0_ERL);
+ change_c0_config(CONF_CM_CMASK, CONF_CM_UNCACHED);
+ flush_cache_all();
+ write_c0_wired(0);
+ __asm__ __volatile__("jr\t%0"::"r"(0xbfc00000));
+ while (1);
+}
+
+static void mips_machine_halt(void)
+{
+ printk(KERN_NOTICE "You can safely turn off the power\n");
+ while (1)
+ __asm__(".set\tmips3\n\t"
+ "wait\n\t"
+ ".set\tmips0");
+}
+
+void mips_reboot_setup(void)
+{
+ _machine_restart = mips_machine_restart;
+ _machine_halt = mips_machine_halt;
+}
diff --git a/arch/mips/galileo-boards/ev96100/setup.c b/arch/mips/galileo-boards/ev96100/setup.c
new file mode 100644
index 0000000..28bd908
--- /dev/null
+++ b/arch/mips/galileo-boards/ev96100/setup.c
@@ -0,0 +1,162 @@
+/*
+ * BRIEF MODULE DESCRIPTION
+ * Galileo EV96100 setup.
+ *
+ * Copyright 2000 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ * ppopov@mvista.com or source@mvista.com
+ *
+ * This file was derived from Carsten Langgaard's
+ * arch/mips/mips-boards/atlas/atlas_setup.c.
+ *
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/string.h>
+#include <linux/ctype.h>
+#include <linux/pci.h>
+
+#include <asm/cpu.h>
+#include <asm/bootinfo.h>
+#include <asm/mipsregs.h>
+#include <asm/irq.h>
+#include <asm/delay.h>
+#include <asm/gt64120.h>
+#include <asm/galileo-boards/ev96100int.h>
+
+
+extern char *__init prom_getcmdline(void);
+
+extern void mips_reboot_setup(void);
+
+unsigned char mac_0_1[12];
+
+static void __init ev96100_setup(void)
+{
+ unsigned int config = read_c0_config();
+ unsigned int status = read_c0_status();
+ unsigned int info = read_c0_info();
+ u32 tmp;
+
+ char *argptr;
+
+ clear_c0_status(ST0_FR);
+
+ if (config & 0x8)
+ printk("Secondary cache is enabled\n");
+ else
+ printk("Secondary cache is disabled\n");
+
+ if (status & (1 << 27))
+ printk("User-mode cache ops enabled\n");
+ else
+ printk("User-mode cache ops disabled\n");
+
+ printk("CP0 info reg: %x\n", (unsigned) info);
+ if (info & (1 << 28))
+ printk("burst mode Scache RAMS\n");
+ else
+ printk("pipelined Scache RAMS\n");
+
+ if (info & 0x1)
+ printk("Atomic Enable is set\n");
+
+ argptr = prom_getcmdline();
+#ifdef CONFIG_SERIAL_CONSOLE
+ if (strstr(argptr, "console=") == NULL) {
+ argptr = prom_getcmdline();
+ strcat(argptr, " console=ttyS0,115200");
+ }
+#endif
+
+ mips_reboot_setup();
+
+ set_io_port_base(KSEG1);
+ ioport_resource.start = GT_PCI_IO_BASE;
+ ioport_resource.end = GT_PCI_IO_BASE + 0x01ffffff;
+
+#ifdef CONFIG_BLK_DEV_INITRD
+ ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0);
+#endif
+
+
+ /*
+ * Setup GT controller master bit so we can do config cycles
+ */
+
+ /* Clear cause register bits */
+ GT_WRITE(GT_INTRCAUSE_OFS, ~(GT_INTRCAUSE_MASABORT0_BIT |
+ GT_INTRCAUSE_TARABORT0_BIT));
+ /* Setup address */
+ GT_WRITE(GT_PCI0_CFGADDR_OFS,
+ (0 << GT_PCI0_CFGADDR_BUSNUM_SHF) |
+ (0 << GT_PCI0_CFGADDR_FUNCTNUM_SHF) |
+ ((PCI_COMMAND / 4) << GT_PCI0_CFGADDR_REGNUM_SHF) |
+ GT_PCI0_CFGADDR_CONFIGEN_BIT);
+
+ udelay(2);
+ tmp = GT_READ(GT_PCI0_CFGDATA_OFS);
+
+ tmp |= (PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
+ PCI_COMMAND_MASTER | PCI_COMMAND_SERR);
+ GT_WRITE(GT_PCI0_CFGADDR_OFS,
+ (0 << GT_PCI0_CFGADDR_BUSNUM_SHF) |
+ (0 << GT_PCI0_CFGADDR_FUNCTNUM_SHF) |
+ ((PCI_COMMAND / 4) << GT_PCI0_CFGADDR_REGNUM_SHF) |
+ GT_PCI0_CFGADDR_CONFIGEN_BIT);
+ udelay(2);
+ GT_WRITE(GT_PCI0_CFGDATA_OFS, tmp);
+
+ /* Setup address */
+ GT_WRITE(GT_PCI0_CFGADDR_OFS,
+ (0 << GT_PCI0_CFGADDR_BUSNUM_SHF) |
+ (0 << GT_PCI0_CFGADDR_FUNCTNUM_SHF) |
+ ((PCI_COMMAND / 4) << GT_PCI0_CFGADDR_REGNUM_SHF) |
+ GT_PCI0_CFGADDR_CONFIGEN_BIT);
+
+ udelay(2);
+ tmp = GT_READ(GT_PCI0_CFGDATA_OFS);
+}
+
+early_initcall(ev96100_setup);
+
+unsigned short get_gt_devid(void)
+{
+ u32 gt_devid;
+
+ /* Figure out if this is a gt96100 or gt96100A */
+ GT_WRITE(GT_PCI0_CFGADDR_OFS,
+ (0 << GT_PCI0_CFGADDR_BUSNUM_SHF) |
+ (0 << GT_PCI0_CFGADDR_FUNCTNUM_SHF) |
+ ((PCI_VENDOR_ID / 4) << GT_PCI0_CFGADDR_REGNUM_SHF) |
+ GT_PCI0_CFGADDR_CONFIGEN_BIT);
+
+ udelay(4);
+ gt_devid = GT_READ(GT_PCI0_CFGDATA_OFS);
+
+ return gt_devid >> 16;
+}
diff --git a/arch/mips/galileo-boards/ev96100/time.c b/arch/mips/galileo-boards/ev96100/time.c
new file mode 100644
index 0000000..bff5b1c
--- /dev/null
+++ b/arch/mips/galileo-boards/ev96100/time.c
@@ -0,0 +1,89 @@
+/*
+ * BRIEF MODULE DESCRIPTION
+ * Galileo EV96100 rtc routines.
+ *
+ * Copyright 2000 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ * ppopov@mvista.com or source@mvista.com
+ *
+ * This file was derived from Carsten Langgaard's
+ * arch/mips/mips-boards/atlas/atlas_rtc.c.
+ *
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/kernel_stat.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/timex.h>
+
+#include <asm/mipsregs.h>
+#include <asm/ptrace.h>
+#include <asm/time.h>
+
+
+#define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5)
+
+extern volatile unsigned long wall_jiffies;
+unsigned long missed_heart_beats = 0;
+
+static unsigned long r4k_offset; /* Amount to increment compare reg each time */
+static unsigned long r4k_cur; /* What counter should be at next timer irq */
+
+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 probably more robust.
+ */
+void mips_timer_interrupt(struct pt_regs *regs)
+{
+ int irq = 7; /* FIX ME */
+
+ if (r4k_offset == 0) {
+ goto null;
+ }
+
+ do {
+ kstat_this_cpu.irqs[irq]++;
+ do_timer(regs);
+#ifndef CONFIG_SMP
+ update_process_times(user_mode(regs));
+#endif
+ r4k_cur += r4k_offset;
+ ack_r4ktimer(r4k_cur);
+
+ } while (((unsigned long)read_c0_count()
+ - r4k_cur) < 0x7fffffff);
+ return;
+
+null:
+ ack_r4ktimer(0);
+}
diff --git a/arch/mips/gt64120/common/Makefile b/arch/mips/gt64120/common/Makefile
new file mode 100644
index 0000000..eba5051
--- /dev/null
+++ b/arch/mips/gt64120/common/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for common code of gt64120-based boards.
+#
+
+obj-y += time.o
+obj-$(CONFIG_PCI) += pci.o
diff --git a/arch/mips/gt64120/common/pci.c b/arch/mips/gt64120/common/pci.c
new file mode 100644
index 0000000..e9e5419
--- /dev/null
+++ b/arch/mips/gt64120/common/pci.c
@@ -0,0 +1,147 @@
+/*
+ * BRIEF MODULE DESCRIPTION
+ * Galileo Evaluation Boards PCI support.
+ *
+ * The general-purpose functions to read/write and configure the GT64120A's
+ * PCI registers (function names start with pci0 or pci1) are either direct
+ * copies of functions written by Galileo Technology, or are modifications
+ * of their functions to work with Linux 2.4 vs Linux 2.2. These functions
+ * are Copyright - Galileo Technology.
+ *
+ * Other functions are derived from other MIPS PCI implementations, or were
+ * written by RidgeRun, Inc, Copyright (C) 2000 RidgeRun, Inc.
+ * glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <asm/gt64120.h>
+
+#define SELF 0
+
+/*
+ * pciXReadConfigReg - Read from a PCI configuration register
+ * - Make sure the GT is configured as a master before
+ * reading from another device on the PCI.
+ * - The function takes care of Big/Little endian conversion.
+ * INPUTS: regOffset: The register offset as it apears in the GT spec (or PCI
+ * spec)
+ * pciDevNum: The device number needs to be addressed.
+ * RETURNS: data , if the data == 0xffffffff check the master abort bit in the
+ * cause register to make sure the data is valid
+ *
+ * Configuration Address 0xCF8:
+ *
+ * 31 30 24 23 16 15 11 10 8 7 2 0 <=bit Number
+ * |congif|Reserved| Bus |Device|Function|Register|00|
+ * |Enable| |Number|Number| Number | Number | | <=field Name
+ *
+ */
+static unsigned int pci0ReadConfigReg(int offset, struct pci_dev *device)
+{
+ unsigned int DataForRegCf8;
+ unsigned int data;
+
+ DataForRegCf8 = ((PCI_SLOT(device->devfn) << 11) |
+ (PCI_FUNC(device->devfn) << 8) |
+ (offset & ~0x3)) | 0x80000000;
+ GT_WRITE(GT_PCI0_CFGADDR_OFS, DataForRegCf8);
+
+ /*
+ * The casual observer might wonder why the READ is duplicated here,
+ * rather than immediately following the WRITE, and just have the swap
+ * in the "if". That's because there is a latency problem with trying
+ * to read immediately after setting up the address register. The "if"
+ * check gives enough time for the address to stabilize, so the READ
+ * can work.
+ */
+ if (PCI_SLOT(device->devfn) == SELF) /* This board */
+ return GT_READ(GT_PCI0_CFGDATA_OFS);
+ else /* PCI is little endian so swap the Data. */
+ return __GT_READ(GT_PCI0_CFGDATA_OFS);
+}
+
+/*
+ * pciXWriteConfigReg - Write to a PCI configuration register
+ * - Make sure the GT is configured as a master before
+ * writingto another device on the PCI.
+ * - The function takes care of Big/Little endian conversion.
+ * Inputs: unsigned int regOffset: The register offset as it apears in the
+ * GT spec
+ * (or any other PCI device spec)
+ * pciDevNum: The device number needs to be addressed.
+ *
+ * Configuration Address 0xCF8:
+ *
+ * 31 30 24 23 16 15 11 10 8 7 2 0 <=bit Number
+ * |congif|Reserved| Bus |Device|Function|Register|00|
+ * |Enable| |Number|Number| Number | Number | | <=field Name
+ *
+ */
+static void pci0WriteConfigReg(unsigned int offset,
+ struct pci_dev *device, unsigned int data)
+{
+ unsigned int DataForRegCf8;
+
+ DataForRegCf8 = ((PCI_SLOT(device->devfn) << 11) |
+ (PCI_FUNC(device->devfn) << 8) |
+ (offset & ~0x3)) | 0x80000000;
+ GT_WRITE(GT_PCI0_CFGADDR_OFS, DataForRegCf8);
+
+ if (PCI_SLOT(device->devfn) == SELF) /* This board */
+ GT_WRITE(GT_PCI0_CFGDATA_OFS, data);
+ else /* configuration Transaction over the pci. */
+ __GT_WRITE(GT_PCI0_CFGDATA_OFS, data);
+}
+
+extern struct pci_ops gt64120_pci_ops;
+
+void __init pcibios_init(void)
+{
+ u32 tmp;
+ struct pci_dev controller;
+
+ controller.devfn = SELF;
+
+ tmp = GT_READ(GT_PCI0_CMD_OFS); /* Huh??? -- Ralf */
+ tmp = GT_READ(GT_PCI0_BARE_OFS);
+
+ /*
+ * You have to enable bus mastering to configure any other
+ * card on the bus.
+ */
+ tmp = pci0ReadConfigReg(PCI_COMMAND, &controller);
+ tmp |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_SERR;
+ pci0WriteConfigReg(PCI_COMMAND, &controller, tmp);
+
+ /*
+ * Reset PCI I/O and PCI MEM values to ones supported by EVM.
+ */
+ ioport_resource.start = GT_PCI_IO_BASE;
+ ioport_resource.end = GT_PCI_IO_BASE + GT_PCI_IO_SIZE - 1;
+ iomem_resource.start = GT_PCI_MEM_BASE;
+ iomem_resource.end = GT_PCI_MEM_BASE + GT_PCI_MEM_SIZE - 1;
+
+ pci_scan_bus(0, >64120_pci_ops, NULL);
+}
diff --git a/arch/mips/gt64120/common/time.c b/arch/mips/gt64120/common/time.c
new file mode 100644
index 0000000..2287b59
--- /dev/null
+++ b/arch/mips/gt64120/common/time.c
@@ -0,0 +1,100 @@
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * Galileo Technology chip interrupt handler
+ */
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/config.h>
+#include <linux/sched.h>
+#include <linux/kernel_stat.h>
+#include <asm/ptrace.h>
+#include <asm/gt64120.h>
+
+/*
+ * These are interrupt handlers for the GT on-chip interrupts. They all come
+ * in to the MIPS on a single interrupt line, and have to be handled and ack'ed
+ * differently than other MIPS interrupts.
+ */
+
+static void gt64120_irq(int irq, void *dev_id, struct pt_regs *regs)
+{
+ unsigned int irq_src, int_high_src, irq_src_mask, int_high_src_mask;
+ int handled = 0;
+
+ irq_src = GT_READ(GT_INTRCAUSE_OFS);
+ irq_src_mask = GT_READ(GT_INTRMASK_OFS);
+ int_high_src = GT_READ(GT_HINTRCAUSE_OFS);
+ int_high_src_mask = GT_READ(GT_HINTRMASK_OFS);
+ irq_src = irq_src & irq_src_mask;
+ int_high_src = int_high_src & int_high_src_mask;
+
+ if (irq_src & 0x00000800) { /* Check for timer interrupt */
+ handled = 1;
+ irq_src &= ~0x00000800;
+ do_timer(regs);
+#ifndef CONFIG_SMP
+ update_process_times(user_mode(regs));
+#endif
+ }
+
+ GT_WRITE(GT_INTRCAUSE_OFS, 0);
+ GT_WRITE(GT_HINTRCAUSE_OFS, 0);
+}
+
+/*
+ * Initializes timer using galileo's built in timer.
+ */
+#ifdef CONFIG_SYSCLK_100
+#define Sys_clock (100 * 1000000) // 100 MHz
+#endif
+#ifdef CONFIG_SYSCLK_83
+#define Sys_clock (83.333 * 1000000) // 83.333 MHz
+#endif
+#ifdef CONFIG_SYSCLK_75
+#define Sys_clock (75 * 1000000) // 75 MHz
+#endif
+
+/*
+ * This will ignore the standard MIPS timer interrupt handler that is passed in
+ * as *irq (=irq0 in ../kernel/time.c). We will do our own timer interrupt
+ * handling.
+ */
+void gt64120_time_init(void)
+{
+ static struct irqaction timer;
+
+ /* Disable timer first */
+ GT_WRITE(GT_TC_CONTROL_OFS, 0);
+ /* Load timer value for 100 Hz */
+ GT_WRITE(GT_TC3_OFS, Sys_clock / 100);
+
+ /*
+ * Create the IRQ structure entry for the timer. Since we're too early
+ * in the boot process to use the "request_irq()" call, we'll hard-code
+ * the values to the correct interrupt line.
+ */
+ timer.handler = gt64120_irq;
+ timer.flags = SA_SHIRQ | SA_INTERRUPT;
+ timer.name = "timer";
+ timer.dev_id = NULL;
+ timer.next = NULL;
+ timer.mask = CPU_MASK_NONE;
+ irq_desc[GT_TIMER].action = &timer;
+
+ enable_irq(GT_TIMER);
+
+ /* Enable timer ints */
+ GT_WRITE(GT_TC_CONTROL_OFS, 0xc0);
+ /* clear Cause register first */
+ GT_WRITE(GT_INTRCAUSE_OFS, 0x0);
+ /* Unmask timer int */
+ GT_WRITE(GT_INTRMASK_OFS, 0x800);
+ /* Clear High int register */
+ GT_WRITE(GT_HINTRCAUSE_OFS, 0x0);
+ /* Mask All interrupts at High cause interrupt */
+ GT_WRITE(GT_HINTRMASK_OFS, 0x0);
+}
diff --git a/arch/mips/gt64120/ev64120/Makefile b/arch/mips/gt64120/ev64120/Makefile
new file mode 100644
index 0000000..ebe91c5
--- /dev/null
+++ b/arch/mips/gt64120/ev64120/Makefile
@@ -0,0 +1,11 @@
+#
+# Copyright 2000 RidgeRun, Inc.
+# Author: RidgeRun, Inc.
+# glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com
+#
+# Makefile for the Galileo EV64120 board.
+#
+
+obj-y += int-handler.o irq.o promcon.o reset.o serialGT.o setup.o
+
+EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/gt64120/ev64120/int-handler.S b/arch/mips/gt64120/ev64120/int-handler.S
new file mode 100644
index 0000000..752435f
--- /dev/null
+++ b/arch/mips/gt64120/ev64120/int-handler.S
@@ -0,0 +1,113 @@
+/*
+ * int-handler.S
+ *
+ * Based on the cobalt handler.
+ */
+#include <asm/asm.h>
+#include <asm/mipsregs.h>
+#include <asm/addrspace.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+
+/*
+ * galileo_handle_int -
+ * We check for the timer first, then check PCI ints A and D.
+ * Then check for serial IRQ and fall through.
+ */
+ .align 5
+ .set reorder
+ .set noat
+ NESTED(galileo_handle_int, PT_SIZE, sp)
+ SAVE_ALL
+ CLI
+ .set at
+ mfc0 t0,CP0_CAUSE
+ mfc0 t2,CP0_STATUS
+
+ and t0,t2
+
+ andi t1,t0,STATUSF_IP4 /* int2 hardware line (timer) */
+ bnez t1,ll_gt64120_irq
+ andi t1,t0,STATUSF_IP2 /* int0 hardware line */
+ bnez t1,ll_pci_intA
+ andi t1,t0,STATUSF_IP5 /* int3 hardware line */
+ bnez t1,ll_pci_intD
+ andi t1,t0,STATUSF_IP6 /* int4 hardware line */
+ bnez t1,ll_serial_irq
+ andi t1,t0,STATUSF_IP7 /* compare int */
+ bnez t1,ll_compare_irq
+ nop
+
+ /* wrong alarm or masked ... */
+ j spurious_interrupt
+ nop
+ END(galileo_handle_int)
+
+
+ .align 5
+ .set reorder
+ll_gt64120_irq:
+ li a0,4
+ move a1,sp
+ jal do_IRQ
+ nop
+ j ret_from_irq
+ nop
+
+ .align 5
+ .set reorder
+ll_compare_irq:
+ li a0,7
+ move a1,sp
+ jal do_IRQ
+ nop
+ j ret_from_irq
+ nop
+
+ .align 5
+ .set reorder
+ll_pci_intA:
+ move a0,sp
+ jal pci_intA
+ nop
+ j ret_from_irq
+ nop
+
+#if 0
+ .align 5
+ .set reorder
+ll_pci_intB:
+ move a0,sp
+ jal pci_intB
+ nop
+ j ret_from_irq
+ nop
+
+ .align 5
+ .set reorder
+ll_pci_intC:
+ move a0,sp
+ jal pci_intC
+ nop
+ j ret_from_irq
+ nop
+#endif
+
+ .align 5
+ .set reorder
+ll_pci_intD:
+ move a0,sp
+ jal pci_intD
+ nop
+ j ret_from_irq
+ nop
+
+ .align 5
+ .set reorder
+ll_serial_irq:
+ li a0,6
+ move a1,sp
+ jal do_IRQ
+ nop
+ j ret_from_irq
+ nop
diff --git a/arch/mips/gt64120/ev64120/irq.c b/arch/mips/gt64120/ev64120/irq.c
new file mode 100644
index 0000000..3b18615
--- /dev/null
+++ b/arch/mips/gt64120/ev64120/irq.c
@@ -0,0 +1,145 @@
+/*
+ * BRIEF MODULE DESCRIPTION
+ * Code to handle irqs on GT64120A boards
+ * Derived from mips/orion and Cort <cort@fsmlabs.com>
+ *
+ * Copyright (C) 2000 RidgeRun, Inc.
+ * Author: RidgeRun, Inc.
+ * glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel_stat.h>
+#include <linux/module.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/timex.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+#include <linux/bitops.h>
+#include <asm/bootinfo.h>
+#include <asm/io.h>
+#include <asm/mipsregs.h>
+#include <asm/system.h>
+#include <asm/gt64120.h>
+
+asmlinkage inline void pci_intA(struct pt_regs *regs)
+{
+ do_IRQ(GT_INTA, regs);
+}
+
+asmlinkage inline void pci_intD(struct pt_regs *regs)
+{
+ do_IRQ(GT_INTD, regs);
+}
+
+static void disable_ev64120_irq(unsigned int irq_nr)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+ if (irq_nr >= 8) { // All PCI interrupts are on line 5 or 2
+ clear_c0_status(9 << 10);
+ } else {
+ clear_c0_status(1 << (irq_nr + 8));
+ }
+ local_irq_restore(flags);
+}
+
+static void enable_ev64120_irq(unsigned int irq_nr)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+ if (irq_nr >= 8) // All PCI interrupts are on line 5 or 2
+ set_c0_status(9 << 10);
+ else
+ set_c0_status(1 << (irq_nr + 8));
+ local_irq_restore(flags);
+}
+
+static unsigned int startup_ev64120_irq(unsigned int irq)
+{
+ enable_ev64120_irq(irq);
+ return 0; /* Never anything pending */
+}
+
+#define shutdown_ev64120_irq disable_ev64120_irq
+#define mask_and_ack_ev64120_irq disable_ev64120_irq
+
+static void end_ev64120_irq(unsigned int irq)
+{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+ enable_ev64120_irq(irq);
+}
+
+static struct hw_interrupt_type ev64120_irq_type = {
+ .typename = "EV64120",
+ .startup = startup_ev64120_irq,
+ .shutdown = shutdown_ev64120_irq,
+ .enable = enable_ev64120_irq,
+ .disable = disable_ev64120_irq,
+ .ack = mask_and_ack_ev64120_irq,
+ .end = end_ev64120_irq,
+ .set_affinity = NULL
+};
+
+void gt64120_irq_setup(void)
+{
+ extern asmlinkage void galileo_handle_int(void);
+
+ /*
+ * Clear all of the interrupts while we change the able around a bit.
+ */
+ clear_c0_status(ST0_IM);
+
+ /* Sets the exception_handler array. */
+ set_except_vector(0, galileo_handle_int);
+
+ local_irq_disable();
+
+ /*
+ * Enable timer. Other interrupts will be enabled as they are
+ * registered.
+ */
+ set_c0_status(IE_IRQ2);
+}
+
+void __init arch_init_irq(void)
+{
+ int i;
+
+ /* Let's initialize our IRQ descriptors */
+ for (i = 0; i < NR_IRQS; i++) {
+ irq_desc[i].status = 0;
+ irq_desc[i].handler = &no_irq_type;
+ irq_desc[i].action = NULL;
+ irq_desc[i].depth = 0;
+ spin_lock_init(&irq_desc[i].lock);
+ }
+
+ gt64120_irq_setup();
+}
diff --git a/arch/mips/gt64120/ev64120/promcon.c b/arch/mips/gt64120/ev64120/promcon.c
new file mode 100644
index 0000000..b5937c4
--- /dev/null
+++ b/arch/mips/gt64120/ev64120/promcon.c
@@ -0,0 +1,53 @@
+/*
+ * Wrap-around code for a console using the
+ * SGI PROM io-routines.
+ *
+ * Copyright (c) 1999 Ulf Carlsson
+ *
+ * Derived from DECstation promcon.c
+ * Copyright (c) 1998 Harald Koerfgen
+ */
+#include <linux/tty.h>
+#include <linux/init.h>
+#include <linux/console.h>
+
+static void prom_console_write(struct console *co, const char *s,
+ unsigned count)
+{
+ extern int CONSOLE_CHANNEL; // The default serial port
+ unsigned i;
+
+ for (i = 0; i < count; i++) {
+ if (*s == 10)
+ serial_putc(CONSOLE_CHANNEL, 13);
+ serial_putc(CONSOLE_CHANNEL, *s++);
+ }
+}
+
+int prom_getchar(void)
+{
+ return 0;
+}
+
+static struct console sercons = {
+ .name = "ttyS",
+ .write = prom_console_write,
+ .flags = CON_PRINTBUFFER,
+ .index = -1,
+};
+
+/*
+ * Register console.
+ */
+
+static int gal_serial_console_init(void)
+{
+ // serial_init();
+ //serial_set(115200);
+
+ register_console(&sercons);
+
+ return 0;
+}
+
+console_initcall(gal_serial_console_init);
diff --git a/arch/mips/gt64120/ev64120/reset.c b/arch/mips/gt64120/ev64120/reset.c
new file mode 100644
index 0000000..7b9f5e5
--- /dev/null
+++ b/arch/mips/gt64120/ev64120/reset.c
@@ -0,0 +1,45 @@
+/*
+ * 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) 1997 Ralf Baechle
+ */
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/reboot.h>
+#include <asm/system.h>
+
+void galileo_machine_restart(char *command)
+{
+ *(volatile char *) 0xbc000000 = 0x0f;
+ /*
+ * Ouch, we're still alive ... This time we take the silver bullet ...
+ * ... and find that we leave the hardware in a state in which the
+ * kernel in the flush locks up somewhen during of after the PCI
+ * detection stuff.
+ */
+ set_c0_status(ST0_BEV | ST0_ERL);
+ change_c0_config(CONF_CM_CMASK, CONF_CM_UNCACHED);
+ flush_cache_all();
+ write_c0_wired(0);
+ __asm__ __volatile__("jr\t%0"::"r"(0xbfc00000));
+}
+
+void galileo_machine_halt(void)
+{
+ printk(KERN_NOTICE "You can safely turn off the power\n");
+ while (1)
+ __asm__(".set\tmips3\n\t"
+ "wait\n\t"
+ ".set\tmips0");
+
+}
+
+void galileo_machine_power_off(void)
+{
+ galileo_machine_halt();
+}
diff --git a/arch/mips/gt64120/ev64120/serialGT.c b/arch/mips/gt64120/ev64120/serialGT.c
new file mode 100644
index 0000000..16e34a5
--- /dev/null
+++ b/arch/mips/gt64120/ev64120/serialGT.c
@@ -0,0 +1,212 @@
+/*
+ * serialGT.c
+ *
+ * BRIEF MODULE DESCRIPTION
+ * Low Level Serial Port control for use
+ * with the Galileo EVB64120A MIPS eval board and
+ * its on board two channel 16552 Uart.
+ *
+ * Copyright (C) 2000 RidgeRun, Inc.
+ * Author: RidgeRun, Inc.
+ * glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+// Note:
+// Serial CHANNELS - 0 is the bottom connector of evb64120A.
+// (The one that maps to the "B" channel of the
+// board's uart)
+// 1 is the top connector of evb64120A.
+// (The one that maps to the "A" channel of the
+// board's uart)
+int DEBUG_CHANNEL = 0; // See Note Above
+int CONSOLE_CHANNEL = 1; // See Note Above
+
+#define DUART 0xBD000000 /* Base address of Uart. */
+#define CHANNELOFFSET 0x20 /* DUART+CHANNELOFFSET gets you to the ChanA
+ register set of the 16552 Uart device.
+ DUART+0 gets you to the ChanB register set.
+ */
+#define DUART_DELTA 0x4
+#define FIFO_ENABLE 0x07
+#define INT_ENABLE 0x04 /* default interrupt mask */
+
+#define RBR 0x00
+#define THR 0x00
+#define DLL 0x00
+#define IER 0x01
+#define DLM 0x01
+#define IIR 0x02
+#define FCR 0x02
+#define LCR 0x03
+#define MCR 0x04
+#define LSR 0x05
+#define MSR 0x06
+#define SCR 0x07
+
+#define LCR_DLAB 0x80
+#define XTAL 1843200
+#define LSR_THRE 0x20
+#define LSR_BI 0x10
+#define LSR_DR 0x01
+#define MCR_LOOP 0x10
+#define ACCESS_DELAY 0x10000
+
+/******************************
+ Routine:
+ Description:
+ ******************************/
+int inreg(int channel, int reg)
+{
+ int val;
+ val =
+ *((volatile unsigned char *) DUART +
+ (channel * CHANNELOFFSET) + (reg * DUART_DELTA));
+ return val;
+}
+
+/******************************
+ Routine:
+ Description:
+ ******************************/
+void outreg(int channel, int reg, unsigned char val)
+{
+ *((volatile unsigned char *) DUART + (channel * CHANNELOFFSET)
+ + (reg * DUART_DELTA)) = val;
+}
+
+/******************************
+ Routine:
+ Description:
+ Initialize the device driver.
+ ******************************/
+void serial_init(int channel)
+{
+ /*
+ * Configure active port, (CHANNELOFFSET already set.)
+ *
+ * Set 8 bits, 1 stop bit, no parity.
+ *
+ * LCR<7> 0 divisor latch access bit
+ * LCR<6> 0 break control (1=send break)
+ * LCR<5> 0 stick parity (0=space, 1=mark)
+ * LCR<4> 0 parity even (0=odd, 1=even)
+ * LCR<3> 0 parity enable (1=enabled)
+ * LCR<2> 0 # stop bits (0=1, 1=1.5)
+ * LCR<1:0> 11 bits per character(00=5, 01=6, 10=7, 11=8)
+ */
+ outreg(channel, LCR, 0x3);
+
+ outreg(channel, FCR, FIFO_ENABLE); /* Enable the FIFO */
+
+ outreg(channel, IER, INT_ENABLE); /* Enable appropriate interrupts */
+}
+
+/******************************
+ Routine:
+ Description:
+ Set the baud rate.
+ ******************************/
+void serial_set(int channel, unsigned long baud)
+{
+ unsigned char sav_lcr;
+
+ /*
+ * Enable access to the divisor latches by setting DLAB in LCR.
+ *
+ */
+ sav_lcr = inreg(channel, LCR);
+
+#if 0
+ /*
+ * Set baud rate
+ */
+ outreg(channel, LCR, LCR_DLAB | sav_lcr);
+ // outreg(DLL,(XTAL/(16*2*(baud))-2));
+ outreg(channel, DLL, XTAL / (16 * baud));
+ // outreg(DLM,(XTAL/(16*2*(baud))-2)>>8);
+ outreg(channel, DLM, (XTAL / (16 * baud)) >> 8);
+#else
+ /*
+ * Note: Set baud rate, hardcoded here for rate of 115200
+ * since became unsure of above "buad rate" algorithm (??).
+ */
+ outreg(channel, LCR, 0x83);
+ outreg(channel, DLM, 0x00); // See note above
+ outreg(channel, DLL, 0x02); // See note above.
+ outreg(channel, LCR, 0x03);
+#endif
+
+ /*
+ * Restore line control register
+ */
+ outreg(channel, LCR, sav_lcr);
+}
+
+
+/******************************
+ Routine:
+ Description:
+ Transmit a character.
+ ******************************/
+void serial_putc(int channel, int c)
+{
+ while ((inreg(channel, LSR) & LSR_THRE) == 0);
+ outreg(channel, THR, c);
+}
+
+/******************************
+ Routine:
+ Description:
+ Read a received character if one is
+ available. Return -1 otherwise.
+ ******************************/
+int serial_getc(int channel)
+{
+ if (inreg(channel, LSR) & LSR_DR) {
+ return inreg(channel, RBR);
+ }
+ return -1;
+}
+
+/******************************
+ Routine:
+ Description:
+ Used by embedded gdb client. (example; gdb-stub.c)
+ ******************************/
+char getDebugChar()
+{
+ int val;
+ while ((val = serial_getc(DEBUG_CHANNEL)) == -1); // loop until we get a character in.
+ return (char) val;
+}
+
+/******************************
+ Routine:
+ Description:
+ Used by embedded gdb target. (example; gdb-stub.c)
+ ******************************/
+void putDebugChar(char c)
+{
+ serial_putc(DEBUG_CHANNEL, (int) c);
+}
diff --git a/arch/mips/gt64120/ev64120/setup.c b/arch/mips/gt64120/ev64120/setup.c
new file mode 100644
index 0000000..dba0961
--- /dev/null
+++ b/arch/mips/gt64120/ev64120/setup.c
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2000 RidgeRun, Inc.
+ * Author: RidgeRun, Inc.
+ * glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/swap.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/timex.h>
+#include <asm/bootinfo.h>
+#include <asm/page.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/pci.h>
+#include <asm/processor.h>
+#include <asm/ptrace.h>
+#include <asm/time.h>
+#include <asm/reboot.h>
+#include <asm/traps.h>
+#include <linux/bootmem.h>
+
+unsigned long gt64120_base = KSEG1ADDR(0x14000000);
+
+/* These functions are used for rebooting or halting the machine*/
+extern void galileo_machine_restart(char *command);
+extern void galileo_machine_halt(void);
+extern void galileo_machine_power_off(void);
+/*
+ *This structure holds pointers to the pci configuration space accesses
+ *and interrupts allocating routine for device over the PCI
+ */
+extern struct pci_ops galileo_pci_ops;
+
+unsigned long __init prom_free_prom_memory(void)
+{
+ return 0;
+}
+
+/*
+ * Initializes basic routines and structures pointers, memory size (as
+ * given by the bios and saves the command line.
+ */
+extern void gt64120_time_init(void);
+
+static void __init ev64120_setup(void)
+{
+ _machine_restart = galileo_machine_restart;
+ _machine_halt = galileo_machine_halt;
+ _machine_power_off = galileo_machine_power_off;
+
+ board_time_init = gt64120_time_init;
+ set_io_port_base(KSEG1);
+}
+
+early_initcall(ev64120_setup);
+
+const char *get_system_type(void)
+{
+ return "Galileo EV64120A";
+}
+
+/*
+ * Kernel arguments passed by the firmware
+ *
+ * $a0 - nothing
+ * $a1 - holds a pointer to the eprom parameters
+ * $a2 - nothing
+ */
+
+void __init prom_init(void)
+{
+ mips_machgroup = MACH_GROUP_GALILEO;
+ mips_machtype = MACH_EV64120A;
+
+ add_memory_region(0, 32 << 20, BOOT_MEM_RAM);
+}
diff --git a/arch/mips/gt64120/momenco_ocelot/Makefile b/arch/mips/gt64120/momenco_ocelot/Makefile
new file mode 100644
index 0000000..7b59c65
--- /dev/null
+++ b/arch/mips/gt64120/momenco_ocelot/Makefile
@@ -0,0 +1,9 @@
+#
+# Makefile for Momentum's Ocelot board.
+#
+
+obj-y += int-handler.o irq.o prom.o reset.o setup.o
+
+obj-$(CONFIG_KGDB) += dbg_io.o
+
+EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/gt64120/momenco_ocelot/dbg_io.c b/arch/mips/gt64120/momenco_ocelot/dbg_io.c
new file mode 100644
index 0000000..8720bcc
--- /dev/null
+++ b/arch/mips/gt64120/momenco_ocelot/dbg_io.c
@@ -0,0 +1,126 @@
+#include <linux/config.h>
+
+#ifdef CONFIG_KGDB
+
+#include <asm/serial.h> /* For the serial port location and base baud */
+
+/* --- CONFIG --- */
+
+typedef unsigned char uint8;
+typedef unsigned int uint32;
+
+/* --- END OF CONFIG --- */
+
+#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
+
+/* ----------------------------------------------------- */
+
+/* === CONFIG === */
+
+/* [jsun] we use the second serial port for kdb */
+#define BASE OCELOT_SERIAL1_BASE
+#define MAX_BAUD OCELOT_BASE_BAUD
+
+/* === END OF CONFIG === */
+
+#define REG_OFFSET 4
+
+/* register offset */
+#define OFS_RCV_BUFFER 0
+#define OFS_TRANS_HOLD 0
+#define OFS_SEND_BUFFER 0
+#define OFS_INTR_ENABLE (1*REG_OFFSET)
+#define OFS_INTR_ID (2*REG_OFFSET)
+#define OFS_DATA_FORMAT (3*REG_OFFSET)
+#define OFS_LINE_CONTROL (3*REG_OFFSET)
+#define OFS_MODEM_CONTROL (4*REG_OFFSET)
+#define OFS_RS232_OUTPUT (4*REG_OFFSET)
+#define OFS_LINE_STATUS (5*REG_OFFSET)
+#define OFS_MODEM_STATUS (6*REG_OFFSET)
+#define OFS_RS232_INPUT (6*REG_OFFSET)
+#define OFS_SCRATCH_PAD (7*REG_OFFSET)
+
+#define OFS_DIVISOR_LSB (0*REG_OFFSET)
+#define OFS_DIVISOR_MSB (1*REG_OFFSET)
+
+
+/* memory-mapped read/write of the port */
+#define UART16550_READ(y) (*((volatile uint8*)(BASE + y)))
+#define UART16550_WRITE(y, z) ((*((volatile uint8*)(BASE + y))) = z)
+
+void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop)
+{
+ /* disable interrupts */
+ UART16550_WRITE(OFS_INTR_ENABLE, 0);
+
+ /* set up buad rate */
+ {
+ uint32 divisor;
+
+ /* set DIAB bit */
+ UART16550_WRITE(OFS_LINE_CONTROL, 0x80);
+
+ /* set divisor */
+ divisor = MAX_BAUD / baud;
+ UART16550_WRITE(OFS_DIVISOR_LSB, divisor & 0xff);
+ UART16550_WRITE(OFS_DIVISOR_MSB, (divisor & 0xff00) >> 8);
+
+ /* clear DIAB bit */
+ UART16550_WRITE(OFS_LINE_CONTROL, 0x0);
+ }
+
+ /* set data format */
+ UART16550_WRITE(OFS_DATA_FORMAT, data | parity | stop);
+}
+
+static int remoteDebugInitialized = 0;
+
+uint8 getDebugChar(void)
+{
+ if (!remoteDebugInitialized) {
+ remoteDebugInitialized = 1;
+ debugInit(UART16550_BAUD_38400,
+ UART16550_DATA_8BIT,
+ UART16550_PARITY_NONE, UART16550_STOP_1BIT);
+ }
+
+ while ((UART16550_READ(OFS_LINE_STATUS) & 0x1) == 0);
+ return UART16550_READ(OFS_RCV_BUFFER);
+}
+
+
+int putDebugChar(uint8 byte)
+{
+ if (!remoteDebugInitialized) {
+ remoteDebugInitialized = 1;
+ debugInit(UART16550_BAUD_38400,
+ UART16550_DATA_8BIT,
+ UART16550_PARITY_NONE, UART16550_STOP_1BIT);
+ }
+
+ while ((UART16550_READ(OFS_LINE_STATUS) & 0x20) == 0);
+ UART16550_WRITE(OFS_SEND_BUFFER, byte);
+ return 1;
+}
+
+#endif
diff --git a/arch/mips/gt64120/momenco_ocelot/int-handler.S b/arch/mips/gt64120/momenco_ocelot/int-handler.S
new file mode 100644
index 0000000..808acef
--- /dev/null
+++ b/arch/mips/gt64120/momenco_ocelot/int-handler.S
@@ -0,0 +1,131 @@
+/*
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: jsun@mvista.com or jsun@junsun.net
+ *
+ * First-level interrupt dispatcher for ocelot board.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+#include <asm/asm.h>
+#include <asm/mipsregs.h>
+#include <asm/addrspace.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+
+/*
+ * first level interrupt dispatcher for ocelot board -
+ * We check for the timer first, then check PCI ints A and D.
+ * Then check for serial IRQ and fall through.
+ */
+ .align 5
+ NESTED(ocelot_handle_int, PT_SIZE, sp)
+ SAVE_ALL
+ CLI
+ .set at
+ mfc0 t0, CP0_CAUSE
+ mfc0 t2, CP0_STATUS
+
+ and t0, t2
+
+ andi t1, t0, STATUSF_IP2 /* int0 hardware line */
+ bnez t1, ll_pri_enet_irq
+ andi t1, t0, STATUSF_IP3 /* int1 hardware line */
+ bnez t1, ll_sec_enet_irq
+ andi t1, t0, STATUSF_IP4 /* int2 hardware line */
+ bnez t1, ll_uart1_irq
+ andi t1, t0, STATUSF_IP5 /* int3 hardware line */
+ bnez t1, ll_cpci_irq
+ andi t1, t0, STATUSF_IP6 /* int4 hardware line */
+ bnez t1, ll_galileo_irq
+ andi t1, t0, STATUSF_IP7 /* cpu timer */
+ bnez t1, ll_cputimer_irq
+
+ /* now look at the extended interrupts */
+ mfc0 t0, CP0_CAUSE
+ cfc0 t1, CP0_S1_INTCONTROL
+
+ /* shift the mask 8 bits left to line up the bits */
+ sll t2, t1, 8
+
+ and t0, t2
+ srl t0, t0, 16
+
+ andi t1, t0, STATUSF_IP8 /* int6 hardware line */
+ bnez t1, ll_pmc1_irq
+ andi t1, t0, STATUSF_IP9 /* int7 hardware line */
+ bnez t1, ll_pmc2_irq
+ andi t1, t0, STATUSF_IP10 /* int8 hardware line */
+ bnez t1, ll_cpci_abcd_irq
+ andi t1, t0, STATUSF_IP11 /* int9 hardware line */
+ bnez t1, ll_uart2_irq
+
+ .set reorder
+
+ /* wrong alarm or masked ... */
+ j spurious_interrupt
+ nop
+ END(ocelot_handle_int)
+
+ .align 5
+ll_pri_enet_irq:
+ li a0, 2
+ move a1, sp
+ jal do_IRQ
+ j ret_from_irq
+
+ll_sec_enet_irq:
+ li a0, 3
+ move a1, sp
+ jal do_IRQ
+ j ret_from_irq
+
+ll_uart1_irq:
+ li a0, 4
+ move a1, sp
+ jal do_IRQ
+ j ret_from_irq
+
+ll_cpci_irq:
+ li a0, 5
+ move a1, sp
+ jal do_IRQ
+ j ret_from_irq
+
+ll_galileo_irq:
+ li a0, 6
+ move a1, sp
+ jal do_IRQ
+ j ret_from_irq
+
+ll_cputimer_irq:
+ li a0, 7
+ move a1, sp
+ jal do_IRQ
+ j ret_from_irq
+
+ll_pmc1_irq:
+ li a0, 8
+ move a1, sp
+ jal do_IRQ
+ j ret_from_irq
+
+ll_pmc2_irq:
+ li a0, 9
+ move a1, sp
+ jal do_IRQ
+ j ret_from_irq
+
+ll_cpci_abcd_irq:
+ li a0, 10
+ move a1, sp
+ jal do_IRQ
+ j ret_from_irq
+
+ll_uart2_irq:
+ li a0, 11
+ move a1, sp
+ jal do_IRQ
+ j ret_from_irq
diff --git a/arch/mips/gt64120/momenco_ocelot/irq.c b/arch/mips/gt64120/momenco_ocelot/irq.c
new file mode 100644
index 0000000..4f108da
--- /dev/null
+++ b/arch/mips/gt64120/momenco_ocelot/irq.c
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2000 RidgeRun, Inc.
+ * Author: RidgeRun, Inc.
+ * glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
+ * Copyright (C) 2000, 2001, 2003 Ralf Baechle (ralf@gnu.org)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel_stat.h>
+#include <linux/module.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/timex.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+#include <linux/bitops.h>
+#include <asm/bootinfo.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/irq_cpu.h>
+#include <asm/mipsregs.h>
+#include <asm/system.h>
+
+extern asmlinkage void ocelot_handle_int(void);
+
+void __init arch_init_irq(void)
+{
+ /*
+ * Clear all of the interrupts while we change the able around a bit.
+ * int-handler is not on bootstrap
+ */
+ clear_c0_status(ST0_IM);
+ local_irq_disable();
+
+ /* Sets the first-level interrupt dispatcher. */
+ set_except_vector(0, ocelot_handle_int);
+
+ mips_cpu_irq_init(0);
+ rm7k_cpu_irq_init(8);
+}
diff --git a/arch/mips/gt64120/momenco_ocelot/ocelot_pld.h b/arch/mips/gt64120/momenco_ocelot/ocelot_pld.h
new file mode 100644
index 0000000..11f02c4
--- /dev/null
+++ b/arch/mips/gt64120/momenco_ocelot/ocelot_pld.h
@@ -0,0 +1,30 @@
+/*
+ * Ocelot Board Register Definitions
+ *
+ * (C) 2001 Red Hat, Inc.
+ *
+ * GPL'd
+ */
+#ifndef __MOMENCO_OCELOT_PLD_H__
+#define __MOMENCO_OCELOT_PLD_H__
+
+#define OCELOT_CS0_ADDR (0xe0020000)
+
+#define OCELOT_REG_BOARDREV (0)
+#define OCELOT_REG_PLD1_ID (1)
+#define OCELOT_REG_PLD2_ID (2)
+#define OCELOT_REG_RESET_STATUS (3)
+#define OCELOT_REG_BOARD_STATUS (4)
+#define OCELOT_REG_CPCI_ID (5)
+#define OCELOT_REG_I2C_CTRL (8)
+#define OCELOT_REG_EEPROM_MODE (9)
+#define OCELOT_REG_INTMASK (10)
+#define OCELOT_REG_INTSTATUS (11)
+#define OCELOT_REG_INTSET (12)
+#define OCELOT_REG_INTCLR (13)
+
+#define OCELOT_PLD_WRITE(x, y) writeb(x, OCELOT_CS0_ADDR + OCELOT_REG_##y)
+#define OCELOT_PLD_READ(x) readb(OCELOT_CS0_ADDR + OCELOT_REG_##x)
+
+
+#endif /* __MOMENCO_OCELOT_PLD_H__ */
diff --git a/arch/mips/gt64120/momenco_ocelot/prom.c b/arch/mips/gt64120/momenco_ocelot/prom.c
new file mode 100644
index 0000000..8677b6d
--- /dev/null
+++ b/arch/mips/gt64120/momenco_ocelot/prom.c
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: jsun@mvista.com or jsun@junsun.net
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/bootmem.h>
+
+#include <asm/addrspace.h>
+#include <asm/bootinfo.h>
+#include <asm/pmon.h>
+
+struct callvectors* debug_vectors;
+
+extern unsigned long gt64120_base;
+
+const char *get_system_type(void)
+{
+ return "Momentum Ocelot";
+}
+
+/* [jsun@junsun.net] PMON passes arguments in C main() style */
+void __init prom_init(void)
+{
+ int argc = fw_arg0;
+ char **arg = (char **) fw_arg1;
+ char **env = (char **) fw_arg2;
+ struct callvectors *cv = (struct callvectors *) fw_arg3;
+ uint32_t tmp;
+ int i;
+
+ /* save the PROM vectors for debugging use */
+ debug_vectors = cv;
+
+ /* arg[0] is "g", the rest is boot parameters */
+ arcs_cmdline[0] = '\0';
+ for (i = 1; i < argc; i++) {
+ if (strlen(arcs_cmdline) + strlen(arg[i] + 1)
+ >= sizeof(arcs_cmdline))
+ break;
+ strcat(arcs_cmdline, arg[i]);
+ strcat(arcs_cmdline, " ");
+ }
+
+ mips_machgroup = MACH_GROUP_MOMENCO;
+ mips_machtype = MACH_MOMENCO_OCELOT;
+
+ while (*env) {
+ if (strncmp("gtbase", *env, 6) == 0) {
+ gt64120_base = simple_strtol(*env + strlen("gtbase="),
+ NULL, 16);
+ break;
+ }
+ *env++;
+ }
+
+ debug_vectors->printf("Booting Linux kernel...\n");
+
+ /* All the boards have at least 64MiB. If there's more, we
+ detect and register it later */
+ add_memory_region(0, 64 << 20, BOOT_MEM_RAM);
+}
+
+unsigned long __init prom_free_prom_memory(void)
+{
+ return 0;
+}
diff --git a/arch/mips/gt64120/momenco_ocelot/reset.c b/arch/mips/gt64120/momenco_ocelot/reset.c
new file mode 100644
index 0000000..3fd499a
--- /dev/null
+++ b/arch/mips/gt64120/momenco_ocelot/reset.c
@@ -0,0 +1,47 @@
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * Copyright (C) 1997, 2001 Ralf Baechle
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: jsun@mvista.com or jsun@junsun.net
+ */
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/reboot.h>
+#include <asm/system.h>
+#include <linux/delay.h>
+
+void momenco_ocelot_restart(char *command)
+{
+ void *nvram = ioremap_nocache(0x2c807000, 0x1000);
+
+ if (!nvram) {
+ printk(KERN_NOTICE "ioremap of reset register failed\n");
+ return;
+ }
+ writeb(0x84, nvram + 0xff7); /* Ask the NVRAM/RTC/watchdog chip to
+ assert reset in 1/16 second */
+ mdelay(10+(1000/16));
+ iounmap(nvram);
+ printk(KERN_NOTICE "Watchdog reset failed\n");
+}
+
+void momenco_ocelot_halt(void)
+{
+ printk(KERN_NOTICE "\n** You can safely turn off the power\n");
+ while (1)
+ __asm__(".set\tmips3\n\t"
+ "wait\n\t"
+ ".set\tmips0");
+}
+
+void momenco_ocelot_power_off(void)
+{
+ momenco_ocelot_halt();
+}
diff --git a/arch/mips/gt64120/momenco_ocelot/setup.c b/arch/mips/gt64120/momenco_ocelot/setup.c
new file mode 100644
index 0000000..d610f8c
--- /dev/null
+++ b/arch/mips/gt64120/momenco_ocelot/setup.c
@@ -0,0 +1,369 @@
+/*
+ * setup.c
+ *
+ * BRIEF MODULE DESCRIPTION
+ * Momentum Computer Ocelot (CP7000) - board dependent boot routines
+ *
+ * Copyright (C) 1996, 1997, 2001 Ralf Baechle
+ * Copyright (C) 2000 RidgeRun, Inc.
+ * Copyright (C) 2001 Red Hat, Inc.
+ * Copyright (C) 2002 Momentum Computer
+ *
+ * Author: RidgeRun, Inc.
+ * glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: jsun@mvista.com or jsun@junsun.net
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/swap.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/timex.h>
+#include <linux/vmalloc.h>
+#include <asm/time.h>
+#include <asm/bootinfo.h>
+#include <asm/page.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/pci.h>
+#include <asm/processor.h>
+#include <asm/ptrace.h>
+#include <asm/reboot.h>
+#include <asm/traps.h>
+#include <linux/bootmem.h>
+#include <linux/initrd.h>
+#include <asm/gt64120.h>
+#include "ocelot_pld.h"
+
+unsigned long gt64120_base = KSEG1ADDR(GT_DEF_BASE);
+
+/* These functions are used for rebooting or halting the machine*/
+extern void momenco_ocelot_restart(char *command);
+extern void momenco_ocelot_halt(void);
+extern void momenco_ocelot_power_off(void);
+
+extern void gt64120_time_init(void);
+extern void momenco_ocelot_irq_setup(void);
+
+static char reset_reason;
+
+#define ENTRYLO(x) ((pte_val(pfn_pte((x) >> PAGE_SHIFT, PAGE_KERNEL_UNCACHED)) >> 6)|1)
+
+static void __init setup_l3cache(unsigned long size);
+
+/* setup code for a handoff from a version 1 PMON 2000 PROM */
+void PMON_v1_setup()
+{
+ /* A wired TLB entry for the GT64120A and the serial port. The
+ GT64120A is going to be hit on every IRQ anyway - there's
+ absolutely no point in letting it be a random TLB entry, as
+ it'll just cause needless churning of the TLB. And we use
+ the other half for the serial port, which is just a PITA
+ otherwise :)
+
+ Device Physical Virtual
+ GT64120 Internal Regs 0x24000000 0xe0000000
+ UARTs (CS2) 0x2d000000 0xe0001000
+ */
+ add_wired_entry(ENTRYLO(0x24000000), ENTRYLO(0x2D000000), 0xe0000000, PM_4K);
+
+ /* Also a temporary entry to let us talk to the Ocelot PLD and NVRAM
+ in the CS[012] region. We can't use ioremap() yet. The NVRAM
+ is a ST M48T37Y, which includes NVRAM, RTC, and Watchdog functions.
+
+ Ocelot PLD (CS0) 0x2c000000 0xe0020000
+ NVRAM 0x2c800000 0xe0030000
+ */
+
+ add_temporary_entry(ENTRYLO(0x2C000000), ENTRYLO(0x2d000000), 0xe0020000, PM_64K);
+
+ /* Relocate the CS3/BootCS region */
+ GT_WRITE(GT_CS3BOOTLD_OFS, 0x2f000000 >> 21);
+
+ /* Relocate CS[012] */
+ GT_WRITE(GT_CS20LD_OFS, 0x2c000000 >> 21);
+
+ /* Relocate the GT64120A itself... */
+ GT_WRITE(GT_ISD_OFS, 0x24000000 >> 21);
+ mb();
+ gt64120_base = 0xe0000000;
+
+ /* ...and the PCI0 view of it. */
+ GT_WRITE(GT_PCI0_CFGADDR_OFS, 0x80000020);
+ GT_WRITE(GT_PCI0_CFGDATA_OFS, 0x24000000);
+ GT_WRITE(GT_PCI0_CFGADDR_OFS, 0x80000024);
+ GT_WRITE(GT_PCI0_CFGDATA_OFS, 0x24000001);
+}
+
+/* setup code for a handoff from a version 2 PMON 2000 PROM */
+void PMON_v2_setup()
+{
+ /* A wired TLB entry for the GT64120A and the serial port. The
+ GT64120A is going to be hit on every IRQ anyway - there's
+ absolutely no point in letting it be a random TLB entry, as
+ it'll just cause needless churning of the TLB. And we use
+ the other half for the serial port, which is just a PITA
+ otherwise :)
+
+ Device Physical Virtual
+ GT64120 Internal Regs 0xf4000000 0xe0000000
+ UARTs (CS2) 0xfd000000 0xe0001000
+ */
+ add_wired_entry(ENTRYLO(0xf4000000), ENTRYLO(0xfD000000), 0xe0000000, PM_4K);
+
+ /* Also a temporary entry to let us talk to the Ocelot PLD and NVRAM
+ in the CS[012] region. We can't use ioremap() yet. The NVRAM
+ is a ST M48T37Y, which includes NVRAM, RTC, and Watchdog functions.
+
+ Ocelot PLD (CS0) 0xfc000000 0xe0020000
+ NVRAM 0xfc800000 0xe0030000
+ */
+ add_temporary_entry(ENTRYLO(0xfC000000), ENTRYLO(0xfd000000), 0xe0020000, PM_64K);
+
+ gt64120_base = 0xe0000000;
+}
+
+static void __init momenco_ocelot_setup(void)
+{
+ void (*l3func)(unsigned long)=KSEG1ADDR(&setup_l3cache);
+ unsigned int tmpword;
+
+ board_time_init = gt64120_time_init;
+
+ _machine_restart = momenco_ocelot_restart;
+ _machine_halt = momenco_ocelot_halt;
+ _machine_power_off = momenco_ocelot_power_off;
+
+ /*
+ * initrd_start = (ulong)ocelot_initrd_start;
+ * initrd_end = (ulong)ocelot_initrd_start + (ulong)ocelot_initrd_size;
+ * initrd_below_start_ok = 1;
+ */
+
+ /* do handoff reconfiguration */
+ if (gt64120_base == KSEG1ADDR(GT_DEF_BASE))
+ PMON_v1_setup();
+ else
+ PMON_v2_setup();
+
+ /* Turn off the Bit-Error LED */
+ OCELOT_PLD_WRITE(0x80, INTCLR);
+
+ /* Relocate all the PCI1 stuff, not that we use it */
+ GT_WRITE(GT_PCI1IOLD_OFS, 0x30000000 >> 21);
+ GT_WRITE(GT_PCI1M0LD_OFS, 0x32000000 >> 21);
+ GT_WRITE(GT_PCI1M1LD_OFS, 0x34000000 >> 21);
+
+ /* Relocate PCI0 I/O and Mem0 */
+ GT_WRITE(GT_PCI0IOLD_OFS, 0x20000000 >> 21);
+ GT_WRITE(GT_PCI0M0LD_OFS, 0x22000000 >> 21);
+
+ /* Relocate PCI0 Mem1 */
+ GT_WRITE(GT_PCI0M1LD_OFS, 0x36000000 >> 21);
+
+ /* For the initial programming, we assume 512MB configuration */
+ /* Relocate the CPU's view of the RAM... */
+ GT_WRITE(GT_SCS10LD_OFS, 0);
+ GT_WRITE(GT_SCS10HD_OFS, 0x0fe00000 >> 21);
+ GT_WRITE(GT_SCS32LD_OFS, 0x10000000 >> 21);
+ GT_WRITE(GT_SCS32HD_OFS, 0x0fe00000 >> 21);
+
+ GT_WRITE(GT_SCS1LD_OFS, 0xff);
+ GT_WRITE(GT_SCS1HD_OFS, 0x00);
+ GT_WRITE(GT_SCS0LD_OFS, 0);
+ GT_WRITE(GT_SCS0HD_OFS, 0xff);
+ GT_WRITE(GT_SCS3LD_OFS, 0xff);
+ GT_WRITE(GT_SCS3HD_OFS, 0x00);
+ GT_WRITE(GT_SCS2LD_OFS, 0);
+ GT_WRITE(GT_SCS2HD_OFS, 0xff);
+
+ /* ...and the PCI0 view of it. */
+ GT_WRITE(GT_PCI0_CFGADDR_OFS, 0x80000010);
+ GT_WRITE(GT_PCI0_CFGDATA_OFS, 0x00000000);
+ GT_WRITE(GT_PCI0_CFGADDR_OFS, 0x80000014);
+ GT_WRITE(GT_PCI0_CFGDATA_OFS, 0x10000000);
+ GT_WRITE(GT_PCI0_BS_SCS10_OFS, 0x0ffff000);
+ GT_WRITE(GT_PCI0_BS_SCS32_OFS, 0x0ffff000);
+
+ tmpword = OCELOT_PLD_READ(BOARDREV);
+ if (tmpword < 26)
+ printk("Momenco Ocelot: Board Assembly Rev. %c\n", 'A'+tmpword);
+ else
+ printk("Momenco Ocelot: Board Assembly Revision #0x%x\n", tmpword);
+
+ tmpword = OCELOT_PLD_READ(PLD1_ID);
+ printk("PLD 1 ID: %d.%d\n", tmpword>>4, tmpword&15);
+ tmpword = OCELOT_PLD_READ(PLD2_ID);
+ printk("PLD 2 ID: %d.%d\n", tmpword>>4, tmpword&15);
+ tmpword = OCELOT_PLD_READ(RESET_STATUS);
+ printk("Reset reason: 0x%x\n", tmpword);
+ reset_reason = tmpword;
+ OCELOT_PLD_WRITE(0xff, RESET_STATUS);
+
+ tmpword = OCELOT_PLD_READ(BOARD_STATUS);
+ printk("Board Status register: 0x%02x\n", tmpword);
+ printk(" - User jumper: %s\n", (tmpword & 0x80)?"installed":"absent");
+ printk(" - Boot flash write jumper: %s\n", (tmpword&0x40)?"installed":"absent");
+ printk(" - Tulip PHY %s connected\n", (tmpword&0x10)?"is":"not");
+ printk(" - L3 Cache size: %d MiB\n", (1<<((tmpword&12) >> 2))&~1);
+ printk(" - SDRAM size: %d MiB\n", 1<<(6+(tmpword&3)));
+
+ if (tmpword&12)
+ l3func((1<<(((tmpword&12) >> 2)+20)));
+
+ switch(tmpword &3) {
+ case 3:
+ /* 512MiB */
+ /* Decoders are allready set -- just add the
+ * appropriate region */
+ add_memory_region( 0x40<<20, 0xC0<<20, BOOT_MEM_RAM);
+ add_memory_region(0x100<<20, 0x100<<20, BOOT_MEM_RAM);
+ break;
+ case 2:
+ /* 256MiB -- two banks of 128MiB */
+ GT_WRITE(GT_SCS10HD_OFS, 0x07e00000 >> 21);
+ GT_WRITE(GT_SCS32LD_OFS, 0x08000000 >> 21);
+ GT_WRITE(GT_SCS32HD_OFS, 0x0fe00000 >> 21);
+
+ GT_WRITE(GT_SCS0HD_OFS, 0x7f);
+ GT_WRITE(GT_SCS2LD_OFS, 0x80);
+ GT_WRITE(GT_SCS2HD_OFS, 0xff);
+
+ /* reconfigure the PCI0 interface view of memory */
+ GT_WRITE(GT_PCI0_CFGADDR_OFS, 0x80000014);
+ GT_WRITE(GT_PCI0_CFGDATA_OFS, 0x08000000);
+ GT_WRITE(GT_PCI0_BS_SCS10_OFS, 0x0ffff000);
+ GT_WRITE(GT_PCI0_BS_SCS32_OFS, 0x0ffff000);
+
+ add_memory_region(0x40<<20, 0x40<<20, BOOT_MEM_RAM);
+ add_memory_region(0x80<<20, 0x80<<20, BOOT_MEM_RAM);
+ break;
+ case 1:
+ /* 128MiB -- 64MiB per bank */
+ GT_WRITE(GT_SCS10HD_OFS, 0x03e00000 >> 21);
+ GT_WRITE(GT_SCS32LD_OFS, 0x04000000 >> 21);
+ GT_WRITE(GT_SCS32HD_OFS, 0x07e00000 >> 21);
+
+ GT_WRITE(GT_SCS0HD_OFS, 0x3f);
+ GT_WRITE(GT_SCS2LD_OFS, 0x40);
+ GT_WRITE(GT_SCS2HD_OFS, 0x7f);
+
+ /* reconfigure the PCI0 interface view of memory */
+ GT_WRITE(GT_PCI0_CFGADDR_OFS, 0x80000014);
+ GT_WRITE(GT_PCI0_CFGDATA_OFS, 0x04000000);
+ GT_WRITE(GT_PCI0_BS_SCS10_OFS, 0x03fff000);
+ GT_WRITE(GT_PCI0_BS_SCS32_OFS, 0x03fff000);
+
+ /* add the appropriate region */
+ add_memory_region(0x40<<20, 0x40<<20, BOOT_MEM_RAM);
+ break;
+ case 0:
+ /* 64MiB */
+ GT_WRITE(GT_SCS10HD_OFS, 0x01e00000 >> 21);
+ GT_WRITE(GT_SCS32LD_OFS, 0x02000000 >> 21);
+ GT_WRITE(GT_SCS32HD_OFS, 0x03e00000 >> 21);
+
+ GT_WRITE(GT_SCS0HD_OFS, 0x1f);
+ GT_WRITE(GT_SCS2LD_OFS, 0x20);
+ GT_WRITE(GT_SCS2HD_OFS, 0x3f);
+
+ /* reconfigure the PCI0 interface view of memory */
+ GT_WRITE(GT_PCI0_CFGADDR_OFS, 0x80000014);
+ GT_WRITE(GT_PCI0_CFGDATA_OFS, 0x04000000);
+ GT_WRITE(GT_PCI0_BS_SCS10_OFS, 0x01fff000);
+ GT_WRITE(GT_PCI0_BS_SCS32_OFS, 0x01fff000);
+
+ break;
+ }
+
+ /* Fix up the DiskOnChip mapping */
+ GT_WRITE(GT_DEV_B3_OFS, 0xfef73);
+}
+
+early_initcall(momenco_ocelot_setup);
+
+extern int rm7k_tcache_enabled;
+/*
+ * This runs in KSEG1. See the verbiage in rm7k.c::probe_scache()
+ */
+#define Page_Invalidate_T 0x16
+static void __init setup_l3cache(unsigned long size)
+{
+ int register i;
+ unsigned long tmp;
+
+ printk("Enabling L3 cache...");
+
+ /* Enable the L3 cache in the GT64120A's CPU Configuration register */
+ tmp = GT_READ(GT_CPU_OFS);
+ GT_WRITE(GT_CPU_OFS, tmp | (1<<14));
+
+ /* Enable the L3 cache in the CPU */
+ set_c0_config(1<<12 /* CONF_TE */);
+
+ /* Clear the cache */
+ write_c0_taglo(0);
+ write_c0_taghi(0);
+
+ for (i=0; i < size; i+= 4096) {
+ __asm__ __volatile__ (
+ ".set noreorder\n\t"
+ ".set mips3\n\t"
+ "cache %1, (%0)\n\t"
+ ".set mips0\n\t"
+ ".set reorder"
+ :
+ : "r" (KSEG0ADDR(i)),
+ "i" (Page_Invalidate_T));
+ }
+
+ /* Let the RM7000 MM code know that the tertiary cache is enabled */
+ rm7k_tcache_enabled = 1;
+
+ printk("Done\n");
+}
+
+
+/* This needs to be one of the first initcalls, because no I/O port access
+ can work before this */
+
+static int io_base_ioremap(void)
+{
+ void *io_remap_range = ioremap(GT_PCI_IO_BASE, GT_PCI_IO_SIZE);
+
+ if (!io_remap_range) {
+ panic("Could not ioremap I/O port range");
+ }
+ set_io_port_base(io_remap_range - GT_PCI_IO_BASE);
+
+ return 0;
+}
+
+module_init(io_base_ioremap);
diff --git a/arch/mips/ite-boards/generic/Makefile b/arch/mips/ite-boards/generic/Makefile
new file mode 100644
index 0000000..0e7853f
--- /dev/null
+++ b/arch/mips/ite-boards/generic/Makefile
@@ -0,0 +1,15 @@
+#
+# Copyright 2000 MontaVista Software Inc.
+# Author: MontaVista Software, Inc.
+# ppopov@mvista.com or source@mvista.com
+#
+# Makefile for the ITE 8172 (qed-4n-s01b) board, generic files.
+#
+
+obj-y += it8172_setup.o irq.o int-handler.o pmon_prom.o \
+ time.o lpc.o puts.o reset.o
+
+obj-$(CONFIG_IT8172_CIR)+= it8172_cir.o
+obj-$(CONFIG_KGDB) += dbg_io.o
+
+EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/ite-boards/generic/dbg_io.c b/arch/mips/ite-boards/generic/dbg_io.c
new file mode 100644
index 0000000..c4f8530
--- /dev/null
+++ b/arch/mips/ite-boards/generic/dbg_io.c
@@ -0,0 +1,125 @@
+
+#include <linux/config.h>
+
+#ifdef CONFIG_KGDB
+
+/* --- CONFIG --- */
+
+/* we need uint32 uint8 */
+/* #include "types.h" */
+typedef unsigned char uint8;
+typedef unsigned int uint32;
+
+/* --- END OF CONFIG --- */
+
+#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
+
+/* ----------------------------------------------------- */
+
+/* === CONFIG === */
+
+/* [stevel] we use the IT8712 serial port for kgdb */
+#define DEBUG_BASE 0xB40003F8 /* 8712 serial port 1 base address */
+#define MAX_BAUD 115200
+
+/* === END OF CONFIG === */
+
+/* register offset */
+#define OFS_RCV_BUFFER 0
+#define OFS_TRANS_HOLD 0
+#define OFS_SEND_BUFFER 0
+#define OFS_INTR_ENABLE 1
+#define OFS_INTR_ID 2
+#define OFS_DATA_FORMAT 3
+#define OFS_LINE_CONTROL 3
+#define OFS_MODEM_CONTROL 4
+#define OFS_RS232_OUTPUT 4
+#define OFS_LINE_STATUS 5
+#define OFS_MODEM_STATUS 6
+#define OFS_RS232_INPUT 6
+#define OFS_SCRATCH_PAD 7
+
+#define OFS_DIVISOR_LSB 0
+#define OFS_DIVISOR_MSB 1
+
+
+/* memory-mapped read/write of the port */
+#define UART16550_READ(y) (*((volatile uint8*)(DEBUG_BASE + y)))
+#define UART16550_WRITE(y,z) ((*((volatile uint8*)(DEBUG_BASE + y))) = z)
+
+void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop)
+{
+ /* disable interrupts */
+ UART16550_WRITE(OFS_INTR_ENABLE, 0);
+
+ /* set up buad rate */
+ {
+ uint32 divisor;
+
+ /* set DIAB bit */
+ UART16550_WRITE(OFS_LINE_CONTROL, 0x80);
+
+ /* set divisor */
+ divisor = MAX_BAUD / baud;
+ UART16550_WRITE(OFS_DIVISOR_LSB, divisor & 0xff);
+ UART16550_WRITE(OFS_DIVISOR_MSB, (divisor & 0xff00) >> 8);
+
+ /* clear DIAB bit */
+ UART16550_WRITE(OFS_LINE_CONTROL, 0x0);
+ }
+
+ /* set data format */
+ UART16550_WRITE(OFS_DATA_FORMAT, data | parity | stop);
+}
+
+static int remoteDebugInitialized = 0;
+
+uint8 getDebugChar(void)
+{
+ if (!remoteDebugInitialized) {
+ remoteDebugInitialized = 1;
+ debugInit(UART16550_BAUD_115200,
+ UART16550_DATA_8BIT,
+ UART16550_PARITY_NONE, UART16550_STOP_1BIT);
+ }
+
+ while ((UART16550_READ(OFS_LINE_STATUS) & 0x1) == 0);
+ return UART16550_READ(OFS_RCV_BUFFER);
+}
+
+
+int putDebugChar(uint8 byte)
+{
+ if (!remoteDebugInitialized) {
+ remoteDebugInitialized = 1;
+ debugInit(UART16550_BAUD_115200,
+ UART16550_DATA_8BIT,
+ UART16550_PARITY_NONE, UART16550_STOP_1BIT);
+ }
+
+ while ((UART16550_READ(OFS_LINE_STATUS) & 0x20) == 0);
+ UART16550_WRITE(OFS_SEND_BUFFER, byte);
+ return 1;
+}
+
+#endif
diff --git a/arch/mips/ite-boards/generic/int-handler.S b/arch/mips/ite-boards/generic/int-handler.S
new file mode 100644
index 0000000..d190d8a
--- /dev/null
+++ b/arch/mips/ite-boards/generic/int-handler.S
@@ -0,0 +1,63 @@
+#include <asm/asm.h>
+#include <asm/mipsregs.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+
+ .text
+ .set macro
+ .set noat
+ .align 5
+
+NESTED(it8172_IRQ, PT_SIZE, sp)
+ SAVE_ALL
+ CLI # Important: mark KERNEL mode !
+
+ /* We're working with 'reorder' set at this point. */
+ /*
+ * Get pending interrupts
+ */
+
+ mfc0 t0,CP0_CAUSE # get pending interrupts
+ mfc0 t1,CP0_STATUS # get enabled interrupts
+ and t0,t1 # isolate allowed ones
+
+ andi t0,0xff00 # isolate pending bits
+ beqz t0, 3f # spurious interrupt
+
+ andi a0, t0, CAUSEF_IP7
+ beq a0, zero, 1f
+
+ li a0, 127 # MIPS_CPU_TIMER_IRQ = (NR_IRQS-1)
+ move a1, sp
+ jal ll_timer_interrupt
+ j ret_from_irq
+ nop
+
+1:
+ andi a0, t0, CAUSEF_IP2 # the only int we expect at this time
+ beq a0, zero, 3f
+ move a0,sp
+ jal it8172_hw0_irqdispatch
+
+ mfc0 t0,CP0_STATUS # disable interrupts
+ ori t0,1
+ xori t0,1
+ mtc0 t0,CP0_STATUS
+ nop
+ nop
+ nop
+
+ la a1, ret_from_irq
+ jr a1
+ nop
+
+3:
+ move a0, sp
+ jal mips_spurious_interrupt
+ nop
+ la a1, ret_from_irq
+ jr a1
+ nop
+
+END(it8172_IRQ)
+
diff --git a/arch/mips/ite-boards/generic/irq.c b/arch/mips/ite-boards/generic/irq.c
new file mode 100644
index 0000000..cb71b90
--- /dev/null
+++ b/arch/mips/ite-boards/generic/irq.c
@@ -0,0 +1,304 @@
+/*
+ * BRIEF MODULE DESCRIPTION
+ * ITE 8172G interrupt/setup routines.
+ *
+ * Copyright 2000,2001 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ * ppopov@mvista.com or source@mvista.com
+ *
+ * Part of this file was derived from Carsten Langgaard's
+ * arch/mips/mips-boards/atlas/atlas_int.c.
+ *
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/kernel_stat.h>
+#include <linux/module.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/timex.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+#include <linux/serial_reg.h>
+#include <linux/bitops.h>
+
+#include <asm/bootinfo.h>
+#include <asm/io.h>
+#include <asm/mipsregs.h>
+#include <asm/system.h>
+#include <asm/it8172/it8172.h>
+#include <asm/it8172/it8172_int.h>
+#include <asm/it8172/it8172_dbg.h>
+
+/* revisit */
+#define EXT_IRQ0_TO_IP 2 /* IP 2 */
+#define EXT_IRQ5_TO_IP 7 /* IP 7 */
+
+#define ALLINTS_NOTIMER (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4)
+
+void disable_it8172_irq(unsigned int irq_nr);
+void enable_it8172_irq(unsigned int irq_nr);
+
+extern void set_debug_traps(void);
+extern void mips_timer_interrupt(int irq, struct pt_regs *regs);
+extern asmlinkage void it8172_IRQ(void);
+
+struct it8172_intc_regs volatile *it8172_hw0_icregs =
+ (struct it8172_intc_regs volatile *)(KSEG1ADDR(IT8172_PCI_IO_BASE + IT_INTC_BASE));
+
+static void disable_it8172_irq(unsigned int irq_nr)
+{
+ if ( (irq_nr >= IT8172_LPC_IRQ_BASE) && (irq_nr <= IT8172_SERIRQ_15)) {
+ /* LPC interrupt */
+ it8172_hw0_icregs->lpc_mask |=
+ (1 << (irq_nr - IT8172_LPC_IRQ_BASE));
+ } else if ( (irq_nr >= IT8172_LB_IRQ_BASE) && (irq_nr <= IT8172_IOCHK_IRQ)) {
+ /* Local Bus interrupt */
+ it8172_hw0_icregs->lb_mask |=
+ (1 << (irq_nr - IT8172_LB_IRQ_BASE));
+ } else if ( (irq_nr >= IT8172_PCI_DEV_IRQ_BASE) && (irq_nr <= IT8172_DMA_IRQ)) {
+ /* PCI and other interrupts */
+ it8172_hw0_icregs->pci_mask |=
+ (1 << (irq_nr - IT8172_PCI_DEV_IRQ_BASE));
+ } else if ( (irq_nr >= IT8172_NMI_IRQ_BASE) && (irq_nr <= IT8172_POWER_NMI_IRQ)) {
+ /* NMI interrupts */
+ it8172_hw0_icregs->nmi_mask |=
+ (1 << (irq_nr - IT8172_NMI_IRQ_BASE));
+ } else {
+ panic("disable_it8172_irq: bad irq %d", irq_nr);
+ }
+}
+
+static void enable_it8172_irq(unsigned int irq_nr)
+{
+ if ( (irq_nr >= IT8172_LPC_IRQ_BASE) && (irq_nr <= IT8172_SERIRQ_15)) {
+ /* LPC interrupt */
+ it8172_hw0_icregs->lpc_mask &=
+ ~(1 << (irq_nr - IT8172_LPC_IRQ_BASE));
+ }
+ else if ( (irq_nr >= IT8172_LB_IRQ_BASE) && (irq_nr <= IT8172_IOCHK_IRQ)) {
+ /* Local Bus interrupt */
+ it8172_hw0_icregs->lb_mask &=
+ ~(1 << (irq_nr - IT8172_LB_IRQ_BASE));
+ }
+ else if ( (irq_nr >= IT8172_PCI_DEV_IRQ_BASE) && (irq_nr <= IT8172_DMA_IRQ)) {
+ /* PCI and other interrupts */
+ it8172_hw0_icregs->pci_mask &=
+ ~(1 << (irq_nr - IT8172_PCI_DEV_IRQ_BASE));
+ }
+ else if ( (irq_nr >= IT8172_NMI_IRQ_BASE) && (irq_nr <= IT8172_POWER_NMI_IRQ)) {
+ /* NMI interrupts */
+ it8172_hw0_icregs->nmi_mask &=
+ ~(1 << (irq_nr - IT8172_NMI_IRQ_BASE));
+ }
+ else {
+ panic("enable_it8172_irq: bad irq %d", irq_nr);
+ }
+}
+
+static unsigned int startup_ite_irq(unsigned int irq)
+{
+ enable_it8172_irq(irq);
+ return 0;
+}
+
+#define shutdown_ite_irq disable_it8172_irq
+#define mask_and_ack_ite_irq disable_it8172_irq
+
+static void end_ite_irq(unsigned int irq)
+{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+ enable_it8172_irq(irq);
+}
+
+static struct hw_interrupt_type it8172_irq_type = {
+ "ITE8172",
+ startup_ite_irq,
+ shutdown_ite_irq,
+ enable_it8172_irq,
+ disable_it8172_irq,
+ mask_and_ack_ite_irq,
+ end_ite_irq,
+ NULL
+};
+
+
+static void enable_none(unsigned int irq) { }
+static unsigned int startup_none(unsigned int irq) { return 0; }
+static void disable_none(unsigned int irq) { }
+static void ack_none(unsigned int irq) { }
+
+/* startup is the same as "enable", shutdown is same as "disable" */
+#define shutdown_none disable_none
+#define end_none enable_none
+
+static struct hw_interrupt_type cp0_irq_type = {
+ "CP0 Count",
+ startup_none,
+ shutdown_none,
+ enable_none,
+ disable_none,
+ ack_none,
+ end_none
+};
+
+void enable_cpu_timer(void)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+ set_c0_status(0x100 << EXT_IRQ5_TO_IP);
+ local_irq_restore(flags);
+}
+
+void __init arch_init_irq(void)
+{
+ int i;
+ unsigned long flags;
+
+ memset(irq_desc, 0, sizeof(irq_desc));
+ set_except_vector(0, it8172_IRQ);
+
+ /* mask all interrupts */
+ it8172_hw0_icregs->lb_mask = 0xffff;
+ it8172_hw0_icregs->lpc_mask = 0xffff;
+ it8172_hw0_icregs->pci_mask = 0xffff;
+ it8172_hw0_icregs->nmi_mask = 0xffff;
+
+ /* make all interrupts level triggered */
+ it8172_hw0_icregs->lb_trigger = 0;
+ it8172_hw0_icregs->lpc_trigger = 0;
+ it8172_hw0_icregs->pci_trigger = 0;
+ it8172_hw0_icregs->nmi_trigger = 0;
+
+ /* active level setting */
+ /* uart, keyboard, and mouse are active high */
+ it8172_hw0_icregs->lpc_level = (0x10 | 0x2 | 0x1000);
+ it8172_hw0_icregs->lb_level |= 0x20;
+
+ /* keyboard and mouse are edge triggered */
+ it8172_hw0_icregs->lpc_trigger |= (0x2 | 0x1000);
+
+
+#if 0
+ // Enable this piece of code to make internal USB interrupt
+ // edge triggered.
+ it8172_hw0_icregs->pci_trigger |=
+ (1 << (IT8172_USB_IRQ - IT8172_PCI_DEV_IRQ_BASE));
+ it8172_hw0_icregs->pci_level &=
+ ~(1 << (IT8172_USB_IRQ - IT8172_PCI_DEV_IRQ_BASE));
+#endif
+
+ for (i = 0; i <= IT8172_LAST_IRQ; i++) {
+ irq_desc[i].handler = &it8172_irq_type;
+ spin_lock_init(&irq_desc[i].lock);
+ }
+ irq_desc[MIPS_CPU_TIMER_IRQ].handler = &cp0_irq_type;
+ set_c0_status(ALLINTS_NOTIMER);
+}
+
+void mips_spurious_interrupt(struct pt_regs *regs)
+{
+#if 1
+ return;
+#else
+ unsigned long status, cause;
+
+ printk("got spurious interrupt\n");
+ status = read_c0_status();
+ cause = read_c0_cause();
+ printk("status %x cause %x\n", status, cause);
+ printk("epc %x badvaddr %x \n", regs->cp0_epc, regs->cp0_badvaddr);
+#endif
+}
+
+void it8172_hw0_irqdispatch(struct pt_regs *regs)
+{
+ int irq;
+ unsigned short intstatus = 0, status = 0;
+
+ intstatus = it8172_hw0_icregs->intstatus;
+ if (intstatus & 0x8) {
+ panic("Got NMI interrupt");
+ } else if (intstatus & 0x4) {
+ /* PCI interrupt */
+ irq = 0;
+ status |= it8172_hw0_icregs->pci_req;
+ while (!(status & 0x1)) {
+ irq++;
+ status >>= 1;
+ }
+ irq += IT8172_PCI_DEV_IRQ_BASE;
+ } else if (intstatus & 0x1) {
+ /* Local Bus interrupt */
+ irq = 0;
+ status |= it8172_hw0_icregs->lb_req;
+ while (!(status & 0x1)) {
+ irq++;
+ status >>= 1;
+ }
+ irq += IT8172_LB_IRQ_BASE;
+ } else if (intstatus & 0x2) {
+ /* LPC interrupt */
+ /* Since some lpc interrupts are edge triggered,
+ * we could lose an interrupt this way because
+ * we acknowledge all ints at onces. Revisit.
+ */
+ status |= it8172_hw0_icregs->lpc_req;
+ it8172_hw0_icregs->lpc_req = 0; /* acknowledge ints */
+ irq = 0;
+ while (!(status & 0x1)) {
+ irq++;
+ status >>= 1;
+ }
+ irq += IT8172_LPC_IRQ_BASE;
+ } else
+ return;
+
+ do_IRQ(irq, regs);
+}
+
+void show_pending_irqs(void)
+{
+ fputs("intstatus: ");
+ put32(it8172_hw0_icregs->intstatus);
+ puts("");
+
+ fputs("pci_req: ");
+ put32(it8172_hw0_icregs->pci_req);
+ puts("");
+
+ fputs("lb_req: ");
+ put32(it8172_hw0_icregs->lb_req);
+ puts("");
+
+ fputs("lpc_req: ");
+ put32(it8172_hw0_icregs->lpc_req);
+ puts("");
+}
diff --git a/arch/mips/ite-boards/generic/it8172_cir.c b/arch/mips/ite-boards/generic/it8172_cir.c
new file mode 100644
index 0000000..19deb15
--- /dev/null
+++ b/arch/mips/ite-boards/generic/it8172_cir.c
@@ -0,0 +1,171 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ * IT8172 Consumer IR port generic routines.
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ * ppopov@mvista.com or source@mvista.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/config.h>
+
+#ifdef CONFIG_IT8172_CIR
+
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/it8172/it8172.h>
+#include <asm/it8172/it8172_cir.h>
+
+
+volatile struct it8172_cir_regs *cir_regs[NUM_CIR_PORTS] = {
+ (volatile struct it8172_cir_regs *)(KSEG1ADDR(IT8172_PCI_IO_BASE + IT_CIR0_BASE)),
+ (volatile struct it8172_cir_regs *)(KSEG1ADDR(IT8172_PCI_IO_BASE + IT_CIR1_BASE))};
+
+
+/*
+ * Initialize Consumer IR Port.
+ */
+int cir_port_init(struct cir_port *cir)
+{
+ int port = cir->port;
+ unsigned char data;
+
+ /* set baud rate */
+ cir_regs[port]->bdlr = cir->baud_rate & 0xff;
+ cir_regs[port]->bdhr = (cir->baud_rate >> 8) & 0xff;
+
+ /* set receiver control register */
+ cir_regs[port]->rcr = (CIR_SET_RDWOS(cir->rdwos) | CIR_SET_RXDCR(cir->rxdcr));
+
+ /* set carrier frequency register */
+ cir_regs[port]->cfr = (CIR_SET_CF(cir->cfq) | CIR_SET_HS(cir->hcfs));
+
+ /* set fifo threshold */
+ data = cir_regs[port]->mstcr & 0xf3;
+ data |= CIR_SET_FIFO_TL(cir->fifo_tl);
+ cir_regs[port]->mstcr = data;
+
+ clear_fifo(cir);
+ enable_receiver(cir);
+ disable_rx_demodulation(cir);
+
+ set_rx_active(cir);
+ int_enable(cir);
+ rx_int_enable(cir);
+
+ return 0;
+}
+
+
+void clear_fifo(struct cir_port *cir)
+{
+ cir_regs[cir->port]->mstcr |= CIR_FIFO_CLEAR;
+}
+
+void enable_receiver(struct cir_port *cir)
+{
+ cir_regs[cir->port]->rcr |= CIR_RXEN;
+}
+
+void disable_receiver(struct cir_port *cir)
+{
+ cir_regs[cir->port]->rcr &= ~CIR_RXEN;
+}
+
+void enable_rx_demodulation(struct cir_port *cir)
+{
+ cir_regs[cir->port]->rcr |= CIR_RXEND;
+}
+
+void disable_rx_demodulation(struct cir_port *cir)
+{
+ cir_regs[cir->port]->rcr &= ~CIR_RXEND;
+}
+
+void set_rx_active(struct cir_port *cir)
+{
+ cir_regs[cir->port]->rcr |= CIR_RXACT;
+}
+
+void int_enable(struct cir_port *cir)
+{
+ cir_regs[cir->port]->ier |= CIR_IEC;
+}
+
+void rx_int_enable(struct cir_port *cir)
+{
+ cir_regs[cir->port]->ier |= CIR_RDAIE;
+}
+
+void dump_regs(struct cir_port *cir)
+{
+ printk("mstcr %x ier %x iir %x cfr %x rcr %x tcr %x tfsr %x rfsr %x\n",
+ cir_regs[cir->port]->mstcr,
+ cir_regs[cir->port]->ier,
+ cir_regs[cir->port]->iir,
+ cir_regs[cir->port]->cfr,
+ cir_regs[cir->port]->rcr,
+ cir_regs[cir->port]->tcr,
+ cir_regs[cir->port]->tfsr,
+ cir_regs[cir->port]->rfsr);
+
+ while (cir_regs[cir->port]->iir & CIR_RDAI) {
+ printk("data %x\n", cir_regs[cir->port]->dr);
+ }
+}
+
+void dump_reg_addr(struct cir_port *cir)
+{
+ printk("dr %x mstcr %x ier %x iir %x cfr %x rcr %x tcr %x bdlr %x bdhr %x tfsr %x rfsr %x\n",
+ (unsigned)&cir_regs[cir->port]->dr,
+ (unsigned)&cir_regs[cir->port]->mstcr,
+ (unsigned)&cir_regs[cir->port]->ier,
+ (unsigned)&cir_regs[cir->port]->iir,
+ (unsigned)&cir_regs[cir->port]->cfr,
+ (unsigned)&cir_regs[cir->port]->rcr,
+ (unsigned)&cir_regs[cir->port]->tcr,
+ (unsigned)&cir_regs[cir->port]->bdlr,
+ (unsigned)&cir_regs[cir->port]->bdhr,
+ (unsigned)&cir_regs[cir->port]->tfsr,
+ (unsigned)&cir_regs[cir->port]->rfsr);
+}
+
+int cir_get_rx_count(struct cir_port *cir)
+{
+ return cir_regs[cir->port]->rfsr & CIR_RXFBC_MASK;
+}
+
+char cir_read_data(struct cir_port *cir)
+{
+ return cir_regs[cir->port]->dr;
+}
+
+char get_int_status(struct cir_port *cir)
+{
+ return cir_regs[cir->port]->iir;
+}
+#endif
diff --git a/arch/mips/ite-boards/generic/it8172_setup.c b/arch/mips/ite-boards/generic/it8172_setup.c
new file mode 100644
index 0000000..d808a67
--- /dev/null
+++ b/arch/mips/ite-boards/generic/it8172_setup.c
@@ -0,0 +1,309 @@
+/*
+ * BRIEF MODULE DESCRIPTION
+ * IT8172/QED5231 board setup.
+ *
+ * Copyright 2000 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ * ppopov@mvista.com or source@mvista.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/serial_reg.h>
+#include <linux/major.h>
+#include <linux/kdev_t.h>
+#include <linux/root_dev.h>
+
+#include <asm/cpu.h>
+#include <asm/time.h>
+#include <asm/io.h>
+#include <asm/bootinfo.h>
+#include <asm/irq.h>
+#include <asm/mipsregs.h>
+#include <asm/reboot.h>
+#include <asm/traps.h>
+#include <asm/it8172/it8172.h>
+#include <asm/it8712.h>
+
+extern struct resource ioport_resource;
+#ifdef CONFIG_SERIO_I8042
+int init_8712_keyboard(void);
+#endif
+
+extern int SearchIT8712(void);
+extern void InitLPCInterface(void);
+extern char * __init prom_getcmdline(void);
+extern void it8172_restart(char *command);
+extern void it8172_halt(void);
+extern void it8172_power_off(void);
+
+extern void (*board_time_init)(void);
+extern void (*board_timer_setup)(struct irqaction *irq);
+extern void it8172_time_init(void);
+extern void it8172_timer_setup(struct irqaction *irq);
+
+#ifdef CONFIG_IT8172_REVC
+struct {
+ struct resource ram;
+ struct resource pci_mem;
+ struct resource pci_io;
+ struct resource flash;
+ struct resource boot;
+} it8172_resources = {
+ { "RAM", 0, 0, IORESOURCE_MEM }, /* to be initted */
+ { "PCI Mem", 0x10000000, 0x13FFFFFF, IORESOURCE_MEM },
+ { "PCI I/O", 0x14000000, 0x17FFFFFF },
+ { "Flash", 0x08000000, 0x0CFFFFFF },
+ { "Boot ROM", 0x1FC00000, 0x1FFFFFFF }
+};
+#else
+struct {
+ struct resource ram;
+ struct resource pci_mem0;
+ struct resource pci_mem1;
+ struct resource pci_io;
+ struct resource pci_mem2;
+ struct resource pci_mem3;
+ struct resource flash;
+ struct resource boot;
+} it8172_resources = {
+ { "RAM", 0, 0, IORESOURCE_MEM }, /* to be initted */
+ { "PCI Mem0", 0x0C000000, 0x0FFFFFFF, IORESOURCE_MEM },
+ { "PCI Mem1", 0x10000000, 0x13FFFFFF, IORESOURCE_MEM },
+ { "PCI I/O", 0x14000000, 0x17FFFFFF },
+ { "PCI Mem2", 0x1A000000, 0x1BFFFFFF, IORESOURCE_MEM },
+ { "PCI Mem3", 0x1C000000, 0x1FBFFFFF, IORESOURCE_MEM },
+ { "Flash", 0x08000000, 0x0CFFFFFF },
+ { "Boot ROM", 0x1FC00000, 0x1FFFFFFF }
+};
+#endif
+
+
+void __init it8172_init_ram_resource(unsigned long memsize)
+{
+ it8172_resources.ram.end = memsize;
+}
+
+static void __init it8172_setup(void)
+{
+ unsigned short dsr;
+ char *argptr;
+
+ argptr = prom_getcmdline();
+#ifdef CONFIG_SERIAL_CONSOLE
+ if ((argptr = strstr(argptr, "console=")) == NULL) {
+ argptr = prom_getcmdline();
+ strcat(argptr, " console=ttyS0,115200");
+ }
+#endif
+
+ clear_c0_status(ST0_FR);
+
+ board_time_init = it8172_time_init;
+ board_timer_setup = it8172_timer_setup;
+
+ _machine_restart = it8172_restart;
+ _machine_halt = it8172_halt;
+ _machine_power_off = it8172_power_off;
+
+ /*
+ * IO/MEM resources.
+ *
+ * revisit this area.
+ */
+ set_io_port_base(KSEG1);
+ ioport_resource.start = it8172_resources.pci_io.start;
+ ioport_resource.end = it8172_resources.pci_io.end;
+#ifdef CONFIG_IT8172_REVC
+ iomem_resource.start = it8172_resources.pci_mem.start;
+ iomem_resource.end = it8172_resources.pci_mem.end;
+#else
+ iomem_resource.start = it8172_resources.pci_mem0.start;
+ iomem_resource.end = it8172_resources.pci_mem3.end;
+#endif
+
+#ifdef CONFIG_BLK_DEV_INITRD
+ ROOT_DEV = Root_RAM0;
+#endif
+
+ /*
+ * Pull enabled devices out of standby
+ */
+ IT_IO_READ16(IT_PM_DSR, dsr);
+
+ /*
+ * Fixme: This breaks when these drivers are modules!!!
+ */
+#ifdef CONFIG_SOUND_IT8172
+ dsr &= ~IT_PM_DSR_ACSB;
+#else
+ dsr |= IT_PM_DSR_ACSB;
+#endif
+#ifdef CONFIG_BLK_DEV_IT8172
+ dsr &= ~IT_PM_DSR_IDESB;
+#else
+ dsr |= IT_PM_DSR_IDESB;
+#endif
+ IT_IO_WRITE16(IT_PM_DSR, dsr);
+
+ InitLPCInterface();
+
+#ifdef CONFIG_MIPS_ITE8172
+ if (SearchIT8712()) {
+ printk("Found IT8712 Super IO\n");
+ /* enable IT8712 serial port */
+ LPCSetConfig(LDN_SERIAL1, 0x30, 0x01); /* enable */
+ LPCSetConfig(LDN_SERIAL1, 0x23, 0x01); /* clock selection */
+#ifdef CONFIG_SERIO_I8042
+ if (init_8712_keyboard()) {
+ printk("Unable to initialize keyboard\n");
+ LPCSetConfig(LDN_KEYBOARD, 0x30, 0x0); /* disable keyboard */
+ } else {
+ LPCSetConfig(LDN_KEYBOARD, 0x30, 0x1); /* enable keyboard */
+ LPCSetConfig(LDN_KEYBOARD, 0xf0, 0x2);
+ LPCSetConfig(LDN_KEYBOARD, 0x71, 0x3);
+
+ LPCSetConfig(LDN_MOUSE, 0x30, 0x1); /* enable mouse */
+
+ LPCSetConfig(0x4, 0x30, 0x1);
+ LPCSetConfig(0x4, 0xf4, LPCGetConfig(0x4, 0xf4) | 0x80);
+
+ if ((LPCGetConfig(LDN_KEYBOARD, 0x30) == 0) ||
+ (LPCGetConfig(LDN_MOUSE, 0x30) == 0))
+ printk("Error: keyboard or mouse not enabled\n");
+
+ }
+#endif
+ }
+ else {
+ printk("IT8712 Super IO not found\n");
+ }
+#endif
+
+#ifdef CONFIG_IT8172_CIR
+ {
+ unsigned long data;
+ //printk("Enabling CIR0\n");
+ IT_IO_READ16(IT_PM_DSR, data);
+ data &= ~IT_PM_DSR_CIR0SB;
+ IT_IO_WRITE16(IT_PM_DSR, data);
+ //printk("DSR register: %x\n", (unsigned)IT_IO_READ16(IT_PM_DSR, data));
+ }
+#endif
+#ifdef CONFIG_IT8172_SCR0
+ {
+ unsigned i;
+ /* Enable Smart Card Reader 0 */
+ /* First power it up */
+ IT_IO_READ16(IT_PM_DSR, i);
+ i &= ~IT_PM_DSR_SCR0SB;
+ IT_IO_WRITE16(IT_PM_DSR, i);
+ /* Then initialize its registers */
+ outb(( IT_SCR_SFR_GATE_UART_OFF << IT_SCR_SFR_GATE_UART_BIT
+ |IT_SCR_SFR_FET_CHARGE_213_US << IT_SCR_SFR_FET_CHARGE_BIT
+ |IT_SCR_SFR_CARD_FREQ_3_5_MHZ << IT_SCR_SFR_CARD_FREQ_BIT
+ |IT_SCR_SFR_FET_ACTIVE_INVERT << IT_SCR_SFR_FET_ACTIVE_BIT
+ |IT_SCR_SFR_ENABLE_ON << IT_SCR_SFR_ENABLE_BIT),
+ IT8172_PCI_IO_BASE + IT_SCR0_BASE + IT_SCR_SFR);
+ outb(IT_SCR_SCDR_RESET_MODE_ASYNC << IT_SCR_SCDR_RESET_MODE_BIT,
+ IT8172_PCI_IO_BASE + IT_SCR0_BASE + IT_SCR_SCDR);
+ }
+#endif /* CONFIG_IT8172_SCR0 */
+#ifdef CONFIG_IT8172_SCR1
+ {
+ unsigned i;
+ /* Enable Smart Card Reader 1 */
+ /* First power it up */
+ IT_IO_READ16(IT_PM_DSR, i);
+ i &= ~IT_PM_DSR_SCR1SB;
+ IT_IO_WRITE16(IT_PM_DSR, i);
+ /* Then initialize its registers */
+ outb(( IT_SCR_SFR_GATE_UART_OFF << IT_SCR_SFR_GATE_UART_BIT
+ |IT_SCR_SFR_FET_CHARGE_213_US << IT_SCR_SFR_FET_CHARGE_BIT
+ |IT_SCR_SFR_CARD_FREQ_3_5_MHZ << IT_SCR_SFR_CARD_FREQ_BIT
+ |IT_SCR_SFR_FET_ACTIVE_INVERT << IT_SCR_SFR_FET_ACTIVE_BIT
+ |IT_SCR_SFR_ENABLE_ON << IT_SCR_SFR_ENABLE_BIT),
+ IT8172_PCI_IO_BASE + IT_SCR1_BASE + IT_SCR_SFR);
+ outb(IT_SCR_SCDR_RESET_MODE_ASYNC << IT_SCR_SCDR_RESET_MODE_BIT,
+ IT8172_PCI_IO_BASE + IT_SCR1_BASE + IT_SCR_SCDR);
+ }
+#endif /* CONFIG_IT8172_SCR1 */
+}
+
+early_initcall(it8172_setup);
+
+#ifdef CONFIG_SERIO_I8042
+/*
+ * According to the ITE Special BIOS Note for waking up the
+ * keyboard controller...
+ */
+static int init_8712_keyboard(void)
+{
+ unsigned int cmd_port = 0x14000064;
+ unsigned int data_port = 0x14000060;
+ ^^^^^^^^^^^
+ Somebody here doesn't grok the concept of io ports.
+
+ unsigned char data;
+ int i;
+
+ outb(0xaa, cmd_port); /* send self-test cmd */
+ i = 0;
+ while (!(inb(cmd_port) & 0x1)) { /* wait output buffer full */
+ i++;
+ if (i > 0xffffff)
+ return 1;
+ }
+
+ data = inb(data_port);
+ outb(0xcb, cmd_port); /* set ps2 mode */
+ while (inb(cmd_port) & 0x2) { /* wait while input buffer full */
+ i++;
+ if (i > 0xffffff)
+ return 1;
+ }
+ outb(0x01, data_port);
+ while (inb(cmd_port) & 0x2) { /* wait while input buffer full */
+ i++;
+ if (i > 0xffffff)
+ return 1;
+ }
+
+ outb(0x60, cmd_port); /* write 8042 command byte */
+ while (inb(cmd_port) & 0x2) { /* wait while input buffer full */
+ i++;
+ if (i > 0xffffff)
+ return 1;
+ }
+ outb(0x45, data_port); /* at interface, keyboard enabled, system flag */
+ while (inb(cmd_port) & 0x2) { /* wait while input buffer full */
+ i++;
+ if (i > 0xffffff)
+ return 1;
+ }
+
+ outb(0xae, cmd_port); /* enable interface */
+ return 0;
+}
+#endif
diff --git a/arch/mips/ite-boards/generic/lpc.c b/arch/mips/ite-boards/generic/lpc.c
new file mode 100644
index 0000000..cc7584f
--- /dev/null
+++ b/arch/mips/ite-boards/generic/lpc.c
@@ -0,0 +1,144 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ * ITE Semi IT8712 Super I/O functions.
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ * ppopov@mvista.com or source@mvista.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <asm/io.h>
+#include <asm/types.h>
+#include <asm/it8712.h>
+#include <asm/it8172/it8172.h>
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+void LPCEnterMBPnP(void)
+{
+ int i;
+ unsigned char key[4] = {0x87, 0x01, 0x55, 0x55};
+
+ for (i = 0; i<4; i++)
+ outb(key[i], LPC_KEY_ADDR);
+
+}
+
+void LPCExitMBPnP(void)
+{
+ outb(0x02, LPC_KEY_ADDR);
+ outb(0x02, LPC_DATA_ADDR);
+}
+
+void LPCSetConfig(char LdnNumber, char Index, char data)
+{
+ LPCEnterMBPnP(); // Enter IT8712 MB PnP mode
+ outb(0x07, LPC_KEY_ADDR);
+ outb(LdnNumber, LPC_DATA_ADDR);
+ outb(Index, LPC_KEY_ADDR);
+ outb(data, LPC_DATA_ADDR);
+ LPCExitMBPnP();
+}
+
+char LPCGetConfig(char LdnNumber, char Index)
+{
+ char rtn;
+
+ LPCEnterMBPnP(); // Enter IT8712 MB PnP mode
+ outb(0x07, LPC_KEY_ADDR);
+ outb(LdnNumber, LPC_DATA_ADDR);
+ outb(Index, LPC_KEY_ADDR);
+ rtn = inb(LPC_DATA_ADDR);
+ LPCExitMBPnP();
+ return rtn;
+}
+
+int SearchIT8712(void)
+{
+ unsigned char Id1, Id2;
+ unsigned short Id;
+
+ LPCEnterMBPnP();
+ outb(0x20, LPC_KEY_ADDR); /* chip id byte 1 */
+ Id1 = inb(LPC_DATA_ADDR);
+ outb(0x21, LPC_KEY_ADDR); /* chip id byte 2 */
+ Id2 = inb(LPC_DATA_ADDR);
+ Id = (Id1 << 8) | Id2;
+ LPCExitMBPnP();
+ if (Id == 0x8712)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+void InitLPCInterface(void)
+{
+ unsigned char bus, dev_fn;
+ unsigned long data;
+
+ bus = 0;
+ dev_fn = 1<<3 | 4;
+
+
+ /* pci cmd, SERR# Enable */
+ IT_WRITE(IT_CONFADDR,
+ (bus << IT_BUSNUM_SHF) |
+ (dev_fn << IT_FUNCNUM_SHF) |
+ ((0x4 / 4) << IT_REGNUM_SHF));
+ IT_READ(IT_CONFDATA, data);
+ data |= 0x0100;
+ IT_WRITE(IT_CONFADDR,
+ (bus << IT_BUSNUM_SHF) |
+ (dev_fn << IT_FUNCNUM_SHF) |
+ ((0x4 / 4) << IT_REGNUM_SHF));
+ IT_WRITE(IT_CONFDATA, data);
+
+ /* setup serial irq control register */
+ IT_WRITE(IT_CONFADDR,
+ (bus << IT_BUSNUM_SHF) |
+ (dev_fn << IT_FUNCNUM_SHF) |
+ ((0x48 / 4) << IT_REGNUM_SHF));
+ IT_READ(IT_CONFDATA, data);
+ data = (data & 0xffff00ff) | 0xc400;
+ IT_WRITE(IT_CONFADDR,
+ (bus << IT_BUSNUM_SHF) |
+ (dev_fn << IT_FUNCNUM_SHF) |
+ ((0x48 / 4) << IT_REGNUM_SHF));
+ IT_WRITE(IT_CONFDATA, data);
+
+
+ /* Enable I/O Space Subtractive Decode */
+ /* default 0x4C is 0x3f220000 */
+ IT_WRITE(IT_CONFADDR,
+ (bus << IT_BUSNUM_SHF) |
+ (dev_fn << IT_FUNCNUM_SHF) |
+ ((0x4C / 4) << IT_REGNUM_SHF));
+ IT_WRITE(IT_CONFDATA, 0x3f2200f3);
+}
diff --git a/arch/mips/ite-boards/generic/pmon_prom.c b/arch/mips/ite-boards/generic/pmon_prom.c
new file mode 100644
index 0000000..6e505af
--- /dev/null
+++ b/arch/mips/ite-boards/generic/pmon_prom.c
@@ -0,0 +1,136 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ * PROM library initialisation code, assuming a version of
+ * pmon is the boot code.
+ *
+ * Copyright 2000 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ * ppopov@mvista.com or source@mvista.com
+ *
+ * This file was derived from Carsten Langgaard's
+ * arch/mips/mips-boards/xx files.
+ *
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/string.h>
+
+#include <asm/bootinfo.h>
+
+extern int prom_argc;
+extern char **prom_argv, **prom_envp;
+
+typedef struct
+{
+ char *name;
+/* char *val; */
+}t_env_var;
+
+
+char * __init prom_getcmdline(void)
+{
+ return &(arcs_cmdline[0]);
+}
+
+void __init prom_init_cmdline(void)
+{
+ char *cp;
+ int actr;
+
+ actr = 1; /* Always ignore argv[0] */
+
+ cp = &(arcs_cmdline[0]);
+ while(actr < prom_argc) {
+ strcpy(cp, prom_argv[actr]);
+ cp += strlen(prom_argv[actr]);
+ *cp++ = ' ';
+ actr++;
+ }
+ if (cp != &(arcs_cmdline[0])) /* get rid of trailing space */
+ --cp;
+ *cp = '\0';
+
+}
+
+
+char *prom_getenv(char *envname)
+{
+ /*
+ * Return a pointer to the given environment variable.
+ * Environment variables are stored in the form of "memsize=64".
+ */
+
+ t_env_var *env = (t_env_var *)prom_envp;
+ int i;
+
+ i = strlen(envname);
+
+ while(env->name) {
+ if(strncmp(envname, env->name, i) == 0) {
+ return(env->name + strlen(envname) + 1);
+ }
+ env++;
+ }
+ return(NULL);
+}
+
+static inline unsigned char str2hexnum(unsigned char c)
+{
+ if(c >= '0' && c <= '9')
+ return c - '0';
+ if(c >= 'a' && c <= 'f')
+ return c - 'a' + 10;
+ return 0; /* foo */
+}
+
+unsigned long __init prom_free_prom_memory(void)
+{
+ return 0;
+}
+
+unsigned long __init prom_get_memsize(void)
+{
+ char *memsize_str;
+ unsigned int memsize;
+
+ memsize_str = prom_getenv("memsize");
+ if (!memsize_str) {
+#ifdef CONFIG_MIPS_ITE8172
+ memsize = 32;
+#elif defined(CONFIG_MIPS_IVR)
+ memsize = 64;
+#else
+ memsize = 8;
+#endif
+ printk("memsize unknown: setting to %dMB\n", memsize);
+ } else {
+ printk("memsize: %s\n", memsize_str);
+ memsize = simple_strtol(memsize_str, NULL, 0);
+ }
+ return memsize;
+}
diff --git a/arch/mips/ite-boards/generic/puts.c b/arch/mips/ite-boards/generic/puts.c
new file mode 100644
index 0000000..20b02df
--- /dev/null
+++ b/arch/mips/ite-boards/generic/puts.c
@@ -0,0 +1,139 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ * Low level uart routines to directly access a 16550 uart.
+ *
+ * Copyright 2000,2001 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ * ppopov@mvista.com or source@mvista.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/types.h>
+
+#define SERIAL_BASE 0xB4011800 /* it8172 */
+#define SER_CMD 5
+#define SER_DATA 0x00
+#define TX_BUSY 0x20
+
+#define TIMEOUT 0xffff
+#undef SLOW_DOWN
+
+static const char digits[16] = "0123456789abcdef";
+static volatile unsigned char *const com1 = (unsigned char *) SERIAL_BASE;
+
+
+#ifdef SLOW_DOWN
+static inline void slow_down()
+{
+ int k;
+ for (k = 0; k < 10000; k++);
+}
+#else
+#define slow_down()
+#endif
+
+void putch(const unsigned char c)
+{
+ unsigned char ch;
+ int i = 0;
+
+ do {
+ ch = com1[SER_CMD];
+ slow_down();
+ i++;
+ if (i > TIMEOUT) {
+ break;
+ }
+ } while (0 == (ch & TX_BUSY));
+ com1[SER_DATA] = c;
+}
+
+void puts(unsigned char *cp)
+{
+ unsigned char ch;
+ int i = 0;
+
+ while (*cp) {
+ do {
+ ch = com1[SER_CMD];
+ slow_down();
+ i++;
+ if (i > TIMEOUT) {
+ break;
+ }
+ } while (0 == (ch & TX_BUSY));
+ com1[SER_DATA] = *cp++;
+ }
+ putch('\r');
+ putch('\n');
+}
+
+void fputs(unsigned char *cp)
+{
+ unsigned char ch;
+ int i = 0;
+
+ while (*cp) {
+
+ do {
+ ch = com1[SER_CMD];
+ slow_down();
+ i++;
+ if (i > TIMEOUT) {
+ break;
+ }
+ } while (0 == (ch & TX_BUSY));
+ com1[SER_DATA] = *cp++;
+ }
+}
+
+
+void put64(uint64_t ul)
+{
+ int cnt;
+ unsigned ch;
+
+ cnt = 16; /* 16 nibbles in a 64 bit long */
+ putch('0');
+ putch('x');
+ do {
+ cnt--;
+ ch = (unsigned char) (ul >> cnt * 4) & 0x0F;
+ putch(digits[ch]);
+ } while (cnt > 0);
+}
+
+void put32(unsigned u)
+{
+ int cnt;
+ unsigned ch;
+
+ cnt = 8; /* 8 nibbles in a 32 bit long */
+ putch('0');
+ putch('x');
+ do {
+ cnt--;
+ ch = (unsigned char) (u >> cnt * 4) & 0x0F;
+ putch(digits[ch]);
+ } while (cnt > 0);
+}
diff --git a/arch/mips/ite-boards/generic/reset.c b/arch/mips/ite-boards/generic/reset.c
new file mode 100644
index 0000000..03bd5ba
--- /dev/null
+++ b/arch/mips/ite-boards/generic/reset.c
@@ -0,0 +1,60 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ * ITE 8172 reset routines.
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ * ppopov@mvista.com or source@mvista.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <asm/cacheflush.h>
+#include <asm/io.h>
+#include <asm/processor.h>
+#include <asm/reboot.h>
+#include <asm/system.h>
+
+void it8172_restart()
+{
+ set_c0_status(ST0_BEV | ST0_ERL);
+ change_c0_config(CONF_CM_CMASK, CONF_CM_UNCACHED);
+ flush_cache_all();
+ write_c0_wired(0);
+ __asm__ __volatile__("jr\t%0"::"r"(0xbfc00000));
+}
+
+void it8172_halt(void)
+{
+ printk(KERN_NOTICE "\n** You can safely turn off the power\n");
+ while (1)
+ __asm__(".set\tmips3\n\t"
+ "wait\n\t"
+ ".set\tmips0");
+}
+
+void it8172_power_off(void)
+{
+ it8172_halt();
+}
diff --git a/arch/mips/ite-boards/generic/time.c b/arch/mips/ite-boards/generic/time.c
new file mode 100644
index 0000000..30a6c0d
--- /dev/null
+++ b/arch/mips/ite-boards/generic/time.c
@@ -0,0 +1,247 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
+ *
+ * Copyright (C) 2003 MontaVista Software Inc.
+ * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
+ *
+ * ########################################################################
+ *
+ * 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.
+ *
+ * ########################################################################
+ *
+ * Setting up the clock on the MIPS boards.
+ */
+#include <linux/init.h>
+#include <linux/kernel_stat.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/spinlock.h>
+
+#include <asm/time.h>
+#include <asm/mipsregs.h>
+#include <asm/ptrace.h>
+#include <asm/it8172/it8172.h>
+#include <asm/it8172/it8172_int.h>
+#include <asm/debug.h>
+
+#define IT8172_RTC_ADR_REG (IT8172_PCI_IO_BASE + IT_RTC_BASE)
+#define IT8172_RTC_DAT_REG (IT8172_RTC_ADR_REG + 1)
+#define IT8172_RTC_CENTURY_REG (IT8172_PCI_IO_BASE + IT_RTC_CENTURY)
+
+static volatile char *rtc_adr_reg = (char*)KSEG1ADDR(IT8172_RTC_ADR_REG);
+static volatile char *rtc_dat_reg = (char*)KSEG1ADDR(IT8172_RTC_DAT_REG);
+static volatile char *rtc_century_reg = (char*)KSEG1ADDR(IT8172_RTC_CENTURY_REG);
+
+unsigned char it8172_rtc_read_data(unsigned long addr)
+{
+ unsigned char retval;
+
+ *rtc_adr_reg = addr;
+ retval = *rtc_dat_reg;
+ return retval;
+}
+
+void it8172_rtc_write_data(unsigned char data, unsigned long addr)
+{
+ *rtc_adr_reg = addr;
+ *rtc_dat_reg = data;
+}
+
+#undef CMOS_READ
+#undef CMOS_WRITE
+#define CMOS_READ(addr) it8172_rtc_read_data(addr)
+#define CMOS_WRITE(data, addr) it8172_rtc_write_data(data, addr)
+
+static unsigned char saved_control; /* remember rtc control reg */
+static inline int rtc_24h(void) { return saved_control & RTC_24H; }
+static inline int rtc_dm_binary(void) { return saved_control & RTC_DM_BINARY; }
+
+static inline unsigned char
+bin_to_hw(unsigned char c)
+{
+ if (rtc_dm_binary())
+ return c;
+ else
+ return ((c/10) << 4) + (c%10);
+}
+
+static inline unsigned char
+hw_to_bin(unsigned char c)
+{
+ if (rtc_dm_binary())
+ return c;
+ else
+ return (c>>4)*10 + (c &0xf);
+}
+
+/* 0x80 bit indicates pm in 12-hour format */
+static inline unsigned char
+hour_bin_to_hw(unsigned char c)
+{
+ if (rtc_24h())
+ return bin_to_hw(c);
+ if (c >= 12)
+ return 0x80 | bin_to_hw((c==12)?12:c-12); /* 12 is 12pm */
+ else
+ return bin_to_hw((c==0)?12:c); /* 0 is 12 AM, not 0 am */
+}
+
+static inline unsigned char
+hour_hw_to_bin(unsigned char c)
+{
+ unsigned char tmp = hw_to_bin(c&0x3f);
+ if (rtc_24h())
+ return tmp;
+ if (c & 0x80)
+ return (tmp==12)?12:tmp+12; /* 12pm is 12, not 24 */
+ else
+ return (tmp==12)?0:tmp; /* 12am is 0 */
+}
+
+static unsigned long r4k_offset; /* Amount to increment compare reg each time */
+static unsigned long r4k_cur; /* What counter should be at next timer irq */
+extern unsigned int mips_hpt_frequency;
+
+/*
+ * Figure out the r4k offset, the amount to increment the compare
+ * register for each time tick.
+ * Use the RTC to calculate offset.
+ */
+static unsigned long __init cal_r4koff(void)
+{
+ unsigned int flags;
+
+ local_irq_save(flags);
+
+ /* Start counter exactly on falling edge of update flag */
+ while (CMOS_READ(RTC_REG_A) & RTC_UIP);
+ while (!(CMOS_READ(RTC_REG_A) & RTC_UIP));
+
+ /* Start r4k counter. */
+ write_c0_count(0);
+
+ /* Read counter exactly on falling edge of update flag */
+ while (CMOS_READ(RTC_REG_A) & RTC_UIP);
+ while (!(CMOS_READ(RTC_REG_A) & RTC_UIP));
+
+ mips_hpt_frequency = read_c0_count();
+
+ /* restore interrupts */
+ local_irq_restore(flags);
+
+ return (mips_hpt_frequency / HZ);
+}
+
+static unsigned long
+it8172_rtc_get_time(void)
+{
+ unsigned int year, mon, day, hour, min, sec;
+ unsigned int flags;
+
+ /* avoid update-in-progress. */
+ for (;;) {
+ local_irq_save(flags);
+ if (! (CMOS_READ(RTC_REG_A) & RTC_UIP))
+ break;
+ /* don't hold intr closed all the time */
+ local_irq_restore(flags);
+ }
+
+ /* Read regs. */
+ sec = hw_to_bin(CMOS_READ(RTC_SECONDS));
+ min = hw_to_bin(CMOS_READ(RTC_MINUTES));
+ hour = hour_hw_to_bin(CMOS_READ(RTC_HOURS));
+ day = hw_to_bin(CMOS_READ(RTC_DAY_OF_MONTH));
+ mon = hw_to_bin(CMOS_READ(RTC_MONTH));
+ year = hw_to_bin(CMOS_READ(RTC_YEAR)) +
+ hw_to_bin(*rtc_century_reg) * 100;
+
+ /* restore interrupts */
+ local_irq_restore(flags);
+
+ return mktime(year, mon, day, hour, min, sec);
+}
+
+static int
+it8172_rtc_set_time(unsigned long t)
+{
+ struct rtc_time tm;
+ unsigned int flags;
+
+ /* convert */
+ to_tm(t, &tm);
+
+ /* avoid update-in-progress. */
+ for (;;) {
+ local_irq_save(flags);
+ if (! (CMOS_READ(RTC_REG_A) & RTC_UIP))
+ break;
+ /* don't hold intr closed all the time */
+ local_irq_restore(flags);
+ }
+
+ *rtc_century_reg = bin_to_hw(tm.tm_year/100);
+ CMOS_WRITE(bin_to_hw(tm.tm_sec), RTC_SECONDS);
+ CMOS_WRITE(bin_to_hw(tm.tm_min), RTC_MINUTES);
+ CMOS_WRITE(hour_bin_to_hw(tm.tm_hour), RTC_HOURS);
+ CMOS_WRITE(bin_to_hw(tm.tm_mday), RTC_DAY_OF_MONTH);
+ CMOS_WRITE(bin_to_hw(tm.tm_mon+1), RTC_MONTH); /* tm_mon starts from 0 */
+ CMOS_WRITE(bin_to_hw(tm.tm_year%100), RTC_YEAR);
+
+ /* restore interrupts */
+ local_irq_restore(flags);
+
+ return 0;
+}
+
+void __init it8172_time_init(void)
+{
+ unsigned int est_freq, flags;
+
+ local_irq_save(flags);
+
+ saved_control = CMOS_READ(RTC_CONTROL);
+
+ printk("calculating r4koff... ");
+ r4k_offset = cal_r4koff();
+ printk("%08lx(%d)\n", r4k_offset, (int) r4k_offset);
+
+ est_freq = 2*r4k_offset*HZ;
+ est_freq += 5000; /* round */
+ est_freq -= est_freq%10000;
+ printk("CPU frequency %d.%02d MHz\n", est_freq/1000000,
+ (est_freq%1000000)*100/1000000);
+
+ local_irq_restore(flags);
+
+ rtc_get_time = it8172_rtc_get_time;
+ rtc_set_time = it8172_rtc_set_time;
+}
+
+#define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5)
+void __init it8172_timer_setup(struct irqaction *irq)
+{
+ puts("timer_setup\n");
+ put32(NR_IRQS);
+ puts("");
+ /* we are using the cpu counter for timer interrupts */
+ setup_irq(MIPS_CPU_TIMER_IRQ, irq);
+
+ /* to generate the first timer interrupt */
+ r4k_cur = (read_c0_count() + r4k_offset);
+ write_c0_compare(r4k_cur);
+ set_c0_status(ALLINTS);
+}
diff --git a/arch/mips/ite-boards/ivr/Makefile b/arch/mips/ite-boards/ivr/Makefile
new file mode 100644
index 0000000..e4fa604
--- /dev/null
+++ b/arch/mips/ite-boards/ivr/Makefile
@@ -0,0 +1,10 @@
+#
+# Copyright 2000 MontaVista Software Inc.
+# Author: MontaVista Software, Inc.
+# ppopov@mvista.com or source@mvista.com
+#
+# Makefile for the Globespan IVR board,
+# board-specific files.
+#
+
+obj-y += init.o
diff --git a/arch/mips/ite-boards/ivr/README b/arch/mips/ite-boards/ivr/README
new file mode 100644
index 0000000..aa7d8db
--- /dev/null
+++ b/arch/mips/ite-boards/ivr/README
@@ -0,0 +1,3 @@
+This is not really a board made by ITE Semi, but it's very
+similar to the ITE QED-4N-S01B board. The IVR board is made
+by Globespan and it's a reference board for the PVR chip.
diff --git a/arch/mips/ite-boards/ivr/init.c b/arch/mips/ite-boards/ivr/init.c
new file mode 100644
index 0000000..ea4e193
--- /dev/null
+++ b/arch/mips/ite-boards/ivr/init.c
@@ -0,0 +1,84 @@
+/*
+ * BRIEF MODULE DESCRIPTION
+ * IVR board setup.
+ *
+ * Copyright 2000 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ * ppopov@mvista.com or source@mvista.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/bootmem.h>
+#include <asm/addrspace.h>
+#include <asm/bootinfo.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <asm/it8172/it8172.h>
+#include <asm/it8172/it8172_dbg.h>
+
+int prom_argc;
+char **prom_argv, **prom_envp;
+
+extern char _end;
+extern void __init prom_init_cmdline(void);
+extern unsigned long __init prom_get_memsize(void);
+extern void __init it8172_init_ram_resource(unsigned long memsize);
+
+#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
+#define PFN_ALIGN(x) (((unsigned long)(x) + (PAGE_SIZE - 1)) & PAGE_MASK)
+
+const char *get_system_type(void)
+{
+ return "Globespan IVR";
+}
+
+void __init prom_init(void)
+{
+ unsigned long mem_size;
+ unsigned long pcicr;
+
+ prom_argc = fw_arg0;
+ prom_argv = (char **) fw_arg1;
+ prom_envp = (int *) fw_arg3;
+
+ mips_machgroup = MACH_GROUP_GLOBESPAN;
+ mips_machtype = MACH_IVR; /* Globespan's iTVC15 reference board */
+
+ prom_init_cmdline();
+
+ /* pmon does not set memsize */
+ mem_size = prom_get_memsize();
+ mem_size = mem_size << 20;
+
+ /*
+ * make the entire physical memory visible to pci bus masters
+ */
+ IT_READ(IT_MC_PCICR, pcicr);
+ pcicr &= ~0x1f;
+ pcicr |= (mem_size - 1) >> 22;
+ IT_WRITE(IT_MC_PCICR, pcicr);
+
+ it8172_init_ram_resource(mem_size);
+ add_memory_region(0, mem_size, BOOT_MEM_RAM);
+}
diff --git a/arch/mips/ite-boards/qed-4n-s01b/Makefile b/arch/mips/ite-boards/qed-4n-s01b/Makefile
new file mode 100644
index 0000000..bb9972a
--- /dev/null
+++ b/arch/mips/ite-boards/qed-4n-s01b/Makefile
@@ -0,0 +1,10 @@
+#
+# Copyright 2000 MontaVista Software Inc.
+# Author: MontaVista Software, Inc.
+# ppopov@mvista.com or source@mvista.com
+#
+# Makefile for the ITE 8172 (qed-4n-s01b) board, board
+# specific files.
+#
+
+obj-y := init.o
diff --git a/arch/mips/ite-boards/qed-4n-s01b/README b/arch/mips/ite-boards/qed-4n-s01b/README
new file mode 100644
index 0000000..fb4b519
--- /dev/null
+++ b/arch/mips/ite-boards/qed-4n-s01b/README
@@ -0,0 +1,2 @@
+This is an ITE (www.iteusa.com) eval board for the ITE 8172G
+system controller, with a QED 5231 CPU.
diff --git a/arch/mips/ite-boards/qed-4n-s01b/init.c b/arch/mips/ite-boards/qed-4n-s01b/init.c
new file mode 100644
index 0000000..56dca7e
--- /dev/null
+++ b/arch/mips/ite-boards/qed-4n-s01b/init.c
@@ -0,0 +1,85 @@
+/*
+ * BRIEF MODULE DESCRIPTION
+ * IT8172/QED5231 board setup.
+ *
+ * Copyright 2000 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ * ppopov@mvista.com or source@mvista.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/bootmem.h>
+#include <asm/addrspace.h>
+#include <asm/bootinfo.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <asm/it8172/it8172.h>
+#include <asm/it8172/it8172_dbg.h>
+
+int prom_argc;
+char **prom_argv, **prom_envp;
+
+extern char _end;
+extern void __init prom_init_cmdline(void);
+extern unsigned long __init prom_get_memsize(void);
+extern void __init it8172_init_ram_resource(unsigned long memsize);
+
+#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
+#define PFN_ALIGN(x) (((unsigned long)(x) + (PAGE_SIZE - 1)) & PAGE_MASK)
+
+const char *get_system_type(void)
+{
+ return "ITE QED-4N-S01B";
+}
+
+void __init prom_init(void)
+{
+ unsigned long mem_size;
+ unsigned long pcicr;
+
+ prom_argc = fw_arg0;
+ prom_argv = (char **) fw_arg1;
+ prom_envp = (int *) fw_arg3;
+
+ mips_machgroup = MACH_GROUP_ITE;
+ mips_machtype = MACH_QED_4N_S01B; /* ITE board name/number */
+
+ prom_init_cmdline();
+ mem_size = prom_get_memsize();
+
+ printk("Memory size: %dMB\n", (unsigned)mem_size);
+
+ mem_size <<= 20; /* MB */
+
+ /*
+ * make the entire physical memory visible to pci bus masters
+ */
+ IT_READ(IT_MC_PCICR, pcicr);
+ pcicr &= ~0x1f;
+ pcicr |= (mem_size - 1) >> 22;
+ IT_WRITE(IT_MC_PCICR, pcicr);
+
+ it8172_init_ram_resource(mem_size);
+ add_memory_region(0, mem_size, BOOT_MEM_RAM);
+}
diff --git a/arch/mips/jazz/Makefile b/arch/mips/jazz/Makefile
new file mode 100644
index 0000000..8574924
--- /dev/null
+++ b/arch/mips/jazz/Makefile
@@ -0,0 +1,7 @@
+#
+# Makefile for the Jazz family specific parts of the kernel
+#
+
+obj-y := int-handler.o irq.o jazzdma.o reset.o setup.o
+
+EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/jazz/int-handler.S b/arch/mips/jazz/int-handler.S
new file mode 100644
index 0000000..4dbcf91
--- /dev/null
+++ b/arch/mips/jazz/int-handler.S
@@ -0,0 +1,282 @@
+/*
+ * 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, 1996, 1997, 1998 by Ralf Baechle and Andreas Busse
+ *
+ * Jazz family specific interrupt stuff
+ *
+ * To do: On Jazz machines we remap some non-ISA interrupts to ISA
+ * interrupts. These interrupts should use their own vectors.
+ * Squeeze the last cycles out of the handlers. Only a dead
+ * cycle is a good cycle.
+ */
+#include <asm/asm.h>
+#include <asm/mipsregs.h>
+#include <asm/jazz.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+
+/*
+ * jazz_handle_int: Interrupt handler for the ACER Pica-61 boards
+ */
+ .set noreorder
+
+ NESTED(jazz_handle_int, PT_SIZE, ra)
+ .set noat
+ SAVE_ALL
+ CLI
+ .set at
+
+ /*
+ * Get pending interrupts
+ */
+ mfc0 t0,CP0_CAUSE # get pending interrupts
+ mfc0 t1,CP0_STATUS # get enabled interrupts
+ and t0,t1 # isolate allowed ones
+ andi t0,0xff00 # isolate pending bits
+ beqz t0,3f
+ sll t0,16 # delay slot
+
+ /*
+ * Find irq with highest priority
+ * FIXME: This is slow - use binary search
+ */
+ la t1,ll_vectors
+1: bltz t0,2f # found pending irq
+ sll t0,1
+ b 1b
+ subu t1,PTRSIZE # delay slot
+
+ /*
+ * Do the low-level stuff
+ */
+2: lw t0,(t1)
+ jr t0
+ nop # delay slot
+ END(jazz_handle_int)
+
+ll_sw0: li s1,~IE_SW0
+ mfc0 t0,CP0_CAUSE
+ and t0,s1
+ mtc0 t0,CP0_CAUSE
+ PANIC("Unimplemented sw0 handler")
+
+ll_sw1: li s1,~IE_SW1
+ mfc0 t0,CP0_CAUSE
+ and t0,s1
+ mtc0 t0,CP0_CAUSE
+ PANIC("Unimplemented sw1 handler")
+
+ll_local_dma: li s1,~IE_IRQ0
+ PANIC("Unimplemented local_dma handler")
+
+ll_local_dev: lbu t0,JAZZ_IO_IRQ_SOURCE
+#if PTRSIZE == 8 /* True 64 bit kernel */
+ dsll t0,1
+#endif
+ .set reorder
+ LONG_L t0,local_vector(t0)
+ jr t0
+ .set noreorder
+
+/*
+ * The braindead PICA hardware gives us no way to distinguish if we really
+ * received interrupt 7 from the (E)ISA bus or if we just received an
+ * interrupt with no findable cause. This sometimes happens with braindead
+ * cards. Oh well - for all the Jazz boxes slots are more or less just
+ * whistles and bells and we're aware of the problem.
+ */
+ll_isa_irq: lw a0, JAZZ_EISA_IRQ_ACK
+
+ jal do_IRQ
+ move a1,sp
+
+ j ret_from_irq
+ nop
+
+/*
+ * Hmm... This is not just a plain PC clone so the question is
+ * which devices on Jazz machines can generate an (E)ISA NMI?
+ * (Writing to nonexistent memory?)
+ */
+ll_isa_nmi: li s1,~IE_IRQ3
+ PANIC("Unimplemented isa_nmi handler")
+
+/*
+ * Timer IRQ - remapped to be more similar to an IBM compatible.
+ *
+ * The timer interrupt is handled specially to ensure that the jiffies
+ * variable is updated at all times. Specifically, the timer interrupt is
+ * just like the complete handlers except that it is invoked with interrupts
+ * disabled and should never re-enable them. If other interrupts were
+ * allowed to be processed while the timer interrupt is active, then the
+ * other interrupts would have to avoid using the jiffies variable for delay
+ * and interval timing operations to avoid hanging the system.
+ */
+ll_timer: lw zero,JAZZ_TIMER_REGISTER # timer irq cleared on read
+ li s1,~IE_IRQ4
+
+ li a0, JAZZ_TIMER_IRQ
+ jal do_IRQ
+ move a1,sp
+
+ mfc0 t0,CP0_STATUS # disable interrupts again
+ ori t0,1
+ xori t0,1
+ mtc0 t0,CP0_STATUS
+
+ j ret_from_irq
+ nop
+
+/*
+ * CPU count/compare IRQ (unused)
+ */
+ll_count: j ret_from_irq
+ mtc0 zero,CP0_COMPARE
+
+#if 0
+/*
+ * Call the handler for the interrupt
+ * (Currently unused)
+ */
+call_real: /*
+ * temporarily disable interrupt
+ */
+ mfc0 t2,CP0_STATUS
+ and t2,s1
+ mtc0 t2,CP0_STATUS
+ nor s1,zero,s1
+ jal do_IRQ
+
+ /*
+ * reenable interrupt
+ */
+ mfc0 t2,CP0_STATUS
+ or t2,s1
+ mtc0 t2,CP0_STATUS
+ j ret_from_irq
+#endif
+
+ .data
+ PTR ll_sw0 # SW0
+ PTR ll_sw1 # SW1
+ PTR ll_local_dma # Local DMA
+ PTR ll_local_dev # Local devices
+ PTR ll_isa_irq # ISA IRQ
+ PTR ll_isa_nmi # ISA NMI
+ PTR ll_timer # Timer
+ll_vectors: PTR ll_count # Count/Compare IRQ
+
+ /*
+ * Interrupt handlers for local devices.
+ */
+ .text
+ .set reorder
+loc_no_irq: PANIC("Unimplemented loc_no_irq handler")
+/*
+ * Parallel port IRQ
+ */
+loc_parallel: li s1,~JAZZ_IE_PARALLEL
+ li a0,JAZZ_PARALLEL_IRQ
+ b loc_call
+
+/*
+ * Floppy IRQ
+ */
+loc_floppy: li s1,~JAZZ_IE_FLOPPY
+ li a0,JAZZ_FLOPPY_IRQ
+ b loc_call
+
+/*
+ * Sound IRQ
+ */
+loc_sound: PANIC("Unimplemented loc_sound handler")
+loc_video: PANIC("Unimplemented loc_video handler")
+
+/*
+ * Ethernet interrupt handler
+ */
+loc_ethernet: li s1,~JAZZ_IE_ETHERNET
+ li a0,JAZZ_ETHERNET_IRQ
+ b loc_call
+
+/*
+ * SCSI interrupt handler
+ */
+loc_scsi: li s1,~JAZZ_IE_SCSI
+ li a0,JAZZ_SCSI_IRQ
+ b loc_call
+
+/*
+ * Keyboard interrupt handler
+ */
+loc_keyboard: li s1,~JAZZ_IE_KEYBOARD
+ li a0,JAZZ_KEYBOARD_IRQ
+ b loc_call
+
+/*
+ * Mouse interrupt handler
+ */
+loc_mouse: li s1,~JAZZ_IE_MOUSE
+ li a0,JAZZ_MOUSE_IRQ
+ b loc_call
+
+/*
+ * Serial port 1 IRQ
+ */
+loc_serial1: li s1,~JAZZ_IE_SERIAL1
+ li a0,JAZZ_SERIAL1_IRQ
+ b loc_call
+
+/*
+ * Serial port 2 IRQ
+ */
+loc_serial2: li s1,~JAZZ_IE_SERIAL2
+ li a0,JAZZ_SERIAL2_IRQ
+ b loc_call
+
+/*
+ * Call the interrupt handler for an interrupt generated by a
+ * local device.
+ */
+loc_call: /*
+ * Temporarily disable interrupt source
+ */
+ lhu t2,JAZZ_IO_IRQ_ENABLE
+ and t2,s1
+ sh t2,JAZZ_IO_IRQ_ENABLE
+
+ nor s1,zero,s1
+ jal do_IRQ
+
+ /*
+ * Reenable interrupt
+ */
+ lhu t2,JAZZ_IO_IRQ_ENABLE
+ or t2,s1
+ sh t2,JAZZ_IO_IRQ_ENABLE
+
+ j ret_from_irq
+
+/*
+ * "Jump extender" to reach spurious_interrupt
+ */
+3: j spurious_interrupt
+
+/*
+ * Vectors for interrupts generated by local devices
+ */
+ .data
+local_vector: PTR loc_no_irq
+ PTR loc_parallel
+ PTR loc_floppy
+ PTR loc_sound
+ PTR loc_video
+ PTR loc_ethernet
+ PTR loc_scsi
+ PTR loc_keyboard
+ PTR loc_mouse
+ PTR loc_serial1
+ PTR loc_serial2
diff --git a/arch/mips/jazz/io.c b/arch/mips/jazz/io.c
new file mode 100644
index 0000000..e869044
--- /dev/null
+++ b/arch/mips/jazz/io.c
@@ -0,0 +1,135 @@
+/*
+ * 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.
+ *
+ * Low level I/O functions for Jazz family machines.
+ *
+ * Copyright (C) 1997 by Ralf Baechle.
+ */
+#include <linux/string.h>
+#include <linux/spinlock.h>
+#include <asm/addrspace.h>
+#include <asm/system.h>
+#include <asm/jazz.h>
+
+/*
+ * Map an 16mb segment of the EISA address space to 0xe3000000;
+ */
+static inline void map_eisa_address(unsigned long address)
+{
+ /* XXX */
+ /* We've got an wired entry in the TLB. We just need to modify it.
+ fast and clean. But since we want to get rid of wired entries
+ things are a little bit more complicated ... */
+}
+
+static unsigned char jazz_readb(unsigned long addr)
+{
+ unsigned char res;
+
+ map_eisa_address(addr);
+ addr &= 0xffffff;
+ res = *(volatile unsigned char *) (JAZZ_EISA_BASE + addr);
+
+ return res;
+}
+
+static unsigned short jazz_readw(unsigned long addr)
+{
+ unsigned short res;
+
+ map_eisa_address(addr);
+ addr &= 0xffffff;
+ res = *(volatile unsigned char *) (JAZZ_EISA_BASE + addr);
+
+ return res;
+}
+
+static unsigned int jazz_readl(unsigned long addr)
+{
+ unsigned int res;
+
+ map_eisa_address(addr);
+ addr &= 0xffffff;
+ res = *(volatile unsigned char *) (JAZZ_EISA_BASE + addr);
+
+ return res;
+}
+
+static void jazz_writeb(unsigned char val, unsigned long addr)
+{
+ map_eisa_address(addr);
+ addr &= 0xffffff;
+ *(volatile unsigned char *) (JAZZ_EISA_BASE + addr) = val;
+}
+
+static void jazz_writew(unsigned short val, unsigned long addr)
+{
+ map_eisa_address(addr);
+ addr &= 0xffffff;
+ *(volatile unsigned char *) (JAZZ_EISA_BASE + addr) = val;
+}
+
+static void jazz_writel(unsigned int val, unsigned long addr)
+{
+ map_eisa_address(addr);
+ addr &= 0xffffff;
+ *(volatile unsigned char *) (JAZZ_EISA_BASE + addr) = val;
+}
+
+static void jazz_memset_io(unsigned long addr, int val, unsigned long len)
+{
+ unsigned long waddr;
+
+ waddr = JAZZ_EISA_BASE | (addr & 0xffffff);
+ while(len) {
+ unsigned long fraglen;
+
+ fraglen = (~addr + 1) & 0xffffff;
+ fraglen = (fraglen < len) ? fraglen : len;
+ map_eisa_address(addr);
+ memset((char *)waddr, val, fraglen);
+ addr += fraglen;
+ waddr = waddr + fraglen - 0x1000000;
+ len -= fraglen;
+ }
+}
+
+static void jazz_memcpy_fromio(unsigned long to, unsigned long from, unsigned long len)
+{
+ unsigned long waddr;
+
+ waddr = JAZZ_EISA_BASE | (from & 0xffffff);
+ while(len) {
+ unsigned long fraglen;
+
+ fraglen = (~from + 1) & 0xffffff;
+ fraglen = (fraglen < len) ? fraglen : len;
+ map_eisa_address(from);
+ memcpy((void *)to, (void *)waddr, fraglen);
+ to += fraglen;
+ from += fraglen;
+ waddr = waddr + fraglen - 0x1000000;
+ len -= fraglen;
+ }
+}
+
+static void jazz_memcpy_toio(unsigned long to, unsigned long from, unsigned long len)
+{
+ unsigned long waddr;
+
+ waddr = JAZZ_EISA_BASE | (to & 0xffffff);
+ while(len) {
+ unsigned long fraglen;
+
+ fraglen = (~to + 1) & 0xffffff;
+ fraglen = (fraglen < len) ? fraglen : len;
+ map_eisa_address(to);
+ memcpy((char *)to + JAZZ_EISA_BASE, (void *)from, fraglen);
+ to += fraglen;
+ from += fraglen;
+ waddr = waddr + fraglen - 0x1000000;
+ len -= fraglen;
+ }
+}
diff --git a/arch/mips/jazz/irq.c b/arch/mips/jazz/irq.c
new file mode 100644
index 0000000..0b608fa
--- /dev/null
+++ b/arch/mips/jazz/irq.c
@@ -0,0 +1,100 @@
+/*
+ * 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) 1992 Linus Torvalds
+ * Copyright (C) 1994 - 2001, 2003 Ralf Baechle
+ */
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+
+#include <asm/i8259.h>
+#include <asm/io.h>
+#include <asm/jazz.h>
+
+extern asmlinkage void jazz_handle_int(void);
+
+static DEFINE_SPINLOCK(r4030_lock);
+
+static void enable_r4030_irq(unsigned int irq)
+{
+ unsigned int mask = 1 << (irq - JAZZ_PARALLEL_IRQ);
+ unsigned long flags;
+
+ spin_lock_irqsave(&r4030_lock, flags);
+ mask |= r4030_read_reg16(JAZZ_IO_IRQ_ENABLE);
+ r4030_write_reg16(JAZZ_IO_IRQ_ENABLE, mask);
+ spin_unlock_irqrestore(&r4030_lock, flags);
+}
+
+static unsigned int startup_r4030_irq(unsigned int irq)
+{
+ enable_r4030_irq(irq);
+ return 0; /* never anything pending */
+}
+
+#define shutdown_r4030_irq disable_r4030_irq
+
+void disable_r4030_irq(unsigned int irq)
+{
+ unsigned int mask = ~(1 << (irq - JAZZ_PARALLEL_IRQ));
+ unsigned long flags;
+
+ spin_lock_irqsave(&r4030_lock, flags);
+ mask &= r4030_read_reg16(JAZZ_IO_IRQ_ENABLE);
+ r4030_write_reg16(JAZZ_IO_IRQ_ENABLE, mask);
+ spin_unlock_irqrestore(&r4030_lock, flags);
+}
+
+#define mask_and_ack_r4030_irq disable_r4030_irq
+
+static void end_r4030_irq(unsigned int irq)
+{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+ enable_r4030_irq(irq);
+}
+
+static struct hw_interrupt_type r4030_irq_type = {
+ "R4030",
+ startup_r4030_irq,
+ shutdown_r4030_irq,
+ enable_r4030_irq,
+ disable_r4030_irq,
+ mask_and_ack_r4030_irq,
+ end_r4030_irq,
+ NULL
+};
+
+void __init init_r4030_ints(void)
+{
+ int i;
+
+ for (i = JAZZ_PARALLEL_IRQ; i <= JAZZ_TIMER_IRQ; i++) {
+ irq_desc[i].status = IRQ_DISABLED;
+ irq_desc[i].action = 0;
+ irq_desc[i].depth = 1;
+ irq_desc[i].handler = &r4030_irq_type;
+ }
+
+ r4030_write_reg16(JAZZ_IO_IRQ_ENABLE, 0);
+ r4030_read_reg16(JAZZ_IO_IRQ_SOURCE); /* clear pending IRQs */
+ r4030_read_reg32(JAZZ_R4030_INVAL_ADDR); /* clear error bits */
+}
+
+/*
+ * On systems with i8259-style interrupt controllers we assume for
+ * driver compatibility reasons interrupts 0 - 15 to be the i8259
+ * interrupts even if the hardware uses a different interrupt numbering.
+ */
+void __init arch_init_irq(void)
+{
+ set_except_vector(0, jazz_handle_int);
+
+ init_i8259_irqs(); /* Integrated i8259 */
+ init_r4030_ints();
+
+ change_c0_status(ST0_IM, IE_IRQ4 | IE_IRQ3 | IE_IRQ2 | IE_IRQ1);
+}
diff --git a/arch/mips/jazz/jazzdma.c b/arch/mips/jazz/jazzdma.c
new file mode 100644
index 0000000..46e421e
--- /dev/null
+++ b/arch/mips/jazz/jazzdma.c
@@ -0,0 +1,565 @@
+/*
+ * Mips Jazz DMA controller support
+ * Copyright (C) 1995, 1996 by Andreas Busse
+ *
+ * NOTE: Some of the argument checking could be removed when
+ * things have settled down. Also, instead of returning 0xffffffff
+ * on failure of vdma_alloc() one could leave page #0 unused
+ * and return the more usual NULL pointer as logical address.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/mm.h>
+#include <linux/bootmem.h>
+#include <linux/spinlock.h>
+#include <asm/mipsregs.h>
+#include <asm/jazz.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/dma.h>
+#include <asm/jazzdma.h>
+#include <asm/pgtable.h>
+
+/*
+ * Set this to one to enable additional vdma debug code.
+ */
+#define CONF_DEBUG_VDMA 0
+
+static unsigned long vdma_pagetable_start;
+
+static DEFINE_SPINLOCK(vdma_lock);
+
+/*
+ * Debug stuff
+ */
+#define vdma_debug ((CONF_DEBUG_VDMA) ? debuglvl : 0)
+
+static int debuglvl = 3;
+
+/*
+ * Initialize the pagetable with a one-to-one mapping of
+ * the first 16 Mbytes of main memory and declare all
+ * entries to be unused. Using this method will at least
+ * allow some early device driver operations to work.
+ */
+static inline void vdma_pgtbl_init(void)
+{
+ VDMA_PGTBL_ENTRY *pgtbl = (VDMA_PGTBL_ENTRY *) vdma_pagetable_start;
+ unsigned long paddr = 0;
+ int i;
+
+ for (i = 0; i < VDMA_PGTBL_ENTRIES; i++) {
+ pgtbl[i].frame = paddr;
+ pgtbl[i].owner = VDMA_PAGE_EMPTY;
+ paddr += VDMA_PAGESIZE;
+ }
+}
+
+/*
+ * Initialize the Jazz R4030 dma controller
+ */
+void __init vdma_init(void)
+{
+ /*
+ * Allocate 32k of memory for DMA page tables. This needs to be page
+ * aligned and should be uncached to avoid cache flushing after every
+ * update.
+ */
+ vdma_pagetable_start = alloc_bootmem_low_pages(VDMA_PGTBL_SIZE);
+ if (!vdma_pagetable_start)
+ BUG();
+ dma_cache_wback_inv(vdma_pagetable_start, VDMA_PGTBL_SIZE);
+ vdma_pagetable_start = KSEG1ADDR(vdma_pagetable_start);
+
+ /*
+ * Clear the R4030 translation table
+ */
+ vdma_pgtbl_init();
+
+ r4030_write_reg32(JAZZ_R4030_TRSTBL_BASE,
+ CPHYSADDR(vdma_pagetable_start));
+ r4030_write_reg32(JAZZ_R4030_TRSTBL_LIM, VDMA_PGTBL_SIZE);
+ r4030_write_reg32(JAZZ_R4030_TRSTBL_INV, 0);
+
+ printk("VDMA: R4030 DMA pagetables initialized.\n");
+}
+
+/*
+ * Allocate DMA pagetables using a simple first-fit algorithm
+ */
+unsigned long vdma_alloc(unsigned long paddr, unsigned long size)
+{
+ VDMA_PGTBL_ENTRY *entry = (VDMA_PGTBL_ENTRY *) vdma_pagetable_start;
+ int first, last, pages, frame, i;
+ unsigned long laddr, flags;
+
+ /* check arguments */
+
+ if (paddr > 0x1fffffff) {
+ if (vdma_debug)
+ printk("vdma_alloc: Invalid physical address: %08lx\n",
+ paddr);
+ return VDMA_ERROR; /* invalid physical address */
+ }
+ if (size > 0x400000 || size == 0) {
+ if (vdma_debug)
+ printk("vdma_alloc: Invalid size: %08lx\n", size);
+ return VDMA_ERROR; /* invalid physical address */
+ }
+
+ spin_lock_irqsave(&vdma_lock, flags);
+ /*
+ * Find free chunk
+ */
+ pages = (size + 4095) >> 12; /* no. of pages to allocate */
+ first = 0;
+ while (1) {
+ while (entry[first].owner != VDMA_PAGE_EMPTY &&
+ first < VDMA_PGTBL_ENTRIES) first++;
+ if (first + pages > VDMA_PGTBL_ENTRIES) { /* nothing free */
+ spin_unlock_irqrestore(&vdma_lock, flags);
+ return VDMA_ERROR;
+ }
+
+ last = first + 1;
+ while (entry[last].owner == VDMA_PAGE_EMPTY
+ && last - first < pages)
+ last++;
+
+ if (last - first == pages)
+ break; /* found */
+ }
+
+ /*
+ * Mark pages as allocated
+ */
+ laddr = (first << 12) + (paddr & (VDMA_PAGESIZE - 1));
+ frame = paddr & ~(VDMA_PAGESIZE - 1);
+
+ for (i = first; i < last; i++) {
+ entry[i].frame = frame;
+ entry[i].owner = laddr;
+ frame += VDMA_PAGESIZE;
+ }
+
+ /*
+ * Update translation table and return logical start address
+ */
+ r4030_write_reg32(JAZZ_R4030_TRSTBL_INV, 0);
+
+ if (vdma_debug > 1)
+ printk("vdma_alloc: Allocated %d pages starting from %08lx\n",
+ pages, laddr);
+
+ if (vdma_debug > 2) {
+ printk("LADDR: ");
+ for (i = first; i < last; i++)
+ printk("%08x ", i << 12);
+ printk("\nPADDR: ");
+ for (i = first; i < last; i++)
+ printk("%08x ", entry[i].frame);
+ printk("\nOWNER: ");
+ for (i = first; i < last; i++)
+ printk("%08x ", entry[i].owner);
+ printk("\n");
+ }
+
+ spin_unlock_irqrestore(&vdma_lock, flags);
+
+ return laddr;
+}
+
+EXPORT_SYMBOL(vdma_alloc);
+
+/*
+ * Free previously allocated dma translation pages
+ * Note that this does NOT change the translation table,
+ * it just marks the free'd pages as unused!
+ */
+int vdma_free(unsigned long laddr)
+{
+ VDMA_PGTBL_ENTRY *pgtbl = (VDMA_PGTBL_ENTRY *) vdma_pagetable_start;
+ int i;
+
+ i = laddr >> 12;
+
+ if (pgtbl[i].owner != laddr) {
+ printk
+ ("vdma_free: trying to free other's dma pages, laddr=%8lx\n",
+ laddr);
+ return -1;
+ }
+
+ while (pgtbl[i].owner == laddr && i < VDMA_PGTBL_ENTRIES) {
+ pgtbl[i].owner = VDMA_PAGE_EMPTY;
+ i++;
+ }
+
+ if (vdma_debug > 1)
+ printk("vdma_free: freed %ld pages starting from %08lx\n",
+ i - (laddr >> 12), laddr);
+
+ return 0;
+}
+
+EXPORT_SYMBOL(vdma_free);
+
+/*
+ * Map certain page(s) to another physical address.
+ * Caller must have allocated the page(s) before.
+ */
+int vdma_remap(unsigned long laddr, unsigned long paddr, unsigned long size)
+{
+ VDMA_PGTBL_ENTRY *pgtbl =
+ (VDMA_PGTBL_ENTRY *) vdma_pagetable_start;
+ int first, pages, npages;
+
+ if (laddr > 0xffffff) {
+ if (vdma_debug)
+ printk
+ ("vdma_map: Invalid logical address: %08lx\n",
+ laddr);
+ return -EINVAL; /* invalid logical address */
+ }
+ if (paddr > 0x1fffffff) {
+ if (vdma_debug)
+ printk
+ ("vdma_map: Invalid physical address: %08lx\n",
+ paddr);
+ return -EINVAL; /* invalid physical address */
+ }
+
+ npages = pages =
+ (((paddr & (VDMA_PAGESIZE - 1)) + size) >> 12) + 1;
+ first = laddr >> 12;
+ if (vdma_debug)
+ printk("vdma_remap: first=%x, pages=%x\n", first, pages);
+ if (first + pages > VDMA_PGTBL_ENTRIES) {
+ if (vdma_debug)
+ printk("vdma_alloc: Invalid size: %08lx\n", size);
+ return -EINVAL;
+ }
+
+ paddr &= ~(VDMA_PAGESIZE - 1);
+ while (pages > 0 && first < VDMA_PGTBL_ENTRIES) {
+ if (pgtbl[first].owner != laddr) {
+ if (vdma_debug)
+ printk("Trying to remap other's pages.\n");
+ return -EPERM; /* not owner */
+ }
+ pgtbl[first].frame = paddr;
+ paddr += VDMA_PAGESIZE;
+ first++;
+ pages--;
+ }
+
+ /*
+ * Update translation table
+ */
+ r4030_write_reg32(JAZZ_R4030_TRSTBL_INV, 0);
+
+ if (vdma_debug > 2) {
+ int i;
+ pages = (((paddr & (VDMA_PAGESIZE - 1)) + size) >> 12) + 1;
+ first = laddr >> 12;
+ printk("LADDR: ");
+ for (i = first; i < first + pages; i++)
+ printk("%08x ", i << 12);
+ printk("\nPADDR: ");
+ for (i = first; i < first + pages; i++)
+ printk("%08x ", pgtbl[i].frame);
+ printk("\nOWNER: ");
+ for (i = first; i < first + pages; i++)
+ printk("%08x ", pgtbl[i].owner);
+ printk("\n");
+ }
+
+ return 0;
+}
+
+/*
+ * Translate a physical address to a logical address.
+ * This will return the logical address of the first
+ * match.
+ */
+unsigned long vdma_phys2log(unsigned long paddr)
+{
+ int i;
+ int frame;
+ VDMA_PGTBL_ENTRY *pgtbl =
+ (VDMA_PGTBL_ENTRY *) vdma_pagetable_start;
+
+ frame = paddr & ~(VDMA_PAGESIZE - 1);
+
+ for (i = 0; i < VDMA_PGTBL_ENTRIES; i++) {
+ if (pgtbl[i].frame == frame)
+ break;
+ }
+
+ if (i == VDMA_PGTBL_ENTRIES)
+ return ~0UL;
+
+ return (i << 12) + (paddr & (VDMA_PAGESIZE - 1));
+}
+
+EXPORT_SYMBOL(vdma_phys2log);
+
+/*
+ * Translate a logical DMA address to a physical address
+ */
+unsigned long vdma_log2phys(unsigned long laddr)
+{
+ VDMA_PGTBL_ENTRY *pgtbl =
+ (VDMA_PGTBL_ENTRY *) vdma_pagetable_start;
+
+ return pgtbl[laddr >> 12].frame + (laddr & (VDMA_PAGESIZE - 1));
+}
+
+EXPORT_SYMBOL(vdma_log2phys);
+
+/*
+ * Print DMA statistics
+ */
+void vdma_stats(void)
+{
+ int i;
+
+ printk("vdma_stats: CONFIG: %08x\n",
+ r4030_read_reg32(JAZZ_R4030_CONFIG));
+ printk("R4030 translation table base: %08x\n",
+ r4030_read_reg32(JAZZ_R4030_TRSTBL_BASE));
+ printk("R4030 translation table limit: %08x\n",
+ r4030_read_reg32(JAZZ_R4030_TRSTBL_LIM));
+ printk("vdma_stats: INV_ADDR: %08x\n",
+ r4030_read_reg32(JAZZ_R4030_INV_ADDR));
+ printk("vdma_stats: R_FAIL_ADDR: %08x\n",
+ r4030_read_reg32(JAZZ_R4030_R_FAIL_ADDR));
+ printk("vdma_stats: M_FAIL_ADDR: %08x\n",
+ r4030_read_reg32(JAZZ_R4030_M_FAIL_ADDR));
+ printk("vdma_stats: IRQ_SOURCE: %08x\n",
+ r4030_read_reg32(JAZZ_R4030_IRQ_SOURCE));
+ printk("vdma_stats: I386_ERROR: %08x\n",
+ r4030_read_reg32(JAZZ_R4030_I386_ERROR));
+ printk("vdma_chnl_modes: ");
+ for (i = 0; i < 8; i++)
+ printk("%04x ",
+ (unsigned) r4030_read_reg32(JAZZ_R4030_CHNL_MODE +
+ (i << 5)));
+ printk("\n");
+ printk("vdma_chnl_enables: ");
+ for (i = 0; i < 8; i++)
+ printk("%04x ",
+ (unsigned) r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE +
+ (i << 5)));
+ printk("\n");
+}
+
+/*
+ * DMA transfer functions
+ */
+
+/*
+ * Enable a DMA channel. Also clear any error conditions.
+ */
+void vdma_enable(int channel)
+{
+ int status;
+
+ if (vdma_debug)
+ printk("vdma_enable: channel %d\n", channel);
+
+ /*
+ * Check error conditions first
+ */
+ status = r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE + (channel << 5));
+ if (status & 0x400)
+ printk("VDMA: Channel %d: Address error!\n", channel);
+ if (status & 0x200)
+ printk("VDMA: Channel %d: Memory error!\n", channel);
+
+ /*
+ * Clear all interrupt flags
+ */
+ r4030_write_reg32(JAZZ_R4030_CHNL_ENABLE + (channel << 5),
+ r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE +
+ (channel << 5)) | R4030_TC_INTR
+ | R4030_MEM_INTR | R4030_ADDR_INTR);
+
+ /*
+ * Enable the desired channel
+ */
+ r4030_write_reg32(JAZZ_R4030_CHNL_ENABLE + (channel << 5),
+ r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE +
+ (channel << 5)) |
+ R4030_CHNL_ENABLE);
+}
+
+EXPORT_SYMBOL(vdma_enable);
+
+/*
+ * Disable a DMA channel
+ */
+void vdma_disable(int channel)
+{
+ if (vdma_debug) {
+ int status =
+ r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE +
+ (channel << 5));
+
+ printk("vdma_disable: channel %d\n", channel);
+ printk("VDMA: channel %d status: %04x (%s) mode: "
+ "%02x addr: %06x count: %06x\n",
+ channel, status,
+ ((status & 0x600) ? "ERROR" : "OK"),
+ (unsigned) r4030_read_reg32(JAZZ_R4030_CHNL_MODE +
+ (channel << 5)),
+ (unsigned) r4030_read_reg32(JAZZ_R4030_CHNL_ADDR +
+ (channel << 5)),
+ (unsigned) r4030_read_reg32(JAZZ_R4030_CHNL_COUNT +
+ (channel << 5)));
+ }
+
+ r4030_write_reg32(JAZZ_R4030_CHNL_ENABLE + (channel << 5),
+ r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE +
+ (channel << 5)) &
+ ~R4030_CHNL_ENABLE);
+
+ /*
+ * After disabling a DMA channel a remote bus register should be
+ * read to ensure that the current DMA acknowledge cycle is completed.
+ */
+ *((volatile unsigned int *) JAZZ_DUMMY_DEVICE);
+}
+
+EXPORT_SYMBOL(vdma_disable);
+
+/*
+ * Set DMA mode. This function accepts the mode values used
+ * to set a PC-style DMA controller. For the SCSI and FDC
+ * channels, we also set the default modes each time we're
+ * called.
+ * NOTE: The FAST and BURST dma modes are supported by the
+ * R4030 Rev. 2 and PICA chipsets only. I leave them disabled
+ * for now.
+ */
+void vdma_set_mode(int channel, int mode)
+{
+ if (vdma_debug)
+ printk("vdma_set_mode: channel %d, mode 0x%x\n", channel,
+ mode);
+
+ switch (channel) {
+ case JAZZ_SCSI_DMA: /* scsi */
+ r4030_write_reg32(JAZZ_R4030_CHNL_MODE + (channel << 5),
+/* R4030_MODE_FAST | */
+/* R4030_MODE_BURST | */
+ R4030_MODE_INTR_EN |
+ R4030_MODE_WIDTH_16 |
+ R4030_MODE_ATIME_80);
+ break;
+
+ case JAZZ_FLOPPY_DMA: /* floppy */
+ r4030_write_reg32(JAZZ_R4030_CHNL_MODE + (channel << 5),
+/* R4030_MODE_FAST | */
+/* R4030_MODE_BURST | */
+ R4030_MODE_INTR_EN |
+ R4030_MODE_WIDTH_8 |
+ R4030_MODE_ATIME_120);
+ break;
+
+ case JAZZ_AUDIOL_DMA:
+ case JAZZ_AUDIOR_DMA:
+ printk("VDMA: Audio DMA not supported yet.\n");
+ break;
+
+ default:
+ printk
+ ("VDMA: vdma_set_mode() called with unsupported channel %d!\n",
+ channel);
+ }
+
+ switch (mode) {
+ case DMA_MODE_READ:
+ r4030_write_reg32(JAZZ_R4030_CHNL_ENABLE + (channel << 5),
+ r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE +
+ (channel << 5)) &
+ ~R4030_CHNL_WRITE);
+ break;
+
+ case DMA_MODE_WRITE:
+ r4030_write_reg32(JAZZ_R4030_CHNL_ENABLE + (channel << 5),
+ r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE +
+ (channel << 5)) |
+ R4030_CHNL_WRITE);
+ break;
+
+ default:
+ printk
+ ("VDMA: vdma_set_mode() called with unknown dma mode 0x%x\n",
+ mode);
+ }
+}
+
+EXPORT_SYMBOL(vdma_set_mode);
+
+/*
+ * Set Transfer Address
+ */
+void vdma_set_addr(int channel, long addr)
+{
+ if (vdma_debug)
+ printk("vdma_set_addr: channel %d, addr %lx\n", channel,
+ addr);
+
+ r4030_write_reg32(JAZZ_R4030_CHNL_ADDR + (channel << 5), addr);
+}
+
+EXPORT_SYMBOL(vdma_set_addr);
+
+/*
+ * Set Transfer Count
+ */
+void vdma_set_count(int channel, int count)
+{
+ if (vdma_debug)
+ printk("vdma_set_count: channel %d, count %08x\n", channel,
+ (unsigned) count);
+
+ r4030_write_reg32(JAZZ_R4030_CHNL_COUNT + (channel << 5), count);
+}
+
+EXPORT_SYMBOL(vdma_set_count);
+
+/*
+ * Get Residual
+ */
+int vdma_get_residue(int channel)
+{
+ int residual;
+
+ residual = r4030_read_reg32(JAZZ_R4030_CHNL_COUNT + (channel << 5));
+
+ if (vdma_debug)
+ printk("vdma_get_residual: channel %d: residual=%d\n",
+ channel, residual);
+
+ return residual;
+}
+
+/*
+ * Get DMA channel enable register
+ */
+int vdma_get_enable(int channel)
+{
+ int enable;
+
+ enable = r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE + (channel << 5));
+
+ if (vdma_debug)
+ printk("vdma_get_enable: channel %d: enable=%d\n", channel,
+ enable);
+
+ return enable;
+}
diff --git a/arch/mips/jazz/reset.c b/arch/mips/jazz/reset.c
new file mode 100644
index 0000000..2a97547
--- /dev/null
+++ b/arch/mips/jazz/reset.c
@@ -0,0 +1,69 @@
+/*
+ * Reset a Jazz machine.
+ *
+ * We don't trust the firmware so we do it the classic way by poking and
+ * stabbing at the keyboard controller ...
+ */
+#include <linux/jiffies.h>
+#include <asm/jazz.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/reboot.h>
+#include <asm/delay.h>
+
+#define KBD_STAT_IBF 0x02 /* Keyboard input buffer full */
+
+static void jazz_write_output(unsigned char val)
+{
+ int status;
+
+ do {
+ status = jazz_kh->command;
+ } while (status & KBD_STAT_IBF);
+ jazz_kh->data = val;
+}
+
+static void jazz_write_command(unsigned char val)
+{
+ int status;
+
+ do {
+ status = jazz_kh->command;
+ } while (status & KBD_STAT_IBF);
+ jazz_kh->command = val;
+}
+
+static unsigned char jazz_read_status(void)
+{
+ return jazz_kh->command;
+}
+
+static inline void kb_wait(void)
+{
+ unsigned long start = jiffies;
+ unsigned long timeout = start + HZ/2;
+
+ do {
+ if (! (jazz_read_status() & 0x02))
+ return;
+ } while (time_before_eq(jiffies, timeout));
+}
+
+void jazz_machine_restart(char *command)
+{
+ while(1) {
+ kb_wait();
+ jazz_write_command (0xd1);
+ kb_wait();
+ jazz_write_output (0x00);
+ }
+}
+
+void jazz_machine_halt(void)
+{
+}
+
+void jazz_machine_power_off(void)
+{
+ /* Jazz machines don't have a software power switch */
+}
diff --git a/arch/mips/jazz/setup.c b/arch/mips/jazz/setup.c
new file mode 100644
index 0000000..fccb06f
--- /dev/null
+++ b/arch/mips/jazz/setup.c
@@ -0,0 +1,101 @@
+/*
+ * Setup pointers to hardware-dependent routines.
+ *
+ * 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) 1996, 1997, 1998, 2001 by Ralf Baechle
+ * Copyright (C) 2001 MIPS Technologies, Inc.
+ */
+#include <linux/config.h>
+#include <linux/eisa.h>
+#include <linux/hdreg.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/mm.h>
+#include <linux/console.h>
+#include <linux/fb.h>
+#include <linux/ide.h>
+#include <asm/bootinfo.h>
+#include <asm/irq.h>
+#include <asm/jazz.h>
+#include <asm/jazzdma.h>
+#include <asm/ptrace.h>
+#include <asm/reboot.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/time.h>
+#include <asm/traps.h>
+
+extern asmlinkage void jazz_handle_int(void);
+
+extern void jazz_machine_restart(char *command);
+extern void jazz_machine_halt(void);
+extern void jazz_machine_power_off(void);
+
+static void __init jazz_time_init(struct irqaction *irq)
+{
+ /* set the clock to 100 Hz */
+ r4030_write_reg32(JAZZ_TIMER_INTERVAL, 9);
+ setup_irq(JAZZ_TIMER_IRQ, irq);
+}
+
+static struct resource jazz_io_resources[] = {
+ { "dma1", 0x00, 0x1f, IORESOURCE_BUSY },
+ { "timer", 0x40, 0x5f, IORESOURCE_BUSY },
+ { "dma page reg", 0x80, 0x8f, IORESOURCE_BUSY },
+ { "dma2", 0xc0, 0xdf, IORESOURCE_BUSY },
+};
+
+static void __init jazz_setup(void)
+{
+ int i;
+
+ /* Map 0xe0000000 -> 0x0:800005C0, 0xe0010000 -> 0x1:30000580 */
+ add_wired_entry (0x02000017, 0x03c00017, 0xe0000000, PM_64K);
+
+ /* Map 0xe2000000 -> 0x0:900005C0, 0xe3010000 -> 0x0:910005C0 */
+ add_wired_entry (0x02400017, 0x02440017, 0xe2000000, PM_16M);
+
+ /* Map 0xe4000000 -> 0x0:600005C0, 0xe4100000 -> 400005C0 */
+ add_wired_entry (0x01800017, 0x01000017, 0xe4000000, PM_4M);
+
+ set_io_port_base(JAZZ_PORT_BASE);
+#ifdef CONFIG_EISA
+ if (mips_machtype == MACH_MIPS_MAGNUM_4000)
+ EISA_bus = 1;
+#endif
+ isa_slot_offset = 0xe3000000;
+
+ /* request I/O space for devices used on all i[345]86 PCs */
+ for (i = 0; i < ARRAY_SIZE(jazz_io_resources); i++)
+ request_resource(&ioport_resource, jazz_io_resources + i);
+
+ board_timer_setup = jazz_time_init;
+ /* The RTC is outside the port address space */
+
+ _machine_restart = jazz_machine_restart;
+ _machine_halt = jazz_machine_halt;
+ _machine_power_off = jazz_machine_power_off;
+
+#warning "Somebody should check if screen_info is ok for Jazz."
+
+ screen_info = (struct screen_info) {
+ 0, 0, /* orig-x, orig-y */
+ 0, /* unused */
+ 0, /* orig_video_page */
+ 0, /* orig_video_mode */
+ 160, /* orig_video_cols */
+ 0, 0, 0, /* unused, ega_bx, unused */
+ 64, /* orig_video_lines */
+ 0, /* orig_video_isVGA */
+ 16 /* orig_video_points */
+ };
+
+ vdma_init();
+}
+
+early_initcall(jazz_setup);
diff --git a/arch/mips/jmr3927/common/Makefile b/arch/mips/jmr3927/common/Makefile
new file mode 100644
index 0000000..cb09a8e
--- /dev/null
+++ b/arch/mips/jmr3927/common/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for the common code of TOSHIBA JMR-TX3927 board
+#
+
+obj-y += prom.o puts.o rtc_ds1742.o
diff --git a/arch/mips/jmr3927/common/prom.c b/arch/mips/jmr3927/common/prom.c
new file mode 100644
index 0000000..5d5838f
--- /dev/null
+++ b/arch/mips/jmr3927/common/prom.c
@@ -0,0 +1,81 @@
+/*
+ * BRIEF MODULE DESCRIPTION
+ * PROM library initialisation code, assuming a version of
+ * pmon is the boot code.
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ * ahennessy@mvista.com
+ *
+ * Based on arch/mips/au1000/common/prom.c
+ *
+ * This file was derived from Carsten Langgaard's
+ * arch/mips/mips-boards/xx files.
+ *
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/string.h>
+
+#include <asm/bootinfo.h>
+
+extern int prom_argc;
+extern char **prom_argv, **prom_envp;
+
+typedef struct
+{
+ char *name;
+/* char *val; */
+}t_env_var;
+
+
+char * __init prom_getcmdline(void)
+{
+ return &(arcs_cmdline[0]);
+}
+
+void __init prom_init_cmdline(void)
+{
+ char *cp;
+ int actr;
+
+ actr = 1; /* Always ignore argv[0] */
+
+ cp = &(arcs_cmdline[0]);
+ while(actr < prom_argc) {
+ strcpy(cp, prom_argv[actr]);
+ cp += strlen(prom_argv[actr]);
+ *cp++ = ' ';
+ actr++;
+ }
+ if (cp != &(arcs_cmdline[0])) /* get rid of trailing space */
+ --cp;
+ *cp = '\0';
+}
+
+unsigned long __init prom_free_prom_memory(void)
+{
+ return 0;
+}
diff --git a/arch/mips/jmr3927/common/puts.c b/arch/mips/jmr3927/common/puts.c
new file mode 100644
index 0000000..1c1cad9
--- /dev/null
+++ b/arch/mips/jmr3927/common/puts.c
@@ -0,0 +1,168 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ * Low level uart routines to directly access a TX[34]927 SIO.
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ * ahennessy@mvista.com or source@mvista.com
+ *
+ * Copyright (C) 2000-2001 Toshiba Corporation
+ *
+ * Based on arch/mips/au1000/common/puts.c
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/types.h>
+#include <asm/jmr3927/txx927.h>
+#include <asm/jmr3927/tx3927.h>
+#include <asm/jmr3927/jmr3927.h>
+
+#define TIMEOUT 0xffffff
+#define SLOW_DOWN
+
+static const char digits[16] = "0123456789abcdef";
+
+#ifdef SLOW_DOWN
+#define slow_down() { int k; for (k=0; k<10000; k++); }
+#else
+#define slow_down()
+#endif
+
+void
+putch(const unsigned char c)
+{
+ int i = 0;
+
+ do {
+ slow_down();
+ i++;
+ if (i>TIMEOUT) {
+ break;
+ }
+ } while (!(tx3927_sioptr(1)->cisr & TXx927_SICISR_TXALS));
+ tx3927_sioptr(1)->tfifo = c;
+ return;
+}
+
+unsigned char getch(void)
+{
+ int i = 0;
+ int dicr;
+ char c;
+
+ /* diable RX int. */
+ dicr = tx3927_sioptr(1)->dicr;
+ tx3927_sioptr(1)->dicr = 0;
+
+ do {
+ slow_down();
+ i++;
+ if (i>TIMEOUT) {
+ break;
+ }
+ } while (tx3927_sioptr(1)->disr & TXx927_SIDISR_UVALID)
+ ;
+ c = tx3927_sioptr(1)->rfifo;
+
+ /* clear RX int. status */
+ tx3927_sioptr(1)->disr &= ~TXx927_SIDISR_RDIS;
+ /* enable RX int. */
+ tx3927_sioptr(1)->dicr = dicr;
+
+ return c;
+}
+void
+do_jmr3927_led_set(char n)
+{
+ /* and with current leds */
+ jmr3927_led_and_set(n);
+}
+
+void
+puts(unsigned char *cp)
+{
+ int i = 0;
+
+ while (*cp) {
+ do {
+ slow_down();
+ i++;
+ if (i>TIMEOUT) {
+ break;
+ }
+ } while (!(tx3927_sioptr(1)->cisr & TXx927_SICISR_TXALS));
+ tx3927_sioptr(1)->tfifo = *cp++;
+ }
+ putch('\r');
+ putch('\n');
+}
+
+void
+fputs(unsigned char *cp)
+{
+ int i = 0;
+
+ while (*cp) {
+ do {
+ slow_down();
+ i++;
+ if (i>TIMEOUT) {
+ break;
+ }
+ } while (!(tx3927_sioptr(1)->cisr & TXx927_SICISR_TXALS));
+ tx3927_sioptr(1)->tfifo = *cp++;
+ }
+}
+
+
+void
+put64(uint64_t ul)
+{
+ int cnt;
+ unsigned ch;
+
+ cnt = 16; /* 16 nibbles in a 64 bit long */
+ putch('0');
+ putch('x');
+ do {
+ cnt--;
+ ch = (unsigned char)(ul >> cnt * 4) & 0x0F;
+ putch(digits[ch]);
+ } while (cnt > 0);
+}
+
+void
+put32(unsigned u)
+{
+ int cnt;
+ unsigned ch;
+
+ cnt = 8; /* 8 nibbles in a 32 bit long */
+ putch('0');
+ putch('x');
+ do {
+ cnt--;
+ ch = (unsigned char)(u >> cnt * 4) & 0x0F;
+ putch(digits[ch]);
+ } while (cnt > 0);
+}
diff --git a/arch/mips/jmr3927/common/rtc_ds1742.c b/arch/mips/jmr3927/common/rtc_ds1742.c
new file mode 100644
index 0000000..1ae4318
--- /dev/null
+++ b/arch/mips/jmr3927/common/rtc_ds1742.c
@@ -0,0 +1,165 @@
+/*
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ * ahennessy@mvista.com
+ *
+ * arch/mips/jmr3927/common/rtc_ds1742.c
+ * Based on arch/mips/ddb5xxx/common/rtc_ds1386.c
+ * low-level RTC hookups for s for Dallas 1742 chip.
+ *
+ * Copyright (C) 2000-2001 Toshiba Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+/*
+ * This file exports a function, rtc_ds1386_init(), which expects an
+ * uncached base address as the argument. It will set the two function
+ * pointers expected by the MIPS generic timer code.
+ */
+
+#include <linux/bcd.h>
+#include <linux/types.h>
+#include <linux/time.h>
+#include <linux/rtc.h>
+
+#include <asm/time.h>
+#include <asm/addrspace.h>
+
+#include <asm/jmr3927/ds1742rtc.h>
+#include <asm/debug.h>
+
+#define EPOCH 2000
+
+static unsigned long rtc_base;
+
+static unsigned long
+rtc_ds1742_get_time(void)
+{
+ unsigned int year, month, day, hour, minute, second;
+ unsigned int century;
+
+ CMOS_WRITE(RTC_READ, RTC_CONTROL);
+ second = BCD2BIN(CMOS_READ(RTC_SECONDS) & RTC_SECONDS_MASK);
+ minute = BCD2BIN(CMOS_READ(RTC_MINUTES));
+ hour = BCD2BIN(CMOS_READ(RTC_HOURS));
+ day = BCD2BIN(CMOS_READ(RTC_DATE));
+ month = BCD2BIN(CMOS_READ(RTC_MONTH));
+ year = BCD2BIN(CMOS_READ(RTC_YEAR));
+ century = BCD2BIN(CMOS_READ(RTC_CENTURY) & RTC_CENTURY_MASK);
+ CMOS_WRITE(0, RTC_CONTROL);
+
+ year += century * 100;
+
+ return mktime(year, month, day, hour, minute, second);
+}
+extern void to_tm(unsigned long tim, struct rtc_time * tm);
+
+static int
+rtc_ds1742_set_time(unsigned long t)
+{
+ struct rtc_time tm;
+ u8 year, month, day, hour, minute, second;
+ u8 cmos_year, cmos_month, cmos_day, cmos_hour, cmos_minute, cmos_second;
+ int cmos_century;
+
+ CMOS_WRITE(RTC_READ, RTC_CONTROL);
+ cmos_second = (u8)(CMOS_READ(RTC_SECONDS) & RTC_SECONDS_MASK);
+ cmos_minute = (u8)CMOS_READ(RTC_MINUTES);
+ cmos_hour = (u8)CMOS_READ(RTC_HOURS);
+ cmos_day = (u8)CMOS_READ(RTC_DATE);
+ cmos_month = (u8)CMOS_READ(RTC_MONTH);
+ cmos_year = (u8)CMOS_READ(RTC_YEAR);
+ cmos_century = CMOS_READ(RTC_CENTURY) & RTC_CENTURY_MASK;
+
+ CMOS_WRITE(RTC_WRITE, RTC_CONTROL);
+
+ /* convert */
+ to_tm(t, &tm);
+
+ /* check each field one by one */
+ year = BIN2BCD(tm.tm_year - EPOCH);
+ if (year != cmos_year) {
+ CMOS_WRITE(year,RTC_YEAR);
+ }
+
+ month = BIN2BCD(tm.tm_mon);
+ if (month != (cmos_month & 0x1f)) {
+ CMOS_WRITE((month & 0x1f) | (cmos_month & ~0x1f),RTC_MONTH);
+ }
+
+ day = BIN2BCD(tm.tm_mday);
+ if (day != cmos_day) {
+
+ CMOS_WRITE(day, RTC_DATE);
+ }
+
+ if (cmos_hour & 0x40) {
+ /* 12 hour format */
+ hour = 0x40;
+ if (tm.tm_hour > 12) {
+ hour |= 0x20 | (BIN2BCD(hour-12) & 0x1f);
+ } else {
+ hour |= BIN2BCD(tm.tm_hour);
+ }
+ } else {
+ /* 24 hour format */
+ hour = BIN2BCD(tm.tm_hour) & 0x3f;
+ }
+ if (hour != cmos_hour) CMOS_WRITE(hour, RTC_HOURS);
+
+ minute = BIN2BCD(tm.tm_min);
+ if (minute != cmos_minute) {
+ CMOS_WRITE(minute, RTC_MINUTES);
+ }
+
+ second = BIN2BCD(tm.tm_sec);
+ if (second != cmos_second) {
+ CMOS_WRITE(second & RTC_SECONDS_MASK,RTC_SECONDS);
+ }
+
+ /* RTC_CENTURY and RTC_CONTROL share same address... */
+ CMOS_WRITE(cmos_century, RTC_CONTROL);
+
+ return 0;
+}
+
+void
+rtc_ds1742_init(unsigned long base)
+{
+ u8 cmos_second;
+
+ /* remember the base */
+ rtc_base = base;
+ db_assert((rtc_base & 0xe0000000) == KSEG1);
+
+ /* set the function pointers */
+ rtc_get_time = rtc_ds1742_get_time;
+ rtc_set_time = rtc_ds1742_set_time;
+
+ /* clear oscillator stop bit */
+ CMOS_WRITE(RTC_READ, RTC_CONTROL);
+ cmos_second = (u8)(CMOS_READ(RTC_SECONDS) & RTC_SECONDS_MASK);
+ CMOS_WRITE(RTC_WRITE, RTC_CONTROL);
+ CMOS_WRITE(cmos_second, RTC_SECONDS); /* clear msb */
+ CMOS_WRITE(0, RTC_CONTROL);
+}
diff --git a/arch/mips/jmr3927/rbhma3100/Makefile b/arch/mips/jmr3927/rbhma3100/Makefile
new file mode 100644
index 0000000..75bf418
--- /dev/null
+++ b/arch/mips/jmr3927/rbhma3100/Makefile
@@ -0,0 +1,9 @@
+#
+# Makefile for TOSHIBA JMR-TX3927 board
+#
+
+obj-y += init.o int-handler.o irq.o setup.o
+obj-$(CONFIG_RUNTIME_DEBUG) += debug.o
+obj-$(CONFIG_KGDB) += kgdb_io.o
+
+EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/jmr3927/rbhma3100/init.c b/arch/mips/jmr3927/rbhma3100/init.c
new file mode 100644
index 0000000..a0674d7
--- /dev/null
+++ b/arch/mips/jmr3927/rbhma3100/init.c
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ * ahennessy@mvista.com
+ *
+ * arch/mips/jmr3927/common/init.c
+ *
+ * Copyright (C) 2000-2001 Toshiba Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/bootmem.h>
+
+#include <asm/addrspace.h>
+#include <asm/bootinfo.h>
+#include <asm/mipsregs.h>
+#include <asm/jmr3927/jmr3927.h>
+
+int prom_argc;
+char **prom_argv, **prom_envp;
+extern void __init prom_init_cmdline(void);
+extern char *prom_getenv(char *envname);
+unsigned long mips_nofpu = 0;
+
+const char *get_system_type(void)
+{
+ return "Toshiba"
+#ifdef CONFIG_TOSHIBA_JMR3927
+ " JMR_TX3927"
+#endif
+ ;
+}
+
+extern void puts(unsigned char *cp);
+
+void __init prom_init(void)
+{
+#ifdef CONFIG_TOSHIBA_JMR3927
+ /* CCFG */
+ if ((tx3927_ccfgptr->ccfg & TX3927_CCFG_TLBOFF) == 0)
+ puts("Warning: TX3927 TLB off\n");
+#endif
+ prom_argc = fw_arg0;
+ prom_argv = (char **) fw_arg1;
+ prom_envp = (char **) fw_arg2;
+
+ mips_machgroup = MACH_GROUP_TOSHIBA;
+
+#ifdef CONFIG_TOSHIBA_JMR3927
+ mips_machtype = MACH_TOSHIBA_JMR3927;
+#endif
+
+ prom_init_cmdline();
+ add_memory_region(0, JMR3927_SDRAM_SIZE, BOOT_MEM_RAM);
+}
diff --git a/arch/mips/jmr3927/rbhma3100/int-handler.S b/arch/mips/jmr3927/rbhma3100/int-handler.S
new file mode 100644
index 0000000..f85bbf4
--- /dev/null
+++ b/arch/mips/jmr3927/rbhma3100/int-handler.S
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ * ahennessy@mvista.com
+ *
+ * Based on arch/mips/tsdb/kernel/int-handler.S
+ *
+ * Copyright (C) 2000-2001 Toshiba Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <asm/asm.h>
+#include <asm/mipsregs.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+#include <asm/jmr3927/jmr3927.h>
+
+ /* A lot of complication here is taken away because:
+ *
+ * 1) We handle one interrupt and return, sitting in a loop
+ * and moving across all the pending IRQ bits in the cause
+ * register is _NOT_ the answer, the common case is one
+ * pending IRQ so optimize in that direction.
+ *
+ * 2) We need not check against bits in the status register
+ * IRQ mask, that would make this routine slow as hell.
+ *
+ * 3) Linux only thinks in terms of all IRQs on or all IRQs
+ * off, nothing in between like BSD spl() brain-damage.
+ *
+ */
+
+/* Flush write buffer (needed?)
+ * NOTE: TX39xx performs "non-blocking load", so explicitly use the target
+ * register of LBU to flush immediately.
+ */
+#define FLUSH_WB(tmp) \
+ la tmp, JMR3927_IOC_REV_ADDR; \
+ lbu tmp, (tmp); \
+ move tmp, zero;
+
+ .text
+ .set noreorder
+ .set noat
+ .align 5
+ NESTED(jmr3927_IRQ, PT_SIZE, sp)
+ SAVE_ALL
+ CLI
+ .set at
+ jal jmr3927_irc_irqdispatch
+ move a0, sp
+ FLUSH_WB(t0)
+ j ret_from_irq
+ nop
+ END(jmr3927_IRQ)
diff --git a/arch/mips/jmr3927/rbhma3100/irq.c b/arch/mips/jmr3927/rbhma3100/irq.c
new file mode 100644
index 0000000..b9799b8
--- /dev/null
+++ b/arch/mips/jmr3927/rbhma3100/irq.c
@@ -0,0 +1,466 @@
+/*
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ * ahennessy@mvista.com
+ *
+ * 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) 2000-2001 Toshiba Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+
+#include <linux/errno.h>
+#include <linux/irq.h>
+#include <linux/kernel_stat.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/timex.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/bitops.h>
+
+#include <asm/io.h>
+#include <asm/mipsregs.h>
+#include <asm/system.h>
+
+#include <asm/ptrace.h>
+#include <asm/processor.h>
+#include <asm/jmr3927/irq.h>
+#include <asm/debug.h>
+#include <asm/jmr3927/jmr3927.h>
+
+#if JMR3927_IRQ_END > NR_IRQS
+#error JMR3927_IRQ_END > NR_IRQS
+#endif
+
+struct tb_irq_space* tb_irq_spaces;
+
+static int jmr3927_irq_base = -1;
+
+#ifdef CONFIG_PCI
+static int jmr3927_gen_iack(void)
+{
+ /* generate ACK cycle */
+#ifdef __BIG_ENDIAN
+ return (tx3927_pcicptr->iiadp >> 24) & 0xff;
+#else
+ return tx3927_pcicptr->iiadp & 0xff;
+#endif
+}
+#endif
+
+extern asmlinkage void jmr3927_IRQ(void);
+
+#define irc_dlevel 0
+#define irc_elevel 1
+
+static unsigned char irc_level[TX3927_NUM_IR] = {
+ 5, 5, 5, 5, 5, 5, /* INT[5:0] */
+ 7, 7, /* SIO */
+ 5, 5, 5, 0, 0, /* DMA, PIO, PCI */
+ 6, 6, 6 /* TMR */
+};
+
+static void jmr3927_irq_disable(unsigned int irq_nr);
+static void jmr3927_irq_enable(unsigned int irq_nr);
+
+static DEFINE_SPINLOCK(jmr3927_irq_lock);
+
+static unsigned int jmr3927_irq_startup(unsigned int irq)
+{
+ jmr3927_irq_enable(irq);
+
+ return 0;
+}
+
+#define jmr3927_irq_shutdown jmr3927_irq_disable
+
+static void jmr3927_irq_ack(unsigned int irq)
+{
+ if (irq == JMR3927_IRQ_IRC_TMR0)
+ jmr3927_tmrptr->tisr = 0; /* ack interrupt */
+
+ jmr3927_irq_disable(irq);
+}
+
+static void jmr3927_irq_end(unsigned int irq)
+{
+ jmr3927_irq_enable(irq);
+}
+
+static void jmr3927_irq_disable(unsigned int irq_nr)
+{
+ struct tb_irq_space* sp;
+ unsigned long flags;
+
+ spinlock_irqsave(&jmr3927_irq_lock, flags);
+ for (sp = tb_irq_spaces; sp; sp = sp->next) {
+ if (sp->start_irqno <= irq_nr &&
+ irq_nr < sp->start_irqno + sp->nr_irqs) {
+ if (sp->mask_func)
+ sp->mask_func(irq_nr - sp->start_irqno,
+ sp->space_id);
+ break;
+ }
+ }
+ spinlock_irqrestore(&jmr3927_irq_lock, flags);
+}
+
+static void jmr3927_irq_enable(unsigned int irq_nr)
+{
+ struct tb_irq_space* sp;
+ unsigned long flags;
+
+ spinlock_irqsave(&jmr3927_irq_lock, flags);
+ for (sp = tb_irq_spaces; sp; sp = sp->next) {
+ if (sp->start_irqno <= irq_nr &&
+ irq_nr < sp->start_irqno + sp->nr_irqs) {
+ if (sp->unmask_func)
+ sp->unmask_func(irq_nr - sp->start_irqno,
+ sp->space_id);
+ break;
+ }
+ }
+ spinlock_irqrestore(&jmr3927_irq_lock, flags);
+}
+
+/*
+ * CP0_STATUS is a thread's resource (saved/restored on context switch).
+ * So disable_irq/enable_irq MUST handle IOC/ISAC/IRC registers.
+ */
+static void mask_irq_isac(int irq_nr, int space_id)
+{
+ /* 0: mask */
+ unsigned char imask =
+ jmr3927_isac_reg_in(JMR3927_ISAC_INTM_ADDR);
+ unsigned int bit = 1 << irq_nr;
+ jmr3927_isac_reg_out(imask & ~bit, JMR3927_ISAC_INTM_ADDR);
+ /* flush write buffer */
+ (void)jmr3927_ioc_reg_in(JMR3927_IOC_REV_ADDR);
+}
+static void unmask_irq_isac(int irq_nr, int space_id)
+{
+ /* 0: mask */
+ unsigned char imask = jmr3927_isac_reg_in(JMR3927_ISAC_INTM_ADDR);
+ unsigned int bit = 1 << irq_nr;
+ jmr3927_isac_reg_out(imask | bit, JMR3927_ISAC_INTM_ADDR);
+ /* flush write buffer */
+ (void)jmr3927_ioc_reg_in(JMR3927_IOC_REV_ADDR);
+}
+
+static void mask_irq_ioc(int irq_nr, int space_id)
+{
+ /* 0: mask */
+ unsigned char imask = jmr3927_ioc_reg_in(JMR3927_IOC_INTM_ADDR);
+ unsigned int bit = 1 << irq_nr;
+ jmr3927_ioc_reg_out(imask & ~bit, JMR3927_IOC_INTM_ADDR);
+ /* flush write buffer */
+ (void)jmr3927_ioc_reg_in(JMR3927_IOC_REV_ADDR);
+}
+static void unmask_irq_ioc(int irq_nr, int space_id)
+{
+ /* 0: mask */
+ unsigned char imask = jmr3927_ioc_reg_in(JMR3927_IOC_INTM_ADDR);
+ unsigned int bit = 1 << irq_nr;
+ jmr3927_ioc_reg_out(imask | bit, JMR3927_IOC_INTM_ADDR);
+ /* flush write buffer */
+ (void)jmr3927_ioc_reg_in(JMR3927_IOC_REV_ADDR);
+}
+
+static void mask_irq_irc(int irq_nr, int space_id)
+{
+ volatile unsigned long *ilrp = &tx3927_ircptr->ilr[irq_nr / 2];
+ if (irq_nr & 1)
+ *ilrp = (*ilrp & 0x00ff) | (irc_dlevel << 8);
+ else
+ *ilrp = (*ilrp & 0xff00) | irc_dlevel;
+ /* update IRCSR */
+ tx3927_ircptr->imr = 0;
+ tx3927_ircptr->imr = irc_elevel;
+}
+static void unmask_irq_irc(int irq_nr, int space_id)
+{
+ volatile unsigned long *ilrp = &tx3927_ircptr->ilr[irq_nr / 2];
+ if (irq_nr & 1)
+ *ilrp = (*ilrp & 0x00ff) | (irc_level[irq_nr] << 8);
+ else
+ *ilrp = (*ilrp & 0xff00) | irc_level[irq_nr];
+ /* update IRCSR */
+ tx3927_ircptr->imr = 0;
+ tx3927_ircptr->imr = irc_elevel;
+}
+
+struct tb_irq_space jmr3927_isac_irqspace = {
+ .next = NULL,
+ .start_irqno = JMR3927_IRQ_ISAC,
+ nr_irqs : JMR3927_NR_IRQ_ISAC,
+ .mask_func = mask_irq_isac,
+ .unmask_func = unmask_irq_isac,
+ .name = "ISAC",
+ .space_id = 0,
+ can_share : 0
+};
+struct tb_irq_space jmr3927_ioc_irqspace = {
+ .next = NULL,
+ .start_irqno = JMR3927_IRQ_IOC,
+ nr_irqs : JMR3927_NR_IRQ_IOC,
+ .mask_func = mask_irq_ioc,
+ .unmask_func = unmask_irq_ioc,
+ .name = "IOC",
+ .space_id = 0,
+ can_share : 1
+};
+struct tb_irq_space jmr3927_irc_irqspace = {
+ .next = NULL,
+ .start_irqno = JMR3927_IRQ_IRC,
+ nr_irqs : JMR3927_NR_IRQ_IRC,
+ .mask_func = mask_irq_irc,
+ .unmask_func = unmask_irq_irc,
+ .name = "on-chip",
+ .space_id = 0,
+ can_share : 0
+};
+
+void jmr3927_spurious(struct pt_regs *regs)
+{
+#ifdef CONFIG_TX_BRANCH_LIKELY_BUG_WORKAROUND
+ tx_branch_likely_bug_fixup(regs);
+#endif
+ printk(KERN_WARNING "spurious interrupt (cause 0x%lx, pc 0x%lx, ra 0x%lx).\n",
+ regs->cp0_cause, regs->cp0_epc, regs->regs[31]);
+}
+
+void jmr3927_irc_irqdispatch(struct pt_regs *regs)
+{
+ int irq;
+
+#ifdef CONFIG_TX_BRANCH_LIKELY_BUG_WORKAROUND
+ tx_branch_likely_bug_fixup(regs);
+#endif
+ if ((regs->cp0_cause & CAUSEF_IP7) == 0) {
+#if 0
+ jmr3927_spurious(regs);
+#endif
+ return;
+ }
+ irq = (regs->cp0_cause >> CAUSEB_IP2) & 0x0f;
+
+ do_IRQ(irq + JMR3927_IRQ_IRC, regs);
+}
+
+static void jmr3927_ioc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ unsigned char istat = jmr3927_ioc_reg_in(JMR3927_IOC_INTS2_ADDR);
+ int i;
+
+ for (i = 0; i < JMR3927_NR_IRQ_IOC; i++) {
+ if (istat & (1 << i)) {
+ irq = JMR3927_IRQ_IOC + i;
+ do_IRQ(irq, regs);
+ }
+ }
+}
+
+static struct irqaction ioc_action = {
+ jmr3927_ioc_interrupt, 0, CPU_MASK_NONE, "IOC", NULL, NULL,
+};
+
+static void jmr3927_isac_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ unsigned char istat = jmr3927_isac_reg_in(JMR3927_ISAC_INTS2_ADDR);
+ int i;
+
+ for (i = 0; i < JMR3927_NR_IRQ_ISAC; i++) {
+ if (istat & (1 << i)) {
+ irq = JMR3927_IRQ_ISAC + i;
+ do_IRQ(irq, regs);
+ }
+ }
+}
+
+static struct irqaction isac_action = {
+ jmr3927_isac_interrupt, 0, CPU_MASK_NONE, "ISAC", NULL, NULL,
+};
+
+
+static void jmr3927_isaerr_interrupt(int irq, void * dev_id, struct pt_regs * regs)
+{
+ printk(KERN_WARNING "ISA error interrupt (irq 0x%x).\n", irq);
+}
+static struct irqaction isaerr_action = {
+ jmr3927_isaerr_interrupt, 0, CPU_MASK_NONE, "ISA error", NULL, NULL,
+};
+
+static void jmr3927_pcierr_interrupt(int irq, void * dev_id, struct pt_regs * regs)
+{
+ printk(KERN_WARNING "PCI error interrupt (irq 0x%x).\n", irq);
+ printk(KERN_WARNING "pcistat:%02x, lbstat:%04lx\n",
+ tx3927_pcicptr->pcistat, tx3927_pcicptr->lbstat);
+}
+static struct irqaction pcierr_action = {
+ jmr3927_pcierr_interrupt, 0, CPU_MASK_NONE, "PCI error", NULL, NULL,
+};
+
+int jmr3927_ether1_irq = 0;
+
+void jmr3927_irq_init(u32 irq_base);
+
+void __init arch_init_irq(void)
+{
+ /* look for io board's presence */
+ int have_isac = jmr3927_have_isac();
+
+ /* Now, interrupt control disabled, */
+ /* all IRC interrupts are masked, */
+ /* all IRC interrupt mode are Low Active. */
+
+ if (have_isac) {
+
+ /* ETHER1 (NE2000 compatible 10M-Ether) parameter setup */
+ /* temporary enable interrupt control */
+ tx3927_ircptr->cer = 1;
+ /* ETHER1 Int. Is High-Active. */
+ if (tx3927_ircptr->ssr & (1 << 0))
+ jmr3927_ether1_irq = JMR3927_IRQ_IRC_INT0;
+#if 0 /* INT3 may be asserted by ether0 (even after reboot...) */
+ else if (tx3927_ircptr->ssr & (1 << 3))
+ jmr3927_ether1_irq = JMR3927_IRQ_IRC_INT3;
+#endif
+ /* disable interrupt control */
+ tx3927_ircptr->cer = 0;
+
+ /* Ether1: High Active */
+ if (jmr3927_ether1_irq) {
+ int ether1_irc = jmr3927_ether1_irq - JMR3927_IRQ_IRC;
+ tx3927_ircptr->cr[ether1_irc / 8] |=
+ TX3927_IRCR_HIGH << ((ether1_irc % 8) * 2);
+ }
+ }
+
+ /* mask all IOC interrupts */
+ jmr3927_ioc_reg_out(0, JMR3927_IOC_INTM_ADDR);
+ /* setup IOC interrupt mode (SOFT:High Active, Others:Low Active) */
+ jmr3927_ioc_reg_out(JMR3927_IOC_INTF_SOFT, JMR3927_IOC_INTP_ADDR);
+
+ if (have_isac) {
+ /* mask all ISAC interrupts */
+ jmr3927_isac_reg_out(0, JMR3927_ISAC_INTM_ADDR);
+ /* setup ISAC interrupt mode (ISAIRQ3,ISAIRQ5:Low Active ???) */
+ jmr3927_isac_reg_out(JMR3927_ISAC_INTF_IRQ3|JMR3927_ISAC_INTF_IRQ5, JMR3927_ISAC_INTP_ADDR);
+ }
+
+ /* clear PCI Soft interrupts */
+ jmr3927_ioc_reg_out(0, JMR3927_IOC_INTS1_ADDR);
+ /* clear PCI Reset interrupts */
+ jmr3927_ioc_reg_out(0, JMR3927_IOC_RESET_ADDR);
+
+ /* enable interrupt control */
+ tx3927_ircptr->cer = TX3927_IRCER_ICE;
+ tx3927_ircptr->imr = irc_elevel;
+
+ jmr3927_irq_init(NR_ISA_IRQS);
+
+ set_except_vector(0, jmr3927_IRQ);
+
+ /* setup irq space */
+ add_tb_irq_space(&jmr3927_isac_irqspace);
+ add_tb_irq_space(&jmr3927_ioc_irqspace);
+ add_tb_irq_space(&jmr3927_irc_irqspace);
+
+ /* setup IOC interrupt 1 (PCI, MODEM) */
+ setup_irq(JMR3927_IRQ_IOCINT, &ioc_action);
+
+ if (have_isac) {
+ setup_irq(JMR3927_IRQ_ISACINT, &isac_action);
+ setup_irq(JMR3927_IRQ_ISAC_ISAER, &isaerr_action);
+ }
+
+#ifdef CONFIG_PCI
+ setup_irq(JMR3927_IRQ_IRC_PCI, &pcierr_action);
+#endif
+
+ /* enable all CPU interrupt bits. */
+ set_c0_status(ST0_IM); /* IE bit is still 0. */
+}
+
+static hw_irq_controller jmr3927_irq_controller = {
+ "jmr3927_irq",
+ jmr3927_irq_startup,
+ jmr3927_irq_shutdown,
+ jmr3927_irq_enable,
+ jmr3927_irq_disable,
+ jmr3927_irq_ack,
+ jmr3927_irq_end,
+};
+
+void jmr3927_irq_init(u32 irq_base)
+{
+ u32 i;
+
+ for (i= irq_base; i< irq_base + JMR3927_NR_IRQ_IRC + JMR3927_NR_IRQ_IOC; i++) {
+ irq_desc[i].status = IRQ_DISABLED;
+ irq_desc[i].action = NULL;
+ irq_desc[i].depth = 1;
+ irq_desc[i].handler = &jmr3927_irq_controller;
+ }
+
+ jmr3927_irq_base = irq_base;
+}
+
+#ifdef CONFIG_TX_BRANCH_LIKELY_BUG_WORKAROUND
+static int tx_branch_likely_bug_count = 0;
+static int have_tx_branch_likely_bug = 0;
+void tx_branch_likely_bug_fixup(struct pt_regs *regs)
+{
+ /* TX39/49-BUG: Under this condition, the insn in delay slot
+ of the branch likely insn is executed (not nullified) even
+ the branch condition is false. */
+ if (!have_tx_branch_likely_bug)
+ return;
+ if ((regs->cp0_epc & 0xfff) == 0xffc &&
+ KSEGX(regs->cp0_epc) != KSEG0 &&
+ KSEGX(regs->cp0_epc) != KSEG1) {
+ unsigned int insn = *(unsigned int*)(regs->cp0_epc - 4);
+ /* beql,bnel,blezl,bgtzl */
+ /* bltzl,bgezl,blezall,bgezall */
+ /* bczfl, bcztl */
+ if ((insn & 0xf0000000) == 0x50000000 ||
+ (insn & 0xfc0e0000) == 0x04020000 ||
+ (insn & 0xf3fe0000) == 0x41020000) {
+ regs->cp0_epc -= 4;
+ tx_branch_likely_bug_count++;
+ printk(KERN_INFO
+ "fix branch-likery bug in %s (insn %08x)\n",
+ current->comm, insn);
+ }
+ }
+}
+#endif
diff --git a/arch/mips/jmr3927/rbhma3100/kgdb_io.c b/arch/mips/jmr3927/rbhma3100/kgdb_io.c
new file mode 100644
index 0000000..269a42d
--- /dev/null
+++ b/arch/mips/jmr3927/rbhma3100/kgdb_io.c
@@ -0,0 +1,155 @@
+/*
+ * BRIEF MODULE DESCRIPTION
+ * Low level uart routines to directly access a TX[34]927 SIO.
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ * ahennessy@mvista.com or source@mvista.com
+ *
+ * Based on arch/mips/ddb5xxx/ddb5477/kgdb_io.c
+ *
+ * Copyright (C) 2000-2001 Toshiba Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/types.h>
+#include <asm/jmr3927/txx927.h>
+#include <asm/jmr3927/tx3927.h>
+#include <asm/jmr3927/jmr3927.h>
+
+#define TIMEOUT 0xffffff
+#define SLOW_DOWN
+
+static const char digits[16] = "0123456789abcdef";
+
+#ifdef SLOW_DOWN
+#define slow_down() { int k; for (k=0; k<10000; k++); }
+#else
+#define slow_down()
+#endif
+
+static int remoteDebugInitialized = 0;
+
+int putDebugChar(unsigned char c)
+{
+ int i = 0;
+
+ if (!remoteDebugInitialized) {
+ remoteDebugInitialized = 1;
+ debugInit(38400);
+ }
+
+ do {
+ slow_down();
+ i++;
+ if (i>TIMEOUT) {
+ break;
+ }
+ } while (!(tx3927_sioptr(0)->cisr & TXx927_SICISR_TXALS));
+ tx3927_sioptr(0)->tfifo = c;
+
+ return 1;
+}
+
+unsigned char getDebugChar(void)
+{
+ int i = 0;
+ int dicr;
+ char c;
+
+ if (!remoteDebugInitialized) {
+ remoteDebugInitialized = 1;
+ debugInit(38400);
+ }
+
+ /* diable RX int. */
+ dicr = tx3927_sioptr(0)->dicr;
+ tx3927_sioptr(0)->dicr = 0;
+
+ do {
+ slow_down();
+ i++;
+ if (i>TIMEOUT) {
+ break;
+ }
+ } while (tx3927_sioptr(0)->disr & TXx927_SIDISR_UVALID)
+ ;
+ c = tx3927_sioptr(0)->rfifo;
+
+ /* clear RX int. status */
+ tx3927_sioptr(0)->disr &= ~TXx927_SIDISR_RDIS;
+ /* enable RX int. */
+ tx3927_sioptr(0)->dicr = dicr;
+
+ return c;
+}
+
+void debugInit(int baud)
+{
+ /*
+ volatile unsigned long lcr;
+ volatile unsigned long dicr;
+ volatile unsigned long disr;
+ volatile unsigned long cisr;
+ volatile unsigned long fcr;
+ volatile unsigned long flcr;
+ volatile unsigned long bgr;
+ volatile unsigned long tfifo;
+ volatile unsigned long rfifo;
+ */
+
+ tx3927_sioptr(0)->lcr = 0x020;
+ tx3927_sioptr(0)->dicr = 0;
+ tx3927_sioptr(0)->disr = 0x4100;
+ tx3927_sioptr(0)->cisr = 0x014;
+ tx3927_sioptr(0)->fcr = 0;
+ tx3927_sioptr(0)->flcr = 0x02;
+ tx3927_sioptr(0)->bgr = ((JMR3927_BASE_BAUD + baud / 2) / baud) |
+ TXx927_SIBGR_BCLK_T0;
+#if 0
+ /*
+ * Reset the UART.
+ */
+ tx3927_sioptr(0)->fcr = TXx927_SIFCR_SWRST;
+ while (tx3927_sioptr(0)->fcr & TXx927_SIFCR_SWRST)
+ ;
+
+ /*
+ * and set the speed of the serial port
+ * (currently hardwired to 9600 8N1
+ */
+
+ tx3927_sioptr(0)->lcr = TXx927_SILCR_UMODE_8BIT |
+ TXx927_SILCR_USBL_1BIT |
+ TXx927_SILCR_SCS_IMCLK_BG;
+ tx3927_sioptr(0)->bgr =
+ ((JMR3927_BASE_BAUD + baud / 2) / baud) |
+ TXx927_SIBGR_BCLK_T0;
+
+ /* HW RTS/CTS control */
+ if (ser->flags & ASYNC_HAVE_CTS_LINE)
+ tx3927_sioptr(0)->flcr = TXx927_SIFLCR_RCS | TXx927_SIFLCR_TES |
+ TXx927_SIFLCR_RTSTL_MAX /* 15 */;
+ /* Enable RX/TX */
+ tx3927_sioptr(0)->flcr &= ~(TXx927_SIFLCR_RSDE | TXx927_SIFLCR_TSDE);
+#endif
+}
diff --git a/arch/mips/jmr3927/rbhma3100/setup.c b/arch/mips/jmr3927/rbhma3100/setup.c
new file mode 100644
index 0000000..32039bb
--- /dev/null
+++ b/arch/mips/jmr3927/rbhma3100/setup.c
@@ -0,0 +1,510 @@
+/***********************************************************************
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ * ahennessy@mvista.com
+ *
+ * Based on arch/mips/ddb5xxx/ddb5477/setup.c
+ *
+ * Setup file for JMR3927.
+ *
+ * Copyright (C) 2000-2001 Toshiba Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ ***********************************************************************
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/kdev_t.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/pci.h>
+#include <linux/ide.h>
+#include <linux/ioport.h>
+#include <linux/param.h> /* for HZ */
+#include <linux/delay.h>
+
+#include <asm/addrspace.h>
+#include <asm/time.h>
+#include <asm/bcache.h>
+#include <asm/irq.h>
+#include <asm/reboot.h>
+#include <asm/gdb-stub.h>
+#include <asm/jmr3927/jmr3927.h>
+#include <asm/mipsregs.h>
+#include <asm/traps.h>
+
+/* Tick Timer divider */
+#define JMR3927_TIMER_CCD 0 /* 1/2 */
+#define JMR3927_TIMER_CLK (JMR3927_IMCLK / (2 << JMR3927_TIMER_CCD))
+
+unsigned char led_state = 0xf;
+
+struct {
+ struct resource ram0;
+ struct resource ram1;
+ struct resource pcimem;
+ struct resource iob;
+ struct resource ioc;
+ struct resource pciio;
+ struct resource jmy1394;
+ struct resource rom1;
+ struct resource rom0;
+ struct resource sio0;
+ struct resource sio1;
+} jmr3927_resources = {
+ { "RAM0", 0, 0x01FFFFFF, IORESOURCE_MEM },
+ { "RAM1", 0x02000000, 0x03FFFFFF, IORESOURCE_MEM },
+ { "PCIMEM", 0x08000000, 0x07FFFFFF, IORESOURCE_MEM },
+ { "IOB", 0x10000000, 0x13FFFFFF },
+ { "IOC", 0x14000000, 0x14FFFFFF },
+ { "PCIIO", 0x15000000, 0x15FFFFFF },
+ { "JMY1394", 0x1D000000, 0x1D3FFFFF },
+ { "ROM1", 0x1E000000, 0x1E3FFFFF },
+ { "ROM0", 0x1FC00000, 0x1FFFFFFF },
+ { "SIO0", 0xFFFEF300, 0xFFFEF3FF },
+ { "SIO1", 0xFFFEF400, 0xFFFEF4FF },
+};
+
+/* don't enable - see errata */
+int jmr3927_ccfg_toeon = 0;
+
+static inline void do_reset(void)
+{
+#ifdef CONFIG_TC35815
+ extern void tc35815_killall(void);
+ tc35815_killall();
+#endif
+#if 1 /* Resetting PCI bus */
+ jmr3927_ioc_reg_out(0, JMR3927_IOC_RESET_ADDR);
+ jmr3927_ioc_reg_out(JMR3927_IOC_RESET_PCI, JMR3927_IOC_RESET_ADDR);
+ (void)jmr3927_ioc_reg_in(JMR3927_IOC_RESET_ADDR); /* flush WB */
+ mdelay(1);
+ jmr3927_ioc_reg_out(0, JMR3927_IOC_RESET_ADDR);
+#endif
+ jmr3927_ioc_reg_out(JMR3927_IOC_RESET_CPU, JMR3927_IOC_RESET_ADDR);
+}
+
+static void jmr3927_machine_restart(char *command)
+{
+ local_irq_disable();
+ puts("Rebooting...");
+ do_reset();
+}
+
+static void jmr3927_machine_halt(void)
+{
+ puts("JMR-TX3927 halted.\n");
+ while (1);
+}
+
+static void jmr3927_machine_power_off(void)
+{
+ puts("JMR-TX3927 halted. Please turn off the power.\n");
+ while (1);
+}
+
+#define USE_RTC_DS1742
+#ifdef USE_RTC_DS1742
+extern void rtc_ds1742_init(unsigned long base);
+#endif
+static void __init jmr3927_time_init(void)
+{
+#ifdef USE_RTC_DS1742
+ if (jmr3927_have_nvram()) {
+ rtc_ds1742_init(JMR3927_IOC_NVRAMB_ADDR);
+ }
+#endif
+}
+
+unsigned long jmr3927_do_gettimeoffset(void);
+extern int setup_irq(unsigned int irq, struct irqaction *irqaction);
+
+static void __init jmr3927_timer_setup(struct irqaction *irq)
+{
+ do_gettimeoffset = jmr3927_do_gettimeoffset;
+
+ jmr3927_tmrptr->cpra = JMR3927_TIMER_CLK / HZ;
+ jmr3927_tmrptr->itmr = TXx927_TMTITMR_TIIE | TXx927_TMTITMR_TZCE;
+ jmr3927_tmrptr->ccdr = JMR3927_TIMER_CCD;
+ jmr3927_tmrptr->tcr =
+ TXx927_TMTCR_TCE | TXx927_TMTCR_CCDE | TXx927_TMTCR_TMODE_ITVL;
+
+ setup_irq(JMR3927_IRQ_TICK, irq);
+}
+
+#define USECS_PER_JIFFY (1000000/HZ)
+
+unsigned long jmr3927_do_gettimeoffset(void)
+{
+ unsigned long count;
+ unsigned long res = 0;
+
+ /* MUST read TRR before TISR. */
+ count = jmr3927_tmrptr->trr;
+
+ if (jmr3927_tmrptr->tisr & TXx927_TMTISR_TIIS) {
+ /* timer interrupt is pending. use Max value. */
+ res = USECS_PER_JIFFY - 1;
+ } else {
+ /* convert to usec */
+ /* res = count / (JMR3927_TIMER_CLK / 1000000); */
+ res = (count << 7) / ((JMR3927_TIMER_CLK << 7) / 1000000);
+
+ /*
+ * 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;
+}
+
+
+//#undef DO_WRITE_THROUGH
+#define DO_WRITE_THROUGH
+#define DO_ENABLE_CACHE
+
+extern char * __init prom_getcmdline(void);
+static void jmr3927_board_init(void);
+extern struct resource pci_io_resource;
+extern struct resource pci_mem_resource;
+
+static void __init jmr3927_setup(void)
+{
+ char *argptr;
+
+ set_io_port_base(JMR3927_PORT_BASE + JMR3927_PCIIO);
+
+ board_time_init = jmr3927_time_init;
+ board_timer_setup = jmr3927_timer_setup;
+
+ _machine_restart = jmr3927_machine_restart;
+ _machine_halt = jmr3927_machine_halt;
+ _machine_power_off = jmr3927_machine_power_off;
+
+ /*
+ * IO/MEM resources.
+ */
+ ioport_resource.start = pci_io_resource.start;
+ ioport_resource.end = pci_io_resource.end;
+ iomem_resource.start = pci_mem_resource.start;
+ iomem_resource.end = pci_mem_resource.end;
+
+ /* Reboot on panic */
+ panic_timeout = 180;
+
+ {
+ unsigned int conf;
+ conf = read_c0_conf();
+ }
+
+#if 1
+ /* cache setup */
+ {
+ unsigned int conf;
+#ifdef DO_ENABLE_CACHE
+ int mips_ic_disable = 0, mips_dc_disable = 0;
+#else
+ int mips_ic_disable = 1, mips_dc_disable = 1;
+#endif
+#ifdef DO_WRITE_THROUGH
+ int mips_config_cwfon = 0;
+ int mips_config_wbon = 0;
+#else
+ int mips_config_cwfon = 1;
+ int mips_config_wbon = 1;
+#endif
+
+ conf = read_c0_conf();
+ conf &= ~(TX39_CONF_ICE | TX39_CONF_DCE | TX39_CONF_WBON | TX39_CONF_CWFON);
+ conf |= mips_ic_disable ? 0 : TX39_CONF_ICE;
+ conf |= mips_dc_disable ? 0 : TX39_CONF_DCE;
+ conf |= mips_config_wbon ? TX39_CONF_WBON : 0;
+ conf |= mips_config_cwfon ? TX39_CONF_CWFON : 0;
+
+ write_c0_conf(conf);
+ write_c0_cache(0);
+ }
+#endif
+
+ /* initialize board */
+ jmr3927_board_init();
+
+ argptr = prom_getcmdline();
+
+ if ((argptr = strstr(argptr, "toeon")) != NULL) {
+ jmr3927_ccfg_toeon = 1;
+ }
+ argptr = prom_getcmdline();
+ if ((argptr = strstr(argptr, "ip=")) == NULL) {
+ argptr = prom_getcmdline();
+ strcat(argptr, " ip=bootp");
+ }
+
+#ifdef CONFIG_TXX927_SERIAL_CONSOLE
+ argptr = prom_getcmdline();
+ if ((argptr = strstr(argptr, "console=")) == NULL) {
+ argptr = prom_getcmdline();
+ strcat(argptr, " console=ttyS1,115200");
+ }
+#endif
+}
+
+early_initcall(jmr3927_setup);
+
+
+static void tx3927_setup(void);
+
+#ifdef CONFIG_PCI
+unsigned long mips_pci_io_base;
+unsigned long mips_pci_io_size;
+unsigned long mips_pci_mem_base;
+unsigned long mips_pci_mem_size;
+/* for legacy I/O, PCI I/O PCI Bus address must be 0 */
+unsigned long mips_pci_io_pciaddr = 0;
+#endif
+
+static void __init jmr3927_board_init(void)
+{
+ char *argptr;
+
+#ifdef CONFIG_PCI
+ mips_pci_io_base = JMR3927_PCIIO;
+ mips_pci_io_size = JMR3927_PCIIO_SIZE;
+ mips_pci_mem_base = JMR3927_PCIMEM;
+ mips_pci_mem_size = JMR3927_PCIMEM_SIZE;
+#endif
+
+ tx3927_setup();
+
+ if (jmr3927_have_isac()) {
+
+#ifdef CONFIG_FB_E1355
+ argptr = prom_getcmdline();
+ if ((argptr = strstr(argptr, "video=")) == NULL) {
+ argptr = prom_getcmdline();
+ strcat(argptr, " video=e1355fb:crt16h");
+ }
+#endif
+
+#ifdef CONFIG_BLK_DEV_IDE
+ /* overrides PCI-IDE */
+#endif
+ }
+
+ /* SIO0 DTR on */
+ jmr3927_ioc_reg_out(0, JMR3927_IOC_DTR_ADDR);
+
+ jmr3927_led_set(0);
+
+
+ if (jmr3927_have_isac())
+ jmr3927_io_led_set(0);
+ printk("JMR-TX3927 (Rev %d) --- IOC(Rev %d) DIPSW:%d,%d,%d,%d\n",
+ jmr3927_ioc_reg_in(JMR3927_IOC_BREV_ADDR) & JMR3927_REV_MASK,
+ jmr3927_ioc_reg_in(JMR3927_IOC_REV_ADDR) & JMR3927_REV_MASK,
+ jmr3927_dipsw1(), jmr3927_dipsw2(),
+ jmr3927_dipsw3(), jmr3927_dipsw4());
+ if (jmr3927_have_isac())
+ printk("JMI-3927IO2 --- ISAC(Rev %d) DIPSW:%01x\n",
+ jmr3927_isac_reg_in(JMR3927_ISAC_REV_ADDR) & JMR3927_REV_MASK,
+ jmr3927_io_dipsw());
+}
+
+static void __init tx3927_setup(void)
+{
+ int i;
+
+ /* SDRAMC are configured by PROM */
+
+ /* ROMC */
+ tx3927_romcptr->cr[1] = JMR3927_ROMCE1 | 0x00030048;
+ tx3927_romcptr->cr[2] = JMR3927_ROMCE2 | 0x000064c8;
+ tx3927_romcptr->cr[3] = JMR3927_ROMCE3 | 0x0003f698;
+ tx3927_romcptr->cr[5] = JMR3927_ROMCE5 | 0x0000f218;
+
+ /* CCFG */
+ /* enable Timeout BusError */
+ if (jmr3927_ccfg_toeon)
+ tx3927_ccfgptr->ccfg |= TX3927_CCFG_TOE;
+
+ /* clear BusErrorOnWrite flag */
+ tx3927_ccfgptr->ccfg &= ~TX3927_CCFG_BEOW;
+ /* Disable PCI snoop */
+ tx3927_ccfgptr->ccfg &= ~TX3927_CCFG_PSNP;
+
+#ifdef DO_WRITE_THROUGH
+ /* Enable PCI SNOOP - with write through only */
+ tx3927_ccfgptr->ccfg |= TX3927_CCFG_PSNP;
+#endif
+
+ /* Pin selection */
+ tx3927_ccfgptr->pcfg &= ~TX3927_PCFG_SELALL;
+ tx3927_ccfgptr->pcfg |=
+ TX3927_PCFG_SELSIOC(0) | TX3927_PCFG_SELSIO_ALL |
+ (TX3927_PCFG_SELDMA_ALL & ~TX3927_PCFG_SELDMA(1));
+
+ printk("TX3927 -- CRIR:%08lx CCFG:%08lx PCFG:%08lx\n",
+ tx3927_ccfgptr->crir,
+ tx3927_ccfgptr->ccfg, tx3927_ccfgptr->pcfg);
+
+ /* IRC */
+ /* disable interrupt control */
+ tx3927_ircptr->cer = 0;
+ /* mask all IRC interrupts */
+ tx3927_ircptr->imr = 0;
+ for (i = 0; i < TX3927_NUM_IR / 2; i++) {
+ tx3927_ircptr->ilr[i] = 0;
+ }
+ /* setup IRC interrupt mode (Low Active) */
+ for (i = 0; i < TX3927_NUM_IR / 8; i++) {
+ tx3927_ircptr->cr[i] = 0;
+ }
+
+ /* TMR */
+ /* disable all timers */
+ for (i = 0; i < TX3927_NR_TMR; i++) {
+ tx3927_tmrptr(i)->tcr = TXx927_TMTCR_CRE;
+ tx3927_tmrptr(i)->tisr = 0;
+ tx3927_tmrptr(i)->cpra = 0xffffffff;
+ tx3927_tmrptr(i)->itmr = 0;
+ tx3927_tmrptr(i)->ccdr = 0;
+ tx3927_tmrptr(i)->pgmr = 0;
+ }
+
+ /* DMA */
+ tx3927_dmaptr->mcr = 0;
+ for (i = 0; i < sizeof(tx3927_dmaptr->ch) / sizeof(tx3927_dmaptr->ch[0]); i++) {
+ /* reset channel */
+ tx3927_dmaptr->ch[i].ccr = TX3927_DMA_CCR_CHRST;
+ tx3927_dmaptr->ch[i].ccr = 0;
+ }
+ /* enable DMA */
+#ifdef __BIG_ENDIAN
+ tx3927_dmaptr->mcr = TX3927_DMA_MCR_MSTEN;
+#else
+ tx3927_dmaptr->mcr = TX3927_DMA_MCR_MSTEN | TX3927_DMA_MCR_LE;
+#endif
+
+#ifdef CONFIG_PCI
+ /* PCIC */
+ printk("TX3927 PCIC -- DID:%04x VID:%04x RID:%02x Arbiter:",
+ tx3927_pcicptr->did, tx3927_pcicptr->vid,
+ tx3927_pcicptr->rid);
+ if (!(tx3927_ccfgptr->ccfg & TX3927_CCFG_PCIXARB)) {
+ printk("External\n");
+ /* XXX */
+ } else {
+ printk("Internal\n");
+
+ /* Reset PCI Bus */
+ jmr3927_ioc_reg_out(0, JMR3927_IOC_RESET_ADDR);
+ udelay(100);
+ jmr3927_ioc_reg_out(JMR3927_IOC_RESET_PCI,
+ JMR3927_IOC_RESET_ADDR);
+ udelay(100);
+ jmr3927_ioc_reg_out(0, JMR3927_IOC_RESET_ADDR);
+
+
+ /* Disable External PCI Config. Access */
+ tx3927_pcicptr->lbc = TX3927_PCIC_LBC_EPCAD;
+#ifdef __BIG_ENDIAN
+ tx3927_pcicptr->lbc |= TX3927_PCIC_LBC_IBSE |
+ TX3927_PCIC_LBC_TIBSE |
+ TX3927_PCIC_LBC_TMFBSE | TX3927_PCIC_LBC_MSDSE;
+#endif
+ /* LB->PCI mappings */
+ tx3927_pcicptr->iomas = ~(mips_pci_io_size - 1);
+ tx3927_pcicptr->ilbioma = mips_pci_io_base;
+ tx3927_pcicptr->ipbioma = mips_pci_io_pciaddr;
+ tx3927_pcicptr->mmas = ~(mips_pci_mem_size - 1);
+ tx3927_pcicptr->ilbmma = mips_pci_mem_base;
+ tx3927_pcicptr->ipbmma = mips_pci_mem_base;
+ /* PCI->LB mappings */
+ tx3927_pcicptr->iobas = 0xffffffff;
+ tx3927_pcicptr->ioba = 0;
+ tx3927_pcicptr->tlbioma = 0;
+ tx3927_pcicptr->mbas = ~(mips_pci_mem_size - 1);
+ tx3927_pcicptr->mba = 0;
+ tx3927_pcicptr->tlbmma = 0;
+#ifndef JMR3927_INIT_INDIRECT_PCI
+ /* Enable Direct mapping Address Space Decoder */
+ tx3927_pcicptr->lbc |= TX3927_PCIC_LBC_ILMDE | TX3927_PCIC_LBC_ILIDE;
+#endif
+
+ /* Clear All Local Bus Status */
+ tx3927_pcicptr->lbstat = TX3927_PCIC_LBIM_ALL;
+ /* Enable All Local Bus Interrupts */
+ tx3927_pcicptr->lbim = TX3927_PCIC_LBIM_ALL;
+ /* Clear All PCI Status Error */
+ tx3927_pcicptr->pcistat = TX3927_PCIC_PCISTATIM_ALL;
+ /* Enable All PCI Status Error Interrupts */
+ tx3927_pcicptr->pcistatim = TX3927_PCIC_PCISTATIM_ALL;
+
+ /* PCIC Int => IRC IRQ10 */
+ tx3927_pcicptr->il = TX3927_IR_PCI;
+#if 1
+ /* Target Control (per errata) */
+ tx3927_pcicptr->tc = TX3927_PCIC_TC_OF8E | TX3927_PCIC_TC_IF8E;
+#endif
+
+ /* Enable Bus Arbiter */
+#if 0
+ tx3927_pcicptr->req_trace = 0x73737373;
+#endif
+ tx3927_pcicptr->pbapmc = TX3927_PCIC_PBAPMC_PBAEN;
+
+ tx3927_pcicptr->pcicmd = PCI_COMMAND_MASTER |
+ PCI_COMMAND_MEMORY |
+#if 1
+ PCI_COMMAND_IO |
+#endif
+ PCI_COMMAND_PARITY | PCI_COMMAND_SERR;
+ }
+#endif /* CONFIG_PCI */
+
+ /* PIO */
+ /* PIO[15:12] connected to LEDs */
+ tx3927_pioptr->dir = 0x0000f000;
+ tx3927_pioptr->maskcpu = 0;
+ tx3927_pioptr->maskext = 0;
+ {
+ unsigned int conf;
+
+ conf = read_c0_conf();
+ if (!(conf & TX39_CONF_ICE))
+ printk("TX3927 I-Cache disabled.\n");
+ if (!(conf & TX39_CONF_DCE))
+ printk("TX3927 D-Cache disabled.\n");
+ else if (!(conf & TX39_CONF_WBON))
+ printk("TX3927 D-Cache WriteThrough.\n");
+ else if (!(conf & TX39_CONF_CWFON))
+ printk("TX3927 D-Cache WriteBack.\n");
+ else
+ printk("TX3927 D-Cache WriteBack (CWF) .\n");
+ }
+}
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
new file mode 100644
index 0000000..a0230ee
--- /dev/null
+++ b/arch/mips/kernel/Makefile
@@ -0,0 +1,65 @@
+#
+# Makefile for the Linux/MIPS kernel.
+#
+
+extra-y := head.o init_task.o vmlinux.lds
+
+obj-y += cpu-probe.o branch.o entry.o genex.o irq.o process.o \
+ ptrace.o reset.o semaphore.o setup.o signal.o syscall.o \
+ time.o traps.o unaligned.o
+
+binfmt_irix-objs := irixelf.o irixinv.o irixioctl.o irixsig.o \
+ irix5sys.o sysirix.o
+
+ifdef CONFIG_MODULES
+obj-y += mips_ksyms.o module.o
+obj-$(CONFIG_MIPS32) += module-elf32.o
+obj-$(CONFIG_MIPS64) += module-elf64.o
+endif
+
+obj-$(CONFIG_CPU_R3000) += r2300_fpu.o r2300_switch.o
+obj-$(CONFIG_CPU_TX39XX) += r2300_fpu.o r2300_switch.o
+obj-$(CONFIG_CPU_TX49XX) += r4k_fpu.o r4k_switch.o
+obj-$(CONFIG_CPU_R4000) += r4k_fpu.o r4k_switch.o
+obj-$(CONFIG_CPU_VR41XX) += r4k_fpu.o r4k_switch.o
+obj-$(CONFIG_CPU_R4300) += r4k_fpu.o r4k_switch.o
+obj-$(CONFIG_CPU_R4X00) += r4k_fpu.o r4k_switch.o
+obj-$(CONFIG_CPU_R5000) += r4k_fpu.o r4k_switch.o
+obj-$(CONFIG_CPU_R5432) += r4k_fpu.o r4k_switch.o
+obj-$(CONFIG_CPU_R8000) += r4k_fpu.o r4k_switch.o
+obj-$(CONFIG_CPU_RM7000) += r4k_fpu.o r4k_switch.o
+obj-$(CONFIG_CPU_RM9000) += r4k_fpu.o r4k_switch.o
+obj-$(CONFIG_CPU_NEVADA) += r4k_fpu.o r4k_switch.o
+obj-$(CONFIG_CPU_R10000) += r4k_fpu.o r4k_switch.o
+obj-$(CONFIG_CPU_SB1) += r4k_fpu.o r4k_switch.o
+obj-$(CONFIG_CPU_MIPS32) += r4k_fpu.o r4k_switch.o
+obj-$(CONFIG_CPU_MIPS64) += r4k_fpu.o r4k_switch.o
+obj-$(CONFIG_CPU_R6000) += r6000_fpu.o r4k_switch.o
+
+obj-$(CONFIG_SMP) += smp.o
+
+obj-$(CONFIG_NO_ISA) += dma-no-isa.o
+obj-$(CONFIG_I8259) += i8259.o
+obj-$(CONFIG_IRQ_CPU) += irq_cpu.o
+obj-$(CONFIG_IRQ_CPU_RM7K) += irq-rm7000.o
+obj-$(CONFIG_IRQ_CPU_RM9K) += irq-rm9000.o
+obj-$(CONFIG_IRQ_MV64340) += irq-mv6434x.o
+
+obj-$(CONFIG_MIPS32) += scall32-o32.o
+obj-$(CONFIG_MIPS64) += scall64-64.o
+obj-$(CONFIG_BINFMT_IRIX) += binfmt_irix.o
+obj-$(CONFIG_MIPS32_COMPAT) += ioctl32.o linux32.o signal32.o
+obj-$(CONFIG_MIPS32_N32) += binfmt_elfn32.o scall64-n32.o signal_n32.o
+obj-$(CONFIG_MIPS32_O32) += binfmt_elfo32.o scall64-o32.o ptrace32.o
+
+obj-$(CONFIG_KGDB) += gdb-low.o gdb-stub.o
+obj-$(CONFIG_PROC_FS) += proc.o
+
+obj-$(CONFIG_MIPS64) += cpu-bugs64.o
+
+obj-$(CONFIG_GEN_RTC) += genrtc.o
+
+CFLAGS_cpu-bugs64.o = $(shell if $(CC) $(CFLAGS) -Wa,-mdaddi -c -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-DHAVE_AS_SET_DADDI"; fi)
+CFLAGS_ioctl32.o += -Ifs/
+
+EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/kernel/binfmt_elfn32.c b/arch/mips/kernel/binfmt_elfn32.c
new file mode 100644
index 0000000..ed47041
--- /dev/null
+++ b/arch/mips/kernel/binfmt_elfn32.c
@@ -0,0 +1,119 @@
+/*
+ * Support for n32 Linux/MIPS ELF binaries.
+ *
+ * Copyright (C) 1999, 2001 Ralf Baechle
+ * Copyright (C) 1999, 2001 Silicon Graphics, Inc.
+ *
+ * Heavily inspired by the 32-bit Sparc compat code which is
+ * Copyright (C) 1995, 1996, 1997, 1998 David S. Miller (davem@redhat.com)
+ * Copyright (C) 1995, 1996, 1997, 1998 Jakub Jelinek (jj@ultra.linux.cz)
+ */
+
+#define ELF_ARCH EM_MIPS
+#define ELF_CLASS ELFCLASS32
+#ifdef __MIPSEB__
+#define ELF_DATA ELFDATA2MSB;
+#else /* __MIPSEL__ */
+#define ELF_DATA ELFDATA2LSB;
+#endif
+
+/* ELF register definitions */
+#define ELF_NGREG 45
+#define ELF_NFPREG 33
+
+typedef unsigned long elf_greg_t;
+typedef elf_greg_t elf_gregset_t[ELF_NGREG];
+
+typedef double elf_fpreg_t;
+typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
+
+/*
+ * This is used to ensure we don't load something for the wrong architecture.
+ */
+#define elf_check_arch(hdr) \
+({ \
+ int __res = 1; \
+ struct elfhdr *__h = (hdr); \
+ \
+ if (__h->e_machine != EM_MIPS) \
+ __res = 0; \
+ if (__h->e_ident[EI_CLASS] != ELFCLASS32) \
+ __res = 0; \
+ if (((__h->e_flags & EF_MIPS_ABI2) == 0) || \
+ ((__h->e_flags & EF_MIPS_ABI) != 0)) \
+ __res = 0; \
+ \
+ __res; \
+})
+
+#define TASK32_SIZE 0x7fff8000UL
+#undef ELF_ET_DYN_BASE
+#define ELF_ET_DYN_BASE (TASK32_SIZE / 3 * 2)
+
+#include <asm/processor.h>
+#include <linux/module.h>
+#include <linux/config.h>
+#include <linux/elfcore.h>
+#include <linux/compat.h>
+
+#define elf_prstatus elf_prstatus32
+struct elf_prstatus32
+{
+ struct elf_siginfo pr_info; /* Info associated with signal */
+ short pr_cursig; /* Current signal */
+ unsigned int pr_sigpend; /* Set of pending signals */
+ unsigned int pr_sighold; /* Set of held signals */
+ pid_t pr_pid;
+ pid_t pr_ppid;
+ pid_t pr_pgrp;
+ pid_t pr_sid;
+ struct compat_timeval pr_utime; /* User time */
+ struct compat_timeval pr_stime; /* System time */
+ struct compat_timeval pr_cutime;/* Cumulative user time */
+ struct compat_timeval pr_cstime;/* Cumulative system time */
+ elf_gregset_t pr_reg; /* GP registers */
+ int pr_fpvalid; /* True if math co-processor being used. */
+};
+
+#define elf_prpsinfo elf_prpsinfo32
+struct elf_prpsinfo32
+{
+ char pr_state; /* numeric process state */
+ char pr_sname; /* char for pr_state */
+ char pr_zomb; /* zombie */
+ char pr_nice; /* nice val */
+ unsigned int pr_flag; /* flags */
+ __kernel_uid_t pr_uid;
+ __kernel_gid_t pr_gid;
+ pid_t pr_pid, pr_ppid, pr_pgrp, pr_sid;
+ /* Lots missing */
+ char pr_fname[16]; /* filename of executable */
+ char pr_psargs[ELF_PRARGSZ]; /* initial part of arg list */
+};
+
+#define elf_addr_t u32
+#define elf_caddr_t u32
+#define init_elf_binfmt init_elfn32_binfmt
+
+#define jiffies_to_timeval jiffies_to_compat_timeval
+static __inline__ void
+jiffies_to_compat_timeval(unsigned long jiffies, struct compat_timeval *value)
+{
+ /*
+ * Convert jiffies to nanoseconds and seperate with
+ * one divide.
+ */
+ u64 nsec = (u64)jiffies * TICK_NSEC;
+ value->tv_sec = div_long_long_rem(nsec, NSEC_PER_SEC, &value->tv_usec);
+ value->tv_usec /= NSEC_PER_USEC;
+}
+
+#define ELF_CORE_EFLAGS EF_MIPS_ABI2
+
+MODULE_DESCRIPTION("Binary format loader for compatibility with n32 Linux/MIPS binaries");
+MODULE_AUTHOR("Ralf Baechle (ralf@linux-mips.org)");
+
+#undef MODULE_DESCRIPTION
+#undef MODULE_AUTHOR
+
+#include "../../../fs/binfmt_elf.c"
diff --git a/arch/mips/kernel/binfmt_elfo32.c b/arch/mips/kernel/binfmt_elfo32.c
new file mode 100644
index 0000000..ee21b18
--- /dev/null
+++ b/arch/mips/kernel/binfmt_elfo32.c
@@ -0,0 +1,139 @@
+/*
+ * Support for o32 Linux/MIPS ELF binaries.
+ *
+ * Copyright (C) 1999, 2001 Ralf Baechle
+ * Copyright (C) 1999, 2001 Silicon Graphics, Inc.
+ *
+ * Heavily inspired by the 32-bit Sparc compat code which is
+ * Copyright (C) 1995, 1996, 1997, 1998 David S. Miller (davem@redhat.com)
+ * Copyright (C) 1995, 1996, 1997, 1998 Jakub Jelinek (jj@ultra.linux.cz)
+ */
+
+#define ELF_ARCH EM_MIPS
+#define ELF_CLASS ELFCLASS32
+#ifdef __MIPSEB__
+#define ELF_DATA ELFDATA2MSB;
+#else /* __MIPSEL__ */
+#define ELF_DATA ELFDATA2LSB;
+#endif
+
+/* ELF register definitions */
+#define ELF_NGREG 45
+#define ELF_NFPREG 33
+
+typedef unsigned int elf_greg_t;
+typedef elf_greg_t elf_gregset_t[ELF_NGREG];
+
+typedef double elf_fpreg_t;
+typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
+
+/*
+ * This is used to ensure we don't load something for the wrong architecture.
+ */
+#define elf_check_arch(hdr) \
+({ \
+ int __res = 1; \
+ struct elfhdr *__h = (hdr); \
+ \
+ if (__h->e_machine != EM_MIPS) \
+ __res = 0; \
+ if (__h->e_ident[EI_CLASS] != ELFCLASS32) \
+ __res = 0; \
+ if ((__h->e_flags & EF_MIPS_ABI2) != 0) \
+ __res = 0; \
+ if (((__h->e_flags & EF_MIPS_ABI) != 0) && \
+ ((__h->e_flags & EF_MIPS_ABI) != EF_MIPS_ABI_O32)) \
+ __res = 0; \
+ \
+ __res; \
+})
+
+#define TASK32_SIZE 0x7fff8000UL
+#undef ELF_ET_DYN_BASE
+#define ELF_ET_DYN_BASE (TASK32_SIZE / 3 * 2)
+
+#include <asm/processor.h>
+#include <linux/module.h>
+#include <linux/config.h>
+#include <linux/elfcore.h>
+#include <linux/compat.h>
+
+#define elf_prstatus elf_prstatus32
+struct elf_prstatus32
+{
+ struct elf_siginfo pr_info; /* Info associated with signal */
+ short pr_cursig; /* Current signal */
+ unsigned int pr_sigpend; /* Set of pending signals */
+ unsigned int pr_sighold; /* Set of held signals */
+ pid_t pr_pid;
+ pid_t pr_ppid;
+ pid_t pr_pgrp;
+ pid_t pr_sid;
+ struct compat_timeval pr_utime; /* User time */
+ struct compat_timeval pr_stime; /* System time */
+ struct compat_timeval pr_cutime;/* Cumulative user time */
+ struct compat_timeval pr_cstime;/* Cumulative system time */
+ elf_gregset_t pr_reg; /* GP registers */
+ int pr_fpvalid; /* True if math co-processor being used. */
+};
+
+#define elf_prpsinfo elf_prpsinfo32
+struct elf_prpsinfo32
+{
+ char pr_state; /* numeric process state */
+ char pr_sname; /* char for pr_state */
+ char pr_zomb; /* zombie */
+ char pr_nice; /* nice val */
+ unsigned int pr_flag; /* flags */
+ __kernel_uid_t pr_uid;
+ __kernel_gid_t pr_gid;
+ pid_t pr_pid, pr_ppid, pr_pgrp, pr_sid;
+ /* Lots missing */
+ char pr_fname[16]; /* filename of executable */
+ char pr_psargs[ELF_PRARGSZ]; /* initial part of arg list */
+};
+
+#define elf_addr_t u32
+#define elf_caddr_t u32
+#define init_elf_binfmt init_elf32_binfmt
+
+#define jiffies_to_timeval jiffies_to_compat_timeval
+static __inline__ void
+jiffies_to_compat_timeval(unsigned long jiffies, struct compat_timeval *value)
+{
+ /*
+ * Convert jiffies to nanoseconds and seperate with
+ * one divide.
+ */
+ u64 nsec = (u64)jiffies * TICK_NSEC;
+ value->tv_sec = div_long_long_rem(nsec, NSEC_PER_SEC, &value->tv_usec);
+ value->tv_usec /= NSEC_PER_USEC;
+}
+
+#undef ELF_CORE_COPY_REGS
+#define ELF_CORE_COPY_REGS(_dest,_regs) elf32_core_copy_regs(_dest,_regs);
+
+void elf32_core_copy_regs(elf_gregset_t _dest, struct pt_regs *_regs)
+{
+ int i;
+
+ memset(_dest, 0, sizeof(elf_gregset_t));
+
+ /* XXXKW the 6 is from EF_REG0 in gdb/gdb/mips-linux-tdep.c, include/asm-mips/reg.h */
+ for (i=6; i<38; i++)
+ _dest[i] = (elf_greg_t) _regs->regs[i-6];
+ _dest[i++] = (elf_greg_t) _regs->lo;
+ _dest[i++] = (elf_greg_t) _regs->hi;
+ _dest[i++] = (elf_greg_t) _regs->cp0_epc;
+ _dest[i++] = (elf_greg_t) _regs->cp0_badvaddr;
+ _dest[i++] = (elf_greg_t) _regs->cp0_status;
+ _dest[i++] = (elf_greg_t) _regs->cp0_cause;
+}
+
+MODULE_DESCRIPTION("Binary format loader for compatibility with o32 Linux/MIPS binaries");
+MODULE_AUTHOR("Ralf Baechle (ralf@linux-mips.org)");
+
+#undef MODULE_DESCRIPTION
+#undef MODULE_AUTHOR
+
+#include "../../../fs/binfmt_elf.c"
diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
new file mode 100644
index 0000000..01117e9
--- /dev/null
+++ b/arch/mips/kernel/branch.c
@@ -0,0 +1,199 @@
+/*
+ * 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) 1996, 97, 2000, 2001 by Ralf Baechle
+ * Copyright (C) 2001 MIPS Technologies, Inc.
+ */
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <asm/branch.h>
+#include <asm/cpu.h>
+#include <asm/cpu-features.h>
+#include <asm/inst.h>
+#include <asm/ptrace.h>
+#include <asm/uaccess.h>
+
+/*
+ * Compute the return address and do emulate branch simulation, if required.
+ */
+int __compute_return_epc(struct pt_regs *regs)
+{
+ unsigned int *addr, bit, fcr31;
+ long epc;
+ union mips_instruction insn;
+
+ epc = regs->cp0_epc;
+ if (epc & 3)
+ goto unaligned;
+
+ /*
+ * Read the instruction
+ */
+ addr = (unsigned int *) epc;
+ if (__get_user(insn.word, addr)) {
+ force_sig(SIGSEGV, current);
+ return -EFAULT;
+ }
+
+ regs->regs[0] = 0;
+ switch (insn.i_format.opcode) {
+ /*
+ * jr and jalr are in r_format format.
+ */
+ case spec_op:
+ switch (insn.r_format.func) {
+ case jalr_op:
+ regs->regs[insn.r_format.rd] = epc + 8;
+ /* Fall through */
+ case jr_op:
+ regs->cp0_epc = regs->regs[insn.r_format.rs];
+ break;
+ }
+ break;
+
+ /*
+ * This group contains:
+ * bltz_op, bgez_op, bltzl_op, bgezl_op,
+ * bltzal_op, bgezal_op, bltzall_op, bgezall_op.
+ */
+ case bcond_op:
+ switch (insn.i_format.rt) {
+ case bltz_op:
+ case bltzl_op:
+ if ((long)regs->regs[insn.i_format.rs] < 0)
+ epc = epc + 4 + (insn.i_format.simmediate << 2);
+ else
+ epc += 8;
+ regs->cp0_epc = epc;
+ break;
+
+ case bgez_op:
+ case bgezl_op:
+ if ((long)regs->regs[insn.i_format.rs] >= 0)
+ epc = epc + 4 + (insn.i_format.simmediate << 2);
+ else
+ epc += 8;
+ regs->cp0_epc = epc;
+ break;
+
+ case bltzal_op:
+ case bltzall_op:
+ regs->regs[31] = epc + 8;
+ if ((long)regs->regs[insn.i_format.rs] < 0)
+ epc = epc + 4 + (insn.i_format.simmediate << 2);
+ else
+ epc += 8;
+ regs->cp0_epc = epc;
+ break;
+
+ case bgezal_op:
+ case bgezall_op:
+ regs->regs[31] = epc + 8;
+ if ((long)regs->regs[insn.i_format.rs] >= 0)
+ epc = epc + 4 + (insn.i_format.simmediate << 2);
+ else
+ epc += 8;
+ regs->cp0_epc = epc;
+ break;
+ }
+ break;
+
+ /*
+ * These are unconditional and in j_format.
+ */
+ case jal_op:
+ regs->regs[31] = regs->cp0_epc + 8;
+ case j_op:
+ epc += 4;
+ epc >>= 28;
+ epc <<= 28;
+ epc |= (insn.j_format.target << 2);
+ regs->cp0_epc = epc;
+ break;
+
+ /*
+ * These are conditional and in i_format.
+ */
+ case beq_op:
+ case beql_op:
+ if (regs->regs[insn.i_format.rs] ==
+ regs->regs[insn.i_format.rt])
+ epc = epc + 4 + (insn.i_format.simmediate << 2);
+ else
+ epc += 8;
+ regs->cp0_epc = epc;
+ break;
+
+ case bne_op:
+ case bnel_op:
+ if (regs->regs[insn.i_format.rs] !=
+ regs->regs[insn.i_format.rt])
+ epc = epc + 4 + (insn.i_format.simmediate << 2);
+ else
+ epc += 8;
+ regs->cp0_epc = epc;
+ break;
+
+ case blez_op: /* not really i_format */
+ case blezl_op:
+ /* rt field assumed to be zero */
+ if ((long)regs->regs[insn.i_format.rs] <= 0)
+ epc = epc + 4 + (insn.i_format.simmediate << 2);
+ else
+ epc += 8;
+ regs->cp0_epc = epc;
+ break;
+
+ case bgtz_op:
+ case bgtzl_op:
+ /* rt field assumed to be zero */
+ if ((long)regs->regs[insn.i_format.rs] > 0)
+ epc = epc + 4 + (insn.i_format.simmediate << 2);
+ else
+ epc += 8;
+ regs->cp0_epc = epc;
+ break;
+
+ /*
+ * And now the FPA/cp1 branch instructions.
+ */
+ case cop1_op:
+ if (!cpu_has_fpu)
+ fcr31 = current->thread.fpu.soft.fcr31;
+ else
+ asm volatile("cfc1\t%0,$31" : "=r" (fcr31));
+ bit = (insn.i_format.rt >> 2);
+ bit += (bit != 0);
+ bit += 23;
+ switch (insn.i_format.rt) {
+ case 0: /* bc1f */
+ case 2: /* bc1fl */
+ if (~fcr31 & (1 << bit))
+ epc = epc + 4 + (insn.i_format.simmediate << 2);
+ else
+ epc += 8;
+ regs->cp0_epc = epc;
+ break;
+
+ case 1: /* bc1t */
+ case 3: /* bc1tl */
+ if (fcr31 & (1 << bit))
+ epc = epc + 4 + (insn.i_format.simmediate << 2);
+ else
+ epc += 8;
+ regs->cp0_epc = epc;
+ break;
+ }
+ break;
+ }
+
+ return 0;
+
+unaligned:
+ printk("%s: unaligned epc - sending SIGBUS.\n", current->comm);
+ force_sig(SIGBUS, current);
+ return -EFAULT;
+}
diff --git a/arch/mips/kernel/cpu-bugs64.c b/arch/mips/kernel/cpu-bugs64.c
new file mode 100644
index 0000000..11ebe5d
--- /dev/null
+++ b/arch/mips/kernel/cpu-bugs64.c
@@ -0,0 +1,321 @@
+/*
+ * Copyright (C) 2003, 2004 Maciej W. Rozycki
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/ptrace.h>
+#include <linux/stddef.h>
+
+#include <asm/bugs.h>
+#include <asm/compiler.h>
+#include <asm/cpu.h>
+#include <asm/fpu.h>
+#include <asm/mipsregs.h>
+#include <asm/system.h>
+
+static inline void align_mod(const int align, const int mod)
+{
+ asm volatile(
+ ".set push\n\t"
+ ".set noreorder\n\t"
+ ".balign %0\n\t"
+ ".rept %1\n\t"
+ "nop\n\t"
+ ".endr\n\t"
+ ".set pop"
+ :
+ : "n" (align), "n" (mod));
+}
+
+static inline void mult_sh_align_mod(long *v1, long *v2, long *w,
+ const int align, const int mod)
+{
+ unsigned long flags;
+ int m1, m2;
+ long p, s, lv1, lv2, lw;
+
+ /*
+ * We want the multiply and the shift to be isolated from the
+ * rest of the code to disable gcc optimizations. Hence the
+ * asm statements that execute nothing, but make gcc not know
+ * what the values of m1, m2 and s are and what lv2 and p are
+ * used for.
+ */
+
+ local_irq_save(flags);
+ /*
+ * The following code leads to a wrong result of the first
+ * dsll32 when executed on R4000 rev. 2.2 or 3.0 (PRId
+ * 00000422 or 00000430, respectively).
+ *
+ * See "MIPS R4000PC/SC Errata, Processor Revision 2.2 and
+ * 3.0" by MIPS Technologies, Inc., errata #16 and #28 for
+ * details. I got no permission to duplicate them here,
+ * sigh... --macro
+ */
+ asm volatile(
+ ""
+ : "=r" (m1), "=r" (m2), "=r" (s)
+ : "0" (5), "1" (8), "2" (5));
+ align_mod(align, mod);
+ /*
+ * The trailing nop is needed to fullfill the two-instruction
+ * requirement between reading hi/lo and staring a mult/div.
+ * Leaving it out may cause gas insert a nop itself breaking
+ * the desired alignment of the next chunk.
+ */
+ asm volatile(
+ ".set push\n\t"
+ ".set noat\n\t"
+ ".set noreorder\n\t"
+ ".set nomacro\n\t"
+ "mult %2, %3\n\t"
+ "dsll32 %0, %4, %5\n\t"
+ "mflo $0\n\t"
+ "dsll32 %1, %4, %5\n\t"
+ "nop\n\t"
+ ".set pop"
+ : "=&r" (lv1), "=r" (lw)
+ : "r" (m1), "r" (m2), "r" (s), "I" (0)
+ : "hi", "lo", GCC_REG_ACCUM);
+ /* We have to use single integers for m1 and m2 and a double
+ * one for p to be sure the mulsidi3 gcc's RTL multiplication
+ * instruction has the workaround applied. Older versions of
+ * gcc have correct umulsi3 and mulsi3, but other
+ * multiplication variants lack the workaround.
+ */
+ asm volatile(
+ ""
+ : "=r" (m1), "=r" (m2), "=r" (s)
+ : "0" (m1), "1" (m2), "2" (s));
+ align_mod(align, mod);
+ p = m1 * m2;
+ lv2 = s << 32;
+ asm volatile(
+ ""
+ : "=r" (lv2)
+ : "0" (lv2), "r" (p));
+ local_irq_restore(flags);
+
+ *v1 = lv1;
+ *v2 = lv2;
+ *w = lw;
+}
+
+static inline void check_mult_sh(void)
+{
+ long v1[8], v2[8], w[8];
+ int bug, fix, i;
+
+ printk("Checking for the multiply/shift bug... ");
+
+ /*
+ * Testing discovered false negatives for certain code offsets
+ * into cache lines. Hence we test all possible offsets for
+ * the worst assumption of an R4000 I-cache line width of 32
+ * bytes.
+ *
+ * We can't use a loop as alignment directives need to be
+ * immediates.
+ */
+ mult_sh_align_mod(&v1[0], &v2[0], &w[0], 32, 0);
+ mult_sh_align_mod(&v1[1], &v2[1], &w[1], 32, 1);
+ mult_sh_align_mod(&v1[2], &v2[2], &w[2], 32, 2);
+ mult_sh_align_mod(&v1[3], &v2[3], &w[3], 32, 3);
+ mult_sh_align_mod(&v1[4], &v2[4], &w[4], 32, 4);
+ mult_sh_align_mod(&v1[5], &v2[5], &w[5], 32, 5);
+ mult_sh_align_mod(&v1[6], &v2[6], &w[6], 32, 6);
+ mult_sh_align_mod(&v1[7], &v2[7], &w[7], 32, 7);
+
+ bug = 0;
+ for (i = 0; i < 8; i++)
+ if (v1[i] != w[i])
+ bug = 1;
+
+ if (bug == 0) {
+ printk("no.\n");
+ return;
+ }
+
+ printk("yes, workaround... ");
+
+ fix = 1;
+ for (i = 0; i < 8; i++)
+ if (v2[i] != w[i])
+ fix = 0;
+
+ if (fix == 1) {
+ printk("yes.\n");
+ return;
+ }
+
+ printk("no.\n");
+ panic("Reliable operation impossible!\n"
+#ifndef CONFIG_CPU_R4000
+ "Configure for R4000 to enable the workaround."
+#else
+ "Please report to <linux-mips@linux-mips.org>."
+#endif
+ );
+}
+
+static volatile int daddi_ov __initdata = 0;
+
+asmlinkage void __init do_daddi_ov(struct pt_regs *regs)
+{
+ daddi_ov = 1;
+ regs->cp0_epc += 4;
+}
+
+static inline void check_daddi(void)
+{
+ extern asmlinkage void handle_daddi_ov(void);
+ unsigned long flags;
+ void *handler;
+ long v, tmp;
+
+ printk("Checking for the daddi bug... ");
+
+ local_irq_save(flags);
+ handler = set_except_vector(12, handle_daddi_ov);
+ /*
+ * The following code fails to trigger an overflow exception
+ * when executed on R4000 rev. 2.2 or 3.0 (PRId 00000422 or
+ * 00000430, respectively).
+ *
+ * See "MIPS R4000PC/SC Errata, Processor Revision 2.2 and
+ * 3.0" by MIPS Technologies, Inc., erratum #23 for details.
+ * I got no permission to duplicate it here, sigh... --macro
+ */
+ asm volatile(
+ ".set push\n\t"
+ ".set noat\n\t"
+ ".set noreorder\n\t"
+ ".set nomacro\n\t"
+ "addiu %1, $0, %2\n\t"
+ "dsrl %1, %1, 1\n\t"
+#ifdef HAVE_AS_SET_DADDI
+ ".set daddi\n\t"
+#endif
+ "daddi %0, %1, %3\n\t"
+ ".set pop"
+ : "=r" (v), "=&r" (tmp)
+ : "I" (0xffffffffffffdb9a), "I" (0x1234));
+ set_except_vector(12, handler);
+ local_irq_restore(flags);
+
+ if (daddi_ov) {
+ printk("no.\n");
+ return;
+ }
+
+ printk("yes, workaround... ");
+
+ local_irq_save(flags);
+ handler = set_except_vector(12, handle_daddi_ov);
+ asm volatile(
+ "addiu %1, $0, %2\n\t"
+ "dsrl %1, %1, 1\n\t"
+ "daddi %0, %1, %3"
+ : "=r" (v), "=&r" (tmp)
+ : "I" (0xffffffffffffdb9a), "I" (0x1234));
+ set_except_vector(12, handler);
+ local_irq_restore(flags);
+
+ if (daddi_ov) {
+ printk("yes.\n");
+ return;
+ }
+
+ printk("no.\n");
+ panic("Reliable operation impossible!\n"
+#if !defined(CONFIG_CPU_R4000) && !defined(CONFIG_CPU_R4400)
+ "Configure for R4000 or R4400 to enable the workaround."
+#else
+ "Please report to <linux-mips@linux-mips.org>."
+#endif
+ );
+}
+
+static inline void check_daddiu(void)
+{
+ long v, w, tmp;
+
+ printk("Checking for the daddiu bug... ");
+
+ /*
+ * The following code leads to a wrong result of daddiu when
+ * executed on R4400 rev. 1.0 (PRId 00000440).
+ *
+ * See "MIPS R4400PC/SC Errata, Processor Revision 1.0" by
+ * MIPS Technologies, Inc., erratum #7 for details.
+ *
+ * According to "MIPS R4000PC/SC Errata, Processor Revision
+ * 2.2 and 3.0" by MIPS Technologies, Inc., erratum #41 this
+ * problem affects R4000 rev. 2.2 and 3.0 (PRId 00000422 and
+ * 00000430, respectively), too. Testing failed to trigger it
+ * so far.
+ *
+ * I got no permission to duplicate the errata here, sigh...
+ * --macro
+ */
+ asm volatile(
+ ".set push\n\t"
+ ".set noat\n\t"
+ ".set noreorder\n\t"
+ ".set nomacro\n\t"
+ "addiu %2, $0, %3\n\t"
+ "dsrl %2, %2, 1\n\t"
+#ifdef HAVE_AS_SET_DADDI
+ ".set daddi\n\t"
+#endif
+ "daddiu %0, %2, %4\n\t"
+ "addiu %1, $0, %4\n\t"
+ "daddu %1, %2\n\t"
+ ".set pop"
+ : "=&r" (v), "=&r" (w), "=&r" (tmp)
+ : "I" (0xffffffffffffdb9a), "I" (0x1234));
+
+ if (v == w) {
+ printk("no.\n");
+ return;
+ }
+
+ printk("yes, workaround... ");
+
+ asm volatile(
+ "addiu %2, $0, %3\n\t"
+ "dsrl %2, %2, 1\n\t"
+ "daddiu %0, %2, %4\n\t"
+ "addiu %1, $0, %4\n\t"
+ "daddu %1, %2"
+ : "=&r" (v), "=&r" (w), "=&r" (tmp)
+ : "I" (0xffffffffffffdb9a), "I" (0x1234));
+
+ if (v == w) {
+ printk("yes.\n");
+ return;
+ }
+
+ printk("no.\n");
+ panic("Reliable operation impossible!\n"
+#if !defined(CONFIG_CPU_R4000) && !defined(CONFIG_CPU_R4400)
+ "Configure for R4000 or R4400 to enable the workaround."
+#else
+ "Please report to <linux-mips@linux-mips.org>."
+#endif
+ );
+}
+
+void __init check_bugs64(void)
+{
+ check_mult_sh();
+ check_daddi();
+ check_daddiu();
+}
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
new file mode 100644
index 0000000..4bb8495
--- /dev/null
+++ b/arch/mips/kernel/cpu-probe.c
@@ -0,0 +1,598 @@
+/*
+ * Processor capabilities determination functions.
+ *
+ * Copyright (C) xxxx the Anonymous
+ * Copyright (C) 2003 Maciej W. Rozycki
+ * Copyright (C) 1994 - 2003 Ralf Baechle
+ * Copyright (C) 2001 MIPS Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/ptrace.h>
+#include <linux/stddef.h>
+
+#include <asm/bugs.h>
+#include <asm/cpu.h>
+#include <asm/fpu.h>
+#include <asm/mipsregs.h>
+#include <asm/system.h>
+
+/*
+ * Not all of the MIPS CPUs have the "wait" instruction available. Moreover,
+ * the implementation of the "wait" feature differs between CPU families. This
+ * points to the function that implements CPU specific wait.
+ * The wait instruction stops the pipeline and reduces the power consumption of
+ * the CPU very much.
+ */
+void (*cpu_wait)(void) = NULL;
+
+static void r3081_wait(void)
+{
+ unsigned long cfg = read_c0_conf();
+ write_c0_conf(cfg | R30XX_CONF_HALT);
+}
+
+static void r39xx_wait(void)
+{
+ unsigned long cfg = read_c0_conf();
+ write_c0_conf(cfg | TX39_CONF_HALT);
+}
+
+static void r4k_wait(void)
+{
+ __asm__(".set\tmips3\n\t"
+ "wait\n\t"
+ ".set\tmips0");
+}
+
+/*
+ * The Au1xxx wait is available only if we run CONFIG_PM and
+ * the timer setup found we had a 32KHz counter available.
+ * There are still problems with functions that may call au1k_wait
+ * directly, but that will be discovered pretty quickly.
+ */
+extern void (*au1k_wait_ptr)(void);
+
+void au1k_wait(void)
+{
+#ifdef CONFIG_PM
+ /* using the wait instruction makes CP0 counter unusable */
+ __asm__(".set\tmips3\n\t"
+ "wait\n\t"
+ "nop\n\t"
+ "nop\n\t"
+ "nop\n\t"
+ "nop\n\t"
+ ".set\tmips0");
+#else
+ __asm__("nop\n\t"
+ "nop");
+#endif
+}
+
+static inline void check_wait(void)
+{
+ struct cpuinfo_mips *c = ¤t_cpu_data;
+
+ printk("Checking for 'wait' instruction... ");
+ switch (c->cputype) {
+ case CPU_R3081:
+ case CPU_R3081E:
+ cpu_wait = r3081_wait;
+ printk(" available.\n");
+ break;
+ case CPU_TX3927:
+ cpu_wait = r39xx_wait;
+ printk(" available.\n");
+ break;
+ case CPU_R4200:
+/* case CPU_R4300: */
+ case CPU_R4600:
+ case CPU_R4640:
+ case CPU_R4650:
+ case CPU_R4700:
+ case CPU_R5000:
+ case CPU_NEVADA:
+ case CPU_RM7000:
+ case CPU_RM9000:
+ case CPU_TX49XX:
+ case CPU_4KC:
+ case CPU_4KEC:
+ case CPU_4KSC:
+ case CPU_5KC:
+/* case CPU_20KC:*/
+ case CPU_24K:
+ case CPU_25KF:
+ cpu_wait = r4k_wait;
+ printk(" available.\n");
+ break;
+#ifdef CONFIG_PM
+ case CPU_AU1000:
+ case CPU_AU1100:
+ case CPU_AU1500:
+ if (au1k_wait_ptr != NULL) {
+ cpu_wait = au1k_wait_ptr;
+ printk(" available.\n");
+ }
+ else {
+ printk(" unavailable.\n");
+ }
+ break;
+#endif
+ default:
+ printk(" unavailable.\n");
+ break;
+ }
+}
+
+void __init check_bugs32(void)
+{
+ check_wait();
+}
+
+/*
+ * Probe whether cpu has config register by trying to play with
+ * alternate cache bit and see whether it matters.
+ * It's used by cpu_probe to distinguish between R3000A and R3081.
+ */
+static inline int cpu_has_confreg(void)
+{
+#ifdef CONFIG_CPU_R3000
+ extern unsigned long r3k_cache_size(unsigned long);
+ unsigned long size1, size2;
+ unsigned long cfg = read_c0_conf();
+
+ size1 = r3k_cache_size(ST0_ISC);
+ write_c0_conf(cfg ^ R30XX_CONF_AC);
+ size2 = r3k_cache_size(ST0_ISC);
+ write_c0_conf(cfg);
+ return size1 != size2;
+#else
+ return 0;
+#endif
+}
+
+/*
+ * Get the FPU Implementation/Revision.
+ */
+static inline unsigned long cpu_get_fpu_id(void)
+{
+ unsigned long tmp, fpu_id;
+
+ tmp = read_c0_status();
+ __enable_fpu();
+ fpu_id = read_32bit_cp1_register(CP1_REVISION);
+ write_c0_status(tmp);
+ return fpu_id;
+}
+
+/*
+ * Check the CPU has an FPU the official way.
+ */
+static inline int __cpu_has_fpu(void)
+{
+ return ((cpu_get_fpu_id() & 0xff00) != FPIR_IMP_NONE);
+}
+
+#define R4K_OPTS (MIPS_CPU_TLB | MIPS_CPU_4KEX | MIPS_CPU_4KTLB \
+ | MIPS_CPU_COUNTER)
+
+static inline void cpu_probe_legacy(struct cpuinfo_mips *c)
+{
+ switch (c->processor_id & 0xff00) {
+ case PRID_IMP_R2000:
+ c->cputype = CPU_R2000;
+ c->isa_level = MIPS_CPU_ISA_I;
+ c->options = MIPS_CPU_TLB | MIPS_CPU_NOFPUEX;
+ if (__cpu_has_fpu())
+ c->options |= MIPS_CPU_FPU;
+ c->tlbsize = 64;
+ break;
+ case PRID_IMP_R3000:
+ if ((c->processor_id & 0xff) == PRID_REV_R3000A)
+ if (cpu_has_confreg())
+ c->cputype = CPU_R3081E;
+ else
+ c->cputype = CPU_R3000A;
+ else
+ c->cputype = CPU_R3000;
+ c->isa_level = MIPS_CPU_ISA_I;
+ c->options = MIPS_CPU_TLB | MIPS_CPU_NOFPUEX;
+ if (__cpu_has_fpu())
+ c->options |= MIPS_CPU_FPU;
+ c->tlbsize = 64;
+ break;
+ case PRID_IMP_R4000:
+ if (read_c0_config() & CONF_SC) {
+ if ((c->processor_id & 0xff) >= PRID_REV_R4400)
+ c->cputype = CPU_R4400PC;
+ else
+ c->cputype = CPU_R4000PC;
+ } else {
+ if ((c->processor_id & 0xff) >= PRID_REV_R4400)
+ c->cputype = CPU_R4400SC;
+ else
+ c->cputype = CPU_R4000SC;
+ }
+
+ c->isa_level = MIPS_CPU_ISA_III;
+ c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
+ MIPS_CPU_WATCH | MIPS_CPU_VCE |
+ MIPS_CPU_LLSC;
+ c->tlbsize = 48;
+ break;
+ case PRID_IMP_VR41XX:
+ switch (c->processor_id & 0xf0) {
+#ifndef CONFIG_VR4181
+ case PRID_REV_VR4111:
+ c->cputype = CPU_VR4111;
+ break;
+#else
+ case PRID_REV_VR4181:
+ c->cputype = CPU_VR4181;
+ break;
+#endif
+ case PRID_REV_VR4121:
+ c->cputype = CPU_VR4121;
+ break;
+ case PRID_REV_VR4122:
+ if ((c->processor_id & 0xf) < 0x3)
+ c->cputype = CPU_VR4122;
+ else
+ c->cputype = CPU_VR4181A;
+ break;
+ case PRID_REV_VR4130:
+ if ((c->processor_id & 0xf) < 0x4)
+ c->cputype = CPU_VR4131;
+ else
+ c->cputype = CPU_VR4133;
+ break;
+ default:
+ printk(KERN_INFO "Unexpected CPU of NEC VR4100 series\n");
+ c->cputype = CPU_VR41XX;
+ break;
+ }
+ c->isa_level = MIPS_CPU_ISA_III;
+ c->options = R4K_OPTS;
+ c->tlbsize = 32;
+ break;
+ case PRID_IMP_R4300:
+ c->cputype = CPU_R4300;
+ c->isa_level = MIPS_CPU_ISA_III;
+ c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
+ MIPS_CPU_LLSC;
+ c->tlbsize = 32;
+ break;
+ case PRID_IMP_R4600:
+ c->cputype = CPU_R4600;
+ c->isa_level = MIPS_CPU_ISA_III;
+ c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_LLSC;
+ c->tlbsize = 48;
+ break;
+ #if 0
+ case PRID_IMP_R4650:
+ /*
+ * This processor doesn't have an MMU, so it's not
+ * "real easy" to run Linux on it. It is left purely
+ * for documentation. Commented out because it shares
+ * it's c0_prid id number with the TX3900.
+ */
+ c->cputype = CPU_R4650;
+ c->isa_level = MIPS_CPU_ISA_III;
+ c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_LLSC;
+ c->tlbsize = 48;
+ break;
+ #endif
+ case PRID_IMP_TX39:
+ c->isa_level = MIPS_CPU_ISA_I;
+ c->options = MIPS_CPU_TLB;
+
+ if ((c->processor_id & 0xf0) == (PRID_REV_TX3927 & 0xf0)) {
+ c->cputype = CPU_TX3927;
+ c->tlbsize = 64;
+ } else {
+ switch (c->processor_id & 0xff) {
+ case PRID_REV_TX3912:
+ c->cputype = CPU_TX3912;
+ c->tlbsize = 32;
+ break;
+ case PRID_REV_TX3922:
+ c->cputype = CPU_TX3922;
+ c->tlbsize = 64;
+ break;
+ default:
+ c->cputype = CPU_UNKNOWN;
+ break;
+ }
+ }
+ break;
+ case PRID_IMP_R4700:
+ c->cputype = CPU_R4700;
+ c->isa_level = MIPS_CPU_ISA_III;
+ c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
+ MIPS_CPU_LLSC;
+ c->tlbsize = 48;
+ break;
+ case PRID_IMP_TX49:
+ c->cputype = CPU_TX49XX;
+ c->isa_level = MIPS_CPU_ISA_III;
+ c->options = R4K_OPTS | MIPS_CPU_LLSC;
+ if (!(c->processor_id & 0x08))
+ c->options |= MIPS_CPU_FPU | MIPS_CPU_32FPR;
+ c->tlbsize = 48;
+ break;
+ case PRID_IMP_R5000:
+ c->cputype = CPU_R5000;
+ c->isa_level = MIPS_CPU_ISA_IV;
+ c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
+ MIPS_CPU_LLSC;
+ c->tlbsize = 48;
+ break;
+ case PRID_IMP_R5432:
+ c->cputype = CPU_R5432;
+ c->isa_level = MIPS_CPU_ISA_IV;
+ c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
+ MIPS_CPU_WATCH | MIPS_CPU_LLSC;
+ c->tlbsize = 48;
+ break;
+ case PRID_IMP_R5500:
+ c->cputype = CPU_R5500;
+ c->isa_level = MIPS_CPU_ISA_IV;
+ c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
+ MIPS_CPU_WATCH | MIPS_CPU_LLSC;
+ c->tlbsize = 48;
+ break;
+ case PRID_IMP_NEVADA:
+ c->cputype = CPU_NEVADA;
+ c->isa_level = MIPS_CPU_ISA_IV;
+ c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
+ MIPS_CPU_DIVEC | MIPS_CPU_LLSC;
+ c->tlbsize = 48;
+ break;
+ case PRID_IMP_R6000:
+ c->cputype = CPU_R6000;
+ c->isa_level = MIPS_CPU_ISA_II;
+ c->options = MIPS_CPU_TLB | MIPS_CPU_FPU |
+ MIPS_CPU_LLSC;
+ c->tlbsize = 32;
+ break;
+ case PRID_IMP_R6000A:
+ c->cputype = CPU_R6000A;
+ c->isa_level = MIPS_CPU_ISA_II;
+ c->options = MIPS_CPU_TLB | MIPS_CPU_FPU |
+ MIPS_CPU_LLSC;
+ c->tlbsize = 32;
+ break;
+ case PRID_IMP_RM7000:
+ c->cputype = CPU_RM7000;
+ c->isa_level = MIPS_CPU_ISA_IV;
+ c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
+ MIPS_CPU_LLSC;
+ /*
+ * Undocumented RM7000: Bit 29 in the info register of
+ * the RM7000 v2.0 indicates if the TLB has 48 or 64
+ * entries.
+ *
+ * 29 1 => 64 entry JTLB
+ * 0 => 48 entry JTLB
+ */
+ c->tlbsize = (read_c0_info() & (1 << 29)) ? 64 : 48;
+ break;
+ case PRID_IMP_RM9000:
+ c->cputype = CPU_RM9000;
+ c->isa_level = MIPS_CPU_ISA_IV;
+ c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
+ MIPS_CPU_LLSC;
+ /*
+ * Bit 29 in the info register of the RM9000
+ * indicates if the TLB has 48 or 64 entries.
+ *
+ * 29 1 => 64 entry JTLB
+ * 0 => 48 entry JTLB
+ */
+ c->tlbsize = (read_c0_info() & (1 << 29)) ? 64 : 48;
+ break;
+ case PRID_IMP_R8000:
+ c->cputype = CPU_R8000;
+ c->isa_level = MIPS_CPU_ISA_IV;
+ c->options = MIPS_CPU_TLB | MIPS_CPU_4KEX |
+ MIPS_CPU_FPU | MIPS_CPU_32FPR |
+ MIPS_CPU_LLSC;
+ c->tlbsize = 384; /* has weird TLB: 3-way x 128 */
+ break;
+ case PRID_IMP_R10000:
+ c->cputype = CPU_R10000;
+ c->isa_level = MIPS_CPU_ISA_IV;
+ c->options = MIPS_CPU_TLB | MIPS_CPU_4KEX |
+ MIPS_CPU_FPU | MIPS_CPU_32FPR |
+ MIPS_CPU_COUNTER | MIPS_CPU_WATCH |
+ MIPS_CPU_LLSC;
+ c->tlbsize = 64;
+ break;
+ case PRID_IMP_R12000:
+ c->cputype = CPU_R12000;
+ c->isa_level = MIPS_CPU_ISA_IV;
+ c->options = MIPS_CPU_TLB | MIPS_CPU_4KEX |
+ MIPS_CPU_FPU | MIPS_CPU_32FPR |
+ MIPS_CPU_COUNTER | MIPS_CPU_WATCH |
+ MIPS_CPU_LLSC;
+ c->tlbsize = 64;
+ break;
+ }
+}
+
+static inline void decode_config1(struct cpuinfo_mips *c)
+{
+ unsigned long config0 = read_c0_config();
+ unsigned long config1;
+
+ if ((config0 & (1 << 31)) == 0)
+ return; /* actually wort a panic() */
+
+ /* MIPS32 or MIPS64 compliant CPU. Read Config 1 register. */
+ c->options = MIPS_CPU_TLB | MIPS_CPU_4KEX |
+ MIPS_CPU_4KTLB | MIPS_CPU_COUNTER | MIPS_CPU_DIVEC |
+ MIPS_CPU_LLSC | MIPS_CPU_MCHECK;
+ config1 = read_c0_config1();
+ if (config1 & (1 << 3))
+ c->options |= MIPS_CPU_WATCH;
+ if (config1 & (1 << 2))
+ c->options |= MIPS_CPU_MIPS16;
+ if (config1 & (1 << 1))
+ c->options |= MIPS_CPU_EJTAG;
+ if (config1 & 1) {
+ c->options |= MIPS_CPU_FPU;
+ c->options |= MIPS_CPU_32FPR;
+ }
+ c->scache.flags = MIPS_CACHE_NOT_PRESENT;
+
+ c->tlbsize = ((config1 >> 25) & 0x3f) + 1;
+}
+
+static inline void cpu_probe_mips(struct cpuinfo_mips *c)
+{
+ decode_config1(c);
+ switch (c->processor_id & 0xff00) {
+ case PRID_IMP_4KC:
+ c->cputype = CPU_4KC;
+ c->isa_level = MIPS_CPU_ISA_M32;
+ break;
+ case PRID_IMP_4KEC:
+ c->cputype = CPU_4KEC;
+ c->isa_level = MIPS_CPU_ISA_M32;
+ break;
+ case PRID_IMP_4KSC:
+ c->cputype = CPU_4KSC;
+ c->isa_level = MIPS_CPU_ISA_M32;
+ break;
+ case PRID_IMP_5KC:
+ c->cputype = CPU_5KC;
+ c->isa_level = MIPS_CPU_ISA_M64;
+ break;
+ case PRID_IMP_20KC:
+ c->cputype = CPU_20KC;
+ c->isa_level = MIPS_CPU_ISA_M64;
+ break;
+ case PRID_IMP_24K:
+ c->cputype = CPU_24K;
+ c->isa_level = MIPS_CPU_ISA_M32;
+ break;
+ case PRID_IMP_25KF:
+ c->cputype = CPU_25KF;
+ c->isa_level = MIPS_CPU_ISA_M64;
+ /* Probe for L2 cache */
+ c->scache.flags &= ~MIPS_CACHE_NOT_PRESENT;
+ break;
+ }
+}
+
+static inline void cpu_probe_alchemy(struct cpuinfo_mips *c)
+{
+ decode_config1(c);
+ switch (c->processor_id & 0xff00) {
+ case PRID_IMP_AU1_REV1:
+ case PRID_IMP_AU1_REV2:
+ switch ((c->processor_id >> 24) & 0xff) {
+ case 0:
+ c->cputype = CPU_AU1000;
+ break;
+ case 1:
+ c->cputype = CPU_AU1500;
+ break;
+ case 2:
+ c->cputype = CPU_AU1100;
+ break;
+ case 3:
+ c->cputype = CPU_AU1550;
+ break;
+ default:
+ panic("Unknown Au Core!");
+ break;
+ }
+ c->isa_level = MIPS_CPU_ISA_M32;
+ break;
+ }
+}
+
+static inline void cpu_probe_sibyte(struct cpuinfo_mips *c)
+{
+ decode_config1(c);
+ switch (c->processor_id & 0xff00) {
+ case PRID_IMP_SB1:
+ c->cputype = CPU_SB1;
+ c->isa_level = MIPS_CPU_ISA_M64;
+ c->options = MIPS_CPU_TLB | MIPS_CPU_4KEX |
+ MIPS_CPU_COUNTER | MIPS_CPU_DIVEC |
+ MIPS_CPU_MCHECK | MIPS_CPU_EJTAG |
+ MIPS_CPU_WATCH | MIPS_CPU_LLSC;
+#ifndef CONFIG_SB1_PASS_1_WORKAROUNDS
+ /* FPU in pass1 is known to have issues. */
+ c->options |= MIPS_CPU_FPU | MIPS_CPU_32FPR;
+#endif
+ break;
+ }
+}
+
+static inline void cpu_probe_sandcraft(struct cpuinfo_mips *c)
+{
+ decode_config1(c);
+ switch (c->processor_id & 0xff00) {
+ case PRID_IMP_SR71000:
+ c->cputype = CPU_SR71000;
+ c->isa_level = MIPS_CPU_ISA_M64;
+ c->options = MIPS_CPU_TLB | MIPS_CPU_4KEX |
+ MIPS_CPU_4KTLB | MIPS_CPU_FPU |
+ MIPS_CPU_COUNTER | MIPS_CPU_MCHECK;
+ c->scache.ways = 8;
+ c->tlbsize = 64;
+ break;
+ }
+}
+
+__init void cpu_probe(void)
+{
+ struct cpuinfo_mips *c = ¤t_cpu_data;
+
+ c->processor_id = PRID_IMP_UNKNOWN;
+ c->fpu_id = FPIR_IMP_NONE;
+ c->cputype = CPU_UNKNOWN;
+
+ c->processor_id = read_c0_prid();
+ switch (c->processor_id & 0xff0000) {
+ case PRID_COMP_LEGACY:
+ cpu_probe_legacy(c);
+ break;
+ case PRID_COMP_MIPS:
+ cpu_probe_mips(c);
+ break;
+ case PRID_COMP_ALCHEMY:
+ cpu_probe_alchemy(c);
+ break;
+ case PRID_COMP_SIBYTE:
+ cpu_probe_sibyte(c);
+ break;
+
+ case PRID_COMP_SANDCRAFT:
+ cpu_probe_sandcraft(c);
+ break;
+ default:
+ c->cputype = CPU_UNKNOWN;
+ }
+ if (c->options & MIPS_CPU_FPU)
+ c->fpu_id = cpu_get_fpu_id();
+}
+
+__init void cpu_report(void)
+{
+ struct cpuinfo_mips *c = ¤t_cpu_data;
+
+ printk("CPU revision is: %08x\n", c->processor_id);
+ if (c->options & MIPS_CPU_FPU)
+ printk("FPU revision is: %08x\n", c->fpu_id);
+}
diff --git a/arch/mips/kernel/entry.S b/arch/mips/kernel/entry.S
new file mode 100644
index 0000000..5eb4291
--- /dev/null
+++ b/arch/mips/kernel/entry.S
@@ -0,0 +1,155 @@
+/*
+ * 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) 1994 - 2000, 2001, 2003 Ralf Baechle
+ * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
+ * Copyright (C) 2001 MIPS Technologies, Inc.
+ */
+#include <linux/config.h>
+
+#include <asm/asm.h>
+#include <asm/asmmacro.h>
+#include <asm/regdef.h>
+#include <asm/mipsregs.h>
+#include <asm/stackframe.h>
+#include <asm/isadep.h>
+#include <asm/thread_info.h>
+#include <asm/war.h>
+
+#ifdef CONFIG_PREEMPT
+ .macro preempt_stop reg=t0
+ .endm
+#else
+ .macro preempt_stop reg=t0
+ local_irq_disable \reg
+ .endm
+#define resume_kernel restore_all
+#endif
+
+ .text
+ .align 5
+FEXPORT(ret_from_exception)
+ preempt_stop
+FEXPORT(ret_from_irq)
+ LONG_L t0, PT_STATUS(sp) # returning to kernel mode?
+ andi t0, t0, KU_USER
+ beqz t0, resume_kernel
+
+FEXPORT(resume_userspace)
+ local_irq_disable t0 # make sure we dont miss an
+ # interrupt setting need_resched
+ # between sampling and return
+ LONG_L a2, TI_FLAGS($28) # current->work
+ andi a2, _TIF_WORK_MASK # (ignoring syscall_trace)
+ bnez a2, work_pending
+ j restore_all
+
+#ifdef CONFIG_PREEMPT
+ENTRY(resume_kernel)
+ lw t0, TI_PRE_COUNT($28)
+ bnez t0, restore_all
+need_resched:
+ LONG_L t0, TI_FLAGS($28)
+ andi t1, t0, _TIF_NEED_RESCHED
+ beqz t1, restore_all
+ LONG_L t0, PT_STATUS(sp) # Interrupts off?
+ andi t0, 1
+ beqz t0, restore_all
+ li t0, PREEMPT_ACTIVE
+ sw t0, TI_PRE_COUNT($28)
+ local_irq_enable t0
+ jal schedule
+ sw zero, TI_PRE_COUNT($28)
+ local_irq_disable t0
+ b need_resched
+#endif
+
+FEXPORT(ret_from_fork)
+ jal schedule_tail # a0 = task_t *prev
+
+FEXPORT(syscall_exit)
+ local_irq_disable # make sure need_resched and
+ # signals dont change between
+ # sampling and return
+ LONG_L a2, TI_FLAGS($28) # current->work
+ li t0, _TIF_ALLWORK_MASK
+ and t0, a2, t0
+ bnez t0, syscall_exit_work
+
+FEXPORT(restore_all) # restore full frame
+ .set noat
+ RESTORE_TEMP
+ RESTORE_AT
+ RESTORE_STATIC
+FEXPORT(restore_partial) # restore partial frame
+ RESTORE_SOME
+ RESTORE_SP_AND_RET
+ .set at
+
+FEXPORT(work_pending)
+ andi t0, a2, _TIF_NEED_RESCHED
+ beqz t0, work_notifysig
+work_resched:
+ jal schedule
+
+ local_irq_disable t0 # make sure need_resched and
+ # signals dont change between
+ # sampling and return
+ LONG_L a2, TI_FLAGS($28)
+ andi t0, a2, _TIF_WORK_MASK # is there any work to be done
+ # other than syscall tracing?
+ beqz t0, restore_all
+ andi t0, a2, _TIF_NEED_RESCHED
+ bnez t0, work_resched
+
+work_notifysig: # deal with pending signals and
+ # notify-resume requests
+ move a0, sp
+ li a1, 0
+ jal do_notify_resume # a2 already loaded
+ j restore_all
+
+FEXPORT(syscall_exit_work_partial)
+ SAVE_STATIC
+FEXPORT(syscall_exit_work)
+ LONG_L t0, TI_FLAGS($28)
+ li t1, _TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT
+ and t0, t1
+ beqz t0, work_pending # trace bit is set
+ local_irq_enable # could let do_syscall_trace()
+ # call schedule() instead
+ move a0, sp
+ li a1, 1
+ jal do_syscall_trace
+ b resume_userspace
+
+/*
+ * Common spurious interrupt handler.
+ */
+ .text
+ .align 5
+LEAF(spurious_interrupt)
+ /*
+ * Someone tried to fool us by sending an interrupt but we
+ * couldn't find a cause for it.
+ */
+#ifdef CONFIG_SMP
+ lui t1, %hi(irq_err_count)
+1: ll t0, %lo(irq_err_count)(t1)
+ addiu t0, 1
+ sc t0, %lo(irq_err_count)(t1)
+#if R10000_LLSC_WAR
+ beqzl t0, 1b
+#else
+ beqz t0, 1b
+#endif
+#else
+ lui t1, %hi(irq_err_count)
+ lw t0, %lo(irq_err_count)(t1)
+ addiu t0, 1
+ sw t0, %lo(irq_err_count)(t1)
+#endif
+ j ret_from_irq
+ END(spurious_interrupt)
diff --git a/arch/mips/kernel/gdb-low.S b/arch/mips/kernel/gdb-low.S
new file mode 100644
index 0000000..ece6dda
--- /dev/null
+++ b/arch/mips/kernel/gdb-low.S
@@ -0,0 +1,370 @@
+/*
+ * gdb-low.S contains the low-level trap handler for the GDB stub.
+ *
+ * Copyright (C) 1995 Andreas Busse
+ */
+#include <linux/config.h>
+#include <linux/sys.h>
+
+#include <asm/asm.h>
+#include <asm/errno.h>
+#include <asm/mipsregs.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+#include <asm/gdb-stub.h>
+
+#ifdef CONFIG_MIPS32
+#define DMFC0 mfc0
+#define DMTC0 mtc0
+#define LDC1 lwc1
+#define SDC1 lwc1
+#endif
+#ifdef CONFIG_MIPS64
+#define DMFC0 dmfc0
+#define DMTC0 dmtc0
+#define LDC1 ldc1
+#define SDC1 ldc1
+#endif
+
+/*
+ * [jsun] We reserves about 2x GDB_FR_SIZE in stack. The lower (addressed)
+ * part is used to store registers and passed to exception handler.
+ * The upper part is reserved for "call func" feature where gdb client
+ * saves some of the regs, setups call frame and passes args.
+ *
+ * A trace shows about 200 bytes are used to store about half of all regs.
+ * The rest should be big enough for frame setup and passing args.
+ */
+
+/*
+ * The low level trap handler
+ */
+ .align 5
+ NESTED(trap_low, GDB_FR_SIZE, sp)
+ .set noat
+ .set noreorder
+
+ mfc0 k0, CP0_STATUS
+ sll k0, 3 /* extract cu0 bit */
+ bltz k0, 1f
+ move k1, sp
+
+ /*
+ * Called from user mode, go somewhere else.
+ */
+ lui k1, %hi(saved_vectors)
+ mfc0 k0, CP0_CAUSE
+ andi k0, k0, 0x7c
+ add k1, k1, k0
+ lw k0, %lo(saved_vectors)(k1)
+ jr k0
+ nop
+1:
+ move k0, sp
+ subu sp, k1, GDB_FR_SIZE*2 # see comment above
+ LONG_S k0, GDB_FR_REG29(sp)
+ LONG_S $2, GDB_FR_REG2(sp)
+
+/*
+ * First save the CP0 and special registers
+ */
+
+ mfc0 v0, CP0_STATUS
+ LONG_S v0, GDB_FR_STATUS(sp)
+ mfc0 v0, CP0_CAUSE
+ LONG_S v0, GDB_FR_CAUSE(sp)
+ DMFC0 v0, CP0_EPC
+ LONG_S v0, GDB_FR_EPC(sp)
+ DMFC0 v0, CP0_BADVADDR
+ LONG_S v0, GDB_FR_BADVADDR(sp)
+ mfhi v0
+ LONG_S v0, GDB_FR_HI(sp)
+ mflo v0
+ LONG_S v0, GDB_FR_LO(sp)
+
+/*
+ * Now the integer registers
+ */
+
+ LONG_S zero, GDB_FR_REG0(sp) /* I know... */
+ LONG_S $1, GDB_FR_REG1(sp)
+ /* v0 already saved */
+ LONG_S $3, GDB_FR_REG3(sp)
+ LONG_S $4, GDB_FR_REG4(sp)
+ LONG_S $5, GDB_FR_REG5(sp)
+ LONG_S $6, GDB_FR_REG6(sp)
+ LONG_S $7, GDB_FR_REG7(sp)
+ LONG_S $8, GDB_FR_REG8(sp)
+ LONG_S $9, GDB_FR_REG9(sp)
+ LONG_S $10, GDB_FR_REG10(sp)
+ LONG_S $11, GDB_FR_REG11(sp)
+ LONG_S $12, GDB_FR_REG12(sp)
+ LONG_S $13, GDB_FR_REG13(sp)
+ LONG_S $14, GDB_FR_REG14(sp)
+ LONG_S $15, GDB_FR_REG15(sp)
+ LONG_S $16, GDB_FR_REG16(sp)
+ LONG_S $17, GDB_FR_REG17(sp)
+ LONG_S $18, GDB_FR_REG18(sp)
+ LONG_S $19, GDB_FR_REG19(sp)
+ LONG_S $20, GDB_FR_REG20(sp)
+ LONG_S $21, GDB_FR_REG21(sp)
+ LONG_S $22, GDB_FR_REG22(sp)
+ LONG_S $23, GDB_FR_REG23(sp)
+ LONG_S $24, GDB_FR_REG24(sp)
+ LONG_S $25, GDB_FR_REG25(sp)
+ LONG_S $26, GDB_FR_REG26(sp)
+ LONG_S $27, GDB_FR_REG27(sp)
+ LONG_S $28, GDB_FR_REG28(sp)
+ /* sp already saved */
+ LONG_S $30, GDB_FR_REG30(sp)
+ LONG_S $31, GDB_FR_REG31(sp)
+
+ CLI /* disable interrupts */
+
+/*
+ * Followed by the floating point registers
+ */
+ mfc0 v0, CP0_STATUS /* FPU enabled? */
+ srl v0, v0, 16
+ andi v0, v0, (ST0_CU1 >> 16)
+
+ beqz v0,2f /* disabled, skip */
+ nop
+
+ SDC1 $0, GDB_FR_FPR0(sp)
+ SDC1 $1, GDB_FR_FPR1(sp)
+ SDC1 $2, GDB_FR_FPR2(sp)
+ SDC1 $3, GDB_FR_FPR3(sp)
+ SDC1 $4, GDB_FR_FPR4(sp)
+ SDC1 $5, GDB_FR_FPR5(sp)
+ SDC1 $6, GDB_FR_FPR6(sp)
+ SDC1 $7, GDB_FR_FPR7(sp)
+ SDC1 $8, GDB_FR_FPR8(sp)
+ SDC1 $9, GDB_FR_FPR9(sp)
+ SDC1 $10, GDB_FR_FPR10(sp)
+ SDC1 $11, GDB_FR_FPR11(sp)
+ SDC1 $12, GDB_FR_FPR12(sp)
+ SDC1 $13, GDB_FR_FPR13(sp)
+ SDC1 $14, GDB_FR_FPR14(sp)
+ SDC1 $15, GDB_FR_FPR15(sp)
+ SDC1 $16, GDB_FR_FPR16(sp)
+ SDC1 $17, GDB_FR_FPR17(sp)
+ SDC1 $18, GDB_FR_FPR18(sp)
+ SDC1 $19, GDB_FR_FPR19(sp)
+ SDC1 $20, GDB_FR_FPR20(sp)
+ SDC1 $21, GDB_FR_FPR21(sp)
+ SDC1 $22, GDB_FR_FPR22(sp)
+ SDC1 $23, GDB_FR_FPR23(sp)
+ SDC1 $24, GDB_FR_FPR24(sp)
+ SDC1 $25, GDB_FR_FPR25(sp)
+ SDC1 $26, GDB_FR_FPR26(sp)
+ SDC1 $27, GDB_FR_FPR27(sp)
+ SDC1 $28, GDB_FR_FPR28(sp)
+ SDC1 $29, GDB_FR_FPR29(sp)
+ SDC1 $30, GDB_FR_FPR30(sp)
+ SDC1 $31, GDB_FR_FPR31(sp)
+
+/*
+ * FPU control registers
+ */
+
+ cfc1 v0, CP1_STATUS
+ LONG_S v0, GDB_FR_FSR(sp)
+ cfc1 v0, CP1_REVISION
+ LONG_S v0, GDB_FR_FIR(sp)
+
+/*
+ * Current stack frame ptr
+ */
+
+2:
+ LONG_S sp, GDB_FR_FRP(sp)
+
+/*
+ * CP0 registers (R4000/R4400 unused registers skipped)
+ */
+
+ mfc0 v0, CP0_INDEX
+ LONG_S v0, GDB_FR_CP0_INDEX(sp)
+ mfc0 v0, CP0_RANDOM
+ LONG_S v0, GDB_FR_CP0_RANDOM(sp)
+ DMFC0 v0, CP0_ENTRYLO0
+ LONG_S v0, GDB_FR_CP0_ENTRYLO0(sp)
+ DMFC0 v0, CP0_ENTRYLO1
+ LONG_S v0, GDB_FR_CP0_ENTRYLO1(sp)
+ DMFC0 v0, CP0_CONTEXT
+ LONG_S v0, GDB_FR_CP0_CONTEXT(sp)
+ mfc0 v0, CP0_PAGEMASK
+ LONG_S v0, GDB_FR_CP0_PAGEMASK(sp)
+ mfc0 v0, CP0_WIRED
+ LONG_S v0, GDB_FR_CP0_WIRED(sp)
+ DMFC0 v0, CP0_ENTRYHI
+ LONG_S v0, GDB_FR_CP0_ENTRYHI(sp)
+ mfc0 v0, CP0_PRID
+ LONG_S v0, GDB_FR_CP0_PRID(sp)
+
+ .set at
+
+/*
+ * Continue with the higher level handler
+ */
+
+ move a0,sp
+
+ jal handle_exception
+ nop
+
+/*
+ * Restore all writable registers, in reverse order
+ */
+
+ .set noat
+
+ LONG_L v0, GDB_FR_CP0_ENTRYHI(sp)
+ LONG_L v1, GDB_FR_CP0_WIRED(sp)
+ DMTC0 v0, CP0_ENTRYHI
+ mtc0 v1, CP0_WIRED
+ LONG_L v0, GDB_FR_CP0_PAGEMASK(sp)
+ LONG_L v1, GDB_FR_CP0_ENTRYLO1(sp)
+ mtc0 v0, CP0_PAGEMASK
+ DMTC0 v1, CP0_ENTRYLO1
+ LONG_L v0, GDB_FR_CP0_ENTRYLO0(sp)
+ LONG_L v1, GDB_FR_CP0_INDEX(sp)
+ DMTC0 v0, CP0_ENTRYLO0
+ LONG_L v0, GDB_FR_CP0_CONTEXT(sp)
+ mtc0 v1, CP0_INDEX
+ DMTC0 v0, CP0_CONTEXT
+
+
+/*
+ * Next, the floating point registers
+ */
+ mfc0 v0, CP0_STATUS /* check if the FPU is enabled */
+ srl v0, v0, 16
+ andi v0, v0, (ST0_CU1 >> 16)
+
+ beqz v0, 3f /* disabled, skip */
+ nop
+
+ LDC1 $31, GDB_FR_FPR31(sp)
+ LDC1 $30, GDB_FR_FPR30(sp)
+ LDC1 $29, GDB_FR_FPR29(sp)
+ LDC1 $28, GDB_FR_FPR28(sp)
+ LDC1 $27, GDB_FR_FPR27(sp)
+ LDC1 $26, GDB_FR_FPR26(sp)
+ LDC1 $25, GDB_FR_FPR25(sp)
+ LDC1 $24, GDB_FR_FPR24(sp)
+ LDC1 $23, GDB_FR_FPR23(sp)
+ LDC1 $22, GDB_FR_FPR22(sp)
+ LDC1 $21, GDB_FR_FPR21(sp)
+ LDC1 $20, GDB_FR_FPR20(sp)
+ LDC1 $19, GDB_FR_FPR19(sp)
+ LDC1 $18, GDB_FR_FPR18(sp)
+ LDC1 $17, GDB_FR_FPR17(sp)
+ LDC1 $16, GDB_FR_FPR16(sp)
+ LDC1 $15, GDB_FR_FPR15(sp)
+ LDC1 $14, GDB_FR_FPR14(sp)
+ LDC1 $13, GDB_FR_FPR13(sp)
+ LDC1 $12, GDB_FR_FPR12(sp)
+ LDC1 $11, GDB_FR_FPR11(sp)
+ LDC1 $10, GDB_FR_FPR10(sp)
+ LDC1 $9, GDB_FR_FPR9(sp)
+ LDC1 $8, GDB_FR_FPR8(sp)
+ LDC1 $7, GDB_FR_FPR7(sp)
+ LDC1 $6, GDB_FR_FPR6(sp)
+ LDC1 $5, GDB_FR_FPR5(sp)
+ LDC1 $4, GDB_FR_FPR4(sp)
+ LDC1 $3, GDB_FR_FPR3(sp)
+ LDC1 $2, GDB_FR_FPR2(sp)
+ LDC1 $1, GDB_FR_FPR1(sp)
+ LDC1 $0, GDB_FR_FPR0(sp)
+
+/*
+ * Now the CP0 and integer registers
+ */
+
+3:
+ mfc0 t0, CP0_STATUS
+ ori t0, 0x1f
+ xori t0, 0x1f
+ mtc0 t0, CP0_STATUS
+
+ LONG_L v0, GDB_FR_STATUS(sp)
+ LONG_L v1, GDB_FR_EPC(sp)
+ mtc0 v0, CP0_STATUS
+ DMTC0 v1, CP0_EPC
+ LONG_L v0, GDB_FR_HI(sp)
+ LONG_L v1, GDB_FR_LO(sp)
+ mthi v0
+ mtlo v1
+ LONG_L $31, GDB_FR_REG31(sp)
+ LONG_L $30, GDB_FR_REG30(sp)
+ LONG_L $28, GDB_FR_REG28(sp)
+ LONG_L $27, GDB_FR_REG27(sp)
+ LONG_L $26, GDB_FR_REG26(sp)
+ LONG_L $25, GDB_FR_REG25(sp)
+ LONG_L $24, GDB_FR_REG24(sp)
+ LONG_L $23, GDB_FR_REG23(sp)
+ LONG_L $22, GDB_FR_REG22(sp)
+ LONG_L $21, GDB_FR_REG21(sp)
+ LONG_L $20, GDB_FR_REG20(sp)
+ LONG_L $19, GDB_FR_REG19(sp)
+ LONG_L $18, GDB_FR_REG18(sp)
+ LONG_L $17, GDB_FR_REG17(sp)
+ LONG_L $16, GDB_FR_REG16(sp)
+ LONG_L $15, GDB_FR_REG15(sp)
+ LONG_L $14, GDB_FR_REG14(sp)
+ LONG_L $13, GDB_FR_REG13(sp)
+ LONG_L $12, GDB_FR_REG12(sp)
+ LONG_L $11, GDB_FR_REG11(sp)
+ LONG_L $10, GDB_FR_REG10(sp)
+ LONG_L $9, GDB_FR_REG9(sp)
+ LONG_L $8, GDB_FR_REG8(sp)
+ LONG_L $7, GDB_FR_REG7(sp)
+ LONG_L $6, GDB_FR_REG6(sp)
+ LONG_L $5, GDB_FR_REG5(sp)
+ LONG_L $4, GDB_FR_REG4(sp)
+ LONG_L $3, GDB_FR_REG3(sp)
+ LONG_L $2, GDB_FR_REG2(sp)
+ LONG_L $1, GDB_FR_REG1(sp)
+#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)
+ LONG_L k0, GDB_FR_EPC(sp)
+ LONG_L $29, GDB_FR_REG29(sp) /* Deallocate stack */
+ jr k0
+ rfe
+#else
+ LONG_L sp, GDB_FR_REG29(sp) /* Deallocate stack */
+
+ .set mips3
+ eret
+ .set mips0
+#endif
+ .set at
+ .set reorder
+ END(trap_low)
+
+LEAF(kgdb_read_byte)
+4: lb t0, (a0)
+ sb t0, (a1)
+ li v0, 0
+ jr ra
+ .section __ex_table,"a"
+ PTR 4b, kgdbfault
+ .previous
+ END(kgdb_read_byte)
+
+LEAF(kgdb_write_byte)
+5: sb a0, (a1)
+ li v0, 0
+ jr ra
+ .section __ex_table,"a"
+ PTR 5b, kgdbfault
+ .previous
+ END(kgdb_write_byte)
+
+ .type kgdbfault@function
+ .ent kgdbfault
+
+kgdbfault: li v0, -EFAULT
+ jr ra
+ .end kgdbfault
diff --git a/arch/mips/kernel/gdb-stub.c b/arch/mips/kernel/gdb-stub.c
new file mode 100644
index 0000000..2698893
--- /dev/null
+++ b/arch/mips/kernel/gdb-stub.c
@@ -0,0 +1,1091 @@
+/*
+ * arch/mips/kernel/gdb-stub.c
+ *
+ * Originally written by Glenn Engel, Lake Stevens Instrument Division
+ *
+ * Contributed by HP Systems
+ *
+ * Modified for SPARC by Stu Grossman, Cygnus Support.
+ *
+ * Modified for Linux/MIPS (and MIPS in general) by Andreas Busse
+ * Send complaints, suggestions etc. to <andy@waldorf-gmbh.de>
+ *
+ * Copyright (C) 1995 Andreas Busse
+ *
+ * Copyright (C) 2003 MontaVista Software Inc.
+ * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
+ */
+
+/*
+ * To enable debugger support, two things need to happen. One, a
+ * call to set_debug_traps() is necessary in order to allow any breakpoints
+ * or error conditions to be properly intercepted and reported to gdb.
+ * Two, a breakpoint needs to be generated to begin communication. This
+ * is most easily accomplished by a call to breakpoint(). Breakpoint()
+ * simulates a breakpoint by executing a BREAK instruction.
+ *
+ *
+ * The following gdb commands are supported:
+ *
+ * command function Return value
+ *
+ * g return the value of the CPU registers hex data or ENN
+ * G set the value of the CPU registers OK or ENN
+ *
+ * mAA..AA,LLLL Read LLLL bytes at address AA..AA hex data or ENN
+ * MAA..AA,LLLL: Write LLLL bytes at address AA.AA OK or ENN
+ *
+ * c Resume at current address SNN ( signal NN)
+ * cAA..AA Continue at address AA..AA SNN
+ *
+ * s Step one instruction SNN
+ * sAA..AA Step one instruction from AA..AA SNN
+ *
+ * k kill
+ *
+ * ? What was the last sigval ? SNN (signal NN)
+ *
+ * bBB..BB Set baud rate to BB..BB OK or BNN, then sets
+ * baud rate
+ *
+ * All commands and responses are sent with a packet which includes a
+ * checksum. A packet consists of
+ *
+ * $<packet info>#<checksum>.
+ *
+ * where
+ * <packet info> :: <characters representing the command or response>
+ * <checksum> :: < two hex digits computed as modulo 256 sum of <packetinfo>>
+ *
+ * When a packet is received, it is first acknowledged with either '+' or '-'.
+ * '+' indicates a successful transfer. '-' indicates a failed transfer.
+ *
+ * Example:
+ *
+ * Host: Reply:
+ * $m0,10#2a +$00010203040506070809101112131415#42
+ *
+ *
+ * ==============
+ * MORE EXAMPLES:
+ * ==============
+ *
+ * For reference -- the following are the steps that one
+ * company took (RidgeRun Inc) to get remote gdb debugging
+ * going. In this scenario the host machine was a PC and the
+ * target platform was a Galileo EVB64120A MIPS evaluation
+ * board.
+ *
+ * Step 1:
+ * First download gdb-5.0.tar.gz from the internet.
+ * and then build/install the package.
+ *
+ * Example:
+ * $ tar zxf gdb-5.0.tar.gz
+ * $ cd gdb-5.0
+ * $ ./configure --target=mips-linux-elf
+ * $ make
+ * $ install
+ * $ which mips-linux-elf-gdb
+ * /usr/local/bin/mips-linux-elf-gdb
+ *
+ * Step 2:
+ * Configure linux for remote debugging and build it.
+ *
+ * Example:
+ * $ cd ~/linux
+ * $ make menuconfig <go to "Kernel Hacking" and turn on remote debugging>
+ * $ make
+ *
+ * Step 3:
+ * Download the kernel to the remote target and start
+ * the kernel running. It will promptly halt and wait
+ * for the host gdb session to connect. It does this
+ * since the "Kernel Hacking" option has defined
+ * CONFIG_KGDB which in turn enables your calls
+ * to:
+ * set_debug_traps();
+ * breakpoint();
+ *
+ * Step 4:
+ * Start the gdb session on the host.
+ *
+ * Example:
+ * $ mips-linux-elf-gdb vmlinux
+ * (gdb) set remotebaud 115200
+ * (gdb) target remote /dev/ttyS1
+ * ...at this point you are connected to
+ * the remote target and can use gdb
+ * in the normal fasion. Setting
+ * breakpoints, single stepping,
+ * printing variables, etc.
+ */
+#include <linux/config.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/console.h>
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+#include <linux/reboot.h>
+
+#include <asm/asm.h>
+#include <asm/cacheflush.h>
+#include <asm/mipsregs.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include <asm/gdb-stub.h>
+#include <asm/inst.h>
+
+/*
+ * external low-level support routines
+ */
+
+extern int putDebugChar(char c); /* write a single character */
+extern char getDebugChar(void); /* read and return a single char */
+extern void trap_low(void);
+
+/*
+ * breakpoint and test functions
+ */
+extern void breakpoint(void);
+extern void breakinst(void);
+extern void async_breakpoint(void);
+extern void async_breakinst(void);
+extern void adel(void);
+
+/*
+ * local prototypes
+ */
+
+static void getpacket(char *buffer);
+static void putpacket(char *buffer);
+static int computeSignal(int tt);
+static int hex(unsigned char ch);
+static int hexToInt(char **ptr, int *intValue);
+static int hexToLong(char **ptr, long *longValue);
+static unsigned char *mem2hex(char *mem, char *buf, int count, int may_fault);
+void handle_exception(struct gdb_regs *regs);
+
+int kgdb_enabled;
+
+/*
+ * spin locks for smp case
+ */
+static spinlock_t kgdb_lock = SPIN_LOCK_UNLOCKED;
+static spinlock_t kgdb_cpulock[NR_CPUS] = { [0 ... NR_CPUS-1] = SPIN_LOCK_UNLOCKED};
+
+/*
+ * BUFMAX defines the maximum number of characters in inbound/outbound buffers
+ * at least NUMREGBYTES*2 are needed for register packets
+ */
+#define BUFMAX 2048
+
+static char input_buffer[BUFMAX];
+static char output_buffer[BUFMAX];
+static int initialized; /* !0 means we've been initialized */
+static int kgdb_started;
+static const char hexchars[]="0123456789abcdef";
+
+/* Used to prevent crashes in memory access. Note that they'll crash anyway if
+ we haven't set up fault handlers yet... */
+int kgdb_read_byte(unsigned char *address, unsigned char *dest);
+int kgdb_write_byte(unsigned char val, unsigned char *dest);
+
+/*
+ * Convert ch from a hex digit to an int
+ */
+static int hex(unsigned char ch)
+{
+ if (ch >= 'a' && ch <= 'f')
+ return ch-'a'+10;
+ if (ch >= '0' && ch <= '9')
+ return ch-'0';
+ if (ch >= 'A' && ch <= 'F')
+ return ch-'A'+10;
+ return -1;
+}
+
+/*
+ * scan for the sequence $<data>#<checksum>
+ */
+static void getpacket(char *buffer)
+{
+ unsigned char checksum;
+ unsigned char xmitcsum;
+ int i;
+ int count;
+ unsigned char ch;
+
+ do {
+ /*
+ * wait around for the start character,
+ * ignore all other characters
+ */
+ while ((ch = (getDebugChar() & 0x7f)) != '$') ;
+
+ checksum = 0;
+ xmitcsum = -1;
+ count = 0;
+
+ /*
+ * now, read until a # or end of buffer is found
+ */
+ while (count < BUFMAX) {
+ ch = getDebugChar();
+ if (ch == '#')
+ break;
+ checksum = checksum + ch;
+ buffer[count] = ch;
+ count = count + 1;
+ }
+
+ if (count >= BUFMAX)
+ continue;
+
+ buffer[count] = 0;
+
+ if (ch == '#') {
+ xmitcsum = hex(getDebugChar() & 0x7f) << 4;
+ xmitcsum |= hex(getDebugChar() & 0x7f);
+
+ if (checksum != xmitcsum)
+ putDebugChar('-'); /* failed checksum */
+ else {
+ putDebugChar('+'); /* successful transfer */
+
+ /*
+ * if a sequence char is present,
+ * reply the sequence ID
+ */
+ if (buffer[2] == ':') {
+ putDebugChar(buffer[0]);
+ putDebugChar(buffer[1]);
+
+ /*
+ * remove sequence chars from buffer
+ */
+ count = strlen(buffer);
+ for (i=3; i <= count; i++)
+ buffer[i-3] = buffer[i];
+ }
+ }
+ }
+ }
+ while (checksum != xmitcsum);
+}
+
+/*
+ * send the packet in buffer.
+ */
+static void putpacket(char *buffer)
+{
+ unsigned char checksum;
+ int count;
+ unsigned char ch;
+
+ /*
+ * $<packet info>#<checksum>.
+ */
+
+ do {
+ putDebugChar('$');
+ checksum = 0;
+ count = 0;
+
+ while ((ch = buffer[count]) != 0) {
+ if (!(putDebugChar(ch)))
+ return;
+ checksum += ch;
+ count += 1;
+ }
+
+ putDebugChar('#');
+ putDebugChar(hexchars[checksum >> 4]);
+ putDebugChar(hexchars[checksum & 0xf]);
+
+ }
+ while ((getDebugChar() & 0x7f) != '+');
+}
+
+
+/*
+ * Convert the memory pointed to by mem into hex, placing result in buf.
+ * Return a pointer to the last char put in buf (null), in case of mem fault,
+ * return 0.
+ * may_fault is non-zero if we are reading from arbitrary memory, but is currently
+ * not used.
+ */
+static unsigned char *mem2hex(char *mem, char *buf, int count, int may_fault)
+{
+ unsigned char ch;
+
+ while (count-- > 0) {
+ if (kgdb_read_byte(mem++, &ch) != 0)
+ return 0;
+ *buf++ = hexchars[ch >> 4];
+ *buf++ = hexchars[ch & 0xf];
+ }
+
+ *buf = 0;
+
+ return buf;
+}
+
+/*
+ * convert the hex array pointed to by buf into binary to be placed in mem
+ * return a pointer to the character AFTER the last byte written
+ * may_fault is non-zero if we are reading from arbitrary memory, but is currently
+ * not used.
+ */
+static char *hex2mem(char *buf, char *mem, int count, int binary, int may_fault)
+{
+ int i;
+ unsigned char ch;
+
+ for (i=0; i<count; i++)
+ {
+ if (binary) {
+ ch = *buf++;
+ if (ch == 0x7d)
+ ch = 0x20 ^ *buf++;
+ }
+ else {
+ ch = hex(*buf++) << 4;
+ ch |= hex(*buf++);
+ }
+ if (kgdb_write_byte(ch, mem++) != 0)
+ return 0;
+ }
+
+ return mem;
+}
+
+/*
+ * This table contains the mapping between SPARC hardware trap types, and
+ * signals, which are primarily what GDB understands. It also indicates
+ * which hardware traps we need to commandeer when initializing the stub.
+ */
+static struct hard_trap_info {
+ unsigned char tt; /* Trap type code for MIPS R3xxx and R4xxx */
+ unsigned char signo; /* Signal that we map this trap into */
+} hard_trap_info[] = {
+ { 6, SIGBUS }, /* instruction bus error */
+ { 7, SIGBUS }, /* data bus error */
+ { 9, SIGTRAP }, /* break */
+ { 10, SIGILL }, /* reserved instruction */
+/* { 11, SIGILL }, */ /* CPU unusable */
+ { 12, SIGFPE }, /* overflow */
+ { 13, SIGTRAP }, /* trap */
+ { 14, SIGSEGV }, /* virtual instruction cache coherency */
+ { 15, SIGFPE }, /* floating point exception */
+ { 23, SIGSEGV }, /* watch */
+ { 31, SIGSEGV }, /* virtual data cache coherency */
+ { 0, 0} /* Must be last */
+};
+
+/* Save the normal trap handlers for user-mode traps. */
+void *saved_vectors[32];
+
+/*
+ * Set up exception handlers for tracing and breakpoints
+ */
+void set_debug_traps(void)
+{
+ struct hard_trap_info *ht;
+ unsigned long flags;
+ unsigned char c;
+
+ local_irq_save(flags);
+ for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
+ saved_vectors[ht->tt] = set_except_vector(ht->tt, trap_low);
+
+ putDebugChar('+'); /* 'hello world' */
+ /*
+ * In case GDB is started before us, ack any packets
+ * (presumably "$?#xx") sitting there.
+ */
+ while((c = getDebugChar()) != '$');
+ while((c = getDebugChar()) != '#');
+ c = getDebugChar(); /* eat first csum byte */
+ c = getDebugChar(); /* eat second csum byte */
+ putDebugChar('+'); /* ack it */
+
+ initialized = 1;
+ local_irq_restore(flags);
+}
+
+void restore_debug_traps(void)
+{
+ struct hard_trap_info *ht;
+ unsigned long flags;
+
+ local_irq_save(flags);
+ for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
+ set_except_vector(ht->tt, saved_vectors[ht->tt]);
+ local_irq_restore(flags);
+}
+
+/*
+ * Convert the MIPS hardware trap type code to a Unix signal number.
+ */
+static int computeSignal(int tt)
+{
+ struct hard_trap_info *ht;
+
+ for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
+ if (ht->tt == tt)
+ return ht->signo;
+
+ return SIGHUP; /* default for things we don't know about */
+}
+
+/*
+ * While we find nice hex chars, build an int.
+ * Return number of chars processed.
+ */
+static int hexToInt(char **ptr, int *intValue)
+{
+ int numChars = 0;
+ int hexValue;
+
+ *intValue = 0;
+
+ while (**ptr) {
+ hexValue = hex(**ptr);
+ if (hexValue < 0)
+ break;
+
+ *intValue = (*intValue << 4) | hexValue;
+ numChars ++;
+
+ (*ptr)++;
+ }
+
+ return (numChars);
+}
+
+static int hexToLong(char **ptr, long *longValue)
+{
+ int numChars = 0;
+ int hexValue;
+
+ *longValue = 0;
+
+ while (**ptr) {
+ hexValue = hex(**ptr);
+ if (hexValue < 0)
+ break;
+
+ *longValue = (*longValue << 4) | hexValue;
+ numChars ++;
+
+ (*ptr)++;
+ }
+
+ return numChars;
+}
+
+
+#if 0
+/*
+ * Print registers (on target console)
+ * Used only to debug the stub...
+ */
+void show_gdbregs(struct gdb_regs * regs)
+{
+ /*
+ * Saved main processor registers
+ */
+ printk("$0 : %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
+ regs->reg0, regs->reg1, regs->reg2, regs->reg3,
+ regs->reg4, regs->reg5, regs->reg6, regs->reg7);
+ printk("$8 : %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
+ regs->reg8, regs->reg9, regs->reg10, regs->reg11,
+ regs->reg12, regs->reg13, regs->reg14, regs->reg15);
+ printk("$16: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
+ regs->reg16, regs->reg17, regs->reg18, regs->reg19,
+ regs->reg20, regs->reg21, regs->reg22, regs->reg23);
+ printk("$24: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
+ regs->reg24, regs->reg25, regs->reg26, regs->reg27,
+ regs->reg28, regs->reg29, regs->reg30, regs->reg31);
+
+ /*
+ * Saved cp0 registers
+ */
+ printk("epc : %08lx\nStatus: %08lx\nCause : %08lx\n",
+ regs->cp0_epc, regs->cp0_status, regs->cp0_cause);
+}
+#endif /* dead code */
+
+/*
+ * We single-step by setting breakpoints. When an exception
+ * is handled, we need to restore the instructions hoisted
+ * when the breakpoints were set.
+ *
+ * This is where we save the original instructions.
+ */
+static struct gdb_bp_save {
+ unsigned long addr;
+ unsigned int val;
+} step_bp[2];
+
+#define BP 0x0000000d /* break opcode */
+
+/*
+ * Set breakpoint instructions for single stepping.
+ */
+static void single_step(struct gdb_regs *regs)
+{
+ union mips_instruction insn;
+ unsigned long targ;
+ int is_branch, is_cond, i;
+
+ targ = regs->cp0_epc;
+ insn.word = *(unsigned int *)targ;
+ is_branch = is_cond = 0;
+
+ switch (insn.i_format.opcode) {
+ /*
+ * jr and jalr are in r_format format.
+ */
+ case spec_op:
+ switch (insn.r_format.func) {
+ case jalr_op:
+ case jr_op:
+ targ = *(®s->reg0 + insn.r_format.rs);
+ is_branch = 1;
+ break;
+ }
+ break;
+
+ /*
+ * This group contains:
+ * bltz_op, bgez_op, bltzl_op, bgezl_op,
+ * bltzal_op, bgezal_op, bltzall_op, bgezall_op.
+ */
+ case bcond_op:
+ is_branch = is_cond = 1;
+ targ += 4 + (insn.i_format.simmediate << 2);
+ break;
+
+ /*
+ * These are unconditional and in j_format.
+ */
+ case jal_op:
+ case j_op:
+ is_branch = 1;
+ targ += 4;
+ targ >>= 28;
+ targ <<= 28;
+ targ |= (insn.j_format.target << 2);
+ break;
+
+ /*
+ * These are conditional.
+ */
+ case beq_op:
+ case beql_op:
+ case bne_op:
+ case bnel_op:
+ case blez_op:
+ case blezl_op:
+ case bgtz_op:
+ case bgtzl_op:
+ case cop0_op:
+ case cop1_op:
+ case cop2_op:
+ case cop1x_op:
+ is_branch = is_cond = 1;
+ targ += 4 + (insn.i_format.simmediate << 2);
+ break;
+ }
+
+ if (is_branch) {
+ i = 0;
+ if (is_cond && targ != (regs->cp0_epc + 8)) {
+ step_bp[i].addr = regs->cp0_epc + 8;
+ step_bp[i++].val = *(unsigned *)(regs->cp0_epc + 8);
+ *(unsigned *)(regs->cp0_epc + 8) = BP;
+ }
+ step_bp[i].addr = targ;
+ step_bp[i].val = *(unsigned *)targ;
+ *(unsigned *)targ = BP;
+ } else {
+ step_bp[0].addr = regs->cp0_epc + 4;
+ step_bp[0].val = *(unsigned *)(regs->cp0_epc + 4);
+ *(unsigned *)(regs->cp0_epc + 4) = BP;
+ }
+}
+
+/*
+ * If asynchronously interrupted by gdb, then we need to set a breakpoint
+ * at the interrupted instruction so that we wind up stopped with a
+ * reasonable stack frame.
+ */
+static struct gdb_bp_save async_bp;
+
+/*
+ * Swap the interrupted EPC with our asynchronous breakpoint routine.
+ * This is safer than stuffing the breakpoint in-place, since no cache
+ * flushes (or resulting smp_call_functions) are required. The
+ * assumption is that only one CPU will be handling asynchronous bp's,
+ * and only one can be active at a time.
+ */
+extern spinlock_t smp_call_lock;
+void set_async_breakpoint(unsigned long *epc)
+{
+ /* skip breaking into userland */
+ if ((*epc & 0x80000000) == 0)
+ return;
+
+ /* avoid deadlock if someone is make IPC */
+ if (spin_is_locked(&smp_call_lock))
+ return;
+
+ async_bp.addr = *epc;
+ *epc = (unsigned long)async_breakpoint;
+}
+
+void kgdb_wait(void *arg)
+{
+ unsigned flags;
+ int cpu = smp_processor_id();
+
+ local_irq_save(flags);
+
+ spin_lock(&kgdb_cpulock[cpu]);
+ spin_unlock(&kgdb_cpulock[cpu]);
+
+ local_irq_restore(flags);
+}
+
+
+/*
+ * This function does all command processing for interfacing to gdb. It
+ * returns 1 if you should skip the instruction at the trap address, 0
+ * otherwise.
+ */
+void handle_exception (struct gdb_regs *regs)
+{
+ int trap; /* Trap type */
+ int sigval;
+ long addr;
+ int length;
+ char *ptr;
+ unsigned long *stack;
+ int i;
+ int bflag = 0;
+
+ kgdb_started = 1;
+
+ /*
+ * acquire the big kgdb spinlock
+ */
+ if (!spin_trylock(&kgdb_lock)) {
+ /*
+ * some other CPU has the lock, we should go back to
+ * receive the gdb_wait IPC
+ */
+ return;
+ }
+
+ /*
+ * If we're in async_breakpoint(), restore the real EPC from
+ * the breakpoint.
+ */
+ if (regs->cp0_epc == (unsigned long)async_breakinst) {
+ regs->cp0_epc = async_bp.addr;
+ async_bp.addr = 0;
+ }
+
+ /*
+ * acquire the CPU spinlocks
+ */
+ for (i = num_online_cpus()-1; i >= 0; i--)
+ if (spin_trylock(&kgdb_cpulock[i]) == 0)
+ panic("kgdb: couldn't get cpulock %d\n", i);
+
+ /*
+ * force other cpus to enter kgdb
+ */
+ smp_call_function(kgdb_wait, NULL, 0, 0);
+
+ /*
+ * If we're in breakpoint() increment the PC
+ */
+ trap = (regs->cp0_cause & 0x7c) >> 2;
+ if (trap == 9 && regs->cp0_epc == (unsigned long)breakinst)
+ regs->cp0_epc += 4;
+
+ /*
+ * If we were single_stepping, restore the opcodes hoisted
+ * for the breakpoint[s].
+ */
+ if (step_bp[0].addr) {
+ *(unsigned *)step_bp[0].addr = step_bp[0].val;
+ step_bp[0].addr = 0;
+
+ if (step_bp[1].addr) {
+ *(unsigned *)step_bp[1].addr = step_bp[1].val;
+ step_bp[1].addr = 0;
+ }
+ }
+
+ stack = (long *)regs->reg29; /* stack ptr */
+ sigval = computeSignal(trap);
+
+ /*
+ * reply to host that an exception has occurred
+ */
+ ptr = output_buffer;
+
+ /*
+ * Send trap type (converted to signal)
+ */
+ *ptr++ = 'T';
+ *ptr++ = hexchars[sigval >> 4];
+ *ptr++ = hexchars[sigval & 0xf];
+
+ /*
+ * Send Error PC
+ */
+ *ptr++ = hexchars[REG_EPC >> 4];
+ *ptr++ = hexchars[REG_EPC & 0xf];
+ *ptr++ = ':';
+ ptr = mem2hex((char *)®s->cp0_epc, ptr, sizeof(long), 0);
+ *ptr++ = ';';
+
+ /*
+ * Send frame pointer
+ */
+ *ptr++ = hexchars[REG_FP >> 4];
+ *ptr++ = hexchars[REG_FP & 0xf];
+ *ptr++ = ':';
+ ptr = mem2hex((char *)®s->reg30, ptr, sizeof(long), 0);
+ *ptr++ = ';';
+
+ /*
+ * Send stack pointer
+ */
+ *ptr++ = hexchars[REG_SP >> 4];
+ *ptr++ = hexchars[REG_SP & 0xf];
+ *ptr++ = ':';
+ ptr = mem2hex((char *)®s->reg29, ptr, sizeof(long), 0);
+ *ptr++ = ';';
+
+ *ptr++ = 0;
+ putpacket(output_buffer); /* send it off... */
+
+ /*
+ * Wait for input from remote GDB
+ */
+ while (1) {
+ output_buffer[0] = 0;
+ getpacket(input_buffer);
+
+ switch (input_buffer[0])
+ {
+ case '?':
+ output_buffer[0] = 'S';
+ output_buffer[1] = hexchars[sigval >> 4];
+ output_buffer[2] = hexchars[sigval & 0xf];
+ output_buffer[3] = 0;
+ break;
+
+ /*
+ * Detach debugger; let CPU run
+ */
+ case 'D':
+ putpacket(output_buffer);
+ goto finish_kgdb;
+ break;
+
+ case 'd':
+ /* toggle debug flag */
+ break;
+
+ /*
+ * Return the value of the CPU registers
+ */
+ case 'g':
+ ptr = output_buffer;
+ ptr = mem2hex((char *)®s->reg0, ptr, 32*sizeof(long), 0); /* r0...r31 */
+ ptr = mem2hex((char *)®s->cp0_status, ptr, 6*sizeof(long), 0); /* cp0 */
+ ptr = mem2hex((char *)®s->fpr0, ptr, 32*sizeof(long), 0); /* f0...31 */
+ ptr = mem2hex((char *)®s->cp1_fsr, ptr, 2*sizeof(long), 0); /* cp1 */
+ ptr = mem2hex((char *)®s->frame_ptr, ptr, 2*sizeof(long), 0); /* frp */
+ ptr = mem2hex((char *)®s->cp0_index, ptr, 16*sizeof(long), 0); /* cp0 */
+ break;
+
+ /*
+ * set the value of the CPU registers - return OK
+ */
+ case 'G':
+ {
+ ptr = &input_buffer[1];
+ hex2mem(ptr, (char *)®s->reg0, 32*sizeof(long), 0, 0);
+ ptr += 32*(2*sizeof(long));
+ hex2mem(ptr, (char *)®s->cp0_status, 6*sizeof(long), 0, 0);
+ ptr += 6*(2*sizeof(long));
+ hex2mem(ptr, (char *)®s->fpr0, 32*sizeof(long), 0, 0);
+ ptr += 32*(2*sizeof(long));
+ hex2mem(ptr, (char *)®s->cp1_fsr, 2*sizeof(long), 0, 0);
+ ptr += 2*(2*sizeof(long));
+ hex2mem(ptr, (char *)®s->frame_ptr, 2*sizeof(long), 0, 0);
+ ptr += 2*(2*sizeof(long));
+ hex2mem(ptr, (char *)®s->cp0_index, 16*sizeof(long), 0, 0);
+ strcpy(output_buffer,"OK");
+ }
+ break;
+
+ /*
+ * mAA..AA,LLLL Read LLLL bytes at address AA..AA
+ */
+ case 'm':
+ ptr = &input_buffer[1];
+
+ if (hexToLong(&ptr, &addr)
+ && *ptr++ == ','
+ && hexToInt(&ptr, &length)) {
+ if (mem2hex((char *)addr, output_buffer, length, 1))
+ break;
+ strcpy (output_buffer, "E03");
+ } else
+ strcpy(output_buffer,"E01");
+ break;
+
+ /*
+ * XAA..AA,LLLL: Write LLLL escaped binary bytes at address AA.AA
+ */
+ case 'X':
+ bflag = 1;
+ /* fall through */
+
+ /*
+ * MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK
+ */
+ case 'M':
+ ptr = &input_buffer[1];
+
+ if (hexToLong(&ptr, &addr)
+ && *ptr++ == ','
+ && hexToInt(&ptr, &length)
+ && *ptr++ == ':') {
+ if (hex2mem(ptr, (char *)addr, length, bflag, 1))
+ strcpy(output_buffer, "OK");
+ else
+ strcpy(output_buffer, "E03");
+ }
+ else
+ strcpy(output_buffer, "E02");
+ break;
+
+ /*
+ * cAA..AA Continue at address AA..AA(optional)
+ */
+ case 'c':
+ /* try to read optional parameter, pc unchanged if no parm */
+
+ ptr = &input_buffer[1];
+ if (hexToLong(&ptr, &addr))
+ regs->cp0_epc = addr;
+
+ goto exit_kgdb_exception;
+ break;
+
+ /*
+ * kill the program; let us try to restart the machine
+ * Reset the whole machine.
+ */
+ case 'k':
+ case 'r':
+ machine_restart("kgdb restarts machine");
+ break;
+
+ /*
+ * Step to next instruction
+ */
+ case 's':
+ /*
+ * There is no single step insn in the MIPS ISA, so we
+ * use breakpoints and continue, instead.
+ */
+ single_step(regs);
+ goto exit_kgdb_exception;
+ /* NOTREACHED */
+ break;
+
+ /*
+ * Set baud rate (bBB)
+ * FIXME: Needs to be written
+ */
+ case 'b':
+ {
+#if 0
+ int baudrate;
+ extern void set_timer_3();
+
+ ptr = &input_buffer[1];
+ if (!hexToInt(&ptr, &baudrate))
+ {
+ strcpy(output_buffer,"B01");
+ break;
+ }
+
+ /* Convert baud rate to uart clock divider */
+
+ switch (baudrate)
+ {
+ case 38400:
+ baudrate = 16;
+ break;
+ case 19200:
+ baudrate = 33;
+ break;
+ case 9600:
+ baudrate = 65;
+ break;
+ default:
+ baudrate = 0;
+ strcpy(output_buffer,"B02");
+ goto x1;
+ }
+
+ if (baudrate) {
+ putpacket("OK"); /* Ack before changing speed */
+ set_timer_3(baudrate); /* Set it */
+ }
+#endif
+ }
+ break;
+
+ } /* switch */
+
+ /*
+ * reply to the request
+ */
+
+ putpacket(output_buffer);
+
+ } /* while */
+
+ return;
+
+finish_kgdb:
+ restore_debug_traps();
+
+exit_kgdb_exception:
+ /* release locks so other CPUs can go */
+ for (i = num_online_cpus()-1; i >= 0; i--)
+ spin_unlock(&kgdb_cpulock[i]);
+ spin_unlock(&kgdb_lock);
+
+ __flush_cache_all();
+ return;
+}
+
+/*
+ * This function will generate a breakpoint exception. It is used at the
+ * beginning of a program to sync up with a debugger and can be used
+ * otherwise as a quick means to stop program execution and "break" into
+ * the debugger.
+ */
+void breakpoint(void)
+{
+ if (!initialized)
+ return;
+
+ __asm__ __volatile__(
+ ".globl breakinst\n\t"
+ ".set\tnoreorder\n\t"
+ "nop\n"
+ "breakinst:\tbreak\n\t"
+ "nop\n\t"
+ ".set\treorder"
+ );
+}
+
+/* Nothing but the break; don't pollute any registers */
+void async_breakpoint(void)
+{
+ __asm__ __volatile__(
+ ".globl async_breakinst\n\t"
+ ".set\tnoreorder\n\t"
+ "nop\n"
+ "async_breakinst:\tbreak\n\t"
+ "nop\n\t"
+ ".set\treorder"
+ );
+}
+
+void adel(void)
+{
+ __asm__ __volatile__(
+ ".globl\tadel\n\t"
+ "lui\t$8,0x8000\n\t"
+ "lw\t$9,1($8)\n\t"
+ );
+}
+
+/*
+ * malloc is needed by gdb client in "call func()", even a private one
+ * will make gdb happy
+ */
+static void *malloc(size_t size)
+{
+ return kmalloc(size, GFP_ATOMIC);
+}
+
+static void free(void *where)
+{
+ kfree(where);
+}
+
+#ifdef CONFIG_GDB_CONSOLE
+
+void gdb_putsn(const char *str, int l)
+{
+ char outbuf[18];
+
+ if (!kgdb_started)
+ return;
+
+ outbuf[0]='O';
+
+ while(l) {
+ int i = (l>8)?8:l;
+ mem2hex((char *)str, &outbuf[1], i, 0);
+ outbuf[(i*2)+1]=0;
+ putpacket(outbuf);
+ str += i;
+ l -= i;
+ }
+}
+
+static void gdb_console_write(struct console *con, const char *s, unsigned n)
+{
+ gdb_putsn(s, n);
+}
+
+static struct console gdb_console = {
+ .name = "gdb",
+ .write = gdb_console_write,
+ .flags = CON_PRINTBUFFER,
+ .index = -1
+};
+
+static int __init register_gdb_console(void)
+{
+ register_console(&gdb_console);
+
+ return 0;
+}
+
+console_initcall(register_gdb_console);
+
+#endif
diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S
new file mode 100644
index 0000000..a5b0a38
--- /dev/null
+++ b/arch/mips/kernel/genex.S
@@ -0,0 +1,302 @@
+/*
+ * 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) 1994 - 2000, 2001, 2003 Ralf Baechle
+ * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
+ * Copyright (C) 2001 MIPS Technologies, Inc.
+ * Copyright (C) 2002 Maciej W. Rozycki
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+
+#include <asm/asm.h>
+#include <asm/cacheops.h>
+#include <asm/regdef.h>
+#include <asm/fpregdef.h>
+#include <asm/mipsregs.h>
+#include <asm/stackframe.h>
+#include <asm/war.h>
+
+#define PANIC_PIC(msg) \
+ .set push; \
+ .set reorder; \
+ PTR_LA a0,8f; \
+ .set noat; \
+ PTR_LA AT, panic; \
+ jr AT; \
+9: b 9b; \
+ .set pop; \
+ TEXT(msg)
+
+ __INIT
+
+NESTED(except_vec0_generic, 0, sp)
+ PANIC_PIC("Exception vector 0 called")
+ END(except_vec0_generic)
+
+NESTED(except_vec1_generic, 0, sp)
+ PANIC_PIC("Exception vector 1 called")
+ END(except_vec1_generic)
+
+/*
+ * General exception vector for all other CPUs.
+ *
+ * Be careful when changing this, it has to be at most 128 bytes
+ * to fit into space reserved for the exception handler.
+ */
+NESTED(except_vec3_generic, 0, sp)
+ .set push
+ .set noat
+#if R5432_CP0_INTERRUPT_WAR
+ mfc0 k0, CP0_INDEX
+#endif
+ mfc0 k1, CP0_CAUSE
+ andi k1, k1, 0x7c
+#ifdef CONFIG_MIPS64
+ dsll k1, k1, 1
+#endif
+ PTR_L k0, exception_handlers(k1)
+ jr k0
+ .set pop
+ END(except_vec3_generic)
+
+/*
+ * General exception handler for CPUs with virtual coherency exception.
+ *
+ * Be careful when changing this, it has to be at most 256 (as a special
+ * exception) bytes to fit into space reserved for the exception handler.
+ */
+NESTED(except_vec3_r4000, 0, sp)
+ .set push
+ .set mips3
+ .set noat
+ mfc0 k1, CP0_CAUSE
+ li k0, 31<<2
+ andi k1, k1, 0x7c
+ .set push
+ .set noreorder
+ .set nomacro
+ beq k1, k0, handle_vced
+ li k0, 14<<2
+ beq k1, k0, handle_vcei
+#ifdef CONFIG_MIPS64
+ dsll k1, k1, 1
+#endif
+ .set pop
+ PTR_L k0, exception_handlers(k1)
+ jr k0
+
+ /*
+ * Big shit, we now may have two dirty primary cache lines for the same
+ * physical address. We can savely invalidate the line pointed to by
+ * c0_badvaddr because after return from this exception handler the
+ * load / store will be re-executed.
+ */
+handle_vced:
+ DMFC0 k0, CP0_BADVADDR
+ li k1, -4 # Is this ...
+ and k0, k1 # ... really needed?
+ mtc0 zero, CP0_TAGLO
+ cache Index_Store_Tag_D,(k0)
+ cache Hit_Writeback_Inv_SD,(k0)
+#ifdef CONFIG_PROC_FS
+ PTR_LA k0, vced_count
+ lw k1, (k0)
+ addiu k1, 1
+ sw k1, (k0)
+#endif
+ eret
+
+handle_vcei:
+ MFC0 k0, CP0_BADVADDR
+ cache Hit_Writeback_Inv_SD, (k0) # also cleans pi
+#ifdef CONFIG_PROC_FS
+ PTR_LA k0, vcei_count
+ lw k1, (k0)
+ addiu k1, 1
+ sw k1, (k0)
+#endif
+ eret
+ .set pop
+ END(except_vec3_r4000)
+
+/*
+ * Special interrupt vector for MIPS64 ISA & embedded MIPS processors.
+ * This is a dedicated interrupt exception vector which reduces the
+ * interrupt processing overhead. The jump instruction will be replaced
+ * at the initialization time.
+ *
+ * Be careful when changing this, it has to be at most 128 bytes
+ * to fit into space reserved for the exception handler.
+ */
+NESTED(except_vec4, 0, sp)
+1: j 1b /* Dummy, will be replaced */
+ END(except_vec4)
+
+/*
+ * EJTAG debug exception handler.
+ * The EJTAG debug exception entry point is 0xbfc00480, which
+ * normally is in the boot PROM, so the boot PROM must do a
+ * unconditional jump to this vector.
+ */
+NESTED(except_vec_ejtag_debug, 0, sp)
+ j ejtag_debug_handler
+ END(except_vec_ejtag_debug)
+
+ __FINIT
+
+/*
+ * EJTAG debug exception handler.
+ */
+NESTED(ejtag_debug_handler, PT_SIZE, sp)
+ .set push
+ .set noat
+ MTC0 k0, CP0_DESAVE
+ mfc0 k0, CP0_DEBUG
+
+ sll k0, k0, 30 # Check for SDBBP.
+ bgez k0, ejtag_return
+
+ PTR_LA k0, ejtag_debug_buffer
+ LONG_S k1, 0(k0)
+ SAVE_ALL
+ move a0, sp
+ jal ejtag_exception_handler
+ RESTORE_ALL
+ PTR_LA k0, ejtag_debug_buffer
+ LONG_L k1, 0(k0)
+
+ejtag_return:
+ MFC0 k0, CP0_DESAVE
+ .set mips32
+ deret
+ .set pop
+ END(ejtag_debug_handler)
+
+/*
+ * This buffer is reserved for the use of the EJTAG debug
+ * handler.
+ */
+ .data
+EXPORT(ejtag_debug_buffer)
+ .fill LONGSIZE
+ .previous
+
+ __INIT
+
+/*
+ * NMI debug exception handler for MIPS reference boards.
+ * The NMI debug exception entry point is 0xbfc00000, which
+ * normally is in the boot PROM, so the boot PROM must do a
+ * unconditional jump to this vector.
+ */
+NESTED(except_vec_nmi, 0, sp)
+ j nmi_handler
+ END(except_vec_nmi)
+
+ __FINIT
+
+NESTED(nmi_handler, PT_SIZE, sp)
+ .set push
+ .set noat
+ .set mips3
+ SAVE_ALL
+ move a0, sp
+ jal nmi_exception_handler
+ RESTORE_ALL
+ eret
+ .set pop
+ END(nmi_handler)
+
+ .macro __build_clear_none
+ .endm
+
+ .macro __build_clear_sti
+ STI
+ .endm
+
+ .macro __build_clear_cli
+ CLI
+ .endm
+
+ .macro __build_clear_fpe
+ cfc1 a1, fcr31
+ li a2, ~(0x3f << 12)
+ and a2, a1
+ ctc1 a2, fcr31
+ STI
+ .endm
+
+ .macro __build_clear_ade
+ MFC0 t0, CP0_BADVADDR
+ PTR_S t0, PT_BVADDR(sp)
+ KMODE
+ .endm
+
+ .macro __BUILD_silent exception
+ .endm
+
+ /* Gas tries to parse the PRINT argument as a string containing
+ string escapes and emits bogus warnings if it believes to
+ recognize an unknown escape code. So make the arguments
+ start with an n and gas will believe \n is ok ... */
+ .macro __BUILD_verbose nexception
+ LONG_L a1, PT_EPC(sp)
+#if CONFIG_MIPS32
+ PRINT("Got \nexception at %08lx\012")
+#endif
+#if CONFIG_MIPS64
+ PRINT("Got \nexception at %016lx\012")
+#endif
+ .endm
+
+ .macro __BUILD_count exception
+ LONG_L t0,exception_count_\exception
+ LONG_ADDIU t0, 1
+ LONG_S t0,exception_count_\exception
+ .comm exception_count\exception, 8, 8
+ .endm
+
+ .macro __BUILD_HANDLER exception handler clear verbose ext
+ .align 5
+ NESTED(handle_\exception, PT_SIZE, sp)
+ .set noat
+ SAVE_ALL
+ FEXPORT(handle_\exception\ext)
+ __BUILD_clear_\clear
+ .set at
+ __BUILD_\verbose \exception
+ move a0, sp
+ jal do_\handler
+ j ret_from_exception
+ END(handle_\exception)
+ .endm
+
+ .macro BUILD_HANDLER exception handler clear verbose
+ __BUILD_HANDLER \exception \handler \clear \verbose _int
+ .endm
+
+ BUILD_HANDLER adel ade ade silent /* #4 */
+ BUILD_HANDLER ades ade ade silent /* #5 */
+ BUILD_HANDLER ibe be cli silent /* #6 */
+ BUILD_HANDLER dbe be cli silent /* #7 */
+ BUILD_HANDLER bp bp sti silent /* #9 */
+ BUILD_HANDLER ri ri sti silent /* #10 */
+ BUILD_HANDLER cpu cpu sti silent /* #11 */
+ BUILD_HANDLER ov ov sti silent /* #12 */
+ BUILD_HANDLER tr tr sti silent /* #13 */
+ BUILD_HANDLER fpe fpe fpe silent /* #15 */
+ BUILD_HANDLER mdmx mdmx sti silent /* #22 */
+ BUILD_HANDLER watch watch sti verbose /* #23 */
+ BUILD_HANDLER mcheck mcheck cli verbose /* #24 */
+ BUILD_HANDLER reserved reserved sti verbose /* others */
+
+#ifdef CONFIG_MIPS64
+/* A temporary overflow handler used by check_daddi(). */
+
+ __INIT
+
+ BUILD_HANDLER daddi_ov daddi_ov none silent /* #12 */
+#endif
diff --git a/arch/mips/kernel/genrtc.c b/arch/mips/kernel/genrtc.c
new file mode 100644
index 0000000..288bf51
--- /dev/null
+++ b/arch/mips/kernel/genrtc.c
@@ -0,0 +1,64 @@
+/*
+ * A glue layer that provides RTC read/write to drivers/char/genrtc.c driver
+ * based on MIPS internal RTC routines. It does take care locking
+ * issues so that we are SMP/Preemption safe.
+ *
+ * Copyright (C) 2004 MontaVista Software Inc.
+ * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
+ *
+ * Please read the COPYING file for all license details.
+ */
+
+#include <linux/spinlock.h>
+
+#include <asm/rtc.h>
+#include <asm/time.h>
+
+static spinlock_t mips_rtc_lock = SPIN_LOCK_UNLOCKED;
+
+unsigned int get_rtc_time(struct rtc_time *time)
+{
+ unsigned long nowtime;
+
+ spin_lock(&mips_rtc_lock);
+ nowtime = rtc_get_time();
+ to_tm(nowtime, time);
+ time->tm_year -= 1900;
+ spin_unlock(&mips_rtc_lock);
+
+ return RTC_24H;
+}
+
+int set_rtc_time(struct rtc_time *time)
+{
+ unsigned long nowtime;
+ int ret;
+
+ spin_lock(&mips_rtc_lock);
+ nowtime = mktime(time->tm_year+1900, time->tm_mon+1,
+ time->tm_mday, time->tm_hour, time->tm_min,
+ time->tm_sec);
+ ret = rtc_set_time(nowtime);
+ spin_unlock(&mips_rtc_lock);
+
+ return ret;
+}
+
+unsigned int get_rtc_ss(void)
+{
+ struct rtc_time h;
+
+ get_rtc_time(&h);
+ return h.tm_sec;
+}
+
+int get_rtc_pll(struct rtc_pll_info *pll)
+{
+ return -EINVAL;
+}
+
+int set_rtc_pll(struct rtc_pll_info *pll)
+{
+ return -EINVAL;
+}
+
diff --git a/arch/mips/kernel/head.S b/arch/mips/kernel/head.S
new file mode 100644
index 0000000..a64e87d
--- /dev/null
+++ b/arch/mips/kernel/head.S
@@ -0,0 +1,221 @@
+/*
+ * 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) 1994, 1995 Waldorf Electronics
+ * Written by Ralf Baechle and Andreas Busse
+ * Copyright (C) 1994, 95, 96, 97, 98, 99, 2003 Ralf Baechle
+ * Copyright (C) 1996 Paul M. Antoine
+ * Modified for DECStation and hence R3000 support by Paul M. Antoine
+ * Further modifications by David S. Miller and Harald Koerfgen
+ * Copyright (C) 1999 Silicon Graphics, Inc.
+ * Kevin Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/threads.h>
+
+#include <asm/asm.h>
+#include <asm/regdef.h>
+#include <asm/page.h>
+#include <asm/mipsregs.h>
+#include <asm/stackframe.h>
+#ifdef CONFIG_SGI_IP27
+#include <asm/sn/addrs.h>
+#include <asm/sn/sn0/hubni.h>
+#include <asm/sn/klkernvars.h>
+#endif
+
+ .macro ARC64_TWIDDLE_PC
+#if defined(CONFIG_ARC64) || defined(CONFIG_MAPPED_KERNEL)
+ /* We get launched at a XKPHYS address but the kernel is linked to
+ run at a KSEG0 address, so jump there. */
+ PTR_LA t0, \@f
+ jr t0
+\@:
+#endif
+ .endm
+
+#ifdef CONFIG_SGI_IP27
+ /*
+ * outputs the local nasid into res. IP27 stuff.
+ */
+ .macro GET_NASID_ASM res
+ dli \res, LOCAL_HUB_ADDR(NI_STATUS_REV_ID)
+ ld \res, (\res)
+ and \res, NSRI_NODEID_MASK
+ dsrl \res, NSRI_NODEID_SHFT
+ .endm
+#endif /* CONFIG_SGI_IP27 */
+
+ /*
+ * inputs are the text nasid in t1, data nasid in t2.
+ */
+ .macro MAPPED_KERNEL_SETUP_TLB
+#ifdef CONFIG_MAPPED_KERNEL
+ /*
+ * This needs to read the nasid - assume 0 for now.
+ * Drop in 0xffffffffc0000000 in tlbhi, 0+VG in tlblo_0,
+ * 0+DVG in tlblo_1.
+ */
+ dli t0, 0xffffffffc0000000
+ dmtc0 t0, CP0_ENTRYHI
+ li t0, 0x1c000 # Offset of text into node memory
+ dsll t1, NASID_SHFT # Shift text nasid into place
+ dsll t2, NASID_SHFT # Same for data nasid
+ or t1, t1, t0 # Physical load address of kernel text
+ or t2, t2, t0 # Physical load address of kernel data
+ dsrl t1, 12 # 4K pfn
+ dsrl t2, 12 # 4K pfn
+ dsll t1, 6 # Get pfn into place
+ dsll t2, 6 # Get pfn into place
+ li t0, ((_PAGE_GLOBAL|_PAGE_VALID| _CACHE_CACHABLE_COW) >> 6)
+ or t0, t0, t1
+ mtc0 t0, CP0_ENTRYLO0 # physaddr, VG, cach exlwr
+ li t0, ((_PAGE_GLOBAL|_PAGE_VALID| _PAGE_DIRTY|_CACHE_CACHABLE_COW) >> 6)
+ or t0, t0, t2
+ mtc0 t0, CP0_ENTRYLO1 # physaddr, DVG, cach exlwr
+ li t0, 0x1ffe000 # MAPPED_KERN_TLBMASK, TLBPGMASK_16M
+ mtc0 t0, CP0_PAGEMASK
+ li t0, 0 # KMAP_INX
+ mtc0 t0, CP0_INDEX
+ li t0, 1
+ mtc0 t0, CP0_WIRED
+ tlbwi
+#else
+ mtc0 zero, CP0_WIRED
+#endif
+ .endm
+
+ /*
+ * For the moment disable interrupts, mark the kernel mode and
+ * set ST0_KX so that the CPU does not spit fire when using
+ * 64-bit addresses. A full initialization of the CPU's status
+ * register is done later in per_cpu_trap_init().
+ */
+ .macro setup_c0_status set clr
+ .set push
+ mfc0 t0, CP0_STATUS
+ or t0, ST0_CU0|\set|0x1f|\clr
+ xor t0, 0x1f|\clr
+ mtc0 t0, CP0_STATUS
+ .set noreorder
+ sll zero,3 # ehb
+ .set pop
+ .endm
+
+ .macro setup_c0_status_pri
+#ifdef CONFIG_MIPS64
+ setup_c0_status ST0_KX 0
+#else
+ setup_c0_status 0 0
+#endif
+ .endm
+
+ .macro setup_c0_status_sec
+#ifdef CONFIG_MIPS64
+ setup_c0_status ST0_KX ST0_BEV
+#else
+ setup_c0_status 0 ST0_BEV
+#endif
+ .endm
+
+ /*
+ * Reserved space for exception handlers.
+ * Necessary for machines which link their kernels at KSEG0.
+ */
+ .fill 0x400
+
+EXPORT(stext) # used for profiling
+EXPORT(_stext)
+
+ __INIT
+
+NESTED(kernel_entry, 16, sp) # kernel entry point
+ setup_c0_status_pri
+
+#ifdef CONFIG_SGI_IP27
+ GET_NASID_ASM t1
+ move t2, t1 # text and data are here
+ MAPPED_KERNEL_SETUP_TLB
+#endif /* IP27 */
+
+ ARC64_TWIDDLE_PC
+
+ PTR_LA t0, __bss_start # clear .bss
+ LONG_S zero, (t0)
+ PTR_LA t1, __bss_stop - LONGSIZE
+1:
+ PTR_ADDIU t0, LONGSIZE
+ LONG_S zero, (t0)
+ bne t0, t1, 1b
+
+ LONG_S a0, fw_arg0 # firmware arguments
+ LONG_S a1, fw_arg1
+ LONG_S a2, fw_arg2
+ LONG_S a3, fw_arg3
+
+ PTR_LA $28, init_thread_union
+ PTR_ADDIU sp, $28, _THREAD_SIZE - 32
+ set_saved_sp sp, t0, t1
+ PTR_SUBU sp, 4 * SZREG # init stack pointer
+
+ j start_kernel
+ END(kernel_entry)
+
+#ifdef CONFIG_SMP
+/*
+ * SMP slave cpus entry point. Board specific code for bootstrap calls this
+ * function after setting up the stack and gp registers.
+ */
+NESTED(smp_bootstrap, 16, sp)
+ setup_c0_status_sec
+
+#ifdef CONFIG_SGI_IP27
+ GET_NASID_ASM t1
+ dli t0, KLDIR_OFFSET + (KLI_KERN_VARS * KLDIR_ENT_SIZE) + \
+ KLDIR_OFF_POINTER + CAC_BASE
+ dsll t1, NASID_SHFT
+ or t0, t0, t1
+ ld t0, 0(t0) # t0 points to kern_vars struct
+ lh t1, KV_RO_NASID_OFFSET(t0)
+ lh t2, KV_RW_NASID_OFFSET(t0)
+ MAPPED_KERNEL_SETUP_TLB
+ ARC64_TWIDDLE_PC
+#endif /* CONFIG_SGI_IP27 */
+
+ j start_secondary
+ END(smp_bootstrap)
+#endif /* CONFIG_SMP */
+
+ __FINIT
+
+ .comm kernelsp, NR_CPUS * 8, 8
+ .comm pgd_current, NR_CPUS * 8, 8
+
+ .comm fw_arg0, SZREG, SZREG # firmware arguments
+ .comm fw_arg1, SZREG, SZREG
+ .comm fw_arg2, SZREG, SZREG
+ .comm fw_arg3, SZREG, SZREG
+
+ .macro page name, order=0
+ .globl \name
+\name: .size \name, (_PAGE_SIZE << \order)
+ .org . + (_PAGE_SIZE << \order)
+ .type \name, @object
+ .endm
+
+ .data
+ .align PAGE_SHIFT
+
+ /*
+ * ... but on 64-bit we've got three-level pagetables with a
+ * slightly different layout ...
+ */
+ page swapper_pg_dir, _PGD_ORDER
+#ifdef CONFIG_MIPS64
+ page invalid_pmd_table, _PMD_ORDER
+#endif
+ page invalid_pte_table, _PTE_ORDER
diff --git a/arch/mips/kernel/i8259.c b/arch/mips/kernel/i8259.c
new file mode 100644
index 0000000..7eec756
--- /dev/null
+++ b/arch/mips/kernel/i8259.c
@@ -0,0 +1,331 @@
+/*
+ * 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.
+ *
+ * Code to handle x86 style IRQs plus some generic interrupt stuff.
+ *
+ * Copyright (C) 1992 Linus Torvalds
+ * Copyright (C) 1994 - 2000 Ralf Baechle
+ */
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/sysdev.h>
+
+#include <asm/i8259.h>
+#include <asm/io.h>
+
+void enable_8259A_irq(unsigned int irq);
+void disable_8259A_irq(unsigned int irq);
+
+/*
+ * This is the 'legacy' 8259A Programmable Interrupt Controller,
+ * present in the majority of PC/AT boxes.
+ * plus some generic x86 specific things if generic specifics makes
+ * any sense at all.
+ * this file should become arch/i386/kernel/irq.c when the old irq.c
+ * moves to arch independent land
+ */
+
+spinlock_t i8259A_lock = SPIN_LOCK_UNLOCKED;
+
+static void end_8259A_irq (unsigned int irq)
+{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)) &&
+ irq_desc[irq].action)
+ enable_8259A_irq(irq);
+}
+
+#define shutdown_8259A_irq disable_8259A_irq
+
+void mask_and_ack_8259A(unsigned int);
+
+static unsigned int startup_8259A_irq(unsigned int irq)
+{
+ enable_8259A_irq(irq);
+
+ return 0; /* never anything pending */
+}
+
+static struct hw_interrupt_type i8259A_irq_type = {
+ "XT-PIC",
+ startup_8259A_irq,
+ shutdown_8259A_irq,
+ enable_8259A_irq,
+ disable_8259A_irq,
+ mask_and_ack_8259A,
+ end_8259A_irq,
+ NULL
+};
+
+/*
+ * 8259A PIC functions to handle ISA devices:
+ */
+
+/*
+ * This contains the irq mask for both 8259A irq controllers,
+ */
+static unsigned int cached_irq_mask = 0xffff;
+
+#define cached_21 (cached_irq_mask)
+#define cached_A1 (cached_irq_mask >> 8)
+
+void disable_8259A_irq(unsigned int irq)
+{
+ unsigned int mask = 1 << irq;
+ unsigned long flags;
+
+ spin_lock_irqsave(&i8259A_lock, flags);
+ cached_irq_mask |= mask;
+ if (irq & 8)
+ outb(cached_A1,0xA1);
+ else
+ outb(cached_21,0x21);
+ spin_unlock_irqrestore(&i8259A_lock, flags);
+}
+
+void enable_8259A_irq(unsigned int irq)
+{
+ unsigned int mask = ~(1 << irq);
+ unsigned long flags;
+
+ spin_lock_irqsave(&i8259A_lock, flags);
+ cached_irq_mask &= mask;
+ if (irq & 8)
+ outb(cached_A1,0xA1);
+ else
+ outb(cached_21,0x21);
+ spin_unlock_irqrestore(&i8259A_lock, flags);
+}
+
+int i8259A_irq_pending(unsigned int irq)
+{
+ unsigned int mask = 1 << irq;
+ unsigned long flags;
+ int ret;
+
+ spin_lock_irqsave(&i8259A_lock, flags);
+ if (irq < 8)
+ ret = inb(0x20) & mask;
+ else
+ ret = inb(0xA0) & (mask >> 8);
+ spin_unlock_irqrestore(&i8259A_lock, flags);
+
+ return ret;
+}
+
+void make_8259A_irq(unsigned int irq)
+{
+ disable_irq_nosync(irq);
+ irq_desc[irq].handler = &i8259A_irq_type;
+ enable_irq(irq);
+}
+
+/*
+ * This function assumes to be called rarely. Switching between
+ * 8259A registers is slow.
+ * This has to be protected by the irq controller spinlock
+ * before being called.
+ */
+static inline int i8259A_irq_real(unsigned int irq)
+{
+ int value;
+ int irqmask = 1 << irq;
+
+ if (irq < 8) {
+ outb(0x0B,0x20); /* ISR register */
+ value = inb(0x20) & irqmask;
+ outb(0x0A,0x20); /* back to the IRR register */
+ return value;
+ }
+ outb(0x0B,0xA0); /* ISR register */
+ value = inb(0xA0) & (irqmask >> 8);
+ outb(0x0A,0xA0); /* back to the IRR register */
+ return value;
+}
+
+/*
+ * Careful! The 8259A is a fragile beast, it pretty
+ * much _has_ to be done exactly like this (mask it
+ * first, _then_ send the EOI, and the order of EOI
+ * to the two 8259s is important!
+ */
+void mask_and_ack_8259A(unsigned int irq)
+{
+ unsigned int irqmask = 1 << irq;
+ unsigned long flags;
+
+ spin_lock_irqsave(&i8259A_lock, flags);
+ /*
+ * Lightweight spurious IRQ detection. We do not want to overdo
+ * spurious IRQ handling - it's usually a sign of hardware problems, so
+ * we only do the checks we can do without slowing down good hardware
+ * nnecesserily.
+ *
+ * Note that IRQ7 and IRQ15 (the two spurious IRQs usually resulting
+ * rom the 8259A-1|2 PICs) occur even if the IRQ is masked in the 8259A.
+ * Thus we can check spurious 8259A IRQs without doing the quite slow
+ * i8259A_irq_real() call for every IRQ. This does not cover 100% of
+ * spurious interrupts, but should be enough to warn the user that
+ * there is something bad going on ...
+ */
+ if (cached_irq_mask & irqmask)
+ goto spurious_8259A_irq;
+ cached_irq_mask |= irqmask;
+
+handle_real_irq:
+ if (irq & 8) {
+ inb(0xA1); /* DUMMY - (do we need this?) */
+ outb(cached_A1,0xA1);
+ outb(0x60+(irq&7),0xA0);/* 'Specific EOI' to slave */
+ outb(0x62,0x20); /* 'Specific EOI' to master-IRQ2 */
+ } else {
+ inb(0x21); /* DUMMY - (do we need this?) */
+ outb(cached_21,0x21);
+ outb(0x60+irq,0x20); /* 'Specific EOI' to master */
+ }
+ spin_unlock_irqrestore(&i8259A_lock, flags);
+ return;
+
+spurious_8259A_irq:
+ /*
+ * this is the slow path - should happen rarely.
+ */
+ if (i8259A_irq_real(irq))
+ /*
+ * oops, the IRQ _is_ in service according to the
+ * 8259A - not spurious, go handle it.
+ */
+ goto handle_real_irq;
+
+ {
+ static int spurious_irq_mask = 0;
+ /*
+ * At this point we can be sure the IRQ is spurious,
+ * lets ACK and report it. [once per IRQ]
+ */
+ if (!(spurious_irq_mask & irqmask)) {
+ printk(KERN_DEBUG "spurious 8259A interrupt: IRQ%d.\n", irq);
+ spurious_irq_mask |= irqmask;
+ }
+ atomic_inc(&irq_err_count);
+ /*
+ * Theoretically we do not have to handle this IRQ,
+ * but in Linux this does not cause problems and is
+ * simpler for us.
+ */
+ goto handle_real_irq;
+ }
+}
+
+static int i8259A_resume(struct sys_device *dev)
+{
+ init_8259A(0);
+ return 0;
+}
+
+static struct sysdev_class i8259_sysdev_class = {
+ set_kset_name("i8259"),
+ .resume = i8259A_resume,
+};
+
+static struct sys_device device_i8259A = {
+ .id = 0,
+ .cls = &i8259_sysdev_class,
+};
+
+static int __init i8259A_init_sysfs(void)
+{
+ int error = sysdev_class_register(&i8259_sysdev_class);
+ if (!error)
+ error = sysdev_register(&device_i8259A);
+ return error;
+}
+
+device_initcall(i8259A_init_sysfs);
+
+void __init init_8259A(int auto_eoi)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&i8259A_lock, flags);
+
+ outb(0xff, 0x21); /* mask all of 8259A-1 */
+ outb(0xff, 0xA1); /* mask all of 8259A-2 */
+
+ /*
+ * outb_p - this has to work on a wide range of PC hardware.
+ */
+ outb_p(0x11, 0x20); /* ICW1: select 8259A-1 init */
+ outb_p(0x00, 0x21); /* ICW2: 8259A-1 IR0-7 mapped to 0x00-0x07 */
+ outb_p(0x04, 0x21); /* 8259A-1 (the master) has a slave on IR2 */
+ if (auto_eoi)
+ outb_p(0x03, 0x21); /* master does Auto EOI */
+ else
+ outb_p(0x01, 0x21); /* master expects normal EOI */
+
+ outb_p(0x11, 0xA0); /* ICW1: select 8259A-2 init */
+ outb_p(0x08, 0xA1); /* ICW2: 8259A-2 IR0-7 mapped to 0x08-0x0f */
+ outb_p(0x02, 0xA1); /* 8259A-2 is a slave on master's IR2 */
+ outb_p(0x01, 0xA1); /* (slave's support for AEOI in flat mode
+ is to be investigated) */
+
+ if (auto_eoi)
+ /*
+ * in AEOI mode we just have to mask the interrupt
+ * when acking.
+ */
+ i8259A_irq_type.ack = disable_8259A_irq;
+ else
+ i8259A_irq_type.ack = mask_and_ack_8259A;
+
+ udelay(100); /* wait for 8259A to initialize */
+
+ outb(cached_21, 0x21); /* restore master IRQ mask */
+ outb(cached_A1, 0xA1); /* restore slave IRQ mask */
+
+ spin_unlock_irqrestore(&i8259A_lock, flags);
+}
+
+/*
+ * IRQ2 is cascade interrupt to second interrupt controller
+ */
+static struct irqaction irq2 = {
+ no_action, 0, CPU_MASK_NONE, "cascade", NULL, NULL
+};
+
+static struct resource pic1_io_resource = {
+ "pic1", 0x20, 0x3f, IORESOURCE_BUSY
+};
+
+static struct resource pic2_io_resource = {
+ "pic2", 0xa0, 0xbf, IORESOURCE_BUSY
+};
+
+/*
+ * On systems with i8259-style interrupt controllers we assume for
+ * driver compatibility reasons interrupts 0 - 15 to be the i8295
+ * interrupts even if the hardware uses a different interrupt numbering.
+ */
+void __init init_i8259_irqs (void)
+{
+ int i;
+
+ request_resource(&ioport_resource, &pic1_io_resource);
+ request_resource(&ioport_resource, &pic2_io_resource);
+
+ init_8259A(0);
+
+ for (i = 0; i < 16; i++) {
+ irq_desc[i].status = IRQ_DISABLED;
+ irq_desc[i].action = 0;
+ irq_desc[i].depth = 1;
+ irq_desc[i].handler = &i8259A_irq_type;
+ }
+
+ setup_irq(2, &irq2);
+}
diff --git a/arch/mips/kernel/init_task.c b/arch/mips/kernel/init_task.c
new file mode 100644
index 0000000..aeda7f5
--- /dev/null
+++ b/arch/mips/kernel/init_task.c
@@ -0,0 +1,42 @@
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/init_task.h>
+#include <linux/fs.h>
+#include <linux/mqueue.h>
+
+#include <asm/thread_info.h>
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+
+static struct fs_struct init_fs = INIT_FS;
+static struct files_struct init_files = INIT_FILES;
+static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
+static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
+struct mm_struct init_mm = INIT_MM(init_mm);
+
+EXPORT_SYMBOL(init_mm);
+
+/*
+ * Initial thread structure.
+ *
+ * We need to make sure that this is 8192-byte aligned due to the
+ * way process stacks are handled. This is done by making sure
+ * the linker maps this in the .text segment right after head.S,
+ * and making head.S ensure the proper alignment.
+ *
+ * The things we do for performance..
+ */
+union thread_union init_thread_union
+ __attribute__((__section__(".data.init_task"),
+ __aligned__(THREAD_SIZE))) =
+ { INIT_THREAD_INFO(init_task) };
+
+/*
+ * Initial task structure.
+ *
+ * All other task structs will be allocated on slabs in fork.c
+ */
+struct task_struct init_task = INIT_TASK(init_task);
+
+EXPORT_SYMBOL(init_task);
diff --git a/arch/mips/kernel/ioctl32.c b/arch/mips/kernel/ioctl32.c
new file mode 100644
index 0000000..519cd5d
--- /dev/null
+++ b/arch/mips/kernel/ioctl32.c
@@ -0,0 +1,58 @@
+/*
+ * ioctl32.c: Conversion between 32bit and 64bit native ioctls.
+ *
+ * Copyright (C) 2000 Silicon Graphics, Inc.
+ * Written by Ulf Carlsson (ulfc@engr.sgi.com)
+ * Copyright (C) 2000, 2004 Ralf Baechle
+ * Copyright (C) 2002, 2003 Maciej W. Rozycki
+ */
+#define INCLUDES
+#include "compat_ioctl.c"
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/compat.h>
+#include <linux/ioctl32.h>
+#include <linux/syscalls.h>
+
+#ifdef CONFIG_SIBYTE_TBPROF
+#include <asm/sibyte/trace_prof.h>
+#endif
+
+#define A(__x) ((unsigned long)(__x))
+
+long sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg);
+
+#define CODE
+#include "compat_ioctl.c"
+
+typedef int (* ioctl32_handler_t)(unsigned int, unsigned int, unsigned long, struct file *);
+
+#define COMPATIBLE_IOCTL(cmd) HANDLE_IOCTL((cmd),sys_ioctl)
+#define HANDLE_IOCTL(cmd,handler) { (cmd), (ioctl32_handler_t)(handler), NULL },
+#define IOCTL_TABLE_START \
+ struct ioctl_trans ioctl_start[] = {
+#define IOCTL_TABLE_END \
+ };
+
+IOCTL_TABLE_START
+
+#include <linux/compat_ioctl.h>
+#define DECLARES
+#include "compat_ioctl.c"
+
+#ifdef CONFIG_SIBYTE_TBPROF
+COMPATIBLE_IOCTL(SBPROF_ZBSTART)
+COMPATIBLE_IOCTL(SBPROF_ZBSTOP)
+COMPATIBLE_IOCTL(SBPROF_ZBWAITFULL)
+#endif /* CONFIG_SIBYTE_TBPROF */
+
+/*HANDLE_IOCTL(RTC_IRQP_READ, w_long)
+COMPATIBLE_IOCTL(RTC_IRQP_SET)
+HANDLE_IOCTL(RTC_EPOCH_READ, w_long)
+COMPATIBLE_IOCTL(RTC_EPOCH_SET)
+*/
+
+IOCTL_TABLE_END
+
+int ioctl_table_size = ARRAY_SIZE(ioctl_start);
diff --git a/arch/mips/kernel/irix5sys.S b/arch/mips/kernel/irix5sys.S
new file mode 100644
index 0000000..eeef891
--- /dev/null
+++ b/arch/mips/kernel/irix5sys.S
@@ -0,0 +1,1041 @@
+/*
+ * 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.
+ *
+ * 32-bit IRIX5 ABI system call table derived from original file 'irix5sys.h'
+ * created by David S. Miller.
+ *
+ * Copyright (C) 1996 - 2004 David S. Miller <dm@engr.sgi.com>
+ * Copyright (C) 2004 Steven J. Hill <sjhill@realitydiluted.com>
+ */
+#include <asm/asm.h>
+
+ /*
+ * Key:
+ * V == Valid and should work as expected for most cases.
+ * HV == Half Valid, some things will work, some likely will not
+ * IV == InValid, certainly will not work at all yet
+ * ?V == ?'ably Valid, I have not done enough looking into it
+ * DC == Don't Care, a rats ass we couldn't give
+ */
+
+ .macro irix5syscalltable
+
+ sys sys_syscall 0 /* 1000 sysindir() V*/
+ sys sys_exit 1 /* 1001 exit() V*/
+ sys sys_fork 0 /* 1002 fork() V*/
+ sys sys_read 3 /* 1003 read() V*/
+ sys sys_write 3 /* 1004 write() V*/
+ sys sys_open 3 /* 1005 open() V*/
+ sys sys_close 1 /* 1006 close() V*/
+ sys irix_unimp 0 /* 1007 (XXX IRIX 4 wait) V*/
+ sys sys_creat 2 /* 1008 creat() V*/
+ sys sys_link 2 /* 1009 link() V*/
+ sys sys_unlink 1 /* 1010 unlink() V*/
+ sys irix_exec 0 /* 1011 exec() V*/
+ sys sys_chdir 1 /* 1012 chdir() V*/
+ sys irix_gtime 0 /* 1013 time() V*/
+ sys irix_unimp 0 /* 1014 (XXX IRIX 4 mknod) V*/
+ sys sys_chmod 2 /* 1015 chmod() V*/
+ sys sys_chown 3 /* 1016 chown() V*/
+ sys irix_brk 1 /* 1017 break() V*/
+ sys irix_unimp 0 /* 1018 (XXX IRIX 4 stat) V*/
+ sys sys_lseek 3 /* 1019 lseek() XXX64bit HV*/
+ sys irix_getpid 0 /* 1020 getpid() V*/
+ sys irix_mount 6 /* 1021 mount() IV*/
+ sys sys_umount 1 /* 1022 umount() V*/
+ sys sys_setuid 1 /* 1023 setuid() V*/
+ sys irix_getuid 0 /* 1024 getuid() V*/
+ sys irix_stime 1 /* 1025 stime() V*/
+ sys irix_unimp 4 /* 1026 XXX ptrace() IV*/
+ sys irix_alarm 1 /* 1027 alarm() V*/
+ sys irix_unimp 0 /* 1028 (XXX IRIX 4 fstat) V*/
+ sys irix_pause 0 /* 1029 pause() V*/
+ sys sys_utime 2 /* 1030 utime() V*/
+ sys irix_unimp 0 /* 1031 nuthin' V*/
+ sys irix_unimp 0 /* 1032 nobody home man... V*/
+ sys sys_access 2 /* 1033 access() V*/
+ sys sys_nice 1 /* 1034 nice() V*/
+ sys irix_statfs 2 /* 1035 statfs() V*/
+ sys sys_sync 0 /* 1036 sync() V*/
+ sys sys_kill 2 /* 1037 kill() V*/
+ sys irix_fstatfs 2 /* 1038 fstatfs() V*/
+ sys irix_setpgrp 1 /* 1039 setpgrp() V*/
+ sys irix_syssgi 0 /* 1040 syssgi() HV*/
+ sys sys_dup 1 /* 1041 dup() V*/
+ sys sys_pipe 0 /* 1042 pipe() V*/
+ sys irix_times 1 /* 1043 times() V*/
+ sys irix_unimp 0 /* 1044 XXX profil() IV*/
+ sys irix_unimp 0 /* 1045 XXX lock() IV*/
+ sys sys_setgid 1 /* 1046 setgid() V*/
+ sys irix_getgid 0 /* 1047 getgid() V*/
+ sys irix_unimp 0 /* 1048 (XXX IRIX 4 ssig) V*/
+ sys irix_msgsys 6 /* 1049 sys_msgsys V*/
+ sys sys_sysmips 4 /* 1050 sysmips() HV*/
+ sys irix_unimp 0 /* 1051 XXX sysacct() IV*/
+ sys irix_shmsys 5 /* 1052 sys_shmsys V*/
+ sys irix_semsys 0 /* 1053 sys_semsys V*/
+ sys irix_ioctl 3 /* 1054 ioctl() HV*/
+ sys irix_uadmin 0 /* 1055 XXX sys_uadmin() HC*/
+ sys irix_sysmp 0 /* 1056 sysmp() HV*/
+ sys irix_utssys 4 /* 1057 sys_utssys() HV*/
+ sys irix_unimp 0 /* 1058 nada enchilada V*/
+ sys irix_exece 0 /* 1059 exece() V*/
+ sys sys_umask 1 /* 1060 umask() V*/
+ sys sys_chroot 1 /* 1061 chroot() V*/
+ sys irix_fcntl 3 /* 1062 fcntl() ?V*/
+ sys irix_ulimit 2 /* 1063 ulimit() HV*/
+ sys irix_unimp 0 /* 1064 XXX AFS shit DC*/
+ sys irix_unimp 0 /* 1065 XXX AFS shit DC*/
+ sys irix_unimp 0 /* 1066 XXX AFS shit DC*/
+ sys irix_unimp 0 /* 1067 XXX AFS shit DC*/
+ sys irix_unimp 0 /* 1068 XXX AFS shit DC*/
+ sys irix_unimp 0 /* 1069 XXX AFS shit DC*/
+ sys irix_unimp 0 /* 1070 XXX AFS shit DC*/
+ sys irix_unimp 0 /* 1071 XXX AFS shit DC*/
+ sys irix_unimp 0 /* 1072 XXX AFS shit DC*/
+ sys irix_unimp 0 /* 1073 XXX AFS shit DC*/
+ sys irix_unimp 0 /* 1074 nuttin' V*/
+ sys irix_unimp 0 /* 1075 XXX sys_getrlimit64()IV*/
+ sys irix_unimp 0 /* 1076 XXX sys_setrlimit64()IV*/
+ sys sys_nanosleep 2 /* 1077 nanosleep() V*/
+ sys irix_lseek64 5 /* 1078 lseek64() ?V*/
+ sys sys_rmdir 1 /* 1079 rmdir() V*/
+ sys sys_mkdir 2 /* 1080 mkdir() V*/
+ sys sys_getdents 3 /* 1081 getdents() V*/
+ sys irix_sginap 1 /* 1082 sys_sginap() V*/
+ sys irix_sgikopt 3 /* 1083 sys_sgikopt() DC*/
+ sys sys_sysfs 3 /* 1084 sysfs() ?V*/
+ sys irix_unimp 0 /* 1085 XXX sys_getmsg() DC*/
+ sys irix_unimp 0 /* 1086 XXX sys_putmsg() DC*/
+ sys sys_poll 3 /* 1087 poll() V*/
+ sys irix_sigreturn 0 /* 1088 sigreturn() ?V*/
+ sys sys_accept 3 /* 1089 accept() V*/
+ sys sys_bind 3 /* 1090 bind() V*/
+ sys sys_connect 3 /* 1091 connect() V*/
+ sys irix_gethostid 0 /* 1092 sys_gethostid() ?V*/
+ sys sys_getpeername 3 /* 1093 getpeername() V*/
+ sys sys_getsockname 3 /* 1094 getsockname() V*/
+ sys sys_getsockopt 5 /* 1095 getsockopt() V*/
+ sys sys_listen 2 /* 1096 listen() V*/
+ sys sys_recv 4 /* 1097 recv() V*/
+ sys sys_recvfrom 6 /* 1098 recvfrom() V*/
+ sys sys_recvmsg 3 /* 1099 recvmsg() V*/
+ sys sys_select 5 /* 1100 select() V*/
+ sys sys_send 4 /* 1101 send() V*/
+ sys sys_sendmsg 3 /* 1102 sendmsg() V*/
+ sys sys_sendto 6 /* 1103 sendto() V*/
+ sys irix_sethostid 1 /* 1104 sys_sethostid() ?V*/
+ sys sys_setsockopt 5 /* 1105 setsockopt() V*/
+ sys sys_shutdown 2 /* 1106 shutdown() ?V*/
+ sys irix_socket 3 /* 1107 socket() V*/
+ sys sys_gethostname 2 /* 1108 sys_gethostname() ?V*/
+ sys sys_sethostname 2 /* 1109 sethostname() ?V*/
+ sys irix_getdomainname 2 /* 1110 sys_getdomainname() ?V*/
+ sys sys_setdomainname 2 /* 1111 setdomainname() ?V*/
+ sys sys_truncate 2 /* 1112 truncate() V*/
+ sys sys_ftruncate 2 /* 1113 ftruncate() V*/
+ sys sys_rename 2 /* 1114 rename() V*/
+ sys sys_symlink 2 /* 1115 symlink() V*/
+ sys sys_readlink 3 /* 1116 readlink() V*/
+ sys irix_unimp 0 /* 1117 XXX IRIX 4 lstat() DC*/
+ sys irix_unimp 0 /* 1118 nothin' V*/
+ sys irix_unimp 0 /* 1119 XXX nfs_svc() DC*/
+ sys irix_unimp 0 /* 1120 XXX nfs_getfh() DC*/
+ sys irix_unimp 0 /* 1121 XXX async_daemon() DC*/
+ sys irix_unimp 0 /* 1122 XXX exportfs() DC*/
+ sys sys_setregid 2 /* 1123 setregid() V*/
+ sys sys_setreuid 2 /* 1124 setreuid() V*/
+ sys sys_getitimer 2 /* 1125 getitimer() V*/
+ sys sys_setitimer 3 /* 1126 setitimer() V*/
+ sys irix_unimp 1 /* 1127 XXX adjtime() IV*/
+ sys irix_gettimeofday 1 /* 1128 gettimeofday() V*/
+ sys irix_unimp 0 /* 1129 XXX sproc() IV*/
+ sys irix_prctl 0 /* 1130 prctl() HV*/
+ sys irix_unimp 0 /* 1131 XXX procblk() IV*/
+ sys irix_unimp 0 /* 1132 XXX sprocsp() IV*/
+ sys irix_unimp 0 /* 1133 XXX sgigsc() IV*/
+ sys irix_mmap32 6 /* 1134 mmap() XXXflags? ?V*/
+ sys sys_munmap 2 /* 1135 munmap() V*/
+ sys sys_mprotect 3 /* 1136 mprotect() V*/
+ sys sys_msync 4 /* 1137 msync() V*/
+ sys irix_madvise 3 /* 1138 madvise() DC*/
+ sys irix_pagelock 3 /* 1139 pagelock() IV*/
+ sys irix_getpagesize 0 /* 1140 getpagesize() V*/
+ sys irix_quotactl 0 /* 1141 quotactl() V*/
+ sys irix_unimp 0 /* 1142 nobody home man V*/
+ sys sys_getpgid 1 /* 1143 BSD getpgrp() V*/
+ sys irix_BSDsetpgrp 2 /* 1143 BSD setpgrp() V*/
+ sys sys_vhangup 0 /* 1144 vhangup() V*/
+ sys sys_fsync 1 /* 1145 fsync() V*/
+ sys sys_fchdir 1 /* 1146 fchdir() V*/
+ sys sys_getrlimit 2 /* 1147 getrlimit() ?V*/
+ sys sys_setrlimit 2 /* 1148 setrlimit() ?V*/
+ sys sys_cacheflush 3 /* 1150 cacheflush() HV*/
+ sys sys_cachectl 3 /* 1151 cachectl() HV*/
+ sys sys_fchown 3 /* 1152 fchown() ?V*/
+ sys sys_fchmod 2 /* 1153 fchmod() ?V*/
+ sys irix_unimp 0 /* 1154 XXX IRIX 4 wait3() V*/
+ sys sys_socketpair 4 /* 1155 socketpair() V*/
+ sys irix_systeminfo 3 /* 1156 systeminfo() IV*/
+ sys irix_uname 1 /* 1157 uname() IV*/
+ sys irix_xstat 3 /* 1158 xstat() V*/
+ sys irix_lxstat 3 /* 1159 lxstat() V*/
+ sys irix_fxstat 3 /* 1160 fxstat() V*/
+ sys irix_xmknod 0 /* 1161 xmknod() ?V*/
+ sys irix_sigaction 4 /* 1162 sigaction() ?V*/
+ sys irix_sigpending 1 /* 1163 sigpending() ?V*/
+ sys irix_sigprocmask 3 /* 1164 sigprocmask() ?V*/
+ sys irix_sigsuspend 0 /* 1165 sigsuspend() ?V*/
+ sys irix_sigpoll_sys 3 /* 1166 sigpoll_sys() IV*/
+ sys irix_swapctl 2 /* 1167 swapctl() IV*/
+ sys irix_getcontext 0 /* 1168 getcontext() HV*/
+ sys irix_setcontext 0 /* 1169 setcontext() HV*/
+ sys irix_waitsys 5 /* 1170 waitsys() IV*/
+ sys irix_sigstack 2 /* 1171 sigstack() HV*/
+ sys irix_sigaltstack 2 /* 1172 sigaltstack() HV*/
+ sys irix_sigsendset 2 /* 1173 sigsendset() IV*/
+ sys irix_statvfs 2 /* 1174 statvfs() V*/
+ sys irix_fstatvfs 2 /* 1175 fstatvfs() V*/
+ sys irix_unimp 0 /* 1176 XXX getpmsg() DC*/
+ sys irix_unimp 0 /* 1177 XXX putpmsg() DC*/
+ sys sys_lchown 3 /* 1178 lchown() V*/
+ sys irix_priocntl 0 /* 1179 priocntl() DC*/
+ sys irix_sigqueue 4 /* 1180 sigqueue() IV*/
+ sys sys_readv 3 /* 1181 readv() V*/
+ sys sys_writev 3 /* 1182 writev() V*/
+ sys irix_truncate64 4 /* 1183 truncate64() XX32bit HV*/
+ sys irix_ftruncate64 4 /* 1184 ftruncate64()XX32bit HV*/
+ sys irix_mmap64 0 /* 1185 mmap64() XX32bit HV*/
+ sys irix_dmi 0 /* 1186 dmi() DC*/
+ sys irix_pread 6 /* 1187 pread() IV*/
+ sys irix_pwrite 6 /* 1188 pwrite() IV*/
+ sys sys_fsync 1 /* 1189 fdatasync() XXPOSIX HV*/
+ sys irix_sgifastpath 7 /* 1190 sgifastpath() WHEEE IV*/
+ sys irix_unimp 0 /* 1191 XXX attr_get() DC*/
+ sys irix_unimp 0 /* 1192 XXX attr_getf() DC*/
+ sys irix_unimp 0 /* 1193 XXX attr_set() DC*/
+ sys irix_unimp 0 /* 1194 XXX attr_setf() DC*/
+ sys irix_unimp 0 /* 1195 XXX attr_remove() DC*/
+ sys irix_unimp 0 /* 1196 XXX attr_removef() DC*/
+ sys irix_unimp 0 /* 1197 XXX attr_list() DC*/
+ sys irix_unimp 0 /* 1198 XXX attr_listf() DC*/
+ sys irix_unimp 0 /* 1199 XXX attr_multi() DC*/
+ sys irix_unimp 0 /* 1200 XXX attr_multif() DC*/
+ sys irix_statvfs64 2 /* 1201 statvfs64() V*/
+ sys irix_fstatvfs64 2 /* 1202 fstatvfs64() V*/
+ sys irix_getmountid 2 /* 1203 getmountid()XXXfsids HV*/
+ sys irix_nsproc 5 /* 1204 nsproc() IV*/
+ sys irix_getdents64 3 /* 1205 getdents64() HV*/
+ sys irix_unimp 0 /* 1206 XXX DFS garbage DC*/
+ sys irix_ngetdents 4 /* 1207 ngetdents() XXXeop HV*/
+ sys irix_ngetdents64 4 /* 1208 ngetdents64() XXXeop HV*/
+ sys irix_unimp 0 /* 1209 nothin' V*/
+ sys irix_unimp 0 /* 1210 XXX pidsprocsp() */
+ sys irix_unimp 0 /* 1211 XXX rexec() */
+ sys irix_unimp 0 /* 1212 XXX timer_create() */
+ sys irix_unimp 0 /* 1213 XXX timer_delete() */
+ sys irix_unimp 0 /* 1214 XXX timer_settime() */
+ sys irix_unimp 0 /* 1215 XXX timer_gettime() */
+ sys irix_unimp 0 /* 1216 XXX timer_setoverrun() */
+ sys sys_sched_rr_get_interval 2 /* 1217 sched_rr_get_interval()V*/
+ sys sys_sched_yield 0 /* 1218 sched_yield() V*/
+ sys sys_sched_getscheduler 1 /* 1219 sched_getscheduler() V*/
+ sys sys_sched_setscheduler 3 /* 1220 sched_setscheduler() V*/
+ sys sys_sched_getparam 2 /* 1221 sched_getparam() V*/
+ sys sys_sched_setparam 2 /* 1222 sched_setparam() V*/
+ sys irix_unimp 0 /* 1223 XXX usync_cntl() */
+ sys irix_unimp 0 /* 1224 XXX psema_cntl() */
+ sys irix_unimp 0 /* 1225 XXX restartreturn() */
+
+ /* Just to pad things out nicely. */
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+ sys irix_unimp 0
+
+ .endm
+
+ /*
+ * Pre-compute the number of _instruction_ bytes needed to load
+ * or store the arguments 6-8. Negative values are ignored.
+ */
+ .macro sys function, nargs
+ PTR \function
+ LONG (\nargs << 2) - (5 << 2)
+ .endm
+
+ .align 4
+EXPORT(sys_call_table_irix5)
+ irix5syscalltable
diff --git a/arch/mips/kernel/irixelf.c b/arch/mips/kernel/irixelf.c
new file mode 100644
index 0000000..4af20cd
--- /dev/null
+++ b/arch/mips/kernel/irixelf.c
@@ -0,0 +1,1326 @@
+/*
+ * 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.
+ *
+ * irixelf.c: Code to load IRIX ELF executables conforming to the MIPS ABI.
+ * Based off of work by Eric Youngdale.
+ *
+ * Copyright (C) 1993 - 1994 Eric Youngdale <ericy@cais.com>
+ * Copyright (C) 1996 - 2004 David S. Miller <dm@engr.sgi.com>
+ * Copyright (C) 2004 Steven J. Hill <sjhill@realitydiluted.com>
+ */
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/stat.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/mman.h>
+#include <linux/a.out.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/signal.h>
+#include <linux/binfmts.h>
+#include <linux/string.h>
+#include <linux/file.h>
+#include <linux/fcntl.h>
+#include <linux/ptrace.h>
+#include <linux/slab.h>
+#include <linux/shm.h>
+#include <linux/personality.h>
+#include <linux/elfcore.h>
+#include <linux/smp_lock.h>
+
+#include <asm/uaccess.h>
+#include <asm/mipsregs.h>
+#include <asm/prctl.h>
+
+#define DLINFO_ITEMS 12
+
+#include <linux/elf.h>
+
+#undef DEBUG_ELF
+
+static int load_irix_binary(struct linux_binprm * bprm, struct pt_regs * regs);
+static int load_irix_library(struct file *);
+static int irix_core_dump(long signr, struct pt_regs * regs,
+ struct file *file);
+
+static struct linux_binfmt irix_format = {
+ NULL, THIS_MODULE, load_irix_binary, load_irix_library,
+ irix_core_dump, PAGE_SIZE
+};
+
+#ifndef elf_addr_t
+#define elf_addr_t unsigned long
+#endif
+
+#ifdef DEBUG_ELF
+/* Debugging routines. */
+static char *get_elf_p_type(Elf32_Word p_type)
+{
+ int i = (int) p_type;
+
+ switch(i) {
+ case PT_NULL: return("PT_NULL"); break;
+ case PT_LOAD: return("PT_LOAD"); break;
+ case PT_DYNAMIC: return("PT_DYNAMIC"); break;
+ case PT_INTERP: return("PT_INTERP"); break;
+ case PT_NOTE: return("PT_NOTE"); break;
+ case PT_SHLIB: return("PT_SHLIB"); break;
+ case PT_PHDR: return("PT_PHDR"); break;
+ case PT_LOPROC: return("PT_LOPROC/REGINFO"); break;
+ case PT_HIPROC: return("PT_HIPROC"); break;
+ default: return("PT_BOGUS"); break;
+ }
+}
+
+static void print_elfhdr(struct elfhdr *ehp)
+{
+ int i;
+
+ printk("ELFHDR: e_ident<");
+ for(i = 0; i < (EI_NIDENT - 1); i++) printk("%x ", ehp->e_ident[i]);
+ printk("%x>\n", ehp->e_ident[i]);
+ printk(" e_type[%04x] e_machine[%04x] e_version[%08lx]\n",
+ (unsigned short) ehp->e_type, (unsigned short) ehp->e_machine,
+ (unsigned long) ehp->e_version);
+ printk(" e_entry[%08lx] e_phoff[%08lx] e_shoff[%08lx] "
+ "e_flags[%08lx]\n",
+ (unsigned long) ehp->e_entry, (unsigned long) ehp->e_phoff,
+ (unsigned long) ehp->e_shoff, (unsigned long) ehp->e_flags);
+ printk(" e_ehsize[%04x] e_phentsize[%04x] e_phnum[%04x]\n",
+ (unsigned short) ehp->e_ehsize, (unsigned short) ehp->e_phentsize,
+ (unsigned short) ehp->e_phnum);
+ printk(" e_shentsize[%04x] e_shnum[%04x] e_shstrndx[%04x]\n",
+ (unsigned short) ehp->e_shentsize, (unsigned short) ehp->e_shnum,
+ (unsigned short) ehp->e_shstrndx);
+}
+
+static void print_phdr(int i, struct elf_phdr *ep)
+{
+ printk("PHDR[%d]: p_type[%s] p_offset[%08lx] p_vaddr[%08lx] "
+ "p_paddr[%08lx]\n", i, get_elf_p_type(ep->p_type),
+ (unsigned long) ep->p_offset, (unsigned long) ep->p_vaddr,
+ (unsigned long) ep->p_paddr);
+ printk(" p_filesz[%08lx] p_memsz[%08lx] p_flags[%08lx] "
+ "p_align[%08lx]\n", (unsigned long) ep->p_filesz,
+ (unsigned long) ep->p_memsz, (unsigned long) ep->p_flags,
+ (unsigned long) ep->p_align);
+}
+
+static void dump_phdrs(struct elf_phdr *ep, int pnum)
+{
+ int i;
+
+ for(i = 0; i < pnum; i++, ep++) {
+ if((ep->p_type == PT_LOAD) ||
+ (ep->p_type == PT_INTERP) ||
+ (ep->p_type == PT_PHDR))
+ print_phdr(i, ep);
+ }
+}
+#endif /* (DEBUG_ELF) */
+
+static void set_brk(unsigned long start, unsigned long end)
+{
+ start = PAGE_ALIGN(start);
+ end = PAGE_ALIGN(end);
+ if (end <= start)
+ return;
+ down_write(¤t->mm->mmap_sem);
+ do_brk(start, end - start);
+ up_write(¤t->mm->mmap_sem);
+}
+
+
+/* We need to explicitly zero any fractional pages
+ * after the data section (i.e. bss). This would
+ * contain the junk from the file that should not
+ * be in memory.
+ */
+static void padzero(unsigned long elf_bss)
+{
+ unsigned long nbyte;
+
+ nbyte = elf_bss & (PAGE_SIZE-1);
+ if (nbyte) {
+ nbyte = PAGE_SIZE - nbyte;
+ clear_user((void *) elf_bss, nbyte);
+ }
+}
+
+unsigned long * create_irix_tables(char * p, int argc, int envc,
+ struct elfhdr * exec, unsigned int load_addr,
+ unsigned int interp_load_addr,
+ struct pt_regs *regs, struct elf_phdr *ephdr)
+{
+ elf_addr_t *argv;
+ elf_addr_t *envp;
+ elf_addr_t *sp, *csp;
+
+#ifdef DEBUG_ELF
+ printk("create_irix_tables: p[%p] argc[%d] envc[%d] "
+ "load_addr[%08x] interp_load_addr[%08x]\n",
+ p, argc, envc, load_addr, interp_load_addr);
+#endif
+ sp = (elf_addr_t *) (~15UL & (unsigned long) p);
+ csp = sp;
+ csp -= exec ? DLINFO_ITEMS*2 : 2;
+ csp -= envc+1;
+ csp -= argc+1;
+ csp -= 1; /* argc itself */
+ if ((unsigned long)csp & 15UL) {
+ sp -= (16UL - ((unsigned long)csp & 15UL)) / sizeof(*sp);
+ }
+
+ /*
+ * Put the ELF interpreter info on the stack
+ */
+#define NEW_AUX_ENT(nr, id, val) \
+ __put_user ((id), sp+(nr*2)); \
+ __put_user ((val), sp+(nr*2+1)); \
+
+ sp -= 2;
+ NEW_AUX_ENT(0, AT_NULL, 0);
+
+ if(exec) {
+ sp -= 11*2;
+
+ NEW_AUX_ENT (0, AT_PHDR, load_addr + exec->e_phoff);
+ NEW_AUX_ENT (1, AT_PHENT, sizeof (struct elf_phdr));
+ NEW_AUX_ENT (2, AT_PHNUM, exec->e_phnum);
+ NEW_AUX_ENT (3, AT_PAGESZ, ELF_EXEC_PAGESIZE);
+ NEW_AUX_ENT (4, AT_BASE, interp_load_addr);
+ NEW_AUX_ENT (5, AT_FLAGS, 0);
+ NEW_AUX_ENT (6, AT_ENTRY, (elf_addr_t) exec->e_entry);
+ NEW_AUX_ENT (7, AT_UID, (elf_addr_t) current->uid);
+ NEW_AUX_ENT (8, AT_EUID, (elf_addr_t) current->euid);
+ NEW_AUX_ENT (9, AT_GID, (elf_addr_t) current->gid);
+ NEW_AUX_ENT (10, AT_EGID, (elf_addr_t) current->egid);
+ }
+#undef NEW_AUX_ENT
+
+ sp -= envc+1;
+ envp = sp;
+ sp -= argc+1;
+ argv = sp;
+
+ __put_user((elf_addr_t)argc,--sp);
+ current->mm->arg_start = (unsigned long) p;
+ while (argc-->0) {
+ __put_user((unsigned long)p,argv++);
+ p += strlen_user(p);
+ }
+ __put_user((unsigned long) NULL, argv);
+ current->mm->arg_end = current->mm->env_start = (unsigned long) p;
+ while (envc-->0) {
+ __put_user((unsigned long)p,envp++);
+ p += strlen_user(p);
+ }
+ __put_user((unsigned long) NULL, envp);
+ current->mm->env_end = (unsigned long) p;
+ return sp;
+}
+
+
+/* This is much more generalized than the library routine read function,
+ * so we keep this separate. Technically the library read function
+ * is only provided so that we can read a.out libraries that have
+ * an ELF header.
+ */
+static unsigned int load_irix_interp(struct elfhdr * interp_elf_ex,
+ struct file * interpreter,
+ unsigned int *interp_load_addr)
+{
+ struct elf_phdr *elf_phdata = NULL;
+ struct elf_phdr *eppnt;
+ unsigned int len;
+ unsigned int load_addr;
+ int elf_bss;
+ int retval;
+ unsigned int last_bss;
+ int error;
+ int i;
+ unsigned int k;
+
+ elf_bss = 0;
+ last_bss = 0;
+ error = load_addr = 0;
+
+#ifdef DEBUG_ELF
+ print_elfhdr(interp_elf_ex);
+#endif
+
+ /* First of all, some simple consistency checks */
+ if ((interp_elf_ex->e_type != ET_EXEC &&
+ interp_elf_ex->e_type != ET_DYN) ||
+ !irix_elf_check_arch(interp_elf_ex) ||
+ !interpreter->f_op->mmap) {
+ printk("IRIX interp has bad e_type %d\n", interp_elf_ex->e_type);
+ return 0xffffffff;
+ }
+
+ /* Now read in all of the header information */
+ if(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum > PAGE_SIZE) {
+ printk("IRIX interp header bigger than a page (%d)\n",
+ (sizeof(struct elf_phdr) * interp_elf_ex->e_phnum));
+ return 0xffffffff;
+ }
+
+ elf_phdata = kmalloc(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum,
+ GFP_KERNEL);
+
+ if(!elf_phdata) {
+ printk("Cannot kmalloc phdata for IRIX interp.\n");
+ return 0xffffffff;
+ }
+
+ /* If the size of this structure has changed, then punt, since
+ * we will be doing the wrong thing.
+ */
+ if(interp_elf_ex->e_phentsize != 32) {
+ printk("IRIX interp e_phentsize == %d != 32 ",
+ interp_elf_ex->e_phentsize);
+ kfree(elf_phdata);
+ return 0xffffffff;
+ }
+
+ retval = kernel_read(interpreter, interp_elf_ex->e_phoff,
+ (char *) elf_phdata,
+ sizeof(struct elf_phdr) * interp_elf_ex->e_phnum);
+
+#ifdef DEBUG_ELF
+ dump_phdrs(elf_phdata, interp_elf_ex->e_phnum);
+#endif
+
+ eppnt = elf_phdata;
+ for(i=0; i<interp_elf_ex->e_phnum; i++, eppnt++) {
+ if(eppnt->p_type == PT_LOAD) {
+ int elf_type = MAP_PRIVATE | MAP_DENYWRITE;
+ int elf_prot = 0;
+ unsigned long vaddr = 0;
+ if (eppnt->p_flags & PF_R) elf_prot = PROT_READ;
+ if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
+ if (eppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
+ elf_type |= MAP_FIXED;
+ vaddr = eppnt->p_vaddr;
+
+#ifdef DEBUG_ELF
+ printk("INTERP do_mmap(%p, %08lx, %08lx, %08lx, %08lx, %08lx) ",
+ interpreter, vaddr,
+ (unsigned long) (eppnt->p_filesz + (eppnt->p_vaddr & 0xfff)),
+ (unsigned long) elf_prot, (unsigned long) elf_type,
+ (unsigned long) (eppnt->p_offset & 0xfffff000));
+#endif
+ down_write(¤t->mm->mmap_sem);
+ error = do_mmap(interpreter, vaddr,
+ eppnt->p_filesz + (eppnt->p_vaddr & 0xfff),
+ elf_prot, elf_type,
+ eppnt->p_offset & 0xfffff000);
+ up_write(¤t->mm->mmap_sem);
+
+ if(error < 0 && error > -1024) {
+ printk("Aieee IRIX interp mmap error=%d\n", error);
+ break; /* Real error */
+ }
+#ifdef DEBUG_ELF
+ printk("error=%08lx ", (unsigned long) error);
+#endif
+ if(!load_addr && interp_elf_ex->e_type == ET_DYN) {
+ load_addr = error;
+#ifdef DEBUG_ELF
+ printk("load_addr = error ");
+#endif
+ }
+
+ /* Find the end of the file mapping for this phdr, and keep
+ * track of the largest address we see for this.
+ */
+ k = eppnt->p_vaddr + eppnt->p_filesz;
+ if(k > elf_bss) elf_bss = k;
+
+ /* Do the same thing for the memory mapping - between
+ * elf_bss and last_bss is the bss section.
+ */
+ k = eppnt->p_memsz + eppnt->p_vaddr;
+ if(k > last_bss) last_bss = k;
+#ifdef DEBUG_ELF
+ printk("\n");
+#endif
+ }
+ }
+
+ /* Now use mmap to map the library into memory. */
+ if(error < 0 && error > -1024) {
+#ifdef DEBUG_ELF
+ printk("got error %d\n", error);
+#endif
+ kfree(elf_phdata);
+ return 0xffffffff;
+ }
+
+ /* Now fill out the bss section. First pad the last page up
+ * to the page boundary, and then perform a mmap to make sure
+ * that there are zero-mapped pages up to and including the
+ * last bss page.
+ */
+#ifdef DEBUG_ELF
+ printk("padzero(%08lx) ", (unsigned long) (elf_bss));
+#endif
+ padzero(elf_bss);
+ len = (elf_bss + 0xfff) & 0xfffff000; /* What we have mapped so far */
+
+#ifdef DEBUG_ELF
+ printk("last_bss[%08lx] len[%08lx]\n", (unsigned long) last_bss,
+ (unsigned long) len);
+#endif
+
+ /* Map the last of the bss segment */
+ if (last_bss > len) {
+ down_write(¤t->mm->mmap_sem);
+ do_brk(len, (last_bss - len));
+ up_write(¤t->mm->mmap_sem);
+ }
+ kfree(elf_phdata);
+
+ *interp_load_addr = load_addr;
+ return ((unsigned int) interp_elf_ex->e_entry);
+}
+
+/* Check sanity of IRIX elf executable header. */
+static int verify_binary(struct elfhdr *ehp, struct linux_binprm *bprm)
+{
+ if (memcmp(ehp->e_ident, ELFMAG, SELFMAG) != 0)
+ return -ENOEXEC;
+
+ /* First of all, some simple consistency checks */
+ if((ehp->e_type != ET_EXEC && ehp->e_type != ET_DYN) ||
+ !irix_elf_check_arch(ehp) || !bprm->file->f_op->mmap) {
+ return -ENOEXEC;
+ }
+
+ /* Only support MIPS ARCH2 or greater IRIX binaries for now. */
+ if(!(ehp->e_flags & EF_MIPS_ARCH) && !(ehp->e_flags & 0x04)) {
+ return -ENOEXEC;
+ }
+
+ /* XXX Don't support N32 or 64bit binaries yet because they can
+ * XXX and do execute 64 bit instructions and expect all registers
+ * XXX to be 64 bit as well. We need to make the kernel save
+ * XXX all registers as 64bits on cpu's capable of this at
+ * XXX exception time plus frob the XTLB exception vector.
+ */
+ if((ehp->e_flags & 0x20)) {
+ return -ENOEXEC;
+ }
+
+ return 0; /* It's ok. */
+}
+
+#define IRIX_INTERP_PREFIX "/usr/gnemul/irix"
+
+/* Look for an IRIX ELF interpreter. */
+static inline int look_for_irix_interpreter(char **name,
+ struct file **interpreter,
+ struct elfhdr *interp_elf_ex,
+ struct elf_phdr *epp,
+ struct linux_binprm *bprm, int pnum)
+{
+ int i;
+ int retval = -EINVAL;
+ struct file *file = NULL;
+
+ *name = NULL;
+ for(i = 0; i < pnum; i++, epp++) {
+ if (epp->p_type != PT_INTERP)
+ continue;
+
+ /* It is illegal to have two interpreters for one executable. */
+ if (*name != NULL)
+ goto out;
+
+ *name = kmalloc((epp->p_filesz + strlen(IRIX_INTERP_PREFIX)),
+ GFP_KERNEL);
+ if (!*name)
+ return -ENOMEM;
+
+ strcpy(*name, IRIX_INTERP_PREFIX);
+ retval = kernel_read(bprm->file, epp->p_offset, (*name + 16),
+ epp->p_filesz);
+ if (retval < 0)
+ goto out;
+
+ file = open_exec(*name);
+ if (IS_ERR(file)) {
+ retval = PTR_ERR(file);
+ goto out;
+ }
+ retval = kernel_read(file, 0, bprm->buf, 128);
+ if (retval < 0)
+ goto dput_and_out;
+
+ *interp_elf_ex = *(struct elfhdr *) bprm->buf;
+ }
+ *interpreter = file;
+ return 0;
+
+dput_and_out:
+ fput(file);
+out:
+ kfree(*name);
+ return retval;
+}
+
+static inline int verify_irix_interpreter(struct elfhdr *ihp)
+{
+ if (memcmp(ihp->e_ident, ELFMAG, SELFMAG) != 0)
+ return -ELIBBAD;
+ return 0;
+}
+
+#define EXEC_MAP_FLAGS (MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE)
+
+static inline void map_executable(struct file *fp, struct elf_phdr *epp, int pnum,
+ unsigned int *estack, unsigned int *laddr,
+ unsigned int *scode, unsigned int *ebss,
+ unsigned int *ecode, unsigned int *edata,
+ unsigned int *ebrk)
+{
+ unsigned int tmp;
+ int i, prot;
+
+ for(i = 0; i < pnum; i++, epp++) {
+ if(epp->p_type != PT_LOAD)
+ continue;
+
+ /* Map it. */
+ prot = (epp->p_flags & PF_R) ? PROT_READ : 0;
+ prot |= (epp->p_flags & PF_W) ? PROT_WRITE : 0;
+ prot |= (epp->p_flags & PF_X) ? PROT_EXEC : 0;
+ down_write(¤t->mm->mmap_sem);
+ (void) do_mmap(fp, (epp->p_vaddr & 0xfffff000),
+ (epp->p_filesz + (epp->p_vaddr & 0xfff)),
+ prot, EXEC_MAP_FLAGS,
+ (epp->p_offset & 0xfffff000));
+ up_write(¤t->mm->mmap_sem);
+
+ /* Fixup location tracking vars. */
+ if((epp->p_vaddr & 0xfffff000) < *estack)
+ *estack = (epp->p_vaddr & 0xfffff000);
+ if(!*laddr)
+ *laddr = epp->p_vaddr - epp->p_offset;
+ if(epp->p_vaddr < *scode)
+ *scode = epp->p_vaddr;
+
+ tmp = epp->p_vaddr + epp->p_filesz;
+ if(tmp > *ebss)
+ *ebss = tmp;
+ if((epp->p_flags & PF_X) && *ecode < tmp)
+ *ecode = tmp;
+ if(*edata < tmp)
+ *edata = tmp;
+
+ tmp = epp->p_vaddr + epp->p_memsz;
+ if(tmp > *ebrk)
+ *ebrk = tmp;
+ }
+
+}
+
+static inline int map_interpreter(struct elf_phdr *epp, struct elfhdr *ihp,
+ struct file *interp, unsigned int *iladdr,
+ int pnum, mm_segment_t old_fs,
+ unsigned int *eentry)
+{
+ int i;
+
+ *eentry = 0xffffffff;
+ for(i = 0; i < pnum; i++, epp++) {
+ if(epp->p_type != PT_INTERP)
+ continue;
+
+ /* We should have fielded this error elsewhere... */
+ if(*eentry != 0xffffffff)
+ return -1;
+
+ set_fs(old_fs);
+ *eentry = load_irix_interp(ihp, interp, iladdr);
+ old_fs = get_fs();
+ set_fs(get_ds());
+
+ fput(interp);
+
+ if (*eentry == 0xffffffff)
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ * IRIX maps a page at 0x200000 that holds information about the
+ * process and the system, here we map the page and fill the
+ * structure
+ */
+void irix_map_prda_page (void)
+{
+ unsigned long v;
+ struct prda *pp;
+
+ down_write(¤t->mm->mmap_sem);
+ v = do_brk (PRDA_ADDRESS, PAGE_SIZE);
+ up_write(¤t->mm->mmap_sem);
+
+ if (v < 0)
+ return;
+
+ pp = (struct prda *) v;
+ pp->prda_sys.t_pid = current->pid;
+ pp->prda_sys.t_prid = read_c0_prid();
+ pp->prda_sys.t_rpid = current->pid;
+
+ /* We leave the rest set to zero */
+}
+
+
+
+/* These are the functions used to load ELF style executables and shared
+ * libraries. There is no binary dependent code anywhere else.
+ */
+static int load_irix_binary(struct linux_binprm * bprm, struct pt_regs * regs)
+{
+ struct elfhdr elf_ex, interp_elf_ex;
+ struct file *interpreter;
+ struct elf_phdr *elf_phdata, *elf_ihdr, *elf_ephdr;
+ unsigned int load_addr, elf_bss, elf_brk;
+ unsigned int elf_entry, interp_load_addr = 0;
+ unsigned int start_code, end_code, end_data, elf_stack;
+ int retval, has_interp, has_ephdr, size, i;
+ char *elf_interpreter;
+ mm_segment_t old_fs;
+
+ load_addr = 0;
+ has_interp = has_ephdr = 0;
+ elf_ihdr = elf_ephdr = 0;
+ elf_ex = *((struct elfhdr *) bprm->buf);
+ retval = -ENOEXEC;
+
+ if (verify_binary(&elf_ex, bprm))
+ goto out;
+
+#ifdef DEBUG_ELF
+ print_elfhdr(&elf_ex);
+#endif
+
+ /* Now read in all of the header information */
+ size = elf_ex.e_phentsize * elf_ex.e_phnum;
+ if (size > 65536)
+ goto out;
+ elf_phdata = kmalloc(size, GFP_KERNEL);
+ if (elf_phdata == NULL) {
+ retval = -ENOMEM;
+ goto out;
+ }
+
+ retval = kernel_read(bprm->file, elf_ex.e_phoff, (char *)elf_phdata, size);
+
+ if (retval < 0)
+ goto out_free_ph;
+
+#ifdef DEBUG_ELF
+ dump_phdrs(elf_phdata, elf_ex.e_phnum);
+#endif
+
+ /* Set some things for later. */
+ for(i = 0; i < elf_ex.e_phnum; i++) {
+ switch(elf_phdata[i].p_type) {
+ case PT_INTERP:
+ has_interp = 1;
+ elf_ihdr = &elf_phdata[i];
+ break;
+ case PT_PHDR:
+ has_ephdr = 1;
+ elf_ephdr = &elf_phdata[i];
+ break;
+ };
+ }
+#ifdef DEBUG_ELF
+ printk("\n");
+#endif
+
+ elf_bss = 0;
+ elf_brk = 0;
+
+ elf_stack = 0xffffffff;
+ elf_interpreter = NULL;
+ start_code = 0xffffffff;
+ end_code = 0;
+ end_data = 0;
+
+ retval = look_for_irix_interpreter(&elf_interpreter,
+ &interpreter,
+ &interp_elf_ex, elf_phdata, bprm,
+ elf_ex.e_phnum);
+ if (retval)
+ goto out_free_file;
+
+ if (elf_interpreter) {
+ retval = verify_irix_interpreter(&interp_elf_ex);
+ if(retval)
+ goto out_free_interp;
+ }
+
+ /* OK, we are done with that, now set up the arg stuff,
+ * and then start this sucker up.
+ */
+ retval = -E2BIG;
+ if (!bprm->sh_bang && !bprm->p)
+ goto out_free_interp;
+
+ /* Flush all traces of the currently running executable */
+ retval = flush_old_exec(bprm);
+ if (retval)
+ goto out_free_dentry;
+
+ /* OK, This is the point of no return */
+ current->mm->end_data = 0;
+ current->mm->end_code = 0;
+ current->mm->mmap = NULL;
+ current->flags &= ~PF_FORKNOEXEC;
+ elf_entry = (unsigned int) elf_ex.e_entry;
+
+ /* Do this so that we can load the interpreter, if need be. We will
+ * change some of these later.
+ */
+ set_mm_counter(current->mm, rss, 0);
+ setup_arg_pages(bprm, STACK_TOP, EXSTACK_DEFAULT);
+ current->mm->start_stack = bprm->p;
+
+ /* At this point, we assume that the image should be loaded at
+ * fixed address, not at a variable address.
+ */
+ old_fs = get_fs();
+ set_fs(get_ds());
+
+ map_executable(bprm->file, elf_phdata, elf_ex.e_phnum, &elf_stack,
+ &load_addr, &start_code, &elf_bss, &end_code,
+ &end_data, &elf_brk);
+
+ if(elf_interpreter) {
+ retval = map_interpreter(elf_phdata, &interp_elf_ex,
+ interpreter, &interp_load_addr,
+ elf_ex.e_phnum, old_fs, &elf_entry);
+ kfree(elf_interpreter);
+ if(retval) {
+ set_fs(old_fs);
+ printk("Unable to load IRIX ELF interpreter\n");
+ send_sig(SIGSEGV, current, 0);
+ retval = 0;
+ goto out_free_file;
+ }
+ }
+
+ set_fs(old_fs);
+
+ kfree(elf_phdata);
+ set_personality(PER_IRIX32);
+ set_binfmt(&irix_format);
+ compute_creds(bprm);
+ current->flags &= ~PF_FORKNOEXEC;
+ bprm->p = (unsigned long)
+ create_irix_tables((char *)bprm->p, bprm->argc, bprm->envc,
+ (elf_interpreter ? &elf_ex : NULL),
+ load_addr, interp_load_addr, regs, elf_ephdr);
+ current->mm->start_brk = current->mm->brk = elf_brk;
+ current->mm->end_code = end_code;
+ current->mm->start_code = start_code;
+ current->mm->end_data = end_data;
+ current->mm->start_stack = bprm->p;
+
+ /* Calling set_brk effectively mmaps the pages that we need for the
+ * bss and break sections.
+ */
+ set_brk(elf_bss, elf_brk);
+
+ /*
+ * IRIX maps a page at 0x200000 which holds some system
+ * information. Programs depend on this.
+ */
+ irix_map_prda_page ();
+
+ padzero(elf_bss);
+
+#ifdef DEBUG_ELF
+ printk("(start_brk) %lx\n" , (long) current->mm->start_brk);
+ printk("(end_code) %lx\n" , (long) current->mm->end_code);
+ printk("(start_code) %lx\n" , (long) current->mm->start_code);
+ printk("(end_data) %lx\n" , (long) current->mm->end_data);
+ printk("(start_stack) %lx\n" , (long) current->mm->start_stack);
+ printk("(brk) %lx\n" , (long) current->mm->brk);
+#endif
+
+#if 0 /* XXX No fucking way dude... */
+ /* Why this, you ask??? Well SVr4 maps page 0 as read-only,
+ * and some applications "depend" upon this behavior.
+ * Since we do not have the power to recompile these, we
+ * emulate the SVr4 behavior. Sigh.
+ */
+ down_write(¤t->mm->mmap_sem);
+ (void) do_mmap(NULL, 0, 4096, PROT_READ | PROT_EXEC,
+ MAP_FIXED | MAP_PRIVATE, 0);
+ up_write(¤t->mm->mmap_sem);
+#endif
+
+ start_thread(regs, elf_entry, bprm->p);
+ if (current->ptrace & PT_PTRACED)
+ send_sig(SIGTRAP, current, 0);
+ return 0;
+out:
+ return retval;
+
+out_free_dentry:
+ allow_write_access(interpreter);
+ fput(interpreter);
+out_free_interp:
+ if (elf_interpreter)
+ kfree(elf_interpreter);
+out_free_file:
+out_free_ph:
+ kfree (elf_phdata);
+ goto out;
+}
+
+/* This is really simpleminded and specialized - we are loading an
+ * a.out library that is given an ELF header.
+ */
+static int load_irix_library(struct file *file)
+{
+ struct elfhdr elf_ex;
+ struct elf_phdr *elf_phdata = NULL;
+ unsigned int len = 0;
+ int elf_bss = 0;
+ int retval;
+ unsigned int bss;
+ int error;
+ int i,j, k;
+
+ error = kernel_read(file, 0, (char *) &elf_ex, sizeof(elf_ex));
+ if (error != sizeof(elf_ex))
+ return -ENOEXEC;
+
+ if (memcmp(elf_ex.e_ident, ELFMAG, SELFMAG) != 0)
+ return -ENOEXEC;
+
+ /* First of all, some simple consistency checks. */
+ if(elf_ex.e_type != ET_EXEC || elf_ex.e_phnum > 2 ||
+ !irix_elf_check_arch(&elf_ex) || !file->f_op->mmap)
+ return -ENOEXEC;
+
+ /* Now read in all of the header information. */
+ if(sizeof(struct elf_phdr) * elf_ex.e_phnum > PAGE_SIZE)
+ return -ENOEXEC;
+
+ elf_phdata = kmalloc(sizeof(struct elf_phdr) * elf_ex.e_phnum, GFP_KERNEL);
+ if (elf_phdata == NULL)
+ return -ENOMEM;
+
+ retval = kernel_read(file, elf_ex.e_phoff, (char *) elf_phdata,
+ sizeof(struct elf_phdr) * elf_ex.e_phnum);
+
+ j = 0;
+ for(i=0; i<elf_ex.e_phnum; i++)
+ if((elf_phdata + i)->p_type == PT_LOAD) j++;
+
+ if(j != 1) {
+ kfree(elf_phdata);
+ return -ENOEXEC;
+ }
+
+ while(elf_phdata->p_type != PT_LOAD) elf_phdata++;
+
+ /* Now use mmap to map the library into memory. */
+ down_write(¤t->mm->mmap_sem);
+ error = do_mmap(file,
+ elf_phdata->p_vaddr & 0xfffff000,
+ elf_phdata->p_filesz + (elf_phdata->p_vaddr & 0xfff),
+ PROT_READ | PROT_WRITE | PROT_EXEC,
+ MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE,
+ elf_phdata->p_offset & 0xfffff000);
+ up_write(¤t->mm->mmap_sem);
+
+ k = elf_phdata->p_vaddr + elf_phdata->p_filesz;
+ if (k > elf_bss) elf_bss = k;
+
+ if (error != (elf_phdata->p_vaddr & 0xfffff000)) {
+ kfree(elf_phdata);
+ return error;
+ }
+
+ padzero(elf_bss);
+
+ len = (elf_phdata->p_filesz + elf_phdata->p_vaddr+ 0xfff) & 0xfffff000;
+ bss = elf_phdata->p_memsz + elf_phdata->p_vaddr;
+ if (bss > len) {
+ down_write(¤t->mm->mmap_sem);
+ do_brk(len, bss-len);
+ up_write(¤t->mm->mmap_sem);
+ }
+ kfree(elf_phdata);
+ return 0;
+}
+
+/* Called through irix_syssgi() to map an elf image given an FD,
+ * a phdr ptr USER_PHDRP in userspace, and a count CNT telling how many
+ * phdrs there are in the USER_PHDRP array. We return the vaddr the
+ * first phdr was successfully mapped to.
+ */
+unsigned long irix_mapelf(int fd, struct elf_phdr *user_phdrp, int cnt)
+{
+ struct elf_phdr *hp;
+ struct file *filp;
+ int i, retval;
+
+#ifdef DEBUG_ELF
+ printk("irix_mapelf: fd[%d] user_phdrp[%p] cnt[%d]\n",
+ fd, user_phdrp, cnt);
+#endif
+
+ /* First get the verification out of the way. */
+ hp = user_phdrp;
+ if (!access_ok(VERIFY_READ, hp, (sizeof(struct elf_phdr) * cnt))) {
+#ifdef DEBUG_ELF
+ printk("irix_mapelf: access_ok fails!\n");
+#endif
+ return -EFAULT;
+ }
+
+#ifdef DEBUG_ELF
+ dump_phdrs(user_phdrp, cnt);
+#endif
+
+ for(i = 0; i < cnt; i++, hp++)
+ if(hp->p_type != PT_LOAD) {
+ printk("irix_mapelf: One section is not PT_LOAD!\n");
+ return -ENOEXEC;
+ }
+
+ filp = fget(fd);
+ if (!filp)
+ return -EACCES;
+ if(!filp->f_op) {
+ printk("irix_mapelf: Bogon filp!\n");
+ fput(filp);
+ return -EACCES;
+ }
+
+ hp = user_phdrp;
+ for(i = 0; i < cnt; i++, hp++) {
+ int prot;
+
+ prot = (hp->p_flags & PF_R) ? PROT_READ : 0;
+ prot |= (hp->p_flags & PF_W) ? PROT_WRITE : 0;
+ prot |= (hp->p_flags & PF_X) ? PROT_EXEC : 0;
+ down_write(¤t->mm->mmap_sem);
+ retval = do_mmap(filp, (hp->p_vaddr & 0xfffff000),
+ (hp->p_filesz + (hp->p_vaddr & 0xfff)),
+ prot, (MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE),
+ (hp->p_offset & 0xfffff000));
+ up_write(¤t->mm->mmap_sem);
+
+ if(retval != (hp->p_vaddr & 0xfffff000)) {
+ printk("irix_mapelf: do_mmap fails with %d!\n", retval);
+ fput(filp);
+ return retval;
+ }
+ }
+
+#ifdef DEBUG_ELF
+ printk("irix_mapelf: Success, returning %08lx\n",
+ (unsigned long) user_phdrp->p_vaddr);
+#endif
+ fput(filp);
+ return user_phdrp->p_vaddr;
+}
+
+/*
+ * ELF core dumper
+ *
+ * Modelled on fs/exec.c:aout_core_dump()
+ * Jeremy Fitzhardinge <jeremy@sw.oz.au>
+ */
+
+/* These are the only things you should do on a core-file: use only these
+ * functions to write out all the necessary info.
+ */
+static int dump_write(struct file *file, const void *addr, int nr)
+{
+ return file->f_op->write(file, addr, nr, &file->f_pos) == nr;
+}
+
+static int dump_seek(struct file *file, off_t off)
+{
+ if (file->f_op->llseek) {
+ if (file->f_op->llseek(file, off, 0) != off)
+ return 0;
+ } else
+ file->f_pos = off;
+ return 1;
+}
+
+/* Decide whether a segment is worth dumping; default is yes to be
+ * sure (missing info is worse than too much; etc).
+ * Personally I'd include everything, and use the coredump limit...
+ *
+ * I think we should skip something. But I am not sure how. H.J.
+ */
+static inline int maydump(struct vm_area_struct *vma)
+{
+ if (!(vma->vm_flags & (VM_READ|VM_WRITE|VM_EXEC)))
+ return 0;
+#if 1
+ if (vma->vm_flags & (VM_WRITE|VM_GROWSUP|VM_GROWSDOWN))
+ return 1;
+ if (vma->vm_flags & (VM_READ|VM_EXEC|VM_EXECUTABLE|VM_SHARED))
+ return 0;
+#endif
+ return 1;
+}
+
+#define roundup(x, y) ((((x)+((y)-1))/(y))*(y))
+
+/* An ELF note in memory. */
+struct memelfnote
+{
+ const char *name;
+ int type;
+ unsigned int datasz;
+ void *data;
+};
+
+static int notesize(struct memelfnote *en)
+{
+ int sz;
+
+ sz = sizeof(struct elf_note);
+ sz += roundup(strlen(en->name), 4);
+ sz += roundup(en->datasz, 4);
+
+ return sz;
+}
+
+/* #define DEBUG */
+
+#define DUMP_WRITE(addr, nr) \
+ if (!dump_write(file, (addr), (nr))) \
+ goto end_coredump;
+#define DUMP_SEEK(off) \
+ if (!dump_seek(file, (off))) \
+ goto end_coredump;
+
+static int writenote(struct memelfnote *men, struct file *file)
+{
+ struct elf_note en;
+
+ en.n_namesz = strlen(men->name);
+ en.n_descsz = men->datasz;
+ en.n_type = men->type;
+
+ DUMP_WRITE(&en, sizeof(en));
+ DUMP_WRITE(men->name, en.n_namesz);
+ /* XXX - cast from long long to long to avoid need for libgcc.a */
+ DUMP_SEEK(roundup((unsigned long)file->f_pos, 4)); /* XXX */
+ DUMP_WRITE(men->data, men->datasz);
+ DUMP_SEEK(roundup((unsigned long)file->f_pos, 4)); /* XXX */
+
+ return 1;
+
+end_coredump:
+ return 0;
+}
+#undef DUMP_WRITE
+#undef DUMP_SEEK
+
+#define DUMP_WRITE(addr, nr) \
+ if (!dump_write(file, (addr), (nr))) \
+ goto end_coredump;
+#define DUMP_SEEK(off) \
+ if (!dump_seek(file, (off))) \
+ goto end_coredump;
+
+/* Actual dumper.
+ *
+ * This is a two-pass process; first we find the offsets of the bits,
+ * and then they are actually written out. If we run out of core limit
+ * we just truncate.
+ */
+static int irix_core_dump(long signr, struct pt_regs * regs, struct file *file)
+{
+ int has_dumped = 0;
+ mm_segment_t fs;
+ int segs;
+ int i;
+ size_t size;
+ struct vm_area_struct *vma;
+ struct elfhdr elf;
+ off_t offset = 0, dataoff;
+ int limit = current->signal->rlim[RLIMIT_CORE].rlim_cur;
+ int numnote = 4;
+ struct memelfnote notes[4];
+ struct elf_prstatus prstatus; /* NT_PRSTATUS */
+ elf_fpregset_t fpu; /* NT_PRFPREG */
+ struct elf_prpsinfo psinfo; /* NT_PRPSINFO */
+
+ /* Count what's needed to dump, up to the limit of coredump size. */
+ segs = 0;
+ size = 0;
+ for(vma = current->mm->mmap; vma != NULL; vma = vma->vm_next) {
+ if (maydump(vma))
+ {
+ int sz = vma->vm_end-vma->vm_start;
+
+ if (size+sz >= limit)
+ break;
+ else
+ size += sz;
+ }
+
+ segs++;
+ }
+#ifdef DEBUG
+ printk("irix_core_dump: %d segs taking %d bytes\n", segs, size);
+#endif
+
+ /* Set up header. */
+ memcpy(elf.e_ident, ELFMAG, SELFMAG);
+ elf.e_ident[EI_CLASS] = ELFCLASS32;
+ elf.e_ident[EI_DATA] = ELFDATA2LSB;
+ elf.e_ident[EI_VERSION] = EV_CURRENT;
+ elf.e_ident[EI_OSABI] = ELF_OSABI;
+ memset(elf.e_ident+EI_PAD, 0, EI_NIDENT-EI_PAD);
+
+ elf.e_type = ET_CORE;
+ elf.e_machine = ELF_ARCH;
+ elf.e_version = EV_CURRENT;
+ elf.e_entry = 0;
+ elf.e_phoff = sizeof(elf);
+ elf.e_shoff = 0;
+ elf.e_flags = 0;
+ elf.e_ehsize = sizeof(elf);
+ elf.e_phentsize = sizeof(struct elf_phdr);
+ elf.e_phnum = segs+1; /* Include notes. */
+ elf.e_shentsize = 0;
+ elf.e_shnum = 0;
+ elf.e_shstrndx = 0;
+
+ fs = get_fs();
+ set_fs(KERNEL_DS);
+
+ has_dumped = 1;
+ current->flags |= PF_DUMPCORE;
+
+ DUMP_WRITE(&elf, sizeof(elf));
+ offset += sizeof(elf); /* Elf header. */
+ offset += (segs+1) * sizeof(struct elf_phdr); /* Program headers. */
+
+ /* Set up the notes in similar form to SVR4 core dumps made
+ * with info from their /proc.
+ */
+ memset(&psinfo, 0, sizeof(psinfo));
+ memset(&prstatus, 0, sizeof(prstatus));
+
+ notes[0].name = "CORE";
+ notes[0].type = NT_PRSTATUS;
+ notes[0].datasz = sizeof(prstatus);
+ notes[0].data = &prstatus;
+ prstatus.pr_info.si_signo = prstatus.pr_cursig = signr;
+ prstatus.pr_sigpend = current->pending.signal.sig[0];
+ prstatus.pr_sighold = current->blocked.sig[0];
+ psinfo.pr_pid = prstatus.pr_pid = current->pid;
+ psinfo.pr_ppid = prstatus.pr_ppid = current->parent->pid;
+ psinfo.pr_pgrp = prstatus.pr_pgrp = process_group(current);
+ psinfo.pr_sid = prstatus.pr_sid = current->signal->session;
+ if (current->pid == current->tgid) {
+ /*
+ * This is the record for the group leader. Add in the
+ * cumulative times of previous dead threads. This total
+ * won't include the time of each live thread whose state
+ * is included in the core dump. The final total reported
+ * to our parent process when it calls wait4 will include
+ * those sums as well as the little bit more time it takes
+ * this and each other thread to finish dying after the
+ * core dump synchronization phase.
+ */
+ jiffies_to_timeval(current->utime + current->signal->utime,
+ &prstatus.pr_utime);
+ jiffies_to_timeval(current->stime + current->signal->stime,
+ &prstatus.pr_stime);
+ } else {
+ jiffies_to_timeval(current->utime, &prstatus.pr_utime);
+ jiffies_to_timeval(current->stime, &prstatus.pr_stime);
+ }
+ jiffies_to_timeval(current->signal->cutime, &prstatus.pr_cutime);
+ jiffies_to_timeval(current->signal->cstime, &prstatus.pr_cstime);
+
+ if (sizeof(elf_gregset_t) != sizeof(struct pt_regs)) {
+ printk("sizeof(elf_gregset_t) (%d) != sizeof(struct pt_regs) "
+ "(%d)\n", sizeof(elf_gregset_t), sizeof(struct pt_regs));
+ } else {
+ *(struct pt_regs *)&prstatus.pr_reg = *regs;
+ }
+
+ notes[1].name = "CORE";
+ notes[1].type = NT_PRPSINFO;
+ notes[1].datasz = sizeof(psinfo);
+ notes[1].data = &psinfo;
+ i = current->state ? ffz(~current->state) + 1 : 0;
+ psinfo.pr_state = i;
+ psinfo.pr_sname = (i < 0 || i > 5) ? '.' : "RSDZTD"[i];
+ psinfo.pr_zomb = psinfo.pr_sname == 'Z';
+ psinfo.pr_nice = task_nice(current);
+ psinfo.pr_flag = current->flags;
+ psinfo.pr_uid = current->uid;
+ psinfo.pr_gid = current->gid;
+ {
+ int i, len;
+
+ set_fs(fs);
+
+ len = current->mm->arg_end - current->mm->arg_start;
+ len = len >= ELF_PRARGSZ ? ELF_PRARGSZ : len;
+ copy_from_user(&psinfo.pr_psargs,
+ (const char *)current->mm->arg_start, len);
+ for(i = 0; i < len; i++)
+ if (psinfo.pr_psargs[i] == 0)
+ psinfo.pr_psargs[i] = ' ';
+ psinfo.pr_psargs[len] = 0;
+
+ set_fs(KERNEL_DS);
+ }
+ strlcpy(psinfo.pr_fname, current->comm, sizeof(psinfo.pr_fname));
+
+ notes[2].name = "CORE";
+ notes[2].type = NT_TASKSTRUCT;
+ notes[2].datasz = sizeof(*current);
+ notes[2].data = current;
+
+ /* Try to dump the FPU. */
+ prstatus.pr_fpvalid = dump_fpu (regs, &fpu);
+ if (!prstatus.pr_fpvalid) {
+ numnote--;
+ } else {
+ notes[3].name = "CORE";
+ notes[3].type = NT_PRFPREG;
+ notes[3].datasz = sizeof(fpu);
+ notes[3].data = &fpu;
+ }
+
+ /* Write notes phdr entry. */
+ {
+ struct elf_phdr phdr;
+ int sz = 0;
+
+ for(i = 0; i < numnote; i++)
+ sz += notesize(¬es[i]);
+
+ phdr.p_type = PT_NOTE;
+ phdr.p_offset = offset;
+ phdr.p_vaddr = 0;
+ phdr.p_paddr = 0;
+ phdr.p_filesz = sz;
+ phdr.p_memsz = 0;
+ phdr.p_flags = 0;
+ phdr.p_align = 0;
+
+ offset += phdr.p_filesz;
+ DUMP_WRITE(&phdr, sizeof(phdr));
+ }
+
+ /* Page-align dumped data. */
+ dataoff = offset = roundup(offset, PAGE_SIZE);
+
+ /* Write program headers for segments dump. */
+ for(vma = current->mm->mmap, i = 0;
+ i < segs && vma != NULL; vma = vma->vm_next) {
+ struct elf_phdr phdr;
+ size_t sz;
+
+ i++;
+
+ sz = vma->vm_end - vma->vm_start;
+
+ phdr.p_type = PT_LOAD;
+ phdr.p_offset = offset;
+ phdr.p_vaddr = vma->vm_start;
+ phdr.p_paddr = 0;
+ phdr.p_filesz = maydump(vma) ? sz : 0;
+ phdr.p_memsz = sz;
+ offset += phdr.p_filesz;
+ phdr.p_flags = vma->vm_flags & VM_READ ? PF_R : 0;
+ if (vma->vm_flags & VM_WRITE) phdr.p_flags |= PF_W;
+ if (vma->vm_flags & VM_EXEC) phdr.p_flags |= PF_X;
+ phdr.p_align = PAGE_SIZE;
+
+ DUMP_WRITE(&phdr, sizeof(phdr));
+ }
+
+ for(i = 0; i < numnote; i++)
+ if (!writenote(¬es[i], file))
+ goto end_coredump;
+
+ set_fs(fs);
+
+ DUMP_SEEK(dataoff);
+
+ for(i = 0, vma = current->mm->mmap;
+ i < segs && vma != NULL;
+ vma = vma->vm_next) {
+ unsigned long addr = vma->vm_start;
+ unsigned long len = vma->vm_end - vma->vm_start;
+
+ if (!maydump(vma))
+ continue;
+ i++;
+#ifdef DEBUG
+ printk("elf_core_dump: writing %08lx %lx\n", addr, len);
+#endif
+ DUMP_WRITE((void *)addr, len);
+ }
+
+ if ((off_t) file->f_pos != offset) {
+ /* Sanity check. */
+ printk("elf_core_dump: file->f_pos (%ld) != offset (%ld)\n",
+ (off_t) file->f_pos, offset);
+ }
+
+end_coredump:
+ set_fs(fs);
+ return has_dumped;
+}
+
+static int __init init_irix_binfmt(void)
+{
+ int init_inventory(void);
+ extern asmlinkage unsigned long sys_call_table;
+ extern asmlinkage unsigned long sys_call_table_irix5;
+
+ init_inventory();
+
+ /*
+ * Copy the IRIX5 syscall table (8000 bytes) into the main syscall
+ * table. The IRIX5 calls are located by an offset of 8000 bytes
+ * from the beginning of the main table.
+ */
+ memcpy((void *) ((unsigned long) &sys_call_table + 8000),
+ &sys_call_table_irix5, 8000);
+
+ return register_binfmt(&irix_format);
+}
+
+static void __exit exit_irix_binfmt(void)
+{
+ /* Remove the IRIX ELF loaders. */
+ unregister_binfmt(&irix_format);
+}
+
+module_init(init_irix_binfmt)
+module_exit(exit_irix_binfmt)
diff --git a/arch/mips/kernel/irixinv.c b/arch/mips/kernel/irixinv.c
new file mode 100644
index 0000000..60aa98c
--- /dev/null
+++ b/arch/mips/kernel/irixinv.c
@@ -0,0 +1,77 @@
+/*
+ * Support the inventory interface for IRIX binaries
+ * This is invoked before the mm layer is working, so we do not
+ * use the linked lists for the inventory yet.
+ *
+ * Miguel de Icaza, 1997.
+ */
+#include <linux/mm.h>
+#include <asm/inventory.h>
+#include <asm/uaccess.h>
+
+#define MAX_INVENTORY 50
+int inventory_items = 0;
+
+static inventory_t inventory [MAX_INVENTORY];
+
+void add_to_inventory (int class, int type, int controller, int unit, int state)
+{
+ inventory_t *ni = &inventory [inventory_items];
+
+ if (inventory_items == MAX_INVENTORY)
+ return;
+
+ ni->inv_class = class;
+ ni->inv_type = type;
+ ni->inv_controller = controller;
+ ni->inv_unit = unit;
+ ni->inv_state = state;
+ ni->inv_next = ni;
+ inventory_items++;
+}
+
+int dump_inventory_to_user (void *userbuf, int size)
+{
+ inventory_t *inv = &inventory [0];
+ inventory_t *user = userbuf;
+ int v;
+
+ if (!access_ok(VERIFY_WRITE, userbuf, size))
+ return -EFAULT;
+
+ for (v = 0; v < inventory_items; v++){
+ inv = &inventory [v];
+ copy_to_user (user, inv, sizeof (inventory_t));
+ user++;
+ }
+ return inventory_items * sizeof (inventory_t);
+}
+
+int __init init_inventory(void)
+{
+ /*
+ * gross hack while we put the right bits all over the kernel
+ * most likely this will not let just anyone run the X server
+ * until we put the right values all over the place
+ */
+ add_to_inventory (10, 3, 0, 0, 16400);
+ add_to_inventory (1, 1, 150, -1, 12);
+ add_to_inventory (1, 3, 0, 0, 8976);
+ add_to_inventory (1, 2, 0, 0, 8976);
+ add_to_inventory (4, 8, 0, 0, 2);
+ add_to_inventory (5, 5, 0, 0, 1);
+ add_to_inventory (3, 3, 0, 0, 32768);
+ add_to_inventory (3, 4, 0, 0, 32768);
+ add_to_inventory (3, 8, 0, 0, 524288);
+ add_to_inventory (3, 9, 0, 0, 64);
+ add_to_inventory (3, 1, 0, 0, 67108864);
+ add_to_inventory (12, 3, 0, 0, 16);
+ add_to_inventory (8, 7, 17, 0, 16777472);
+ add_to_inventory (8, 0, 0, 0, 1);
+ add_to_inventory (2, 1, 0, 13, 2);
+ add_to_inventory (2, 2, 0, 2, 0);
+ add_to_inventory (2, 2, 0, 1, 0);
+ add_to_inventory (7, 14, 0, 0, 6);
+
+ return 0;
+}
diff --git a/arch/mips/kernel/irixioctl.c b/arch/mips/kernel/irixioctl.c
new file mode 100644
index 0000000..4cd3d38
--- /dev/null
+++ b/arch/mips/kernel/irixioctl.c
@@ -0,0 +1,261 @@
+/*
+ * irixioctl.c: A fucking mess...
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/sockios.h>
+#include <linux/syscalls.h>
+#include <linux/tty.h>
+#include <linux/file.h>
+
+#include <asm/uaccess.h>
+#include <asm/ioctl.h>
+#include <asm/ioctls.h>
+
+#undef DEBUG_IOCTLS
+#undef DEBUG_MISSING_IOCTL
+
+struct irix_termios {
+ tcflag_t c_iflag, c_oflag, c_cflag, c_lflag;
+ cc_t c_cc[NCCS];
+};
+
+extern void start_tty(struct tty_struct *tty);
+static struct tty_struct *get_tty(int fd)
+{
+ struct file *filp;
+ struct tty_struct *ttyp = NULL;
+
+ spin_lock(¤t->files->file_lock);
+ filp = fcheck(fd);
+ if(filp && filp->private_data) {
+ ttyp = (struct tty_struct *) filp->private_data;
+
+ if(ttyp->magic != TTY_MAGIC)
+ ttyp =NULL;
+ }
+ spin_unlock(¤t->files->file_lock);
+ return ttyp;
+}
+
+static struct tty_struct *get_real_tty(struct tty_struct *tp)
+{
+ if (tp->driver->type == TTY_DRIVER_TYPE_PTY &&
+ tp->driver->subtype == PTY_TYPE_MASTER)
+ return tp->link;
+ else
+ return tp;
+}
+
+asmlinkage int irix_ioctl(int fd, unsigned long cmd, unsigned long arg)
+{
+ struct tty_struct *tp, *rtp;
+ mm_segment_t old_fs;
+ int error = 0;
+
+#ifdef DEBUG_IOCTLS
+ printk("[%s:%d] irix_ioctl(%d, ", current->comm, current->pid, fd);
+#endif
+ switch(cmd) {
+ case 0x00005401:
+#ifdef DEBUG_IOCTLS
+ printk("TCGETA, %08lx) ", arg);
+#endif
+ error = sys_ioctl(fd, TCGETA, arg);
+ break;
+
+ case 0x0000540d: {
+ struct termios kt;
+ struct irix_termios *it = (struct irix_termios *) arg;
+
+#ifdef DEBUG_IOCTLS
+ printk("TCGETS, %08lx) ", arg);
+#endif
+ if(!access_ok(VERIFY_WRITE, it, sizeof(*it))) {
+ error = -EFAULT;
+ break;
+ }
+ old_fs = get_fs(); set_fs(get_ds());
+ error = sys_ioctl(fd, TCGETS, (unsigned long) &kt);
+ set_fs(old_fs);
+ if (error)
+ break;
+ __put_user(kt.c_iflag, &it->c_iflag);
+ __put_user(kt.c_oflag, &it->c_oflag);
+ __put_user(kt.c_cflag, &it->c_cflag);
+ __put_user(kt.c_lflag, &it->c_lflag);
+ for(error = 0; error < NCCS; error++)
+ __put_user(kt.c_cc[error], &it->c_cc[error]);
+ error = 0;
+ break;
+ }
+
+ case 0x0000540e: {
+ struct termios kt;
+ struct irix_termios *it = (struct irix_termios *) arg;
+
+#ifdef DEBUG_IOCTLS
+ printk("TCSETS, %08lx) ", arg);
+#endif
+ if (!access_ok(VERIFY_READ, it, sizeof(*it))) {
+ error = -EFAULT;
+ break;
+ }
+ old_fs = get_fs(); set_fs(get_ds());
+ error = sys_ioctl(fd, TCGETS, (unsigned long) &kt);
+ set_fs(old_fs);
+ if(error)
+ break;
+ __get_user(kt.c_iflag, &it->c_iflag);
+ __get_user(kt.c_oflag, &it->c_oflag);
+ __get_user(kt.c_cflag, &it->c_cflag);
+ __get_user(kt.c_lflag, &it->c_lflag);
+ for(error = 0; error < NCCS; error++)
+ __get_user(kt.c_cc[error], &it->c_cc[error]);
+ old_fs = get_fs(); set_fs(get_ds());
+ error = sys_ioctl(fd, TCSETS, (unsigned long) &kt);
+ set_fs(old_fs);
+ break;
+ }
+
+ case 0x0000540f:
+#ifdef DEBUG_IOCTLS
+ printk("TCSETSW, %08lx) ", arg);
+#endif
+ error = sys_ioctl(fd, TCSETSW, arg);
+ break;
+
+ case 0x00005471:
+#ifdef DEBUG_IOCTLS
+ printk("TIOCNOTTY, %08lx) ", arg);
+#endif
+ error = sys_ioctl(fd, TIOCNOTTY, arg);
+ break;
+
+ case 0x00007416:
+#ifdef DEBUG_IOCTLS
+ printk("TIOCGSID, %08lx) ", arg);
+#endif
+ tp = get_tty(fd);
+ if(!tp) {
+ error = -EINVAL;
+ break;
+ }
+ rtp = get_real_tty(tp);
+#ifdef DEBUG_IOCTLS
+ printk("rtp->session=%d ", rtp->session);
+#endif
+ error = put_user(rtp->session, (unsigned long *) arg);
+ break;
+
+ case 0x746e:
+ /* TIOCSTART, same effect as hitting ^Q */
+#ifdef DEBUG_IOCTLS
+ printk("TIOCSTART, %08lx) ", arg);
+#endif
+ tp = get_tty(fd);
+ if(!tp) {
+ error = -EINVAL;
+ break;
+ }
+ rtp = get_real_tty(tp);
+ start_tty(rtp);
+ break;
+
+ case 0x20006968:
+#ifdef DEBUG_IOCTLS
+ printk("SIOCGETLABEL, %08lx) ", arg);
+#endif
+ error = -ENOPKG;
+ break;
+
+ case 0x40047477:
+#ifdef DEBUG_IOCTLS
+ printk("TIOCGPGRP, %08lx) ", arg);
+#endif
+ error = sys_ioctl(fd, TIOCGPGRP, arg);
+#ifdef DEBUG_IOCTLS
+ printk("arg=%d ", *(int *)arg);
+#endif
+ break;
+
+ case 0x40087468:
+#ifdef DEBUG_IOCTLS
+ printk("TIOCGWINSZ, %08lx) ", arg);
+#endif
+ error = sys_ioctl(fd, TIOCGWINSZ, arg);
+ break;
+
+ case 0x8004667e:
+#ifdef DEBUG_IOCTLS
+ printk("FIONBIO, %08lx) arg=%d ", arg, *(int *)arg);
+#endif
+ error = sys_ioctl(fd, FIONBIO, arg);
+ break;
+
+ case 0x80047476:
+#ifdef DEBUG_IOCTLS
+ printk("TIOCSPGRP, %08lx) arg=%d ", arg, *(int *)arg);
+#endif
+ error = sys_ioctl(fd, TIOCSPGRP, arg);
+ break;
+
+ case 0x8020690c:
+#ifdef DEBUG_IOCTLS
+ printk("SIOCSIFADDR, %08lx) arg=%d ", arg, *(int *)arg);
+#endif
+ error = sys_ioctl(fd, SIOCSIFADDR, arg);
+ break;
+
+ case 0x80206910:
+#ifdef DEBUG_IOCTLS
+ printk("SIOCSIFFLAGS, %08lx) arg=%d ", arg, *(int *)arg);
+#endif
+ error = sys_ioctl(fd, SIOCSIFFLAGS, arg);
+ break;
+
+ case 0xc0206911:
+#ifdef DEBUG_IOCTLS
+ printk("SIOCGIFFLAGS, %08lx) arg=%d ", arg, *(int *)arg);
+#endif
+ error = sys_ioctl(fd, SIOCGIFFLAGS, arg);
+ break;
+
+ case 0xc020691b:
+#ifdef DEBUG_IOCTLS
+ printk("SIOCGIFMETRIC, %08lx) arg=%d ", arg, *(int *)arg);
+#endif
+ error = sys_ioctl(fd, SIOCGIFMETRIC, arg);
+ break;
+
+ default: {
+#ifdef DEBUG_MISSING_IOCTL
+ char *msg = "Unimplemented IOCTL cmd tell linux@engr.sgi.com\n";
+
+#ifdef DEBUG_IOCTLS
+ printk("UNIMP_IOCTL, %08lx)\n", arg);
+#endif
+ old_fs = get_fs(); set_fs(get_ds());
+ sys_write(2, msg, strlen(msg));
+ set_fs(old_fs);
+ printk("[%s:%d] Does unimplemented IRIX ioctl cmd %08lx\n",
+ current->comm, current->pid, cmd);
+ do_exit(255);
+#else
+ error = sys_ioctl (fd, cmd, arg);
+#endif
+ }
+
+ };
+#ifdef DEBUG_IOCTLS
+ printk("error=%d\n", error);
+#endif
+ return error;
+}
diff --git a/arch/mips/kernel/irixsig.c b/arch/mips/kernel/irixsig.c
new file mode 100644
index 0000000..3f956f8
--- /dev/null
+++ b/arch/mips/kernel/irixsig.c
@@ -0,0 +1,853 @@
+/*
+ * irixsig.c: WHEEE, IRIX signals! YOW, am I compatible or what?!?!
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ * Copyright (C) 1997 - 2000 Ralf Baechle (ralf@gnu.org)
+ * Copyright (C) 2000 Silicon Graphics, Inc.
+ */
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/errno.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/time.h>
+#include <linux/ptrace.h>
+
+#include <asm/ptrace.h>
+#include <asm/uaccess.h>
+
+#undef DEBUG_SIG
+
+#define _S(nr) (1<<((nr)-1))
+
+#define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
+
+typedef struct {
+ unsigned long sig[4];
+} irix_sigset_t;
+
+struct sigctx_irix5 {
+ u32 rmask, cp0_status;
+ u64 pc;
+ u64 regs[32];
+ u64 fpregs[32];
+ u32 usedfp, fpcsr, fpeir, sstk_flags;
+ u64 hi, lo;
+ u64 cp0_cause, cp0_badvaddr, _unused0;
+ irix_sigset_t sigset;
+ u64 weird_fpu_thing;
+ u64 _unused1[31];
+};
+
+#ifdef DEBUG_SIG
+/* Debugging */
+static inline void dump_irix5_sigctx(struct sigctx_irix5 *c)
+{
+ int i;
+
+ printk("misc: rmask[%08lx] status[%08lx] pc[%08lx]\n",
+ (unsigned long) c->rmask,
+ (unsigned long) c->cp0_status,
+ (unsigned long) c->pc);
+ printk("regs: ");
+ for(i = 0; i < 16; i++)
+ printk("[%d]<%08lx> ", i, (unsigned long) c->regs[i]);
+ printk("\nregs: ");
+ for(i = 16; i < 32; i++)
+ printk("[%d]<%08lx> ", i, (unsigned long) c->regs[i]);
+ printk("\nfpregs: ");
+ for(i = 0; i < 16; i++)
+ printk("[%d]<%08lx> ", i, (unsigned long) c->fpregs[i]);
+ printk("\nfpregs: ");
+ for(i = 16; i < 32; i++)
+ printk("[%d]<%08lx> ", i, (unsigned long) c->fpregs[i]);
+ printk("misc: usedfp[%d] fpcsr[%08lx] fpeir[%08lx] stk_flgs[%08lx]\n",
+ (int) c->usedfp, (unsigned long) c->fpcsr,
+ (unsigned long) c->fpeir, (unsigned long) c->sstk_flags);
+ printk("misc: hi[%08lx] lo[%08lx] cause[%08lx] badvaddr[%08lx]\n",
+ (unsigned long) c->hi, (unsigned long) c->lo,
+ (unsigned long) c->cp0_cause, (unsigned long) c->cp0_badvaddr);
+ printk("misc: sigset<0>[%08lx] sigset<1>[%08lx] sigset<2>[%08lx] "
+ "sigset<3>[%08lx]\n", (unsigned long) c->sigset.sig[0],
+ (unsigned long) c->sigset.sig[1],
+ (unsigned long) c->sigset.sig[2],
+ (unsigned long) c->sigset.sig[3]);
+}
+#endif
+
+static void setup_irix_frame(struct k_sigaction *ka, struct pt_regs *regs,
+ int signr, sigset_t *oldmask)
+{
+ unsigned long sp;
+ struct sigctx_irix5 *ctx;
+ int i;
+
+ sp = regs->regs[29];
+ sp -= sizeof(struct sigctx_irix5);
+ sp &= ~(0xf);
+ ctx = (struct sigctx_irix5 *) sp;
+ if (!access_ok(VERIFY_WRITE, ctx, sizeof(*ctx)))
+ goto segv_and_exit;
+
+ __put_user(0, &ctx->weird_fpu_thing);
+ __put_user(~(0x00000001), &ctx->rmask);
+ __put_user(0, &ctx->regs[0]);
+ for(i = 1; i < 32; i++)
+ __put_user((u64) regs->regs[i], &ctx->regs[i]);
+
+ __put_user((u64) regs->hi, &ctx->hi);
+ __put_user((u64) regs->lo, &ctx->lo);
+ __put_user((u64) regs->cp0_epc, &ctx->pc);
+ __put_user(!!used_math(), &ctx->usedfp);
+ __put_user((u64) regs->cp0_cause, &ctx->cp0_cause);
+ __put_user((u64) regs->cp0_badvaddr, &ctx->cp0_badvaddr);
+
+ __put_user(0, &ctx->sstk_flags); /* XXX sigstack unimp... todo... */
+
+ __copy_to_user(&ctx->sigset, oldmask, sizeof(irix_sigset_t));
+
+#ifdef DEBUG_SIG
+ dump_irix5_sigctx(ctx);
+#endif
+
+ regs->regs[4] = (unsigned long) signr;
+ regs->regs[5] = 0; /* XXX sigcode XXX */
+ regs->regs[6] = regs->regs[29] = sp;
+ regs->regs[7] = (unsigned long) ka->sa.sa_handler;
+ regs->regs[25] = regs->cp0_epc = (unsigned long) ka->sa_restorer;
+
+ return;
+
+segv_and_exit:
+ force_sigsegv(signr, current);
+}
+
+static void inline
+setup_irix_rt_frame(struct k_sigaction * ka, struct pt_regs *regs,
+ int signr, sigset_t *oldmask, siginfo_t *info)
+{
+ printk("Aiee: setup_tr_frame wants to be written");
+ do_exit(SIGSEGV);
+}
+
+static inline void handle_signal(unsigned long sig, siginfo_t *info,
+ struct k_sigaction *ka, sigset_t *oldset, struct pt_regs * regs)
+{
+ switch(regs->regs[0]) {
+ case ERESTARTNOHAND:
+ regs->regs[2] = EINTR;
+ break;
+ case ERESTARTSYS:
+ if(!(ka->sa.sa_flags & SA_RESTART)) {
+ regs->regs[2] = EINTR;
+ break;
+ }
+ /* fallthrough */
+ case ERESTARTNOINTR: /* Userland will reload $v0. */
+ regs->cp0_epc -= 8;
+ }
+
+ regs->regs[0] = 0; /* Don't deal with this again. */
+
+ if (ka->sa.sa_flags & SA_SIGINFO)
+ setup_irix_rt_frame(ka, regs, sig, oldset, info);
+ else
+ setup_irix_frame(ka, regs, sig, oldset);
+
+ if (!(ka->sa.sa_flags & SA_NODEFER)) {
+ spin_lock_irq(¤t->sighand->siglock);
+ sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask);
+ sigaddset(¤t->blocked,sig);
+ recalc_sigpending();
+ spin_unlock_irq(¤t->sighand->siglock);
+ }
+}
+
+asmlinkage int do_irix_signal(sigset_t *oldset, struct pt_regs *regs)
+{
+ struct k_sigaction ka;
+ siginfo_t info;
+ int signr;
+
+ /*
+ * We want the common case to go fast, which is why we may in certain
+ * cases get here from kernel mode. Just return without doing anything
+ * if so.
+ */
+ if (!user_mode(regs))
+ return 1;
+
+ if (try_to_freeze(0))
+ goto no_signal;
+
+ if (!oldset)
+ oldset = ¤t->blocked;
+
+ signr = get_signal_to_deliver(&info, &ka, regs, NULL);
+ if (signr > 0) {
+ handle_signal(signr, &info, &ka, oldset, regs);
+ return 1;
+ }
+
+no_signal:
+ /*
+ * Who's code doesn't conform to the restartable syscall convention
+ * dies here!!! The li instruction, a single machine instruction,
+ * must directly be followed by the syscall instruction.
+ */
+ if (regs->regs[0]) {
+ if (regs->regs[2] == ERESTARTNOHAND ||
+ regs->regs[2] == ERESTARTSYS ||
+ regs->regs[2] == ERESTARTNOINTR) {
+ regs->cp0_epc -= 8;
+ }
+ }
+ return 0;
+}
+
+asmlinkage void
+irix_sigreturn(struct pt_regs *regs)
+{
+ struct sigctx_irix5 *context, *magic;
+ unsigned long umask, mask;
+ u64 *fregs;
+ int sig, i, base = 0;
+ sigset_t blocked;
+
+ /* Always make any pending restarted system calls return -EINTR */
+ current_thread_info()->restart_block.fn = do_no_restart_syscall;
+
+ if (regs->regs[2] == 1000)
+ base = 1;
+
+ context = (struct sigctx_irix5 *) regs->regs[base + 4];
+ magic = (struct sigctx_irix5 *) regs->regs[base + 5];
+ sig = (int) regs->regs[base + 6];
+#ifdef DEBUG_SIG
+ printk("[%s:%d] IRIX sigreturn(scp[%p],ucp[%p],sig[%d])\n",
+ current->comm, current->pid, context, magic, sig);
+#endif
+ if (!context)
+ context = magic;
+ if (!access_ok(VERIFY_READ, context, sizeof(struct sigctx_irix5)))
+ goto badframe;
+
+#ifdef DEBUG_SIG
+ dump_irix5_sigctx(context);
+#endif
+
+ __get_user(regs->cp0_epc, &context->pc);
+ umask = context->rmask; mask = 2;
+ for (i = 1; i < 32; i++, mask <<= 1) {
+ if(umask & mask)
+ __get_user(regs->regs[i], &context->regs[i]);
+ }
+ __get_user(regs->hi, &context->hi);
+ __get_user(regs->lo, &context->lo);
+
+ if ((umask & 1) && context->usedfp) {
+ fregs = (u64 *) ¤t->thread.fpu;
+ for(i = 0; i < 32; i++)
+ fregs[i] = (u64) context->fpregs[i];
+ __get_user(current->thread.fpu.hard.fcr31, &context->fpcsr);
+ }
+
+ /* XXX do sigstack crapola here... XXX */
+
+ if (__copy_from_user(&blocked, &context->sigset, sizeof(blocked)))
+ goto badframe;
+
+ sigdelsetmask(&blocked, ~_BLOCKABLE);
+ spin_lock_irq(¤t->sighand->siglock);
+ current->blocked = blocked;
+ recalc_sigpending();
+ spin_unlock_irq(¤t->sighand->siglock);
+
+ /*
+ * Don't let your children do this ...
+ */
+ if (current_thread_info()->flags & TIF_SYSCALL_TRACE)
+ do_syscall_trace(regs, 1);
+ __asm__ __volatile__(
+ "move\t$29,%0\n\t"
+ "j\tsyscall_exit"
+ :/* no outputs */
+ :"r" (®s));
+ /* Unreached */
+
+badframe:
+ force_sig(SIGSEGV, current);
+}
+
+struct sigact_irix5 {
+ int flags;
+ void (*handler)(int);
+ u32 sigset[4];
+ int _unused0[2];
+};
+
+#ifdef DEBUG_SIG
+static inline void dump_sigact_irix5(struct sigact_irix5 *p)
+{
+ printk("<f[%d] hndlr[%08lx] msk[%08lx]>", p->flags,
+ (unsigned long) p->handler,
+ (unsigned long) p->sigset[0]);
+}
+#endif
+
+asmlinkage int
+irix_sigaction(int sig, const struct sigaction *act,
+ struct sigaction *oact, void *trampoline)
+{
+ struct k_sigaction new_ka, old_ka;
+ int ret;
+
+#ifdef DEBUG_SIG
+ printk(" (%d,%s,%s,%08lx) ", sig, (!new ? "0" : "NEW"),
+ (!old ? "0" : "OLD"), trampoline);
+ if(new) {
+ dump_sigact_irix5(new); printk(" ");
+ }
+#endif
+ if (act) {
+ sigset_t mask;
+ if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
+ __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
+ __get_user(new_ka.sa.sa_flags, &act->sa_flags))
+ return -EFAULT;
+
+ __copy_from_user(&mask, &act->sa_mask, sizeof(sigset_t));
+
+ /*
+ * Hmmm... methinks IRIX libc always passes a valid trampoline
+ * value for all invocations of sigaction. Will have to
+ * investigate. POSIX POSIX, die die die...
+ */
+ new_ka.sa_restorer = trampoline;
+ }
+
+/* XXX Implement SIG_SETMASK32 for IRIX compatibility */
+ ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
+
+ if (!ret && oact) {
+ if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
+ __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
+ __put_user(old_ka.sa.sa_flags, &oact->sa_flags))
+ return -EFAULT;
+ __copy_to_user(&old_ka.sa.sa_mask, &oact->sa_mask,
+ sizeof(sigset_t));
+ }
+
+ return ret;
+}
+
+asmlinkage int irix_sigpending(irix_sigset_t *set)
+{
+ return do_sigpending(set, sizeof(*set));
+}
+
+asmlinkage int irix_sigprocmask(int how, irix_sigset_t *new, irix_sigset_t *old)
+{
+ sigset_t oldbits, newbits;
+
+ if (new) {
+ if (!access_ok(VERIFY_READ, new, sizeof(*new)))
+ return -EFAULT;
+ __copy_from_user(&newbits, new, sizeof(unsigned long)*4);
+ sigdelsetmask(&newbits, ~_BLOCKABLE);
+
+ spin_lock_irq(¤t->sighand->siglock);
+ oldbits = current->blocked;
+
+ switch(how) {
+ case 1:
+ sigorsets(&newbits, &oldbits, &newbits);
+ break;
+
+ case 2:
+ sigandsets(&newbits, &oldbits, &newbits);
+ break;
+
+ case 3:
+ break;
+
+ case 256:
+ siginitset(&newbits, newbits.sig[0]);
+ break;
+
+ default:
+ return -EINVAL;
+ }
+ recalc_sigpending();
+ spin_unlock_irq(¤t->sighand->siglock);
+ }
+ if(old) {
+ if (!access_ok(VERIFY_WRITE, old, sizeof(*old)))
+ return -EFAULT;
+ __copy_to_user(old, ¤t->blocked, sizeof(unsigned long)*4);
+ }
+
+ return 0;
+}
+
+asmlinkage int irix_sigsuspend(struct pt_regs *regs)
+{
+ sigset_t *uset, saveset, newset;
+
+ uset = (sigset_t *) regs->regs[4];
+ if (copy_from_user(&newset, uset, sizeof(sigset_t)))
+ return -EFAULT;
+ sigdelsetmask(&newset, ~_BLOCKABLE);
+
+ spin_lock_irq(¤t->sighand->siglock);
+ saveset = current->blocked;
+ current->blocked = newset;
+ recalc_sigpending();
+ spin_unlock_irq(¤t->sighand->siglock);
+
+ regs->regs[2] = -EINTR;
+ while (1) {
+ current->state = TASK_INTERRUPTIBLE;
+ schedule();
+ if (do_irix_signal(&saveset, regs))
+ return -EINTR;
+ }
+}
+
+/* hate hate hate... */
+struct irix5_siginfo {
+ int sig, code, error;
+ union {
+ char unused[128 - (3 * 4)]; /* Safety net. */
+ struct {
+ int pid;
+ union {
+ int uid;
+ struct {
+ int utime, status, stime;
+ } child;
+ } procdata;
+ } procinfo;
+
+ unsigned long fault_addr;
+
+ struct {
+ int fd;
+ long band;
+ } fileinfo;
+
+ unsigned long sigval;
+ } stuff;
+};
+
+static inline unsigned long timespectojiffies(struct timespec *value)
+{
+ unsigned long sec = (unsigned) value->tv_sec;
+ long nsec = value->tv_nsec;
+
+ if (sec > (LONG_MAX / HZ))
+ return LONG_MAX;
+ nsec += 1000000000L / HZ - 1;
+ nsec /= 1000000000L / HZ;
+ return HZ * sec + nsec;
+}
+
+asmlinkage int irix_sigpoll_sys(unsigned long *set, struct irix5_siginfo *info,
+ struct timespec *tp)
+{
+ long expire = MAX_SCHEDULE_TIMEOUT;
+ sigset_t kset;
+ int i, sig, error, timeo = 0;
+
+#ifdef DEBUG_SIG
+ printk("[%s:%d] irix_sigpoll_sys(%p,%p,%p)\n",
+ current->comm, current->pid, set, info, tp);
+#endif
+
+ /* Must always specify the signal set. */
+ if (!set)
+ return -EINVAL;
+
+ if (!access_ok(VERIFY_READ, set, sizeof(kset))) {
+ error = -EFAULT;
+ goto out;
+ }
+
+ __copy_from_user(&kset, set, sizeof(set));
+ if (error)
+ goto out;
+
+ if (info && clear_user(info, sizeof(*info))) {
+ error = -EFAULT;
+ goto out;
+ }
+
+ if (tp) {
+ if (!access_ok(VERIFY_READ, tp, sizeof(*tp)))
+ return -EFAULT;
+ if (!tp->tv_sec && !tp->tv_nsec) {
+ error = -EINVAL;
+ goto out;
+ }
+ expire = timespectojiffies(tp)+(tp->tv_sec||tp->tv_nsec);
+ }
+
+ while(1) {
+ long tmp = 0;
+
+ current->state = TASK_INTERRUPTIBLE;
+ expire = schedule_timeout(expire);
+
+ for (i=0; i<=4; i++)
+ tmp |= (current->pending.signal.sig[i] & kset.sig[i]);
+
+ if (tmp)
+ break;
+ if (!expire) {
+ timeo = 1;
+ break;
+ }
+ if (signal_pending(current))
+ return -EINTR;
+ }
+ if (timeo)
+ return -EAGAIN;
+
+ for(sig = 1; i <= 65 /* IRIX_NSIG */; sig++) {
+ if (sigismember (&kset, sig))
+ continue;
+ if (sigismember (¤t->pending.signal, sig)) {
+ /* XXX need more than this... */
+ if (info)
+ info->sig = sig;
+ error = 0;
+ goto out;
+ }
+ }
+
+ /* Should not get here, but do something sane if we do. */
+ error = -EINTR;
+
+out:
+ return error;
+}
+
+/* This is here because of irix5_siginfo definition. */
+#define IRIX_P_PID 0
+#define IRIX_P_PGID 2
+#define IRIX_P_ALL 7
+
+extern int getrusage(struct task_struct *, int, struct rusage __user *);
+
+#define W_EXITED 1
+#define W_TRAPPED 2
+#define W_STOPPED 4
+#define W_CONT 8
+#define W_NOHANG 64
+
+#define W_MASK (W_EXITED | W_TRAPPED | W_STOPPED | W_CONT | W_NOHANG)
+
+asmlinkage int irix_waitsys(int type, int pid, struct irix5_siginfo *info,
+ int options, struct rusage *ru)
+{
+ int flag, retval;
+ DECLARE_WAITQUEUE(wait, current);
+ struct task_struct *tsk;
+ struct task_struct *p;
+ struct list_head *_p;
+
+ if (!info) {
+ retval = -EINVAL;
+ goto out;
+ }
+ if (!access_ok(VERIFY_WRITE, info, sizeof(*info))) {
+ retval = -EFAULT;
+ goto out;
+ }
+ if (ru) {
+ if (!access_ok(VERIFY_WRITE, ru, sizeof(*ru))) {
+ retval = -EFAULT;
+ goto out;
+ }
+ }
+ if (options & ~(W_MASK)) {
+ retval = -EINVAL;
+ goto out;
+ }
+ if (type != IRIX_P_PID && type != IRIX_P_PGID && type != IRIX_P_ALL) {
+ retval = -EINVAL;
+ goto out;
+ }
+ add_wait_queue(¤t->signal->wait_chldexit, &wait);
+repeat:
+ flag = 0;
+ current->state = TASK_INTERRUPTIBLE;
+ read_lock(&tasklist_lock);
+ tsk = current;
+ list_for_each(_p,&tsk->children) {
+ p = list_entry(_p,struct task_struct,sibling);
+ if ((type == IRIX_P_PID) && p->pid != pid)
+ continue;
+ if ((type == IRIX_P_PGID) && process_group(p) != pid)
+ continue;
+ if ((p->exit_signal != SIGCHLD))
+ continue;
+ flag = 1;
+ switch (p->state) {
+ case TASK_STOPPED:
+ if (!p->exit_code)
+ continue;
+ if (!(options & (W_TRAPPED|W_STOPPED)) &&
+ !(p->ptrace & PT_PTRACED))
+ continue;
+ read_unlock(&tasklist_lock);
+
+ /* move to end of parent's list to avoid starvation */
+ write_lock_irq(&tasklist_lock);
+ remove_parent(p);
+ add_parent(p, p->parent);
+ write_unlock_irq(&tasklist_lock);
+ retval = ru ? getrusage(p, RUSAGE_BOTH, ru) : 0;
+ if (!retval && ru) {
+ retval |= __put_user(SIGCHLD, &info->sig);
+ retval |= __put_user(0, &info->code);
+ retval |= __put_user(p->pid, &info->stuff.procinfo.pid);
+ retval |= __put_user((p->exit_code >> 8) & 0xff,
+ &info->stuff.procinfo.procdata.child.status);
+ retval |= __put_user(p->utime, &info->stuff.procinfo.procdata.child.utime);
+ retval |= __put_user(p->stime, &info->stuff.procinfo.procdata.child.stime);
+ }
+ if (!retval) {
+ p->exit_code = 0;
+ }
+ goto end_waitsys;
+
+ case EXIT_ZOMBIE:
+ current->signal->cutime += p->utime + p->signal->cutime;
+ current->signal->cstime += p->stime + p->signal->cstime;
+ if (ru != NULL)
+ getrusage(p, RUSAGE_BOTH, ru);
+ __put_user(SIGCHLD, &info->sig);
+ __put_user(1, &info->code); /* CLD_EXITED */
+ __put_user(p->pid, &info->stuff.procinfo.pid);
+ __put_user((p->exit_code >> 8) & 0xff,
+ &info->stuff.procinfo.procdata.child.status);
+ __put_user(p->utime,
+ &info->stuff.procinfo.procdata.child.utime);
+ __put_user(p->stime,
+ &info->stuff.procinfo.procdata.child.stime);
+ retval = 0;
+ if (p->real_parent != p->parent) {
+ write_lock_irq(&tasklist_lock);
+ remove_parent(p);
+ p->parent = p->real_parent;
+ add_parent(p, p->parent);
+ do_notify_parent(p, SIGCHLD);
+ write_unlock_irq(&tasklist_lock);
+ } else
+ release_task(p);
+ goto end_waitsys;
+ default:
+ continue;
+ }
+ tsk = next_thread(tsk);
+ }
+ read_unlock(&tasklist_lock);
+ if (flag) {
+ retval = 0;
+ if (options & W_NOHANG)
+ goto end_waitsys;
+ retval = -ERESTARTSYS;
+ if (signal_pending(current))
+ goto end_waitsys;
+ current->state = TASK_INTERRUPTIBLE;
+ schedule();
+ goto repeat;
+ }
+ retval = -ECHILD;
+end_waitsys:
+ current->state = TASK_RUNNING;
+ remove_wait_queue(¤t->signal->wait_chldexit, &wait);
+
+out:
+ return retval;
+}
+
+struct irix5_context {
+ u32 flags;
+ u32 link;
+ u32 sigmask[4];
+ struct { u32 sp, size, flags; } stack;
+ int regs[36];
+ u32 fpregs[32];
+ u32 fpcsr;
+ u32 _unused0;
+ u32 _unused1[47];
+ u32 weird_graphics_thing;
+};
+
+asmlinkage int irix_getcontext(struct pt_regs *regs)
+{
+ int i, base = 0;
+ struct irix5_context *ctx;
+ unsigned long flags;
+
+ if (regs->regs[2] == 1000)
+ base = 1;
+ ctx = (struct irix5_context *) regs->regs[base + 4];
+
+#ifdef DEBUG_SIG
+ printk("[%s:%d] irix_getcontext(%p)\n",
+ current->comm, current->pid, ctx);
+#endif
+
+ if (!access_ok(VERIFY_WRITE, ctx, sizeof(*ctx)))
+ return -EFAULT;
+
+ __put_user(current->thread.irix_oldctx, &ctx->link);
+
+ __copy_to_user(&ctx->sigmask, ¤t->blocked, sizeof(irix_sigset_t));
+
+ /* XXX Do sigstack stuff someday... */
+ __put_user(0, &ctx->stack.sp);
+ __put_user(0, &ctx->stack.size);
+ __put_user(0, &ctx->stack.flags);
+
+ __put_user(0, &ctx->weird_graphics_thing);
+ __put_user(0, &ctx->regs[0]);
+ for (i = 1; i < 32; i++)
+ __put_user(regs->regs[i], &ctx->regs[i]);
+ __put_user(regs->lo, &ctx->regs[32]);
+ __put_user(regs->hi, &ctx->regs[33]);
+ __put_user(regs->cp0_cause, &ctx->regs[34]);
+ __put_user(regs->cp0_epc, &ctx->regs[35]);
+
+ flags = 0x0f;
+ if (!used_math()) {
+ flags &= ~(0x08);
+ } else {
+ /* XXX wheee... */
+ printk("Wheee, no code for saving IRIX FPU context yet.\n");
+ }
+ __put_user(flags, &ctx->flags);
+
+ return 0;
+}
+
+asmlinkage unsigned long irix_setcontext(struct pt_regs *regs)
+{
+ int error, base = 0;
+ struct irix5_context *ctx;
+
+ if(regs->regs[2] == 1000)
+ base = 1;
+ ctx = (struct irix5_context *) regs->regs[base + 4];
+
+#ifdef DEBUG_SIG
+ printk("[%s:%d] irix_setcontext(%p)\n",
+ current->comm, current->pid, ctx);
+#endif
+
+ if (!access_ok(VERIFY_READ, ctx, sizeof(*ctx))) {
+ error = -EFAULT;
+ goto out;
+ }
+
+ if (ctx->flags & 0x02) {
+ /* XXX sigstack garbage, todo... */
+ printk("Wheee, cannot do sigstack stuff in setcontext\n");
+ }
+
+ if (ctx->flags & 0x04) {
+ int i;
+
+ /* XXX extra control block stuff... todo... */
+ for(i = 1; i < 32; i++)
+ regs->regs[i] = ctx->regs[i];
+ regs->lo = ctx->regs[32];
+ regs->hi = ctx->regs[33];
+ regs->cp0_epc = ctx->regs[35];
+ }
+
+ if (ctx->flags & 0x08) {
+ /* XXX fpu context, blah... */
+ printk("Wheee, cannot restore FPU context yet...\n");
+ }
+ current->thread.irix_oldctx = ctx->link;
+ error = regs->regs[2];
+
+out:
+ return error;
+}
+
+struct irix_sigstack { unsigned long sp; int status; };
+
+asmlinkage int irix_sigstack(struct irix_sigstack *new, struct irix_sigstack *old)
+{
+ int error = -EFAULT;
+
+#ifdef DEBUG_SIG
+ printk("[%s:%d] irix_sigstack(%p,%p)\n",
+ current->comm, current->pid, new, old);
+#endif
+ if(new) {
+ if (!access_ok(VERIFY_READ, new, sizeof(*new)))
+ goto out;
+ }
+
+ if(old) {
+ if (!access_ok(VERIFY_WRITE, old, sizeof(*old)))
+ goto out;
+ }
+ error = 0;
+
+out:
+ return error;
+}
+
+struct irix_sigaltstack { unsigned long sp; int size; int status; };
+
+asmlinkage int irix_sigaltstack(struct irix_sigaltstack *new,
+ struct irix_sigaltstack *old)
+{
+ int error = -EFAULT;
+
+#ifdef DEBUG_SIG
+ printk("[%s:%d] irix_sigaltstack(%p,%p)\n",
+ current->comm, current->pid, new, old);
+#endif
+ if (new) {
+ if (!access_ok(VERIFY_READ, new, sizeof(*new)))
+ goto out;
+ }
+
+ if (old) {
+ if (!access_ok(VERIFY_WRITE, old, sizeof(*old)))
+ goto out;
+ }
+ error = 0;
+
+out:
+ error = 0;
+
+ return error;
+}
+
+struct irix_procset {
+ int cmd, ltype, lid, rtype, rid;
+};
+
+asmlinkage int irix_sigsendset(struct irix_procset *pset, int sig)
+{
+ if (!access_ok(VERIFY_READ, pset, sizeof(*pset)))
+ return -EFAULT;
+
+#ifdef DEBUG_SIG
+ printk("[%s:%d] irix_sigsendset([%d,%d,%d,%d,%d],%d)\n",
+ current->comm, current->pid,
+ pset->cmd, pset->ltype, pset->lid, pset->rtype, pset->rid,
+ sig);
+#endif
+ return -EINVAL;
+}
diff --git a/arch/mips/kernel/irq-msc01.c b/arch/mips/kernel/irq-msc01.c
new file mode 100644
index 0000000..43c00ac
--- /dev/null
+++ b/arch/mips/kernel/irq-msc01.c
@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) 2004 MIPS Inc
+ * Author: chris@mips.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <asm/ptrace.h>
+#include <linux/sched.h>
+#include <linux/kernel_stat.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/msc01_ic.h>
+
+static unsigned long _icctrl_msc;
+#define MSC01_IC_REG_BASE _icctrl_msc
+
+#define MSCIC_WRITE(reg, data) do { *(volatile u32 *)(reg) = data; } while (0)
+#define MSCIC_READ(reg, data) do { data = *(volatile u32 *)(reg); } while (0)
+
+static unsigned int irq_base;
+
+/* mask off an interrupt */
+static inline void mask_msc_irq(unsigned int irq)
+{
+ if (irq < (irq_base + 32))
+ MSCIC_WRITE(MSC01_IC_DISL, 1<<(irq - irq_base));
+ else
+ MSCIC_WRITE(MSC01_IC_DISH, 1<<(irq - irq_base - 32));
+}
+
+/* unmask an interrupt */
+static inline void unmask_msc_irq(unsigned int irq)
+{
+ if (irq < (irq_base + 32))
+ MSCIC_WRITE(MSC01_IC_ENAL, 1<<(irq - irq_base));
+ else
+ MSCIC_WRITE(MSC01_IC_ENAH, 1<<(irq - irq_base - 32));
+}
+
+/*
+ * Enables the IRQ on SOC-it
+ */
+static void enable_msc_irq(unsigned int irq)
+{
+ unmask_msc_irq(irq);
+}
+
+/*
+ * Initialize the IRQ on SOC-it
+ */
+static unsigned int startup_msc_irq(unsigned int irq)
+{
+ unmask_msc_irq(irq);
+ return 0;
+}
+
+/*
+ * Disables the IRQ on SOC-it
+ */
+static void disable_msc_irq(unsigned int irq)
+{
+ mask_msc_irq(irq);
+}
+
+/*
+ * Masks and ACKs an IRQ
+ */
+static void level_mask_and_ack_msc_irq(unsigned int irq)
+{
+ mask_msc_irq(irq);
+ if (!cpu_has_ei)
+ MSCIC_WRITE(MSC01_IC_EOI, 0);
+}
+
+/*
+ * Masks and ACKs an IRQ
+ */
+static void edge_mask_and_ack_msc_irq(unsigned int irq)
+{
+ mask_msc_irq(irq);
+ if (!cpu_has_ei)
+ MSCIC_WRITE(MSC01_IC_EOI, 0);
+ else {
+ u32 r;
+ MSCIC_READ(MSC01_IC_SUP+irq*8, r);
+ MSCIC_WRITE(MSC01_IC_SUP+irq*8, r | ~MSC01_IC_SUP_EDGE_BIT);
+ MSCIC_WRITE(MSC01_IC_SUP+irq*8, r);
+ }
+}
+
+/*
+ * End IRQ processing
+ */
+static void end_msc_irq(unsigned int irq)
+{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+ unmask_msc_irq(irq);
+}
+
+/*
+ * Interrupt handler for interrupts coming from SOC-it.
+ */
+void ll_msc_irq(struct pt_regs *regs)
+{
+ unsigned int irq;
+
+ /* read the interrupt vector register */
+ MSCIC_READ(MSC01_IC_VEC, irq);
+ if (irq < 64)
+ do_IRQ(irq + irq_base, regs);
+ else {
+ /* Ignore spurious interrupt */
+ }
+}
+
+void
+msc_bind_eic_interrupt (unsigned int irq, unsigned int set)
+{
+ MSCIC_WRITE(MSC01_IC_RAMW,
+ (irq<<MSC01_IC_RAMW_ADDR_SHF) | (set<<MSC01_IC_RAMW_DATA_SHF));
+}
+
+#define shutdown_msc_irq disable_msc_irq
+
+struct hw_interrupt_type msc_levelirq_type = {
+ "SOC-it-Level",
+ startup_msc_irq,
+ shutdown_msc_irq,
+ enable_msc_irq,
+ disable_msc_irq,
+ level_mask_and_ack_msc_irq,
+ end_msc_irq,
+ NULL
+};
+
+struct hw_interrupt_type msc_edgeirq_type = {
+ "SOC-it-Edge",
+ startup_msc_irq,
+ shutdown_msc_irq,
+ enable_msc_irq,
+ disable_msc_irq,
+ edge_mask_and_ack_msc_irq,
+ end_msc_irq,
+ NULL
+};
+
+
+void __init init_msc_irqs(unsigned int base, msc_irqmap_t *imp, int nirq)
+{
+ extern void (*board_bind_eic_interrupt)(unsigned int irq, unsigned int regset);
+
+ _icctrl_msc = (unsigned long) ioremap (MIPS_MSC01_IC_REG_BASE, 0x40000);
+
+ /* Reset interrupt controller - initialises all registers to 0 */
+ MSCIC_WRITE(MSC01_IC_RST, MSC01_IC_RST_RST_BIT);
+
+ board_bind_eic_interrupt = &msc_bind_eic_interrupt;
+
+ for (; nirq >= 0; nirq--, imp++) {
+ int n = imp->im_irq;
+
+ switch (imp->im_type) {
+ case MSC01_IRQ_EDGE:
+ irq_desc[base+n].handler = &msc_edgeirq_type;
+ if (cpu_has_ei)
+ MSCIC_WRITE(MSC01_IC_SUP+n*8, MSC01_IC_SUP_EDGE_BIT);
+ else
+ MSCIC_WRITE(MSC01_IC_SUP+n*8, MSC01_IC_SUP_EDGE_BIT | imp->im_lvl);
+ break;
+ case MSC01_IRQ_LEVEL:
+ irq_desc[base+n].handler = &msc_levelirq_type;
+ if (cpu_has_ei)
+ MSCIC_WRITE(MSC01_IC_SUP+n*8, 0);
+ else
+ MSCIC_WRITE(MSC01_IC_SUP+n*8, imp->im_lvl);
+ }
+ }
+
+ irq_base = base;
+
+ MSCIC_WRITE(MSC01_IC_GENA, MSC01_IC_GENA_GENA_BIT); /* Enable interrupt generation */
+
+}
diff --git a/arch/mips/kernel/irq-mv6434x.c b/arch/mips/kernel/irq-mv6434x.c
new file mode 100644
index 0000000..088bbbc
--- /dev/null
+++ b/arch/mips/kernel/irq-mv6434x.c
@@ -0,0 +1,161 @@
+/*
+ * Copyright 2002 Momentum Computer
+ * Author: mdharm@momenco.com
+ * Copyright (C) 2004 Ralf Baechle <ralf@linux-mips.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <asm/ptrace.h>
+#include <linux/sched.h>
+#include <linux/kernel_stat.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <linux/mv643xx.h>
+
+static unsigned int irq_base;
+
+static inline int ls1bit32(unsigned int x)
+{
+ int b = 31, s;
+
+ s = 16; if (x << 16 == 0) s = 0; b -= s; x <<= s;
+ s = 8; if (x << 8 == 0) s = 0; b -= s; x <<= s;
+ s = 4; if (x << 4 == 0) s = 0; b -= s; x <<= s;
+ s = 2; if (x << 2 == 0) s = 0; b -= s; x <<= s;
+ s = 1; if (x << 1 == 0) s = 0; b -= s;
+
+ return b;
+}
+
+/* mask off an interrupt -- 1 is enable, 0 is disable */
+static inline void mask_mv64340_irq(unsigned int irq)
+{
+ uint32_t value;
+
+ if (irq < (irq_base + 32)) {
+ value = MV_READ(MV64340_INTERRUPT0_MASK_0_LOW);
+ value &= ~(1 << (irq - irq_base));
+ MV_WRITE(MV64340_INTERRUPT0_MASK_0_LOW, value);
+ } else {
+ value = MV_READ(MV64340_INTERRUPT0_MASK_0_HIGH);
+ value &= ~(1 << (irq - irq_base - 32));
+ MV_WRITE(MV64340_INTERRUPT0_MASK_0_HIGH, value);
+ }
+}
+
+/* unmask an interrupt -- 1 is enable, 0 is disable */
+static inline void unmask_mv64340_irq(unsigned int irq)
+{
+ uint32_t value;
+
+ if (irq < (irq_base + 32)) {
+ value = MV_READ(MV64340_INTERRUPT0_MASK_0_LOW);
+ value |= 1 << (irq - irq_base);
+ MV_WRITE(MV64340_INTERRUPT0_MASK_0_LOW, value);
+ } else {
+ value = MV_READ(MV64340_INTERRUPT0_MASK_0_HIGH);
+ value |= 1 << (irq - irq_base - 32);
+ MV_WRITE(MV64340_INTERRUPT0_MASK_0_HIGH, value);
+ }
+}
+
+/*
+ * Enables the IRQ on Marvell Chip
+ */
+static void enable_mv64340_irq(unsigned int irq)
+{
+ unmask_mv64340_irq(irq);
+}
+
+/*
+ * Initialize the IRQ on Marvell Chip
+ */
+static unsigned int startup_mv64340_irq(unsigned int irq)
+{
+ unmask_mv64340_irq(irq);
+ return 0;
+}
+
+/*
+ * Disables the IRQ on Marvell Chip
+ */
+static void disable_mv64340_irq(unsigned int irq)
+{
+ mask_mv64340_irq(irq);
+}
+
+/*
+ * Masks and ACKs an IRQ
+ */
+static void mask_and_ack_mv64340_irq(unsigned int irq)
+{
+ mask_mv64340_irq(irq);
+}
+
+/*
+ * End IRQ processing
+ */
+static void end_mv64340_irq(unsigned int irq)
+{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+ unmask_mv64340_irq(irq);
+}
+
+/*
+ * Interrupt handler for interrupts coming from the Marvell chip.
+ * It could be built in ethernet ports etc...
+ */
+void ll_mv64340_irq(struct pt_regs *regs)
+{
+ unsigned int irq_src_low, irq_src_high;
+ unsigned int irq_mask_low, irq_mask_high;
+
+ /* read the interrupt status registers */
+ irq_mask_low = MV_READ(MV64340_INTERRUPT0_MASK_0_LOW);
+ irq_mask_high = MV_READ(MV64340_INTERRUPT0_MASK_0_HIGH);
+ irq_src_low = MV_READ(MV64340_MAIN_INTERRUPT_CAUSE_LOW);
+ irq_src_high = MV_READ(MV64340_MAIN_INTERRUPT_CAUSE_HIGH);
+
+ /* mask for just the interrupts we want */
+ irq_src_low &= irq_mask_low;
+ irq_src_high &= irq_mask_high;
+
+ if (irq_src_low)
+ do_IRQ(ls1bit32(irq_src_low) + irq_base, regs);
+ else
+ do_IRQ(ls1bit32(irq_src_high) + irq_base + 32, regs);
+}
+
+#define shutdown_mv64340_irq disable_mv64340_irq
+
+struct hw_interrupt_type mv64340_irq_type = {
+ "MV-64340",
+ startup_mv64340_irq,
+ shutdown_mv64340_irq,
+ enable_mv64340_irq,
+ disable_mv64340_irq,
+ mask_and_ack_mv64340_irq,
+ end_mv64340_irq,
+ NULL
+};
+
+void __init mv64340_irq_init(unsigned int base)
+{
+ int i;
+
+ /* Reset irq handlers pointers to NULL */
+ for (i = base; i < base + 64; i++) {
+ irq_desc[i].status = IRQ_DISABLED;
+ irq_desc[i].action = 0;
+ irq_desc[i].depth = 2;
+ irq_desc[i].handler = &mv64340_irq_type;
+ }
+
+ irq_base = base;
+}
diff --git a/arch/mips/kernel/irq-rm7000.c b/arch/mips/kernel/irq-rm7000.c
new file mode 100644
index 0000000..f5d779f
--- /dev/null
+++ b/arch/mips/kernel/irq-rm7000.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2003 Ralf Baechle
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * Handler for RM7000 extended interrupts. These are a non-standard
+ * feature so we handle them separately from standard interrupts.
+ */
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+
+#include <asm/irq_cpu.h>
+#include <asm/mipsregs.h>
+#include <asm/system.h>
+
+static int irq_base;
+
+static inline void unmask_rm7k_irq(unsigned int irq)
+{
+ set_c0_intcontrol(0x100 << (irq - irq_base));
+}
+
+static inline void mask_rm7k_irq(unsigned int irq)
+{
+ clear_c0_intcontrol(0x100 << (irq - irq_base));
+}
+
+static inline void rm7k_cpu_irq_enable(unsigned int irq)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+ unmask_rm7k_irq(irq);
+ local_irq_restore(flags);
+}
+
+static void rm7k_cpu_irq_disable(unsigned int irq)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+ mask_rm7k_irq(irq);
+ local_irq_restore(flags);
+}
+
+static unsigned int rm7k_cpu_irq_startup(unsigned int irq)
+{
+ rm7k_cpu_irq_enable(irq);
+
+ return 0;
+}
+
+#define rm7k_cpu_irq_shutdown rm7k_cpu_irq_disable
+
+/*
+ * While we ack the interrupt interrupts are disabled and thus we don't need
+ * to deal with concurrency issues. Same for rm7k_cpu_irq_end.
+ */
+static void rm7k_cpu_irq_ack(unsigned int irq)
+{
+ mask_rm7k_irq(irq);
+}
+
+static void rm7k_cpu_irq_end(unsigned int irq)
+{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
+ unmask_rm7k_irq(irq);
+}
+
+static hw_irq_controller rm7k_irq_controller = {
+ "RM7000",
+ rm7k_cpu_irq_startup,
+ rm7k_cpu_irq_shutdown,
+ rm7k_cpu_irq_enable,
+ rm7k_cpu_irq_disable,
+ rm7k_cpu_irq_ack,
+ rm7k_cpu_irq_end,
+};
+
+void __init rm7k_cpu_irq_init(int base)
+{
+ int i;
+
+ clear_c0_intcontrol(0x00000f00); /* Mask all */
+
+ for (i = base; i < base + 4; i++) {
+ irq_desc[i].status = IRQ_DISABLED;
+ irq_desc[i].action = NULL;
+ irq_desc[i].depth = 1;
+ irq_desc[i].handler = &rm7k_irq_controller;
+ }
+
+ irq_base = base;
+}
diff --git a/arch/mips/kernel/irq-rm9000.c b/arch/mips/kernel/irq-rm9000.c
new file mode 100644
index 0000000..bdd1302
--- /dev/null
+++ b/arch/mips/kernel/irq-rm9000.c
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2003 Ralf Baechle
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * Handler for RM9000 extended interrupts. These are a non-standard
+ * feature so we handle them separately from standard interrupts.
+ */
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#include <asm/irq_cpu.h>
+#include <asm/mipsregs.h>
+#include <asm/system.h>
+
+static int irq_base;
+
+static inline void unmask_rm9k_irq(unsigned int irq)
+{
+ set_c0_intcontrol(0x1000 << (irq - irq_base));
+}
+
+static inline void mask_rm9k_irq(unsigned int irq)
+{
+ clear_c0_intcontrol(0x1000 << (irq - irq_base));
+}
+
+static inline void rm9k_cpu_irq_enable(unsigned int irq)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+ unmask_rm9k_irq(irq);
+ local_irq_restore(flags);
+}
+
+static void rm9k_cpu_irq_disable(unsigned int irq)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+ mask_rm9k_irq(irq);
+ local_irq_restore(flags);
+}
+
+static unsigned int rm9k_cpu_irq_startup(unsigned int irq)
+{
+ rm9k_cpu_irq_enable(irq);
+
+ return 0;
+}
+
+#define rm9k_cpu_irq_shutdown rm9k_cpu_irq_disable
+
+/*
+ * Performance counter interrupts are global on all processors.
+ */
+static void local_rm9k_perfcounter_irq_startup(void *args)
+{
+ unsigned int irq = (unsigned int) args;
+
+ rm9k_cpu_irq_enable(irq);
+}
+
+static unsigned int rm9k_perfcounter_irq_startup(unsigned int irq)
+{
+ on_each_cpu(local_rm9k_perfcounter_irq_startup, (void *) irq, 0, 1);
+
+ return 0;
+}
+
+static void local_rm9k_perfcounter_irq_shutdown(void *args)
+{
+ unsigned int irq = (unsigned int) args;
+ unsigned long flags;
+
+ local_irq_save(flags);
+ mask_rm9k_irq(irq);
+ local_irq_restore(flags);
+}
+
+static void rm9k_perfcounter_irq_shutdown(unsigned int irq)
+{
+ on_each_cpu(local_rm9k_perfcounter_irq_shutdown, (void *) irq, 0, 1);
+}
+
+
+/*
+ * While we ack the interrupt interrupts are disabled and thus we don't need
+ * to deal with concurrency issues. Same for rm9k_cpu_irq_end.
+ */
+static void rm9k_cpu_irq_ack(unsigned int irq)
+{
+ mask_rm9k_irq(irq);
+}
+
+static void rm9k_cpu_irq_end(unsigned int irq)
+{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
+ unmask_rm9k_irq(irq);
+}
+
+static hw_irq_controller rm9k_irq_controller = {
+ "RM9000",
+ rm9k_cpu_irq_startup,
+ rm9k_cpu_irq_shutdown,
+ rm9k_cpu_irq_enable,
+ rm9k_cpu_irq_disable,
+ rm9k_cpu_irq_ack,
+ rm9k_cpu_irq_end,
+};
+
+static hw_irq_controller rm9k_perfcounter_irq = {
+ "RM9000",
+ rm9k_perfcounter_irq_startup,
+ rm9k_perfcounter_irq_shutdown,
+ rm9k_cpu_irq_enable,
+ rm9k_cpu_irq_disable,
+ rm9k_cpu_irq_ack,
+ rm9k_cpu_irq_end,
+};
+
+unsigned int rm9000_perfcount_irq;
+
+EXPORT_SYMBOL(rm9000_perfcount_irq);
+
+void __init rm9k_cpu_irq_init(int base)
+{
+ int i;
+
+ clear_c0_intcontrol(0x0000f000); /* Mask all */
+
+ for (i = base; i < base + 4; i++) {
+ irq_desc[i].status = IRQ_DISABLED;
+ irq_desc[i].action = NULL;
+ irq_desc[i].depth = 1;
+ irq_desc[i].handler = &rm9k_irq_controller;
+ }
+
+ rm9000_perfcount_irq = base + 1;
+ irq_desc[rm9000_perfcount_irq].handler = &rm9k_perfcounter_irq;
+
+ irq_base = base;
+}
diff --git a/arch/mips/kernel/irq.c b/arch/mips/kernel/irq.c
new file mode 100644
index 0000000..441157a
--- /dev/null
+++ b/arch/mips/kernel/irq.c
@@ -0,0 +1,140 @@
+/*
+ * 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.
+ *
+ * Code to handle x86 style IRQs plus some generic interrupt stuff.
+ *
+ * Copyright (C) 1992 Linus Torvalds
+ * Copyright (C) 1994 - 2000 Ralf Baechle
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/kernel_stat.h>
+#include <linux/module.h>
+#include <linux/proc_fs.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/random.h>
+#include <linux/sched.h>
+#include <linux/seq_file.h>
+#include <linux/kallsyms.h>
+
+#include <asm/atomic.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+
+/*
+ * 'what should we do if we get a hw irq event on an illegal vector'.
+ * each architecture has to answer this themselves.
+ */
+void ack_bad_irq(unsigned int irq)
+{
+ printk("unexpected IRQ # %d\n", irq);
+}
+
+atomic_t irq_err_count;
+
+#undef do_IRQ
+
+/*
+ * do_IRQ handles all normal device IRQ's (the special
+ * SMP cross-CPU interrupts have their own specific
+ * handlers).
+ */
+asmlinkage unsigned int do_IRQ(unsigned int irq, struct pt_regs *regs)
+{
+ irq_enter();
+
+ __do_IRQ(irq, regs);
+
+ irq_exit();
+
+ return 1;
+}
+
+/*
+ * Generic, controller-independent functions:
+ */
+
+int show_interrupts(struct seq_file *p, void *v)
+{
+ int i = *(loff_t *) v, j;
+ struct irqaction * action;
+ unsigned long flags;
+
+ if (i == 0) {
+ seq_printf(p, " ");
+ for (j=0; j<NR_CPUS; j++)
+ if (cpu_online(j))
+ seq_printf(p, "CPU%d ",j);
+ seq_putc(p, '\n');
+ }
+
+ if (i < NR_IRQS) {
+ spin_lock_irqsave(&irq_desc[i].lock, flags);
+ action = irq_desc[i].action;
+ if (!action)
+ goto skip;
+ seq_printf(p, "%3d: ",i);
+#ifndef CONFIG_SMP
+ seq_printf(p, "%10u ", kstat_irqs(i));
+#else
+ for (j = 0; j < NR_CPUS; j++)
+ if (cpu_online(j))
+ seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
+#endif
+ seq_printf(p, " %14s", irq_desc[i].handler->typename);
+ seq_printf(p, " %s", action->name);
+
+ for (action=action->next; action; action = action->next)
+ seq_printf(p, ", %s", action->name);
+
+ seq_putc(p, '\n');
+skip:
+ spin_unlock_irqrestore(&irq_desc[i].lock, flags);
+ } else if (i == NR_IRQS) {
+ seq_putc(p, '\n');
+ seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count));
+ }
+ return 0;
+}
+
+#ifdef CONFIG_KGDB
+extern void breakpoint(void);
+extern void set_debug_traps(void);
+
+static int kgdb_flag = 1;
+static int __init nokgdb(char *str)
+{
+ kgdb_flag = 0;
+ return 1;
+}
+__setup("nokgdb", nokgdb);
+#endif
+
+void __init init_IRQ(void)
+{
+ int i;
+
+ for (i = 0; i < NR_IRQS; i++) {
+ irq_desc[i].status = IRQ_DISABLED;
+ irq_desc[i].action = NULL;
+ irq_desc[i].depth = 1;
+ irq_desc[i].handler = &no_irq_type;
+ spin_lock_init(&irq_desc[i].lock);
+ }
+
+ arch_init_irq();
+
+#ifdef CONFIG_KGDB
+ if (kgdb_flag) {
+ printk("Wait for gdb client connection ...\n");
+ set_debug_traps();
+ breakpoint();
+ }
+#endif
+}
diff --git a/arch/mips/kernel/irq_cpu.c b/arch/mips/kernel/irq_cpu.c
new file mode 100644
index 0000000..2b936cf
--- /dev/null
+++ b/arch/mips/kernel/irq_cpu.c
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
+ *
+ * Copyright (C) 2001 Ralf Baechle
+ *
+ * This file define the irq handler for MIPS CPU interrupts.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+/*
+ * Almost all MIPS CPUs define 8 interrupt sources. They are typically
+ * level triggered (i.e., cannot be cleared from CPU; must be cleared from
+ * device). The first two are software interrupts which we don't really
+ * use or support. The last one is usually the CPU timer interrupt if
+ * counter register is present or, for CPUs with an external FPU, by
+ * convention it's the FPU exception interrupt.
+ *
+ * Don't even think about using this on SMP. You have been warned.
+ *
+ * This file exports one global function:
+ * void mips_cpu_irq_init(int irq_base);
+ */
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+
+#include <asm/irq_cpu.h>
+#include <asm/mipsregs.h>
+#include <asm/system.h>
+
+static int mips_cpu_irq_base;
+
+static inline void unmask_mips_irq(unsigned int irq)
+{
+ clear_c0_cause(0x100 << (irq - mips_cpu_irq_base));
+ set_c0_status(0x100 << (irq - mips_cpu_irq_base));
+}
+
+static inline void mask_mips_irq(unsigned int irq)
+{
+ clear_c0_status(0x100 << (irq - mips_cpu_irq_base));
+}
+
+static inline void mips_cpu_irq_enable(unsigned int irq)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+ unmask_mips_irq(irq);
+ local_irq_restore(flags);
+}
+
+static void mips_cpu_irq_disable(unsigned int irq)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+ mask_mips_irq(irq);
+ local_irq_restore(flags);
+}
+
+static unsigned int mips_cpu_irq_startup(unsigned int irq)
+{
+ mips_cpu_irq_enable(irq);
+
+ return 0;
+}
+
+#define mips_cpu_irq_shutdown mips_cpu_irq_disable
+
+/*
+ * While we ack the interrupt interrupts are disabled and thus we don't need
+ * to deal with concurrency issues. Same for mips_cpu_irq_end.
+ */
+static void mips_cpu_irq_ack(unsigned int irq)
+{
+ /* Only necessary for soft interrupts */
+ clear_c0_cause(0x100 << (irq - mips_cpu_irq_base));
+
+ mask_mips_irq(irq);
+}
+
+static void mips_cpu_irq_end(unsigned int irq)
+{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
+ unmask_mips_irq(irq);
+}
+
+static hw_irq_controller mips_cpu_irq_controller = {
+ "MIPS",
+ mips_cpu_irq_startup,
+ mips_cpu_irq_shutdown,
+ mips_cpu_irq_enable,
+ mips_cpu_irq_disable,
+ mips_cpu_irq_ack,
+ mips_cpu_irq_end,
+ NULL /* no affinity stuff for UP */
+};
+
+
+void __init mips_cpu_irq_init(int irq_base)
+{
+ int i;
+
+ for (i = irq_base; i < irq_base + 8; i++) {
+ irq_desc[i].status = IRQ_DISABLED;
+ irq_desc[i].action = NULL;
+ irq_desc[i].depth = 1;
+ irq_desc[i].handler = &mips_cpu_irq_controller;
+ }
+
+ mips_cpu_irq_base = irq_base;
+}
diff --git a/arch/mips/kernel/linux32.c b/arch/mips/kernel/linux32.c
new file mode 100644
index 0000000..993abc8
--- /dev/null
+++ b/arch/mips/kernel/linux32.c
@@ -0,0 +1,1469 @@
+/*
+ * Conversion between 32-bit and 64-bit native system calls.
+ *
+ * Copyright (C) 2000 Silicon Graphics, Inc.
+ * Written by Ulf Carlsson (ulfc@engr.sgi.com)
+ * sys32_execve from ia64/ia32 code, Feb 2000, Kanoj Sarcar (kanoj@sgi.com)
+ */
+#include <linux/config.h>
+#include <linux/compiler.h>
+#include <linux/mm.h>
+#include <linux/errno.h>
+#include <linux/file.h>
+#include <linux/smp_lock.h>
+#include <linux/highuid.h>
+#include <linux/dirent.h>
+#include <linux/resource.h>
+#include <linux/highmem.h>
+#include <linux/time.h>
+#include <linux/times.h>
+#include <linux/poll.h>
+#include <linux/slab.h>
+#include <linux/skbuff.h>
+#include <linux/filter.h>
+#include <linux/shm.h>
+#include <linux/sem.h>
+#include <linux/msg.h>
+#include <linux/icmpv6.h>
+#include <linux/syscalls.h>
+#include <linux/sysctl.h>
+#include <linux/utime.h>
+#include <linux/utsname.h>
+#include <linux/personality.h>
+#include <linux/timex.h>
+#include <linux/dnotify.h>
+#include <linux/module.h>
+#include <linux/binfmts.h>
+#include <linux/security.h>
+#include <linux/compat.h>
+#include <linux/vfs.h>
+
+#include <net/sock.h>
+#include <net/scm.h>
+
+#include <asm/ipc.h>
+#include <asm/sim.h>
+#include <asm/uaccess.h>
+#include <asm/mmu_context.h>
+#include <asm/mman.h>
+
+/* Use this to get at 32-bit user passed pointers. */
+/* A() macro should be used for places where you e.g.
+ have some internal variable u32 and just want to get
+ rid of a compiler warning. AA() has to be used in
+ places where you want to convert a function argument
+ to 32bit pointer or when you e.g. access pt_regs
+ structure and want to consider 32bit registers only.
+ */
+#define A(__x) ((unsigned long)(__x))
+#define AA(__x) ((unsigned long)((int)__x))
+
+#ifdef __MIPSEB__
+#define merge_64(r1,r2) ((((r1) & 0xffffffffUL) << 32) + ((r2) & 0xffffffffUL))
+#endif
+#ifdef __MIPSEL__
+#define merge_64(r1,r2) ((((r2) & 0xffffffffUL) << 32) + ((r1) & 0xffffffffUL))
+#endif
+
+/*
+ * Revalidate the inode. This is required for proper NFS attribute caching.
+ */
+
+int cp_compat_stat(struct kstat *stat, struct compat_stat *statbuf)
+{
+ struct compat_stat tmp;
+
+ if (!new_valid_dev(stat->dev) || !new_valid_dev(stat->rdev))
+ return -EOVERFLOW;
+
+ memset(&tmp, 0, sizeof(tmp));
+ tmp.st_dev = new_encode_dev(stat->dev);
+ tmp.st_ino = stat->ino;
+ tmp.st_mode = stat->mode;
+ tmp.st_nlink = stat->nlink;
+ SET_UID(tmp.st_uid, stat->uid);
+ SET_GID(tmp.st_gid, stat->gid);
+ tmp.st_rdev = new_encode_dev(stat->rdev);
+ tmp.st_size = stat->size;
+ tmp.st_atime = stat->atime.tv_sec;
+ tmp.st_mtime = stat->mtime.tv_sec;
+ tmp.st_ctime = stat->ctime.tv_sec;
+#ifdef STAT_HAVE_NSEC
+ tmp.st_atime_nsec = stat->atime.tv_nsec;
+ tmp.st_mtime_nsec = stat->mtime.tv_nsec;
+ tmp.st_ctime_nsec = stat->ctime.tv_nsec;
+#endif
+ tmp.st_blocks = stat->blocks;
+ tmp.st_blksize = stat->blksize;
+ return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
+}
+
+asmlinkage unsigned long
+sys32_mmap2(unsigned long addr, unsigned long len, unsigned long prot,
+ unsigned long flags, unsigned long fd, unsigned long pgoff)
+{
+ struct file * file = NULL;
+ unsigned long error;
+
+ error = -EINVAL;
+ if (!(flags & MAP_ANONYMOUS)) {
+ error = -EBADF;
+ file = fget(fd);
+ if (!file)
+ goto out;
+ }
+ flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+
+ down_write(¤t->mm->mmap_sem);
+ error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
+ up_write(¤t->mm->mmap_sem);
+ if (file)
+ fput(file);
+
+out:
+ return error;
+}
+
+
+asmlinkage int sys_truncate64(const char *path, unsigned int high,
+ unsigned int low)
+{
+ if ((int)high < 0)
+ return -EINVAL;
+ return sys_truncate(path, ((long) high << 32) | low);
+}
+
+asmlinkage int sys_ftruncate64(unsigned int fd, unsigned int high,
+ unsigned int low)
+{
+ if ((int)high < 0)
+ return -EINVAL;
+ return sys_ftruncate(fd, ((long) high << 32) | low);
+}
+
+/*
+ * sys_execve() executes a new program.
+ */
+asmlinkage int sys32_execve(nabi_no_regargs struct pt_regs regs)
+{
+ int error;
+ char * filename;
+
+ filename = getname(compat_ptr(regs.regs[4]));
+ error = PTR_ERR(filename);
+ if (IS_ERR(filename))
+ goto out;
+ error = compat_do_execve(filename, compat_ptr(regs.regs[5]),
+ compat_ptr(regs.regs[6]), ®s);
+ putname(filename);
+
+out:
+ return error;
+}
+
+struct dirent32 {
+ unsigned int d_ino;
+ unsigned int d_off;
+ unsigned short d_reclen;
+ char d_name[NAME_MAX + 1];
+};
+
+static void
+xlate_dirent(void *dirent64, void *dirent32, long n)
+{
+ long off;
+ struct dirent *dirp;
+ struct dirent32 *dirp32;
+
+ off = 0;
+ while (off < n) {
+ dirp = (struct dirent *)(dirent64 + off);
+ dirp32 = (struct dirent32 *)(dirent32 + off);
+ off += dirp->d_reclen;
+ dirp32->d_ino = dirp->d_ino;
+ dirp32->d_off = (unsigned int)dirp->d_off;
+ dirp32->d_reclen = dirp->d_reclen;
+ strncpy(dirp32->d_name, dirp->d_name, dirp->d_reclen - ((3 * 4) + 2));
+ }
+ return;
+}
+
+asmlinkage long
+sys32_getdents(unsigned int fd, void * dirent32, unsigned int count)
+{
+ long n;
+ void *dirent64;
+
+ dirent64 = (void *)((unsigned long)(dirent32 + (sizeof(long) - 1)) & ~(sizeof(long) - 1));
+ if ((n = sys_getdents(fd, dirent64, count - (dirent64 - dirent32))) < 0)
+ return(n);
+ xlate_dirent(dirent64, dirent32, n);
+ return(n);
+}
+
+asmlinkage int old_readdir(unsigned int fd, void * dirent, unsigned int count);
+
+asmlinkage int
+sys32_readdir(unsigned int fd, void * dirent32, unsigned int count)
+{
+ int n;
+ struct dirent dirent64;
+
+ if ((n = old_readdir(fd, &dirent64, count)) < 0)
+ return(n);
+ xlate_dirent(&dirent64, dirent32, dirent64.d_reclen);
+ return(n);
+}
+
+struct rusage32 {
+ struct compat_timeval ru_utime;
+ struct compat_timeval ru_stime;
+ int ru_maxrss;
+ int ru_ixrss;
+ int ru_idrss;
+ int ru_isrss;
+ int ru_minflt;
+ int ru_majflt;
+ int ru_nswap;
+ int ru_inblock;
+ int ru_oublock;
+ int ru_msgsnd;
+ int ru_msgrcv;
+ int ru_nsignals;
+ int ru_nvcsw;
+ int ru_nivcsw;
+};
+
+static int
+put_rusage (struct rusage32 *ru, struct rusage *r)
+{
+ int err;
+
+ if (!access_ok(VERIFY_WRITE, ru, sizeof *ru))
+ return -EFAULT;
+
+ err = __put_user (r->ru_utime.tv_sec, &ru->ru_utime.tv_sec);
+ err |= __put_user (r->ru_utime.tv_usec, &ru->ru_utime.tv_usec);
+ err |= __put_user (r->ru_stime.tv_sec, &ru->ru_stime.tv_sec);
+ err |= __put_user (r->ru_stime.tv_usec, &ru->ru_stime.tv_usec);
+ err |= __put_user (r->ru_maxrss, &ru->ru_maxrss);
+ err |= __put_user (r->ru_ixrss, &ru->ru_ixrss);
+ err |= __put_user (r->ru_idrss, &ru->ru_idrss);
+ err |= __put_user (r->ru_isrss, &ru->ru_isrss);
+ err |= __put_user (r->ru_minflt, &ru->ru_minflt);
+ err |= __put_user (r->ru_majflt, &ru->ru_majflt);
+ err |= __put_user (r->ru_nswap, &ru->ru_nswap);
+ err |= __put_user (r->ru_inblock, &ru->ru_inblock);
+ err |= __put_user (r->ru_oublock, &ru->ru_oublock);
+ err |= __put_user (r->ru_msgsnd, &ru->ru_msgsnd);
+ err |= __put_user (r->ru_msgrcv, &ru->ru_msgrcv);
+ err |= __put_user (r->ru_nsignals, &ru->ru_nsignals);
+ err |= __put_user (r->ru_nvcsw, &ru->ru_nvcsw);
+ err |= __put_user (r->ru_nivcsw, &ru->ru_nivcsw);
+
+ return err;
+}
+
+asmlinkage int
+sys32_wait4(compat_pid_t pid, unsigned int * stat_addr, int options,
+ struct rusage32 * ru)
+{
+ if (!ru)
+ return sys_wait4(pid, stat_addr, options, NULL);
+ else {
+ struct rusage r;
+ int ret;
+ unsigned int status;
+ mm_segment_t old_fs = get_fs();
+
+ set_fs(KERNEL_DS);
+ ret = sys_wait4(pid, stat_addr ? &status : NULL, options, &r);
+ set_fs(old_fs);
+ if (put_rusage (ru, &r)) return -EFAULT;
+ if (stat_addr && put_user (status, stat_addr))
+ return -EFAULT;
+ return ret;
+ }
+}
+
+asmlinkage int
+sys32_waitpid(compat_pid_t pid, unsigned int *stat_addr, int options)
+{
+ return sys32_wait4(pid, stat_addr, options, NULL);
+}
+
+struct sysinfo32 {
+ s32 uptime;
+ u32 loads[3];
+ u32 totalram;
+ u32 freeram;
+ u32 sharedram;
+ u32 bufferram;
+ u32 totalswap;
+ u32 freeswap;
+ u16 procs;
+ u32 totalhigh;
+ u32 freehigh;
+ u32 mem_unit;
+ char _f[8];
+};
+
+asmlinkage int sys32_sysinfo(struct sysinfo32 *info)
+{
+ struct sysinfo s;
+ int ret, err;
+ mm_segment_t old_fs = get_fs ();
+
+ set_fs (KERNEL_DS);
+ ret = sys_sysinfo(&s);
+ set_fs (old_fs);
+ err = put_user (s.uptime, &info->uptime);
+ err |= __put_user (s.loads[0], &info->loads[0]);
+ err |= __put_user (s.loads[1], &info->loads[1]);
+ err |= __put_user (s.loads[2], &info->loads[2]);
+ err |= __put_user (s.totalram, &info->totalram);
+ err |= __put_user (s.freeram, &info->freeram);
+ err |= __put_user (s.sharedram, &info->sharedram);
+ err |= __put_user (s.bufferram, &info->bufferram);
+ err |= __put_user (s.totalswap, &info->totalswap);
+ err |= __put_user (s.freeswap, &info->freeswap);
+ err |= __put_user (s.procs, &info->procs);
+ err |= __put_user (s.totalhigh, &info->totalhigh);
+ err |= __put_user (s.freehigh, &info->freehigh);
+ err |= __put_user (s.mem_unit, &info->mem_unit);
+ if (err)
+ return -EFAULT;
+ return ret;
+}
+
+#define RLIM_INFINITY32 0x7fffffff
+#define RESOURCE32(x) ((x > RLIM_INFINITY32) ? RLIM_INFINITY32 : x)
+
+struct rlimit32 {
+ int rlim_cur;
+ int rlim_max;
+};
+
+#ifdef __MIPSEB__
+asmlinkage long sys32_truncate64(const char * path, unsigned long __dummy,
+ int length_hi, int length_lo)
+#endif
+#ifdef __MIPSEL__
+asmlinkage long sys32_truncate64(const char * path, unsigned long __dummy,
+ int length_lo, int length_hi)
+#endif
+{
+ loff_t length;
+
+ length = ((unsigned long) length_hi << 32) | (unsigned int) length_lo;
+
+ return sys_truncate(path, length);
+}
+
+#ifdef __MIPSEB__
+asmlinkage long sys32_ftruncate64(unsigned int fd, unsigned long __dummy,
+ int length_hi, int length_lo)
+#endif
+#ifdef __MIPSEL__
+asmlinkage long sys32_ftruncate64(unsigned int fd, unsigned long __dummy,
+ int length_lo, int length_hi)
+#endif
+{
+ loff_t length;
+
+ length = ((unsigned long) length_hi << 32) | (unsigned int) length_lo;
+
+ return sys_ftruncate(fd, length);
+}
+
+static inline long
+get_tv32(struct timeval *o, struct compat_timeval *i)
+{
+ return (!access_ok(VERIFY_READ, i, sizeof(*i)) ||
+ (__get_user(o->tv_sec, &i->tv_sec) |
+ __get_user(o->tv_usec, &i->tv_usec)));
+}
+
+static inline long
+put_tv32(struct compat_timeval *o, struct timeval *i)
+{
+ return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) ||
+ (__put_user(i->tv_sec, &o->tv_sec) |
+ __put_user(i->tv_usec, &o->tv_usec)));
+}
+
+extern struct timezone sys_tz;
+
+asmlinkage int
+sys32_gettimeofday(struct compat_timeval *tv, struct timezone *tz)
+{
+ if (tv) {
+ struct timeval ktv;
+ do_gettimeofday(&ktv);
+ if (put_tv32(tv, &ktv))
+ return -EFAULT;
+ }
+ if (tz) {
+ if (copy_to_user(tz, &sys_tz, sizeof(sys_tz)))
+ return -EFAULT;
+ }
+ return 0;
+}
+
+static inline long get_ts32(struct timespec *o, struct compat_timeval *i)
+{
+ long usec;
+
+ if (!access_ok(VERIFY_READ, i, sizeof(*i)))
+ return -EFAULT;
+ if (__get_user(o->tv_sec, &i->tv_sec))
+ return -EFAULT;
+ if (__get_user(usec, &i->tv_usec))
+ return -EFAULT;
+ o->tv_nsec = usec * 1000;
+ return 0;
+}
+
+asmlinkage int
+sys32_settimeofday(struct compat_timeval *tv, struct timezone *tz)
+{
+ struct timespec kts;
+ struct timezone ktz;
+
+ if (tv) {
+ if (get_ts32(&kts, tv))
+ return -EFAULT;
+ }
+ if (tz) {
+ if (copy_from_user(&ktz, tz, sizeof(ktz)))
+ return -EFAULT;
+ }
+
+ return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL);
+}
+
+asmlinkage int sys32_llseek(unsigned int fd, unsigned int offset_high,
+ unsigned int offset_low, loff_t * result,
+ unsigned int origin)
+{
+ return sys_llseek(fd, offset_high, offset_low, result, origin);
+}
+
+/* From the Single Unix Spec: pread & pwrite act like lseek to pos + op +
+ lseek back to original location. They fail just like lseek does on
+ non-seekable files. */
+
+asmlinkage ssize_t sys32_pread(unsigned int fd, char * buf,
+ size_t count, u32 unused, u64 a4, u64 a5)
+{
+ ssize_t ret;
+ struct file * file;
+ ssize_t (*read)(struct file *, char *, size_t, loff_t *);
+ loff_t pos;
+
+ ret = -EBADF;
+ file = fget(fd);
+ if (!file)
+ goto bad_file;
+ if (!(file->f_mode & FMODE_READ))
+ goto out;
+ pos = merge_64(a4, a5);
+ ret = rw_verify_area(READ, file, &pos, count);
+ if (ret)
+ goto out;
+ ret = -EINVAL;
+ if (!file->f_op || !(read = file->f_op->read))
+ goto out;
+ if (pos < 0)
+ goto out;
+ ret = -ESPIPE;
+ if (!(file->f_mode & FMODE_PREAD))
+ goto out;
+ ret = read(file, buf, count, &pos);
+ if (ret > 0)
+ dnotify_parent(file->f_dentry, DN_ACCESS);
+out:
+ fput(file);
+bad_file:
+ return ret;
+}
+
+asmlinkage ssize_t sys32_pwrite(unsigned int fd, const char * buf,
+ size_t count, u32 unused, u64 a4, u64 a5)
+{
+ ssize_t ret;
+ struct file * file;
+ ssize_t (*write)(struct file *, const char *, size_t, loff_t *);
+ loff_t pos;
+
+ ret = -EBADF;
+ file = fget(fd);
+ if (!file)
+ goto bad_file;
+ if (!(file->f_mode & FMODE_WRITE))
+ goto out;
+ pos = merge_64(a4, a5);
+ ret = rw_verify_area(WRITE, file, &pos, count);
+ if (ret)
+ goto out;
+ ret = -EINVAL;
+ if (!file->f_op || !(write = file->f_op->write))
+ goto out;
+ if (pos < 0)
+ goto out;
+
+ ret = -ESPIPE;
+ if (!(file->f_mode & FMODE_PWRITE))
+ goto out;
+
+ ret = write(file, buf, count, &pos);
+ if (ret > 0)
+ dnotify_parent(file->f_dentry, DN_MODIFY);
+out:
+ fput(file);
+bad_file:
+ return ret;
+}
+
+asmlinkage int sys32_sched_rr_get_interval(compat_pid_t pid,
+ struct compat_timespec *interval)
+{
+ struct timespec t;
+ int ret;
+ mm_segment_t old_fs = get_fs ();
+
+ set_fs (KERNEL_DS);
+ ret = sys_sched_rr_get_interval(pid, &t);
+ set_fs (old_fs);
+ if (put_user (t.tv_sec, &interval->tv_sec) ||
+ __put_user (t.tv_nsec, &interval->tv_nsec))
+ return -EFAULT;
+ return ret;
+}
+
+struct msgbuf32 { s32 mtype; char mtext[1]; };
+
+struct ipc_perm32
+{
+ key_t key;
+ compat_uid_t uid;
+ compat_gid_t gid;
+ compat_uid_t cuid;
+ compat_gid_t cgid;
+ compat_mode_t mode;
+ unsigned short seq;
+};
+
+struct ipc64_perm32 {
+ key_t key;
+ compat_uid_t uid;
+ compat_gid_t gid;
+ compat_uid_t cuid;
+ compat_gid_t cgid;
+ compat_mode_t mode;
+ unsigned short seq;
+ unsigned short __pad1;
+ unsigned int __unused1;
+ unsigned int __unused2;
+};
+
+struct semid_ds32 {
+ struct ipc_perm32 sem_perm; /* permissions .. see ipc.h */
+ compat_time_t sem_otime; /* last semop time */
+ compat_time_t sem_ctime; /* last change time */
+ u32 sem_base; /* ptr to first semaphore in array */
+ u32 sem_pending; /* pending operations to be processed */
+ u32 sem_pending_last; /* last pending operation */
+ u32 undo; /* undo requests on this array */
+ unsigned short sem_nsems; /* no. of semaphores in array */
+};
+
+struct semid64_ds32 {
+ struct ipc64_perm32 sem_perm;
+ compat_time_t sem_otime;
+ compat_time_t sem_ctime;
+ unsigned int sem_nsems;
+ unsigned int __unused1;
+ unsigned int __unused2;
+};
+
+struct msqid_ds32
+{
+ struct ipc_perm32 msg_perm;
+ u32 msg_first;
+ u32 msg_last;
+ compat_time_t msg_stime;
+ compat_time_t msg_rtime;
+ compat_time_t msg_ctime;
+ u32 wwait;
+ u32 rwait;
+ unsigned short msg_cbytes;
+ unsigned short msg_qnum;
+ unsigned short msg_qbytes;
+ compat_ipc_pid_t msg_lspid;
+ compat_ipc_pid_t msg_lrpid;
+};
+
+struct msqid64_ds32 {
+ struct ipc64_perm32 msg_perm;
+ compat_time_t msg_stime;
+ unsigned int __unused1;
+ compat_time_t msg_rtime;
+ unsigned int __unused2;
+ compat_time_t msg_ctime;
+ unsigned int __unused3;
+ unsigned int msg_cbytes;
+ unsigned int msg_qnum;
+ unsigned int msg_qbytes;
+ compat_pid_t msg_lspid;
+ compat_pid_t msg_lrpid;
+ unsigned int __unused4;
+ unsigned int __unused5;
+};
+
+struct shmid_ds32 {
+ struct ipc_perm32 shm_perm;
+ int shm_segsz;
+ compat_time_t shm_atime;
+ compat_time_t shm_dtime;
+ compat_time_t shm_ctime;
+ compat_ipc_pid_t shm_cpid;
+ compat_ipc_pid_t shm_lpid;
+ unsigned short shm_nattch;
+};
+
+struct shmid64_ds32 {
+ struct ipc64_perm32 shm_perm;
+ compat_size_t shm_segsz;
+ compat_time_t shm_atime;
+ compat_time_t shm_dtime;
+ compat_time_t shm_ctime;
+ compat_pid_t shm_cpid;
+ compat_pid_t shm_lpid;
+ unsigned int shm_nattch;
+ unsigned int __unused1;
+ unsigned int __unused2;
+};
+
+struct ipc_kludge32 {
+ u32 msgp;
+ s32 msgtyp;
+};
+
+static int
+do_sys32_semctl(int first, int second, int third, void *uptr)
+{
+ union semun fourth;
+ u32 pad;
+ int err, err2;
+ struct semid64_ds s;
+ mm_segment_t old_fs;
+
+ if (!uptr)
+ return -EINVAL;
+ err = -EFAULT;
+ if (get_user (pad, (u32 *)uptr))
+ return err;
+ if ((third & ~IPC_64) == SETVAL)
+ fourth.val = (int)pad;
+ else
+ fourth.__pad = (void *)A(pad);
+ switch (third & ~IPC_64) {
+ case IPC_INFO:
+ case IPC_RMID:
+ case IPC_SET:
+ case SEM_INFO:
+ case GETVAL:
+ case GETPID:
+ case GETNCNT:
+ case GETZCNT:
+ case GETALL:
+ case SETVAL:
+ case SETALL:
+ err = sys_semctl (first, second, third, fourth);
+ break;
+
+ case IPC_STAT:
+ case SEM_STAT:
+ fourth.__pad = &s;
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+ err = sys_semctl(first, second, third | IPC_64, fourth);
+ set_fs(old_fs);
+
+ if (third & IPC_64) {
+ struct semid64_ds32 *usp64 = (struct semid64_ds32 *) A(pad);
+
+ if (!access_ok(VERIFY_WRITE, usp64, sizeof(*usp64))) {
+ err = -EFAULT;
+ break;
+ }
+ err2 = __put_user(s.sem_perm.key, &usp64->sem_perm.key);
+ err2 |= __put_user(s.sem_perm.uid, &usp64->sem_perm.uid);
+ err2 |= __put_user(s.sem_perm.gid, &usp64->sem_perm.gid);
+ err2 |= __put_user(s.sem_perm.cuid, &usp64->sem_perm.cuid);
+ err2 |= __put_user(s.sem_perm.cgid, &usp64->sem_perm.cgid);
+ err2 |= __put_user(s.sem_perm.mode, &usp64->sem_perm.mode);
+ err2 |= __put_user(s.sem_perm.seq, &usp64->sem_perm.seq);
+ err2 |= __put_user(s.sem_otime, &usp64->sem_otime);
+ err2 |= __put_user(s.sem_ctime, &usp64->sem_ctime);
+ err2 |= __put_user(s.sem_nsems, &usp64->sem_nsems);
+ } else {
+ struct semid_ds32 *usp32 = (struct semid_ds32 *) A(pad);
+
+ if (!access_ok(VERIFY_WRITE, usp32, sizeof(*usp32))) {
+ err = -EFAULT;
+ break;
+ }
+ err2 = __put_user(s.sem_perm.key, &usp32->sem_perm.key);
+ err2 |= __put_user(s.sem_perm.uid, &usp32->sem_perm.uid);
+ err2 |= __put_user(s.sem_perm.gid, &usp32->sem_perm.gid);
+ err2 |= __put_user(s.sem_perm.cuid, &usp32->sem_perm.cuid);
+ err2 |= __put_user(s.sem_perm.cgid, &usp32->sem_perm.cgid);
+ err2 |= __put_user(s.sem_perm.mode, &usp32->sem_perm.mode);
+ err2 |= __put_user(s.sem_perm.seq, &usp32->sem_perm.seq);
+ err2 |= __put_user(s.sem_otime, &usp32->sem_otime);
+ err2 |= __put_user(s.sem_ctime, &usp32->sem_ctime);
+ err2 |= __put_user(s.sem_nsems, &usp32->sem_nsems);
+ }
+ if (err2)
+ err = -EFAULT;
+ break;
+
+ default:
+ err = - EINVAL;
+ break;
+ }
+
+ return err;
+}
+
+static int
+do_sys32_msgsnd (int first, int second, int third, void *uptr)
+{
+ struct msgbuf32 *up = (struct msgbuf32 *)uptr;
+ struct msgbuf *p;
+ mm_segment_t old_fs;
+ int err;
+
+ if (second < 0)
+ return -EINVAL;
+ p = kmalloc (second + sizeof (struct msgbuf)
+ + 4, GFP_USER);
+ if (!p)
+ return -ENOMEM;
+ err = get_user (p->mtype, &up->mtype);
+ if (err)
+ goto out;
+ err |= __copy_from_user (p->mtext, &up->mtext, second);
+ if (err)
+ goto out;
+ old_fs = get_fs ();
+ set_fs (KERNEL_DS);
+ err = sys_msgsnd (first, p, second, third);
+ set_fs (old_fs);
+out:
+ kfree (p);
+
+ return err;
+}
+
+static int
+do_sys32_msgrcv (int first, int second, int msgtyp, int third,
+ int version, void *uptr)
+{
+ struct msgbuf32 *up;
+ struct msgbuf *p;
+ mm_segment_t old_fs;
+ int err;
+
+ if (!version) {
+ struct ipc_kludge32 *uipck = (struct ipc_kludge32 *)uptr;
+ struct ipc_kludge32 ipck;
+
+ err = -EINVAL;
+ if (!uptr)
+ goto out;
+ err = -EFAULT;
+ if (copy_from_user (&ipck, uipck, sizeof (struct ipc_kludge32)))
+ goto out;
+ uptr = (void *)AA(ipck.msgp);
+ msgtyp = ipck.msgtyp;
+ }
+
+ if (second < 0)
+ return -EINVAL;
+ err = -ENOMEM;
+ p = kmalloc (second + sizeof (struct msgbuf) + 4, GFP_USER);
+ if (!p)
+ goto out;
+ old_fs = get_fs ();
+ set_fs (KERNEL_DS);
+ err = sys_msgrcv (first, p, second + 4, msgtyp, third);
+ set_fs (old_fs);
+ if (err < 0)
+ goto free_then_out;
+ up = (struct msgbuf32 *)uptr;
+ if (put_user (p->mtype, &up->mtype) ||
+ __copy_to_user (&up->mtext, p->mtext, err))
+ err = -EFAULT;
+free_then_out:
+ kfree (p);
+out:
+ return err;
+}
+
+static int
+do_sys32_msgctl (int first, int second, void *uptr)
+{
+ int err = -EINVAL, err2;
+ struct msqid64_ds m;
+ struct msqid_ds32 *up32 = (struct msqid_ds32 *)uptr;
+ struct msqid64_ds32 *up64 = (struct msqid64_ds32 *)uptr;
+ mm_segment_t old_fs;
+
+ switch (second & ~IPC_64) {
+ case IPC_INFO:
+ case IPC_RMID:
+ case MSG_INFO:
+ err = sys_msgctl (first, second, (struct msqid_ds *)uptr);
+ break;
+
+ case IPC_SET:
+ if (second & IPC_64) {
+ if (!access_ok(VERIFY_READ, up64, sizeof(*up64))) {
+ err = -EFAULT;
+ break;
+ }
+ err = __get_user(m.msg_perm.uid, &up64->msg_perm.uid);
+ err |= __get_user(m.msg_perm.gid, &up64->msg_perm.gid);
+ err |= __get_user(m.msg_perm.mode, &up64->msg_perm.mode);
+ err |= __get_user(m.msg_qbytes, &up64->msg_qbytes);
+ } else {
+ if (!access_ok(VERIFY_READ, up32, sizeof(*up32))) {
+ err = -EFAULT;
+ break;
+ }
+ err = __get_user(m.msg_perm.uid, &up32->msg_perm.uid);
+ err |= __get_user(m.msg_perm.gid, &up32->msg_perm.gid);
+ err |= __get_user(m.msg_perm.mode, &up32->msg_perm.mode);
+ err |= __get_user(m.msg_qbytes, &up32->msg_qbytes);
+ }
+ if (err)
+ break;
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+ err = sys_msgctl(first, second | IPC_64, (struct msqid_ds *)&m);
+ set_fs(old_fs);
+ break;
+
+ case IPC_STAT:
+ case MSG_STAT:
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+ err = sys_msgctl(first, second | IPC_64, (struct msqid_ds *)&m);
+ set_fs(old_fs);
+ if (second & IPC_64) {
+ if (!access_ok(VERIFY_WRITE, up64, sizeof(*up64))) {
+ err = -EFAULT;
+ break;
+ }
+ err2 = __put_user(m.msg_perm.key, &up64->msg_perm.key);
+ err2 |= __put_user(m.msg_perm.uid, &up64->msg_perm.uid);
+ err2 |= __put_user(m.msg_perm.gid, &up64->msg_perm.gid);
+ err2 |= __put_user(m.msg_perm.cuid, &up64->msg_perm.cuid);
+ err2 |= __put_user(m.msg_perm.cgid, &up64->msg_perm.cgid);
+ err2 |= __put_user(m.msg_perm.mode, &up64->msg_perm.mode);
+ err2 |= __put_user(m.msg_perm.seq, &up64->msg_perm.seq);
+ err2 |= __put_user(m.msg_stime, &up64->msg_stime);
+ err2 |= __put_user(m.msg_rtime, &up64->msg_rtime);
+ err2 |= __put_user(m.msg_ctime, &up64->msg_ctime);
+ err2 |= __put_user(m.msg_cbytes, &up64->msg_cbytes);
+ err2 |= __put_user(m.msg_qnum, &up64->msg_qnum);
+ err2 |= __put_user(m.msg_qbytes, &up64->msg_qbytes);
+ err2 |= __put_user(m.msg_lspid, &up64->msg_lspid);
+ err2 |= __put_user(m.msg_lrpid, &up64->msg_lrpid);
+ if (err2)
+ err = -EFAULT;
+ } else {
+ if (!access_ok(VERIFY_WRITE, up32, sizeof(*up32))) {
+ err = -EFAULT;
+ break;
+ }
+ err2 = __put_user(m.msg_perm.key, &up32->msg_perm.key);
+ err2 |= __put_user(m.msg_perm.uid, &up32->msg_perm.uid);
+ err2 |= __put_user(m.msg_perm.gid, &up32->msg_perm.gid);
+ err2 |= __put_user(m.msg_perm.cuid, &up32->msg_perm.cuid);
+ err2 |= __put_user(m.msg_perm.cgid, &up32->msg_perm.cgid);
+ err2 |= __put_user(m.msg_perm.mode, &up32->msg_perm.mode);
+ err2 |= __put_user(m.msg_perm.seq, &up32->msg_perm.seq);
+ err2 |= __put_user(m.msg_stime, &up32->msg_stime);
+ err2 |= __put_user(m.msg_rtime, &up32->msg_rtime);
+ err2 |= __put_user(m.msg_ctime, &up32->msg_ctime);
+ err2 |= __put_user(m.msg_cbytes, &up32->msg_cbytes);
+ err2 |= __put_user(m.msg_qnum, &up32->msg_qnum);
+ err2 |= __put_user(m.msg_qbytes, &up32->msg_qbytes);
+ err2 |= __put_user(m.msg_lspid, &up32->msg_lspid);
+ err2 |= __put_user(m.msg_lrpid, &up32->msg_lrpid);
+ if (err2)
+ err = -EFAULT;
+ }
+ break;
+ }
+
+ return err;
+}
+
+static int
+do_sys32_shmat (int first, int second, int third, int version, void *uptr)
+{
+ unsigned long raddr;
+ u32 *uaddr = (u32 *)A((u32)third);
+ int err = -EINVAL;
+
+ if (version == 1)
+ return err;
+ err = do_shmat (first, uptr, second, &raddr);
+ if (err)
+ return err;
+ err = put_user (raddr, uaddr);
+ return err;
+}
+
+struct shm_info32 {
+ int used_ids;
+ u32 shm_tot, shm_rss, shm_swp;
+ u32 swap_attempts, swap_successes;
+};
+
+static int
+do_sys32_shmctl (int first, int second, void *uptr)
+{
+ struct shmid64_ds32 *up64 = (struct shmid64_ds32 *)uptr;
+ struct shmid_ds32 *up32 = (struct shmid_ds32 *)uptr;
+ struct shm_info32 *uip = (struct shm_info32 *)uptr;
+ int err = -EFAULT, err2;
+ struct shmid64_ds s64;
+ mm_segment_t old_fs;
+ struct shm_info si;
+ struct shmid_ds s;
+
+ switch (second & ~IPC_64) {
+ case IPC_INFO:
+ second = IPC_INFO; /* So that we don't have to translate it */
+ case IPC_RMID:
+ case SHM_LOCK:
+ case SHM_UNLOCK:
+ err = sys_shmctl(first, second, (struct shmid_ds *)uptr);
+ break;
+ case IPC_SET:
+ if (second & IPC_64) {
+ err = get_user(s.shm_perm.uid, &up64->shm_perm.uid);
+ err |= get_user(s.shm_perm.gid, &up64->shm_perm.gid);
+ err |= get_user(s.shm_perm.mode, &up64->shm_perm.mode);
+ } else {
+ err = get_user(s.shm_perm.uid, &up32->shm_perm.uid);
+ err |= get_user(s.shm_perm.gid, &up32->shm_perm.gid);
+ err |= get_user(s.shm_perm.mode, &up32->shm_perm.mode);
+ }
+ if (err)
+ break;
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+ err = sys_shmctl(first, second & ~IPC_64, &s);
+ set_fs(old_fs);
+ break;
+
+ case IPC_STAT:
+ case SHM_STAT:
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+ err = sys_shmctl(first, second | IPC_64, (void *) &s64);
+ set_fs(old_fs);
+ if (err < 0)
+ break;
+ if (second & IPC_64) {
+ if (!access_ok(VERIFY_WRITE, up64, sizeof(*up64))) {
+ err = -EFAULT;
+ break;
+ }
+ err2 = __put_user(s64.shm_perm.key, &up64->shm_perm.key);
+ err2 |= __put_user(s64.shm_perm.uid, &up64->shm_perm.uid);
+ err2 |= __put_user(s64.shm_perm.gid, &up64->shm_perm.gid);
+ err2 |= __put_user(s64.shm_perm.cuid, &up64->shm_perm.cuid);
+ err2 |= __put_user(s64.shm_perm.cgid, &up64->shm_perm.cgid);
+ err2 |= __put_user(s64.shm_perm.mode, &up64->shm_perm.mode);
+ err2 |= __put_user(s64.shm_perm.seq, &up64->shm_perm.seq);
+ err2 |= __put_user(s64.shm_atime, &up64->shm_atime);
+ err2 |= __put_user(s64.shm_dtime, &up64->shm_dtime);
+ err2 |= __put_user(s64.shm_ctime, &up64->shm_ctime);
+ err2 |= __put_user(s64.shm_segsz, &up64->shm_segsz);
+ err2 |= __put_user(s64.shm_nattch, &up64->shm_nattch);
+ err2 |= __put_user(s64.shm_cpid, &up64->shm_cpid);
+ err2 |= __put_user(s64.shm_lpid, &up64->shm_lpid);
+ } else {
+ if (!access_ok(VERIFY_WRITE, up32, sizeof(*up32))) {
+ err = -EFAULT;
+ break;
+ }
+ err2 = __put_user(s64.shm_perm.key, &up32->shm_perm.key);
+ err2 |= __put_user(s64.shm_perm.uid, &up32->shm_perm.uid);
+ err2 |= __put_user(s64.shm_perm.gid, &up32->shm_perm.gid);
+ err2 |= __put_user(s64.shm_perm.cuid, &up32->shm_perm.cuid);
+ err2 |= __put_user(s64.shm_perm.cgid, &up32->shm_perm.cgid);
+ err2 |= __put_user(s64.shm_perm.mode, &up32->shm_perm.mode);
+ err2 |= __put_user(s64.shm_perm.seq, &up32->shm_perm.seq);
+ err2 |= __put_user(s64.shm_atime, &up32->shm_atime);
+ err2 |= __put_user(s64.shm_dtime, &up32->shm_dtime);
+ err2 |= __put_user(s64.shm_ctime, &up32->shm_ctime);
+ err2 |= __put_user(s64.shm_segsz, &up32->shm_segsz);
+ err2 |= __put_user(s64.shm_nattch, &up32->shm_nattch);
+ err2 |= __put_user(s64.shm_cpid, &up32->shm_cpid);
+ err2 |= __put_user(s64.shm_lpid, &up32->shm_lpid);
+ }
+ if (err2)
+ err = -EFAULT;
+ break;
+
+ case SHM_INFO:
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+ err = sys_shmctl(first, second, (void *)&si);
+ set_fs(old_fs);
+ if (err < 0)
+ break;
+ err2 = put_user(si.used_ids, &uip->used_ids);
+ err2 |= __put_user(si.shm_tot, &uip->shm_tot);
+ err2 |= __put_user(si.shm_rss, &uip->shm_rss);
+ err2 |= __put_user(si.shm_swp, &uip->shm_swp);
+ err2 |= __put_user(si.swap_attempts, &uip->swap_attempts);
+ err2 |= __put_user (si.swap_successes, &uip->swap_successes);
+ if (err2)
+ err = -EFAULT;
+ break;
+
+ default:
+ err = -EINVAL;
+ break;
+ }
+
+ return err;
+}
+
+static int sys32_semtimedop(int semid, struct sembuf *tsems, int nsems,
+ const struct compat_timespec *timeout32)
+{
+ struct compat_timespec t32;
+ struct timespec *t64 = compat_alloc_user_space(sizeof(*t64));
+
+ if (copy_from_user(&t32, timeout32, sizeof(t32)))
+ return -EFAULT;
+
+ if (put_user(t32.tv_sec, &t64->tv_sec) ||
+ put_user(t32.tv_nsec, &t64->tv_nsec))
+ return -EFAULT;
+
+ return sys_semtimedop(semid, tsems, nsems, t64);
+}
+
+asmlinkage long
+sys32_ipc (u32 call, int first, int second, int third, u32 ptr, u32 fifth)
+{
+ int version, err;
+
+ version = call >> 16; /* hack for backward compatibility */
+ call &= 0xffff;
+
+ switch (call) {
+ case SEMOP:
+ /* struct sembuf is the same on 32 and 64bit :)) */
+ err = sys_semtimedop (first, (struct sembuf *)AA(ptr), second,
+ NULL);
+ break;
+ case SEMTIMEDOP:
+ err = sys32_semtimedop (first, (struct sembuf *)AA(ptr), second,
+ (const struct compat_timespec __user *)AA(fifth));
+ break;
+ case SEMGET:
+ err = sys_semget (first, second, third);
+ break;
+ case SEMCTL:
+ err = do_sys32_semctl (first, second, third,
+ (void *)AA(ptr));
+ break;
+
+ case MSGSND:
+ err = do_sys32_msgsnd (first, second, third,
+ (void *)AA(ptr));
+ break;
+ case MSGRCV:
+ err = do_sys32_msgrcv (first, second, fifth, third,
+ version, (void *)AA(ptr));
+ break;
+ case MSGGET:
+ err = sys_msgget ((key_t) first, second);
+ break;
+ case MSGCTL:
+ err = do_sys32_msgctl (first, second, (void *)AA(ptr));
+ break;
+
+ case SHMAT:
+ err = do_sys32_shmat (first, second, third,
+ version, (void *)AA(ptr));
+ break;
+ case SHMDT:
+ err = sys_shmdt ((char *)A(ptr));
+ break;
+ case SHMGET:
+ err = sys_shmget (first, (unsigned)second, third);
+ break;
+ case SHMCTL:
+ err = do_sys32_shmctl (first, second, (void *)AA(ptr));
+ break;
+ default:
+ err = -EINVAL;
+ break;
+ }
+
+ return err;
+}
+
+asmlinkage long sys32_shmat(int shmid, char __user *shmaddr,
+ int shmflg, int32_t *addr)
+{
+ unsigned long raddr;
+ int err;
+
+ err = do_shmat(shmid, shmaddr, shmflg, &raddr);
+ if (err)
+ return err;
+
+ return put_user(raddr, addr);
+}
+
+struct sysctl_args32
+{
+ compat_caddr_t name;
+ int nlen;
+ compat_caddr_t oldval;
+ compat_caddr_t oldlenp;
+ compat_caddr_t newval;
+ compat_size_t newlen;
+ unsigned int __unused[4];
+};
+
+#ifdef CONFIG_SYSCTL
+
+asmlinkage long sys32_sysctl(struct sysctl_args32 *args)
+{
+ struct sysctl_args32 tmp;
+ int error;
+ size_t oldlen, *oldlenp = NULL;
+ unsigned long addr = (((long)&args->__unused[0]) + 7) & ~7;
+
+ if (copy_from_user(&tmp, args, sizeof(tmp)))
+ return -EFAULT;
+
+ if (tmp.oldval && tmp.oldlenp) {
+ /* Duh, this is ugly and might not work if sysctl_args
+ is in read-only memory, but do_sysctl does indirectly
+ a lot of uaccess in both directions and we'd have to
+ basically copy the whole sysctl.c here, and
+ glibc's __sysctl uses rw memory for the structure
+ anyway. */
+ if (get_user(oldlen, (u32 *)A(tmp.oldlenp)) ||
+ put_user(oldlen, (size_t *)addr))
+ return -EFAULT;
+ oldlenp = (size_t *)addr;
+ }
+
+ lock_kernel();
+ error = do_sysctl((int *)A(tmp.name), tmp.nlen, (void *)A(tmp.oldval),
+ oldlenp, (void *)A(tmp.newval), tmp.newlen);
+ unlock_kernel();
+ if (oldlenp) {
+ if (!error) {
+ if (get_user(oldlen, (size_t *)addr) ||
+ put_user(oldlen, (u32 *)A(tmp.oldlenp)))
+ error = -EFAULT;
+ }
+ copy_to_user(args->__unused, tmp.__unused, sizeof(tmp.__unused));
+ }
+ return error;
+}
+
+#endif /* CONFIG_SYSCTL */
+
+asmlinkage long sys32_newuname(struct new_utsname * name)
+{
+ int ret = 0;
+
+ down_read(&uts_sem);
+ if (copy_to_user(name,&system_utsname,sizeof *name))
+ ret = -EFAULT;
+ up_read(&uts_sem);
+
+ if (current->personality == PER_LINUX32 && !ret)
+ if (copy_to_user(name->machine, "mips\0\0\0", 8))
+ ret = -EFAULT;
+
+ return ret;
+}
+
+asmlinkage int sys32_personality(unsigned long personality)
+{
+ int ret;
+ if (current->personality == PER_LINUX32 && personality == PER_LINUX)
+ personality = PER_LINUX32;
+ ret = sys_personality(personality);
+ if (ret == PER_LINUX32)
+ ret = PER_LINUX;
+ return ret;
+}
+
+/* ustat compatibility */
+struct ustat32 {
+ compat_daddr_t f_tfree;
+ compat_ino_t f_tinode;
+ char f_fname[6];
+ char f_fpack[6];
+};
+
+extern asmlinkage long sys_ustat(dev_t dev, struct ustat * ubuf);
+
+asmlinkage int sys32_ustat(dev_t dev, struct ustat32 * ubuf32)
+{
+ int err;
+ struct ustat tmp;
+ struct ustat32 tmp32;
+ mm_segment_t old_fs = get_fs();
+
+ set_fs(KERNEL_DS);
+ err = sys_ustat(dev, &tmp);
+ set_fs (old_fs);
+
+ if (err)
+ goto out;
+
+ memset(&tmp32,0,sizeof(struct ustat32));
+ tmp32.f_tfree = tmp.f_tfree;
+ tmp32.f_tinode = tmp.f_tinode;
+
+ err = copy_to_user(ubuf32,&tmp32,sizeof(struct ustat32)) ? -EFAULT : 0;
+
+out:
+ return err;
+}
+
+/* Handle adjtimex compatibility. */
+
+struct timex32 {
+ u32 modes;
+ s32 offset, freq, maxerror, esterror;
+ s32 status, constant, precision, tolerance;
+ struct compat_timeval time;
+ s32 tick;
+ s32 ppsfreq, jitter, shift, stabil;
+ s32 jitcnt, calcnt, errcnt, stbcnt;
+ s32 :32; s32 :32; s32 :32; s32 :32;
+ s32 :32; s32 :32; s32 :32; s32 :32;
+ s32 :32; s32 :32; s32 :32; s32 :32;
+};
+
+extern int do_adjtimex(struct timex *);
+
+asmlinkage int sys32_adjtimex(struct timex32 *utp)
+{
+ struct timex txc;
+ int ret;
+
+ memset(&txc, 0, sizeof(struct timex));
+
+ if (get_user(txc.modes, &utp->modes) ||
+ __get_user(txc.offset, &utp->offset) ||
+ __get_user(txc.freq, &utp->freq) ||
+ __get_user(txc.maxerror, &utp->maxerror) ||
+ __get_user(txc.esterror, &utp->esterror) ||
+ __get_user(txc.status, &utp->status) ||
+ __get_user(txc.constant, &utp->constant) ||
+ __get_user(txc.precision, &utp->precision) ||
+ __get_user(txc.tolerance, &utp->tolerance) ||
+ __get_user(txc.time.tv_sec, &utp->time.tv_sec) ||
+ __get_user(txc.time.tv_usec, &utp->time.tv_usec) ||
+ __get_user(txc.tick, &utp->tick) ||
+ __get_user(txc.ppsfreq, &utp->ppsfreq) ||
+ __get_user(txc.jitter, &utp->jitter) ||
+ __get_user(txc.shift, &utp->shift) ||
+ __get_user(txc.stabil, &utp->stabil) ||
+ __get_user(txc.jitcnt, &utp->jitcnt) ||
+ __get_user(txc.calcnt, &utp->calcnt) ||
+ __get_user(txc.errcnt, &utp->errcnt) ||
+ __get_user(txc.stbcnt, &utp->stbcnt))
+ return -EFAULT;
+
+ ret = do_adjtimex(&txc);
+
+ if (put_user(txc.modes, &utp->modes) ||
+ __put_user(txc.offset, &utp->offset) ||
+ __put_user(txc.freq, &utp->freq) ||
+ __put_user(txc.maxerror, &utp->maxerror) ||
+ __put_user(txc.esterror, &utp->esterror) ||
+ __put_user(txc.status, &utp->status) ||
+ __put_user(txc.constant, &utp->constant) ||
+ __put_user(txc.precision, &utp->precision) ||
+ __put_user(txc.tolerance, &utp->tolerance) ||
+ __put_user(txc.time.tv_sec, &utp->time.tv_sec) ||
+ __put_user(txc.time.tv_usec, &utp->time.tv_usec) ||
+ __put_user(txc.tick, &utp->tick) ||
+ __put_user(txc.ppsfreq, &utp->ppsfreq) ||
+ __put_user(txc.jitter, &utp->jitter) ||
+ __put_user(txc.shift, &utp->shift) ||
+ __put_user(txc.stabil, &utp->stabil) ||
+ __put_user(txc.jitcnt, &utp->jitcnt) ||
+ __put_user(txc.calcnt, &utp->calcnt) ||
+ __put_user(txc.errcnt, &utp->errcnt) ||
+ __put_user(txc.stbcnt, &utp->stbcnt))
+ ret = -EFAULT;
+
+ return ret;
+}
+
+asmlinkage int sys32_sendfile(int out_fd, int in_fd, compat_off_t *offset,
+ s32 count)
+{
+ mm_segment_t old_fs = get_fs();
+ int ret;
+ off_t of;
+
+ if (offset && get_user(of, offset))
+ return -EFAULT;
+
+ set_fs(KERNEL_DS);
+ ret = sys_sendfile(out_fd, in_fd, offset ? &of : NULL, count);
+ set_fs(old_fs);
+
+ if (offset && put_user(of, offset))
+ return -EFAULT;
+
+ return ret;
+}
+
+asmlinkage ssize_t sys32_readahead(int fd, u32 pad0, u64 a2, u64 a3,
+ size_t count)
+{
+ return sys_readahead(fd, merge_64(a2, a3), count);
+}
+
+/* Argument list sizes for sys_socketcall */
+#define AL(x) ((x) * sizeof(unsigned int))
+static unsigned char socketcall_nargs[18]={AL(0),AL(3),AL(3),AL(3),AL(2),AL(3),
+ AL(3),AL(3),AL(4),AL(4),AL(4),AL(6),
+ AL(6),AL(2),AL(5),AL(5),AL(3),AL(3)};
+#undef AL
+
+/*
+ * System call vectors.
+ *
+ * Argument checking cleaned up. Saved 20% in size.
+ * This function doesn't need to set the kernel lock because
+ * it is set by the callees.
+ */
+
+asmlinkage long sys32_socketcall(int call, unsigned int *args32)
+{
+ unsigned int a[6];
+ unsigned int a0,a1;
+ int err;
+
+ extern asmlinkage long sys_socket(int family, int type, int protocol);
+ extern asmlinkage long sys_bind(int fd, struct sockaddr __user *umyaddr, int addrlen);
+ extern asmlinkage long sys_connect(int fd, struct sockaddr __user *uservaddr, int addrlen);
+ extern asmlinkage long sys_listen(int fd, int backlog);
+ extern asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr, int __user *upeer_addrlen);
+ extern asmlinkage long sys_getsockname(int fd, struct sockaddr __user *usockaddr, int __user *usockaddr_len);
+ extern asmlinkage long sys_getpeername(int fd, struct sockaddr __user *usockaddr, int __user *usockaddr_len);
+ extern asmlinkage long sys_socketpair(int family, int type, int protocol, int __user *usockvec);
+ extern asmlinkage long sys_send(int fd, void __user * buff, size_t len, unsigned flags);
+ extern asmlinkage long sys_sendto(int fd, void __user * buff, size_t len, unsigned flags,
+ struct sockaddr __user *addr, int addr_len);
+ extern asmlinkage long sys_recv(int fd, void __user * ubuf, size_t size, unsigned flags);
+ extern asmlinkage long sys_recvfrom(int fd, void __user * ubuf, size_t size, unsigned flags,
+ struct sockaddr __user *addr, int __user *addr_len);
+ extern asmlinkage long sys_shutdown(int fd, int how);
+ extern asmlinkage long sys_setsockopt(int fd, int level, int optname, char __user *optval, int optlen);
+ extern asmlinkage long sys_getsockopt(int fd, int level, int optname, char __user *optval, int *optlen);
+ extern asmlinkage long sys_sendmsg(int fd, struct msghdr __user *msg, unsigned flags);
+ extern asmlinkage long sys_recvmsg(int fd, struct msghdr __user *msg, unsigned int flags);
+
+
+ if(call<1||call>SYS_RECVMSG)
+ return -EINVAL;
+
+ /* copy_from_user should be SMP safe. */
+ if (copy_from_user(a, args32, socketcall_nargs[call]))
+ return -EFAULT;
+
+ a0=a[0];
+ a1=a[1];
+
+ switch(call)
+ {
+ case SYS_SOCKET:
+ err = sys_socket(a0,a1,a[2]);
+ break;
+ case SYS_BIND:
+ err = sys_bind(a0,(struct sockaddr __user *)A(a1), a[2]);
+ break;
+ case SYS_CONNECT:
+ err = sys_connect(a0, (struct sockaddr __user *)A(a1), a[2]);
+ break;
+ case SYS_LISTEN:
+ err = sys_listen(a0,a1);
+ break;
+ case SYS_ACCEPT:
+ err = sys_accept(a0,(struct sockaddr __user *)A(a1), (int __user *)A(a[2]));
+ break;
+ case SYS_GETSOCKNAME:
+ err = sys_getsockname(a0,(struct sockaddr __user *)A(a1), (int __user *)A(a[2]));
+ break;
+ case SYS_GETPEERNAME:
+ err = sys_getpeername(a0, (struct sockaddr __user *)A(a1), (int __user *)A(a[2]));
+ break;
+ case SYS_SOCKETPAIR:
+ err = sys_socketpair(a0,a1, a[2], (int __user *)A(a[3]));
+ break;
+ case SYS_SEND:
+ err = sys_send(a0, (void __user *)A(a1), a[2], a[3]);
+ break;
+ case SYS_SENDTO:
+ err = sys_sendto(a0,(void __user *)A(a1), a[2], a[3],
+ (struct sockaddr __user *)A(a[4]), a[5]);
+ break;
+ case SYS_RECV:
+ err = sys_recv(a0, (void __user *)A(a1), a[2], a[3]);
+ break;
+ case SYS_RECVFROM:
+ err = sys_recvfrom(a0, (void __user *)A(a1), a[2], a[3],
+ (struct sockaddr __user *)A(a[4]), (int __user *)A(a[5]));
+ break;
+ case SYS_SHUTDOWN:
+ err = sys_shutdown(a0,a1);
+ break;
+ case SYS_SETSOCKOPT:
+ err = sys_setsockopt(a0, a1, a[2], (char __user *)A(a[3]), a[4]);
+ break;
+ case SYS_GETSOCKOPT:
+ err = sys_getsockopt(a0, a1, a[2], (char __user *)A(a[3]), (int __user *)A(a[4]));
+ break;
+ case SYS_SENDMSG:
+ err = sys_sendmsg(a0, (struct msghdr __user *) A(a1), a[2]);
+ break;
+ case SYS_RECVMSG:
+ err = sys_recvmsg(a0, (struct msghdr __user *) A(a1), a[2]);
+ break;
+ default:
+ err = -EINVAL;
+ break;
+ }
+ return err;
+}
diff --git a/arch/mips/kernel/mips_ksyms.c b/arch/mips/kernel/mips_ksyms.c
new file mode 100644
index 0000000..eed29fc
--- /dev/null
+++ b/arch/mips/kernel/mips_ksyms.c
@@ -0,0 +1,67 @@
+/*
+ * Export MIPS-specific functions needed for loadable modules.
+ *
+ * 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) 1996, 97, 98, 99, 2000, 01, 03, 04, 05 by Ralf Baechle
+ * Copyright (C) 1999, 2000, 01 Silicon Graphics, Inc.
+ */
+#include <linux/config.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <asm/checksum.h>
+#include <asm/pgtable.h>
+#include <asm/uaccess.h>
+
+extern void *__bzero(void *__s, size_t __count);
+extern long __strncpy_from_user_nocheck_asm(char *__to,
+ const char *__from, long __len);
+extern long __strncpy_from_user_asm(char *__to, const char *__from,
+ long __len);
+extern long __strlen_user_nocheck_asm(const char *s);
+extern long __strlen_user_asm(const char *s);
+extern long __strnlen_user_nocheck_asm(const char *s);
+extern long __strnlen_user_asm(const char *s);
+
+/*
+ * String functions
+ */
+EXPORT_SYMBOL(memchr);
+EXPORT_SYMBOL(memcmp);
+EXPORT_SYMBOL(memset);
+EXPORT_SYMBOL(memcpy);
+EXPORT_SYMBOL(memmove);
+EXPORT_SYMBOL(strcat);
+EXPORT_SYMBOL(strchr);
+#ifdef CONFIG_MIPS64
+EXPORT_SYMBOL(strncmp);
+#endif
+EXPORT_SYMBOL(strlen);
+EXPORT_SYMBOL(strpbrk);
+EXPORT_SYMBOL(strncat);
+EXPORT_SYMBOL(strnlen);
+EXPORT_SYMBOL(strrchr);
+EXPORT_SYMBOL(strstr);
+
+EXPORT_SYMBOL(kernel_thread);
+
+/*
+ * Userspace access stuff.
+ */
+EXPORT_SYMBOL(__copy_user);
+EXPORT_SYMBOL(__bzero);
+EXPORT_SYMBOL(__strncpy_from_user_nocheck_asm);
+EXPORT_SYMBOL(__strncpy_from_user_asm);
+EXPORT_SYMBOL(__strlen_user_nocheck_asm);
+EXPORT_SYMBOL(__strlen_user_asm);
+EXPORT_SYMBOL(__strnlen_user_nocheck_asm);
+EXPORT_SYMBOL(__strnlen_user_asm);
+
+EXPORT_SYMBOL(csum_partial);
+
+EXPORT_SYMBOL(invalid_pte_table);
+#ifdef CONFIG_GENERIC_IRQ_PROBE
+EXPORT_SYMBOL(probe_irq_mask);
+#endif
diff --git a/arch/mips/kernel/module-elf32.c b/arch/mips/kernel/module-elf32.c
new file mode 100644
index 0000000..ffd216d
--- /dev/null
+++ b/arch/mips/kernel/module-elf32.c
@@ -0,0 +1,250 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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
+ *
+ * Copyright (C) 2001 Rusty Russell.
+ * Copyright (C) 2003, 2004 Ralf Baechle (ralf@linux-mips.org)
+ */
+
+#undef DEBUG
+
+#include <linux/moduleloader.h>
+#include <linux/elf.h>
+#include <linux/vmalloc.h>
+#include <linux/slab.h>
+#include <linux/fs.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+
+struct mips_hi16 {
+ struct mips_hi16 *next;
+ Elf32_Addr *addr;
+ Elf32_Addr value;
+};
+
+static struct mips_hi16 *mips_hi16_list;
+
+void *module_alloc(unsigned long size)
+{
+ if (size == 0)
+ return NULL;
+ return vmalloc(size);
+}
+
+
+/* Free memory returned from module_alloc */
+void module_free(struct module *mod, void *module_region)
+{
+ vfree(module_region);
+ /* FIXME: If module_region == mod->init_region, trim exception
+ table entries. */
+}
+
+int module_frob_arch_sections(Elf_Ehdr *hdr,
+ Elf_Shdr *sechdrs,
+ char *secstrings,
+ struct module *mod)
+{
+ return 0;
+}
+
+static int apply_r_mips_none(struct module *me, uint32_t *location,
+ Elf32_Addr v)
+{
+ return 0;
+}
+
+static int apply_r_mips_32(struct module *me, uint32_t *location,
+ Elf32_Addr v)
+{
+ *location += v;
+
+ return 0;
+}
+
+static int apply_r_mips_26(struct module *me, uint32_t *location,
+ Elf32_Addr v)
+{
+ if (v % 4) {
+ printk(KERN_ERR "module %s: dangerous relocation\n", me->name);
+ return -ENOEXEC;
+ }
+
+ if ((v & 0xf0000000) != (((unsigned long)location + 4) & 0xf0000000)) {
+ printk(KERN_ERR
+ "module %s: relocation overflow\n",
+ me->name);
+ return -ENOEXEC;
+ }
+
+ *location = (*location & ~0x03ffffff) |
+ ((*location + (v >> 2)) & 0x03ffffff);
+
+ return 0;
+}
+
+static int apply_r_mips_hi16(struct module *me, uint32_t *location,
+ Elf32_Addr v)
+{
+ struct mips_hi16 *n;
+
+ /*
+ * We cannot relocate this one now because we don't know the value of
+ * the carry we need to add. Save the information, and let LO16 do the
+ * actual relocation.
+ */
+ n = kmalloc(sizeof *n, GFP_KERNEL);
+ if (!n)
+ return -ENOMEM;
+
+ n->addr = location;
+ n->value = v;
+ n->next = mips_hi16_list;
+ mips_hi16_list = n;
+
+ return 0;
+}
+
+static int apply_r_mips_lo16(struct module *me, uint32_t *location,
+ Elf32_Addr v)
+{
+ unsigned long insnlo = *location;
+ Elf32_Addr val, vallo;
+
+ /* Sign extend the addend we extract from the lo insn. */
+ vallo = ((insnlo & 0xffff) ^ 0x8000) - 0x8000;
+
+ if (mips_hi16_list != NULL) {
+ struct mips_hi16 *l;
+
+ l = mips_hi16_list;
+ while (l != NULL) {
+ struct mips_hi16 *next;
+ unsigned long insn;
+
+ /*
+ * The value for the HI16 had best be the same.
+ */
+ if (v != l->value)
+ goto out_danger;
+
+ /*
+ * Do the HI16 relocation. Note that we actually don't
+ * need to know anything about the LO16 itself, except
+ * where to find the low 16 bits of the addend needed
+ * by the LO16.
+ */
+ insn = *l->addr;
+ val = ((insn & 0xffff) << 16) + vallo;
+ val += v;
+
+ /*
+ * Account for the sign extension that will happen in
+ * the low bits.
+ */
+ val = ((val >> 16) + ((val & 0x8000) != 0)) & 0xffff;
+
+ insn = (insn & ~0xffff) | val;
+ *l->addr = insn;
+
+ next = l->next;
+ kfree(l);
+ l = next;
+ }
+
+ mips_hi16_list = NULL;
+ }
+
+ /*
+ * Ok, we're done with the HI16 relocs. Now deal with the LO16.
+ */
+ val = v + vallo;
+ insnlo = (insnlo & ~0xffff) | (val & 0xffff);
+ *location = insnlo;
+
+ return 0;
+
+out_danger:
+ printk(KERN_ERR "module %s: dangerous " "relocation\n", me->name);
+
+ return -ENOEXEC;
+}
+
+static int (*reloc_handlers[]) (struct module *me, uint32_t *location,
+ Elf32_Addr v) = {
+ [R_MIPS_NONE] = apply_r_mips_none,
+ [R_MIPS_32] = apply_r_mips_32,
+ [R_MIPS_26] = apply_r_mips_26,
+ [R_MIPS_HI16] = apply_r_mips_hi16,
+ [R_MIPS_LO16] = apply_r_mips_lo16
+};
+
+int apply_relocate(Elf32_Shdr *sechdrs,
+ const char *strtab,
+ unsigned int symindex,
+ unsigned int relsec,
+ struct module *me)
+{
+ Elf32_Rel *rel = (void *) sechdrs[relsec].sh_addr;
+ Elf32_Sym *sym;
+ uint32_t *location;
+ unsigned int i;
+ Elf32_Addr v;
+ int res;
+
+ pr_debug("Applying relocate section %u to %u\n", relsec,
+ sechdrs[relsec].sh_info);
+
+ for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
+ Elf32_Word r_info = rel[i].r_info;
+
+ /* This is where to make the change */
+ location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
+ + rel[i].r_offset;
+ /* This is the symbol it is referring to */
+ sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
+ + ELF32_R_SYM(r_info);
+ if (!sym->st_value) {
+ printk(KERN_WARNING "%s: Unknown symbol %s\n",
+ me->name, strtab + sym->st_name);
+ return -ENOENT;
+ }
+
+ v = sym->st_value;
+
+ res = reloc_handlers[ELF32_R_TYPE(r_info)](me, location, v);
+ if (res)
+ return res;
+ }
+
+ return 0;
+}
+
+int apply_relocate_add(Elf32_Shdr *sechdrs,
+ const char *strtab,
+ unsigned int symindex,
+ unsigned int relsec,
+ struct module *me)
+{
+ /*
+ * Current binutils always generate .rela relocations. Keep smiling
+ * if it's empty, abort otherwise.
+ */
+ if (!sechdrs[relsec].sh_size)
+ return 0;
+
+ printk(KERN_ERR "module %s: ADD RELOCATION unsupported\n",
+ me->name);
+ return -ENOEXEC;
+}
diff --git a/arch/mips/kernel/module-elf64.c b/arch/mips/kernel/module-elf64.c
new file mode 100644
index 0000000..e804792
--- /dev/null
+++ b/arch/mips/kernel/module-elf64.c
@@ -0,0 +1,274 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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
+ *
+ * Copyright (C) 2001 Rusty Russell.
+ * Copyright (C) 2003, 2004 Ralf Baechle (ralf@linux-mips.org)
+ */
+
+#undef DEBUG
+
+#include <linux/moduleloader.h>
+#include <linux/elf.h>
+#include <linux/vmalloc.h>
+#include <linux/slab.h>
+#include <linux/fs.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+
+struct mips_hi16 {
+ struct mips_hi16 *next;
+ Elf32_Addr *addr;
+ Elf64_Addr value;
+};
+
+static struct mips_hi16 *mips_hi16_list;
+
+void *module_alloc(unsigned long size)
+{
+ if (size == 0)
+ return NULL;
+ return vmalloc(size);
+}
+
+
+/* Free memory returned from module_alloc */
+void module_free(struct module *mod, void *module_region)
+{
+ vfree(module_region);
+ /* FIXME: If module_region == mod->init_region, trim exception
+ table entries. */
+}
+
+int module_frob_arch_sections(Elf_Ehdr *hdr,
+ Elf_Shdr *sechdrs,
+ char *secstrings,
+ struct module *mod)
+{
+ return 0;
+}
+
+int apply_relocate(Elf64_Shdr *sechdrs,
+ const char *strtab,
+ unsigned int symindex,
+ unsigned int relsec,
+ struct module *me)
+{
+ /*
+ * We don't want to deal with REL relocations - RELA is so much saner.
+ */
+ if (!sechdrs[relsec].sh_size)
+ return 0;
+
+ printk(KERN_ERR "module %s: REL relocation unsupported\n",
+ me->name);
+ return -ENOEXEC;
+}
+
+static int apply_r_mips_none(struct module *me, uint32_t *location,
+ Elf64_Addr v)
+{
+ return 0;
+}
+
+static int apply_r_mips_32(struct module *me, uint32_t *location,
+ Elf64_Addr v)
+{
+ *location = v;
+
+ return 0;
+}
+
+static int apply_r_mips_26(struct module *me, uint32_t *location,
+ Elf64_Addr v)
+{
+ if (v % 4) {
+ printk(KERN_ERR "module %s: dangerous relocation\n", me->name);
+ return -ENOEXEC;
+ }
+
+ if ((v & 0xf0000000) != (((unsigned long)location + 4) & 0xf0000000)) {
+ printk(KERN_ERR
+ "module %s: relocation overflow\n",
+ me->name);
+ return -ENOEXEC;
+ }
+
+ *location = (*location & ~0x03ffffff) | ((v >> 2) & 0x03ffffff);
+
+ return 0;
+}
+
+static int apply_r_mips_hi16(struct module *me, uint32_t *location,
+ Elf64_Addr v)
+{
+ struct mips_hi16 *n;
+
+ /*
+ * We cannot relocate this one now because we don't know the value of
+ * the carry we need to add. Save the information, and let LO16 do the
+ * actual relocation.
+ */
+ n = kmalloc(sizeof *n, GFP_KERNEL);
+ if (!n)
+ return -ENOMEM;
+
+ n->addr = location;
+ n->value = v;
+ n->next = mips_hi16_list;
+ mips_hi16_list = n;
+
+ return 0;
+}
+
+static int apply_r_mips_lo16(struct module *me, uint32_t *location,
+ Elf64_Addr v)
+{
+ unsigned long insnlo = *location;
+ Elf32_Addr val, vallo;
+
+ /* Sign extend the addend we extract from the lo insn. */
+ vallo = ((insnlo & 0xffff) ^ 0x8000) - 0x8000;
+
+ if (mips_hi16_list != NULL) {
+ struct mips_hi16 *l;
+
+ l = mips_hi16_list;
+ while (l != NULL) {
+ struct mips_hi16 *next;
+ unsigned long insn;
+
+ /*
+ * The value for the HI16 had best be the same.
+ */
+ if (v != l->value)
+ goto out_danger;
+
+ /*
+ * Do the HI16 relocation. Note that we actually don't
+ * need to know anything about the LO16 itself, except
+ * where to find the low 16 bits of the addend needed
+ * by the LO16.
+ */
+ insn = *l->addr;
+ val = ((insn & 0xffff) << 16) + vallo;
+ val += v;
+
+ /*
+ * Account for the sign extension that will happen in
+ * the low bits.
+ */
+ val = ((val >> 16) + ((val & 0x8000) != 0)) & 0xffff;
+
+ insn = (insn & ~0xffff) | val;
+ *l->addr = insn;
+
+ next = l->next;
+ kfree(l);
+ l = next;
+ }
+
+ mips_hi16_list = NULL;
+ }
+
+ /*
+ * Ok, we're done with the HI16 relocs. Now deal with the LO16.
+ */
+ insnlo = (insnlo & ~0xffff) | (v & 0xffff);
+ *location = insnlo;
+
+ return 0;
+
+out_danger:
+ printk(KERN_ERR "module %s: dangerous " "relocation\n", me->name);
+
+ return -ENOEXEC;
+}
+
+static int apply_r_mips_64(struct module *me, uint32_t *location,
+ Elf64_Addr v)
+{
+ *(uint64_t *) location = v;
+
+ return 0;
+}
+
+
+static int apply_r_mips_higher(struct module *me, uint32_t *location,
+ Elf64_Addr v)
+{
+ *location = (*location & 0xffff0000) |
+ ((((long long) v + 0x80008000LL) >> 32) & 0xffff);
+
+ return 0;
+}
+
+static int apply_r_mips_highest(struct module *me, uint32_t *location,
+ Elf64_Addr v)
+{
+ *location = (*location & 0xffff0000) |
+ ((((long long) v + 0x800080008000LL) >> 48) & 0xffff);
+
+ return 0;
+}
+
+static int (*reloc_handlers[]) (struct module *me, uint32_t *location,
+ Elf64_Addr v) = {
+ [R_MIPS_NONE] = apply_r_mips_none,
+ [R_MIPS_32] = apply_r_mips_32,
+ [R_MIPS_26] = apply_r_mips_26,
+ [R_MIPS_HI16] = apply_r_mips_hi16,
+ [R_MIPS_LO16] = apply_r_mips_lo16,
+ [R_MIPS_64] = apply_r_mips_64,
+ [R_MIPS_HIGHER] = apply_r_mips_higher,
+ [R_MIPS_HIGHEST] = apply_r_mips_highest
+};
+
+int apply_relocate_add(Elf64_Shdr *sechdrs,
+ const char *strtab,
+ unsigned int symindex,
+ unsigned int relsec,
+ struct module *me)
+{
+ Elf64_Mips_Rela *rel = (void *) sechdrs[relsec].sh_addr;
+ Elf64_Sym *sym;
+ uint32_t *location;
+ unsigned int i;
+ Elf64_Addr v;
+ int res;
+
+ pr_debug("Applying relocate section %u to %u\n", relsec,
+ sechdrs[relsec].sh_info);
+
+ for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
+ /* This is where to make the change */
+ location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
+ + rel[i].r_offset;
+ /* This is the symbol it is referring to */
+ sym = (Elf64_Sym *)sechdrs[symindex].sh_addr + rel[i].r_sym;
+ if (!sym->st_value) {
+ printk(KERN_WARNING "%s: Unknown symbol %s\n",
+ me->name, strtab + sym->st_name);
+ return -ENOENT;
+ }
+
+ v = sym->st_value;
+
+ res = reloc_handlers[rel[i].r_type](me, location, v);
+ if (res)
+ return res;
+ }
+
+ return 0;
+}
diff --git a/arch/mips/kernel/module.c b/arch/mips/kernel/module.c
new file mode 100644
index 0000000..458af3c
--- /dev/null
+++ b/arch/mips/kernel/module.c
@@ -0,0 +1,53 @@
+#include <linux/module.h>
+#include <linux/spinlock.h>
+
+static LIST_HEAD(dbe_list);
+static DEFINE_SPINLOCK(dbe_lock);
+
+/* Given an address, look for it in the module exception tables. */
+const struct exception_table_entry *search_module_dbetables(unsigned long addr)
+{
+ unsigned long flags;
+ const struct exception_table_entry *e = NULL;
+ struct mod_arch_specific *dbe;
+
+ spin_lock_irqsave(&dbe_lock, flags);
+ list_for_each_entry(dbe, &dbe_list, dbe_list) {
+ e = search_extable(dbe->dbe_start, dbe->dbe_end - 1, addr);
+ if (e)
+ break;
+ }
+ spin_unlock_irqrestore(&dbe_lock, flags);
+
+ /* Now, if we found one, we are running inside it now, hence
+ we cannot unload the module, hence no refcnt needed. */
+ return e;
+}
+
+/* Put in dbe list if neccessary. */
+int module_finalize(const Elf_Ehdr *hdr,
+ const Elf_Shdr *sechdrs,
+ struct module *me)
+{
+ const Elf_Shdr *s;
+ char *secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
+
+ INIT_LIST_HEAD(&me->arch.dbe_list);
+ for (s = sechdrs; s < sechdrs + hdr->e_shnum; s++) {
+ if (strcmp("__dbe_table", secstrings + s->sh_name) != 0)
+ continue;
+ me->arch.dbe_start = (void *)s->sh_addr;
+ me->arch.dbe_end = (void *)s->sh_addr + s->sh_size;
+ spin_lock_irq(&dbe_lock);
+ list_add(&me->arch.dbe_list, &dbe_list);
+ spin_unlock_irq(&dbe_lock);
+ }
+ return 0;
+}
+
+void module_arch_cleanup(struct module *mod)
+{
+ spin_lock_irq(&dbe_lock);
+ list_del(&mod->arch.dbe_list);
+ spin_unlock_irq(&dbe_lock);
+}
diff --git a/arch/mips/kernel/offset.c b/arch/mips/kernel/offset.c
new file mode 100644
index 0000000..2c11abb
--- /dev/null
+++ b/arch/mips/kernel/offset.c
@@ -0,0 +1,314 @@
+/*
+ * offset.c: Calculate pt_regs and task_struct offsets.
+ *
+ * Copyright (C) 1996 David S. Miller
+ * Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003 Ralf Baechle
+ * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
+ *
+ * Kevin Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2000 MIPS Technologies, Inc.
+ */
+#include <linux/config.h>
+#include <linux/compat.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+
+#include <asm/ptrace.h>
+#include <asm/processor.h>
+
+#define text(t) __asm__("\n@@@" t)
+#define _offset(type, member) (&(((type *)NULL)->member))
+#define offset(string, ptr, member) \
+ __asm__("\n@@@" string "%0" : : "i" (_offset(ptr, member)))
+#define constant(string, member) \
+ __asm__("\n@@@" string "%x0" : : "ri" (member))
+#define size(string, size) \
+ __asm__("\n@@@" string "%0" : : "i" (sizeof(size)))
+#define linefeed text("")
+
+void output_ptreg_defines(void)
+{
+ text("/* MIPS pt_regs offsets. */");
+ offset("#define PT_R0 ", struct pt_regs, regs[0]);
+ offset("#define PT_R1 ", struct pt_regs, regs[1]);
+ offset("#define PT_R2 ", struct pt_regs, regs[2]);
+ offset("#define PT_R3 ", struct pt_regs, regs[3]);
+ offset("#define PT_R4 ", struct pt_regs, regs[4]);
+ offset("#define PT_R5 ", struct pt_regs, regs[5]);
+ offset("#define PT_R6 ", struct pt_regs, regs[6]);
+ offset("#define PT_R7 ", struct pt_regs, regs[7]);
+ offset("#define PT_R8 ", struct pt_regs, regs[8]);
+ offset("#define PT_R9 ", struct pt_regs, regs[9]);
+ offset("#define PT_R10 ", struct pt_regs, regs[10]);
+ offset("#define PT_R11 ", struct pt_regs, regs[11]);
+ offset("#define PT_R12 ", struct pt_regs, regs[12]);
+ offset("#define PT_R13 ", struct pt_regs, regs[13]);
+ offset("#define PT_R14 ", struct pt_regs, regs[14]);
+ offset("#define PT_R15 ", struct pt_regs, regs[15]);
+ offset("#define PT_R16 ", struct pt_regs, regs[16]);
+ offset("#define PT_R17 ", struct pt_regs, regs[17]);
+ offset("#define PT_R18 ", struct pt_regs, regs[18]);
+ offset("#define PT_R19 ", struct pt_regs, regs[19]);
+ offset("#define PT_R20 ", struct pt_regs, regs[20]);
+ offset("#define PT_R21 ", struct pt_regs, regs[21]);
+ offset("#define PT_R22 ", struct pt_regs, regs[22]);
+ offset("#define PT_R23 ", struct pt_regs, regs[23]);
+ offset("#define PT_R24 ", struct pt_regs, regs[24]);
+ offset("#define PT_R25 ", struct pt_regs, regs[25]);
+ offset("#define PT_R26 ", struct pt_regs, regs[26]);
+ offset("#define PT_R27 ", struct pt_regs, regs[27]);
+ offset("#define PT_R28 ", struct pt_regs, regs[28]);
+ offset("#define PT_R29 ", struct pt_regs, regs[29]);
+ offset("#define PT_R30 ", struct pt_regs, regs[30]);
+ offset("#define PT_R31 ", struct pt_regs, regs[31]);
+ offset("#define PT_LO ", struct pt_regs, lo);
+ offset("#define PT_HI ", struct pt_regs, hi);
+ offset("#define PT_EPC ", struct pt_regs, cp0_epc);
+ offset("#define PT_BVADDR ", struct pt_regs, cp0_badvaddr);
+ offset("#define PT_STATUS ", struct pt_regs, cp0_status);
+ offset("#define PT_CAUSE ", struct pt_regs, cp0_cause);
+ size("#define PT_SIZE ", struct pt_regs);
+ linefeed;
+}
+
+void output_task_defines(void)
+{
+ text("/* MIPS task_struct offsets. */");
+ offset("#define TASK_STATE ", struct task_struct, state);
+ offset("#define TASK_THREAD_INFO ", struct task_struct, thread_info);
+ offset("#define TASK_FLAGS ", struct task_struct, flags);
+ offset("#define TASK_MM ", struct task_struct, mm);
+ offset("#define TASK_PID ", struct task_struct, pid);
+ size( "#define TASK_STRUCT_SIZE ", struct task_struct);
+ linefeed;
+}
+
+void output_thread_info_defines(void)
+{
+ text("/* MIPS thread_info offsets. */");
+ offset("#define TI_TASK ", struct thread_info, task);
+ offset("#define TI_EXEC_DOMAIN ", struct thread_info, exec_domain);
+ offset("#define TI_FLAGS ", struct thread_info, flags);
+ offset("#define TI_CPU ", struct thread_info, cpu);
+ offset("#define TI_PRE_COUNT ", struct thread_info, preempt_count);
+ offset("#define TI_ADDR_LIMIT ", struct thread_info, addr_limit);
+ offset("#define TI_RESTART_BLOCK ", struct thread_info, restart_block);
+ constant("#define _THREAD_SIZE_ORDER ", THREAD_SIZE_ORDER);
+ constant("#define _THREAD_SIZE ", THREAD_SIZE);
+ constant("#define _THREAD_MASK ", THREAD_MASK);
+ linefeed;
+}
+
+void output_thread_defines(void)
+{
+ text("/* MIPS specific thread_struct offsets. */");
+ offset("#define THREAD_REG16 ", struct task_struct, thread.reg16);
+ offset("#define THREAD_REG17 ", struct task_struct, thread.reg17);
+ offset("#define THREAD_REG18 ", struct task_struct, thread.reg18);
+ offset("#define THREAD_REG19 ", struct task_struct, thread.reg19);
+ offset("#define THREAD_REG20 ", struct task_struct, thread.reg20);
+ offset("#define THREAD_REG21 ", struct task_struct, thread.reg21);
+ offset("#define THREAD_REG22 ", struct task_struct, thread.reg22);
+ offset("#define THREAD_REG23 ", struct task_struct, thread.reg23);
+ offset("#define THREAD_REG29 ", struct task_struct, thread.reg29);
+ offset("#define THREAD_REG30 ", struct task_struct, thread.reg30);
+ offset("#define THREAD_REG31 ", struct task_struct, thread.reg31);
+ offset("#define THREAD_STATUS ", struct task_struct,
+ thread.cp0_status);
+ offset("#define THREAD_FPU ", struct task_struct, thread.fpu);
+
+ offset("#define THREAD_BVADDR ", struct task_struct, \
+ thread.cp0_badvaddr);
+ offset("#define THREAD_BUADDR ", struct task_struct, \
+ thread.cp0_baduaddr);
+ offset("#define THREAD_ECODE ", struct task_struct, \
+ thread.error_code);
+ offset("#define THREAD_TRAPNO ", struct task_struct, thread.trap_no);
+ offset("#define THREAD_MFLAGS ", struct task_struct, thread.mflags);
+ offset("#define THREAD_TRAMP ", struct task_struct, \
+ thread.irix_trampoline);
+ offset("#define THREAD_OLDCTX ", struct task_struct, \
+ thread.irix_oldctx);
+ linefeed;
+}
+
+void output_thread_fpu_defines(void)
+{
+ offset("#define THREAD_FPR0 ",
+ struct task_struct, thread.fpu.hard.fpr[0]);
+ offset("#define THREAD_FPR1 ",
+ struct task_struct, thread.fpu.hard.fpr[1]);
+ offset("#define THREAD_FPR2 ",
+ struct task_struct, thread.fpu.hard.fpr[2]);
+ offset("#define THREAD_FPR3 ",
+ struct task_struct, thread.fpu.hard.fpr[3]);
+ offset("#define THREAD_FPR4 ",
+ struct task_struct, thread.fpu.hard.fpr[4]);
+ offset("#define THREAD_FPR5 ",
+ struct task_struct, thread.fpu.hard.fpr[5]);
+ offset("#define THREAD_FPR6 ",
+ struct task_struct, thread.fpu.hard.fpr[6]);
+ offset("#define THREAD_FPR7 ",
+ struct task_struct, thread.fpu.hard.fpr[7]);
+ offset("#define THREAD_FPR8 ",
+ struct task_struct, thread.fpu.hard.fpr[8]);
+ offset("#define THREAD_FPR9 ",
+ struct task_struct, thread.fpu.hard.fpr[9]);
+ offset("#define THREAD_FPR10 ",
+ struct task_struct, thread.fpu.hard.fpr[10]);
+ offset("#define THREAD_FPR11 ",
+ struct task_struct, thread.fpu.hard.fpr[11]);
+ offset("#define THREAD_FPR12 ",
+ struct task_struct, thread.fpu.hard.fpr[12]);
+ offset("#define THREAD_FPR13 ",
+ struct task_struct, thread.fpu.hard.fpr[13]);
+ offset("#define THREAD_FPR14 ",
+ struct task_struct, thread.fpu.hard.fpr[14]);
+ offset("#define THREAD_FPR15 ",
+ struct task_struct, thread.fpu.hard.fpr[15]);
+ offset("#define THREAD_FPR16 ",
+ struct task_struct, thread.fpu.hard.fpr[16]);
+ offset("#define THREAD_FPR17 ",
+ struct task_struct, thread.fpu.hard.fpr[17]);
+ offset("#define THREAD_FPR18 ",
+ struct task_struct, thread.fpu.hard.fpr[18]);
+ offset("#define THREAD_FPR19 ",
+ struct task_struct, thread.fpu.hard.fpr[19]);
+ offset("#define THREAD_FPR20 ",
+ struct task_struct, thread.fpu.hard.fpr[20]);
+ offset("#define THREAD_FPR21 ",
+ struct task_struct, thread.fpu.hard.fpr[21]);
+ offset("#define THREAD_FPR22 ",
+ struct task_struct, thread.fpu.hard.fpr[22]);
+ offset("#define THREAD_FPR23 ",
+ struct task_struct, thread.fpu.hard.fpr[23]);
+ offset("#define THREAD_FPR24 ",
+ struct task_struct, thread.fpu.hard.fpr[24]);
+ offset("#define THREAD_FPR25 ",
+ struct task_struct, thread.fpu.hard.fpr[25]);
+ offset("#define THREAD_FPR26 ",
+ struct task_struct, thread.fpu.hard.fpr[26]);
+ offset("#define THREAD_FPR27 ",
+ struct task_struct, thread.fpu.hard.fpr[27]);
+ offset("#define THREAD_FPR28 ",
+ struct task_struct, thread.fpu.hard.fpr[28]);
+ offset("#define THREAD_FPR29 ",
+ struct task_struct, thread.fpu.hard.fpr[29]);
+ offset("#define THREAD_FPR30 ",
+ struct task_struct, thread.fpu.hard.fpr[30]);
+ offset("#define THREAD_FPR31 ",
+ struct task_struct, thread.fpu.hard.fpr[31]);
+
+ offset("#define THREAD_FCR31 ",
+ struct task_struct, thread.fpu.hard.fcr31);
+ linefeed;
+}
+
+void output_mm_defines(void)
+{
+ text("/* Size of struct page */");
+ size("#define STRUCT_PAGE_SIZE ", struct page);
+ linefeed;
+ text("/* Linux mm_struct offsets. */");
+ offset("#define MM_USERS ", struct mm_struct, mm_users);
+ offset("#define MM_PGD ", struct mm_struct, pgd);
+ offset("#define MM_CONTEXT ", struct mm_struct, context);
+ linefeed;
+ constant("#define _PAGE_SIZE ", PAGE_SIZE);
+ constant("#define _PAGE_SHIFT ", PAGE_SHIFT);
+ linefeed;
+ constant("#define _PGD_T_SIZE ", sizeof(pgd_t));
+ constant("#define _PMD_T_SIZE ", sizeof(pmd_t));
+ constant("#define _PTE_T_SIZE ", sizeof(pte_t));
+ linefeed;
+ constant("#define _PGD_T_LOG2 ", PGD_T_LOG2);
+ constant("#define _PMD_T_LOG2 ", PMD_T_LOG2);
+ constant("#define _PTE_T_LOG2 ", PTE_T_LOG2);
+ linefeed;
+ constant("#define _PMD_SHIFT ", PMD_SHIFT);
+ constant("#define _PGDIR_SHIFT ", PGDIR_SHIFT);
+ linefeed;
+ constant("#define _PGD_ORDER ", PGD_ORDER);
+ constant("#define _PMD_ORDER ", PMD_ORDER);
+ constant("#define _PTE_ORDER ", PTE_ORDER);
+ linefeed;
+ constant("#define _PTRS_PER_PGD ", PTRS_PER_PGD);
+ constant("#define _PTRS_PER_PMD ", PTRS_PER_PMD);
+ constant("#define _PTRS_PER_PTE ", PTRS_PER_PTE);
+ linefeed;
+}
+
+void output_sc_defines(void)
+{
+ text("/* Linux sigcontext offsets. */");
+ offset("#define SC_REGS ", struct sigcontext, sc_regs);
+ offset("#define SC_FPREGS ", struct sigcontext, sc_fpregs);
+ offset("#define SC_MDHI ", struct sigcontext, sc_mdhi);
+ offset("#define SC_MDLO ", struct sigcontext, sc_mdlo);
+ offset("#define SC_PC ", struct sigcontext, sc_pc);
+ offset("#define SC_STATUS ", struct sigcontext, sc_status);
+ offset("#define SC_FPC_CSR ", struct sigcontext, sc_fpc_csr);
+ offset("#define SC_FPC_EIR ", struct sigcontext, sc_fpc_eir);
+ offset("#define SC_CAUSE ", struct sigcontext, sc_cause);
+ offset("#define SC_BADVADDR ", struct sigcontext, sc_badvaddr);
+ linefeed;
+}
+
+#ifdef CONFIG_MIPS32_COMPAT
+void output_sc32_defines(void)
+{
+ text("/* Linux 32-bit sigcontext offsets. */");
+ offset("#define SC32_FPREGS ", struct sigcontext32, sc_fpregs);
+ offset("#define SC32_FPC_CSR ", struct sigcontext32, sc_fpc_csr);
+ offset("#define SC32_FPC_EIR ", struct sigcontext32, sc_fpc_eir);
+ linefeed;
+}
+#endif
+
+void output_signal_defined(void)
+{
+ text("/* Linux signal numbers. */");
+ constant("#define _SIGHUP ", SIGHUP);
+ constant("#define _SIGINT ", SIGINT);
+ constant("#define _SIGQUIT ", SIGQUIT);
+ constant("#define _SIGILL ", SIGILL);
+ constant("#define _SIGTRAP ", SIGTRAP);
+ constant("#define _SIGIOT ", SIGIOT);
+ constant("#define _SIGABRT ", SIGABRT);
+ constant("#define _SIGEMT ", SIGEMT);
+ constant("#define _SIGFPE ", SIGFPE);
+ constant("#define _SIGKILL ", SIGKILL);
+ constant("#define _SIGBUS ", SIGBUS);
+ constant("#define _SIGSEGV ", SIGSEGV);
+ constant("#define _SIGSYS ", SIGSYS);
+ constant("#define _SIGPIPE ", SIGPIPE);
+ constant("#define _SIGALRM ", SIGALRM);
+ constant("#define _SIGTERM ", SIGTERM);
+ constant("#define _SIGUSR1 ", SIGUSR1);
+ constant("#define _SIGUSR2 ", SIGUSR2);
+ constant("#define _SIGCHLD ", SIGCHLD);
+ constant("#define _SIGPWR ", SIGPWR);
+ constant("#define _SIGWINCH ", SIGWINCH);
+ constant("#define _SIGURG ", SIGURG);
+ constant("#define _SIGIO ", SIGIO);
+ constant("#define _SIGSTOP ", SIGSTOP);
+ constant("#define _SIGTSTP ", SIGTSTP);
+ constant("#define _SIGCONT ", SIGCONT);
+ constant("#define _SIGTTIN ", SIGTTIN);
+ constant("#define _SIGTTOU ", SIGTTOU);
+ constant("#define _SIGVTALRM ", SIGVTALRM);
+ constant("#define _SIGPROF ", SIGPROF);
+ constant("#define _SIGXCPU ", SIGXCPU);
+ constant("#define _SIGXFSZ ", SIGXFSZ);
+ linefeed;
+}
+
+void output_irq_cpustat_t_defines(void)
+{
+ text("/* Linux irq_cpustat_t offsets. */");
+ offset("#define IC_SOFTIRQ_PENDING ", irq_cpustat_t, __softirq_pending);
+ size("#define IC_IRQ_CPUSTAT_T ", irq_cpustat_t);
+ linefeed;
+}
diff --git a/arch/mips/kernel/proc.c b/arch/mips/kernel/proc.c
new file mode 100644
index 0000000..0f159f3
--- /dev/null
+++ b/arch/mips/kernel/proc.c
@@ -0,0 +1,149 @@
+/*
+ * linux/arch/mips/kernel/proc.c
+ *
+ * Copyright (C) 1995, 1996, 2001 Ralf Baechle
+ * Copyright (C) 2001 MIPS Technologies, Inc.
+ */
+#include <linux/config.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/seq_file.h>
+#include <asm/bootinfo.h>
+#include <asm/cpu.h>
+#include <asm/cpu-features.h>
+#include <asm/mipsregs.h>
+#include <asm/processor.h>
+#include <asm/watch.h>
+
+unsigned int vced_count, vcei_count;
+
+static const char *cpu_name[] = {
+ [CPU_UNKNOWN] "unknown",
+ [CPU_R2000] "R2000",
+ [CPU_R3000] "R3000",
+ [CPU_R3000A] "R3000A",
+ [CPU_R3041] "R3041",
+ [CPU_R3051] "R3051",
+ [CPU_R3052] "R3052",
+ [CPU_R3081] "R3081",
+ [CPU_R3081E] "R3081E",
+ [CPU_R4000PC] "R4000PC",
+ [CPU_R4000SC] "R4000SC",
+ [CPU_R4000MC] "R4000MC",
+ [CPU_R4200] "R4200",
+ [CPU_R4400PC] "R4400PC",
+ [CPU_R4400SC] "R4400SC",
+ [CPU_R4400MC] "R4400MC",
+ [CPU_R4600] "R4600",
+ [CPU_R6000] "R6000",
+ [CPU_R6000A] "R6000A",
+ [CPU_R8000] "R8000",
+ [CPU_R10000] "R10000",
+ [CPU_R12000] "R12000",
+ [CPU_R4300] "R4300",
+ [CPU_R4650] "R4650",
+ [CPU_R4700] "R4700",
+ [CPU_R5000] "R5000",
+ [CPU_R5000A] "R5000A",
+ [CPU_R4640] "R4640",
+ [CPU_NEVADA] "Nevada",
+ [CPU_RM7000] "RM7000",
+ [CPU_RM9000] "RM9000",
+ [CPU_R5432] "R5432",
+ [CPU_4KC] "MIPS 4Kc",
+ [CPU_5KC] "MIPS 5Kc",
+ [CPU_R4310] "R4310",
+ [CPU_SB1] "SiByte SB1",
+ [CPU_TX3912] "TX3912",
+ [CPU_TX3922] "TX3922",
+ [CPU_TX3927] "TX3927",
+ [CPU_AU1000] "Au1000",
+ [CPU_AU1500] "Au1500",
+ [CPU_4KEC] "MIPS 4KEc",
+ [CPU_4KSC] "MIPS 4KSc",
+ [CPU_VR41XX] "NEC Vr41xx",
+ [CPU_R5500] "R5500",
+ [CPU_TX49XX] "TX49xx",
+ [CPU_20KC] "MIPS 20Kc",
+ [CPU_24K] "MIPS 24K",
+ [CPU_25KF] "MIPS 25Kf",
+ [CPU_VR4111] "NEC VR4111",
+ [CPU_VR4121] "NEC VR4121",
+ [CPU_VR4122] "NEC VR4122",
+ [CPU_VR4131] "NEC VR4131",
+ [CPU_VR4133] "NEC VR4133",
+ [CPU_VR4181] "NEC VR4181",
+ [CPU_VR4181A] "NEC VR4181A",
+ [CPU_SR71000] "Sandcraft SR71000"
+};
+
+
+static int show_cpuinfo(struct seq_file *m, void *v)
+{
+ unsigned int version = current_cpu_data.processor_id;
+ unsigned int fp_vers = current_cpu_data.fpu_id;
+ unsigned long n = (unsigned long) v - 1;
+ char fmt [64];
+
+#ifdef CONFIG_SMP
+ if (!cpu_isset(n, cpu_online_map))
+ return 0;
+#endif
+
+ /*
+ * For the first processor also print the system type
+ */
+ if (n == 0)
+ seq_printf(m, "system type\t\t: %s\n", get_system_type());
+
+ seq_printf(m, "processor\t\t: %ld\n", n);
+ sprintf(fmt, "cpu model\t\t: %%s V%%d.%%d%s\n",
+ cpu_has_fpu ? " FPU V%d.%d" : "");
+ seq_printf(m, fmt, cpu_name[current_cpu_data.cputype <= CPU_LAST ?
+ current_cpu_data.cputype : CPU_UNKNOWN],
+ (version >> 4) & 0x0f, version & 0x0f,
+ (fp_vers >> 4) & 0x0f, fp_vers & 0x0f);
+ seq_printf(m, "BogoMIPS\t\t: %lu.%02lu\n",
+ loops_per_jiffy / (500000/HZ),
+ (loops_per_jiffy / (5000/HZ)) % 100);
+ seq_printf(m, "wait instruction\t: %s\n", cpu_wait ? "yes" : "no");
+ seq_printf(m, "microsecond timers\t: %s\n",
+ cpu_has_counter ? "yes" : "no");
+ seq_printf(m, "tlb_entries\t\t: %d\n", current_cpu_data.tlbsize);
+ seq_printf(m, "extra interrupt vector\t: %s\n",
+ cpu_has_divec ? "yes" : "no");
+ seq_printf(m, "hardware watchpoint\t: %s\n",
+ cpu_has_watch ? "yes" : "no");
+
+ sprintf(fmt, "VCE%%c exceptions\t\t: %s\n",
+ cpu_has_vce ? "%u" : "not available");
+ seq_printf(m, fmt, 'D', vced_count);
+ seq_printf(m, fmt, 'I', vcei_count);
+
+ return 0;
+}
+
+static void *c_start(struct seq_file *m, loff_t *pos)
+{
+ unsigned long i = *pos;
+
+ return i < NR_CPUS ? (void *) (i + 1) : NULL;
+}
+
+static void *c_next(struct seq_file *m, void *v, loff_t *pos)
+{
+ ++*pos;
+ return c_start(m, pos);
+}
+
+static void c_stop(struct seq_file *m, void *v)
+{
+}
+
+struct seq_operations cpuinfo_op = {
+ .start = c_start,
+ .next = c_next,
+ .stop = c_stop,
+ .show = show_cpuinfo,
+};
diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c
new file mode 100644
index 0000000..6e70c42
--- /dev/null
+++ b/arch/mips/kernel/process.c
@@ -0,0 +1,364 @@
+/*
+ * 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) 1994 - 1999, 2000 by Ralf Baechle and others.
+ * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
+ * Copyright (C) 2004 Thiemo Seufer
+ */
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/stddef.h>
+#include <linux/unistd.h>
+#include <linux/ptrace.h>
+#include <linux/slab.h>
+#include <linux/mman.h>
+#include <linux/personality.h>
+#include <linux/sys.h>
+#include <linux/user.h>
+#include <linux/a.out.h>
+#include <linux/init.h>
+#include <linux/completion.h>
+
+#include <asm/bootinfo.h>
+#include <asm/cpu.h>
+#include <asm/fpu.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include <asm/mipsregs.h>
+#include <asm/processor.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/elf.h>
+#include <asm/isadep.h>
+#include <asm/inst.h>
+
+/*
+ * We use this if we don't have any better idle routine..
+ * (This to kill: kernel/platform.c.
+ */
+void default_idle (void)
+{
+}
+
+/*
+ * The idle thread. There's no useful work to be done, so just try to conserve
+ * power and have a low exit latency (ie sit in a loop waiting for somebody to
+ * say that they'd like to reschedule)
+ */
+ATTRIB_NORET void cpu_idle(void)
+{
+ /* endless idle loop with no priority at all */
+ while (1) {
+ while (!need_resched())
+ if (cpu_wait)
+ (*cpu_wait)();
+ schedule();
+ }
+}
+
+asmlinkage void ret_from_fork(void);
+
+void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp)
+{
+ unsigned long status;
+
+ /* New thread loses kernel privileges. */
+ status = regs->cp0_status & ~(ST0_CU0|ST0_CU1|KU_MASK);
+#ifdef CONFIG_MIPS64
+ status &= ~ST0_FR;
+ status |= (current->thread.mflags & MF_32BIT_REGS) ? 0 : ST0_FR;
+#endif
+ status |= KU_USER;
+ regs->cp0_status = status;
+ clear_used_math();
+ lose_fpu();
+ regs->cp0_epc = pc;
+ regs->regs[29] = sp;
+ current_thread_info()->addr_limit = USER_DS;
+}
+
+void exit_thread(void)
+{
+}
+
+void flush_thread(void)
+{
+}
+
+int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
+ unsigned long unused, struct task_struct *p, struct pt_regs *regs)
+{
+ struct thread_info *ti = p->thread_info;
+ struct pt_regs *childregs;
+ long childksp;
+
+ childksp = (unsigned long)ti + THREAD_SIZE - 32;
+
+ preempt_disable();
+
+ if (is_fpu_owner()) {
+ save_fp(p);
+ }
+
+ preempt_enable();
+
+ /* set up new TSS. */
+ childregs = (struct pt_regs *) childksp - 1;
+ *childregs = *regs;
+ childregs->regs[7] = 0; /* Clear error flag */
+
+#if defined(CONFIG_BINFMT_IRIX)
+ if (current->personality != PER_LINUX) {
+ /* Under IRIX things are a little different. */
+ childregs->regs[3] = 1;
+ regs->regs[3] = 0;
+ }
+#endif
+ childregs->regs[2] = 0; /* Child gets zero as return value */
+ regs->regs[2] = p->pid;
+
+ if (childregs->cp0_status & ST0_CU0) {
+ childregs->regs[28] = (unsigned long) ti;
+ childregs->regs[29] = childksp;
+ ti->addr_limit = KERNEL_DS;
+ } else {
+ childregs->regs[29] = usp;
+ ti->addr_limit = USER_DS;
+ }
+ p->thread.reg29 = (unsigned long) childregs;
+ p->thread.reg31 = (unsigned long) ret_from_fork;
+
+ /*
+ * New tasks lose permission to use the fpu. This accelerates context
+ * switching for most programs since they don't use the fpu.
+ */
+ p->thread.cp0_status = read_c0_status() & ~(ST0_CU2|ST0_CU1);
+ childregs->cp0_status &= ~(ST0_CU2|ST0_CU1);
+ clear_tsk_thread_flag(p, TIF_USEDFPU);
+
+ return 0;
+}
+
+/* Fill in the fpu structure for a core dump.. */
+int dump_fpu(struct pt_regs *regs, elf_fpregset_t *r)
+{
+ memcpy(r, ¤t->thread.fpu, sizeof(current->thread.fpu));
+
+ return 1;
+}
+
+void dump_regs(elf_greg_t *gp, struct pt_regs *regs)
+{
+ int i;
+
+ for (i = 0; i < EF_R0; i++)
+ gp[i] = 0;
+ gp[EF_R0] = 0;
+ for (i = 1; i <= 31; i++)
+ gp[EF_R0 + i] = regs->regs[i];
+ gp[EF_R26] = 0;
+ gp[EF_R27] = 0;
+ gp[EF_LO] = regs->lo;
+ gp[EF_HI] = regs->hi;
+ gp[EF_CP0_EPC] = regs->cp0_epc;
+ gp[EF_CP0_BADVADDR] = regs->cp0_badvaddr;
+ gp[EF_CP0_STATUS] = regs->cp0_status;
+ gp[EF_CP0_CAUSE] = regs->cp0_cause;
+#ifdef EF_UNUSED0
+ gp[EF_UNUSED0] = 0;
+#endif
+}
+
+int dump_task_fpu (struct task_struct *t, elf_fpregset_t *fpr)
+{
+ memcpy(fpr, &t->thread.fpu, sizeof(current->thread.fpu));
+
+ return 1;
+}
+
+/*
+ * Create a kernel thread
+ */
+ATTRIB_NORET void kernel_thread_helper(void *arg, int (*fn)(void *))
+{
+ do_exit(fn(arg));
+}
+
+long kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
+{
+ struct pt_regs regs;
+
+ memset(®s, 0, sizeof(regs));
+
+ regs.regs[4] = (unsigned long) arg;
+ regs.regs[5] = (unsigned long) fn;
+ regs.cp0_epc = (unsigned long) kernel_thread_helper;
+ regs.cp0_status = read_c0_status();
+#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)
+ regs.cp0_status &= ~(ST0_KUP | ST0_IEC);
+ regs.cp0_status |= ST0_IEP;
+#else
+ regs.cp0_status |= ST0_EXL;
+#endif
+
+ /* Ok, create the new process.. */
+ return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, 0, NULL, NULL);
+}
+
+struct mips_frame_info {
+ int frame_offset;
+ int pc_offset;
+};
+static struct mips_frame_info schedule_frame;
+static struct mips_frame_info schedule_timeout_frame;
+static struct mips_frame_info sleep_on_frame;
+static struct mips_frame_info sleep_on_timeout_frame;
+static struct mips_frame_info wait_for_completion_frame;
+static int mips_frame_info_initialized;
+static int __init get_frame_info(struct mips_frame_info *info, void *func)
+{
+ int i;
+ union mips_instruction *ip = (union mips_instruction *)func;
+ info->pc_offset = -1;
+ info->frame_offset = -1;
+ for (i = 0; i < 128; i++, ip++) {
+ /* if jal, jalr, jr, stop. */
+ if (ip->j_format.opcode == jal_op ||
+ (ip->r_format.opcode == spec_op &&
+ (ip->r_format.func == jalr_op ||
+ ip->r_format.func == jr_op)))
+ break;
+
+ if (
+#ifdef CONFIG_MIPS32
+ ip->i_format.opcode == sw_op &&
+#endif
+#ifdef CONFIG_MIPS64
+ ip->i_format.opcode == sd_op &&
+#endif
+ ip->i_format.rs == 29)
+ {
+ /* sw / sd $ra, offset($sp) */
+ if (ip->i_format.rt == 31) {
+ if (info->pc_offset != -1)
+ break;
+ info->pc_offset =
+ ip->i_format.simmediate / sizeof(long);
+ }
+ /* sw / sd $s8, offset($sp) */
+ if (ip->i_format.rt == 30) {
+ if (info->frame_offset != -1)
+ break;
+ info->frame_offset =
+ ip->i_format.simmediate / sizeof(long);
+ }
+ }
+ }
+ if (info->pc_offset == -1 || info->frame_offset == -1) {
+ printk("Can't analyze prologue code at %p\n", func);
+ info->pc_offset = -1;
+ info->frame_offset = -1;
+ return -1;
+ }
+
+ return 0;
+}
+
+static int __init frame_info_init(void)
+{
+ mips_frame_info_initialized =
+ !get_frame_info(&schedule_frame, schedule) &&
+ !get_frame_info(&schedule_timeout_frame, schedule_timeout) &&
+ !get_frame_info(&sleep_on_frame, sleep_on) &&
+ !get_frame_info(&sleep_on_timeout_frame, sleep_on_timeout) &&
+ !get_frame_info(&wait_for_completion_frame, wait_for_completion);
+
+ return 0;
+}
+
+arch_initcall(frame_info_init);
+
+/*
+ * Return saved PC of a blocked thread.
+ */
+unsigned long thread_saved_pc(struct task_struct *tsk)
+{
+ struct thread_struct *t = &tsk->thread;
+
+ /* New born processes are a special case */
+ if (t->reg31 == (unsigned long) ret_from_fork)
+ return t->reg31;
+
+ if (schedule_frame.pc_offset < 0)
+ return 0;
+ return ((unsigned long *)t->reg29)[schedule_frame.pc_offset];
+}
+
+/* get_wchan - a maintenance nightmare^W^Wpain in the ass ... */
+unsigned long get_wchan(struct task_struct *p)
+{
+ unsigned long frame, pc;
+
+ if (!p || p == current || p->state == TASK_RUNNING)
+ return 0;
+
+ if (!mips_frame_info_initialized)
+ return 0;
+ pc = thread_saved_pc(p);
+ if (!in_sched_functions(pc))
+ goto out;
+
+ if (pc >= (unsigned long) sleep_on_timeout)
+ goto schedule_timeout_caller;
+ if (pc >= (unsigned long) sleep_on)
+ goto schedule_caller;
+ if (pc >= (unsigned long) interruptible_sleep_on_timeout)
+ goto schedule_timeout_caller;
+ if (pc >= (unsigned long)interruptible_sleep_on)
+ goto schedule_caller;
+ if (pc >= (unsigned long)wait_for_completion)
+ goto schedule_caller;
+ goto schedule_timeout_caller;
+
+schedule_caller:
+ frame = ((unsigned long *)p->thread.reg30)[schedule_frame.frame_offset];
+ if (pc >= (unsigned long) sleep_on)
+ pc = ((unsigned long *)frame)[sleep_on_frame.pc_offset];
+ else
+ pc = ((unsigned long *)frame)[wait_for_completion_frame.pc_offset];
+ goto out;
+
+schedule_timeout_caller:
+ /*
+ * The schedule_timeout frame
+ */
+ frame = ((unsigned long *)p->thread.reg30)[schedule_frame.frame_offset];
+
+ /*
+ * frame now points to sleep_on_timeout's frame
+ */
+ pc = ((unsigned long *)frame)[schedule_timeout_frame.pc_offset];
+
+ if (in_sched_functions(pc)) {
+ /* schedule_timeout called by [interruptible_]sleep_on_timeout */
+ frame = ((unsigned long *)frame)[schedule_timeout_frame.frame_offset];
+ pc = ((unsigned long *)frame)[sleep_on_timeout_frame.pc_offset];
+ }
+
+out:
+
+#ifdef CONFIG_MIPS64
+ if (current->thread.mflags & MF_32BIT_REGS) /* Kludge for 32-bit ps */
+ pc &= 0xffffffffUL;
+#endif
+
+ return pc;
+}
+
+EXPORT_SYMBOL(get_wchan);
diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
new file mode 100644
index 0000000..a166954
--- /dev/null
+++ b/arch/mips/kernel/ptrace.c
@@ -0,0 +1,338 @@
+/*
+ * 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) 1992 Ross Biro
+ * Copyright (C) Linus Torvalds
+ * Copyright (C) 1994, 95, 96, 97, 98, 2000 Ralf Baechle
+ * Copyright (C) 1996 David S. Miller
+ * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999 MIPS Technologies, Inc.
+ * Copyright (C) 2000 Ulf Carlsson
+ *
+ * At this time Linux/MIPS64 only supports syscall tracing, even for 32-bit
+ * binaries.
+ */
+#include <linux/config.h>
+#include <linux/compiler.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/errno.h>
+#include <linux/ptrace.h>
+#include <linux/audit.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/user.h>
+#include <linux/security.h>
+#include <linux/audit.h>
+
+#include <asm/cpu.h>
+#include <asm/fpu.h>
+#include <asm/mipsregs.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+#include <asm/bootinfo.h>
+
+/*
+ * Called by kernel/ptrace.c when detaching..
+ *
+ * Make sure single step bits etc are not set.
+ */
+void ptrace_disable(struct task_struct *child)
+{
+ /* Nothing to do.. */
+}
+
+asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
+{
+ struct task_struct *child;
+ int ret;
+
+#if 0
+ printk("ptrace(r=%d,pid=%d,addr=%08lx,data=%08lx)\n",
+ (int) request, (int) pid, (unsigned long) addr,
+ (unsigned long) data);
+#endif
+ lock_kernel();
+ ret = -EPERM;
+ if (request == PTRACE_TRACEME) {
+ /* are we already being traced? */
+ if (current->ptrace & PT_PTRACED)
+ goto out;
+ if ((ret = security_ptrace(current->parent, current)))
+ goto out;
+ /* set the ptrace bit in the process flags. */
+ current->ptrace |= PT_PTRACED;
+ ret = 0;
+ goto out;
+ }
+ ret = -ESRCH;
+ read_lock(&tasklist_lock);
+ child = find_task_by_pid(pid);
+ if (child)
+ get_task_struct(child);
+ read_unlock(&tasklist_lock);
+ if (!child)
+ goto out;
+
+ ret = -EPERM;
+ if (pid == 1) /* you may not mess with init */
+ goto out_tsk;
+
+ if (request == PTRACE_ATTACH) {
+ ret = ptrace_attach(child);
+ goto out_tsk;
+ }
+
+ ret = ptrace_check_attach(child, request == PTRACE_KILL);
+ if (ret < 0)
+ goto out_tsk;
+
+ switch (request) {
+ /* when I and D space are separate, these will need to be fixed. */
+ case PTRACE_PEEKTEXT: /* read word at location addr. */
+ case PTRACE_PEEKDATA: {
+ unsigned long tmp;
+ int copied;
+
+ copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
+ ret = -EIO;
+ if (copied != sizeof(tmp))
+ break;
+ ret = put_user(tmp,(unsigned long *) data);
+ break;
+ }
+
+ /* Read the word at location addr in the USER area. */
+ case PTRACE_PEEKUSR: {
+ struct pt_regs *regs;
+ unsigned long tmp = 0;
+
+ regs = (struct pt_regs *) ((unsigned long) child->thread_info +
+ THREAD_SIZE - 32 - sizeof(struct pt_regs));
+ ret = 0; /* Default return value. */
+
+ switch (addr) {
+ case 0 ... 31:
+ tmp = regs->regs[addr];
+ break;
+ case FPR_BASE ... FPR_BASE + 31:
+ if (tsk_used_math(child)) {
+ fpureg_t *fregs = get_fpu_regs(child);
+
+#ifdef CONFIG_MIPS32
+ /*
+ * The odd registers are actually the high
+ * order bits of the values stored in the even
+ * registers - unless we're using r2k_switch.S.
+ */
+ if (addr & 1)
+ tmp = (unsigned long) (fregs[((addr & ~1) - 32)] >> 32);
+ else
+ tmp = (unsigned long) (fregs[(addr - 32)] & 0xffffffff);
+#endif
+#ifdef CONFIG_MIPS64
+ tmp = fregs[addr - FPR_BASE];
+#endif
+ } else {
+ tmp = -1; /* FP not yet used */
+ }
+ break;
+ case PC:
+ tmp = regs->cp0_epc;
+ break;
+ case CAUSE:
+ tmp = regs->cp0_cause;
+ break;
+ case BADVADDR:
+ tmp = regs->cp0_badvaddr;
+ break;
+ case MMHI:
+ tmp = regs->hi;
+ break;
+ case MMLO:
+ tmp = regs->lo;
+ break;
+ case FPC_CSR:
+ if (cpu_has_fpu)
+ tmp = child->thread.fpu.hard.fcr31;
+ else
+ tmp = child->thread.fpu.soft.fcr31;
+ break;
+ case FPC_EIR: { /* implementation / version register */
+ unsigned int flags;
+
+ if (!cpu_has_fpu)
+ break;
+
+ flags = read_c0_status();
+ __enable_fpu();
+ __asm__ __volatile__("cfc1\t%0,$0": "=r" (tmp));
+ write_c0_status(flags);
+ break;
+ }
+ default:
+ tmp = 0;
+ ret = -EIO;
+ goto out_tsk;
+ }
+ ret = put_user(tmp, (unsigned long *) data);
+ break;
+ }
+
+ /* when I and D space are separate, this will have to be fixed. */
+ case PTRACE_POKETEXT: /* write the word at location addr. */
+ case PTRACE_POKEDATA:
+ ret = 0;
+ if (access_process_vm(child, addr, &data, sizeof(data), 1)
+ == sizeof(data))
+ break;
+ ret = -EIO;
+ break;
+
+ case PTRACE_POKEUSR: {
+ struct pt_regs *regs;
+ ret = 0;
+ regs = (struct pt_regs *) ((unsigned long) child->thread_info +
+ THREAD_SIZE - 32 - sizeof(struct pt_regs));
+
+ switch (addr) {
+ case 0 ... 31:
+ regs->regs[addr] = data;
+ break;
+ case FPR_BASE ... FPR_BASE + 31: {
+ fpureg_t *fregs = get_fpu_regs(child);
+
+ if (!tsk_used_math(child)) {
+ /* FP not yet used */
+ memset(&child->thread.fpu.hard, ~0,
+ sizeof(child->thread.fpu.hard));
+ child->thread.fpu.hard.fcr31 = 0;
+ }
+#ifdef CONFIG_MIPS32
+ /*
+ * The odd registers are actually the high order bits
+ * of the values stored in the even registers - unless
+ * we're using r2k_switch.S.
+ */
+ if (addr & 1) {
+ fregs[(addr & ~1) - FPR_BASE] &= 0xffffffff;
+ fregs[(addr & ~1) - FPR_BASE] |= ((unsigned long long) data) << 32;
+ } else {
+ fregs[addr - FPR_BASE] &= ~0xffffffffLL;
+ fregs[addr - FPR_BASE] |= data;
+ }
+#endif
+#ifdef CONFIG_MIPS64
+ fregs[addr - FPR_BASE] = data;
+#endif
+ break;
+ }
+ case PC:
+ regs->cp0_epc = data;
+ break;
+ case MMHI:
+ regs->hi = data;
+ break;
+ case MMLO:
+ regs->lo = data;
+ break;
+ case FPC_CSR:
+ if (cpu_has_fpu)
+ child->thread.fpu.hard.fcr31 = data;
+ else
+ child->thread.fpu.soft.fcr31 = data;
+ break;
+ default:
+ /* The rest are not allowed. */
+ ret = -EIO;
+ break;
+ }
+ break;
+ }
+
+ case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
+ case PTRACE_CONT: { /* restart after signal. */
+ ret = -EIO;
+ if ((unsigned long) data > _NSIG)
+ break;
+ if (request == PTRACE_SYSCALL) {
+ set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
+ }
+ else {
+ clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
+ }
+ child->exit_code = data;
+ wake_up_process(child);
+ ret = 0;
+ break;
+ }
+
+ /*
+ * make the child exit. Best I can do is send it a sigkill.
+ * perhaps it should be put in the status that it wants to
+ * exit.
+ */
+ case PTRACE_KILL:
+ ret = 0;
+ if (child->exit_state == EXIT_ZOMBIE) /* already dead */
+ break;
+ child->exit_code = SIGKILL;
+ wake_up_process(child);
+ break;
+
+ case PTRACE_DETACH: /* detach a process that was attached. */
+ ret = ptrace_detach(child, data);
+ break;
+
+ default:
+ ret = ptrace_request(child, request, addr, data);
+ break;
+ }
+
+out_tsk:
+ put_task_struct(child);
+out:
+ unlock_kernel();
+ return ret;
+}
+
+/*
+ * Notification of system call entry/exit
+ * - triggered by current->work.syscall_trace
+ */
+asmlinkage void do_syscall_trace(struct pt_regs *regs, int entryexit)
+{
+ if (unlikely(current->audit_context)) {
+ if (!entryexit)
+ audit_syscall_entry(current, regs->regs[2],
+ regs->regs[4], regs->regs[5],
+ regs->regs[6], regs->regs[7]);
+ else
+ audit_syscall_exit(current, regs->regs[2]);
+ }
+
+ if (!test_thread_flag(TIF_SYSCALL_TRACE))
+ return;
+ if (!(current->ptrace & PT_PTRACED))
+ return;
+
+ /* The 0x80 provides a way for the tracing parent to distinguish
+ between a syscall stop and SIGTRAP delivery */
+ ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) ?
+ 0x80 : 0));
+
+ /*
+ * this isn't the same as continuing with a signal, but it will do
+ * for normal use. strace only continues with a signal if the
+ * stopping signal is not SIGTRAP. -brl
+ */
+ if (current->exit_code) {
+ send_sig(current->exit_code, current, 1);
+ current->exit_code = 0;
+ }
+}
diff --git a/arch/mips/kernel/ptrace32.c b/arch/mips/kernel/ptrace32.c
new file mode 100644
index 0000000..611dee9
--- /dev/null
+++ b/arch/mips/kernel/ptrace32.c
@@ -0,0 +1,285 @@
+/*
+ * 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) 1992 Ross Biro
+ * Copyright (C) Linus Torvalds
+ * Copyright (C) 1994, 95, 96, 97, 98, 2000 Ralf Baechle
+ * Copyright (C) 1996 David S. Miller
+ * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999 MIPS Technologies, Inc.
+ * Copyright (C) 2000 Ulf Carlsson
+ *
+ * At this time Linux/MIPS64 only supports syscall tracing, even for 32-bit
+ * binaries.
+ */
+#include <linux/compiler.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/errno.h>
+#include <linux/ptrace.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/user.h>
+#include <linux/security.h>
+
+#include <asm/cpu.h>
+#include <asm/fpu.h>
+#include <asm/mipsregs.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+#include <asm/bootinfo.h>
+
+/*
+ * Tracing a 32-bit process with a 64-bit strace and vice versa will not
+ * work. I don't know how to fix this.
+ */
+asmlinkage int sys32_ptrace(int request, int pid, int addr, int data)
+{
+ struct task_struct *child;
+ int ret;
+
+#if 0
+ printk("ptrace(r=%d,pid=%d,addr=%08lx,data=%08lx)\n",
+ (int) request, (int) pid, (unsigned long) addr,
+ (unsigned long) data);
+#endif
+ lock_kernel();
+ ret = -EPERM;
+ if (request == PTRACE_TRACEME) {
+ /* are we already being traced? */
+ if (current->ptrace & PT_PTRACED)
+ goto out;
+ if ((ret = security_ptrace(current->parent, current)))
+ goto out;
+ /* set the ptrace bit in the process flags. */
+ current->ptrace |= PT_PTRACED;
+ ret = 0;
+ goto out;
+ }
+ ret = -ESRCH;
+ read_lock(&tasklist_lock);
+ child = find_task_by_pid(pid);
+ if (child)
+ get_task_struct(child);
+ read_unlock(&tasklist_lock);
+ if (!child)
+ goto out;
+
+ ret = -EPERM;
+ if (pid == 1) /* you may not mess with init */
+ goto out_tsk;
+
+ if (request == PTRACE_ATTACH) {
+ ret = ptrace_attach(child);
+ goto out_tsk;
+ }
+
+ ret = ptrace_check_attach(child, request == PTRACE_KILL);
+ if (ret < 0)
+ goto out_tsk;
+
+ switch (request) {
+ /* when I and D space are separate, these will need to be fixed. */
+ case PTRACE_PEEKTEXT: /* read word at location addr. */
+ case PTRACE_PEEKDATA: {
+ unsigned int tmp;
+ int copied;
+
+ copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
+ ret = -EIO;
+ if (copied != sizeof(tmp))
+ break;
+ ret = put_user(tmp, (unsigned int *) (unsigned long) data);
+ break;
+ }
+
+ /* Read the word at location addr in the USER area. */
+ case PTRACE_PEEKUSR: {
+ struct pt_regs *regs;
+ unsigned int tmp;
+
+ regs = (struct pt_regs *) ((unsigned long) child->thread_info +
+ THREAD_SIZE - 32 - sizeof(struct pt_regs));
+ ret = 0; /* Default return value. */
+
+ switch (addr) {
+ case 0 ... 31:
+ tmp = regs->regs[addr];
+ break;
+ case FPR_BASE ... FPR_BASE + 31:
+ if (tsk_used_math(child)) {
+ fpureg_t *fregs = get_fpu_regs(child);
+
+ /*
+ * The odd registers are actually the high
+ * order bits of the values stored in the even
+ * registers - unless we're using r2k_switch.S.
+ */
+ if (addr & 1)
+ tmp = (unsigned long) (fregs[((addr & ~1) - 32)] >> 32);
+ else
+ tmp = (unsigned long) (fregs[(addr - 32)] & 0xffffffff);
+ } else {
+ tmp = -1; /* FP not yet used */
+ }
+ break;
+ case PC:
+ tmp = regs->cp0_epc;
+ break;
+ case CAUSE:
+ tmp = regs->cp0_cause;
+ break;
+ case BADVADDR:
+ tmp = regs->cp0_badvaddr;
+ break;
+ case MMHI:
+ tmp = regs->hi;
+ break;
+ case MMLO:
+ tmp = regs->lo;
+ break;
+ case FPC_CSR:
+ if (cpu_has_fpu)
+ tmp = child->thread.fpu.hard.fcr31;
+ else
+ tmp = child->thread.fpu.soft.fcr31;
+ break;
+ case FPC_EIR: { /* implementation / version register */
+ unsigned int flags;
+
+ if (!cpu_has_fpu)
+ break;
+
+ flags = read_c0_status();
+ __enable_fpu();
+ __asm__ __volatile__("cfc1\t%0,$0": "=r" (tmp));
+ write_c0_status(flags);
+ break;
+ }
+ default:
+ tmp = 0;
+ ret = -EIO;
+ goto out_tsk;
+ }
+ ret = put_user(tmp, (unsigned *) (unsigned long) data);
+ break;
+ }
+
+ /* when I and D space are separate, this will have to be fixed. */
+ case PTRACE_POKETEXT: /* write the word at location addr. */
+ case PTRACE_POKEDATA:
+ ret = 0;
+ if (access_process_vm(child, addr, &data, sizeof(data), 1)
+ == sizeof(data))
+ break;
+ ret = -EIO;
+ break;
+
+ case PTRACE_POKEUSR: {
+ struct pt_regs *regs;
+ ret = 0;
+ regs = (struct pt_regs *) ((unsigned long) child->thread_info +
+ THREAD_SIZE - 32 - sizeof(struct pt_regs));
+
+ switch (addr) {
+ case 0 ... 31:
+ regs->regs[addr] = data;
+ break;
+ case FPR_BASE ... FPR_BASE + 31: {
+ fpureg_t *fregs = get_fpu_regs(child);
+
+ if (!tsk_used_math(child)) {
+ /* FP not yet used */
+ memset(&child->thread.fpu.hard, ~0,
+ sizeof(child->thread.fpu.hard));
+ child->thread.fpu.hard.fcr31 = 0;
+ }
+ /*
+ * The odd registers are actually the high order bits
+ * of the values stored in the even registers - unless
+ * we're using r2k_switch.S.
+ */
+ if (addr & 1) {
+ fregs[(addr & ~1) - FPR_BASE] &= 0xffffffff;
+ fregs[(addr & ~1) - FPR_BASE] |= ((unsigned long long) data) << 32;
+ } else {
+ fregs[addr - FPR_BASE] &= ~0xffffffffLL;
+ /* Must cast, lest sign extension fill upper
+ bits! */
+ fregs[addr - FPR_BASE] |= (unsigned int)data;
+ }
+ break;
+ }
+ case PC:
+ regs->cp0_epc = data;
+ break;
+ case MMHI:
+ regs->hi = data;
+ break;
+ case MMLO:
+ regs->lo = data;
+ break;
+ case FPC_CSR:
+ if (cpu_has_fpu)
+ child->thread.fpu.hard.fcr31 = data;
+ else
+ child->thread.fpu.soft.fcr31 = data;
+ break;
+ default:
+ /* The rest are not allowed. */
+ ret = -EIO;
+ break;
+ }
+ break;
+ }
+
+ case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
+ case PTRACE_CONT: { /* restart after signal. */
+ ret = -EIO;
+ if ((unsigned int) data > _NSIG)
+ break;
+ if (request == PTRACE_SYSCALL) {
+ set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
+ }
+ else {
+ clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
+ }
+ child->exit_code = data;
+ wake_up_process(child);
+ ret = 0;
+ break;
+ }
+
+ /*
+ * make the child exit. Best I can do is send it a sigkill.
+ * perhaps it should be put in the status that it wants to
+ * exit.
+ */
+ case PTRACE_KILL:
+ ret = 0;
+ if (child->exit_state == EXIT_ZOMBIE) /* already dead */
+ break;
+ child->exit_code = SIGKILL;
+ wake_up_process(child);
+ break;
+
+ case PTRACE_DETACH: /* detach a process that was attached. */
+ ret = ptrace_detach(child, data);
+ break;
+
+ default:
+ ret = ptrace_request(child, request, addr, data);
+ break;
+ }
+
+out_tsk:
+ put_task_struct(child);
+out:
+ unlock_kernel();
+ return ret;
+}
diff --git a/arch/mips/kernel/r2300_fpu.S b/arch/mips/kernel/r2300_fpu.S
new file mode 100644
index 0000000..f83c31f
--- /dev/null
+++ b/arch/mips/kernel/r2300_fpu.S
@@ -0,0 +1,126 @@
+/*
+ * 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) 1996, 1998 by Ralf Baechle
+ *
+ * Multi-arch abstraction and asm macros for easier reading:
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ *
+ * Further modifications to make this work:
+ * Copyright (c) 1998 Harald Koerfgen
+ */
+#include <asm/asm.h>
+#include <asm/errno.h>
+#include <asm/fpregdef.h>
+#include <asm/mipsregs.h>
+#include <asm/offset.h>
+#include <asm/regdef.h>
+
+#define EX(a,b) \
+9: a,##b; \
+ .section __ex_table,"a"; \
+ PTR 9b,bad_stack; \
+ .previous
+
+ .set noreorder
+ .set mips1
+ /* Save floating point context */
+LEAF(_save_fp_context)
+ li v0, 0 # assume success
+ cfc1 t1,fcr31
+ EX(swc1 $f0,(SC_FPREGS+0)(a0))
+ EX(swc1 $f1,(SC_FPREGS+8)(a0))
+ EX(swc1 $f2,(SC_FPREGS+16)(a0))
+ EX(swc1 $f3,(SC_FPREGS+24)(a0))
+ EX(swc1 $f4,(SC_FPREGS+32)(a0))
+ EX(swc1 $f5,(SC_FPREGS+40)(a0))
+ EX(swc1 $f6,(SC_FPREGS+48)(a0))
+ EX(swc1 $f7,(SC_FPREGS+56)(a0))
+ EX(swc1 $f8,(SC_FPREGS+64)(a0))
+ EX(swc1 $f9,(SC_FPREGS+72)(a0))
+ EX(swc1 $f10,(SC_FPREGS+80)(a0))
+ EX(swc1 $f11,(SC_FPREGS+88)(a0))
+ EX(swc1 $f12,(SC_FPREGS+96)(a0))
+ EX(swc1 $f13,(SC_FPREGS+104)(a0))
+ EX(swc1 $f14,(SC_FPREGS+112)(a0))
+ EX(swc1 $f15,(SC_FPREGS+120)(a0))
+ EX(swc1 $f16,(SC_FPREGS+128)(a0))
+ EX(swc1 $f17,(SC_FPREGS+136)(a0))
+ EX(swc1 $f18,(SC_FPREGS+144)(a0))
+ EX(swc1 $f19,(SC_FPREGS+152)(a0))
+ EX(swc1 $f20,(SC_FPREGS+160)(a0))
+ EX(swc1 $f21,(SC_FPREGS+168)(a0))
+ EX(swc1 $f22,(SC_FPREGS+176)(a0))
+ EX(swc1 $f23,(SC_FPREGS+184)(a0))
+ EX(swc1 $f24,(SC_FPREGS+192)(a0))
+ EX(swc1 $f25,(SC_FPREGS+200)(a0))
+ EX(swc1 $f26,(SC_FPREGS+208)(a0))
+ EX(swc1 $f27,(SC_FPREGS+216)(a0))
+ EX(swc1 $f28,(SC_FPREGS+224)(a0))
+ EX(swc1 $f29,(SC_FPREGS+232)(a0))
+ EX(swc1 $f30,(SC_FPREGS+240)(a0))
+ EX(swc1 $f31,(SC_FPREGS+248)(a0))
+ EX(sw t1,(SC_FPC_CSR)(a0))
+ cfc1 t0,$0 # implementation/version
+ jr ra
+ .set nomacro
+ EX(sw t0,(SC_FPC_EIR)(a0))
+ .set macro
+ END(_save_fp_context)
+
+/*
+ * Restore FPU state:
+ * - fp gp registers
+ * - cp1 status/control register
+ *
+ * We base the decision which registers to restore from the signal stack
+ * frame on the current content of c0_status, not on the content of the
+ * stack frame which might have been changed by the user.
+ */
+LEAF(_restore_fp_context)
+ li v0, 0 # assume success
+ EX(lw t0,(SC_FPC_CSR)(a0))
+ EX(lwc1 $f0,(SC_FPREGS+0)(a0))
+ EX(lwc1 $f1,(SC_FPREGS+8)(a0))
+ EX(lwc1 $f2,(SC_FPREGS+16)(a0))
+ EX(lwc1 $f3,(SC_FPREGS+24)(a0))
+ EX(lwc1 $f4,(SC_FPREGS+32)(a0))
+ EX(lwc1 $f5,(SC_FPREGS+40)(a0))
+ EX(lwc1 $f6,(SC_FPREGS+48)(a0))
+ EX(lwc1 $f7,(SC_FPREGS+56)(a0))
+ EX(lwc1 $f8,(SC_FPREGS+64)(a0))
+ EX(lwc1 $f9,(SC_FPREGS+72)(a0))
+ EX(lwc1 $f10,(SC_FPREGS+80)(a0))
+ EX(lwc1 $f11,(SC_FPREGS+88)(a0))
+ EX(lwc1 $f12,(SC_FPREGS+96)(a0))
+ EX(lwc1 $f13,(SC_FPREGS+104)(a0))
+ EX(lwc1 $f14,(SC_FPREGS+112)(a0))
+ EX(lwc1 $f15,(SC_FPREGS+120)(a0))
+ EX(lwc1 $f16,(SC_FPREGS+128)(a0))
+ EX(lwc1 $f17,(SC_FPREGS+136)(a0))
+ EX(lwc1 $f18,(SC_FPREGS+144)(a0))
+ EX(lwc1 $f19,(SC_FPREGS+152)(a0))
+ EX(lwc1 $f20,(SC_FPREGS+160)(a0))
+ EX(lwc1 $f21,(SC_FPREGS+168)(a0))
+ EX(lwc1 $f22,(SC_FPREGS+176)(a0))
+ EX(lwc1 $f23,(SC_FPREGS+184)(a0))
+ EX(lwc1 $f24,(SC_FPREGS+192)(a0))
+ EX(lwc1 $f25,(SC_FPREGS+200)(a0))
+ EX(lwc1 $f26,(SC_FPREGS+208)(a0))
+ EX(lwc1 $f27,(SC_FPREGS+216)(a0))
+ EX(lwc1 $f28,(SC_FPREGS+224)(a0))
+ EX(lwc1 $f29,(SC_FPREGS+232)(a0))
+ EX(lwc1 $f30,(SC_FPREGS+240)(a0))
+ EX(lwc1 $f31,(SC_FPREGS+248)(a0))
+ jr ra
+ ctc1 t0,fcr31
+ END(_restore_fp_context)
+ .set reorder
+
+ .type fault@function
+ .ent fault
+fault: li v0, -EFAULT
+ jr ra
+ .end fault
diff --git a/arch/mips/kernel/r2300_switch.S b/arch/mips/kernel/r2300_switch.S
new file mode 100644
index 0000000..243e7b6
--- /dev/null
+++ b/arch/mips/kernel/r2300_switch.S
@@ -0,0 +1,174 @@
+/*
+ * r2300_switch.S: R2300 specific task switching code.
+ *
+ * Copyright (C) 1994, 1995, 1996, 1999 by Ralf Baechle
+ * Copyright (C) 1994, 1995, 1996 by Andreas Busse
+ *
+ * Multi-cpu abstraction and macros for easier reading:
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ *
+ * Further modifications to make this work:
+ * Copyright (c) 1998-2000 Harald Koerfgen
+ */
+#include <linux/config.h>
+#include <asm/asm.h>
+#include <asm/cachectl.h>
+#include <asm/fpregdef.h>
+#include <asm/mipsregs.h>
+#include <asm/offset.h>
+#include <asm/page.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+#include <asm/thread_info.h>
+
+#include <asm/asmmacro.h>
+
+ .set mips1
+ .align 5
+
+/*
+ * Offset to the current process status flags, the first 32 bytes of the
+ * stack are not used.
+ */
+#define ST_OFF (_THREAD_SIZE - 32 - PT_SIZE + PT_STATUS)
+
+/*
+ * FPU context is saved iff the process has used it's FPU in the current
+ * time slice as indicated by TIF_USEDFPU. In any case, the CU1 bit for user
+ * space STATUS register should be 0, so that a process *always* starts its
+ * userland with FPU disabled after each context switch.
+ *
+ * FPU will be enabled as soon as the process accesses FPU again, through
+ * do_cpu() trap.
+ */
+
+/*
+ * task_struct *resume(task_struct *prev, task_struct *next,
+ * struct thread_info *next_ti) )
+ */
+LEAF(resume)
+#ifndef CONFIG_CPU_HAS_LLSC
+ sw zero, ll_bit
+#endif
+ mfc0 t1, CP0_STATUS
+ sw t1, THREAD_STATUS(a0)
+ cpu_save_nonscratch a0
+ sw ra, THREAD_REG31(a0)
+
+ /*
+ * check if we need to save FPU registers
+ */
+ lw t3, TASK_THREAD_INFO(a0)
+ lw t0, TI_FLAGS(t3)
+ li t1, _TIF_USEDFPU
+ and t2, t0, t1
+ beqz t2, 1f
+ nor t1, zero, t1
+
+ and t0, t0, t1
+ sw t0, TI_FLAGS(t3)
+
+ /*
+ * clear saved user stack CU1 bit
+ */
+ lw t0, ST_OFF(t3)
+ li t1, ~ST0_CU1
+ and t0, t0, t1
+ sw t0, ST_OFF(t3)
+
+ fpu_save_single a0, t0 # clobbers t0
+
+1:
+ /*
+ * The order of restoring the registers takes care of the race
+ * updating $28, $29 and kernelsp without disabling ints.
+ */
+ move $28, a2
+ cpu_restore_nonscratch a1
+
+ addiu t1, $28, _THREAD_SIZE - 32
+ sw t1, kernelsp
+
+ mfc0 t1, CP0_STATUS /* Do we really need this? */
+ li a3, 0xff01
+ and t1, a3
+ lw a2, THREAD_STATUS(a1)
+ nor a3, $0, a3
+ and a2, a3
+ or a2, t1
+ mtc0 a2, CP0_STATUS
+ move v0, a0
+ jr ra
+ END(resume)
+
+/*
+ * Save a thread's fp context.
+ */
+LEAF(_save_fp)
+ fpu_save_single a0, t1 # clobbers t1
+ jr ra
+ END(_save_fp)
+
+/*
+ * Restore a thread's fp context.
+ */
+LEAF(_restore_fp)
+ fpu_restore_single a0, t1 # clobbers t1
+ jr ra
+ END(_restore_fp)
+
+/*
+ * Load the FPU with signalling NANS. This bit pattern we're using has
+ * the property that no matter whether considered as single or as double
+ * precision represents signaling NANS.
+ *
+ * We initialize fcr31 to rounding to nearest, no exceptions.
+ */
+
+#define FPU_DEFAULT 0x00000000
+
+LEAF(_init_fpu)
+ mfc0 t0, CP0_STATUS
+ li t1, ST0_CU1
+ or t0, t1
+ mtc0 t0, CP0_STATUS
+
+ li t1, FPU_DEFAULT
+ ctc1 t1, fcr31
+
+ li t0, -1
+
+ mtc1 t0, $f0
+ mtc1 t0, $f1
+ mtc1 t0, $f2
+ mtc1 t0, $f3
+ mtc1 t0, $f4
+ mtc1 t0, $f5
+ mtc1 t0, $f6
+ mtc1 t0, $f7
+ mtc1 t0, $f8
+ mtc1 t0, $f9
+ mtc1 t0, $f10
+ mtc1 t0, $f11
+ mtc1 t0, $f12
+ mtc1 t0, $f13
+ mtc1 t0, $f14
+ mtc1 t0, $f15
+ mtc1 t0, $f16
+ mtc1 t0, $f17
+ mtc1 t0, $f18
+ mtc1 t0, $f19
+ mtc1 t0, $f20
+ mtc1 t0, $f21
+ mtc1 t0, $f22
+ mtc1 t0, $f23
+ mtc1 t0, $f24
+ mtc1 t0, $f25
+ mtc1 t0, $f26
+ mtc1 t0, $f27
+ mtc1 t0, $f28
+ mtc1 t0, $f29
+ mtc1 t0, $f30
+ mtc1 t0, $f31
+ jr ra
+ END(_init_fpu)
diff --git a/arch/mips/kernel/r4k_fpu.S b/arch/mips/kernel/r4k_fpu.S
new file mode 100644
index 0000000..ebb643d
--- /dev/null
+++ b/arch/mips/kernel/r4k_fpu.S
@@ -0,0 +1,191 @@
+/*
+ * 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) 1996, 98, 99, 2000, 01 Ralf Baechle
+ *
+ * Multi-arch abstraction and asm macros for easier reading:
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ *
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2000 MIPS Technologies, Inc.
+ * Copyright (C) 1999, 2001 Silicon Graphics, Inc.
+ */
+#include <linux/config.h>
+#include <asm/asm.h>
+#include <asm/errno.h>
+#include <asm/fpregdef.h>
+#include <asm/mipsregs.h>
+#include <asm/offset.h>
+#include <asm/regdef.h>
+
+ .macro EX insn, reg, src
+ .set push
+ .set nomacro
+.ex\@: \insn \reg, \src
+ .set pop
+ .section __ex_table,"a"
+ PTR .ex\@, fault
+ .previous
+ .endm
+
+ .set noreorder
+ .set mips3
+ /* Save floating point context */
+LEAF(_save_fp_context)
+ cfc1 t1, fcr31
+
+#ifdef CONFIG_MIPS64
+ /* Store the 16 odd double precision registers */
+ EX sdc1 $f1, SC_FPREGS+8(a0)
+ EX sdc1 $f3, SC_FPREGS+24(a0)
+ EX sdc1 $f5, SC_FPREGS+40(a0)
+ EX sdc1 $f7, SC_FPREGS+56(a0)
+ EX sdc1 $f9, SC_FPREGS+72(a0)
+ EX sdc1 $f11, SC_FPREGS+88(a0)
+ EX sdc1 $f13, SC_FPREGS+104(a0)
+ EX sdc1 $f15, SC_FPREGS+120(a0)
+ EX sdc1 $f17, SC_FPREGS+136(a0)
+ EX sdc1 $f19, SC_FPREGS+152(a0)
+ EX sdc1 $f21, SC_FPREGS+168(a0)
+ EX sdc1 $f23, SC_FPREGS+184(a0)
+ EX sdc1 $f25, SC_FPREGS+200(a0)
+ EX sdc1 $f27, SC_FPREGS+216(a0)
+ EX sdc1 $f29, SC_FPREGS+232(a0)
+ EX sdc1 $f31, SC_FPREGS+248(a0)
+#endif
+
+ /* Store the 16 even double precision registers */
+ EX sdc1 $f0, SC_FPREGS+0(a0)
+ EX sdc1 $f2, SC_FPREGS+16(a0)
+ EX sdc1 $f4, SC_FPREGS+32(a0)
+ EX sdc1 $f6, SC_FPREGS+48(a0)
+ EX sdc1 $f8, SC_FPREGS+64(a0)
+ EX sdc1 $f10, SC_FPREGS+80(a0)
+ EX sdc1 $f12, SC_FPREGS+96(a0)
+ EX sdc1 $f14, SC_FPREGS+112(a0)
+ EX sdc1 $f16, SC_FPREGS+128(a0)
+ EX sdc1 $f18, SC_FPREGS+144(a0)
+ EX sdc1 $f20, SC_FPREGS+160(a0)
+ EX sdc1 $f22, SC_FPREGS+176(a0)
+ EX sdc1 $f24, SC_FPREGS+192(a0)
+ EX sdc1 $f26, SC_FPREGS+208(a0)
+ EX sdc1 $f28, SC_FPREGS+224(a0)
+ EX sdc1 $f30, SC_FPREGS+240(a0)
+ EX sw t1, SC_FPC_CSR(a0)
+ cfc1 t0, $0 # implementation/version
+ EX sw t0, SC_FPC_EIR(a0)
+
+ jr ra
+ li v0, 0 # success
+ END(_save_fp_context)
+
+#ifdef CONFIG_MIPS32_COMPAT
+ /* Save 32-bit process floating point context */
+LEAF(_save_fp_context32)
+ cfc1 t1, fcr31
+
+ EX sdc1 $f0, SC32_FPREGS+0(a0)
+ EX sdc1 $f2, SC32_FPREGS+16(a0)
+ EX sdc1 $f4, SC32_FPREGS+32(a0)
+ EX sdc1 $f6, SC32_FPREGS+48(a0)
+ EX sdc1 $f8, SC32_FPREGS+64(a0)
+ EX sdc1 $f10, SC32_FPREGS+80(a0)
+ EX sdc1 $f12, SC32_FPREGS+96(a0)
+ EX sdc1 $f14, SC32_FPREGS+112(a0)
+ EX sdc1 $f16, SC32_FPREGS+128(a0)
+ EX sdc1 $f18, SC32_FPREGS+144(a0)
+ EX sdc1 $f20, SC32_FPREGS+160(a0)
+ EX sdc1 $f22, SC32_FPREGS+176(a0)
+ EX sdc1 $f24, SC32_FPREGS+192(a0)
+ EX sdc1 $f26, SC32_FPREGS+208(a0)
+ EX sdc1 $f28, SC32_FPREGS+224(a0)
+ EX sdc1 $f30, SC32_FPREGS+240(a0)
+ EX sw t1, SC32_FPC_CSR(a0)
+ cfc1 t0, $0 # implementation/version
+ EX sw t0, SC32_FPC_EIR(a0)
+
+ jr ra
+ li v0, 0 # success
+ END(_save_fp_context32)
+#endif
+
+/*
+ * Restore FPU state:
+ * - fp gp registers
+ * - cp1 status/control register
+ */
+LEAF(_restore_fp_context)
+ EX lw t0, SC_FPC_CSR(a0)
+#ifdef CONFIG_MIPS64
+ EX ldc1 $f1, SC_FPREGS+8(a0)
+ EX ldc1 $f3, SC_FPREGS+24(a0)
+ EX ldc1 $f5, SC_FPREGS+40(a0)
+ EX ldc1 $f7, SC_FPREGS+56(a0)
+ EX ldc1 $f9, SC_FPREGS+72(a0)
+ EX ldc1 $f11, SC_FPREGS+88(a0)
+ EX ldc1 $f13, SC_FPREGS+104(a0)
+ EX ldc1 $f15, SC_FPREGS+120(a0)
+ EX ldc1 $f17, SC_FPREGS+136(a0)
+ EX ldc1 $f19, SC_FPREGS+152(a0)
+ EX ldc1 $f21, SC_FPREGS+168(a0)
+ EX ldc1 $f23, SC_FPREGS+184(a0)
+ EX ldc1 $f25, SC_FPREGS+200(a0)
+ EX ldc1 $f27, SC_FPREGS+216(a0)
+ EX ldc1 $f29, SC_FPREGS+232(a0)
+ EX ldc1 $f31, SC_FPREGS+248(a0)
+#endif
+ EX ldc1 $f0, SC_FPREGS+0(a0)
+ EX ldc1 $f2, SC_FPREGS+16(a0)
+ EX ldc1 $f4, SC_FPREGS+32(a0)
+ EX ldc1 $f6, SC_FPREGS+48(a0)
+ EX ldc1 $f8, SC_FPREGS+64(a0)
+ EX ldc1 $f10, SC_FPREGS+80(a0)
+ EX ldc1 $f12, SC_FPREGS+96(a0)
+ EX ldc1 $f14, SC_FPREGS+112(a0)
+ EX ldc1 $f16, SC_FPREGS+128(a0)
+ EX ldc1 $f18, SC_FPREGS+144(a0)
+ EX ldc1 $f20, SC_FPREGS+160(a0)
+ EX ldc1 $f22, SC_FPREGS+176(a0)
+ EX ldc1 $f24, SC_FPREGS+192(a0)
+ EX ldc1 $f26, SC_FPREGS+208(a0)
+ EX ldc1 $f28, SC_FPREGS+224(a0)
+ EX ldc1 $f30, SC_FPREGS+240(a0)
+ ctc1 t0, fcr31
+ jr ra
+ li v0, 0 # success
+ END(_restore_fp_context)
+
+#ifdef CONFIG_MIPS32_COMPAT
+LEAF(_restore_fp_context32)
+ /* Restore an o32 sigcontext. */
+ EX lw t0, SC32_FPC_CSR(a0)
+ EX ldc1 $f0, SC32_FPREGS+0(a0)
+ EX ldc1 $f2, SC32_FPREGS+16(a0)
+ EX ldc1 $f4, SC32_FPREGS+32(a0)
+ EX ldc1 $f6, SC32_FPREGS+48(a0)
+ EX ldc1 $f8, SC32_FPREGS+64(a0)
+ EX ldc1 $f10, SC32_FPREGS+80(a0)
+ EX ldc1 $f12, SC32_FPREGS+96(a0)
+ EX ldc1 $f14, SC32_FPREGS+112(a0)
+ EX ldc1 $f16, SC32_FPREGS+128(a0)
+ EX ldc1 $f18, SC32_FPREGS+144(a0)
+ EX ldc1 $f20, SC32_FPREGS+160(a0)
+ EX ldc1 $f22, SC32_FPREGS+176(a0)
+ EX ldc1 $f24, SC32_FPREGS+192(a0)
+ EX ldc1 $f26, SC32_FPREGS+208(a0)
+ EX ldc1 $f28, SC32_FPREGS+224(a0)
+ EX ldc1 $f30, SC32_FPREGS+240(a0)
+ ctc1 t0, fcr31
+ jr ra
+ li v0, 0 # success
+ END(_restore_fp_context32)
+ .set reorder
+#endif
+
+ .type fault@function
+ .ent fault
+fault: li v0, -EFAULT # failure
+ jr ra
+ .end fault
diff --git a/arch/mips/kernel/r4k_switch.S b/arch/mips/kernel/r4k_switch.S
new file mode 100644
index 0000000..1fc3b2e
--- /dev/null
+++ b/arch/mips/kernel/r4k_switch.S
@@ -0,0 +1,221 @@
+/*
+ * 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) 1994, 1995, 1996, 1998, 1999, 2002, 2003 Ralf Baechle
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ * Copyright (C) 1994, 1995, 1996, by Andreas Busse
+ * Copyright (C) 1999 Silicon Graphics, Inc.
+ * Copyright (C) 2000 MIPS Technologies, Inc.
+ * written by Carsten Langgaard, carstenl@mips.com
+ */
+#include <linux/config.h>
+#include <asm/asm.h>
+#include <asm/cachectl.h>
+#include <asm/fpregdef.h>
+#include <asm/mipsregs.h>
+#include <asm/offset.h>
+#include <asm/page.h>
+#include <asm/pgtable-bits.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+#include <asm/thread_info.h>
+
+#include <asm/asmmacro.h>
+
+/*
+ * Offset to the current process status flags, the first 32 bytes of the
+ * stack are not used.
+ */
+#define ST_OFF (_THREAD_SIZE - 32 - PT_SIZE + PT_STATUS)
+
+/*
+ * FPU context is saved iff the process has used it's FPU in the current
+ * time slice as indicated by _TIF_USEDFPU. In any case, the CU1 bit for user
+ * space STATUS register should be 0, so that a process *always* starts its
+ * userland with FPU disabled after each context switch.
+ *
+ * FPU will be enabled as soon as the process accesses FPU again, through
+ * do_cpu() trap.
+ */
+
+/*
+ * task_struct *resume(task_struct *prev, task_struct *next,
+ * struct thread_info *next_ti)
+ */
+ .align 5
+ LEAF(resume)
+#ifndef CONFIG_CPU_HAS_LLSC
+ sw zero, ll_bit
+#endif
+ mfc0 t1, CP0_STATUS
+ LONG_S t1, THREAD_STATUS(a0)
+ cpu_save_nonscratch a0
+ LONG_S ra, THREAD_REG31(a0)
+
+ /*
+ * check if we need to save FPU registers
+ */
+ PTR_L t3, TASK_THREAD_INFO(a0)
+ LONG_L t0, TI_FLAGS(t3)
+ li t1, _TIF_USEDFPU
+ and t2, t0, t1
+ beqz t2, 1f
+ nor t1, zero, t1
+
+ and t0, t0, t1
+ LONG_S t0, TI_FLAGS(t3)
+
+ /*
+ * clear saved user stack CU1 bit
+ */
+ LONG_L t0, ST_OFF(t3)
+ li t1, ~ST0_CU1
+ and t0, t0, t1
+ LONG_S t0, ST_OFF(t3)
+
+ fpu_save_double a0 t1 t0 t2 # c0_status passed in t1
+ # clobbers t0 and t2
+1:
+
+ /*
+ * The order of restoring the registers takes care of the race
+ * updating $28, $29 and kernelsp without disabling ints.
+ */
+ move $28, a2
+ cpu_restore_nonscratch a1
+
+ PTR_ADDIU t0, $28, _THREAD_SIZE - 32
+ set_saved_sp t0, t1, t2
+
+ mfc0 t1, CP0_STATUS /* Do we really need this? */
+ li a3, 0xff01
+ and t1, a3
+ LONG_L a2, THREAD_STATUS(a1)
+ nor a3, $0, a3
+ and a2, a3
+ or a2, t1
+ mtc0 a2, CP0_STATUS
+ move v0, a0
+ jr ra
+ END(resume)
+
+/*
+ * Save a thread's fp context.
+ */
+LEAF(_save_fp)
+#ifdef CONFIG_MIPS64
+ mfc0 t1, CP0_STATUS
+#endif
+ fpu_save_double a0 t1 t0 t2 # clobbers t1
+ jr ra
+ END(_save_fp)
+
+/*
+ * Restore a thread's fp context.
+ */
+LEAF(_restore_fp)
+ fpu_restore_double a0, t1 # clobbers t1
+ jr ra
+ END(_restore_fp)
+
+/*
+ * Load the FPU with signalling NANS. This bit pattern we're using has
+ * the property that no matter whether considered as single or as double
+ * precision represents signaling NANS.
+ *
+ * We initialize fcr31 to rounding to nearest, no exceptions.
+ */
+
+#define FPU_DEFAULT 0x00000000
+
+LEAF(_init_fpu)
+ mfc0 t0, CP0_STATUS
+ li t1, ST0_CU1
+ or t0, t1
+ mtc0 t0, CP0_STATUS
+ fpu_enable_hazard
+
+ li t1, FPU_DEFAULT
+ ctc1 t1, fcr31
+
+ li t1, -1 # SNaN
+
+#ifdef CONFIG_MIPS64
+ sll t0, t0, 5
+ bgez t0, 1f # 16 / 32 register mode?
+
+ dmtc1 t1, $f1
+ dmtc1 t1, $f3
+ dmtc1 t1, $f5
+ dmtc1 t1, $f7
+ dmtc1 t1, $f9
+ dmtc1 t1, $f11
+ dmtc1 t1, $f13
+ dmtc1 t1, $f15
+ dmtc1 t1, $f17
+ dmtc1 t1, $f19
+ dmtc1 t1, $f21
+ dmtc1 t1, $f23
+ dmtc1 t1, $f25
+ dmtc1 t1, $f27
+ dmtc1 t1, $f29
+ dmtc1 t1, $f31
+1:
+#endif
+
+#ifdef CONFIG_CPU_MIPS32
+ mtc1 t1, $f0
+ mtc1 t1, $f1
+ mtc1 t1, $f2
+ mtc1 t1, $f3
+ mtc1 t1, $f4
+ mtc1 t1, $f5
+ mtc1 t1, $f6
+ mtc1 t1, $f7
+ mtc1 t1, $f8
+ mtc1 t1, $f9
+ mtc1 t1, $f10
+ mtc1 t1, $f11
+ mtc1 t1, $f12
+ mtc1 t1, $f13
+ mtc1 t1, $f14
+ mtc1 t1, $f15
+ mtc1 t1, $f16
+ mtc1 t1, $f17
+ mtc1 t1, $f18
+ mtc1 t1, $f19
+ mtc1 t1, $f20
+ mtc1 t1, $f21
+ mtc1 t1, $f22
+ mtc1 t1, $f23
+ mtc1 t1, $f24
+ mtc1 t1, $f25
+ mtc1 t1, $f26
+ mtc1 t1, $f27
+ mtc1 t1, $f28
+ mtc1 t1, $f29
+ mtc1 t1, $f30
+ mtc1 t1, $f31
+#else
+ .set mips3
+ dmtc1 t1, $f0
+ dmtc1 t1, $f2
+ dmtc1 t1, $f4
+ dmtc1 t1, $f6
+ dmtc1 t1, $f8
+ dmtc1 t1, $f10
+ dmtc1 t1, $f12
+ dmtc1 t1, $f14
+ dmtc1 t1, $f16
+ dmtc1 t1, $f18
+ dmtc1 t1, $f20
+ dmtc1 t1, $f22
+ dmtc1 t1, $f24
+ dmtc1 t1, $f26
+ dmtc1 t1, $f28
+ dmtc1 t1, $f30
+#endif
+ jr ra
+ END(_init_fpu)
diff --git a/arch/mips/kernel/r6000_fpu.S b/arch/mips/kernel/r6000_fpu.S
new file mode 100644
index 0000000..d8d3b13
--- /dev/null
+++ b/arch/mips/kernel/r6000_fpu.S
@@ -0,0 +1,87 @@
+/*
+ * r6000_fpu.S: Save/restore floating point context for signal handlers.
+ *
+ * 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) 1996 by Ralf Baechle
+ *
+ * Multi-arch abstraction and asm macros for easier reading:
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+#include <asm/asm.h>
+#include <asm/fpregdef.h>
+#include <asm/mipsregs.h>
+#include <asm/offset.h>
+#include <asm/regdef.h>
+
+ .set noreorder
+ .set mips2
+ /* Save floating point context */
+ LEAF(_save_fp_context)
+ mfc0 t0,CP0_STATUS
+ sll t0,t0,2
+ bgez t0,1f
+ nop
+
+ cfc1 t1,fcr31
+ /* Store the 16 double precision registers */
+ sdc1 $f0,(SC_FPREGS+0)(a0)
+ sdc1 $f2,(SC_FPREGS+16)(a0)
+ sdc1 $f4,(SC_FPREGS+32)(a0)
+ sdc1 $f6,(SC_FPREGS+48)(a0)
+ sdc1 $f8,(SC_FPREGS+64)(a0)
+ sdc1 $f10,(SC_FPREGS+80)(a0)
+ sdc1 $f12,(SC_FPREGS+96)(a0)
+ sdc1 $f14,(SC_FPREGS+112)(a0)
+ sdc1 $f16,(SC_FPREGS+128)(a0)
+ sdc1 $f18,(SC_FPREGS+144)(a0)
+ sdc1 $f20,(SC_FPREGS+160)(a0)
+ sdc1 $f22,(SC_FPREGS+176)(a0)
+ sdc1 $f24,(SC_FPREGS+192)(a0)
+ sdc1 $f26,(SC_FPREGS+208)(a0)
+ sdc1 $f28,(SC_FPREGS+224)(a0)
+ sdc1 $f30,(SC_FPREGS+240)(a0)
+ jr ra
+ sw t0,SC_FPC_CSR(a0)
+1: jr ra
+ nop
+ END(_save_fp_context)
+
+/* Restore FPU state:
+ * - fp gp registers
+ * - cp1 status/control register
+ *
+ * We base the decision which registers to restore from the signal stack
+ * frame on the current content of c0_status, not on the content of the
+ * stack frame which might have been changed by the user.
+ */
+ LEAF(_restore_fp_context)
+ mfc0 t0,CP0_STATUS
+ sll t0,t0,2
+
+ bgez t0,1f
+ lw t0,SC_FPC_CSR(a0)
+ /* Restore the 16 double precision registers */
+ ldc1 $f0,(SC_FPREGS+0)(a0)
+ ldc1 $f2,(SC_FPREGS+16)(a0)
+ ldc1 $f4,(SC_FPREGS+32)(a0)
+ ldc1 $f6,(SC_FPREGS+48)(a0)
+ ldc1 $f8,(SC_FPREGS+64)(a0)
+ ldc1 $f10,(SC_FPREGS+80)(a0)
+ ldc1 $f12,(SC_FPREGS+96)(a0)
+ ldc1 $f14,(SC_FPREGS+112)(a0)
+ ldc1 $f16,(SC_FPREGS+128)(a0)
+ ldc1 $f18,(SC_FPREGS+144)(a0)
+ ldc1 $f20,(SC_FPREGS+160)(a0)
+ ldc1 $f22,(SC_FPREGS+176)(a0)
+ ldc1 $f24,(SC_FPREGS+192)(a0)
+ ldc1 $f26,(SC_FPREGS+208)(a0)
+ ldc1 $f28,(SC_FPREGS+224)(a0)
+ ldc1 $f30,(SC_FPREGS+240)(a0)
+ jr ra
+ ctc1 t0,fcr31
+1: jr ra
+ nop
+ END(_restore_fp_context)
diff --git a/arch/mips/kernel/reset.c b/arch/mips/kernel/reset.c
new file mode 100644
index 0000000..7e0a982
--- /dev/null
+++ b/arch/mips/kernel/reset.c
@@ -0,0 +1,43 @@
+/*
+ * 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) 2001 by Ralf Baechle
+ * Copyright (C) 2001 MIPS Technologies, Inc.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/reboot.h>
+#include <asm/reboot.h>
+
+/*
+ * Urgs ... Too many MIPS machines to handle this in a generic way.
+ * So handle all using function pointers to machine specific
+ * functions.
+ */
+void (*_machine_restart)(char *command);
+void (*_machine_halt)(void);
+void (*_machine_power_off)(void);
+
+void machine_restart(char *command)
+{
+ _machine_restart(command);
+}
+
+EXPORT_SYMBOL(machine_restart);
+
+void machine_halt(void)
+{
+ _machine_halt();
+}
+
+EXPORT_SYMBOL(machine_halt);
+
+void machine_power_off(void)
+{
+ _machine_power_off();
+}
+
+EXPORT_SYMBOL(machine_power_off);
diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S
new file mode 100644
index 0000000..344f2e2
--- /dev/null
+++ b/arch/mips/kernel/scall32-o32.S
@@ -0,0 +1,641 @@
+/*
+ * 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, 96, 97, 98, 99, 2000, 01, 02 by Ralf Baechle
+ * Copyright (C) 2001 MIPS Technologies, Inc.
+ * Copyright (C) 2004 Thiemo Seufer
+ */
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <asm/asm.h>
+#include <asm/asmmacro.h>
+#include <asm/mipsregs.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+#include <asm/isadep.h>
+#include <asm/sysmips.h>
+#include <asm/thread_info.h>
+#include <asm/unistd.h>
+#include <asm/war.h>
+#include <asm/offset.h>
+
+/* Highest syscall used of any syscall flavour */
+#define MAX_SYSCALL_NO __NR_O32_Linux + __NR_O32_Linux_syscalls
+
+ .align 5
+NESTED(handle_sys, PT_SIZE, sp)
+ .set noat
+ SAVE_SOME
+ STI
+ .set at
+
+ lw t1, PT_EPC(sp) # skip syscall on return
+
+#if defined(CONFIG_BINFMT_IRIX)
+ sltiu t0, v0, MAX_SYSCALL_NO + 1 # check syscall number
+#else
+ subu v0, v0, __NR_O32_Linux # check syscall number
+ sltiu t0, v0, __NR_O32_Linux_syscalls + 1
+#endif
+ addiu t1, 4 # skip to next instruction
+ sw t1, PT_EPC(sp)
+ beqz t0, illegal_syscall
+
+ sll t0, v0, 3
+ la t1, sys_call_table
+ addu t1, t0
+ lw t2, (t1) # syscall routine
+ lw t3, 4(t1) # >= 0 if we need stack arguments
+ beqz t2, illegal_syscall
+
+ sw a3, PT_R26(sp) # save a3 for syscall restarting
+ bgez t3, stackargs
+
+stack_done:
+ lw t0, TI_FLAGS($28) # syscall tracing enabled?
+ li t1, _TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT
+ and t0, t1
+ bnez t0, syscall_trace_entry # -> yes
+
+ jalr t2 # Do The Real Thing (TM)
+
+ li t0, -EMAXERRNO - 1 # error?
+ sltu t0, t0, v0
+ sw t0, PT_R7(sp) # set error flag
+ beqz t0, 1f
+
+ negu v0 # error
+ sw v0, PT_R0(sp) # set flag for syscall
+ # restarting
+1: sw v0, PT_R2(sp) # result
+
+o32_syscall_exit:
+ local_irq_disable # make sure need_resched and
+ # signals dont change between
+ # sampling and return
+ lw a2, TI_FLAGS($28) # current->work
+ li t0, _TIF_ALLWORK_MASK
+ and t0, a2
+ bnez t0, o32_syscall_exit_work
+
+ j restore_partial
+
+o32_syscall_exit_work:
+ j syscall_exit_work_partial
+
+/* ------------------------------------------------------------------------ */
+
+syscall_trace_entry:
+ SAVE_STATIC
+ move s0, t2
+ move a0, sp
+ li a1, 0
+ jal do_syscall_trace
+
+ lw a0, PT_R4(sp) # Restore argument registers
+ lw a1, PT_R5(sp)
+ lw a2, PT_R6(sp)
+ lw a3, PT_R7(sp)
+ jalr s0
+
+ li t0, -EMAXERRNO - 1 # error?
+ sltu t0, t0, v0
+ sw t0, PT_R7(sp) # set error flag
+ beqz t0, 1f
+
+ negu v0 # error
+ sw v0, PT_R0(sp) # set flag for syscall
+ # restarting
+1: sw v0, PT_R2(sp) # result
+
+ j syscall_exit
+
+/* ------------------------------------------------------------------------ */
+
+ /*
+ * More than four arguments. Try to deal with it by copying the
+ * stack arguments from the user stack to the kernel stack.
+ * This Sucks (TM).
+ */
+stackargs:
+ lw t0, PT_R29(sp) # get old user stack pointer
+
+ /*
+ * We intentionally keep the kernel stack a little below the top of
+ * userspace so we don't have to do a slower byte accurate check here.
+ */
+ lw t5, TI_ADDR_LIMIT($28)
+ addu t4, t0, 32
+ and t5, t4
+ bltz t5, bad_stack # -> sp is bad
+
+ /* Ok, copy the args from the luser stack to the kernel stack.
+ * t3 is the precomputed number of instruction bytes needed to
+ * load or store arguments 6-8.
+ */
+
+ la t1, 5f # load up to 3 arguments
+ subu t1, t3
+1: lw t5, 16(t0) # argument #5 from usp
+ .set push
+ .set noreorder
+ .set nomacro
+ jr t1
+ addiu t1, 6f - 5f
+
+2: lw t8, 28(t0) # argument #8 from usp
+3: lw t7, 24(t0) # argument #7 from usp
+4: lw t6, 20(t0) # argument #6 from usp
+5: jr t1
+ sw t5, 16(sp) # argument #5 to ksp
+
+ sw t8, 28(sp) # argument #8 to ksp
+ sw t7, 24(sp) # argument #7 to ksp
+ sw t6, 20(sp) # argument #6 to ksp
+6: j stack_done # go back
+ nop
+ .set pop
+
+ .section __ex_table,"a"
+ PTR 1b,bad_stack
+ PTR 2b,bad_stack
+ PTR 3b,bad_stack
+ PTR 4b,bad_stack
+ .previous
+
+ /*
+ * The stackpointer for a call with more than 4 arguments is bad.
+ * We probably should handle this case a bit more drastic.
+ */
+bad_stack:
+ negu v0 # error
+ sw v0, PT_R0(sp)
+ sw v0, PT_R2(sp)
+ li t0, 1 # set error flag
+ sw t0, PT_R7(sp)
+ j o32_syscall_exit
+
+ /*
+ * The system call does not exist in this kernel
+ */
+illegal_syscall:
+ li v0, -ENOSYS # error
+ sw v0, PT_R2(sp)
+ li t0, 1 # set error flag
+ sw t0, PT_R7(sp)
+ j o32_syscall_exit
+ END(handle_sys)
+
+ LEAF(mips_atomic_set)
+ andi v0, a1, 3 # must be word aligned
+ bnez v0, bad_alignment
+
+ lw v1, TI_ADDR_LIMIT($28) # in legal address range?
+ addiu a0, a1, 4
+ or a0, a0, a1
+ and a0, a0, v1
+ bltz a0, bad_address
+
+#ifdef CONFIG_CPU_HAS_LLSC
+ /* Ok, this is the ll/sc case. World is sane :-) */
+1: ll v0, (a1)
+ move a0, a2
+2: sc a0, (a1)
+#if R10000_LLSC_WAR
+ beqzl a0, 1b
+#else
+ beqz a0, 1b
+#endif
+
+ .section __ex_table,"a"
+ PTR 1b, bad_stack
+ PTR 2b, bad_stack
+ .previous
+#else
+ sw a1, 16(sp)
+ sw a2, 20(sp)
+
+ move a0, sp
+ move a2, a1
+ li a1, 1
+ jal do_page_fault
+
+ lw a1, 16(sp)
+ lw a2, 20(sp)
+
+ /*
+ * At this point the page should be readable and writable unless
+ * there was no more memory available.
+ */
+1: lw v0, (a1)
+2: sw a2, (a1)
+
+ .section __ex_table,"a"
+ PTR 1b, no_mem
+ PTR 2b, no_mem
+ .previous
+#endif
+
+ sw zero, PT_R7(sp) # success
+ sw v0, PT_R2(sp) # result
+
+ /* Success, so skip usual error handling garbage. */
+ lw a2, TI_FLAGS($28) # syscall tracing enabled?
+ li t0, _TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT
+ and t0, a2, t0
+ bnez t0, 1f
+
+ j o32_syscall_exit
+
+1: SAVE_STATIC
+ move a0, sp
+ li a1, 1
+ jal do_syscall_trace
+ j syscall_exit
+
+no_mem: li v0, -ENOMEM
+ jr ra
+
+bad_address:
+ li v0, -EFAULT
+ jr ra
+
+bad_alignment:
+ li v0, -EINVAL
+ jr ra
+ END(mips_atomic_set)
+
+ LEAF(sys_sysmips)
+ beq a0, MIPS_ATOMIC_SET, mips_atomic_set
+ j _sys_sysmips
+ END(sys_sysmips)
+
+ LEAF(sys_syscall)
+#if defined(CONFIG_BINFMT_IRIX)
+ sltiu v0, a0, MAX_SYSCALL_NO + 1 # check syscall number
+#else
+ subu t0, a0, __NR_O32_Linux # check syscall number
+ sltiu v0, t0, __NR_O32_Linux_syscalls + 1
+#endif
+ sll t1, t0, 3
+ beqz v0, einval
+
+ lw t2, sys_call_table(t1) # syscall routine
+
+#if defined(CONFIG_BINFMT_IRIX)
+ li v1, 4000 # nr of sys_syscall
+#else
+ li v1, 4000 - __NR_O32_Linux # index of sys_syscall
+#endif
+ beq t0, v1, einval # do not recurse
+
+ /* Some syscalls like execve get their arguments from struct pt_regs
+ and claim zero arguments in the syscall table. Thus we have to
+ assume the worst case and shuffle around all potential arguments.
+ If you want performance, don't use indirect syscalls. */
+
+ move a0, a1 # shift argument registers
+ move a1, a2
+ move a2, a3
+ lw a3, 16(sp)
+ lw t4, 20(sp)
+ lw t5, 24(sp)
+ lw t6, 28(sp)
+ sw t4, 16(sp)
+ sw t5, 20(sp)
+ sw t6, 24(sp)
+ sw a0, PT_R4(sp) # .. and push back a0 - a3, some
+ sw a1, PT_R5(sp) # syscalls expect them there
+ sw a2, PT_R6(sp)
+ sw a3, PT_R7(sp)
+ sw a3, PT_R26(sp) # update a3 for syscall restarting
+ jr t2
+ /* Unreached */
+
+einval: li v0, -EINVAL
+ jr ra
+ END(sys_syscall)
+
+ .macro fifty ptr, nargs, from=1, to=50
+ sys \ptr \nargs
+ .if \to-\from
+ fifty \ptr,\nargs,"(\from+1)",\to
+ .endif
+ .endm
+
+ .macro mille ptr, nargs, from=1, to=20
+ fifty \ptr,\nargs
+ .if \to-\from
+ mille \ptr,\nargs,"(\from+1)",\to
+ .endif
+ .endm
+
+ .macro syscalltable
+#if defined(CONFIG_BINFMT_IRIX)
+ mille sys_ni_syscall 0 /* 0 - 999 SVR4 flavour */
+ mille sys_ni_syscall 0 /* 1000 - 1999 32-bit IRIX */
+ mille sys_ni_syscall 0 /* 2000 - 2999 BSD43 flavour */
+ mille sys_ni_syscall 0 /* 3000 - 3999 POSIX flavour */
+#endif
+
+ sys sys_syscall 8 /* 4000 */
+ sys sys_exit 1
+ sys sys_fork 0
+ sys sys_read 3
+ sys sys_write 3
+ sys sys_open 3 /* 4005 */
+ sys sys_close 1
+ sys sys_waitpid 3
+ sys sys_creat 2
+ sys sys_link 2
+ sys sys_unlink 1 /* 4010 */
+ sys sys_execve 0
+ sys sys_chdir 1
+ sys sys_time 1
+ sys sys_mknod 3
+ sys sys_chmod 2 /* 4015 */
+ sys sys_lchown 3
+ sys sys_ni_syscall 0
+ sys sys_ni_syscall 0 /* was sys_stat */
+ sys sys_lseek 3
+ sys sys_getpid 0 /* 4020 */
+ sys sys_mount 5
+ sys sys_oldumount 1
+ sys sys_setuid 1
+ sys sys_getuid 0
+ sys sys_stime 1 /* 4025 */
+ sys sys_ptrace 4
+ sys sys_alarm 1
+ sys sys_ni_syscall 0 /* was sys_fstat */
+ sys sys_pause 0
+ sys sys_utime 2 /* 4030 */
+ sys sys_ni_syscall 0
+ sys sys_ni_syscall 0
+ sys sys_access 2
+ sys sys_nice 1
+ sys sys_ni_syscall 0 /* 4035 */
+ sys sys_sync 0
+ sys sys_kill 2
+ sys sys_rename 2
+ sys sys_mkdir 2
+ sys sys_rmdir 1 /* 4040 */
+ sys sys_dup 1
+ sys sys_pipe 0
+ sys sys_times 1
+ sys sys_ni_syscall 0
+ sys sys_brk 1 /* 4045 */
+ sys sys_setgid 1
+ sys sys_getgid 0
+ sys sys_ni_syscall 0 /* was signal(2) */
+ sys sys_geteuid 0
+ sys sys_getegid 0 /* 4050 */
+ sys sys_acct 1
+ sys sys_umount 2
+ sys sys_ni_syscall 0
+ sys sys_ioctl 3
+ sys sys_fcntl 3 /* 4055 */
+ sys sys_ni_syscall 2
+ sys sys_setpgid 2
+ sys sys_ni_syscall 0
+ sys sys_olduname 1
+ sys sys_umask 1 /* 4060 */
+ sys sys_chroot 1
+ sys sys_ustat 2
+ sys sys_dup2 2
+ sys sys_getppid 0
+ sys sys_getpgrp 0 /* 4065 */
+ sys sys_setsid 0
+ sys sys_sigaction 3
+ sys sys_sgetmask 0
+ sys sys_ssetmask 1
+ sys sys_setreuid 2 /* 4070 */
+ sys sys_setregid 2
+ sys sys_sigsuspend 0
+ sys sys_sigpending 1
+ sys sys_sethostname 2
+ sys sys_setrlimit 2 /* 4075 */
+ sys sys_getrlimit 2
+ sys sys_getrusage 2
+ sys sys_gettimeofday 2
+ sys sys_settimeofday 2
+ sys sys_getgroups 2 /* 4080 */
+ sys sys_setgroups 2
+ sys sys_ni_syscall 0 /* old_select */
+ sys sys_symlink 2
+ sys sys_ni_syscall 0 /* was sys_lstat */
+ sys sys_readlink 3 /* 4085 */
+ sys sys_uselib 1
+ sys sys_swapon 2
+ sys sys_reboot 3
+ sys old_readdir 3
+ sys old_mmap 6 /* 4090 */
+ sys sys_munmap 2
+ sys sys_truncate 2
+ sys sys_ftruncate 2
+ sys sys_fchmod 2
+ sys sys_fchown 3 /* 4095 */
+ sys sys_getpriority 2
+ sys sys_setpriority 3
+ sys sys_ni_syscall 0
+ sys sys_statfs 2
+ sys sys_fstatfs 2 /* 4100 */
+ sys sys_ni_syscall 0 /* was ioperm(2) */
+ sys sys_socketcall 2
+ sys sys_syslog 3
+ sys sys_setitimer 3
+ sys sys_getitimer 2 /* 4105 */
+ sys sys_newstat 2
+ sys sys_newlstat 2
+ sys sys_newfstat 2
+ sys sys_uname 1
+ sys sys_ni_syscall 0 /* 4110 was iopl(2) */
+ sys sys_vhangup 0
+ sys sys_ni_syscall 0 /* was sys_idle() */
+ sys sys_ni_syscall 0 /* was sys_vm86 */
+ sys sys_wait4 4
+ sys sys_swapoff 1 /* 4115 */
+ sys sys_sysinfo 1
+ sys sys_ipc 6
+ sys sys_fsync 1
+ sys sys_sigreturn 0
+ sys sys_clone 0 /* 4120 */
+ sys sys_setdomainname 2
+ sys sys_newuname 1
+ sys sys_ni_syscall 0 /* sys_modify_ldt */
+ sys sys_adjtimex 1
+ sys sys_mprotect 3 /* 4125 */
+ sys sys_sigprocmask 3
+ sys sys_ni_syscall 0 /* was create_module */
+ sys sys_init_module 5
+ sys sys_delete_module 1
+ sys sys_ni_syscall 0 /* 4130 was get_kernel_syms */
+ sys sys_quotactl 4
+ sys sys_getpgid 1
+ sys sys_fchdir 1
+ sys sys_bdflush 2
+ sys sys_sysfs 3 /* 4135 */
+ sys sys_personality 1
+ sys sys_ni_syscall 0 /* for afs_syscall */
+ sys sys_setfsuid 1
+ sys sys_setfsgid 1
+ sys sys_llseek 5 /* 4140 */
+ sys sys_getdents 3
+ sys sys_select 5
+ sys sys_flock 2
+ sys sys_msync 3
+ sys sys_readv 3 /* 4145 */
+ sys sys_writev 3
+ sys sys_cacheflush 3
+ sys sys_cachectl 3
+ sys sys_sysmips 4
+ sys sys_ni_syscall 0 /* 4150 */
+ sys sys_getsid 1
+ sys sys_fdatasync 1
+ sys sys_sysctl 1
+ sys sys_mlock 2
+ sys sys_munlock 2 /* 4155 */
+ sys sys_mlockall 1
+ sys sys_munlockall 0
+ sys sys_sched_setparam 2
+ sys sys_sched_getparam 2
+ sys sys_sched_setscheduler 3 /* 4160 */
+ sys sys_sched_getscheduler 1
+ sys sys_sched_yield 0
+ sys sys_sched_get_priority_max 1
+ sys sys_sched_get_priority_min 1
+ sys sys_sched_rr_get_interval 2 /* 4165 */
+ sys sys_nanosleep, 2
+ sys sys_mremap, 4
+ sys sys_accept 3
+ sys sys_bind 3
+ sys sys_connect 3 /* 4170 */
+ sys sys_getpeername 3
+ sys sys_getsockname 3
+ sys sys_getsockopt 5
+ sys sys_listen 2
+ sys sys_recv 4 /* 4175 */
+ sys sys_recvfrom 6
+ sys sys_recvmsg 3
+ sys sys_send 4
+ sys sys_sendmsg 3
+ sys sys_sendto 6 /* 4180 */
+ sys sys_setsockopt 5
+ sys sys_shutdown 2
+ sys sys_socket 3
+ sys sys_socketpair 4
+ sys sys_setresuid 3 /* 4185 */
+ sys sys_getresuid 3
+ sys sys_ni_syscall 0 /* was sys_query_module */
+ sys sys_poll 3
+ sys sys_nfsservctl 3
+ sys sys_setresgid 3 /* 4190 */
+ sys sys_getresgid 3
+ sys sys_prctl 5
+ sys sys_rt_sigreturn 0
+ sys sys_rt_sigaction 4
+ sys sys_rt_sigprocmask 4 /* 4195 */
+ sys sys_rt_sigpending 2
+ sys sys_rt_sigtimedwait 4
+ sys sys_rt_sigqueueinfo 3
+ sys sys_rt_sigsuspend 0
+ sys sys_pread64 6 /* 4200 */
+ sys sys_pwrite64 6
+ sys sys_chown 3
+ sys sys_getcwd 2
+ sys sys_capget 2
+ sys sys_capset 2 /* 4205 */
+ sys sys_sigaltstack 0
+ sys sys_sendfile 4
+ sys sys_ni_syscall 0
+ sys sys_ni_syscall 0
+ sys sys_mmap2 6 /* 4210 */
+ sys sys_truncate64 4
+ sys sys_ftruncate64 4
+ sys sys_stat64 2
+ sys sys_lstat64 2
+ sys sys_fstat64 2 /* 4215 */
+ sys sys_pivot_root 2
+ sys sys_mincore 3
+ sys sys_madvise 3
+ sys sys_getdents64 3
+ sys sys_fcntl64 3 /* 4220 */
+ sys sys_ni_syscall 0
+ sys sys_gettid 0
+ sys sys_readahead 5
+ sys sys_setxattr 5
+ sys sys_lsetxattr 5 /* 4225 */
+ sys sys_fsetxattr 5
+ sys sys_getxattr 4
+ sys sys_lgetxattr 4
+ sys sys_fgetxattr 4
+ sys sys_listxattr 3 /* 4230 */
+ sys sys_llistxattr 3
+ sys sys_flistxattr 3
+ sys sys_removexattr 2
+ sys sys_lremovexattr 2
+ sys sys_fremovexattr 2 /* 4235 */
+ sys sys_tkill 2
+ sys sys_sendfile64 5
+ sys sys_futex 2
+ sys sys_sched_setaffinity 3
+ sys sys_sched_getaffinity 3 /* 4240 */
+ sys sys_io_setup 2
+ sys sys_io_destroy 1
+ sys sys_io_getevents 5
+ sys sys_io_submit 3
+ sys sys_io_cancel 3 /* 4245 */
+ sys sys_exit_group 1
+ sys sys_lookup_dcookie 3
+ sys sys_epoll_create 1
+ sys sys_epoll_ctl 4
+ sys sys_epoll_wait 3 /* 4250 */
+ sys sys_remap_file_pages 5
+ sys sys_set_tid_address 1
+ sys sys_restart_syscall 0
+ sys sys_fadvise64_64 7
+ sys sys_statfs64 3 /* 4255 */
+ sys sys_fstatfs64 2
+ sys sys_timer_create 3
+ sys sys_timer_settime 4
+ sys sys_timer_gettime 2
+ sys sys_timer_getoverrun 1 /* 4260 */
+ sys sys_timer_delete 1
+ sys sys_clock_settime 2
+ sys sys_clock_gettime 2
+ sys sys_clock_getres 2
+ sys sys_clock_nanosleep 4 /* 4265 */
+ sys sys_tgkill 3
+ sys sys_utimes 2
+ sys sys_mbind 4
+ sys sys_ni_syscall 0 /* sys_get_mempolicy */
+ sys sys_ni_syscall 0 /* 4270 sys_set_mempolicy */
+ sys sys_mq_open 4
+ sys sys_mq_unlink 1
+ sys sys_mq_timedsend 5
+ sys sys_mq_timedreceive 5
+ sys sys_mq_notify 2 /* 4275 */
+ sys sys_mq_getsetattr 3
+ sys sys_ni_syscall 0 /* sys_vserver */
+ sys sys_waitid 4
+ sys sys_ni_syscall 0 /* available, was setaltroot */
+ sys sys_add_key 5
+ sys sys_request_key 4
+ sys sys_keyctl 5
+
+ .endm
+
+ /* We pre-compute the number of _instruction_ bytes needed to
+ load or store the arguments 6-8. Negative values are ignored. */
+
+ .macro sys function, nargs
+ PTR \function
+ LONG (\nargs << 2) - (5 << 2)
+ .endm
+
+ .align 3
+ .type sys_call_table,@object
+EXPORT(sys_call_table)
+ syscalltable
+ .size sys_call_table, . - sys_call_table
diff --git a/arch/mips/kernel/scall64-64.S b/arch/mips/kernel/scall64-64.S
new file mode 100644
index 0000000..32efb88
--- /dev/null
+++ b/arch/mips/kernel/scall64-64.S
@@ -0,0 +1,451 @@
+/*
+ * 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, 96, 97, 98, 99, 2000, 01, 02 by Ralf Baechle
+ * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
+ * Copyright (C) 2001 MIPS Technologies, Inc.
+ */
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <asm/asm.h>
+#include <asm/asmmacro.h>
+#include <asm/mipsregs.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+#include <asm/offset.h>
+#include <asm/sysmips.h>
+#include <asm/thread_info.h>
+#include <asm/unistd.h>
+#include <asm/war.h>
+
+#ifndef CONFIG_BINFMT_ELF32
+/* Neither O32 nor N32, so define handle_sys here */
+#define handle_sys64 handle_sys
+#endif
+
+ .align 5
+NESTED(handle_sys64, PT_SIZE, sp)
+#if !defined(CONFIG_MIPS32_O32) && !defined(CONFIG_MIPS32_N32)
+ /*
+ * When 32-bit compatibility is configured scall_o32.S
+ * already did this.
+ */
+ .set noat
+ SAVE_SOME
+ STI
+ .set at
+#endif
+
+ dsubu t0, v0, __NR_64_Linux # check syscall number
+ sltiu t0, t0, __NR_64_Linux_syscalls + 1
+#if !defined(CONFIG_MIPS32_O32) && !defined(CONFIG_MIPS32_N32)
+ ld t1, PT_EPC(sp) # skip syscall on return
+ daddiu t1, 4 # skip to next instruction
+ sd t1, PT_EPC(sp)
+#endif
+ beqz t0, illegal_syscall
+
+ dsll t0, v0, 3 # offset into table
+ ld t2, (sys_call_table - (__NR_64_Linux * 8))(t0)
+ # syscall routine
+
+ sd a3, PT_R26(sp) # save a3 for syscall restarting
+
+ li t1, _TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT
+ LONG_L t0, TI_FLAGS($28) # syscall tracing enabled?
+ and t0, t1, t0
+ bnez t0, syscall_trace_entry
+
+ jalr t2 # Do The Real Thing (TM)
+
+ li t0, -EMAXERRNO - 1 # error?
+ sltu t0, t0, v0
+ sd t0, PT_R7(sp) # set error flag
+ beqz t0, 1f
+
+ dnegu v0 # error
+ sd v0, PT_R0(sp) # set flag for syscall
+ # restarting
+1: sd v0, PT_R2(sp) # result
+
+n64_syscall_exit:
+ local_irq_disable # make sure need_resched and
+ # signals dont change between
+ # sampling and return
+ LONG_L a2, TI_FLAGS($28) # current->work
+ li t0, _TIF_ALLWORK_MASK
+ and t0, a2, t0
+ bnez t0, n64_syscall_exit_work
+
+ j restore_partial
+
+n64_syscall_exit_work:
+ j syscall_exit_work_partial
+
+/* ------------------------------------------------------------------------ */
+
+syscall_trace_entry:
+ SAVE_STATIC
+ move s0, t2
+ move a0, sp
+ li a1, 0
+ jal do_syscall_trace
+
+ ld a0, PT_R4(sp) # Restore argument registers
+ ld a1, PT_R5(sp)
+ ld a2, PT_R6(sp)
+ ld a3, PT_R7(sp)
+ ld a4, PT_R8(sp)
+ ld a5, PT_R9(sp)
+ jalr s0
+
+ li t0, -EMAXERRNO - 1 # error?
+ sltu t0, t0, v0
+ sd t0, PT_R7(sp) # set error flag
+ beqz t0, 1f
+
+ dnegu v0 # error
+ sd v0, PT_R0(sp) # set flag for syscall restarting
+1: sd v0, PT_R2(sp) # result
+
+ j syscall_exit
+
+illegal_syscall:
+ /* This also isn't a 64-bit syscall, throw an error. */
+ li v0, -ENOSYS # error
+ sd v0, PT_R2(sp)
+ li t0, 1 # set error flag
+ sd t0, PT_R7(sp)
+ j n64_syscall_exit
+ END(handle_sys64)
+
+ LEAF(mips_atomic_set)
+ andi v0, a1, 3 # must be word aligned
+ bnez v0, bad_alignment
+
+ LONG_L v1, TI_ADDR_LIMIT($28) # in legal address range?
+ LONG_ADDIU a0, a1, 4
+ or a0, a0, a1
+ and a0, a0, v1
+ bltz a0, bad_address
+
+#ifdef CONFIG_CPU_HAS_LLSC
+ /* Ok, this is the ll/sc case. World is sane :-) */
+1: ll v0, (a1)
+ move a0, a2
+2: sc a0, (a1)
+#if R10000_LLSC_WAR
+ beqzl a0, 1b
+#else
+ beqz a0, 1b
+#endif
+
+ .section __ex_table,"a"
+ PTR 1b, bad_stack
+ PTR 2b, bad_stack
+ .previous
+#else
+ sw a1, 16(sp)
+ sw a2, 20(sp)
+
+ move a0, sp
+ move a2, a1
+ li a1, 1
+ jal do_page_fault
+
+ lw a1, 16(sp)
+ lw a2, 20(sp)
+
+ /*
+ * At this point the page should be readable and writable unless
+ * there was no more memory available.
+ */
+1: lw v0, (a1)
+2: sw a2, (a1)
+
+ .section __ex_table,"a"
+ PTR 1b, no_mem
+ PTR 2b, no_mem
+ .previous
+#endif
+
+ sd zero, PT_R7(sp) # success
+ sd v0, PT_R2(sp) # result
+
+ /* Success, so skip usual error handling garbage. */
+ li t0, _TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT
+ LONG_L a2, TI_FLAGS($28) # syscall tracing enabled?
+ and t0, a2, t0
+ bnez t0, 1f
+
+ j n64_syscall_exit
+
+1: SAVE_STATIC
+ move a0, sp
+ li a1, 1
+ jal do_syscall_trace
+ j syscall_exit
+
+no_mem: li v0, -ENOMEM
+ jr ra
+
+bad_address:
+ li v0, -EFAULT
+ jr ra
+
+bad_alignment:
+ li v0, -EINVAL
+ jr ra
+ END(mips_atomic_set)
+
+ LEAF(sys_sysmips)
+ beq a0, MIPS_ATOMIC_SET, mips_atomic_set
+ j _sys_sysmips
+ END(sys_sysmips)
+
+ .align 3
+sys_call_table:
+ PTR sys_read /* 5000 */
+ PTR sys_write
+ PTR sys_open
+ PTR sys_close
+ PTR sys_newstat
+ PTR sys_newfstat /* 5005 */
+ PTR sys_newlstat
+ PTR sys_poll
+ PTR sys_lseek
+ PTR old_mmap
+ PTR sys_mprotect /* 5010 */
+ PTR sys_munmap
+ PTR sys_brk
+ PTR sys_rt_sigaction
+ PTR sys_rt_sigprocmask
+ PTR sys_ioctl /* 5015 */
+ PTR sys_pread64
+ PTR sys_pwrite64
+ PTR sys_readv
+ PTR sys_writev
+ PTR sys_access /* 5020 */
+ PTR sys_pipe
+ PTR sys_select
+ PTR sys_sched_yield
+ PTR sys_mremap
+ PTR sys_msync /* 5025 */
+ PTR sys_mincore
+ PTR sys_madvise
+ PTR sys_shmget
+ PTR sys_shmat
+ PTR sys_shmctl /* 5030 */
+ PTR sys_dup
+ PTR sys_dup2
+ PTR sys_pause
+ PTR sys_nanosleep
+ PTR sys_getitimer /* 5035 */
+ PTR sys_setitimer
+ PTR sys_alarm
+ PTR sys_getpid
+ PTR sys_sendfile64
+ PTR sys_socket /* 5040 */
+ PTR sys_connect
+ PTR sys_accept
+ PTR sys_sendto
+ PTR sys_recvfrom
+ PTR sys_sendmsg /* 5045 */
+ PTR sys_recvmsg
+ PTR sys_shutdown
+ PTR sys_bind
+ PTR sys_listen
+ PTR sys_getsockname /* 5050 */
+ PTR sys_getpeername
+ PTR sys_socketpair
+ PTR sys_setsockopt
+ PTR sys_getsockopt
+ PTR sys_clone /* 5055 */
+ PTR sys_fork
+ PTR sys_execve
+ PTR sys_exit
+ PTR sys_wait4
+ PTR sys_kill /* 5060 */
+ PTR sys_newuname
+ PTR sys_semget
+ PTR sys_semop
+ PTR sys_semctl
+ PTR sys_shmdt /* 5065 */
+ PTR sys_msgget
+ PTR sys_msgsnd
+ PTR sys_msgrcv
+ PTR sys_msgctl
+ PTR sys_fcntl /* 5070 */
+ PTR sys_flock
+ PTR sys_fsync
+ PTR sys_fdatasync
+ PTR sys_truncate
+ PTR sys_ftruncate /* 5075 */
+ PTR sys_getdents
+ PTR sys_getcwd
+ PTR sys_chdir
+ PTR sys_fchdir
+ PTR sys_rename /* 5080 */
+ PTR sys_mkdir
+ PTR sys_rmdir
+ PTR sys_creat
+ PTR sys_link
+ PTR sys_unlink /* 5085 */
+ PTR sys_symlink
+ PTR sys_readlink
+ PTR sys_chmod
+ PTR sys_fchmod
+ PTR sys_chown /* 5090 */
+ PTR sys_fchown
+ PTR sys_lchown
+ PTR sys_umask
+ PTR sys_gettimeofday
+ PTR sys_getrlimit /* 5095 */
+ PTR sys_getrusage
+ PTR sys_sysinfo
+ PTR sys_times
+ PTR sys_ptrace
+ PTR sys_getuid /* 5100 */
+ PTR sys_syslog
+ PTR sys_getgid
+ PTR sys_setuid
+ PTR sys_setgid
+ PTR sys_geteuid /* 5105 */
+ PTR sys_getegid
+ PTR sys_setpgid
+ PTR sys_getppid
+ PTR sys_getpgrp
+ PTR sys_setsid /* 5110 */
+ PTR sys_setreuid
+ PTR sys_setregid
+ PTR sys_getgroups
+ PTR sys_setgroups
+ PTR sys_setresuid /* 5115 */
+ PTR sys_getresuid
+ PTR sys_setresgid
+ PTR sys_getresgid
+ PTR sys_getpgid
+ PTR sys_setfsuid /* 5120 */
+ PTR sys_setfsgid
+ PTR sys_getsid
+ PTR sys_capget
+ PTR sys_capset
+ PTR sys_rt_sigpending /* 5125 */
+ PTR sys_rt_sigtimedwait
+ PTR sys_rt_sigqueueinfo
+ PTR sys_rt_sigsuspend
+ PTR sys_sigaltstack
+ PTR sys_utime /* 5130 */
+ PTR sys_mknod
+ PTR sys_personality
+ PTR sys_ustat
+ PTR sys_statfs
+ PTR sys_fstatfs /* 5135 */
+ PTR sys_sysfs
+ PTR sys_getpriority
+ PTR sys_setpriority
+ PTR sys_sched_setparam
+ PTR sys_sched_getparam /* 5140 */
+ PTR sys_sched_setscheduler
+ PTR sys_sched_getscheduler
+ PTR sys_sched_get_priority_max
+ PTR sys_sched_get_priority_min
+ PTR sys_sched_rr_get_interval /* 5145 */
+ PTR sys_mlock
+ PTR sys_munlock
+ PTR sys_mlockall
+ PTR sys_munlockall
+ PTR sys_vhangup /* 5150 */
+ PTR sys_pivot_root
+ PTR sys_sysctl
+ PTR sys_prctl
+ PTR sys_adjtimex
+ PTR sys_setrlimit /* 5155 */
+ PTR sys_chroot
+ PTR sys_sync
+ PTR sys_acct
+ PTR sys_settimeofday
+ PTR sys_mount /* 5160 */
+ PTR sys_umount
+ PTR sys_swapon
+ PTR sys_swapoff
+ PTR sys_reboot
+ PTR sys_sethostname /* 5165 */
+ PTR sys_setdomainname
+ PTR sys_ni_syscall /* was create_module */
+ PTR sys_init_module
+ PTR sys_delete_module
+ PTR sys_ni_syscall /* 5170, was get_kernel_syms */
+ PTR sys_ni_syscall /* was query_module */
+ PTR sys_quotactl
+ PTR sys_nfsservctl
+ PTR sys_ni_syscall /* res. for getpmsg */
+ PTR sys_ni_syscall /* 5175 for putpmsg */
+ PTR sys_ni_syscall /* res. for afs_syscall */
+ PTR sys_ni_syscall /* res. for security */
+ PTR sys_gettid
+ PTR sys_readahead
+ PTR sys_setxattr /* 5180 */
+ PTR sys_lsetxattr
+ PTR sys_fsetxattr
+ PTR sys_getxattr
+ PTR sys_lgetxattr
+ PTR sys_fgetxattr /* 5185 */
+ PTR sys_listxattr
+ PTR sys_llistxattr
+ PTR sys_flistxattr
+ PTR sys_removexattr
+ PTR sys_lremovexattr /* 5190 */
+ PTR sys_fremovexattr
+ PTR sys_tkill
+ PTR sys_ni_syscall
+ PTR sys_futex
+ PTR sys_sched_setaffinity /* 5195 */
+ PTR sys_sched_getaffinity
+ PTR sys_cacheflush
+ PTR sys_cachectl
+ PTR sys_sysmips
+ PTR sys_io_setup /* 5200 */
+ PTR sys_io_destroy
+ PTR sys_io_getevents
+ PTR sys_io_submit
+ PTR sys_io_cancel
+ PTR sys_exit_group /* 5205 */
+ PTR sys_lookup_dcookie
+ PTR sys_epoll_create
+ PTR sys_epoll_ctl
+ PTR sys_epoll_wait
+ PTR sys_remap_file_pages /* 5210 */
+ PTR sys_rt_sigreturn
+ PTR sys_set_tid_address
+ PTR sys_restart_syscall
+ PTR sys_semtimedop
+ PTR sys_fadvise64_64 /* 5215 */
+ PTR sys_timer_create
+ PTR sys_timer_settime
+ PTR sys_timer_gettime
+ PTR sys_timer_getoverrun
+ PTR sys_timer_delete /* 5220 */
+ PTR sys_clock_settime
+ PTR sys_clock_gettime
+ PTR sys_clock_getres
+ PTR sys_clock_nanosleep
+ PTR sys_tgkill /* 5225 */
+ PTR sys_utimes
+ PTR sys_mbind
+ PTR sys_ni_syscall /* sys_get_mempolicy */
+ PTR sys_ni_syscall /* sys_set_mempolicy */
+ PTR sys_mq_open /* 5230 */
+ PTR sys_mq_unlink
+ PTR sys_mq_timedsend
+ PTR sys_mq_timedreceive
+ PTR sys_mq_notify
+ PTR sys_mq_getsetattr /* 5235 */
+ PTR sys_ni_syscall /* sys_vserver */
+ PTR sys_waitid
+ PTR sys_ni_syscall /* available, was setaltroot */
+ PTR sys_add_key
+ PTR sys_request_key /* 5240 */
+ PTR sys_keyctl
diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S
new file mode 100644
index 0000000..e52049c
--- /dev/null
+++ b/arch/mips/kernel/scall64-n32.S
@@ -0,0 +1,365 @@
+/*
+ * 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, 96, 97, 98, 99, 2000, 01 by Ralf Baechle
+ * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
+ * Copyright (C) 2001 MIPS Technologies, Inc.
+ */
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <asm/asm.h>
+#include <asm/asmmacro.h>
+#include <asm/mipsregs.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+#include <asm/thread_info.h>
+#include <asm/unistd.h>
+
+/* This duplicates the definition from <linux/sched.h> */
+#define PT_TRACESYS 0x00000002 /* tracing system calls */
+
+/* This duplicates the definition from <asm/signal.h> */
+#define SIGILL 4 /* Illegal instruction (ANSI). */
+
+#ifndef CONFIG_MIPS32_O32
+/* No O32, so define handle_sys here */
+#define handle_sysn32 handle_sys
+#endif
+
+ .align 5
+NESTED(handle_sysn32, PT_SIZE, sp)
+#ifndef CONFIG_MIPS32_O32
+ .set noat
+ SAVE_SOME
+ STI
+ .set at
+#endif
+
+ dsubu t0, v0, __NR_N32_Linux # check syscall number
+ sltiu t0, t0, __NR_N32_Linux_syscalls + 1
+
+#ifndef CONFIG_MIPS32_O32
+ ld t1, PT_EPC(sp) # skip syscall on return
+ daddiu t1, 4 # skip to next instruction
+ sd t1, PT_EPC(sp)
+#endif
+ beqz t0, not_n32_scall
+
+ dsll t0, v0, 3 # offset into table
+ ld t2, (sysn32_call_table - (__NR_N32_Linux * 8))(t0)
+
+ sd a3, PT_R26(sp) # save a3 for syscall restarting
+
+ li t1, _TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT
+ LONG_L t0, TI_FLAGS($28) # syscall tracing enabled?
+ and t0, t1, t0
+ bnez t0, n32_syscall_trace_entry
+
+ jalr t2 # Do The Real Thing (TM)
+
+ li t0, -EMAXERRNO - 1 # error?
+ sltu t0, t0, v0
+ sd t0, PT_R7(sp) # set error flag
+ beqz t0, 1f
+
+ dnegu v0 # error
+ sd v0, PT_R0(sp) # set flag for syscall restarting
+1: sd v0, PT_R2(sp) # result
+
+ local_irq_disable # make sure need_resched and
+ # signals dont change between
+ # sampling and return
+ LONG_L a2, TI_FLAGS($28) # current->work
+ li t0, _TIF_ALLWORK_MASK
+ and t0, a2, t0
+ bnez t0, n32_syscall_exit_work
+
+ j restore_partial
+
+n32_syscall_exit_work:
+ j syscall_exit_work_partial
+
+/* ------------------------------------------------------------------------ */
+
+n32_syscall_trace_entry:
+ SAVE_STATIC
+ move s0, t2
+ move a0, sp
+ li a1, 0
+ jal do_syscall_trace
+
+ ld a0, PT_R4(sp) # Restore argument registers
+ ld a1, PT_R5(sp)
+ ld a2, PT_R6(sp)
+ ld a3, PT_R7(sp)
+ ld a4, PT_R8(sp)
+ ld a5, PT_R9(sp)
+ jalr s0
+
+ li t0, -EMAXERRNO - 1 # error?
+ sltu t0, t0, v0
+ sd t0, PT_R7(sp) # set error flag
+ beqz t0, 1f
+
+ dnegu v0 # error
+ sd v0, PT_R0(sp) # set flag for syscall restarting
+1: sd v0, PT_R2(sp) # result
+
+ j syscall_exit
+
+not_n32_scall:
+ /* This is not an n32 compatibility syscall, pass it on to
+ the n64 syscall handlers. */
+ j handle_sys64
+
+ END(handle_sysn32)
+
+EXPORT(sysn32_call_table)
+ PTR sys_read /* 6000 */
+ PTR sys_write
+ PTR sys_open
+ PTR sys_close
+ PTR sys_newstat
+ PTR sys_newfstat /* 6005 */
+ PTR sys_newlstat
+ PTR sys_poll
+ PTR sys_lseek
+ PTR old_mmap
+ PTR sys_mprotect /* 6010 */
+ PTR sys_munmap
+ PTR sys_brk
+ PTR sys32_rt_sigaction
+ PTR sys32_rt_sigprocmask
+ PTR compat_sys_ioctl /* 6015 */
+ PTR sys_pread64
+ PTR sys_pwrite64
+ PTR compat_sys_readv
+ PTR compat_sys_writev
+ PTR sys_access /* 6020 */
+ PTR sys_pipe
+ PTR compat_sys_select
+ PTR sys_sched_yield
+ PTR sys_mremap
+ PTR sys_msync /* 6025 */
+ PTR sys_mincore
+ PTR sys_madvise
+ PTR sys_shmget
+ PTR sys32_shmat
+ PTR sys_shmctl /* 6030 */
+ PTR sys_dup
+ PTR sys_dup2
+ PTR sys_pause
+ PTR compat_sys_nanosleep
+ PTR compat_sys_getitimer /* 6035 */
+ PTR compat_sys_setitimer
+ PTR sys_alarm
+ PTR sys_getpid
+ PTR sys32_sendfile
+ PTR sys_socket /* 6040 */
+ PTR sys_connect
+ PTR sys_accept
+ PTR sys_sendto
+ PTR sys_recvfrom
+ PTR compat_sys_sendmsg /* 6045 */
+ PTR compat_sys_recvmsg
+ PTR sys_shutdown
+ PTR sys_bind
+ PTR sys_listen
+ PTR sys_getsockname /* 6050 */
+ PTR sys_getpeername
+ PTR sys_socketpair
+ PTR compat_sys_setsockopt
+ PTR sys_getsockopt
+ PTR sys_clone /* 6055 */
+ PTR sys_fork
+ PTR sys32_execve
+ PTR sys_exit
+ PTR sys32_wait4
+ PTR sys_kill /* 6060 */
+ PTR sys32_newuname
+ PTR sys_semget
+ PTR sys_semop
+ PTR sys_semctl
+ PTR sys_shmdt /* 6065 */
+ PTR sys_msgget
+ PTR sys_msgsnd
+ PTR sys_msgrcv
+ PTR sys_msgctl
+ PTR compat_sys_fcntl /* 6070 */
+ PTR sys_flock
+ PTR sys_fsync
+ PTR sys_fdatasync
+ PTR sys_truncate
+ PTR sys_ftruncate /* 6075 */
+ PTR sys32_getdents
+ PTR sys_getcwd
+ PTR sys_chdir
+ PTR sys_fchdir
+ PTR sys_rename /* 6080 */
+ PTR sys_mkdir
+ PTR sys_rmdir
+ PTR sys_creat
+ PTR sys_link
+ PTR sys_unlink /* 6085 */
+ PTR sys_symlink
+ PTR sys_readlink
+ PTR sys_chmod
+ PTR sys_fchmod
+ PTR sys_chown /* 6090 */
+ PTR sys_fchown
+ PTR sys_lchown
+ PTR sys_umask
+ PTR sys32_gettimeofday
+ PTR compat_sys_getrlimit /* 6095 */
+ PTR compat_sys_getrusage
+ PTR sys32_sysinfo
+ PTR compat_sys_times
+ PTR sys_ptrace
+ PTR sys_getuid /* 6100 */
+ PTR sys_syslog
+ PTR sys_getgid
+ PTR sys_setuid
+ PTR sys_setgid
+ PTR sys_geteuid /* 6105 */
+ PTR sys_getegid
+ PTR sys_setpgid
+ PTR sys_getppid
+ PTR sys_getpgrp
+ PTR sys_setsid /* 6110 */
+ PTR sys_setreuid
+ PTR sys_setregid
+ PTR sys_getgroups
+ PTR sys_setgroups
+ PTR sys_setresuid /* 6115 */
+ PTR sys_getresuid
+ PTR sys_setresgid
+ PTR sys_getresgid
+ PTR sys_getpgid
+ PTR sys_setfsuid /* 6120 */
+ PTR sys_setfsgid
+ PTR sys_getsid
+ PTR sys_capget
+ PTR sys_capset
+ PTR sys32_rt_sigpending /* 6125 */
+ PTR compat_sys_rt_sigtimedwait
+ PTR sys32_rt_sigqueueinfo
+ PTR sys32_rt_sigsuspend
+ PTR sys32_sigaltstack
+ PTR compat_sys_utime /* 6130 */
+ PTR sys_mknod
+ PTR sys32_personality
+ PTR sys_ustat
+ PTR compat_sys_statfs
+ PTR compat_sys_fstatfs /* 6135 */
+ PTR sys_sysfs
+ PTR sys_getpriority
+ PTR sys_setpriority
+ PTR sys_sched_setparam
+ PTR sys_sched_getparam /* 6140 */
+ PTR sys_sched_setscheduler
+ PTR sys_sched_getscheduler
+ PTR sys_sched_get_priority_max
+ PTR sys_sched_get_priority_min
+ PTR sys32_sched_rr_get_interval /* 6145 */
+ PTR sys_mlock
+ PTR sys_munlock
+ PTR sys_mlockall
+ PTR sys_munlockall
+ PTR sys_vhangup /* 6150 */
+ PTR sys_pivot_root
+ PTR sys32_sysctl
+ PTR sys_prctl
+ PTR sys32_adjtimex
+ PTR compat_sys_setrlimit /* 6155 */
+ PTR sys_chroot
+ PTR sys_sync
+ PTR sys_acct
+ PTR sys32_settimeofday
+ PTR sys_mount /* 6160 */
+ PTR sys_umount
+ PTR sys_swapon
+ PTR sys_swapoff
+ PTR sys_reboot
+ PTR sys_sethostname /* 6165 */
+ PTR sys_setdomainname
+ PTR sys_ni_syscall /* was create_module */
+ PTR sys_init_module
+ PTR sys_delete_module
+ PTR sys_ni_syscall /* 6170, was get_kernel_syms */
+ PTR sys_ni_syscall /* was query_module */
+ PTR sys_quotactl
+ PTR sys_nfsservctl
+ PTR sys_ni_syscall /* res. for getpmsg */
+ PTR sys_ni_syscall /* 6175 for putpmsg */
+ PTR sys_ni_syscall /* res. for afs_syscall */
+ PTR sys_ni_syscall /* res. for security */
+ PTR sys_gettid
+ PTR sys32_readahead
+ PTR sys_setxattr /* 6180 */
+ PTR sys_lsetxattr
+ PTR sys_fsetxattr
+ PTR sys_getxattr
+ PTR sys_lgetxattr
+ PTR sys_fgetxattr /* 6185 */
+ PTR sys_listxattr
+ PTR sys_llistxattr
+ PTR sys_flistxattr
+ PTR sys_removexattr
+ PTR sys_lremovexattr /* 6190 */
+ PTR sys_fremovexattr
+ PTR sys_tkill
+ PTR sys_ni_syscall
+ PTR compat_sys_futex
+ PTR compat_sys_sched_setaffinity /* 6195 */
+ PTR compat_sys_sched_getaffinity
+ PTR sys_cacheflush
+ PTR sys_cachectl
+ PTR sys_sysmips
+ PTR sys_io_setup /* 6200 */
+ PTR sys_io_destroy
+ PTR sys_io_getevents
+ PTR sys_io_submit
+ PTR sys_io_cancel
+ PTR sys_exit_group /* 6205 */
+ PTR sys_lookup_dcookie
+ PTR sys_epoll_create
+ PTR sys_epoll_ctl
+ PTR sys_epoll_wait
+ PTR sys_remap_file_pages /* 6210 */
+ PTR sysn32_rt_sigreturn
+ PTR sys_fcntl
+ PTR sys_set_tid_address
+ PTR sys_restart_syscall
+ PTR sys_semtimedop /* 6215 */
+ PTR sys_fadvise64_64
+ PTR compat_sys_statfs64
+ PTR compat_sys_fstatfs64
+ PTR sys_sendfile64
+ PTR sys_timer_create /* 6220 */
+ PTR sys_timer_settime
+ PTR sys_timer_gettime
+ PTR sys_timer_getoverrun
+ PTR sys_timer_delete
+ PTR sys_clock_settime /* 6225 */
+ PTR sys_clock_gettime
+ PTR sys_clock_getres
+ PTR sys_clock_nanosleep
+ PTR sys_tgkill
+ PTR compat_sys_utimes /* 6230 */
+ PTR sys_ni_syscall /* sys_mbind */
+ PTR sys_ni_syscall /* sys_get_mempolicy */
+ PTR sys_ni_syscall /* sys_set_mempolicy */
+ PTR compat_sys_mq_open
+ PTR sys_mq_unlink /* 6235 */
+ PTR compat_sys_mq_timedsend
+ PTR compat_sys_mq_timedreceive
+ PTR compat_sys_mq_notify
+ PTR compat_sys_mq_getsetattr
+ PTR sys_ni_syscall /* 6240, sys_vserver */
+ PTR sys_waitid
+ PTR sys_ni_syscall /* available, was setaltroot */
+ PTR sys_add_key
+ PTR sys_request_key
+ PTR sys_keyctl /* 6245 */
diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S
new file mode 100644
index 0000000..739f399
--- /dev/null
+++ b/arch/mips/kernel/scall64-o32.S
@@ -0,0 +1,488 @@
+/*
+ * 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, 2001 by Ralf Baechle
+ * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
+ * Copyright (C) 2001 MIPS Technologies, Inc.
+ * Copyright (C) 2004 Thiemo Seufer
+ *
+ * Hairy, the userspace application uses a different argument passing
+ * convention than the kernel, so we have to translate things from o32
+ * to ABI64 calling convention. 64-bit syscalls are also processed
+ * here for now.
+ */
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <asm/asm.h>
+#include <asm/asmmacro.h>
+#include <asm/mipsregs.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+#include <asm/thread_info.h>
+#include <asm/unistd.h>
+#include <asm/sysmips.h>
+
+ .align 5
+NESTED(handle_sys, PT_SIZE, sp)
+ .set noat
+ SAVE_SOME
+ STI
+ .set at
+ ld t1, PT_EPC(sp) # skip syscall on return
+
+ dsubu t0, v0, __NR_O32_Linux # check syscall number
+ sltiu t0, t0, __NR_O32_Linux_syscalls + 1
+ daddiu t1, 4 # skip to next instruction
+ sd t1, PT_EPC(sp)
+ beqz t0, not_o32_scall
+#if 0
+ SAVE_ALL
+ move a1, v0
+ PRINT("Scall %ld\n")
+ RESTORE_ALL
+#endif
+
+ /* We don't want to stumble over broken sign extensions from
+ userland. O32 does never use the upper half. */
+ sll a0, a0, 0
+ sll a1, a1, 0
+ sll a2, a2, 0
+ sll a3, a3, 0
+
+ dsll t0, v0, 3 # offset into table
+ ld t2, (sys_call_table - (__NR_O32_Linux * 8))(t0)
+
+ sd a3, PT_R26(sp) # save a3 for syscall restarting
+
+ /*
+ * More than four arguments. Try to deal with it by copying the
+ * stack arguments from the user stack to the kernel stack.
+ * This Sucks (TM).
+ *
+ * We intentionally keep the kernel stack a little below the top of
+ * userspace so we don't have to do a slower byte accurate check here.
+ */
+ ld t0, PT_R29(sp) # get old user stack pointer
+ daddu t1, t0, 32
+ bltz t1, bad_stack
+
+1: lw a4, 16(t0) # argument #5 from usp
+2: lw a5, 20(t0) # argument #6 from usp
+3: lw a6, 24(t0) # argument #7 from usp
+4: lw a7, 28(t0) # argument #8 from usp (for indirect syscalls)
+
+ .section __ex_table,"a"
+ PTR 1b, bad_stack
+ PTR 2b, bad_stack
+ PTR 3b, bad_stack
+ PTR 4b, bad_stack
+ .previous
+
+ li t1, _TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT
+ LONG_L t0, TI_FLAGS($28) # syscall tracing enabled?
+ and t0, t1, t0
+ bnez t0, trace_a_syscall
+
+ jalr t2 # Do The Real Thing (TM)
+
+ li t0, -EMAXERRNO - 1 # error?
+ sltu t0, t0, v0
+ sd t0, PT_R7(sp) # set error flag
+ beqz t0, 1f
+
+ dnegu v0 # error
+ sd v0, PT_R0(sp) # flag for syscall restarting
+1: sd v0, PT_R2(sp) # result
+
+o32_syscall_exit:
+ local_irq_disable # make need_resched and
+ # signals dont change between
+ # sampling and return
+ LONG_L a2, TI_FLAGS($28)
+ li t0, _TIF_ALLWORK_MASK
+ and t0, a2, t0
+ bnez t0, o32_syscall_exit_work
+
+ j restore_partial
+
+o32_syscall_exit_work:
+ j syscall_exit_work_partial
+
+/* ------------------------------------------------------------------------ */
+
+trace_a_syscall:
+ SAVE_STATIC
+ sd a4, PT_R8(sp) # Save argument registers
+ sd a5, PT_R9(sp)
+ sd a6, PT_R10(sp)
+ sd a7, PT_R11(sp) # For indirect syscalls
+
+ move s0, t2 # Save syscall pointer
+ move a0, sp
+ li a1, 0
+ jal do_syscall_trace
+
+ ld a0, PT_R4(sp) # Restore argument registers
+ ld a1, PT_R5(sp)
+ ld a2, PT_R6(sp)
+ ld a3, PT_R7(sp)
+ ld a4, PT_R8(sp)
+ ld a5, PT_R9(sp)
+ ld a6, PT_R10(sp)
+ ld a7, PT_R11(sp) # For indirect syscalls
+ jalr s0
+
+ li t0, -EMAXERRNO - 1 # error?
+ sltu t0, t0, v0
+ sd t0, PT_R7(sp) # set error flag
+ beqz t0, 1f
+
+ dnegu v0 # error
+ sd v0, PT_R0(sp) # set flag for syscall restarting
+1: sd v0, PT_R2(sp) # result
+
+ j syscall_exit
+
+/* ------------------------------------------------------------------------ */
+
+ /*
+ * The stackpointer for a call with more than 4 arguments is bad.
+ */
+bad_stack:
+ dnegu v0 # error
+ sd v0, PT_R0(sp)
+ sd v0, PT_R2(sp)
+ li t0, 1 # set error flag
+ sd t0, PT_R7(sp)
+ j o32_syscall_exit
+
+not_o32_scall:
+ /*
+ * This is not an o32 compatibility syscall, pass it on
+ * to the 64-bit syscall handlers.
+ */
+#ifdef CONFIG_MIPS32_N32
+ j handle_sysn32
+#else
+ j handle_sys64
+#endif
+ END(handle_sys)
+
+LEAF(sys32_syscall)
+ sltu v0, a0, __NR_O32_Linux + __NR_O32_Linux_syscalls + 1
+ beqz v0, einval
+
+ dsll v0, a0, 3
+ ld t2, (sys_call_table - (__NR_O32_Linux * 8))(v0)
+
+ li v1, 4000 # indirect syscall number
+ beq a0, v1, einval # do not recurse
+
+ move a0, a1 # shift argument registers
+ move a1, a2
+ move a2, a3
+ move a3, a4
+ move a4, a5
+ move a5, a6
+ move a6, a7
+ sd a0, PT_R4(sp) # ... and push back a0 - a3, some
+ sd a1, PT_R5(sp) # syscalls expect them there
+ sd a2, PT_R6(sp)
+ sd a3, PT_R7(sp)
+ sd a3, PT_R26(sp) # update a3 for syscall restarting
+ jr t2
+ /* Unreached */
+
+einval: li v0, -EINVAL
+ jr ra
+ END(sys32_syscall)
+
+ .align 3
+ .type sys_call_table,@object
+sys_call_table:
+ PTR sys32_syscall /* 4000 */
+ PTR sys_exit
+ PTR sys_fork
+ PTR sys_read
+ PTR sys_write
+ PTR sys_open /* 4005 */
+ PTR sys_close
+ PTR sys_waitpid
+ PTR sys_creat
+ PTR sys_link
+ PTR sys_unlink /* 4010 */
+ PTR sys32_execve
+ PTR sys_chdir
+ PTR compat_sys_time
+ PTR sys_mknod
+ PTR sys_chmod /* 4015 */
+ PTR sys_lchown
+ PTR sys_ni_syscall
+ PTR sys_ni_syscall /* was sys_stat */
+ PTR sys_lseek
+ PTR sys_getpid /* 4020 */
+ PTR sys_mount
+ PTR sys_oldumount
+ PTR sys_setuid
+ PTR sys_getuid
+ PTR compat_sys_stime /* 4025 */
+ PTR sys32_ptrace
+ PTR sys_alarm
+ PTR sys_ni_syscall /* was sys_fstat */
+ PTR sys_pause
+ PTR compat_sys_utime /* 4030 */
+ PTR sys_ni_syscall
+ PTR sys_ni_syscall
+ PTR sys_access
+ PTR sys_nice
+ PTR sys_ni_syscall /* 4035 */
+ PTR sys_sync
+ PTR sys_kill
+ PTR sys_rename
+ PTR sys_mkdir
+ PTR sys_rmdir /* 4040 */
+ PTR sys_dup
+ PTR sys_pipe
+ PTR compat_sys_times
+ PTR sys_ni_syscall
+ PTR sys_brk /* 4045 */
+ PTR sys_setgid
+ PTR sys_getgid
+ PTR sys_ni_syscall /* was signal 2 */
+ PTR sys_geteuid
+ PTR sys_getegid /* 4050 */
+ PTR sys_acct
+ PTR sys_umount
+ PTR sys_ni_syscall
+ PTR compat_sys_ioctl
+ PTR compat_sys_fcntl /* 4055 */
+ PTR sys_ni_syscall
+ PTR sys_setpgid
+ PTR sys_ni_syscall
+ PTR sys_olduname
+ PTR sys_umask /* 4060 */
+ PTR sys_chroot
+ PTR sys32_ustat
+ PTR sys_dup2
+ PTR sys_getppid
+ PTR sys_getpgrp /* 4065 */
+ PTR sys_setsid
+ PTR sys32_sigaction
+ PTR sys_sgetmask
+ PTR sys_ssetmask
+ PTR sys_setreuid /* 4070 */
+ PTR sys_setregid
+ PTR sys32_sigsuspend
+ PTR compat_sys_sigpending
+ PTR sys_sethostname
+ PTR compat_sys_setrlimit /* 4075 */
+ PTR compat_sys_getrlimit
+ PTR compat_sys_getrusage
+ PTR sys32_gettimeofday
+ PTR sys32_settimeofday
+ PTR sys_getgroups /* 4080 */
+ PTR sys_setgroups
+ PTR sys_ni_syscall /* old_select */
+ PTR sys_symlink
+ PTR sys_ni_syscall /* was sys_lstat */
+ PTR sys_readlink /* 4085 */
+ PTR sys_uselib
+ PTR sys_swapon
+ PTR sys_reboot
+ PTR sys32_readdir
+ PTR old_mmap /* 4090 */
+ PTR sys_munmap
+ PTR sys_truncate
+ PTR sys_ftruncate
+ PTR sys_fchmod
+ PTR sys_fchown /* 4095 */
+ PTR sys_getpriority
+ PTR sys_setpriority
+ PTR sys_ni_syscall
+ PTR compat_sys_statfs
+ PTR compat_sys_fstatfs /* 4100 */
+ PTR sys_ni_syscall /* sys_ioperm */
+ PTR sys32_socketcall
+ PTR sys_syslog
+ PTR compat_sys_setitimer
+ PTR compat_sys_getitimer /* 4105 */
+ PTR compat_sys_newstat
+ PTR compat_sys_newlstat
+ PTR compat_sys_newfstat
+ PTR sys_uname
+ PTR sys_ni_syscall /* sys_ioperm *//* 4110 */
+ PTR sys_vhangup
+ PTR sys_ni_syscall /* was sys_idle */
+ PTR sys_ni_syscall /* sys_vm86 */
+ PTR sys32_wait4
+ PTR sys_swapoff /* 4115 */
+ PTR sys32_sysinfo
+ PTR sys32_ipc
+ PTR sys_fsync
+ PTR sys32_sigreturn
+ PTR sys_clone /* 4120 */
+ PTR sys_setdomainname
+ PTR sys32_newuname
+ PTR sys_ni_syscall /* sys_modify_ldt */
+ PTR sys32_adjtimex
+ PTR sys_mprotect /* 4125 */
+ PTR compat_sys_sigprocmask
+ PTR sys_ni_syscall /* was creat_module */
+ PTR sys_init_module
+ PTR sys_delete_module
+ PTR sys_ni_syscall /* 4130, get_kernel_syms */
+ PTR sys_quotactl
+ PTR sys_getpgid
+ PTR sys_fchdir
+ PTR sys_bdflush
+ PTR sys_sysfs /* 4135 */
+ PTR sys32_personality
+ PTR sys_ni_syscall /* for afs_syscall */
+ PTR sys_setfsuid
+ PTR sys_setfsgid
+ PTR sys32_llseek /* 4140 */
+ PTR sys32_getdents
+ PTR compat_sys_select
+ PTR sys_flock
+ PTR sys_msync
+ PTR compat_sys_readv /* 4145 */
+ PTR compat_sys_writev
+ PTR sys_cacheflush
+ PTR sys_cachectl
+ PTR sys_sysmips
+ PTR sys_ni_syscall /* 4150 */
+ PTR sys_getsid
+ PTR sys_fdatasync
+ PTR sys32_sysctl
+ PTR sys_mlock
+ PTR sys_munlock /* 4155 */
+ PTR sys_mlockall
+ PTR sys_munlockall
+ PTR sys_sched_setparam
+ PTR sys_sched_getparam
+ PTR sys_sched_setscheduler /* 4160 */
+ PTR sys_sched_getscheduler
+ PTR sys_sched_yield
+ PTR sys_sched_get_priority_max
+ PTR sys_sched_get_priority_min
+ PTR sys32_sched_rr_get_interval /* 4165 */
+ PTR compat_sys_nanosleep
+ PTR sys_mremap
+ PTR sys_accept
+ PTR sys_bind
+ PTR sys_connect /* 4170 */
+ PTR sys_getpeername
+ PTR sys_getsockname
+ PTR sys_getsockopt
+ PTR sys_listen
+ PTR sys_recv /* 4175 */
+ PTR sys_recvfrom
+ PTR compat_sys_recvmsg
+ PTR sys_send
+ PTR compat_sys_sendmsg
+ PTR sys_sendto /* 4180 */
+ PTR compat_sys_setsockopt
+ PTR sys_shutdown
+ PTR sys_socket
+ PTR sys_socketpair
+ PTR sys_setresuid /* 4185 */
+ PTR sys_getresuid
+ PTR sys_ni_syscall /* was query_module */
+ PTR sys_poll
+ PTR sys_nfsservctl
+ PTR sys_setresgid /* 4190 */
+ PTR sys_getresgid
+ PTR sys_prctl
+ PTR sys32_rt_sigreturn
+ PTR sys32_rt_sigaction
+ PTR sys32_rt_sigprocmask /* 4195 */
+ PTR sys32_rt_sigpending
+ PTR compat_sys_rt_sigtimedwait
+ PTR sys32_rt_sigqueueinfo
+ PTR sys32_rt_sigsuspend
+ PTR sys32_pread /* 4200 */
+ PTR sys32_pwrite
+ PTR sys_chown
+ PTR sys_getcwd
+ PTR sys_capget
+ PTR sys_capset /* 4205 */
+ PTR sys32_sigaltstack
+ PTR sys32_sendfile
+ PTR sys_ni_syscall
+ PTR sys_ni_syscall
+ PTR sys32_mmap2 /* 4210 */
+ PTR sys32_truncate64
+ PTR sys32_ftruncate64
+ PTR sys_newstat
+ PTR sys_newlstat
+ PTR sys_newfstat /* 4215 */
+ PTR sys_pivot_root
+ PTR sys_mincore
+ PTR sys_madvise
+ PTR sys_getdents64
+ PTR compat_sys_fcntl64 /* 4220 */
+ PTR sys_ni_syscall
+ PTR sys_gettid
+ PTR sys32_readahead
+ PTR sys_setxattr
+ PTR sys_lsetxattr /* 4225 */
+ PTR sys_fsetxattr
+ PTR sys_getxattr
+ PTR sys_lgetxattr
+ PTR sys_fgetxattr
+ PTR sys_listxattr /* 4230 */
+ PTR sys_llistxattr
+ PTR sys_flistxattr
+ PTR sys_removexattr
+ PTR sys_lremovexattr
+ PTR sys_fremovexattr /* 4235 */
+ PTR sys_tkill
+ PTR sys_sendfile64
+ PTR compat_sys_futex
+ PTR compat_sys_sched_setaffinity
+ PTR compat_sys_sched_getaffinity /* 4240 */
+ PTR sys_io_setup
+ PTR sys_io_destroy
+ PTR sys_io_getevents
+ PTR sys_io_submit
+ PTR sys_io_cancel /* 4245 */
+ PTR sys_exit_group
+ PTR sys_lookup_dcookie
+ PTR sys_epoll_create
+ PTR sys_epoll_ctl
+ PTR sys_epoll_wait /* 4250 */
+ PTR sys_remap_file_pages
+ PTR sys_set_tid_address
+ PTR sys_restart_syscall
+ PTR sys_fadvise64_64
+ PTR compat_sys_statfs64 /* 4255 */
+ PTR compat_sys_fstatfs64
+ PTR sys_timer_create
+ PTR compat_sys_timer_settime
+ PTR compat_sys_timer_gettime
+ PTR sys_timer_getoverrun /* 4260 */
+ PTR sys_timer_delete
+ PTR compat_sys_clock_settime
+ PTR compat_sys_clock_gettime
+ PTR compat_sys_clock_getres
+ PTR compat_sys_clock_nanosleep /* 4265 */
+ PTR sys_tgkill
+ PTR compat_sys_utimes
+ PTR sys_ni_syscall /* sys_mbind */
+ PTR sys_ni_syscall /* sys_get_mempolicy */
+ PTR sys_ni_syscall /* 4270 sys_set_mempolicy */
+ PTR compat_sys_mq_open
+ PTR sys_mq_unlink
+ PTR compat_sys_mq_timedsend
+ PTR compat_sys_mq_timedreceive
+ PTR compat_sys_mq_notify /* 4275 */
+ PTR compat_sys_mq_getsetattr
+ PTR sys_ni_syscall /* sys_vserver */
+ PTR sys_waitid
+ PTR sys_ni_syscall /* available, was setaltroot */
+ PTR sys_add_key /* 4280 */
+ PTR sys_request_key
+ PTR sys_keyctl
+ .size sys_call_table,.-sys_call_table
diff --git a/arch/mips/kernel/semaphore.c b/arch/mips/kernel/semaphore.c
new file mode 100644
index 0000000..9c40fe5
--- /dev/null
+++ b/arch/mips/kernel/semaphore.c
@@ -0,0 +1,164 @@
+/*
+ * MIPS-specific semaphore code.
+ *
+ * Copyright (C) 1999 Cort Dougan <cort@cs.nmt.edu>
+ * Copyright (C) 2004 Ralf Baechle <ralf@linux-mips.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * April 2001 - Reworked by Paul Mackerras <paulus@samba.org>
+ * to eliminate the SMP races in the old version between the updates
+ * of `count' and `waking'. Now we use negative `count' values to
+ * indicate that some process(es) are waiting for the semaphore.
+ */
+
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <asm/atomic.h>
+#include <asm/cpu-features.h>
+#include <asm/errno.h>
+#include <asm/semaphore.h>
+#include <asm/war.h>
+/*
+ * Atomically update sem->count.
+ * This does the equivalent of the following:
+ *
+ * old_count = sem->count;
+ * tmp = MAX(old_count, 0) + incr;
+ * sem->count = tmp;
+ * return old_count;
+ *
+ * On machines without lld/scd we need a spinlock to make the manipulation of
+ * sem->count and sem->waking atomic. Scalability isn't an issue because
+ * this lock is used on UP only so it's just an empty variable.
+ */
+static inline int __sem_update_count(struct semaphore *sem, int incr)
+{
+ int old_count, tmp;
+
+ if (cpu_has_llsc && R10000_LLSC_WAR) {
+ __asm__ __volatile__(
+ "1: ll %0, %2 \n"
+ " sra %1, %0, 31 \n"
+ " not %1 \n"
+ " and %1, %0, %1 \n"
+ " add %1, %1, %3 \n"
+ " sc %1, %2 \n"
+ " beqzl %1, 1b \n"
+ : "=&r" (old_count), "=&r" (tmp), "=m" (sem->count)
+ : "r" (incr), "m" (sem->count));
+ } else if (cpu_has_llsc) {
+ __asm__ __volatile__(
+ "1: ll %0, %2 \n"
+ " sra %1, %0, 31 \n"
+ " not %1 \n"
+ " and %1, %0, %1 \n"
+ " add %1, %1, %3 \n"
+ " sc %1, %2 \n"
+ " beqz %1, 1b \n"
+ : "=&r" (old_count), "=&r" (tmp), "=m" (sem->count)
+ : "r" (incr), "m" (sem->count));
+ } else {
+ static DEFINE_SPINLOCK(semaphore_lock);
+ unsigned long flags;
+
+ spin_lock_irqsave(&semaphore_lock, flags);
+ old_count = atomic_read(&sem->count);
+ tmp = max_t(int, old_count, 0) + incr;
+ atomic_set(&sem->count, tmp);
+ spin_unlock_irqrestore(&semaphore_lock, flags);
+ }
+
+ return old_count;
+}
+
+void __up(struct semaphore *sem)
+{
+ /*
+ * Note that we incremented count in up() before we came here,
+ * but that was ineffective since the result was <= 0, and
+ * any negative value of count is equivalent to 0.
+ * This ends up setting count to 1, unless count is now > 0
+ * (i.e. because some other cpu has called up() in the meantime),
+ * in which case we just increment count.
+ */
+ __sem_update_count(sem, 1);
+ wake_up(&sem->wait);
+}
+
+EXPORT_SYMBOL(__up);
+
+/*
+ * Note that when we come in to __down or __down_interruptible,
+ * we have already decremented count, but that decrement was
+ * ineffective since the result was < 0, and any negative value
+ * of count is equivalent to 0.
+ * Thus it is only when we decrement count from some value > 0
+ * that we have actually got the semaphore.
+ */
+void __sched __down(struct semaphore *sem)
+{
+ struct task_struct *tsk = current;
+ DECLARE_WAITQUEUE(wait, tsk);
+
+ __set_task_state(tsk, TASK_UNINTERRUPTIBLE);
+ add_wait_queue_exclusive(&sem->wait, &wait);
+
+ /*
+ * Try to get the semaphore. If the count is > 0, then we've
+ * got the semaphore; we decrement count and exit the loop.
+ * If the count is 0 or negative, we set it to -1, indicating
+ * that we are asleep, and then sleep.
+ */
+ while (__sem_update_count(sem, -1) <= 0) {
+ schedule();
+ set_task_state(tsk, TASK_UNINTERRUPTIBLE);
+ }
+ remove_wait_queue(&sem->wait, &wait);
+ __set_task_state(tsk, TASK_RUNNING);
+
+ /*
+ * If there are any more sleepers, wake one of them up so
+ * that it can either get the semaphore, or set count to -1
+ * indicating that there are still processes sleeping.
+ */
+ wake_up(&sem->wait);
+}
+
+EXPORT_SYMBOL(__down);
+
+int __sched __down_interruptible(struct semaphore * sem)
+{
+ int retval = 0;
+ struct task_struct *tsk = current;
+ DECLARE_WAITQUEUE(wait, tsk);
+
+ __set_task_state(tsk, TASK_INTERRUPTIBLE);
+ add_wait_queue_exclusive(&sem->wait, &wait);
+
+ while (__sem_update_count(sem, -1) <= 0) {
+ if (signal_pending(current)) {
+ /*
+ * A signal is pending - give up trying.
+ * Set sem->count to 0 if it is negative,
+ * since we are no longer sleeping.
+ */
+ __sem_update_count(sem, 0);
+ retval = -EINTR;
+ break;
+ }
+ schedule();
+ set_task_state(tsk, TASK_INTERRUPTIBLE);
+ }
+ remove_wait_queue(&sem->wait, &wait);
+ __set_task_state(tsk, TASK_RUNNING);
+
+ wake_up(&sem->wait);
+ return retval;
+}
+
+EXPORT_SYMBOL(__down_interruptible);
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
new file mode 100644
index 0000000..6018ca2
--- /dev/null
+++ b/arch/mips/kernel/setup.c
@@ -0,0 +1,571 @@
+/*
+ * 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 Linus Torvalds
+ * Copyright (C) 1995 Waldorf Electronics
+ * Copyright (C) 1994, 95, 96, 97, 98, 99, 2000, 01, 02, 03 Ralf Baechle
+ * Copyright (C) 1996 Stoned Elipot
+ * Copyright (C) 1999 Silicon Graphics, Inc.
+ * Copyright (C) 2000 2001, 2002 Maciej W. Rozycki
+ */
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/stddef.h>
+#include <linux/string.h>
+#include <linux/unistd.h>
+#include <linux/slab.h>
+#include <linux/user.h>
+#include <linux/utsname.h>
+#include <linux/a.out.h>
+#include <linux/tty.h>
+#include <linux/bootmem.h>
+#include <linux/initrd.h>
+#include <linux/major.h>
+#include <linux/kdev_t.h>
+#include <linux/root_dev.h>
+#include <linux/highmem.h>
+#include <linux/console.h>
+
+#include <asm/addrspace.h>
+#include <asm/bootinfo.h>
+#include <asm/cpu.h>
+#include <asm/sections.h>
+#include <asm/setup.h>
+#include <asm/system.h>
+
+struct cpuinfo_mips cpu_data[NR_CPUS];
+
+EXPORT_SYMBOL(cpu_data);
+
+#ifdef CONFIG_VT
+struct screen_info screen_info;
+#endif
+
+/*
+ * Despite it's name this variable is even if we don't have PCI
+ */
+unsigned int PCI_DMA_BUS_IS_PHYS;
+
+EXPORT_SYMBOL(PCI_DMA_BUS_IS_PHYS);
+
+/*
+ * Setup information
+ *
+ * These are initialized so they are in the .data section
+ */
+unsigned long mips_machtype = MACH_UNKNOWN;
+unsigned long mips_machgroup = MACH_GROUP_UNKNOWN;
+
+EXPORT_SYMBOL(mips_machtype);
+EXPORT_SYMBOL(mips_machgroup);
+
+struct boot_mem_map boot_mem_map;
+
+static char command_line[CL_SIZE];
+ char arcs_cmdline[CL_SIZE]=CONFIG_CMDLINE;
+
+/*
+ * 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;
+EXPORT_SYMBOL(mips_io_port_base);
+
+/*
+ * isa_slot_offset is the address where E(ISA) busaddress 0 is mapped
+ * for the processor.
+ */
+unsigned long isa_slot_offset;
+EXPORT_SYMBOL(isa_slot_offset);
+
+static struct resource code_resource = { .name = "Kernel code", };
+static struct resource data_resource = { .name = "Kernel data", };
+
+void __init add_memory_region(phys_t start, phys_t size, long type)
+{
+ int x = boot_mem_map.nr_map;
+ struct boot_mem_map_entry *prev = boot_mem_map.map + x - 1;
+
+ /*
+ * Try to merge with previous entry if any. This is far less than
+ * perfect but is sufficient for most real world cases.
+ */
+ if (x && prev->addr + prev->size == start && prev->type == type) {
+ prev->size += size;
+ return;
+ }
+
+ if (x == BOOT_MEM_MAP_MAX) {
+ printk("Ooops! Too many entries in the memory map!\n");
+ return;
+ }
+
+ boot_mem_map.map[x].addr = start;
+ boot_mem_map.map[x].size = size;
+ boot_mem_map.map[x].type = type;
+ boot_mem_map.nr_map++;
+}
+
+static void __init print_memory_map(void)
+{
+ int i;
+ const int field = 2 * sizeof(unsigned long);
+
+ for (i = 0; i < boot_mem_map.nr_map; i++) {
+ printk(" memory: %0*Lx @ %0*Lx ",
+ field, (unsigned long long) boot_mem_map.map[i].size,
+ field, (unsigned long long) boot_mem_map.map[i].addr);
+
+ switch (boot_mem_map.map[i].type) {
+ case BOOT_MEM_RAM:
+ printk("(usable)\n");
+ break;
+ case BOOT_MEM_ROM_DATA:
+ printk("(ROM data)\n");
+ break;
+ case BOOT_MEM_RESERVED:
+ printk("(reserved)\n");
+ break;
+ default:
+ printk("type %lu\n", boot_mem_map.map[i].type);
+ break;
+ }
+ }
+}
+
+static inline void parse_cmdline_early(void)
+{
+ char c = ' ', *to = command_line, *from = saved_command_line;
+ unsigned long start_at, mem_size;
+ int len = 0;
+ int usermem = 0;
+
+ printk("Determined physical RAM map:\n");
+ print_memory_map();
+
+ for (;;) {
+ /*
+ * "mem=XXX[kKmM]" defines a memory region from
+ * 0 to <XXX>, overriding the determined size.
+ * "mem=XXX[KkmM]@YYY[KkmM]" defines a memory region from
+ * <YYY> to <YYY>+<XXX>, overriding the determined size.
+ */
+ if (c == ' ' && !memcmp(from, "mem=", 4)) {
+ if (to != command_line)
+ to--;
+ /*
+ * If a user specifies memory size, we
+ * blow away any automatically generated
+ * size.
+ */
+ if (usermem == 0) {
+ boot_mem_map.nr_map = 0;
+ usermem = 1;
+ }
+ mem_size = memparse(from + 4, &from);
+ if (*from == '@')
+ start_at = memparse(from + 1, &from);
+ else
+ start_at = 0;
+ add_memory_region(start_at, mem_size, BOOT_MEM_RAM);
+ }
+ c = *(from++);
+ if (!c)
+ break;
+ if (CL_SIZE <= ++len)
+ break;
+ *(to++) = c;
+ }
+ *to = '\0';
+
+ if (usermem) {
+ printk("User-defined physical RAM map:\n");
+ print_memory_map();
+ }
+}
+
+static inline int parse_rd_cmdline(unsigned long* rd_start, unsigned long* rd_end)
+{
+ /*
+ * "rd_start=0xNNNNNNNN" defines the memory address of an initrd
+ * "rd_size=0xNN" it's size
+ */
+ unsigned long start = 0;
+ unsigned long size = 0;
+ unsigned long end;
+ char cmd_line[CL_SIZE];
+ char *start_str;
+ char *size_str;
+ char *tmp;
+
+ strcpy(cmd_line, command_line);
+ *command_line = 0;
+ tmp = cmd_line;
+ /* Ignore "rd_start=" strings in other parameters. */
+ start_str = strstr(cmd_line, "rd_start=");
+ if (start_str && start_str != cmd_line && *(start_str - 1) != ' ')
+ start_str = strstr(start_str, " rd_start=");
+ while (start_str) {
+ if (start_str != cmd_line)
+ strncat(command_line, tmp, start_str - tmp);
+ start = memparse(start_str + 9, &start_str);
+ tmp = start_str + 1;
+ start_str = strstr(start_str, " rd_start=");
+ }
+ if (*tmp)
+ strcat(command_line, tmp);
+
+ strcpy(cmd_line, command_line);
+ *command_line = 0;
+ tmp = cmd_line;
+ /* Ignore "rd_size" strings in other parameters. */
+ size_str = strstr(cmd_line, "rd_size=");
+ if (size_str && size_str != cmd_line && *(size_str - 1) != ' ')
+ size_str = strstr(size_str, " rd_size=");
+ while (size_str) {
+ if (size_str != cmd_line)
+ strncat(command_line, tmp, size_str - tmp);
+ size = memparse(size_str + 8, &size_str);
+ tmp = size_str + 1;
+ size_str = strstr(size_str, " rd_size=");
+ }
+ if (*tmp)
+ strcat(command_line, tmp);
+
+#ifdef CONFIG_MIPS64
+ /* HACK: Guess if the sign extension was forgotten */
+ if (start > 0x0000000080000000 && start < 0x00000000ffffffff)
+ start |= 0xffffffff00000000;
+#endif
+
+ end = start + size;
+ if (start && end) {
+ *rd_start = start;
+ *rd_end = end;
+ return 1;
+ }
+ return 0;
+}
+
+#define PFN_UP(x) (((x) + PAGE_SIZE - 1) >> PAGE_SHIFT)
+#define PFN_DOWN(x) ((x) >> PAGE_SHIFT)
+#define PFN_PHYS(x) ((x) << PAGE_SHIFT)
+
+#define MAXMEM HIGHMEM_START
+#define MAXMEM_PFN PFN_DOWN(MAXMEM)
+
+static inline void bootmem_init(void)
+{
+ unsigned long start_pfn;
+ unsigned long reserved_end = (unsigned long)&_end;
+#ifndef CONFIG_SGI_IP27
+ unsigned long first_usable_pfn;
+ unsigned long bootmap_size;
+ int i;
+#endif
+#ifdef CONFIG_BLK_DEV_INITRD
+ int initrd_reserve_bootmem = 0;
+
+ /* Board specific code should have set up initrd_start and initrd_end */
+ ROOT_DEV = Root_RAM0;
+ if (parse_rd_cmdline(&initrd_start, &initrd_end)) {
+ reserved_end = max(reserved_end, initrd_end);
+ initrd_reserve_bootmem = 1;
+ } else {
+ unsigned long tmp;
+ u32 *initrd_header;
+
+ tmp = ((reserved_end + PAGE_SIZE-1) & PAGE_MASK) - sizeof(u32) * 2;
+ if (tmp < reserved_end)
+ tmp += PAGE_SIZE;
+ initrd_header = (u32 *)tmp;
+ if (initrd_header[0] == 0x494E5244) {
+ initrd_start = (unsigned long)&initrd_header[2];
+ initrd_end = initrd_start + initrd_header[1];
+ reserved_end = max(reserved_end, initrd_end);
+ initrd_reserve_bootmem = 1;
+ }
+ }
+#endif /* CONFIG_BLK_DEV_INITRD */
+
+ /*
+ * Partially used pages are not usable - thus
+ * we are rounding upwards.
+ */
+ start_pfn = PFN_UP(CPHYSADDR(reserved_end));
+
+#ifndef CONFIG_SGI_IP27
+ /* Find the highest page frame number we have available. */
+ max_pfn = 0;
+ first_usable_pfn = -1UL;
+ for (i = 0; i < boot_mem_map.nr_map; i++) {
+ unsigned long start, end;
+
+ if (boot_mem_map.map[i].type != BOOT_MEM_RAM)
+ continue;
+
+ start = PFN_UP(boot_mem_map.map[i].addr);
+ end = PFN_DOWN(boot_mem_map.map[i].addr
+ + boot_mem_map.map[i].size);
+
+ if (start >= end)
+ continue;
+ if (end > max_pfn)
+ max_pfn = end;
+ if (start < first_usable_pfn) {
+ if (start > start_pfn) {
+ first_usable_pfn = start;
+ } else if (end > start_pfn) {
+ first_usable_pfn = start_pfn;
+ }
+ }
+ }
+
+ /*
+ * Determine low and high memory ranges
+ */
+ max_low_pfn = max_pfn;
+ if (max_low_pfn > MAXMEM_PFN) {
+ max_low_pfn = MAXMEM_PFN;
+#ifndef CONFIG_HIGHMEM
+ /* Maximum memory usable is what is directly addressable */
+ printk(KERN_WARNING "Warning only %ldMB will be used.\n",
+ MAXMEM >> 20);
+ printk(KERN_WARNING "Use a HIGHMEM enabled kernel.\n");
+#endif
+ }
+
+#ifdef CONFIG_HIGHMEM
+ /*
+ * Crude, we really should make a better attempt at detecting
+ * highstart_pfn
+ */
+ highstart_pfn = highend_pfn = max_pfn;
+ if (max_pfn > MAXMEM_PFN) {
+ highstart_pfn = MAXMEM_PFN;
+ printk(KERN_NOTICE "%ldMB HIGHMEM available.\n",
+ (highend_pfn - highstart_pfn) >> (20 - PAGE_SHIFT));
+ }
+#endif
+
+ /* Initialize the boot-time allocator with low memory only. */
+ bootmap_size = init_bootmem(first_usable_pfn, max_low_pfn);
+
+ /*
+ * Register fully available low RAM pages with the bootmem allocator.
+ */
+ for (i = 0; i < boot_mem_map.nr_map; i++) {
+ unsigned long curr_pfn, last_pfn, size;
+
+ /*
+ * Reserve usable memory.
+ */
+ if (boot_mem_map.map[i].type != BOOT_MEM_RAM)
+ continue;
+
+ /*
+ * We are rounding up the start address of usable memory:
+ */
+ curr_pfn = PFN_UP(boot_mem_map.map[i].addr);
+ if (curr_pfn >= max_low_pfn)
+ continue;
+ if (curr_pfn < start_pfn)
+ curr_pfn = start_pfn;
+
+ /*
+ * ... and at the end of the usable range downwards:
+ */
+ last_pfn = PFN_DOWN(boot_mem_map.map[i].addr
+ + boot_mem_map.map[i].size);
+
+ if (last_pfn > max_low_pfn)
+ last_pfn = max_low_pfn;
+
+ /*
+ * Only register lowmem part of lowmem segment with bootmem.
+ */
+ size = last_pfn - curr_pfn;
+ if (curr_pfn > PFN_DOWN(HIGHMEM_START))
+ continue;
+ if (curr_pfn + size - 1 > PFN_DOWN(HIGHMEM_START))
+ size = PFN_DOWN(HIGHMEM_START) - curr_pfn;
+ if (!size)
+ continue;
+
+ /*
+ * ... finally, did all the rounding and playing
+ * around just make the area go away?
+ */
+ if (last_pfn <= curr_pfn)
+ continue;
+
+ /* Register lowmem ranges */
+ free_bootmem(PFN_PHYS(curr_pfn), PFN_PHYS(size));
+ }
+
+ /* Reserve the bootmap memory. */
+ reserve_bootmem(PFN_PHYS(first_usable_pfn), bootmap_size);
+#endif /* CONFIG_SGI_IP27 */
+
+#ifdef CONFIG_BLK_DEV_INITRD
+ initrd_below_start_ok = 1;
+ if (initrd_start) {
+ unsigned long initrd_size = ((unsigned char *)initrd_end) - ((unsigned char *)initrd_start);
+ printk("Initial ramdisk at: 0x%p (%lu bytes)\n",
+ (void *)initrd_start, initrd_size);
+
+ if (CPHYSADDR(initrd_end) > PFN_PHYS(max_low_pfn)) {
+ printk("initrd extends beyond end of memory "
+ "(0x%0*Lx > 0x%0*Lx)\ndisabling initrd\n",
+ sizeof(long) * 2,
+ (unsigned long long)CPHYSADDR(initrd_end),
+ sizeof(long) * 2,
+ (unsigned long long)PFN_PHYS(max_low_pfn));
+ initrd_start = initrd_end = 0;
+ initrd_reserve_bootmem = 0;
+ }
+
+ if (initrd_reserve_bootmem)
+ reserve_bootmem(CPHYSADDR(initrd_start), initrd_size);
+ }
+#endif /* CONFIG_BLK_DEV_INITRD */
+}
+
+static inline void resource_init(void)
+{
+ int i;
+
+#if defined(CONFIG_MIPS64) && !defined(CONFIG_BUILD_ELF64)
+ /*
+ * The 64bit code in 32bit object format trick can't represent
+ * 64bit wide relocations for linker script symbols.
+ */
+ code_resource.start = CPHYSADDR(&_text);
+ code_resource.end = CPHYSADDR(&_etext) - 1;
+ data_resource.start = CPHYSADDR(&_etext);
+ data_resource.end = CPHYSADDR(&_edata) - 1;
+#else
+ code_resource.start = virt_to_phys(&_text);
+ code_resource.end = virt_to_phys(&_etext) - 1;
+ data_resource.start = virt_to_phys(&_etext);
+ data_resource.end = virt_to_phys(&_edata) - 1;
+#endif
+
+ /*
+ * Request address space for all standard RAM.
+ */
+ for (i = 0; i < boot_mem_map.nr_map; i++) {
+ struct resource *res;
+ unsigned long start, end;
+
+ start = boot_mem_map.map[i].addr;
+ end = boot_mem_map.map[i].addr + boot_mem_map.map[i].size - 1;
+ if (start >= MAXMEM)
+ continue;
+ if (end >= MAXMEM)
+ end = MAXMEM - 1;
+
+ res = alloc_bootmem(sizeof(struct resource));
+ switch (boot_mem_map.map[i].type) {
+ case BOOT_MEM_RAM:
+ case BOOT_MEM_ROM_DATA:
+ res->name = "System RAM";
+ break;
+ case BOOT_MEM_RESERVED:
+ default:
+ res->name = "reserved";
+ }
+
+ res->start = start;
+ res->end = end;
+
+ res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+ request_resource(&iomem_resource, res);
+
+ /*
+ * We don't know which RAM region contains kernel data,
+ * so we try it repeatedly and let the resource manager
+ * test it.
+ */
+ request_resource(res, &code_resource);
+ request_resource(res, &data_resource);
+ }
+}
+
+#undef PFN_UP
+#undef PFN_DOWN
+#undef PFN_PHYS
+
+#undef MAXMEM
+#undef MAXMEM_PFN
+
+static int __initdata earlyinit_debug;
+
+static int __init earlyinit_debug_setup(char *str)
+{
+ earlyinit_debug = 1;
+ return 1;
+}
+__setup("earlyinit_debug", earlyinit_debug_setup);
+
+extern initcall_t __earlyinitcall_start, __earlyinitcall_end;
+
+static void __init do_earlyinitcalls(void)
+{
+ initcall_t *call, *start, *end;
+
+ start = &__earlyinitcall_start;
+ end = &__earlyinitcall_end;
+
+ for (call = start; call < end; call++) {
+ if (earlyinit_debug)
+ printk("calling earlyinitcall 0x%p\n", *call);
+
+ (*call)();
+ }
+}
+
+void __init setup_arch(char **cmdline_p)
+{
+ cpu_probe();
+ prom_init();
+ cpu_report();
+
+#if defined(CONFIG_VT)
+#if defined(CONFIG_VGA_CONSOLE)
+ conswitchp = &vga_con;
+#elif defined(CONFIG_DUMMY_CONSOLE)
+ conswitchp = &dummy_con;
+#endif
+#endif
+
+ /* call board setup routine */
+ do_earlyinitcalls();
+
+ strlcpy(command_line, arcs_cmdline, sizeof(command_line));
+ strlcpy(saved_command_line, command_line, COMMAND_LINE_SIZE);
+
+ *cmdline_p = command_line;
+
+ parse_cmdline_early();
+ bootmem_init();
+ paging_init();
+ resource_init();
+}
+
+int __init fpu_disable(char *s)
+{
+ cpu_data[0].options &= ~MIPS_CPU_FPU;
+
+ return 1;
+}
+
+__setup("nofpu", fpu_disable);
diff --git a/arch/mips/kernel/signal-common.h b/arch/mips/kernel/signal-common.h
new file mode 100644
index 0000000..f9234df
--- /dev/null
+++ b/arch/mips/kernel/signal-common.h
@@ -0,0 +1,137 @@
+/*
+ * 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) 1991, 1992 Linus Torvalds
+ * Copyright (C) 1994 - 2000 Ralf Baechle
+ * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
+ */
+
+static inline int
+setup_sigcontext(struct pt_regs *regs, struct sigcontext *sc)
+{
+ int err = 0;
+
+ err |= __put_user(regs->cp0_epc, &sc->sc_pc);
+ err |= __put_user(regs->cp0_status, &sc->sc_status);
+
+#define save_gp_reg(i) do { \
+ err |= __put_user(regs->regs[i], &sc->sc_regs[i]); \
+} while(0)
+ __put_user(0, &sc->sc_regs[0]); save_gp_reg(1); save_gp_reg(2);
+ save_gp_reg(3); save_gp_reg(4); save_gp_reg(5); save_gp_reg(6);
+ save_gp_reg(7); save_gp_reg(8); save_gp_reg(9); save_gp_reg(10);
+ save_gp_reg(11); save_gp_reg(12); save_gp_reg(13); save_gp_reg(14);
+ save_gp_reg(15); save_gp_reg(16); save_gp_reg(17); save_gp_reg(18);
+ save_gp_reg(19); save_gp_reg(20); save_gp_reg(21); save_gp_reg(22);
+ save_gp_reg(23); save_gp_reg(24); save_gp_reg(25); save_gp_reg(26);
+ save_gp_reg(27); save_gp_reg(28); save_gp_reg(29); save_gp_reg(30);
+ save_gp_reg(31);
+#undef save_gp_reg
+
+ err |= __put_user(regs->hi, &sc->sc_mdhi);
+ err |= __put_user(regs->lo, &sc->sc_mdlo);
+ err |= __put_user(regs->cp0_cause, &sc->sc_cause);
+ err |= __put_user(regs->cp0_badvaddr, &sc->sc_badvaddr);
+
+ err |= __put_user(!!used_math(), &sc->sc_used_math);
+
+ if (!used_math())
+ goto out;
+
+ /*
+ * Save FPU state to signal context. Signal handler will "inherit"
+ * current FPU state.
+ */
+ preempt_disable();
+
+ if (!is_fpu_owner()) {
+ own_fpu();
+ restore_fp(current);
+ }
+ err |= save_fp_context(sc);
+
+ preempt_enable();
+
+out:
+ return err;
+}
+
+static inline int
+restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc)
+{
+ int err = 0;
+ unsigned int used_math;
+
+ /* Always make any pending restarted system calls return -EINTR */
+ current_thread_info()->restart_block.fn = do_no_restart_syscall;
+
+ err |= __get_user(regs->cp0_epc, &sc->sc_pc);
+ err |= __get_user(regs->hi, &sc->sc_mdhi);
+ err |= __get_user(regs->lo, &sc->sc_mdlo);
+
+#define restore_gp_reg(i) do { \
+ err |= __get_user(regs->regs[i], &sc->sc_regs[i]); \
+} while(0)
+ restore_gp_reg( 1); restore_gp_reg( 2); restore_gp_reg( 3);
+ restore_gp_reg( 4); restore_gp_reg( 5); restore_gp_reg( 6);
+ restore_gp_reg( 7); restore_gp_reg( 8); restore_gp_reg( 9);
+ restore_gp_reg(10); restore_gp_reg(11); restore_gp_reg(12);
+ restore_gp_reg(13); restore_gp_reg(14); restore_gp_reg(15);
+ restore_gp_reg(16); restore_gp_reg(17); restore_gp_reg(18);
+ restore_gp_reg(19); restore_gp_reg(20); restore_gp_reg(21);
+ restore_gp_reg(22); restore_gp_reg(23); restore_gp_reg(24);
+ restore_gp_reg(25); restore_gp_reg(26); restore_gp_reg(27);
+ restore_gp_reg(28); restore_gp_reg(29); restore_gp_reg(30);
+ restore_gp_reg(31);
+#undef restore_gp_reg
+
+ err |= __get_user(used_math, &sc->sc_used_math);
+ conditional_used_math(used_math);
+
+ preempt_disable();
+
+ if (used_math()) {
+ /* restore fpu context if we have used it before */
+ own_fpu();
+ err |= restore_fp_context(sc);
+ } else {
+ /* signal handler may have used FPU. Give it up. */
+ lose_fpu();
+ }
+
+ preempt_enable();
+
+ return err;
+}
+
+/*
+ * Determine which stack to use..
+ */
+static inline void *
+get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
+{
+ unsigned long sp, almask;
+
+ /* Default to using normal stack */
+ sp = regs->regs[29];
+
+ /*
+ * FPU emulator may have it's own trampoline active just
+ * above the user stack, 16-bytes before the next lowest
+ * 16 byte boundary. Try to avoid trashing it.
+ */
+ sp -= 32;
+
+ /* This is the X/Open sanctioned signal stack switching. */
+ if ((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags (sp) == 0))
+ sp = current->sas_ss_sp + current->sas_ss_size;
+
+ if (PLAT_TRAMPOLINE_STUFF_LINE)
+ almask = ~(PLAT_TRAMPOLINE_STUFF_LINE - 1);
+ else
+ almask = ALMASK;
+
+ return (void *)((sp - frame_size) & almask);
+}
diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c
new file mode 100644
index 0000000..508026a
--- /dev/null
+++ b/arch/mips/kernel/signal.c
@@ -0,0 +1,517 @@
+/*
+ * 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) 1991, 1992 Linus Torvalds
+ * Copyright (C) 1994 - 2000 Ralf Baechle
+ * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
+ */
+#include <linux/config.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/personality.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/kernel.h>
+#include <linux/signal.h>
+#include <linux/errno.h>
+#include <linux/wait.h>
+#include <linux/ptrace.h>
+#include <linux/unistd.h>
+#include <linux/compiler.h>
+
+#include <asm/asm.h>
+#include <linux/bitops.h>
+#include <asm/cacheflush.h>
+#include <asm/fpu.h>
+#include <asm/sim.h>
+#include <asm/uaccess.h>
+#include <asm/ucontext.h>
+#include <asm/cpu-features.h>
+
+#include "signal-common.h"
+
+#define DEBUG_SIG 0
+
+#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
+
+static int do_signal(sigset_t *oldset, struct pt_regs *regs);
+
+/*
+ * Atomically swap in the new signal mask, and wait for a signal.
+ */
+
+#ifdef CONFIG_TRAD_SIGNALS
+save_static_function(sys_sigsuspend);
+__attribute_used__ noinline static int
+_sys_sigsuspend(nabi_no_regargs struct pt_regs regs)
+{
+ sigset_t *uset, saveset, newset;
+
+ uset = (sigset_t *) regs.regs[4];
+ if (copy_from_user(&newset, uset, sizeof(sigset_t)))
+ return -EFAULT;
+ sigdelsetmask(&newset, ~_BLOCKABLE);
+
+ spin_lock_irq(¤t->sighand->siglock);
+ saveset = current->blocked;
+ current->blocked = newset;
+ recalc_sigpending();
+ spin_unlock_irq(¤t->sighand->siglock);
+
+ regs.regs[2] = EINTR;
+ regs.regs[7] = 1;
+ while (1) {
+ current->state = TASK_INTERRUPTIBLE;
+ schedule();
+ if (do_signal(&saveset, ®s))
+ return -EINTR;
+ }
+}
+#endif
+
+save_static_function(sys_rt_sigsuspend);
+__attribute_used__ noinline static int
+_sys_rt_sigsuspend(nabi_no_regargs struct pt_regs regs)
+{
+ sigset_t *unewset, saveset, newset;
+ size_t sigsetsize;
+
+ /* XXX Don't preclude handling different sized sigset_t's. */
+ sigsetsize = regs.regs[5];
+ if (sigsetsize != sizeof(sigset_t))
+ return -EINVAL;
+
+ unewset = (sigset_t *) regs.regs[4];
+ if (copy_from_user(&newset, unewset, sizeof(newset)))
+ return -EFAULT;
+ sigdelsetmask(&newset, ~_BLOCKABLE);
+
+ spin_lock_irq(¤t->sighand->siglock);
+ saveset = current->blocked;
+ current->blocked = newset;
+ recalc_sigpending();
+ spin_unlock_irq(¤t->sighand->siglock);
+
+ regs.regs[2] = EINTR;
+ regs.regs[7] = 1;
+ while (1) {
+ current->state = TASK_INTERRUPTIBLE;
+ schedule();
+ if (do_signal(&saveset, ®s))
+ return -EINTR;
+ }
+}
+
+#ifdef CONFIG_TRAD_SIGNALS
+asmlinkage int sys_sigaction(int sig, const struct sigaction *act,
+ struct sigaction *oact)
+{
+ struct k_sigaction new_ka, old_ka;
+ int ret;
+ int err = 0;
+
+ if (act) {
+ old_sigset_t mask;
+
+ if (!access_ok(VERIFY_READ, act, sizeof(*act)))
+ return -EFAULT;
+ err |= __get_user(new_ka.sa.sa_handler, &act->sa_handler);
+ err |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
+ err |= __get_user(mask, &act->sa_mask.sig[0]);
+ if (err)
+ return -EFAULT;
+
+ siginitset(&new_ka.sa.sa_mask, mask);
+ }
+
+ ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
+
+ if (!ret && oact) {
+ if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)))
+ return -EFAULT;
+ err |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
+ err |= __put_user(old_ka.sa.sa_handler, &oact->sa_handler);
+ err |= __put_user(old_ka.sa.sa_mask.sig[0], oact->sa_mask.sig);
+ err |= __put_user(0, &oact->sa_mask.sig[1]);
+ err |= __put_user(0, &oact->sa_mask.sig[2]);
+ err |= __put_user(0, &oact->sa_mask.sig[3]);
+ if (err)
+ return -EFAULT;
+ }
+
+ return ret;
+}
+#endif
+
+asmlinkage int sys_sigaltstack(nabi_no_regargs struct pt_regs regs)
+{
+ const stack_t *uss = (const stack_t *) regs.regs[4];
+ stack_t *uoss = (stack_t *) regs.regs[5];
+ unsigned long usp = regs.regs[29];
+
+ return do_sigaltstack(uss, uoss, usp);
+}
+
+#if PLAT_TRAMPOLINE_STUFF_LINE
+#define __tramp __attribute__((aligned(PLAT_TRAMPOLINE_STUFF_LINE)))
+#else
+#define __tramp
+#endif
+
+#ifdef CONFIG_TRAD_SIGNALS
+struct sigframe {
+ u32 sf_ass[4]; /* argument save space for o32 */
+ u32 sf_code[2] __tramp; /* signal trampoline */
+ struct sigcontext sf_sc __tramp;
+ sigset_t sf_mask;
+};
+#endif
+
+struct rt_sigframe {
+ u32 rs_ass[4]; /* argument save space for o32 */
+ u32 rs_code[2] __tramp; /* signal trampoline */
+ struct siginfo rs_info __tramp;
+ struct ucontext rs_uc;
+};
+
+#ifdef CONFIG_TRAD_SIGNALS
+save_static_function(sys_sigreturn);
+__attribute_used__ noinline static void
+_sys_sigreturn(nabi_no_regargs struct pt_regs regs)
+{
+ struct sigframe *frame;
+ sigset_t blocked;
+
+ frame = (struct sigframe *) regs.regs[29];
+ if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
+ goto badframe;
+ if (__copy_from_user(&blocked, &frame->sf_mask, sizeof(blocked)))
+ goto badframe;
+
+ sigdelsetmask(&blocked, ~_BLOCKABLE);
+ spin_lock_irq(¤t->sighand->siglock);
+ current->blocked = blocked;
+ recalc_sigpending();
+ spin_unlock_irq(¤t->sighand->siglock);
+
+ if (restore_sigcontext(®s, &frame->sf_sc))
+ goto badframe;
+
+ /*
+ * Don't let your children do this ...
+ */
+ if (current_thread_info()->flags & TIF_SYSCALL_TRACE)
+ do_syscall_trace(®s, 1);
+ __asm__ __volatile__(
+ "move\t$29, %0\n\t"
+ "j\tsyscall_exit"
+ :/* no outputs */
+ :"r" (®s));
+ /* Unreached */
+
+badframe:
+ force_sig(SIGSEGV, current);
+}
+#endif
+
+save_static_function(sys_rt_sigreturn);
+__attribute_used__ noinline static void
+_sys_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
+{
+ struct rt_sigframe *frame;
+ sigset_t set;
+ stack_t st;
+
+ frame = (struct rt_sigframe *) regs.regs[29];
+ if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
+ goto badframe;
+ if (__copy_from_user(&set, &frame->rs_uc.uc_sigmask, sizeof(set)))
+ goto badframe;
+
+ sigdelsetmask(&set, ~_BLOCKABLE);
+ spin_lock_irq(¤t->sighand->siglock);
+ current->blocked = set;
+ recalc_sigpending();
+ spin_unlock_irq(¤t->sighand->siglock);
+
+ if (restore_sigcontext(®s, &frame->rs_uc.uc_mcontext))
+ goto badframe;
+
+ if (__copy_from_user(&st, &frame->rs_uc.uc_stack, sizeof(st)))
+ goto badframe;
+ /* It is more difficult to avoid calling this function than to
+ call it and ignore errors. */
+ do_sigaltstack(&st, NULL, regs.regs[29]);
+
+ /*
+ * Don't let your children do this ...
+ */
+ __asm__ __volatile__(
+ "move\t$29, %0\n\t"
+ "j\tsyscall_exit"
+ :/* no outputs */
+ :"r" (®s));
+ /* Unreached */
+
+badframe:
+ force_sig(SIGSEGV, current);
+}
+
+#ifdef CONFIG_TRAD_SIGNALS
+static void inline setup_frame(struct k_sigaction * ka, struct pt_regs *regs,
+ int signr, sigset_t *set)
+{
+ struct sigframe *frame;
+ int err = 0;
+
+ frame = get_sigframe(ka, regs, sizeof(*frame));
+ if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
+ goto give_sigsegv;
+
+ /*
+ * Set up the return code ...
+ *
+ * li v0, __NR_sigreturn
+ * syscall
+ */
+ if (PLAT_TRAMPOLINE_STUFF_LINE)
+ __clear_user(frame->sf_code, PLAT_TRAMPOLINE_STUFF_LINE);
+ err |= __put_user(0x24020000 + __NR_sigreturn, frame->sf_code + 0);
+ err |= __put_user(0x0000000c , frame->sf_code + 1);
+ flush_cache_sigtramp((unsigned long) frame->sf_code);
+
+ err |= setup_sigcontext(regs, &frame->sf_sc);
+ err |= __copy_to_user(&frame->sf_mask, set, sizeof(*set));
+ if (err)
+ goto give_sigsegv;
+
+ /*
+ * Arguments to signal handler:
+ *
+ * a0 = signal number
+ * a1 = 0 (should be cause)
+ * a2 = pointer to struct sigcontext
+ *
+ * $25 and c0_epc point to the signal handler, $29 points to the
+ * struct sigframe.
+ */
+ regs->regs[ 4] = signr;
+ regs->regs[ 5] = 0;
+ regs->regs[ 6] = (unsigned long) &frame->sf_sc;
+ regs->regs[29] = (unsigned long) frame;
+ regs->regs[31] = (unsigned long) frame->sf_code;
+ regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;
+
+#if DEBUG_SIG
+ printk("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%p\n",
+ current->comm, current->pid,
+ frame, regs->cp0_epc, frame->regs[31]);
+#endif
+ return;
+
+give_sigsegv:
+ force_sigsegv(signr, current);
+}
+#endif
+
+static void inline setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs,
+ int signr, sigset_t *set, siginfo_t *info)
+{
+ struct rt_sigframe *frame;
+ int err = 0;
+
+ frame = get_sigframe(ka, regs, sizeof(*frame));
+ if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
+ goto give_sigsegv;
+
+ /*
+ * Set up the return code ...
+ *
+ * li v0, __NR_rt_sigreturn
+ * syscall
+ */
+ if (PLAT_TRAMPOLINE_STUFF_LINE)
+ __clear_user(frame->rs_code, PLAT_TRAMPOLINE_STUFF_LINE);
+ err |= __put_user(0x24020000 + __NR_rt_sigreturn, frame->rs_code + 0);
+ err |= __put_user(0x0000000c , frame->rs_code + 1);
+ flush_cache_sigtramp((unsigned long) frame->rs_code);
+
+ /* Create siginfo. */
+ err |= copy_siginfo_to_user(&frame->rs_info, info);
+
+ /* Create the ucontext. */
+ err |= __put_user(0, &frame->rs_uc.uc_flags);
+ err |= __put_user(0, &frame->rs_uc.uc_link);
+ err |= __put_user((void *)current->sas_ss_sp,
+ &frame->rs_uc.uc_stack.ss_sp);
+ err |= __put_user(sas_ss_flags(regs->regs[29]),
+ &frame->rs_uc.uc_stack.ss_flags);
+ err |= __put_user(current->sas_ss_size,
+ &frame->rs_uc.uc_stack.ss_size);
+ err |= setup_sigcontext(regs, &frame->rs_uc.uc_mcontext);
+ err |= __copy_to_user(&frame->rs_uc.uc_sigmask, set, sizeof(*set));
+
+ if (err)
+ goto give_sigsegv;
+
+ /*
+ * Arguments to signal handler:
+ *
+ * a0 = signal number
+ * a1 = 0 (should be cause)
+ * a2 = pointer to ucontext
+ *
+ * $25 and c0_epc point to the signal handler, $29 points to
+ * the struct rt_sigframe.
+ */
+ regs->regs[ 4] = signr;
+ regs->regs[ 5] = (unsigned long) &frame->rs_info;
+ regs->regs[ 6] = (unsigned long) &frame->rs_uc;
+ regs->regs[29] = (unsigned long) frame;
+ regs->regs[31] = (unsigned long) frame->rs_code;
+ regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;
+
+#if DEBUG_SIG
+ printk("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%p\n",
+ current->comm, current->pid,
+ frame, regs->cp0_epc, regs->regs[31]);
+#endif
+ return;
+
+give_sigsegv:
+ force_sigsegv(signr, current);
+}
+
+extern void setup_rt_frame_n32(struct k_sigaction * ka,
+ struct pt_regs *regs, int signr, sigset_t *set, siginfo_t *info);
+
+static inline void handle_signal(unsigned long sig, siginfo_t *info,
+ struct k_sigaction *ka, sigset_t *oldset, struct pt_regs *regs)
+{
+ switch(regs->regs[0]) {
+ case ERESTART_RESTARTBLOCK:
+ case ERESTARTNOHAND:
+ regs->regs[2] = EINTR;
+ break;
+ case ERESTARTSYS:
+ if(!(ka->sa.sa_flags & SA_RESTART)) {
+ regs->regs[2] = EINTR;
+ break;
+ }
+ /* fallthrough */
+ case ERESTARTNOINTR: /* Userland will reload $v0. */
+ regs->regs[7] = regs->regs[26];
+ regs->cp0_epc -= 8;
+ }
+
+ regs->regs[0] = 0; /* Don't deal with this again. */
+
+#ifdef CONFIG_TRAD_SIGNALS
+ if (ka->sa.sa_flags & SA_SIGINFO) {
+#else
+ if (1) {
+#endif
+#ifdef CONFIG_MIPS32_N32
+ if ((current->thread.mflags & MF_ABI_MASK) == MF_N32)
+ setup_rt_frame_n32 (ka, regs, sig, oldset, info);
+ else
+#endif
+ setup_rt_frame(ka, regs, sig, oldset, info);
+ }
+#ifdef CONFIG_TRAD_SIGNALS
+ else
+ setup_frame(ka, regs, sig, oldset);
+#endif
+
+ if (!(ka->sa.sa_flags & SA_NODEFER)) {
+ spin_lock_irq(¤t->sighand->siglock);
+ sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask);
+ sigaddset(¤t->blocked,sig);
+ recalc_sigpending();
+ spin_unlock_irq(¤t->sighand->siglock);
+ }
+}
+
+extern int do_signal32(sigset_t *oldset, struct pt_regs *regs);
+extern int do_irix_signal(sigset_t *oldset, struct pt_regs *regs);
+
+static int do_signal(sigset_t *oldset, struct pt_regs *regs)
+{
+ struct k_sigaction ka;
+ siginfo_t info;
+ int signr;
+
+#ifdef CONFIG_BINFMT_ELF32
+ if ((current->thread.mflags & MF_ABI_MASK) == MF_O32) {
+ return do_signal32(oldset, regs);
+ }
+#endif
+
+ /*
+ * We want the common case to go fast, which is why we may in certain
+ * cases get here from kernel mode. Just return without doing anything
+ * if so.
+ */
+ if (!user_mode(regs))
+ return 1;
+
+ if (try_to_freeze(0))
+ goto no_signal;
+
+ if (!oldset)
+ oldset = ¤t->blocked;
+
+ signr = get_signal_to_deliver(&info, &ka, regs, NULL);
+ if (signr > 0) {
+ handle_signal(signr, &info, &ka, oldset, regs);
+ return 1;
+ }
+
+no_signal:
+ /*
+ * Who's code doesn't conform to the restartable syscall convention
+ * dies here!!! The li instruction, a single machine instruction,
+ * must directly be followed by the syscall instruction.
+ */
+ if (regs->regs[0]) {
+ if (regs->regs[2] == ERESTARTNOHAND ||
+ regs->regs[2] == ERESTARTSYS ||
+ regs->regs[2] == ERESTARTNOINTR) {
+ regs->regs[7] = regs->regs[26];
+ regs->cp0_epc -= 8;
+ }
+ if (regs->regs[2] == ERESTART_RESTARTBLOCK) {
+ regs->regs[2] = __NR_restart_syscall;
+ regs->regs[7] = regs->regs[26];
+ regs->cp0_epc -= 4;
+ }
+ }
+ return 0;
+}
+
+/*
+ * notification of userspace execution resumption
+ * - triggered by current->work.notify_resume
+ */
+asmlinkage void do_notify_resume(struct pt_regs *regs, sigset_t *oldset,
+ __u32 thread_info_flags)
+{
+ /* deal with pending signal delivery */
+ if (thread_info_flags & _TIF_SIGPENDING) {
+#ifdef CONFIG_BINFMT_ELF32
+ if (likely((current->thread.mflags & MF_ABI_MASK) == MF_O32)) {
+ do_signal32(oldset, regs);
+ return;
+ }
+#endif
+#ifdef CONFIG_BINFMT_IRIX
+ if (unlikely(current->personality != PER_LINUX)) {
+ do_irix_signal(oldset, regs);
+ return;
+ }
+#endif
+ do_signal(oldset, regs);
+ }
+}
diff --git a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c
new file mode 100644
index 0000000..1f3b191
--- /dev/null
+++ b/arch/mips/kernel/signal32.c
@@ -0,0 +1,905 @@
+/*
+ * 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) 1991, 1992 Linus Torvalds
+ * Copyright (C) 1994 - 2000 Ralf Baechle
+ * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
+ */
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/kernel.h>
+#include <linux/signal.h>
+#include <linux/syscalls.h>
+#include <linux/errno.h>
+#include <linux/wait.h>
+#include <linux/ptrace.h>
+#include <linux/compat.h>
+#include <linux/suspend.h>
+#include <linux/compiler.h>
+
+#include <asm/asm.h>
+#include <linux/bitops.h>
+#include <asm/cacheflush.h>
+#include <asm/sim.h>
+#include <asm/uaccess.h>
+#include <asm/ucontext.h>
+#include <asm/system.h>
+#include <asm/fpu.h>
+
+#define SI_PAD_SIZE32 ((SI_MAX_SIZE/sizeof(int)) - 3)
+
+typedef struct compat_siginfo {
+ int si_signo;
+ int si_code;
+ int si_errno;
+
+ union {
+ int _pad[SI_PAD_SIZE32];
+
+ /* kill() */
+ struct {
+ compat_pid_t _pid; /* sender's pid */
+ compat_uid_t _uid; /* sender's uid */
+ } _kill;
+
+ /* SIGCHLD */
+ struct {
+ compat_pid_t _pid; /* which child */
+ compat_uid_t _uid; /* sender's uid */
+ int _status; /* exit code */
+ compat_clock_t _utime;
+ compat_clock_t _stime;
+ } _sigchld;
+
+ /* IRIX SIGCHLD */
+ struct {
+ compat_pid_t _pid; /* which child */
+ compat_clock_t _utime;
+ int _status; /* exit code */
+ compat_clock_t _stime;
+ } _irix_sigchld;
+
+ /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
+ struct {
+ s32 _addr; /* faulting insn/memory ref. */
+ } _sigfault;
+
+ /* SIGPOLL, SIGXFSZ (To do ...) */
+ struct {
+ int _band; /* POLL_IN, POLL_OUT, POLL_MSG */
+ int _fd;
+ } _sigpoll;
+
+ /* POSIX.1b timers */
+ struct {
+ unsigned int _timer1;
+ unsigned int _timer2;
+ } _timer;
+
+ /* POSIX.1b signals */
+ struct {
+ compat_pid_t _pid; /* sender's pid */
+ compat_uid_t _uid; /* sender's uid */
+ compat_sigval_t _sigval;
+ } _rt;
+
+ } _sifields;
+} compat_siginfo_t;
+
+/*
+ * Including <asm/unistd.h> would give use the 64-bit syscall numbers ...
+ */
+#define __NR_O32_sigreturn 4119
+#define __NR_O32_rt_sigreturn 4193
+#define __NR_O32_restart_syscall 4253
+
+#define DEBUG_SIG 0
+
+#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
+
+extern int do_signal32(sigset_t *oldset, struct pt_regs *regs);
+
+/* 32-bit compatibility types */
+
+#define _NSIG_BPW32 32
+#define _NSIG_WORDS32 (_NSIG / _NSIG_BPW32)
+
+typedef struct {
+ unsigned int sig[_NSIG_WORDS32];
+} sigset_t32;
+
+typedef unsigned int __sighandler32_t;
+typedef void (*vfptr_t)(void);
+
+struct sigaction32 {
+ unsigned int sa_flags;
+ __sighandler32_t sa_handler;
+ compat_sigset_t sa_mask;
+};
+
+/* IRIX compatible stack_t */
+typedef struct sigaltstack32 {
+ s32 ss_sp;
+ compat_size_t ss_size;
+ int ss_flags;
+} stack32_t;
+
+struct ucontext32 {
+ u32 uc_flags;
+ s32 uc_link;
+ stack32_t uc_stack;
+ struct sigcontext32 uc_mcontext;
+ sigset_t32 uc_sigmask; /* mask last for extensibility */
+};
+
+extern void __put_sigset_unknown_nsig(void);
+extern void __get_sigset_unknown_nsig(void);
+
+static inline int put_sigset(const sigset_t *kbuf, compat_sigset_t *ubuf)
+{
+ int err = 0;
+
+ if (!access_ok(VERIFY_WRITE, ubuf, sizeof(*ubuf)))
+ return -EFAULT;
+
+ switch (_NSIG_WORDS) {
+ default:
+ __put_sigset_unknown_nsig();
+ case 2:
+ err |= __put_user (kbuf->sig[1] >> 32, &ubuf->sig[3]);
+ err |= __put_user (kbuf->sig[1] & 0xffffffff, &ubuf->sig[2]);
+ case 1:
+ err |= __put_user (kbuf->sig[0] >> 32, &ubuf->sig[1]);
+ err |= __put_user (kbuf->sig[0] & 0xffffffff, &ubuf->sig[0]);
+ }
+
+ return err;
+}
+
+static inline int get_sigset(sigset_t *kbuf, const compat_sigset_t *ubuf)
+{
+ int err = 0;
+ unsigned long sig[4];
+
+ if (!access_ok(VERIFY_READ, ubuf, sizeof(*ubuf)))
+ return -EFAULT;
+
+ switch (_NSIG_WORDS) {
+ default:
+ __get_sigset_unknown_nsig();
+ case 2:
+ err |= __get_user (sig[3], &ubuf->sig[3]);
+ err |= __get_user (sig[2], &ubuf->sig[2]);
+ kbuf->sig[1] = sig[2] | (sig[3] << 32);
+ case 1:
+ err |= __get_user (sig[1], &ubuf->sig[1]);
+ err |= __get_user (sig[0], &ubuf->sig[0]);
+ kbuf->sig[0] = sig[0] | (sig[1] << 32);
+ }
+
+ return err;
+}
+
+/*
+ * Atomically swap in the new signal mask, and wait for a signal.
+ */
+
+save_static_function(sys32_sigsuspend);
+__attribute_used__ noinline static int
+_sys32_sigsuspend(nabi_no_regargs struct pt_regs regs)
+{
+ compat_sigset_t *uset;
+ sigset_t newset, saveset;
+
+ uset = (compat_sigset_t *) regs.regs[4];
+ if (get_sigset(&newset, uset))
+ return -EFAULT;
+ sigdelsetmask(&newset, ~_BLOCKABLE);
+
+ spin_lock_irq(¤t->sighand->siglock);
+ saveset = current->blocked;
+ current->blocked = newset;
+ recalc_sigpending();
+ spin_unlock_irq(¤t->sighand->siglock);
+
+ regs.regs[2] = EINTR;
+ regs.regs[7] = 1;
+ while (1) {
+ current->state = TASK_INTERRUPTIBLE;
+ schedule();
+ if (do_signal32(&saveset, ®s))
+ return -EINTR;
+ }
+}
+
+save_static_function(sys32_rt_sigsuspend);
+__attribute_used__ noinline static int
+_sys32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs)
+{
+ compat_sigset_t *uset;
+ sigset_t newset, saveset;
+ size_t sigsetsize;
+
+ /* XXX Don't preclude handling different sized sigset_t's. */
+ sigsetsize = regs.regs[5];
+ if (sigsetsize != sizeof(compat_sigset_t))
+ return -EINVAL;
+
+ uset = (compat_sigset_t *) regs.regs[4];
+ if (get_sigset(&newset, uset))
+ return -EFAULT;
+ sigdelsetmask(&newset, ~_BLOCKABLE);
+
+ spin_lock_irq(¤t->sighand->siglock);
+ saveset = current->blocked;
+ current->blocked = newset;
+ recalc_sigpending();
+ spin_unlock_irq(¤t->sighand->siglock);
+
+ regs.regs[2] = EINTR;
+ regs.regs[7] = 1;
+ while (1) {
+ current->state = TASK_INTERRUPTIBLE;
+ schedule();
+ if (do_signal32(&saveset, ®s))
+ return -EINTR;
+ }
+}
+
+asmlinkage int sys32_sigaction(int sig, const struct sigaction32 *act,
+ struct sigaction32 *oact)
+{
+ struct k_sigaction new_ka, old_ka;
+ int ret;
+ int err = 0;
+
+ if (act) {
+ old_sigset_t mask;
+
+ if (!access_ok(VERIFY_READ, act, sizeof(*act)))
+ return -EFAULT;
+ err |= __get_user((u32)(u64)new_ka.sa.sa_handler,
+ &act->sa_handler);
+ err |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
+ err |= __get_user(mask, &act->sa_mask.sig[0]);
+ if (err)
+ return -EFAULT;
+
+ siginitset(&new_ka.sa.sa_mask, mask);
+ }
+
+ ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
+
+ if (!ret && oact) {
+ if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)))
+ return -EFAULT;
+ err |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
+ err |= __put_user((u32)(u64)old_ka.sa.sa_handler,
+ &oact->sa_handler);
+ err |= __put_user(old_ka.sa.sa_mask.sig[0], oact->sa_mask.sig);
+ err |= __put_user(0, &oact->sa_mask.sig[1]);
+ err |= __put_user(0, &oact->sa_mask.sig[2]);
+ err |= __put_user(0, &oact->sa_mask.sig[3]);
+ if (err)
+ return -EFAULT;
+ }
+
+ return ret;
+}
+
+asmlinkage int sys32_sigaltstack(nabi_no_regargs struct pt_regs regs)
+{
+ const stack32_t *uss = (const stack32_t *) regs.regs[4];
+ stack32_t *uoss = (stack32_t *) regs.regs[5];
+ unsigned long usp = regs.regs[29];
+ stack_t kss, koss;
+ int ret, err = 0;
+ mm_segment_t old_fs = get_fs();
+ s32 sp;
+
+ if (uss) {
+ if (!access_ok(VERIFY_READ, uss, sizeof(*uss)))
+ return -EFAULT;
+ err |= __get_user(sp, &uss->ss_sp);
+ kss.ss_sp = (void *) (long) sp;
+ err |= __get_user(kss.ss_size, &uss->ss_size);
+ err |= __get_user(kss.ss_flags, &uss->ss_flags);
+ if (err)
+ return -EFAULT;
+ }
+
+ set_fs (KERNEL_DS);
+ ret = do_sigaltstack(uss ? &kss : NULL , uoss ? &koss : NULL, usp);
+ set_fs (old_fs);
+
+ if (!ret && uoss) {
+ if (!access_ok(VERIFY_WRITE, uoss, sizeof(*uoss)))
+ return -EFAULT;
+ sp = (int) (long) koss.ss_sp;
+ err |= __put_user(sp, &uoss->ss_sp);
+ err |= __put_user(koss.ss_size, &uoss->ss_size);
+ err |= __put_user(koss.ss_flags, &uoss->ss_flags);
+ if (err)
+ return -EFAULT;
+ }
+ return ret;
+}
+
+static int restore_sigcontext32(struct pt_regs *regs, struct sigcontext32 *sc)
+{
+ int err = 0;
+ __u32 used_math;
+
+ /* Always make any pending restarted system calls return -EINTR */
+ current_thread_info()->restart_block.fn = do_no_restart_syscall;
+
+ err |= __get_user(regs->cp0_epc, &sc->sc_pc);
+ err |= __get_user(regs->hi, &sc->sc_mdhi);
+ err |= __get_user(regs->lo, &sc->sc_mdlo);
+
+#define restore_gp_reg(i) do { \
+ err |= __get_user(regs->regs[i], &sc->sc_regs[i]); \
+} while(0)
+ restore_gp_reg( 1); restore_gp_reg( 2); restore_gp_reg( 3);
+ restore_gp_reg( 4); restore_gp_reg( 5); restore_gp_reg( 6);
+ restore_gp_reg( 7); restore_gp_reg( 8); restore_gp_reg( 9);
+ restore_gp_reg(10); restore_gp_reg(11); restore_gp_reg(12);
+ restore_gp_reg(13); restore_gp_reg(14); restore_gp_reg(15);
+ restore_gp_reg(16); restore_gp_reg(17); restore_gp_reg(18);
+ restore_gp_reg(19); restore_gp_reg(20); restore_gp_reg(21);
+ restore_gp_reg(22); restore_gp_reg(23); restore_gp_reg(24);
+ restore_gp_reg(25); restore_gp_reg(26); restore_gp_reg(27);
+ restore_gp_reg(28); restore_gp_reg(29); restore_gp_reg(30);
+ restore_gp_reg(31);
+#undef restore_gp_reg
+
+ err |= __get_user(used_math, &sc->sc_used_math);
+ conditional_used_math(used_math);
+
+ preempt_disable();
+
+ if (used_math()) {
+ /* restore fpu context if we have used it before */
+ own_fpu();
+ err |= restore_fp_context32(sc);
+ } else {
+ /* signal handler may have used FPU. Give it up. */
+ lose_fpu();
+ }
+
+ preempt_enable();
+
+ return err;
+}
+
+struct sigframe {
+ u32 sf_ass[4]; /* argument save space for o32 */
+ u32 sf_code[2]; /* signal trampoline */
+ struct sigcontext32 sf_sc;
+ sigset_t sf_mask;
+};
+
+struct rt_sigframe32 {
+ u32 rs_ass[4]; /* argument save space for o32 */
+ u32 rs_code[2]; /* signal trampoline */
+ compat_siginfo_t rs_info;
+ struct ucontext32 rs_uc;
+};
+
+int copy_siginfo_to_user32(compat_siginfo_t *to, siginfo_t *from)
+{
+ int err;
+
+ if (!access_ok (VERIFY_WRITE, to, sizeof(compat_siginfo_t)))
+ return -EFAULT;
+
+ /* If you change siginfo_t structure, please be sure
+ this code is fixed accordingly.
+ It should never copy any pad contained in the structure
+ to avoid security leaks, but must copy the generic
+ 3 ints plus the relevant union member.
+ This routine must convert siginfo from 64bit to 32bit as well
+ at the same time. */
+ err = __put_user(from->si_signo, &to->si_signo);
+ err |= __put_user(from->si_errno, &to->si_errno);
+ err |= __put_user((short)from->si_code, &to->si_code);
+ if (from->si_code < 0)
+ err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
+ else {
+ switch (from->si_code >> 16) {
+ case __SI_CHLD >> 16:
+ err |= __put_user(from->si_utime, &to->si_utime);
+ err |= __put_user(from->si_stime, &to->si_stime);
+ err |= __put_user(from->si_status, &to->si_status);
+ default:
+ err |= __put_user(from->si_pid, &to->si_pid);
+ err |= __put_user(from->si_uid, &to->si_uid);
+ break;
+ case __SI_FAULT >> 16:
+ err |= __put_user((long)from->si_addr, &to->si_addr);
+ break;
+ case __SI_POLL >> 16:
+ err |= __put_user(from->si_band, &to->si_band);
+ err |= __put_user(from->si_fd, &to->si_fd);
+ break;
+ case __SI_RT >> 16: /* This is not generated by the kernel as of now. */
+ case __SI_MESGQ >> 16:
+ err |= __put_user(from->si_pid, &to->si_pid);
+ err |= __put_user(from->si_uid, &to->si_uid);
+ err |= __put_user(from->si_int, &to->si_int);
+ break;
+ }
+ }
+ return err;
+}
+
+save_static_function(sys32_sigreturn);
+__attribute_used__ noinline static void
+_sys32_sigreturn(nabi_no_regargs struct pt_regs regs)
+{
+ struct sigframe *frame;
+ sigset_t blocked;
+
+ frame = (struct sigframe *) regs.regs[29];
+ if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
+ goto badframe;
+ if (__copy_from_user(&blocked, &frame->sf_mask, sizeof(blocked)))
+ goto badframe;
+
+ sigdelsetmask(&blocked, ~_BLOCKABLE);
+ spin_lock_irq(¤t->sighand->siglock);
+ current->blocked = blocked;
+ recalc_sigpending();
+ spin_unlock_irq(¤t->sighand->siglock);
+
+ if (restore_sigcontext32(®s, &frame->sf_sc))
+ goto badframe;
+
+ /*
+ * Don't let your children do this ...
+ */
+ if (current_thread_info()->flags & TIF_SYSCALL_TRACE)
+ do_syscall_trace(®s, 1);
+ __asm__ __volatile__(
+ "move\t$29, %0\n\t"
+ "j\tsyscall_exit"
+ :/* no outputs */
+ :"r" (®s));
+ /* Unreached */
+
+badframe:
+ force_sig(SIGSEGV, current);
+}
+
+save_static_function(sys32_rt_sigreturn);
+__attribute_used__ noinline static void
+_sys32_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
+{
+ struct rt_sigframe32 *frame;
+ sigset_t set;
+ stack_t st;
+ s32 sp;
+
+ frame = (struct rt_sigframe32 *) regs.regs[29];
+ if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
+ goto badframe;
+ if (__copy_from_user(&set, &frame->rs_uc.uc_sigmask, sizeof(set)))
+ goto badframe;
+
+ sigdelsetmask(&set, ~_BLOCKABLE);
+ spin_lock_irq(¤t->sighand->siglock);
+ current->blocked = set;
+ recalc_sigpending();
+ spin_unlock_irq(¤t->sighand->siglock);
+
+ if (restore_sigcontext32(®s, &frame->rs_uc.uc_mcontext))
+ goto badframe;
+
+ /* The ucontext contains a stack32_t, so we must convert! */
+ if (__get_user(sp, &frame->rs_uc.uc_stack.ss_sp))
+ goto badframe;
+ st.ss_size = (long) sp;
+ if (__get_user(st.ss_size, &frame->rs_uc.uc_stack.ss_size))
+ goto badframe;
+ if (__get_user(st.ss_flags, &frame->rs_uc.uc_stack.ss_flags))
+ goto badframe;
+
+ /* It is more difficult to avoid calling this function than to
+ call it and ignore errors. */
+ do_sigaltstack(&st, NULL, regs.regs[29]);
+
+ /*
+ * Don't let your children do this ...
+ */
+ __asm__ __volatile__(
+ "move\t$29, %0\n\t"
+ "j\tsyscall_exit"
+ :/* no outputs */
+ :"r" (®s));
+ /* Unreached */
+
+badframe:
+ force_sig(SIGSEGV, current);
+}
+
+static inline int setup_sigcontext32(struct pt_regs *regs,
+ struct sigcontext32 *sc)
+{
+ int err = 0;
+
+ err |= __put_user(regs->cp0_epc, &sc->sc_pc);
+ err |= __put_user(regs->cp0_status, &sc->sc_status);
+
+#define save_gp_reg(i) { \
+ err |= __put_user(regs->regs[i], &sc->sc_regs[i]); \
+} while(0)
+ __put_user(0, &sc->sc_regs[0]); save_gp_reg(1); save_gp_reg(2);
+ save_gp_reg(3); save_gp_reg(4); save_gp_reg(5); save_gp_reg(6);
+ save_gp_reg(7); save_gp_reg(8); save_gp_reg(9); save_gp_reg(10);
+ save_gp_reg(11); save_gp_reg(12); save_gp_reg(13); save_gp_reg(14);
+ save_gp_reg(15); save_gp_reg(16); save_gp_reg(17); save_gp_reg(18);
+ save_gp_reg(19); save_gp_reg(20); save_gp_reg(21); save_gp_reg(22);
+ save_gp_reg(23); save_gp_reg(24); save_gp_reg(25); save_gp_reg(26);
+ save_gp_reg(27); save_gp_reg(28); save_gp_reg(29); save_gp_reg(30);
+ save_gp_reg(31);
+#undef save_gp_reg
+
+ err |= __put_user(regs->hi, &sc->sc_mdhi);
+ err |= __put_user(regs->lo, &sc->sc_mdlo);
+ err |= __put_user(regs->cp0_cause, &sc->sc_cause);
+ err |= __put_user(regs->cp0_badvaddr, &sc->sc_badvaddr);
+
+ err |= __put_user(!!used_math(), &sc->sc_used_math);
+
+ if (!used_math())
+ goto out;
+
+ /*
+ * Save FPU state to signal context. Signal handler will "inherit"
+ * current FPU state.
+ */
+ preempt_disable();
+
+ if (!is_fpu_owner()) {
+ own_fpu();
+ restore_fp(current);
+ }
+ err |= save_fp_context32(sc);
+
+ preempt_enable();
+
+out:
+ return err;
+}
+
+/*
+ * Determine which stack to use..
+ */
+static inline void *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
+ size_t frame_size)
+{
+ unsigned long sp;
+
+ /* Default to using normal stack */
+ sp = regs->regs[29];
+
+ /*
+ * FPU emulator may have it's own trampoline active just
+ * above the user stack, 16-bytes before the next lowest
+ * 16 byte boundary. Try to avoid trashing it.
+ */
+ sp -= 32;
+
+ /* This is the X/Open sanctioned signal stack switching. */
+ if ((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags (sp) == 0))
+ sp = current->sas_ss_sp + current->sas_ss_size;
+
+ return (void *)((sp - frame_size) & ALMASK);
+}
+
+static inline void setup_frame(struct k_sigaction * ka, struct pt_regs *regs,
+ int signr, sigset_t *set)
+{
+ struct sigframe *frame;
+ int err = 0;
+
+ frame = get_sigframe(ka, regs, sizeof(*frame));
+ if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
+ goto give_sigsegv;
+
+ /*
+ * Set up the return code ...
+ *
+ * li v0, __NR_O32_sigreturn
+ * syscall
+ */
+ err |= __put_user(0x24020000 + __NR_O32_sigreturn, frame->sf_code + 0);
+ err |= __put_user(0x0000000c , frame->sf_code + 1);
+ flush_cache_sigtramp((unsigned long) frame->sf_code);
+
+ err |= setup_sigcontext32(regs, &frame->sf_sc);
+ err |= __copy_to_user(&frame->sf_mask, set, sizeof(*set));
+ if (err)
+ goto give_sigsegv;
+
+ /*
+ * Arguments to signal handler:
+ *
+ * a0 = signal number
+ * a1 = 0 (should be cause)
+ * a2 = pointer to struct sigcontext
+ *
+ * $25 and c0_epc point to the signal handler, $29 points to the
+ * struct sigframe.
+ */
+ regs->regs[ 4] = signr;
+ regs->regs[ 5] = 0;
+ regs->regs[ 6] = (unsigned long) &frame->sf_sc;
+ regs->regs[29] = (unsigned long) frame;
+ regs->regs[31] = (unsigned long) frame->sf_code;
+ regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;
+
+#if DEBUG_SIG
+ printk("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%p\n",
+ current->comm, current->pid,
+ frame, regs->cp0_epc, frame->sf_code);
+#endif
+ return;
+
+give_sigsegv:
+ force_sigsegv(signr, current);
+}
+
+static inline void setup_rt_frame(struct k_sigaction * ka,
+ struct pt_regs *regs, int signr,
+ sigset_t *set, siginfo_t *info)
+{
+ struct rt_sigframe32 *frame;
+ int err = 0;
+ s32 sp;
+
+ frame = get_sigframe(ka, regs, sizeof(*frame));
+ if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
+ goto give_sigsegv;
+
+ /* Set up to return from userspace. If provided, use a stub already
+ in userspace. */
+ /*
+ * Set up the return code ...
+ *
+ * li v0, __NR_O32_rt_sigreturn
+ * syscall
+ */
+ err |= __put_user(0x24020000 + __NR_O32_rt_sigreturn, frame->rs_code + 0);
+ err |= __put_user(0x0000000c , frame->rs_code + 1);
+ flush_cache_sigtramp((unsigned long) frame->rs_code);
+
+ /* Convert (siginfo_t -> compat_siginfo_t) and copy to user. */
+ err |= copy_siginfo_to_user32(&frame->rs_info, info);
+
+ /* Create the ucontext. */
+ err |= __put_user(0, &frame->rs_uc.uc_flags);
+ err |= __put_user(0, &frame->rs_uc.uc_link);
+ sp = (int) (long) current->sas_ss_sp;
+ err |= __put_user(sp,
+ &frame->rs_uc.uc_stack.ss_sp);
+ err |= __put_user(sas_ss_flags(regs->regs[29]),
+ &frame->rs_uc.uc_stack.ss_flags);
+ err |= __put_user(current->sas_ss_size,
+ &frame->rs_uc.uc_stack.ss_size);
+ err |= setup_sigcontext32(regs, &frame->rs_uc.uc_mcontext);
+ err |= __copy_to_user(&frame->rs_uc.uc_sigmask, set, sizeof(*set));
+
+ if (err)
+ goto give_sigsegv;
+
+ /*
+ * Arguments to signal handler:
+ *
+ * a0 = signal number
+ * a1 = 0 (should be cause)
+ * a2 = pointer to ucontext
+ *
+ * $25 and c0_epc point to the signal handler, $29 points to
+ * the struct rt_sigframe32.
+ */
+ regs->regs[ 4] = signr;
+ regs->regs[ 5] = (unsigned long) &frame->rs_info;
+ regs->regs[ 6] = (unsigned long) &frame->rs_uc;
+ regs->regs[29] = (unsigned long) frame;
+ regs->regs[31] = (unsigned long) frame->rs_code;
+ regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;
+
+#if DEBUG_SIG
+ printk("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%p\n",
+ current->comm, current->pid,
+ frame, regs->cp0_epc, frame->rs_code);
+#endif
+ return;
+
+give_sigsegv:
+ force_sigsegv(signr, current);
+}
+
+static inline void handle_signal(unsigned long sig, siginfo_t *info,
+ struct k_sigaction *ka, sigset_t *oldset, struct pt_regs * regs)
+{
+ switch (regs->regs[0]) {
+ case ERESTART_RESTARTBLOCK:
+ case ERESTARTNOHAND:
+ regs->regs[2] = EINTR;
+ break;
+ case ERESTARTSYS:
+ if(!(ka->sa.sa_flags & SA_RESTART)) {
+ regs->regs[2] = EINTR;
+ break;
+ }
+ /* fallthrough */
+ case ERESTARTNOINTR: /* Userland will reload $v0. */
+ regs->regs[7] = regs->regs[26];
+ regs->cp0_epc -= 8;
+ }
+
+ regs->regs[0] = 0; /* Don't deal with this again. */
+
+ if (ka->sa.sa_flags & SA_SIGINFO)
+ setup_rt_frame(ka, regs, sig, oldset, info);
+ else
+ setup_frame(ka, regs, sig, oldset);
+
+ if (!(ka->sa.sa_flags & SA_NODEFER)) {
+ spin_lock_irq(¤t->sighand->siglock);
+ sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask);
+ sigaddset(¤t->blocked,sig);
+ recalc_sigpending();
+ spin_unlock_irq(¤t->sighand->siglock);
+ }
+}
+
+int do_signal32(sigset_t *oldset, struct pt_regs *regs)
+{
+ struct k_sigaction ka;
+ siginfo_t info;
+ int signr;
+
+ /*
+ * We want the common case to go fast, which is why we may in certain
+ * cases get here from kernel mode. Just return without doing anything
+ * if so.
+ */
+ if (!user_mode(regs))
+ return 1;
+
+ if (try_to_freeze(0))
+ goto no_signal;
+
+ if (!oldset)
+ oldset = ¤t->blocked;
+
+ signr = get_signal_to_deliver(&info, &ka, regs, NULL);
+ if (signr > 0) {
+ handle_signal(signr, &info, &ka, oldset, regs);
+ return 1;
+ }
+
+no_signal:
+ /*
+ * Who's code doesn't conform to the restartable syscall convention
+ * dies here!!! The li instruction, a single machine instruction,
+ * must directly be followed by the syscall instruction.
+ */
+ if (regs->regs[0]) {
+ if (regs->regs[2] == ERESTARTNOHAND ||
+ regs->regs[2] == ERESTARTSYS ||
+ regs->regs[2] == ERESTARTNOINTR) {
+ regs->regs[7] = regs->regs[26];
+ regs->cp0_epc -= 8;
+ }
+ if (regs->regs[2] == ERESTART_RESTARTBLOCK) {
+ regs->regs[2] = __NR_O32_restart_syscall;
+ regs->regs[7] = regs->regs[26];
+ regs->cp0_epc -= 4;
+ }
+ }
+ return 0;
+}
+
+asmlinkage int sys32_rt_sigaction(int sig, const struct sigaction32 *act,
+ struct sigaction32 *oact,
+ unsigned int sigsetsize)
+{
+ struct k_sigaction new_sa, old_sa;
+ int ret = -EINVAL;
+
+ /* XXX: Don't preclude handling different sized sigset_t's. */
+ if (sigsetsize != sizeof(sigset_t))
+ goto out;
+
+ if (act) {
+ int err = 0;
+
+ if (!access_ok(VERIFY_READ, act, sizeof(*act)))
+ return -EFAULT;
+ err |= __get_user((u32)(u64)new_sa.sa.sa_handler,
+ &act->sa_handler);
+ err |= __get_user(new_sa.sa.sa_flags, &act->sa_flags);
+ err |= get_sigset(&new_sa.sa.sa_mask, &act->sa_mask);
+ if (err)
+ return -EFAULT;
+ }
+
+ ret = do_sigaction(sig, act ? &new_sa : NULL, oact ? &old_sa : NULL);
+
+ if (!ret && oact) {
+ int err = 0;
+
+ if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)))
+ return -EFAULT;
+
+ err |= __put_user((u32)(u64)old_sa.sa.sa_handler,
+ &oact->sa_handler);
+ err |= __put_user(old_sa.sa.sa_flags, &oact->sa_flags);
+ err |= put_sigset(&old_sa.sa.sa_mask, &oact->sa_mask);
+ if (err)
+ return -EFAULT;
+ }
+out:
+ return ret;
+}
+
+asmlinkage int sys32_rt_sigprocmask(int how, compat_sigset_t *set,
+ compat_sigset_t *oset, unsigned int sigsetsize)
+{
+ sigset_t old_set, new_set;
+ int ret;
+ mm_segment_t old_fs = get_fs();
+
+ if (set && get_sigset(&new_set, set))
+ return -EFAULT;
+
+ set_fs (KERNEL_DS);
+ ret = sys_rt_sigprocmask(how, set ? &new_set : NULL,
+ oset ? &old_set : NULL, sigsetsize);
+ set_fs (old_fs);
+
+ if (!ret && oset && put_sigset(&old_set, oset))
+ return -EFAULT;
+
+ return ret;
+}
+
+asmlinkage int sys32_rt_sigpending(compat_sigset_t *uset,
+ unsigned int sigsetsize)
+{
+ int ret;
+ sigset_t set;
+ mm_segment_t old_fs = get_fs();
+
+ set_fs (KERNEL_DS);
+ ret = sys_rt_sigpending(&set, sigsetsize);
+ set_fs (old_fs);
+
+ if (!ret && put_sigset(&set, uset))
+ return -EFAULT;
+
+ return ret;
+}
+
+asmlinkage int sys32_rt_sigqueueinfo(int pid, int sig, compat_siginfo_t *uinfo)
+{
+ siginfo_t info;
+ int ret;
+ mm_segment_t old_fs = get_fs();
+
+ if (copy_from_user (&info, uinfo, 3*sizeof(int)) ||
+ copy_from_user (info._sifields._pad, uinfo->_sifields._pad, SI_PAD_SIZE))
+ return -EFAULT;
+ set_fs (KERNEL_DS);
+ ret = sys_rt_sigqueueinfo(pid, sig, &info);
+ set_fs (old_fs);
+ return ret;
+}
diff --git a/arch/mips/kernel/signal_n32.c b/arch/mips/kernel/signal_n32.c
new file mode 100644
index 0000000..3544208
--- /dev/null
+++ b/arch/mips/kernel/signal_n32.c
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2003 Broadcom Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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 <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/kernel.h>
+#include <linux/signal.h>
+#include <linux/errno.h>
+#include <linux/wait.h>
+#include <linux/ptrace.h>
+#include <linux/unistd.h>
+#include <linux/compat.h>
+#include <linux/bitops.h>
+
+#include <asm/asm.h>
+#include <asm/cacheflush.h>
+#include <asm/sim.h>
+#include <asm/uaccess.h>
+#include <asm/ucontext.h>
+#include <asm/system.h>
+#include <asm/fpu.h>
+#include <asm/cpu-features.h>
+
+#include "signal-common.h"
+
+/*
+ * Including <asm/unistd.h> would give use the 64-bit syscall numbers ...
+ */
+#define __NR_N32_rt_sigreturn 6211
+#define __NR_N32_restart_syscall 6214
+
+#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
+
+/* IRIX compatible stack_t */
+typedef struct sigaltstack32 {
+ s32 ss_sp;
+ compat_size_t ss_size;
+ int ss_flags;
+} stack32_t;
+
+struct ucontextn32 {
+ u32 uc_flags;
+ s32 uc_link;
+ stack32_t uc_stack;
+ struct sigcontext uc_mcontext;
+ sigset_t uc_sigmask; /* mask last for extensibility */
+};
+
+#if PLAT_TRAMPOLINE_STUFF_LINE
+#define __tramp __attribute__((aligned(PLAT_TRAMPOLINE_STUFF_LINE)))
+#else
+#define __tramp
+#endif
+
+struct rt_sigframe_n32 {
+ u32 rs_ass[4]; /* argument save space for o32 */
+ u32 rs_code[2] __tramp; /* signal trampoline */
+ struct siginfo rs_info __tramp;
+ struct ucontextn32 rs_uc;
+};
+
+save_static_function(sysn32_rt_sigreturn);
+__attribute_used__ noinline static void
+_sysn32_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
+{
+ struct rt_sigframe_n32 *frame;
+ sigset_t set;
+ stack_t st;
+ s32 sp;
+
+ frame = (struct rt_sigframe_n32 *) regs.regs[29];
+ if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
+ goto badframe;
+ if (__copy_from_user(&set, &frame->rs_uc.uc_sigmask, sizeof(set)))
+ goto badframe;
+
+ sigdelsetmask(&set, ~_BLOCKABLE);
+ spin_lock_irq(¤t->sighand->siglock);
+ current->blocked = set;
+ recalc_sigpending();
+ spin_unlock_irq(¤t->sighand->siglock);
+
+ if (restore_sigcontext(®s, &frame->rs_uc.uc_mcontext))
+ goto badframe;
+
+ /* The ucontext contains a stack32_t, so we must convert! */
+ if (__get_user(sp, &frame->rs_uc.uc_stack.ss_sp))
+ goto badframe;
+ st.ss_size = (long) sp;
+ if (__get_user(st.ss_size, &frame->rs_uc.uc_stack.ss_size))
+ goto badframe;
+ if (__get_user(st.ss_flags, &frame->rs_uc.uc_stack.ss_flags))
+ goto badframe;
+
+ /* It is more difficult to avoid calling this function than to
+ call it and ignore errors. */
+ do_sigaltstack(&st, NULL, regs.regs[29]);
+
+ /*
+ * Don't let your children do this ...
+ */
+ __asm__ __volatile__(
+ "move\t$29, %0\n\t"
+ "j\tsyscall_exit"
+ :/* no outputs */
+ :"r" (®s));
+ /* Unreached */
+
+badframe:
+ force_sig(SIGSEGV, current);
+}
+
+void setup_rt_frame_n32(struct k_sigaction * ka,
+ struct pt_regs *regs, int signr, sigset_t *set, siginfo_t *info)
+{
+ struct rt_sigframe_n32 *frame;
+ int err = 0;
+ s32 sp;
+
+ frame = get_sigframe(ka, regs, sizeof(*frame));
+ if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
+ goto give_sigsegv;
+
+ /*
+ * Set up the return code ...
+ *
+ * li v0, __NR_rt_sigreturn
+ * syscall
+ */
+ if (PLAT_TRAMPOLINE_STUFF_LINE)
+ __clear_user(frame->rs_code, PLAT_TRAMPOLINE_STUFF_LINE);
+ err |= __put_user(0x24020000 + __NR_N32_rt_sigreturn, frame->rs_code + 0);
+ err |= __put_user(0x0000000c , frame->rs_code + 1);
+ flush_cache_sigtramp((unsigned long) frame->rs_code);
+
+ /* Create siginfo. */
+ err |= copy_siginfo_to_user(&frame->rs_info, info);
+
+ /* Create the ucontext. */
+ err |= __put_user(0, &frame->rs_uc.uc_flags);
+ err |= __put_user(0, &frame->rs_uc.uc_link);
+ sp = (int) (long) current->sas_ss_sp;
+ err |= __put_user(sp,
+ &frame->rs_uc.uc_stack.ss_sp);
+ err |= __put_user(sas_ss_flags(regs->regs[29]),
+ &frame->rs_uc.uc_stack.ss_flags);
+ err |= __put_user(current->sas_ss_size,
+ &frame->rs_uc.uc_stack.ss_size);
+ err |= setup_sigcontext(regs, &frame->rs_uc.uc_mcontext);
+ err |= __copy_to_user(&frame->rs_uc.uc_sigmask, set, sizeof(*set));
+
+ if (err)
+ goto give_sigsegv;
+
+ /*
+ * Arguments to signal handler:
+ *
+ * a0 = signal number
+ * a1 = 0 (should be cause)
+ * a2 = pointer to ucontext
+ *
+ * $25 and c0_epc point to the signal handler, $29 points to
+ * the struct rt_sigframe.
+ */
+ regs->regs[ 4] = signr;
+ regs->regs[ 5] = (unsigned long) &frame->rs_info;
+ regs->regs[ 6] = (unsigned long) &frame->rs_uc;
+ regs->regs[29] = (unsigned long) frame;
+ regs->regs[31] = (unsigned long) frame->rs_code;
+ regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;
+
+#if DEBUG_SIG
+ printk("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%p\n",
+ current->comm, current->pid,
+ frame, regs->cp0_epc, regs->regs[31]);
+#endif
+ return;
+
+give_sigsegv:
+ force_sigsegv(signr, current);
+}
diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c
new file mode 100644
index 0000000..af5cd3b
--- /dev/null
+++ b/arch/mips/kernel/smp.c
@@ -0,0 +1,425 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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.
+ *
+ * Copyright (C) 2000, 2001 Kanoj Sarcar
+ * Copyright (C) 2000, 2001 Ralf Baechle
+ * Copyright (C) 2000, 2001 Silicon Graphics, Inc.
+ * Copyright (C) 2000, 2001, 2003 Broadcom Corporation
+ */
+#include <linux/cache.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/threads.h>
+#include <linux/module.h>
+#include <linux/time.h>
+#include <linux/timex.h>
+#include <linux/sched.h>
+#include <linux/cpumask.h>
+
+#include <asm/atomic.h>
+#include <asm/cpu.h>
+#include <asm/processor.h>
+#include <asm/system.h>
+#include <asm/mmu_context.h>
+#include <asm/smp.h>
+
+cpumask_t phys_cpu_present_map; /* Bitmask of available CPUs */
+volatile cpumask_t cpu_callin_map; /* Bitmask of started secondaries */
+cpumask_t cpu_online_map; /* Bitmask of currently online CPUs */
+int __cpu_number_map[NR_CPUS]; /* Map physical to logical */
+int __cpu_logical_map[NR_CPUS]; /* Map logical to physical */
+
+EXPORT_SYMBOL(phys_cpu_present_map);
+EXPORT_SYMBOL(cpu_online_map);
+
+static void smp_tune_scheduling (void)
+{
+ struct cache_desc *cd = ¤t_cpu_data.scache;
+ unsigned long cachesize; /* kB */
+ unsigned long bandwidth = 350; /* MB/s */
+ unsigned long cpu_khz;
+
+ /*
+ * Crude estimate until we actually meassure ...
+ */
+ cpu_khz = loops_per_jiffy * 2 * HZ / 1000;
+
+ /*
+ * Rough estimation for SMP scheduling, this is the number of
+ * cycles it takes for a fully memory-limited process to flush
+ * the SMP-local cache.
+ *
+ * (For a P5 this pretty much means we will choose another idle
+ * CPU almost always at wakeup time (this is due to the small
+ * L1 cache), on PIIs it's around 50-100 usecs, depending on
+ * the cache size)
+ */
+ if (!cpu_khz)
+ return;
+
+ cachesize = cd->linesz * cd->sets * cd->ways;
+}
+
+extern void __init calibrate_delay(void);
+extern ATTRIB_NORET void cpu_idle(void);
+
+/*
+ * First C code run on the secondary CPUs after being started up by
+ * the master.
+ */
+asmlinkage void start_secondary(void)
+{
+ unsigned int cpu = smp_processor_id();
+
+ cpu_probe();
+ cpu_report();
+ per_cpu_trap_init();
+ prom_init_secondary();
+
+ /*
+ * XXX parity protection should be folded in here when it's converted
+ * to an option instead of something based on .cputype
+ */
+
+ calibrate_delay();
+ cpu_data[cpu].udelay_val = loops_per_jiffy;
+
+ prom_smp_finish();
+
+ cpu_set(cpu, cpu_callin_map);
+
+ cpu_idle();
+}
+
+DEFINE_SPINLOCK(smp_call_lock);
+
+struct call_data_struct *call_data;
+
+/*
+ * Run a function on all other CPUs.
+ * <func> The function to run. This must be fast and non-blocking.
+ * <info> An arbitrary pointer to pass to the function.
+ * <retry> If true, keep retrying until ready.
+ * <wait> If true, wait until function has completed on other CPUs.
+ * [RETURNS] 0 on success, else a negative status code.
+ *
+ * Does not return until remote CPUs are nearly ready to execute <func>
+ * or are or have executed.
+ *
+ * You must not call this function with disabled interrupts or from a
+ * hardware interrupt handler or from a bottom half handler.
+ */
+int smp_call_function (void (*func) (void *info), void *info, int retry,
+ int wait)
+{
+ struct call_data_struct data;
+ int i, cpus = num_online_cpus() - 1;
+ int cpu = smp_processor_id();
+
+ if (!cpus)
+ return 0;
+
+ /* Can deadlock when called with interrupts disabled */
+ WARN_ON(irqs_disabled());
+
+ data.func = func;
+ data.info = info;
+ atomic_set(&data.started, 0);
+ data.wait = wait;
+ if (wait)
+ atomic_set(&data.finished, 0);
+
+ spin_lock(&smp_call_lock);
+ call_data = &data;
+ mb();
+
+ /* Send a message to all other CPUs and wait for them to respond */
+ for (i = 0; i < NR_CPUS; i++)
+ if (cpu_online(i) && i != cpu)
+ core_send_ipi(i, SMP_CALL_FUNCTION);
+
+ /* Wait for response */
+ /* FIXME: lock-up detection, backtrace on lock-up */
+ while (atomic_read(&data.started) != cpus)
+ barrier();
+
+ if (wait)
+ while (atomic_read(&data.finished) != cpus)
+ barrier();
+ spin_unlock(&smp_call_lock);
+
+ return 0;
+}
+
+void smp_call_function_interrupt(void)
+{
+ void (*func) (void *info) = call_data->func;
+ void *info = call_data->info;
+ int wait = call_data->wait;
+
+ /*
+ * Notify initiating CPU that I've grabbed the data and am
+ * about to execute the function.
+ */
+ mb();
+ atomic_inc(&call_data->started);
+
+ /*
+ * At this point the info structure may be out of scope unless wait==1.
+ */
+ irq_enter();
+ (*func)(info);
+ irq_exit();
+
+ if (wait) {
+ mb();
+ atomic_inc(&call_data->finished);
+ }
+}
+
+static void stop_this_cpu(void *dummy)
+{
+ /*
+ * Remove this CPU:
+ */
+ cpu_clear(smp_processor_id(), cpu_online_map);
+ local_irq_enable(); /* May need to service _machine_restart IPI */
+ for (;;); /* Wait if available. */
+}
+
+void smp_send_stop(void)
+{
+ smp_call_function(stop_this_cpu, NULL, 1, 0);
+}
+
+void __init smp_cpus_done(unsigned int max_cpus)
+{
+ prom_cpus_done();
+}
+
+/* called from main before smp_init() */
+void __init smp_prepare_cpus(unsigned int max_cpus)
+{
+ cpu_data[0].udelay_val = loops_per_jiffy;
+ init_new_context(current, &init_mm);
+ current_thread_info()->cpu = 0;
+ smp_tune_scheduling();
+ prom_prepare_cpus(max_cpus);
+}
+
+/* preload SMP state for boot cpu */
+void __devinit smp_prepare_boot_cpu(void)
+{
+ /*
+ * This assumes that bootup is always handled by the processor
+ * with the logic and physical number 0.
+ */
+ __cpu_number_map[0] = 0;
+ __cpu_logical_map[0] = 0;
+ cpu_set(0, phys_cpu_present_map);
+ cpu_set(0, cpu_online_map);
+ cpu_set(0, cpu_callin_map);
+}
+
+/*
+ * Startup the CPU with this logical number
+ */
+static int __init do_boot_cpu(int cpu)
+{
+ struct task_struct *idle;
+
+ /*
+ * The following code is purely to make sure
+ * Linux can schedule processes on this slave.
+ */
+ idle = fork_idle(cpu);
+ if (IS_ERR(idle))
+ panic("failed fork for CPU %d\n", cpu);
+
+ prom_boot_secondary(cpu, idle);
+
+ /* XXXKW timeout */
+ while (!cpu_isset(cpu, cpu_callin_map))
+ udelay(100);
+
+ cpu_set(cpu, cpu_online_map);
+
+ return 0;
+}
+
+/*
+ * Called once for each "cpu_possible(cpu)". Needs to spin up the cpu
+ * and keep control until "cpu_online(cpu)" is set. Note: cpu is
+ * physical, not logical.
+ */
+int __devinit __cpu_up(unsigned int cpu)
+{
+ int ret;
+
+ /* Processor goes to start_secondary(), sets online flag */
+ ret = do_boot_cpu(cpu);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+/* Not really SMP stuff ... */
+int setup_profiling_timer(unsigned int multiplier)
+{
+ return 0;
+}
+
+static void flush_tlb_all_ipi(void *info)
+{
+ local_flush_tlb_all();
+}
+
+void flush_tlb_all(void)
+{
+ on_each_cpu(flush_tlb_all_ipi, 0, 1, 1);
+}
+
+static void flush_tlb_mm_ipi(void *mm)
+{
+ local_flush_tlb_mm((struct mm_struct *)mm);
+}
+
+/*
+ * The following tlb flush calls are invoked when old translations are
+ * being torn down, or pte attributes are changing. For single threaded
+ * address spaces, a new context is obtained on the current cpu, and tlb
+ * context on other cpus are invalidated to force a new context allocation
+ * at switch_mm time, should the mm ever be used on other cpus. For
+ * multithreaded address spaces, intercpu interrupts have to be sent.
+ * Another case where intercpu interrupts are required is when the target
+ * mm might be active on another cpu (eg debuggers doing the flushes on
+ * behalf of debugees, kswapd stealing pages from another process etc).
+ * Kanoj 07/00.
+ */
+
+void flush_tlb_mm(struct mm_struct *mm)
+{
+ preempt_disable();
+
+ if ((atomic_read(&mm->mm_users) != 1) || (current->mm != mm)) {
+ smp_call_function(flush_tlb_mm_ipi, (void *)mm, 1, 1);
+ } else {
+ int i;
+ for (i = 0; i < num_online_cpus(); i++)
+ if (smp_processor_id() != i)
+ cpu_context(i, mm) = 0;
+ }
+ local_flush_tlb_mm(mm);
+
+ preempt_enable();
+}
+
+struct flush_tlb_data {
+ struct vm_area_struct *vma;
+ unsigned long addr1;
+ unsigned long addr2;
+};
+
+static void flush_tlb_range_ipi(void *info)
+{
+ struct flush_tlb_data *fd = (struct flush_tlb_data *)info;
+
+ local_flush_tlb_range(fd->vma, fd->addr1, fd->addr2);
+}
+
+void flush_tlb_range(struct vm_area_struct *vma, unsigned long start, unsigned long end)
+{
+ struct mm_struct *mm = vma->vm_mm;
+
+ preempt_disable();
+ if ((atomic_read(&mm->mm_users) != 1) || (current->mm != mm)) {
+ struct flush_tlb_data fd;
+
+ fd.vma = vma;
+ fd.addr1 = start;
+ fd.addr2 = end;
+ smp_call_function(flush_tlb_range_ipi, (void *)&fd, 1, 1);
+ } else {
+ int i;
+ for (i = 0; i < num_online_cpus(); i++)
+ if (smp_processor_id() != i)
+ cpu_context(i, mm) = 0;
+ }
+ local_flush_tlb_range(vma, start, end);
+ preempt_enable();
+}
+
+static void flush_tlb_kernel_range_ipi(void *info)
+{
+ struct flush_tlb_data *fd = (struct flush_tlb_data *)info;
+
+ local_flush_tlb_kernel_range(fd->addr1, fd->addr2);
+}
+
+void flush_tlb_kernel_range(unsigned long start, unsigned long end)
+{
+ struct flush_tlb_data fd;
+
+ fd.addr1 = start;
+ fd.addr2 = end;
+ on_each_cpu(flush_tlb_kernel_range_ipi, (void *)&fd, 1, 1);
+}
+
+static void flush_tlb_page_ipi(void *info)
+{
+ struct flush_tlb_data *fd = (struct flush_tlb_data *)info;
+
+ local_flush_tlb_page(fd->vma, fd->addr1);
+}
+
+void flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
+{
+ preempt_disable();
+ if ((atomic_read(&vma->vm_mm->mm_users) != 1) || (current->mm != vma->vm_mm)) {
+ struct flush_tlb_data fd;
+
+ fd.vma = vma;
+ fd.addr1 = page;
+ smp_call_function(flush_tlb_page_ipi, (void *)&fd, 1, 1);
+ } else {
+ int i;
+ for (i = 0; i < num_online_cpus(); i++)
+ if (smp_processor_id() != i)
+ cpu_context(i, vma->vm_mm) = 0;
+ }
+ local_flush_tlb_page(vma, page);
+ preempt_enable();
+}
+
+static void flush_tlb_one_ipi(void *info)
+{
+ unsigned long vaddr = (unsigned long) info;
+
+ local_flush_tlb_one(vaddr);
+}
+
+void flush_tlb_one(unsigned long vaddr)
+{
+ smp_call_function(flush_tlb_one_ipi, (void *) vaddr, 1, 1);
+ local_flush_tlb_one(vaddr);
+}
+
+EXPORT_SYMBOL(flush_tlb_page);
+EXPORT_SYMBOL(flush_tlb_one);
+EXPORT_SYMBOL(cpu_data);
+EXPORT_SYMBOL(synchronize_irq);
diff --git a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c
new file mode 100644
index 0000000..598bfe7
--- /dev/null
+++ b/arch/mips/kernel/syscall.c
@@ -0,0 +1,407 @@
+/*
+ * 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, 1996, 1997, 2000, 2001, 05 by Ralf Baechle
+ * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
+ * Copyright (C) 2001 MIPS Technologies, Inc.
+ */
+#include <linux/a.out.h>
+#include <linux/errno.h>
+#include <linux/linkage.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/mman.h>
+#include <linux/ptrace.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/syscalls.h>
+#include <linux/file.h>
+#include <linux/slab.h>
+#include <linux/utsname.h>
+#include <linux/unistd.h>
+#include <linux/sem.h>
+#include <linux/msg.h>
+#include <linux/shm.h>
+#include <linux/compiler.h>
+
+#include <asm/branch.h>
+#include <asm/cachectl.h>
+#include <asm/cacheflush.h>
+#include <asm/ipc.h>
+#include <asm/offset.h>
+#include <asm/signal.h>
+#include <asm/sim.h>
+#include <asm/shmparam.h>
+#include <asm/sysmips.h>
+#include <asm/uaccess.h>
+
+asmlinkage int sys_pipe(nabi_no_regargs volatile struct pt_regs regs)
+{
+ int fd[2];
+ int error, res;
+
+ error = do_pipe(fd);
+ if (error) {
+ res = error;
+ goto out;
+ }
+ regs.regs[3] = fd[1];
+ res = fd[0];
+out:
+ return res;
+}
+
+unsigned long shm_align_mask = PAGE_SIZE - 1; /* Sane caches */
+
+#define COLOUR_ALIGN(addr,pgoff) \
+ ((((addr) + shm_align_mask) & ~shm_align_mask) + \
+ (((pgoff) << PAGE_SHIFT) & shm_align_mask))
+
+unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
+ unsigned long len, unsigned long pgoff, unsigned long flags)
+{
+ struct vm_area_struct * vmm;
+ int do_color_align;
+ unsigned long task_size;
+
+ task_size = STACK_TOP;
+
+ if (flags & MAP_FIXED) {
+ /*
+ * We do not accept a shared mapping if it would violate
+ * cache aliasing constraints.
+ */
+ if ((flags & MAP_SHARED) && (addr & shm_align_mask))
+ return -EINVAL;
+ return addr;
+ }
+
+ if (len > task_size)
+ return -ENOMEM;
+ do_color_align = 0;
+ if (filp || (flags & MAP_SHARED))
+ do_color_align = 1;
+ if (addr) {
+ if (do_color_align)
+ addr = COLOUR_ALIGN(addr, pgoff);
+ else
+ addr = PAGE_ALIGN(addr);
+ vmm = find_vma(current->mm, addr);
+ if (task_size - len >= addr &&
+ (!vmm || addr + len <= vmm->vm_start))
+ return addr;
+ }
+ addr = TASK_UNMAPPED_BASE;
+ if (do_color_align)
+ addr = COLOUR_ALIGN(addr, pgoff);
+ else
+ addr = PAGE_ALIGN(addr);
+
+ for (vmm = find_vma(current->mm, addr); ; vmm = vmm->vm_next) {
+ /* At this point: (!vmm || addr < vmm->vm_end). */
+ if (task_size - len < addr)
+ return -ENOMEM;
+ if (!vmm || addr + len <= vmm->vm_start)
+ return addr;
+ addr = vmm->vm_end;
+ if (do_color_align)
+ addr = COLOUR_ALIGN(addr, pgoff);
+ }
+}
+
+/* common code for old and new mmaps */
+static inline unsigned long
+do_mmap2(unsigned long addr, unsigned long len, unsigned long prot,
+ unsigned long flags, unsigned long fd, unsigned long pgoff)
+{
+ unsigned long error = -EBADF;
+ struct file * file = NULL;
+
+ flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+ if (!(flags & MAP_ANONYMOUS)) {
+ file = fget(fd);
+ if (!file)
+ goto out;
+ }
+
+ down_write(¤t->mm->mmap_sem);
+ error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
+ up_write(¤t->mm->mmap_sem);
+
+ if (file)
+ fput(file);
+out:
+ return error;
+}
+
+asmlinkage unsigned long
+old_mmap(unsigned long addr, unsigned long len, int prot,
+ int flags, int fd, off_t offset)
+{
+ unsigned long result;
+
+ result = -EINVAL;
+ if (offset & ~PAGE_MASK)
+ goto out;
+
+ result = do_mmap2(addr, len, prot, flags, fd, offset >> PAGE_SHIFT);
+
+out:
+ return result;
+}
+
+asmlinkage unsigned long
+sys_mmap2(unsigned long addr, unsigned long len, unsigned long prot,
+ unsigned long flags, unsigned long fd, unsigned long pgoff)
+{
+ return do_mmap2(addr, len, prot, flags, fd, pgoff);
+}
+
+save_static_function(sys_fork);
+__attribute_used__ noinline static int
+_sys_fork(nabi_no_regargs struct pt_regs regs)
+{
+ return do_fork(SIGCHLD, regs.regs[29], ®s, 0, NULL, NULL);
+}
+
+save_static_function(sys_clone);
+__attribute_used__ noinline static int
+_sys_clone(nabi_no_regargs struct pt_regs regs)
+{
+ unsigned long clone_flags;
+ unsigned long newsp;
+ int *parent_tidptr, *child_tidptr;
+
+ clone_flags = regs.regs[4];
+ newsp = regs.regs[5];
+ if (!newsp)
+ newsp = regs.regs[29];
+ parent_tidptr = (int *) regs.regs[6];
+ child_tidptr = (int *) regs.regs[7];
+ return do_fork(clone_flags, newsp, ®s, 0,
+ parent_tidptr, child_tidptr);
+}
+
+/*
+ * sys_execve() executes a new program.
+ */
+asmlinkage int sys_execve(nabi_no_regargs struct pt_regs regs)
+{
+ int error;
+ char * filename;
+
+ filename = getname((char *) (long)regs.regs[4]);
+ error = PTR_ERR(filename);
+ if (IS_ERR(filename))
+ goto out;
+ error = do_execve(filename, (char **) (long)regs.regs[5],
+ (char **) (long)regs.regs[6], ®s);
+ putname(filename);
+
+out:
+ return error;
+}
+
+/*
+ * Compacrapability ...
+ */
+asmlinkage int sys_uname(struct old_utsname * name)
+{
+ if (name && !copy_to_user(name, &system_utsname, sizeof (*name)))
+ return 0;
+ return -EFAULT;
+}
+
+/*
+ * Compacrapability ...
+ */
+asmlinkage int sys_olduname(struct oldold_utsname * name)
+{
+ int error;
+
+ if (!name)
+ return -EFAULT;
+ if (!access_ok(VERIFY_WRITE,name,sizeof(struct oldold_utsname)))
+ return -EFAULT;
+
+ error = __copy_to_user(&name->sysname,&system_utsname.sysname,__OLD_UTS_LEN);
+ error -= __put_user(0,name->sysname+__OLD_UTS_LEN);
+ error -= __copy_to_user(&name->nodename,&system_utsname.nodename,__OLD_UTS_LEN);
+ error -= __put_user(0,name->nodename+__OLD_UTS_LEN);
+ error -= __copy_to_user(&name->release,&system_utsname.release,__OLD_UTS_LEN);
+ error -= __put_user(0,name->release+__OLD_UTS_LEN);
+ error -= __copy_to_user(&name->version,&system_utsname.version,__OLD_UTS_LEN);
+ error -= __put_user(0,name->version+__OLD_UTS_LEN);
+ error -= __copy_to_user(&name->machine,&system_utsname.machine,__OLD_UTS_LEN);
+ error = __put_user(0,name->machine+__OLD_UTS_LEN);
+ error = error ? -EFAULT : 0;
+
+ return error;
+}
+
+asmlinkage int _sys_sysmips(int cmd, long arg1, int arg2, int arg3)
+{
+ int tmp, len;
+ char *name;
+
+ switch(cmd) {
+ case SETNAME: {
+ char nodename[__NEW_UTS_LEN + 1];
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
+ name = (char *) arg1;
+
+ len = strncpy_from_user(nodename, name, __NEW_UTS_LEN);
+ if (len < 0)
+ return -EFAULT;
+
+ down_write(&uts_sem);
+ strncpy(system_utsname.nodename, nodename, len);
+ nodename[__NEW_UTS_LEN] = '\0';
+ strlcpy(system_utsname.nodename, nodename,
+ sizeof(system_utsname.nodename));
+ up_write(&uts_sem);
+ return 0;
+ }
+
+ case MIPS_ATOMIC_SET:
+ printk(KERN_CRIT "How did I get here?\n");
+ return -EINVAL;
+
+ case MIPS_FIXADE:
+ tmp = current->thread.mflags & ~3;
+ current->thread.mflags = tmp | (arg1 & 3);
+ return 0;
+
+ case FLUSH_CACHE:
+ __flush_cache_all();
+ return 0;
+
+ case MIPS_RDNVRAM:
+ return -EIO;
+ }
+
+ return -EINVAL;
+}
+
+/*
+ * sys_ipc() is the de-multiplexer for the SysV IPC calls..
+ *
+ * This is really horribly ugly.
+ */
+asmlinkage int sys_ipc (uint call, int first, int second,
+ unsigned long third, void *ptr, long fifth)
+{
+ int version, ret;
+
+ version = call >> 16; /* hack for backward compatibility */
+ call &= 0xffff;
+
+ switch (call) {
+ case SEMOP:
+ return sys_semtimedop (first, (struct sembuf *)ptr, second,
+ NULL);
+ case SEMTIMEDOP:
+ return sys_semtimedop (first, (struct sembuf *)ptr, second,
+ (const struct timespec __user *)fifth);
+ case SEMGET:
+ return sys_semget (first, second, third);
+ case SEMCTL: {
+ union semun fourth;
+ if (!ptr)
+ return -EINVAL;
+ if (get_user(fourth.__pad, (void **) ptr))
+ return -EFAULT;
+ return sys_semctl (first, second, third, fourth);
+ }
+
+ case MSGSND:
+ return sys_msgsnd (first, (struct msgbuf *) ptr,
+ second, third);
+ case MSGRCV:
+ switch (version) {
+ case 0: {
+ struct ipc_kludge tmp;
+ if (!ptr)
+ return -EINVAL;
+
+ if (copy_from_user(&tmp,
+ (struct ipc_kludge *) ptr,
+ sizeof (tmp)))
+ return -EFAULT;
+ return sys_msgrcv (first, tmp.msgp, second,
+ tmp.msgtyp, third);
+ }
+ default:
+ return sys_msgrcv (first,
+ (struct msgbuf *) ptr,
+ second, fifth, third);
+ }
+ case MSGGET:
+ return sys_msgget ((key_t) first, second);
+ case MSGCTL:
+ return sys_msgctl (first, second, (struct msqid_ds *) ptr);
+
+ case SHMAT:
+ switch (version) {
+ default: {
+ ulong raddr;
+ ret = do_shmat (first, (char *) ptr, second, &raddr);
+ if (ret)
+ return ret;
+ return put_user (raddr, (ulong *) third);
+ }
+ case 1: /* iBCS2 emulator entry point */
+ if (!segment_eq(get_fs(), get_ds()))
+ return -EINVAL;
+ return do_shmat (first, (char *) ptr, second, (ulong *) third);
+ }
+ case SHMDT:
+ return sys_shmdt ((char *)ptr);
+ case SHMGET:
+ return sys_shmget (first, second, third);
+ case SHMCTL:
+ return sys_shmctl (first, second,
+ (struct shmid_ds *) ptr);
+ default:
+ return -ENOSYS;
+ }
+}
+
+/*
+ * Native ABI that is O32 or N64 version
+ */
+asmlinkage long sys_shmat(int shmid, char __user *shmaddr,
+ int shmflg, unsigned long *addr)
+{
+ unsigned long raddr;
+ int err;
+
+ err = do_shmat(shmid, shmaddr, shmflg, &raddr);
+ if (err)
+ return err;
+
+ return put_user(raddr, addr);
+}
+
+/*
+ * No implemented yet ...
+ */
+asmlinkage int sys_cachectl(char *addr, int nbytes, int op)
+{
+ return -ENOSYS;
+}
+
+/*
+ * If we ever come here the user sp is bad. Zap the process right away.
+ * Due to the bad stack signaling wouldn't work.
+ */
+asmlinkage void bad_stack(void)
+{
+ do_exit(SIGSEGV);
+}
diff --git a/arch/mips/kernel/sysirix.c b/arch/mips/kernel/sysirix.c
new file mode 100644
index 0000000..f3bf0e4
--- /dev/null
+++ b/arch/mips/kernel/sysirix.c
@@ -0,0 +1,2179 @@
+/*
+ * sysirix.c: IRIX system call emulation.
+ *
+ * Copyright (C) 1996 David S. Miller
+ * Copyright (C) 1997 Miguel de Icaza
+ * Copyright (C) 1997, 1998, 1999, 2000 Ralf Baechle
+ */
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/binfmts.h>
+#include <linux/highuid.h>
+#include <linux/pagemap.h>
+#include <linux/mm.h>
+#include <linux/mman.h>
+#include <linux/slab.h>
+#include <linux/swap.h>
+#include <linux/errno.h>
+#include <linux/time.h>
+#include <linux/timex.h>
+#include <linux/times.h>
+#include <linux/elf.h>
+#include <linux/msg.h>
+#include <linux/shm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/utsname.h>
+#include <linux/file.h>
+#include <linux/vfs.h>
+#include <linux/namei.h>
+#include <linux/socket.h>
+#include <linux/security.h>
+#include <linux/syscalls.h>
+
+#include <asm/ptrace.h>
+#include <asm/page.h>
+#include <asm/uaccess.h>
+#include <asm/inventory.h>
+
+/* 2,191 lines of complete and utter shit coming up... */
+
+extern int max_threads;
+
+/* The sysmp commands supported thus far. */
+#define MP_NPROCS 1 /* # processor in complex */
+#define MP_NAPROCS 2 /* # active processors in complex */
+#define MP_PGSIZE 14 /* Return system page size in v1. */
+
+asmlinkage int irix_sysmp(struct pt_regs *regs)
+{
+ unsigned long cmd;
+ int base = 0;
+ int error = 0;
+
+ if(regs->regs[2] == 1000)
+ base = 1;
+ cmd = regs->regs[base + 4];
+ switch(cmd) {
+ case MP_PGSIZE:
+ error = PAGE_SIZE;
+ break;
+ case MP_NPROCS:
+ case MP_NAPROCS:
+ error = num_online_cpus();
+ break;
+ default:
+ printk("SYSMP[%s:%d]: Unsupported opcode %d\n",
+ current->comm, current->pid, (int)cmd);
+ error = -EINVAL;
+ break;
+ }
+
+ return error;
+}
+
+/* The prctl commands. */
+#define PR_MAXPROCS 1 /* Tasks/user. */
+#define PR_ISBLOCKED 2 /* If blocked, return 1. */
+#define PR_SETSTACKSIZE 3 /* Set largest task stack size. */
+#define PR_GETSTACKSIZE 4 /* Get largest task stack size. */
+#define PR_MAXPPROCS 5 /* Num parallel tasks. */
+#define PR_UNBLKONEXEC 6 /* When task exec/exit's, unblock. */
+#define PR_SETEXITSIG 8 /* When task exit's, set signal. */
+#define PR_RESIDENT 9 /* Make task unswappable. */
+#define PR_ATTACHADDR 10 /* (Re-)Connect a vma to a task. */
+#define PR_DETACHADDR 11 /* Disconnect a vma from a task. */
+#define PR_TERMCHILD 12 /* When parent sleeps with fishes, kill child. */
+#define PR_GETSHMASK 13 /* Get the sproc() share mask. */
+#define PR_GETNSHARE 14 /* Number of share group members. */
+#define PR_COREPID 15 /* Add task pid to name when it core. */
+#define PR_ATTACHADDRPERM 16 /* (Re-)Connect vma, with specified prot. */
+#define PR_PTHREADEXIT 17 /* Kill a pthread without prejudice. */
+
+asmlinkage int irix_prctl(struct pt_regs *regs)
+{
+ unsigned long cmd;
+ int error = 0, base = 0;
+
+ if (regs->regs[2] == 1000)
+ base = 1;
+ cmd = regs->regs[base + 4];
+ switch (cmd) {
+ case PR_MAXPROCS:
+ printk("irix_prctl[%s:%d]: Wants PR_MAXPROCS\n",
+ current->comm, current->pid);
+ error = max_threads;
+ break;
+
+ case PR_ISBLOCKED: {
+ struct task_struct *task;
+
+ printk("irix_prctl[%s:%d]: Wants PR_ISBLOCKED\n",
+ current->comm, current->pid);
+ read_lock(&tasklist_lock);
+ task = find_task_by_pid(regs->regs[base + 5]);
+ error = -ESRCH;
+ if (error)
+ error = (task->run_list.next != NULL);
+ read_unlock(&tasklist_lock);
+ /* Can _your_ OS find this out that fast? */
+ break;
+ }
+
+ case PR_SETSTACKSIZE: {
+ long value = regs->regs[base + 5];
+
+ printk("irix_prctl[%s:%d]: Wants PR_SETSTACKSIZE<%08lx>\n",
+ current->comm, current->pid, (unsigned long) value);
+ if (value > RLIM_INFINITY)
+ value = RLIM_INFINITY;
+ if (capable(CAP_SYS_ADMIN)) {
+ task_lock(current->group_leader);
+ current->signal->rlim[RLIMIT_STACK].rlim_max =
+ current->signal->rlim[RLIMIT_STACK].rlim_cur = value;
+ task_unlock(current->group_leader);
+ error = value;
+ break;
+ }
+ task_lock(current->group_leader);
+ if (value > current->signal->rlim[RLIMIT_STACK].rlim_max) {
+ error = -EINVAL;
+ task_unlock(current->group_leader);
+ break;
+ }
+ current->signal->rlim[RLIMIT_STACK].rlim_cur = value;
+ task_unlock(current->group_leader);
+ error = value;
+ break;
+ }
+
+ case PR_GETSTACKSIZE:
+ printk("irix_prctl[%s:%d]: Wants PR_GETSTACKSIZE\n",
+ current->comm, current->pid);
+ error = current->signal->rlim[RLIMIT_STACK].rlim_cur;
+ break;
+
+ case PR_MAXPPROCS:
+ printk("irix_prctl[%s:%d]: Wants PR_MAXPROCS\n",
+ current->comm, current->pid);
+ error = 1;
+ break;
+
+ case PR_UNBLKONEXEC:
+ printk("irix_prctl[%s:%d]: Wants PR_UNBLKONEXEC\n",
+ current->comm, current->pid);
+ error = -EINVAL;
+ break;
+
+ case PR_SETEXITSIG:
+ printk("irix_prctl[%s:%d]: Wants PR_SETEXITSIG\n",
+ current->comm, current->pid);
+
+ /* We can probably play some game where we set the task
+ * exit_code to some non-zero value when this is requested,
+ * and check whether exit_code is already set in do_exit().
+ */
+ error = -EINVAL;
+ break;
+
+ case PR_RESIDENT:
+ printk("irix_prctl[%s:%d]: Wants PR_RESIDENT\n",
+ current->comm, current->pid);
+ error = 0; /* Compatibility indeed. */
+ break;
+
+ case PR_ATTACHADDR:
+ printk("irix_prctl[%s:%d]: Wants PR_ATTACHADDR\n",
+ current->comm, current->pid);
+ error = -EINVAL;
+ break;
+
+ case PR_DETACHADDR:
+ printk("irix_prctl[%s:%d]: Wants PR_DETACHADDR\n",
+ current->comm, current->pid);
+ error = -EINVAL;
+ break;
+
+ case PR_TERMCHILD:
+ printk("irix_prctl[%s:%d]: Wants PR_TERMCHILD\n",
+ current->comm, current->pid);
+ error = -EINVAL;
+ break;
+
+ case PR_GETSHMASK:
+ printk("irix_prctl[%s:%d]: Wants PR_GETSHMASK\n",
+ current->comm, current->pid);
+ error = -EINVAL; /* Until I have the sproc() stuff in. */
+ break;
+
+ case PR_GETNSHARE:
+ error = 0; /* Until I have the sproc() stuff in. */
+ break;
+
+ case PR_COREPID:
+ printk("irix_prctl[%s:%d]: Wants PR_COREPID\n",
+ current->comm, current->pid);
+ error = -EINVAL;
+ break;
+
+ case PR_ATTACHADDRPERM:
+ printk("irix_prctl[%s:%d]: Wants PR_ATTACHADDRPERM\n",
+ current->comm, current->pid);
+ error = -EINVAL;
+ break;
+
+ case PR_PTHREADEXIT:
+ printk("irix_prctl[%s:%d]: Wants PR_PTHREADEXIT\n",
+ current->comm, current->pid);
+ do_exit(regs->regs[base + 5]);
+
+ default:
+ printk("irix_prctl[%s:%d]: Non-existant opcode %d\n",
+ current->comm, current->pid, (int)cmd);
+ error = -EINVAL;
+ break;
+ }
+
+ return error;
+}
+
+#undef DEBUG_PROCGRPS
+
+extern unsigned long irix_mapelf(int fd, struct elf_phdr *user_phdrp, int cnt);
+extern int getrusage(struct task_struct *p, int who, struct rusage __user *ru);
+extern char *prom_getenv(char *name);
+extern long prom_setenv(char *name, char *value);
+
+/* The syssgi commands supported thus far. */
+#define SGI_SYSID 1 /* Return unique per-machine identifier. */
+#define SGI_INVENT 5 /* Fetch inventory */
+# define SGI_INV_SIZEOF 1
+# define SGI_INV_READ 2
+#define SGI_RDNAME 6 /* Return string name of a process. */
+#define SGI_SETNVRAM 8 /* Set PROM variable. */
+#define SGI_GETNVRAM 9 /* Get PROM variable. */
+#define SGI_SETPGID 21 /* Set process group id. */
+#define SGI_SYSCONF 22 /* POSIX sysconf garbage. */
+#define SGI_PATHCONF 24 /* POSIX sysconf garbage. */
+#define SGI_SETGROUPS 40 /* POSIX sysconf garbage. */
+#define SGI_GETGROUPS 41 /* POSIX sysconf garbage. */
+#define SGI_RUSAGE 56 /* BSD style rusage(). */
+#define SGI_SSYNC 62 /* Synchronous fs sync. */
+#define SGI_GETSID 65 /* SysVr4 get session id. */
+#define SGI_ELFMAP 68 /* Map an elf image. */
+#define SGI_TOSSTSAVE 108 /* Toss saved vma's. */
+#define SGI_FP_BCOPY 129 /* Should FPU bcopy be used on this machine? */
+#define SGI_PHYSP 1011 /* Translate virtual into physical page. */
+
+asmlinkage int irix_syssgi(struct pt_regs *regs)
+{
+ unsigned long cmd;
+ int retval, base = 0;
+
+ if (regs->regs[2] == 1000)
+ base = 1;
+
+ cmd = regs->regs[base + 4];
+ switch(cmd) {
+ case SGI_SYSID: {
+ char *buf = (char *) regs->regs[base + 5];
+
+ /* XXX Use ethernet addr.... */
+ retval = clear_user(buf, 64);
+ break;
+ }
+#if 0
+ case SGI_RDNAME: {
+ int pid = (int) regs->regs[base + 5];
+ char *buf = (char *) regs->regs[base + 6];
+ struct task_struct *p;
+ char tcomm[sizeof(current->comm)];
+
+ if (!access_ok(VERIFY_WRITE, buf, sizeof(tcomm))) {
+ retval = -EFAULT;
+ break;
+ }
+ read_lock(&tasklist_lock);
+ p = find_task_by_pid(pid);
+ if (!p) {
+ read_unlock(&tasklist_lock);
+ retval = -ESRCH;
+ break;
+ }
+ get_task_comm(tcomm, p);
+ read_unlock(&tasklist_lock);
+
+ /* XXX Need to check sizes. */
+ copy_to_user(buf, tcomm, sizeof(tcomm));
+ retval = 0;
+ break;
+ }
+
+ case SGI_GETNVRAM: {
+ char *name = (char *) regs->regs[base+5];
+ char *buf = (char *) regs->regs[base+6];
+ char *value;
+ return -EINVAL; /* til I fix it */
+ if (!access_ok(VERIFY_WRITE, buf, 128)) {
+ retval = -EFAULT;
+ break;
+ }
+ value = prom_getenv(name); /* PROM lock? */
+ if (!value) {
+ retval = -EINVAL;
+ break;
+ }
+ /* Do I strlen() for the length? */
+ copy_to_user(buf, value, 128);
+ retval = 0;
+ break;
+ }
+
+ case SGI_SETNVRAM: {
+ char *name = (char *) regs->regs[base+5];
+ char *value = (char *) regs->regs[base+6];
+ return -EINVAL; /* til I fix it */
+ retval = prom_setenv(name, value);
+ /* XXX make sure retval conforms to syssgi(2) */
+ printk("[%s:%d] setnvram(\"%s\", \"%s\"): retval %d",
+ current->comm, current->pid, name, value, retval);
+/* if (retval == PROM_ENOENT)
+ retval = -ENOENT; */
+ break;
+ }
+#endif
+
+ case SGI_SETPGID: {
+#ifdef DEBUG_PROCGRPS
+ printk("[%s:%d] setpgid(%d, %d) ",
+ current->comm, current->pid,
+ (int) regs->regs[base + 5], (int)regs->regs[base + 6]);
+#endif
+ retval = sys_setpgid(regs->regs[base + 5], regs->regs[base + 6]);
+
+#ifdef DEBUG_PROCGRPS
+ printk("retval=%d\n", retval);
+#endif
+ }
+
+ case SGI_SYSCONF: {
+ switch(regs->regs[base + 5]) {
+ case 1:
+ retval = (MAX_ARG_PAGES >> 4); /* XXX estimate... */
+ goto out;
+ case 2:
+ retval = max_threads;
+ goto out;
+ case 3:
+ retval = HZ;
+ goto out;
+ case 4:
+ retval = NGROUPS_MAX;
+ goto out;
+ case 5:
+ retval = NR_OPEN;
+ goto out;
+ case 6:
+ retval = 1;
+ goto out;
+ case 7:
+ retval = 1;
+ goto out;
+ case 8:
+ retval = 199009;
+ goto out;
+ case 11:
+ retval = PAGE_SIZE;
+ goto out;
+ case 12:
+ retval = 4;
+ goto out;
+ case 25:
+ case 26:
+ case 27:
+ case 28:
+ case 29:
+ case 30:
+ retval = 0;
+ goto out;
+ case 31:
+ retval = 32;
+ goto out;
+ default:
+ retval = -EINVAL;
+ goto out;
+ };
+ }
+
+ case SGI_SETGROUPS:
+ retval = sys_setgroups((int) regs->regs[base + 5],
+ (gid_t *) regs->regs[base + 6]);
+ break;
+
+ case SGI_GETGROUPS:
+ retval = sys_getgroups((int) regs->regs[base + 5],
+ (gid_t *) regs->regs[base + 6]);
+ break;
+
+ case SGI_RUSAGE: {
+ struct rusage *ru = (struct rusage *) regs->regs[base + 6];
+
+ switch((int) regs->regs[base + 5]) {
+ case 0:
+ /* rusage self */
+ retval = getrusage(current, RUSAGE_SELF, ru);
+ goto out;
+
+ case -1:
+ /* rusage children */
+ retval = getrusage(current, RUSAGE_CHILDREN, ru);
+ goto out;
+
+ default:
+ retval = -EINVAL;
+ goto out;
+ };
+ }
+
+ case SGI_SSYNC:
+ sys_sync();
+ retval = 0;
+ break;
+
+ case SGI_GETSID:
+#ifdef DEBUG_PROCGRPS
+ printk("[%s:%d] getsid(%d) ", current->comm, current->pid,
+ (int) regs->regs[base + 5]);
+#endif
+ retval = sys_getsid(regs->regs[base + 5]);
+#ifdef DEBUG_PROCGRPS
+ printk("retval=%d\n", retval);
+#endif
+ break;
+
+ case SGI_ELFMAP:
+ retval = irix_mapelf((int) regs->regs[base + 5],
+ (struct elf_phdr *) regs->regs[base + 6],
+ (int) regs->regs[base + 7]);
+ break;
+
+ case SGI_TOSSTSAVE:
+ /* XXX We don't need to do anything? */
+ retval = 0;
+ break;
+
+ case SGI_FP_BCOPY:
+ retval = 0;
+ break;
+
+ case SGI_PHYSP: {
+ unsigned long addr = regs->regs[base + 5];
+ int *pageno = (int *) (regs->regs[base + 6]);
+ struct mm_struct *mm = current->mm;
+ pgd_t *pgdp;
+ pmd_t *pmdp;
+ pte_t *ptep;
+
+ if (!access_ok(VERIFY_WRITE, pageno, sizeof(int)))
+ return -EFAULT;
+
+ down_read(&mm->mmap_sem);
+ pgdp = pgd_offset(mm, addr);
+ pmdp = pmd_offset(pgdp, addr);
+ ptep = pte_offset(pmdp, addr);
+ retval = -EINVAL;
+ if (ptep) {
+ pte_t pte = *ptep;
+
+ if (pte_val(pte) & (_PAGE_VALID | _PAGE_PRESENT)) {
+ retval = put_user((pte_val(pte) & PAGE_MASK) >>
+ PAGE_SHIFT, pageno);
+ }
+ }
+ up_read(&mm->mmap_sem);
+ break;
+ }
+
+ case SGI_INVENT: {
+ int arg1 = (int) regs->regs [base + 5];
+ void *buffer = (void *) regs->regs [base + 6];
+ int count = (int) regs->regs [base + 7];
+
+ switch (arg1) {
+ case SGI_INV_SIZEOF:
+ retval = sizeof (inventory_t);
+ break;
+ case SGI_INV_READ:
+ retval = dump_inventory_to_user (buffer, count);
+ break;
+ default:
+ retval = -EINVAL;
+ }
+ break;
+ }
+
+ default:
+ printk("irix_syssgi: Unsupported command %d\n", (int)cmd);
+ retval = -EINVAL;
+ break;
+ };
+
+out:
+ return retval;
+}
+
+asmlinkage int irix_gtime(struct pt_regs *regs)
+{
+ return get_seconds();
+}
+
+/*
+ * IRIX is completely broken... it returns 0 on success, otherwise
+ * ENOMEM.
+ */
+asmlinkage int irix_brk(unsigned long brk)
+{
+ unsigned long rlim;
+ unsigned long newbrk, oldbrk;
+ struct mm_struct *mm = current->mm;
+ int ret;
+
+ down_write(&mm->mmap_sem);
+ if (brk < mm->end_code) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ newbrk = PAGE_ALIGN(brk);
+ oldbrk = PAGE_ALIGN(mm->brk);
+ if (oldbrk == newbrk) {
+ mm->brk = brk;
+ ret = 0;
+ goto out;
+ }
+
+ /*
+ * Always allow shrinking brk
+ */
+ if (brk <= mm->brk) {
+ mm->brk = brk;
+ do_munmap(mm, newbrk, oldbrk-newbrk);
+ ret = 0;
+ goto out;
+ }
+ /*
+ * Check against rlimit and stack..
+ */
+ rlim = current->signal->rlim[RLIMIT_DATA].rlim_cur;
+ if (rlim >= RLIM_INFINITY)
+ rlim = ~0;
+ if (brk - mm->end_code > rlim) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ /*
+ * Check against existing mmap mappings.
+ */
+ if (find_vma_intersection(mm, oldbrk, newbrk+PAGE_SIZE)) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ /*
+ * Check if we have enough memory..
+ */
+ if (security_vm_enough_memory((newbrk-oldbrk) >> PAGE_SHIFT)) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ /*
+ * Ok, looks good - let it rip.
+ */
+ mm->brk = brk;
+ do_brk(oldbrk, newbrk-oldbrk);
+ ret = 0;
+
+out:
+ up_write(&mm->mmap_sem);
+ return ret;
+}
+
+asmlinkage int irix_getpid(struct pt_regs *regs)
+{
+ regs->regs[3] = current->real_parent->pid;
+ return current->pid;
+}
+
+asmlinkage int irix_getuid(struct pt_regs *regs)
+{
+ regs->regs[3] = current->euid;
+ return current->uid;
+}
+
+asmlinkage int irix_getgid(struct pt_regs *regs)
+{
+ regs->regs[3] = current->egid;
+ return current->gid;
+}
+
+asmlinkage int irix_stime(int value)
+{
+ int err;
+ struct timespec tv;
+
+ tv.tv_sec = value;
+ tv.tv_nsec = 0;
+ err = security_settime(&tv, NULL);
+ if (err)
+ return err;
+
+ write_seqlock_irq(&xtime_lock);
+ xtime.tv_sec = value;
+ xtime.tv_nsec = 0;
+ time_adjust = 0; /* stop active adjtime() */
+ time_status |= STA_UNSYNC;
+ time_maxerror = NTP_PHASE_LIMIT;
+ time_esterror = NTP_PHASE_LIMIT;
+ write_sequnlock_irq(&xtime_lock);
+
+ return 0;
+}
+
+static inline void jiffiestotv(unsigned long jiffies, struct timeval *value)
+{
+ value->tv_usec = (jiffies % HZ) * (1000000 / HZ);
+ value->tv_sec = jiffies / HZ;
+}
+
+static inline void getitimer_real(struct itimerval *value)
+{
+ register unsigned long val, interval;
+
+ interval = current->it_real_incr;
+ val = 0;
+ if (del_timer(¤t->real_timer)) {
+ unsigned long now = jiffies;
+ val = current->real_timer.expires;
+ add_timer(¤t->real_timer);
+ /* look out for negative/zero itimer.. */
+ if (val <= now)
+ val = now+1;
+ val -= now;
+ }
+ jiffiestotv(val, &value->it_value);
+ jiffiestotv(interval, &value->it_interval);
+}
+
+asmlinkage unsigned int irix_alarm(unsigned int seconds)
+{
+ struct itimerval it_new, it_old;
+ unsigned int oldalarm;
+
+ if (!seconds) {
+ getitimer_real(&it_old);
+ del_timer(¤t->real_timer);
+ } else {
+ it_new.it_interval.tv_sec = it_new.it_interval.tv_usec = 0;
+ it_new.it_value.tv_sec = seconds;
+ it_new.it_value.tv_usec = 0;
+ do_setitimer(ITIMER_REAL, &it_new, &it_old);
+ }
+ oldalarm = it_old.it_value.tv_sec;
+ /*
+ * ehhh.. We can't return 0 if we have an alarm pending ...
+ * And we'd better return too much than too little anyway
+ */
+ if (it_old.it_value.tv_usec)
+ oldalarm++;
+
+ return oldalarm;
+}
+
+asmlinkage int irix_pause(void)
+{
+ current->state = TASK_INTERRUPTIBLE;
+ schedule();
+
+ return -EINTR;
+}
+
+/* XXX need more than this... */
+asmlinkage int irix_mount(char *dev_name, char *dir_name, unsigned long flags,
+ char *type, void *data, int datalen)
+{
+ printk("[%s:%d] irix_mount(%p,%p,%08lx,%p,%p,%d)\n",
+ current->comm, current->pid,
+ dev_name, dir_name, flags, type, data, datalen);
+
+ return sys_mount(dev_name, dir_name, type, flags, data);
+}
+
+struct irix_statfs {
+ short f_type;
+ long f_bsize, f_frsize, f_blocks, f_bfree, f_files, f_ffree;
+ char f_fname[6], f_fpack[6];
+};
+
+asmlinkage int irix_statfs(const char *path, struct irix_statfs *buf,
+ int len, int fs_type)
+{
+ struct nameidata nd;
+ struct kstatfs kbuf;
+ int error, i;
+
+ /* We don't support this feature yet. */
+ if (fs_type) {
+ error = -EINVAL;
+ goto out;
+ }
+ if (!access_ok(VERIFY_WRITE, buf, sizeof(struct irix_statfs))) {
+ error = -EFAULT;
+ goto out;
+ }
+ error = user_path_walk(path, &nd);
+ if (error)
+ goto out;
+
+ error = vfs_statfs(nd.dentry->d_inode->i_sb, &kbuf);
+ if (error)
+ goto dput_and_out;
+
+ __put_user(kbuf.f_type, &buf->f_type);
+ __put_user(kbuf.f_bsize, &buf->f_bsize);
+ __put_user(kbuf.f_frsize, &buf->f_frsize);
+ __put_user(kbuf.f_blocks, &buf->f_blocks);
+ __put_user(kbuf.f_bfree, &buf->f_bfree);
+ __put_user(kbuf.f_files, &buf->f_files);
+ __put_user(kbuf.f_ffree, &buf->f_ffree);
+ for (i = 0; i < 6; i++) {
+ __put_user(0, &buf->f_fname[i]);
+ __put_user(0, &buf->f_fpack[i]);
+ }
+ error = 0;
+
+dput_and_out:
+ path_release(&nd);
+out:
+ return error;
+}
+
+asmlinkage int irix_fstatfs(unsigned int fd, struct irix_statfs *buf)
+{
+ struct kstatfs kbuf;
+ struct file *file;
+ int error, i;
+
+ if (!access_ok(VERIFY_WRITE, buf, sizeof(struct irix_statfs))) {
+ error = -EFAULT;
+ goto out;
+ }
+ if (!(file = fget(fd))) {
+ error = -EBADF;
+ goto out;
+ }
+
+ error = vfs_statfs(file->f_dentry->d_inode->i_sb, &kbuf);
+ if (error)
+ goto out_f;
+
+ __put_user(kbuf.f_type, &buf->f_type);
+ __put_user(kbuf.f_bsize, &buf->f_bsize);
+ __put_user(kbuf.f_frsize, &buf->f_frsize);
+ __put_user(kbuf.f_blocks, &buf->f_blocks);
+ __put_user(kbuf.f_bfree, &buf->f_bfree);
+ __put_user(kbuf.f_files, &buf->f_files);
+ __put_user(kbuf.f_ffree, &buf->f_ffree);
+ for(i = 0; i < 6; i++) {
+ __put_user(0, &buf->f_fname[i]);
+ __put_user(0, &buf->f_fpack[i]);
+ }
+
+out_f:
+ fput(file);
+out:
+ return error;
+}
+
+asmlinkage int irix_setpgrp(int flags)
+{
+ int error;
+
+#ifdef DEBUG_PROCGRPS
+ printk("[%s:%d] setpgrp(%d) ", current->comm, current->pid, flags);
+#endif
+ if(!flags)
+ error = process_group(current);
+ else
+ error = sys_setsid();
+#ifdef DEBUG_PROCGRPS
+ printk("returning %d\n", process_group(current));
+#endif
+
+ return error;
+}
+
+asmlinkage int irix_times(struct tms * tbuf)
+{
+ int err = 0;
+
+ if (tbuf) {
+ if (!access_ok(VERIFY_WRITE,tbuf,sizeof *tbuf))
+ return -EFAULT;
+ err |= __put_user(current->utime, &tbuf->tms_utime);
+ err |= __put_user(current->stime, &tbuf->tms_stime);
+ err |= __put_user(current->signal->cutime, &tbuf->tms_cutime);
+ err |= __put_user(current->signal->cstime, &tbuf->tms_cstime);
+ }
+
+ return err;
+}
+
+asmlinkage int irix_exec(struct pt_regs *regs)
+{
+ int error, base = 0;
+ char *filename;
+
+ if(regs->regs[2] == 1000)
+ base = 1;
+ filename = getname((char *) (long)regs->regs[base + 4]);
+ error = PTR_ERR(filename);
+ if (IS_ERR(filename))
+ return error;
+
+ error = do_execve(filename, (char **) (long)regs->regs[base + 5],
+ (char **) 0, regs);
+ putname(filename);
+
+ return error;
+}
+
+asmlinkage int irix_exece(struct pt_regs *regs)
+{
+ int error, base = 0;
+ char *filename;
+
+ if (regs->regs[2] == 1000)
+ base = 1;
+ filename = getname((char *) (long)regs->regs[base + 4]);
+ error = PTR_ERR(filename);
+ if (IS_ERR(filename))
+ return error;
+ error = do_execve(filename, (char **) (long)regs->regs[base + 5],
+ (char **) (long)regs->regs[base + 6], regs);
+ putname(filename);
+
+ return error;
+}
+
+asmlinkage unsigned long irix_gethostid(void)
+{
+ printk("[%s:%d]: irix_gethostid() called...\n",
+ current->comm, current->pid);
+
+ return -EINVAL;
+}
+
+asmlinkage unsigned long irix_sethostid(unsigned long val)
+{
+ printk("[%s:%d]: irix_sethostid(%08lx) called...\n",
+ current->comm, current->pid, val);
+
+ return -EINVAL;
+}
+
+asmlinkage int irix_socket(int family, int type, int protocol)
+{
+ switch(type) {
+ case 1:
+ type = SOCK_DGRAM;
+ break;
+
+ case 2:
+ type = SOCK_STREAM;
+ break;
+
+ case 3:
+ type = 9; /* Invalid... */
+ break;
+
+ case 4:
+ type = SOCK_RAW;
+ break;
+
+ case 5:
+ type = SOCK_RDM;
+ break;
+
+ case 6:
+ type = SOCK_SEQPACKET;
+ break;
+
+ default:
+ break;
+ }
+
+ return sys_socket(family, type, protocol);
+}
+
+asmlinkage int irix_getdomainname(char *name, int len)
+{
+ int error;
+
+ if (!access_ok(VERIFY_WRITE, name, len))
+ return -EFAULT;
+
+ down_read(&uts_sem);
+ if (len > __NEW_UTS_LEN)
+ len = __NEW_UTS_LEN;
+ error = 0;
+ if (copy_to_user(name, system_utsname.domainname, len))
+ error = -EFAULT;
+ up_read(&uts_sem);
+
+ return error;
+}
+
+asmlinkage unsigned long irix_getpagesize(void)
+{
+ return PAGE_SIZE;
+}
+
+asmlinkage int irix_msgsys(int opcode, unsigned long arg0, unsigned long arg1,
+ unsigned long arg2, unsigned long arg3,
+ unsigned long arg4)
+{
+ switch (opcode) {
+ case 0:
+ return sys_msgget((key_t) arg0, (int) arg1);
+ case 1:
+ return sys_msgctl((int) arg0, (int) arg1, (struct msqid_ds *)arg2);
+ case 2:
+ return sys_msgrcv((int) arg0, (struct msgbuf *) arg1,
+ (size_t) arg2, (long) arg3, (int) arg4);
+ case 3:
+ return sys_msgsnd((int) arg0, (struct msgbuf *) arg1,
+ (size_t) arg2, (int) arg3);
+ default:
+ return -EINVAL;
+ }
+}
+
+asmlinkage int irix_shmsys(int opcode, unsigned long arg0, unsigned long arg1,
+ unsigned long arg2, unsigned long arg3)
+{
+ switch (opcode) {
+ case 0:
+ return do_shmat((int) arg0, (char *)arg1, (int) arg2,
+ (unsigned long *) arg3);
+ case 1:
+ return sys_shmctl((int)arg0, (int)arg1, (struct shmid_ds *)arg2);
+ case 2:
+ return sys_shmdt((char *)arg0);
+ case 3:
+ return sys_shmget((key_t) arg0, (int) arg1, (int) arg2);
+ default:
+ return -EINVAL;
+ }
+}
+
+asmlinkage int irix_semsys(int opcode, unsigned long arg0, unsigned long arg1,
+ unsigned long arg2, int arg3)
+{
+ switch (opcode) {
+ case 0:
+ return sys_semctl((int) arg0, (int) arg1, (int) arg2,
+ (union semun) arg3);
+ case 1:
+ return sys_semget((key_t) arg0, (int) arg1, (int) arg2);
+ case 2:
+ return sys_semop((int) arg0, (struct sembuf *)arg1,
+ (unsigned int) arg2);
+ default:
+ return -EINVAL;
+ }
+}
+
+static inline loff_t llseek(struct file *file, loff_t offset, int origin)
+{
+ loff_t (*fn)(struct file *, loff_t, int);
+ loff_t retval;
+
+ fn = default_llseek;
+ if (file->f_op && file->f_op->llseek)
+ fn = file->f_op->llseek;
+ lock_kernel();
+ retval = fn(file, offset, origin);
+ unlock_kernel();
+ return retval;
+}
+
+asmlinkage int irix_lseek64(int fd, int _unused, int offhi, int offlow,
+ int origin)
+{
+ int retval;
+ struct file * file;
+ loff_t offset;
+
+ retval = -EBADF;
+ file = fget(fd);
+ if (!file)
+ goto bad;
+ retval = -EINVAL;
+ if (origin > 2)
+ goto out_putf;
+
+ offset = llseek(file, ((loff_t) offhi << 32) | offlow, origin);
+ retval = (int) offset;
+
+out_putf:
+ fput(file);
+bad:
+ return retval;
+}
+
+asmlinkage int irix_sginap(int ticks)
+{
+ current->state = TASK_INTERRUPTIBLE;
+ schedule_timeout(ticks);
+ return 0;
+}
+
+asmlinkage int irix_sgikopt(char *istring, char *ostring, int len)
+{
+ return -EINVAL;
+}
+
+asmlinkage int irix_gettimeofday(struct timeval *tv)
+{
+ time_t sec;
+ long nsec, seq;
+ int err;
+
+ if (!access_ok(VERIFY_WRITE, tv, sizeof(struct timeval)))
+ return -EFAULT;
+
+ do {
+ seq = read_seqbegin(&xtime_lock);
+ sec = xtime.tv_sec;
+ nsec = xtime.tv_nsec;
+ } while (read_seqretry(&xtime_lock, seq));
+
+ err = __put_user(sec, &tv->tv_sec);
+ err |= __put_user((nsec / 1000), &tv->tv_usec);
+
+ return err;
+}
+
+#define IRIX_MAP_AUTOGROW 0x40
+
+asmlinkage unsigned long irix_mmap32(unsigned long addr, size_t len, int prot,
+ int flags, int fd, off_t offset)
+{
+ struct file *file = NULL;
+ unsigned long retval;
+
+ if (!(flags & MAP_ANONYMOUS)) {
+ if (!(file = fget(fd)))
+ return -EBADF;
+
+ /* Ok, bad taste hack follows, try to think in something else
+ * when reading this. */
+ if (flags & IRIX_MAP_AUTOGROW) {
+ unsigned long old_pos;
+ long max_size = offset + len;
+
+ if (max_size > file->f_dentry->d_inode->i_size) {
+ old_pos = sys_lseek (fd, max_size - 1, 0);
+ sys_write (fd, "", 1);
+ sys_lseek (fd, old_pos, 0);
+ }
+ }
+ }
+
+ flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+
+ down_write(¤t->mm->mmap_sem);
+ retval = do_mmap(file, addr, len, prot, flags, offset);
+ up_write(¤t->mm->mmap_sem);
+ if (file)
+ fput(file);
+
+ return retval;
+}
+
+asmlinkage int irix_madvise(unsigned long addr, int len, int behavior)
+{
+ printk("[%s:%d] Wheee.. irix_madvise(%08lx,%d,%d)\n",
+ current->comm, current->pid, addr, len, behavior);
+
+ return -EINVAL;
+}
+
+asmlinkage int irix_pagelock(char *addr, int len, int op)
+{
+ printk("[%s:%d] Wheee.. irix_pagelock(%p,%d,%d)\n",
+ current->comm, current->pid, addr, len, op);
+
+ return -EINVAL;
+}
+
+asmlinkage int irix_quotactl(struct pt_regs *regs)
+{
+ printk("[%s:%d] Wheee.. irix_quotactl()\n",
+ current->comm, current->pid);
+
+ return -EINVAL;
+}
+
+asmlinkage int irix_BSDsetpgrp(int pid, int pgrp)
+{
+ int error;
+
+#ifdef DEBUG_PROCGRPS
+ printk("[%s:%d] BSDsetpgrp(%d, %d) ", current->comm, current->pid,
+ pid, pgrp);
+#endif
+ if(!pid)
+ pid = current->pid;
+
+ /* Wheee, weird sysv thing... */
+ if ((pgrp == 0) && (pid == current->pid))
+ error = sys_setsid();
+ else
+ error = sys_setpgid(pid, pgrp);
+
+#ifdef DEBUG_PROCGRPS
+ printk("error = %d\n", error);
+#endif
+
+ return error;
+}
+
+asmlinkage int irix_systeminfo(int cmd, char *buf, int cnt)
+{
+ printk("[%s:%d] Wheee.. irix_systeminfo(%d,%p,%d)\n",
+ current->comm, current->pid, cmd, buf, cnt);
+
+ return -EINVAL;
+}
+
+struct iuname {
+ char sysname[257], nodename[257], release[257];
+ char version[257], machine[257];
+ char m_type[257], base_rel[257];
+ char _unused0[257], _unused1[257], _unused2[257];
+ char _unused3[257], _unused4[257], _unused5[257];
+};
+
+asmlinkage int irix_uname(struct iuname *buf)
+{
+ down_read(&uts_sem);
+ if (copy_to_user(system_utsname.sysname, buf->sysname, 65)
+ || copy_to_user(system_utsname.nodename, buf->nodename, 65)
+ || copy_to_user(system_utsname.release, buf->release, 65)
+ || copy_to_user(system_utsname.version, buf->version, 65)
+ || copy_to_user(system_utsname.machine, buf->machine, 65)) {
+ return -EFAULT;
+ }
+ up_read(&uts_sem);
+
+ return 1;
+}
+
+#undef DEBUG_XSTAT
+
+static int irix_xstat32_xlate(struct kstat *stat, void *ubuf)
+{
+ struct xstat32 {
+ u32 st_dev, st_pad1[3], st_ino, st_mode, st_nlink, st_uid, st_gid;
+ u32 st_rdev, st_pad2[2], st_size, st_pad3;
+ u32 st_atime0, st_atime1;
+ u32 st_mtime0, st_mtime1;
+ u32 st_ctime0, st_ctime1;
+ u32 st_blksize, st_blocks;
+ char st_fstype[16];
+ u32 st_pad4[8];
+ } ub;
+
+ if (!sysv_valid_dev(stat->dev) || !sysv_valid_dev(stat->rdev))
+ return -EOVERFLOW;
+ ub.st_dev = sysv_encode_dev(stat->dev);
+ ub.st_ino = stat->ino;
+ ub.st_mode = stat->mode;
+ ub.st_nlink = stat->nlink;
+ SET_UID(ub.st_uid, stat->uid);
+ SET_GID(ub.st_gid, stat->gid);
+ ub.st_rdev = sysv_encode_dev(stat->rdev);
+#if BITS_PER_LONG == 32
+ if (stat->size > MAX_NON_LFS)
+ return -EOVERFLOW;
+#endif
+ ub.st_size = stat->size;
+ ub.st_atime0 = stat->atime.tv_sec;
+ ub.st_atime1 = stat->atime.tv_nsec;
+ ub.st_mtime0 = stat->mtime.tv_sec;
+ ub.st_mtime1 = stat->atime.tv_nsec;
+ ub.st_ctime0 = stat->ctime.tv_sec;
+ ub.st_ctime1 = stat->atime.tv_nsec;
+ ub.st_blksize = stat->blksize;
+ ub.st_blocks = stat->blocks;
+ strcpy (ub.st_fstype, "efs");
+
+ return copy_to_user(ubuf, &ub, sizeof(ub)) ? -EFAULT : 0;
+}
+
+static int irix_xstat64_xlate(struct kstat *stat, void *ubuf)
+{
+ struct xstat64 {
+ u32 st_dev; s32 st_pad1[3];
+ unsigned long long st_ino;
+ u32 st_mode;
+ u32 st_nlink; s32 st_uid; s32 st_gid; u32 st_rdev;
+ s32 st_pad2[2];
+ long long st_size;
+ s32 st_pad3;
+ struct { s32 tv_sec, tv_nsec; } st_atime, st_mtime, st_ctime;
+ s32 st_blksize;
+ long long st_blocks;
+ char st_fstype[16];
+ s32 st_pad4[8];
+ } ks;
+
+ if (!sysv_valid_dev(stat->dev) || !sysv_valid_dev(stat->rdev))
+ return -EOVERFLOW;
+
+ ks.st_dev = sysv_encode_dev(stat->dev);
+ ks.st_pad1[0] = ks.st_pad1[1] = ks.st_pad1[2] = 0;
+ ks.st_ino = (unsigned long long) stat->ino;
+ ks.st_mode = (u32) stat->mode;
+ ks.st_nlink = (u32) stat->nlink;
+ ks.st_uid = (s32) stat->uid;
+ ks.st_gid = (s32) stat->gid;
+ ks.st_rdev = sysv_encode_dev (stat->rdev);
+ ks.st_pad2[0] = ks.st_pad2[1] = 0;
+ ks.st_size = (long long) stat->size;
+ ks.st_pad3 = 0;
+
+ /* XXX hackety hack... */
+ ks.st_atime.tv_sec = (s32) stat->atime.tv_sec;
+ ks.st_atime.tv_nsec = stat->atime.tv_nsec;
+ ks.st_mtime.tv_sec = (s32) stat->mtime.tv_sec;
+ ks.st_mtime.tv_nsec = stat->mtime.tv_nsec;
+ ks.st_ctime.tv_sec = (s32) stat->ctime.tv_sec;
+ ks.st_ctime.tv_nsec = stat->ctime.tv_nsec;
+
+ ks.st_blksize = (s32) stat->blksize;
+ ks.st_blocks = (long long) stat->blocks;
+ memset(ks.st_fstype, 0, 16);
+ ks.st_pad4[0] = ks.st_pad4[1] = ks.st_pad4[2] = ks.st_pad4[3] = 0;
+ ks.st_pad4[4] = ks.st_pad4[5] = ks.st_pad4[6] = ks.st_pad4[7] = 0;
+
+ /* Now write it all back. */
+ return copy_to_user(ubuf, &ks, sizeof(ks)) ? -EFAULT : 0;
+}
+
+asmlinkage int irix_xstat(int version, char *filename, struct stat *statbuf)
+{
+ int retval;
+ struct kstat stat;
+
+#ifdef DEBUG_XSTAT
+ printk("[%s:%d] Wheee.. irix_xstat(%d,%s,%p) ",
+ current->comm, current->pid, version, filename, statbuf);
+#endif
+
+ retval = vfs_stat(filename, &stat);
+ if (!retval) {
+ switch(version) {
+ case 2:
+ retval = irix_xstat32_xlate(&stat, statbuf);
+ break;
+ case 3:
+ retval = irix_xstat64_xlate(&stat, statbuf);
+ break;
+ default:
+ retval = -EINVAL;
+ }
+ }
+ return retval;
+}
+
+asmlinkage int irix_lxstat(int version, char *filename, struct stat *statbuf)
+{
+ int error;
+ struct kstat stat;
+
+#ifdef DEBUG_XSTAT
+ printk("[%s:%d] Wheee.. irix_lxstat(%d,%s,%p) ",
+ current->comm, current->pid, version, filename, statbuf);
+#endif
+
+ error = vfs_lstat(filename, &stat);
+
+ if (!error) {
+ switch (version) {
+ case 2:
+ error = irix_xstat32_xlate(&stat, statbuf);
+ break;
+ case 3:
+ error = irix_xstat64_xlate(&stat, statbuf);
+ break;
+ default:
+ error = -EINVAL;
+ }
+ }
+ return error;
+}
+
+asmlinkage int irix_fxstat(int version, int fd, struct stat *statbuf)
+{
+ int error;
+ struct kstat stat;
+
+#ifdef DEBUG_XSTAT
+ printk("[%s:%d] Wheee.. irix_fxstat(%d,%d,%p) ",
+ current->comm, current->pid, version, fd, statbuf);
+#endif
+
+ error = vfs_fstat(fd, &stat);
+ if (!error) {
+ switch (version) {
+ case 2:
+ error = irix_xstat32_xlate(&stat, statbuf);
+ break;
+ case 3:
+ error = irix_xstat64_xlate(&stat, statbuf);
+ break;
+ default:
+ error = -EINVAL;
+ }
+ }
+ return error;
+}
+
+asmlinkage int irix_xmknod(int ver, char *filename, int mode, unsigned dev)
+{
+ int retval;
+ printk("[%s:%d] Wheee.. irix_xmknod(%d,%s,%x,%x)\n",
+ current->comm, current->pid, ver, filename, mode, dev);
+
+ switch(ver) {
+ case 2:
+ /* shouldn't we convert here as well as on stat()? */
+ retval = sys_mknod(filename, mode, dev);
+ break;
+
+ default:
+ retval = -EINVAL;
+ break;
+ };
+
+ return retval;
+}
+
+asmlinkage int irix_swapctl(int cmd, char *arg)
+{
+ printk("[%s:%d] Wheee.. irix_swapctl(%d,%p)\n",
+ current->comm, current->pid, cmd, arg);
+
+ return -EINVAL;
+}
+
+struct irix_statvfs {
+ u32 f_bsize; u32 f_frsize; u32 f_blocks;
+ u32 f_bfree; u32 f_bavail; u32 f_files; u32 f_ffree; u32 f_favail;
+ u32 f_fsid; char f_basetype[16];
+ u32 f_flag; u32 f_namemax;
+ char f_fstr[32]; u32 f_filler[16];
+};
+
+asmlinkage int irix_statvfs(char *fname, struct irix_statvfs *buf)
+{
+ struct nameidata nd;
+ struct kstatfs kbuf;
+ int error, i;
+
+ printk("[%s:%d] Wheee.. irix_statvfs(%s,%p)\n",
+ current->comm, current->pid, fname, buf);
+ if (!access_ok(VERIFY_WRITE, buf, sizeof(struct irix_statvfs))) {
+ error = -EFAULT;
+ goto out;
+ }
+ error = user_path_walk(fname, &nd);
+ if (error)
+ goto out;
+ error = vfs_statfs(nd.dentry->d_inode->i_sb, &kbuf);
+ if (error)
+ goto dput_and_out;
+
+ __put_user(kbuf.f_bsize, &buf->f_bsize);
+ __put_user(kbuf.f_frsize, &buf->f_frsize);
+ __put_user(kbuf.f_blocks, &buf->f_blocks);
+ __put_user(kbuf.f_bfree, &buf->f_bfree);
+ __put_user(kbuf.f_bfree, &buf->f_bavail); /* XXX hackety hack... */
+ __put_user(kbuf.f_files, &buf->f_files);
+ __put_user(kbuf.f_ffree, &buf->f_ffree);
+ __put_user(kbuf.f_ffree, &buf->f_favail); /* XXX hackety hack... */
+#ifdef __MIPSEB__
+ __put_user(kbuf.f_fsid.val[1], &buf->f_fsid);
+#else
+ __put_user(kbuf.f_fsid.val[0], &buf->f_fsid);
+#endif
+ for (i = 0; i < 16; i++)
+ __put_user(0, &buf->f_basetype[i]);
+ __put_user(0, &buf->f_flag);
+ __put_user(kbuf.f_namelen, &buf->f_namemax);
+ for (i = 0; i < 32; i++)
+ __put_user(0, &buf->f_fstr[i]);
+
+ error = 0;
+
+dput_and_out:
+ path_release(&nd);
+out:
+ return error;
+}
+
+asmlinkage int irix_fstatvfs(int fd, struct irix_statvfs *buf)
+{
+ struct kstatfs kbuf;
+ struct file *file;
+ int error, i;
+
+ printk("[%s:%d] Wheee.. irix_fstatvfs(%d,%p)\n",
+ current->comm, current->pid, fd, buf);
+
+ if (!access_ok(VERIFY_WRITE, buf, sizeof(struct irix_statvfs))) {
+ error = -EFAULT;
+ goto out;
+ }
+ if (!(file = fget(fd))) {
+ error = -EBADF;
+ goto out;
+ }
+ error = vfs_statfs(file->f_dentry->d_inode->i_sb, &kbuf);
+ if (error)
+ goto out_f;
+
+ __put_user(kbuf.f_bsize, &buf->f_bsize);
+ __put_user(kbuf.f_frsize, &buf->f_frsize);
+ __put_user(kbuf.f_blocks, &buf->f_blocks);
+ __put_user(kbuf.f_bfree, &buf->f_bfree);
+ __put_user(kbuf.f_bfree, &buf->f_bavail); /* XXX hackety hack... */
+ __put_user(kbuf.f_files, &buf->f_files);
+ __put_user(kbuf.f_ffree, &buf->f_ffree);
+ __put_user(kbuf.f_ffree, &buf->f_favail); /* XXX hackety hack... */
+#ifdef __MIPSEB__
+ __put_user(kbuf.f_fsid.val[1], &buf->f_fsid);
+#else
+ __put_user(kbuf.f_fsid.val[0], &buf->f_fsid);
+#endif
+ for(i = 0; i < 16; i++)
+ __put_user(0, &buf->f_basetype[i]);
+ __put_user(0, &buf->f_flag);
+ __put_user(kbuf.f_namelen, &buf->f_namemax);
+ __clear_user(&buf->f_fstr, sizeof(buf->f_fstr));
+
+out_f:
+ fput(file);
+out:
+ return error;
+}
+
+asmlinkage int irix_priocntl(struct pt_regs *regs)
+{
+ printk("[%s:%d] Wheee.. irix_priocntl()\n",
+ current->comm, current->pid);
+
+ return -EINVAL;
+}
+
+asmlinkage int irix_sigqueue(int pid, int sig, int code, int val)
+{
+ printk("[%s:%d] Wheee.. irix_sigqueue(%d,%d,%d,%d)\n",
+ current->comm, current->pid, pid, sig, code, val);
+
+ return -EINVAL;
+}
+
+asmlinkage int irix_truncate64(char *name, int pad, int size1, int size2)
+{
+ int retval;
+
+ if (size1) {
+ retval = -EINVAL;
+ goto out;
+ }
+ retval = sys_truncate(name, size2);
+
+out:
+ return retval;
+}
+
+asmlinkage int irix_ftruncate64(int fd, int pad, int size1, int size2)
+{
+ int retval;
+
+ if (size1) {
+ retval = -EINVAL;
+ goto out;
+ }
+ retval = sys_ftruncate(fd, size2);
+
+out:
+ return retval;
+}
+
+asmlinkage int irix_mmap64(struct pt_regs *regs)
+{
+ int len, prot, flags, fd, off1, off2, error, base = 0;
+ unsigned long addr, pgoff, *sp;
+ struct file *file = NULL;
+
+ if (regs->regs[2] == 1000)
+ base = 1;
+ sp = (unsigned long *) (regs->regs[29] + 16);
+ addr = regs->regs[base + 4];
+ len = regs->regs[base + 5];
+ prot = regs->regs[base + 6];
+ if (!base) {
+ flags = regs->regs[base + 7];
+ if (!access_ok(VERIFY_READ, sp, (4 * sizeof(unsigned long)))) {
+ error = -EFAULT;
+ goto out;
+ }
+ fd = sp[0];
+ __get_user(off1, &sp[1]);
+ __get_user(off2, &sp[2]);
+ } else {
+ if (!access_ok(VERIFY_READ, sp, (5 * sizeof(unsigned long)))) {
+ error = -EFAULT;
+ goto out;
+ }
+ __get_user(flags, &sp[0]);
+ __get_user(fd, &sp[1]);
+ __get_user(off1, &sp[2]);
+ __get_user(off2, &sp[3]);
+ }
+
+ if (off1 & PAGE_MASK) {
+ error = -EOVERFLOW;
+ goto out;
+ }
+
+ pgoff = (off1 << (32 - PAGE_SHIFT)) | (off2 >> PAGE_SHIFT);
+
+ if (!(flags & MAP_ANONYMOUS)) {
+ if (!(file = fget(fd))) {
+ error = -EBADF;
+ goto out;
+ }
+
+ /* Ok, bad taste hack follows, try to think in something else
+ when reading this */
+ if (flags & IRIX_MAP_AUTOGROW) {
+ unsigned long old_pos;
+ long max_size = off2 + len;
+
+ if (max_size > file->f_dentry->d_inode->i_size) {
+ old_pos = sys_lseek (fd, max_size - 1, 0);
+ sys_write (fd, "", 1);
+ sys_lseek (fd, old_pos, 0);
+ }
+ }
+ }
+
+ flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+
+ down_write(¤t->mm->mmap_sem);
+ error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
+ up_write(¤t->mm->mmap_sem);
+
+ if (file)
+ fput(file);
+
+out:
+ return error;
+}
+
+asmlinkage int irix_dmi(struct pt_regs *regs)
+{
+ printk("[%s:%d] Wheee.. irix_dmi()\n",
+ current->comm, current->pid);
+
+ return -EINVAL;
+}
+
+asmlinkage int irix_pread(int fd, char *buf, int cnt, int off64,
+ int off1, int off2)
+{
+ printk("[%s:%d] Wheee.. irix_pread(%d,%p,%d,%d,%d,%d)\n",
+ current->comm, current->pid, fd, buf, cnt, off64, off1, off2);
+
+ return -EINVAL;
+}
+
+asmlinkage int irix_pwrite(int fd, char *buf, int cnt, int off64,
+ int off1, int off2)
+{
+ printk("[%s:%d] Wheee.. irix_pwrite(%d,%p,%d,%d,%d,%d)\n",
+ current->comm, current->pid, fd, buf, cnt, off64, off1, off2);
+
+ return -EINVAL;
+}
+
+asmlinkage int irix_sgifastpath(int cmd, unsigned long arg0, unsigned long arg1,
+ unsigned long arg2, unsigned long arg3,
+ unsigned long arg4, unsigned long arg5)
+{
+ printk("[%s:%d] Wheee.. irix_fastpath(%d,%08lx,%08lx,%08lx,%08lx,"
+ "%08lx,%08lx)\n",
+ current->comm, current->pid, cmd, arg0, arg1, arg2,
+ arg3, arg4, arg5);
+
+ return -EINVAL;
+}
+
+struct irix_statvfs64 {
+ u32 f_bsize; u32 f_frsize;
+ u64 f_blocks; u64 f_bfree; u64 f_bavail;
+ u64 f_files; u64 f_ffree; u64 f_favail;
+ u32 f_fsid;
+ char f_basetype[16];
+ u32 f_flag; u32 f_namemax;
+ char f_fstr[32];
+ u32 f_filler[16];
+};
+
+asmlinkage int irix_statvfs64(char *fname, struct irix_statvfs64 *buf)
+{
+ struct nameidata nd;
+ struct kstatfs kbuf;
+ int error, i;
+
+ printk("[%s:%d] Wheee.. irix_statvfs64(%s,%p)\n",
+ current->comm, current->pid, fname, buf);
+ if (!access_ok(VERIFY_WRITE, buf, sizeof(struct irix_statvfs64))) {
+ error = -EFAULT;
+ goto out;
+ }
+ error = user_path_walk(fname, &nd);
+ if (error)
+ goto out;
+ error = vfs_statfs(nd.dentry->d_inode->i_sb, &kbuf);
+ if (error)
+ goto dput_and_out;
+
+ __put_user(kbuf.f_bsize, &buf->f_bsize);
+ __put_user(kbuf.f_frsize, &buf->f_frsize);
+ __put_user(kbuf.f_blocks, &buf->f_blocks);
+ __put_user(kbuf.f_bfree, &buf->f_bfree);
+ __put_user(kbuf.f_bfree, &buf->f_bavail); /* XXX hackety hack... */
+ __put_user(kbuf.f_files, &buf->f_files);
+ __put_user(kbuf.f_ffree, &buf->f_ffree);
+ __put_user(kbuf.f_ffree, &buf->f_favail); /* XXX hackety hack... */
+#ifdef __MIPSEB__
+ __put_user(kbuf.f_fsid.val[1], &buf->f_fsid);
+#else
+ __put_user(kbuf.f_fsid.val[0], &buf->f_fsid);
+#endif
+ for(i = 0; i < 16; i++)
+ __put_user(0, &buf->f_basetype[i]);
+ __put_user(0, &buf->f_flag);
+ __put_user(kbuf.f_namelen, &buf->f_namemax);
+ for(i = 0; i < 32; i++)
+ __put_user(0, &buf->f_fstr[i]);
+
+ error = 0;
+
+dput_and_out:
+ path_release(&nd);
+out:
+ return error;
+}
+
+asmlinkage int irix_fstatvfs64(int fd, struct irix_statvfs *buf)
+{
+ struct kstatfs kbuf;
+ struct file *file;
+ int error, i;
+
+ printk("[%s:%d] Wheee.. irix_fstatvfs64(%d,%p)\n",
+ current->comm, current->pid, fd, buf);
+
+ if (!access_ok(VERIFY_WRITE, buf, sizeof(struct irix_statvfs))) {
+ error = -EFAULT;
+ goto out;
+ }
+ if (!(file = fget(fd))) {
+ error = -EBADF;
+ goto out;
+ }
+ error = vfs_statfs(file->f_dentry->d_inode->i_sb, &kbuf);
+ if (error)
+ goto out_f;
+
+ __put_user(kbuf.f_bsize, &buf->f_bsize);
+ __put_user(kbuf.f_frsize, &buf->f_frsize);
+ __put_user(kbuf.f_blocks, &buf->f_blocks);
+ __put_user(kbuf.f_bfree, &buf->f_bfree);
+ __put_user(kbuf.f_bfree, &buf->f_bavail); /* XXX hackety hack... */
+ __put_user(kbuf.f_files, &buf->f_files);
+ __put_user(kbuf.f_ffree, &buf->f_ffree);
+ __put_user(kbuf.f_ffree, &buf->f_favail); /* XXX hackety hack... */
+#ifdef __MIPSEB__
+ __put_user(kbuf.f_fsid.val[1], &buf->f_fsid);
+#else
+ __put_user(kbuf.f_fsid.val[0], &buf->f_fsid);
+#endif
+ for(i = 0; i < 16; i++)
+ __put_user(0, &buf->f_basetype[i]);
+ __put_user(0, &buf->f_flag);
+ __put_user(kbuf.f_namelen, &buf->f_namemax);
+ __clear_user(buf->f_fstr, sizeof(buf->f_fstr[i]));
+
+out_f:
+ fput(file);
+out:
+ return error;
+}
+
+asmlinkage int irix_getmountid(char *fname, unsigned long *midbuf)
+{
+ int err = 0;
+
+ printk("[%s:%d] irix_getmountid(%s, %p)\n",
+ current->comm, current->pid, fname, midbuf);
+ if (!access_ok(VERIFY_WRITE, midbuf, (sizeof(unsigned long) * 4)))
+ return -EFAULT;
+
+ /*
+ * The idea with this system call is that when trying to determine
+ * 'pwd' and it's a toss-up for some reason, userland can use the
+ * fsid of the filesystem to try and make the right decision, but
+ * we don't have this so for now. XXX
+ */
+ err |= __put_user(0, &midbuf[0]);
+ err |= __put_user(0, &midbuf[1]);
+ err |= __put_user(0, &midbuf[2]);
+ err |= __put_user(0, &midbuf[3]);
+
+ return err;
+}
+
+asmlinkage int irix_nsproc(unsigned long entry, unsigned long mask,
+ unsigned long arg, unsigned long sp, int slen)
+{
+ printk("[%s:%d] Wheee.. irix_nsproc(%08lx,%08lx,%08lx,%08lx,%d)\n",
+ current->comm, current->pid, entry, mask, arg, sp, slen);
+
+ return -EINVAL;
+}
+
+#undef DEBUG_GETDENTS
+
+struct irix_dirent32 {
+ u32 d_ino;
+ u32 d_off;
+ unsigned short d_reclen;
+ char d_name[1];
+};
+
+struct irix_dirent32_callback {
+ struct irix_dirent32 *current_dir;
+ struct irix_dirent32 *previous;
+ int count;
+ int error;
+};
+
+#define NAME_OFFSET32(de) ((int) ((de)->d_name - (char *) (de)))
+#define ROUND_UP32(x) (((x)+sizeof(u32)-1) & ~(sizeof(u32)-1))
+
+static int irix_filldir32(void *__buf, const char *name, int namlen,
+ loff_t offset, ino_t ino, unsigned int d_type)
+{
+ struct irix_dirent32 *dirent;
+ struct irix_dirent32_callback *buf =
+ (struct irix_dirent32_callback *)__buf;
+ unsigned short reclen = ROUND_UP32(NAME_OFFSET32(dirent) + namlen + 1);
+
+#ifdef DEBUG_GETDENTS
+ printk("\nirix_filldir32[reclen<%d>namlen<%d>count<%d>]",
+ reclen, namlen, buf->count);
+#endif
+ buf->error = -EINVAL; /* only used if we fail.. */
+ if (reclen > buf->count)
+ return -EINVAL;
+ dirent = buf->previous;
+ if (dirent)
+ __put_user(offset, &dirent->d_off);
+ dirent = buf->current_dir;
+ buf->previous = dirent;
+ __put_user(ino, &dirent->d_ino);
+ __put_user(reclen, &dirent->d_reclen);
+ copy_to_user(dirent->d_name, name, namlen);
+ __put_user(0, &dirent->d_name[namlen]);
+ ((char *) dirent) += reclen;
+ buf->current_dir = dirent;
+ buf->count -= reclen;
+
+ return 0;
+}
+
+asmlinkage int irix_ngetdents(unsigned int fd, void * dirent,
+ unsigned int count, int *eob)
+{
+ struct file *file;
+ struct irix_dirent32 *lastdirent;
+ struct irix_dirent32_callback buf;
+ int error;
+
+#ifdef DEBUG_GETDENTS
+ printk("[%s:%d] ngetdents(%d, %p, %d, %p) ", current->comm,
+ current->pid, fd, dirent, count, eob);
+#endif
+ error = -EBADF;
+ file = fget(fd);
+ if (!file)
+ goto out;
+
+ buf.current_dir = (struct irix_dirent32 *) dirent;
+ buf.previous = NULL;
+ buf.count = count;
+ buf.error = 0;
+
+ error = vfs_readdir(file, irix_filldir32, &buf);
+ if (error < 0)
+ goto out_putf;
+
+ error = buf.error;
+ lastdirent = buf.previous;
+ if (lastdirent) {
+ put_user(file->f_pos, &lastdirent->d_off);
+ error = count - buf.count;
+ }
+
+ if (put_user(0, eob) < 0) {
+ error = -EFAULT;
+ goto out_putf;
+ }
+
+#ifdef DEBUG_GETDENTS
+ printk("eob=%d returning %d\n", *eob, count - buf.count);
+#endif
+ error = count - buf.count;
+
+out_putf:
+ fput(file);
+out:
+ return error;
+}
+
+struct irix_dirent64 {
+ u64 d_ino;
+ u64 d_off;
+ unsigned short d_reclen;
+ char d_name[1];
+};
+
+struct irix_dirent64_callback {
+ struct irix_dirent64 *curr;
+ struct irix_dirent64 *previous;
+ int count;
+ int error;
+};
+
+#define NAME_OFFSET64(de) ((int) ((de)->d_name - (char *) (de)))
+#define ROUND_UP64(x) (((x)+sizeof(u64)-1) & ~(sizeof(u64)-1))
+
+static int irix_filldir64(void * __buf, const char * name, int namlen,
+ loff_t offset, ino_t ino, unsigned int d_type)
+{
+ struct irix_dirent64 *dirent;
+ struct irix_dirent64_callback * buf =
+ (struct irix_dirent64_callback *) __buf;
+ unsigned short reclen = ROUND_UP64(NAME_OFFSET64(dirent) + namlen + 1);
+
+ buf->error = -EINVAL; /* only used if we fail.. */
+ if (reclen > buf->count)
+ return -EINVAL;
+ dirent = buf->previous;
+ if (dirent)
+ __put_user(offset, &dirent->d_off);
+ dirent = buf->curr;
+ buf->previous = dirent;
+ __put_user(ino, &dirent->d_ino);
+ __put_user(reclen, &dirent->d_reclen);
+ __copy_to_user(dirent->d_name, name, namlen);
+ __put_user(0, &dirent->d_name[namlen]);
+ ((char *) dirent) += reclen;
+ buf->curr = dirent;
+ buf->count -= reclen;
+
+ return 0;
+}
+
+asmlinkage int irix_getdents64(int fd, void *dirent, int cnt)
+{
+ struct file *file;
+ struct irix_dirent64 *lastdirent;
+ struct irix_dirent64_callback buf;
+ int error;
+
+#ifdef DEBUG_GETDENTS
+ printk("[%s:%d] getdents64(%d, %p, %d) ", current->comm,
+ current->pid, fd, dirent, cnt);
+#endif
+ error = -EBADF;
+ if (!(file = fget(fd)))
+ goto out;
+
+ error = -EFAULT;
+ if (!access_ok(VERIFY_WRITE, dirent, cnt))
+ goto out_f;
+
+ error = -EINVAL;
+ if (cnt < (sizeof(struct irix_dirent64) + 255))
+ goto out_f;
+
+ buf.curr = (struct irix_dirent64 *) dirent;
+ buf.previous = NULL;
+ buf.count = cnt;
+ buf.error = 0;
+ error = vfs_readdir(file, irix_filldir64, &buf);
+ if (error < 0)
+ goto out_f;
+ lastdirent = buf.previous;
+ if (!lastdirent) {
+ error = buf.error;
+ goto out_f;
+ }
+ lastdirent->d_off = (u64) file->f_pos;
+#ifdef DEBUG_GETDENTS
+ printk("returning %d\n", cnt - buf.count);
+#endif
+ error = cnt - buf.count;
+
+out_f:
+ fput(file);
+out:
+ return error;
+}
+
+asmlinkage int irix_ngetdents64(int fd, void *dirent, int cnt, int *eob)
+{
+ struct file *file;
+ struct irix_dirent64 *lastdirent;
+ struct irix_dirent64_callback buf;
+ int error;
+
+#ifdef DEBUG_GETDENTS
+ printk("[%s:%d] ngetdents64(%d, %p, %d) ", current->comm,
+ current->pid, fd, dirent, cnt);
+#endif
+ error = -EBADF;
+ if (!(file = fget(fd)))
+ goto out;
+
+ error = -EFAULT;
+ if (!access_ok(VERIFY_WRITE, dirent, cnt) ||
+ !access_ok(VERIFY_WRITE, eob, sizeof(*eob)))
+ goto out_f;
+
+ error = -EINVAL;
+ if (cnt < (sizeof(struct irix_dirent64) + 255))
+ goto out_f;
+
+ *eob = 0;
+ buf.curr = (struct irix_dirent64 *) dirent;
+ buf.previous = NULL;
+ buf.count = cnt;
+ buf.error = 0;
+ error = vfs_readdir(file, irix_filldir64, &buf);
+ if (error < 0)
+ goto out_f;
+ lastdirent = buf.previous;
+ if (!lastdirent) {
+ error = buf.error;
+ goto out_f;
+ }
+ lastdirent->d_off = (u64) file->f_pos;
+#ifdef DEBUG_GETDENTS
+ printk("eob=%d returning %d\n", *eob, cnt - buf.count);
+#endif
+ error = cnt - buf.count;
+
+out_f:
+ fput(file);
+out:
+ return error;
+}
+
+asmlinkage int irix_uadmin(unsigned long op, unsigned long func, unsigned long arg)
+{
+ int retval;
+
+ switch (op) {
+ case 1:
+ /* Reboot */
+ printk("[%s:%d] irix_uadmin: Wants to reboot...\n",
+ current->comm, current->pid);
+ retval = -EINVAL;
+ goto out;
+
+ case 2:
+ /* Shutdown */
+ printk("[%s:%d] irix_uadmin: Wants to shutdown...\n",
+ current->comm, current->pid);
+ retval = -EINVAL;
+ goto out;
+
+ case 4:
+ /* Remount-root */
+ printk("[%s:%d] irix_uadmin: Wants to remount root...\n",
+ current->comm, current->pid);
+ retval = -EINVAL;
+ goto out;
+
+ case 8:
+ /* Kill all tasks. */
+ printk("[%s:%d] irix_uadmin: Wants to kill all tasks...\n",
+ current->comm, current->pid);
+ retval = -EINVAL;
+ goto out;
+
+ case 256:
+ /* Set magic mushrooms... */
+ printk("[%s:%d] irix_uadmin: Wants to set magic mushroom[%d]...\n",
+ current->comm, current->pid, (int) func);
+ retval = -EINVAL;
+ goto out;
+
+ default:
+ printk("[%s:%d] irix_uadmin: Unknown operation [%d]...\n",
+ current->comm, current->pid, (int) op);
+ retval = -EINVAL;
+ goto out;
+ };
+
+out:
+ return retval;
+}
+
+asmlinkage int irix_utssys(char *inbuf, int arg, int type, char *outbuf)
+{
+ int retval;
+
+ switch(type) {
+ case 0:
+ /* uname() */
+ retval = irix_uname((struct iuname *)inbuf);
+ goto out;
+
+ case 2:
+ /* ustat() */
+ printk("[%s:%d] irix_utssys: Wants to do ustat()\n",
+ current->comm, current->pid);
+ retval = -EINVAL;
+ goto out;
+
+ case 3:
+ /* fusers() */
+ printk("[%s:%d] irix_utssys: Wants to do fusers()\n",
+ current->comm, current->pid);
+ retval = -EINVAL;
+ goto out;
+
+ default:
+ printk("[%s:%d] irix_utssys: Wants to do unknown type[%d]\n",
+ current->comm, current->pid, (int) type);
+ retval = -EINVAL;
+ goto out;
+ }
+
+out:
+ return retval;
+}
+
+#undef DEBUG_FCNTL
+
+#define IRIX_F_ALLOCSP 10
+
+asmlinkage int irix_fcntl(int fd, int cmd, int arg)
+{
+ int retval;
+
+#ifdef DEBUG_FCNTL
+ printk("[%s:%d] irix_fcntl(%d, %d, %d) ", current->comm,
+ current->pid, fd, cmd, arg);
+#endif
+ if (cmd == IRIX_F_ALLOCSP){
+ return 0;
+ }
+ retval = sys_fcntl(fd, cmd, arg);
+#ifdef DEBUG_FCNTL
+ printk("%d\n", retval);
+#endif
+ return retval;
+}
+
+asmlinkage int irix_ulimit(int cmd, int arg)
+{
+ int retval;
+
+ switch(cmd) {
+ case 1:
+ printk("[%s:%d] irix_ulimit: Wants to get file size limit.\n",
+ current->comm, current->pid);
+ retval = -EINVAL;
+ goto out;
+
+ case 2:
+ printk("[%s:%d] irix_ulimit: Wants to set file size limit.\n",
+ current->comm, current->pid);
+ retval = -EINVAL;
+ goto out;
+
+ case 3:
+ printk("[%s:%d] irix_ulimit: Wants to get brk limit.\n",
+ current->comm, current->pid);
+ retval = -EINVAL;
+ goto out;
+
+ case 4:
+#if 0
+ printk("[%s:%d] irix_ulimit: Wants to get fd limit.\n",
+ current->comm, current->pid);
+ retval = -EINVAL;
+ goto out;
+#endif
+ retval = current->signal->rlim[RLIMIT_NOFILE].rlim_cur;
+ goto out;
+
+ case 5:
+ printk("[%s:%d] irix_ulimit: Wants to get txt offset.\n",
+ current->comm, current->pid);
+ retval = -EINVAL;
+ goto out;
+
+ default:
+ printk("[%s:%d] irix_ulimit: Unknown command [%d].\n",
+ current->comm, current->pid, cmd);
+ retval = -EINVAL;
+ goto out;
+ }
+out:
+ return retval;
+}
+
+asmlinkage int irix_unimp(struct pt_regs *regs)
+{
+ printk("irix_unimp [%s:%d] v0=%d v1=%d a0=%08lx a1=%08lx a2=%08lx "
+ "a3=%08lx\n", current->comm, current->pid,
+ (int) regs->regs[2], (int) regs->regs[3],
+ regs->regs[4], regs->regs[5], regs->regs[6], regs->regs[7]);
+
+ return -ENOSYS;
+}
diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c
new file mode 100644
index 0000000..648c822
--- /dev/null
+++ b/arch/mips/kernel/time.c
@@ -0,0 +1,755 @@
+/*
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
+ * Copyright (c) 2003, 2004 Maciej W. Rozycki
+ *
+ * Common time service routines for MIPS machines. See
+ * Documentation/mips/time.README.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/param.h>
+#include <linux/time.h>
+#include <linux/timex.h>
+#include <linux/smp.h>
+#include <linux/kernel_stat.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+
+#include <asm/bootinfo.h>
+#include <asm/compiler.h>
+#include <asm/cpu.h>
+#include <asm/cpu-features.h>
+#include <asm/div64.h>
+#include <asm/sections.h>
+#include <asm/time.h>
+
+/*
+ * The integer part of the number of usecs per jiffy is taken from tick,
+ * but the fractional part is not recorded, so we calculate it using the
+ * initial value of HZ. This aids systems where tick isn't really an
+ * integer (e.g. for HZ = 128).
+ */
+#define USECS_PER_JIFFY TICK_SIZE
+#define USECS_PER_JIFFY_FRAC ((unsigned long)(u32)((1000000ULL << 32) / HZ))
+
+#define TICK_SIZE (tick_nsec / 1000)
+
+u64 jiffies_64 = INITIAL_JIFFIES;
+
+EXPORT_SYMBOL(jiffies_64);
+
+/*
+ * forward reference
+ */
+extern volatile unsigned long wall_jiffies;
+
+DEFINE_SPINLOCK(rtc_lock);
+
+/*
+ * By default we provide the null RTC ops
+ */
+static unsigned long null_rtc_get_time(void)
+{
+ return mktime(2000, 1, 1, 0, 0, 0);
+}
+
+static int null_rtc_set_time(unsigned long sec)
+{
+ return 0;
+}
+
+unsigned long (*rtc_get_time)(void) = null_rtc_get_time;
+int (*rtc_set_time)(unsigned long) = null_rtc_set_time;
+int (*rtc_set_mmss)(unsigned long);
+
+
+/* usecs per counter cycle, shifted to left by 32 bits */
+static unsigned int sll32_usecs_per_cycle;
+
+/* how many counter cycles in a jiffy */
+static unsigned long cycles_per_jiffy;
+
+/* Cycle counter value at the previous timer interrupt.. */
+static unsigned int timerhi, timerlo;
+
+/* expirelo is the count value for next CPU timer interrupt */
+static unsigned int expirelo;
+
+
+/*
+ * Null timer ack for systems not needing one (e.g. i8254).
+ */
+static void null_timer_ack(void) { /* nothing */ }
+
+/*
+ * Null high precision timer functions for systems lacking one.
+ */
+static unsigned int null_hpt_read(void)
+{
+ return 0;
+}
+
+static void null_hpt_init(unsigned int count) { /* nothing */ }
+
+
+/*
+ * Timer ack for an R4k-compatible timer of a known frequency.
+ */
+static void c0_timer_ack(void)
+{
+ unsigned int count;
+
+ /* Ack this timer interrupt and set the next one. */
+ expirelo += cycles_per_jiffy;
+ write_c0_compare(expirelo);
+
+ /* Check to see if we have missed any timer interrupts. */
+ count = read_c0_count();
+ if ((count - expirelo) < 0x7fffffff) {
+ /* missed_timer_count++; */
+ expirelo = count + cycles_per_jiffy;
+ write_c0_compare(expirelo);
+ }
+}
+
+/*
+ * High precision timer functions for a R4k-compatible timer.
+ */
+static unsigned int c0_hpt_read(void)
+{
+ return read_c0_count();
+}
+
+/* For use solely as a high precision timer. */
+static void c0_hpt_init(unsigned int count)
+{
+ write_c0_count(read_c0_count() - count);
+}
+
+/* For use both as a high precision timer and an interrupt source. */
+static void c0_hpt_timer_init(unsigned int count)
+{
+ count = read_c0_count() - count;
+ expirelo = (count / cycles_per_jiffy + 1) * cycles_per_jiffy;
+ write_c0_count(expirelo - cycles_per_jiffy);
+ write_c0_compare(expirelo);
+ write_c0_count(count);
+}
+
+int (*mips_timer_state)(void);
+void (*mips_timer_ack)(void);
+unsigned int (*mips_hpt_read)(void);
+void (*mips_hpt_init)(unsigned int);
+
+
+/*
+ * This version of gettimeofday has microsecond resolution and better than
+ * microsecond precision on fast machines with cycle counter.
+ */
+void do_gettimeofday(struct timeval *tv)
+{
+ unsigned long seq;
+ unsigned long lost;
+ unsigned long usec, sec;
+ unsigned long max_ntp_tick = tick_usec - tickadj;
+
+ do {
+ seq = read_seqbegin(&xtime_lock);
+
+ usec = do_gettimeoffset();
+
+ lost = jiffies - wall_jiffies;
+
+ /*
+ * If time_adjust is negative then NTP is slowing the clock
+ * so make sure not to go into next possible interval.
+ * Better to lose some accuracy than have time go backwards..
+ */
+ if (unlikely(time_adjust < 0)) {
+ usec = min(usec, max_ntp_tick);
+
+ if (lost)
+ usec += lost * max_ntp_tick;
+ } else if (unlikely(lost))
+ usec += lost * tick_usec;
+
+ sec = xtime.tv_sec;
+ usec += (xtime.tv_nsec / 1000);
+
+ } while (read_seqretry(&xtime_lock, seq));
+
+ while (usec >= 1000000) {
+ usec -= 1000000;
+ sec++;
+ }
+
+ tv->tv_sec = sec;
+ tv->tv_usec = usec;
+}
+
+EXPORT_SYMBOL(do_gettimeofday);
+
+int do_settimeofday(struct timespec *tv)
+{
+ time_t wtm_sec, sec = tv->tv_sec;
+ long wtm_nsec, nsec = tv->tv_nsec;
+
+ if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
+ return -EINVAL;
+
+ write_seqlock_irq(&xtime_lock);
+
+ /*
+ * This is revolting. We need to set "xtime" correctly. However,
+ * the value in this location is the value at the most recent update
+ * of wall time. Discover what correction gettimeofday() would have
+ * made, and then undo it!
+ */
+ nsec -= do_gettimeoffset() * NSEC_PER_USEC;
+ nsec -= (jiffies - wall_jiffies) * tick_nsec;
+
+ wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
+ wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
+
+ set_normalized_timespec(&xtime, sec, nsec);
+ set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
+
+ time_adjust = 0; /* stop active adjtime() */
+ time_status |= STA_UNSYNC;
+ time_maxerror = NTP_PHASE_LIMIT;
+ time_esterror = NTP_PHASE_LIMIT;
+
+ write_sequnlock_irq(&xtime_lock);
+ clock_was_set();
+ return 0;
+}
+
+EXPORT_SYMBOL(do_settimeofday);
+
+/*
+ * Gettimeoffset routines. These routines returns the time duration
+ * since last timer interrupt in usecs.
+ *
+ * If the exact CPU counter frequency is known, use fixed_rate_gettimeoffset.
+ * Otherwise use calibrate_gettimeoffset()
+ *
+ * If the CPU does not have the counter register, you can either supply
+ * your own gettimeoffset() routine, or use null_gettimeoffset(), which
+ * gives the same resolution as HZ.
+ */
+
+static unsigned long null_gettimeoffset(void)
+{
+ return 0;
+}
+
+
+/* The function pointer to one of the gettimeoffset funcs. */
+unsigned long (*do_gettimeoffset)(void) = null_gettimeoffset;
+
+
+static unsigned long fixed_rate_gettimeoffset(void)
+{
+ u32 count;
+ unsigned long res;
+
+ /* Get last timer tick in absolute kernel time */
+ count = mips_hpt_read();
+
+ /* .. relative to previous jiffy (32 bits is enough) */
+ count -= timerlo;
+
+ __asm__("multu %1,%2"
+ : "=h" (res)
+ : "r" (count), "r" (sll32_usecs_per_cycle)
+ : "lo", GCC_REG_ACCUM);
+
+ /*
+ * 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;
+}
+
+
+/*
+ * Cached "1/(clocks per usec) * 2^32" value.
+ * It has to be recalculated once each jiffy.
+ */
+static unsigned long cached_quotient;
+
+/* Last jiffy when calibrate_divXX_gettimeoffset() was called. */
+static unsigned long last_jiffies;
+
+/*
+ * This is moved from dec/time.c:do_ioasic_gettimeoffset() by Maciej.
+ */
+static unsigned long calibrate_div32_gettimeoffset(void)
+{
+ u32 count;
+ unsigned long res, tmp;
+ unsigned long quotient;
+
+ tmp = jiffies;
+
+ quotient = cached_quotient;
+
+ if (last_jiffies != tmp) {
+ last_jiffies = tmp;
+ if (last_jiffies != 0) {
+ unsigned long r0;
+ do_div64_32(r0, timerhi, timerlo, tmp);
+ do_div64_32(quotient, USECS_PER_JIFFY,
+ USECS_PER_JIFFY_FRAC, r0);
+ cached_quotient = quotient;
+ }
+ }
+
+ /* Get last timer tick in absolute kernel time */
+ count = mips_hpt_read();
+
+ /* .. relative to previous jiffy (32 bits is enough) */
+ count -= timerlo;
+
+ __asm__("multu %1,%2"
+ : "=h" (res)
+ : "r" (count), "r" (quotient)
+ : "lo", GCC_REG_ACCUM);
+
+ /*
+ * 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;
+}
+
+static unsigned long calibrate_div64_gettimeoffset(void)
+{
+ u32 count;
+ unsigned long res, tmp;
+ unsigned long quotient;
+
+ tmp = jiffies;
+
+ quotient = cached_quotient;
+
+ if (last_jiffies != tmp) {
+ last_jiffies = tmp;
+ if (last_jiffies) {
+ unsigned long r0;
+ __asm__(".set push\n\t"
+ ".set mips3\n\t"
+ "lwu %0,%3\n\t"
+ "dsll32 %1,%2,0\n\t"
+ "or %1,%1,%0\n\t"
+ "ddivu $0,%1,%4\n\t"
+ "mflo %1\n\t"
+ "dsll32 %0,%5,0\n\t"
+ "or %0,%0,%6\n\t"
+ "ddivu $0,%0,%1\n\t"
+ "mflo %0\n\t"
+ ".set pop"
+ : "=&r" (quotient), "=&r" (r0)
+ : "r" (timerhi), "m" (timerlo),
+ "r" (tmp), "r" (USECS_PER_JIFFY),
+ "r" (USECS_PER_JIFFY_FRAC)
+ : "hi", "lo", GCC_REG_ACCUM);
+ cached_quotient = quotient;
+ }
+ }
+
+ /* Get last timer tick in absolute kernel time */
+ count = mips_hpt_read();
+
+ /* .. relative to previous jiffy (32 bits is enough) */
+ count -= timerlo;
+
+ __asm__("multu %1,%2"
+ : "=h" (res)
+ : "r" (count), "r" (quotient)
+ : "lo", GCC_REG_ACCUM);
+
+ /*
+ * 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;
+}
+
+
+/* last time when xtime and rtc are sync'ed up */
+static long last_rtc_update;
+
+/*
+ * local_timer_interrupt() does profiling and process accounting
+ * on a per-CPU basis.
+ *
+ * In UP mode, it is invoked from the (global) timer_interrupt.
+ *
+ * In SMP mode, it might invoked by per-CPU timer interrupt, or
+ * a broadcasted inter-processor interrupt which itself is triggered
+ * by the global timer interrupt.
+ */
+void local_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ if (current->pid)
+ profile_tick(CPU_PROFILING, regs);
+ update_process_times(user_mode(regs));
+}
+
+/*
+ * High-level timer interrupt service routines. This function
+ * is set as irqaction->handler and is invoked through do_IRQ.
+ */
+irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ unsigned long j;
+ unsigned int count;
+
+ count = mips_hpt_read();
+ mips_timer_ack();
+
+ /* Update timerhi/timerlo for intra-jiffy calibration. */
+ timerhi += count < timerlo; /* Wrap around */
+ timerlo = count;
+
+ /*
+ * call the generic timer interrupt handling
+ */
+ do_timer(regs);
+
+ /*
+ * If we have an externally synchronized Linux clock, then update
+ * CMOS clock accordingly every ~11 minutes. rtc_set_time() has to be
+ * called as close as possible to 500 ms before the new second starts.
+ */
+ write_seqlock(&xtime_lock);
+ if ((time_status & STA_UNSYNC) == 0 &&
+ xtime.tv_sec > last_rtc_update + 660 &&
+ (xtime.tv_nsec / 1000) >= 500000 - ((unsigned) TICK_SIZE) / 2 &&
+ (xtime.tv_nsec / 1000) <= 500000 + ((unsigned) TICK_SIZE) / 2) {
+ if (rtc_set_mmss(xtime.tv_sec) == 0) {
+ last_rtc_update = xtime.tv_sec;
+ } else {
+ /* do it again in 60 s */
+ last_rtc_update = xtime.tv_sec - 600;
+ }
+ }
+ write_sequnlock(&xtime_lock);
+
+ /*
+ * If jiffies has overflown in this timer_interrupt, we must
+ * update the timer[hi]/[lo] to make fast gettimeoffset funcs
+ * quotient calc still valid. -arca
+ *
+ * The first timer interrupt comes late as interrupts are
+ * enabled long after timers are initialized. Therefore the
+ * high precision timer is fast, leading to wrong gettimeoffset()
+ * calculations. We deal with it by setting it based on the
+ * number of its ticks between the second and the third interrupt.
+ * That is still somewhat imprecise, but it's a good estimate.
+ * --macro
+ */
+ j = jiffies;
+ if (j < 4) {
+ static unsigned int prev_count;
+ static int hpt_initialized;
+
+ switch (j) {
+ case 0:
+ timerhi = timerlo = 0;
+ mips_hpt_init(count);
+ break;
+ case 2:
+ prev_count = count;
+ break;
+ case 3:
+ if (!hpt_initialized) {
+ unsigned int c3 = 3 * (count - prev_count);
+
+ timerhi = 0;
+ timerlo = c3;
+ mips_hpt_init(count - c3);
+ hpt_initialized = 1;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ /*
+ * In UP mode, we call local_timer_interrupt() to do profiling
+ * and process accouting.
+ *
+ * In SMP mode, local_timer_interrupt() is invoked by appropriate
+ * low-level local timer interrupt handler.
+ */
+ local_timer_interrupt(irq, dev_id, regs);
+
+ return IRQ_HANDLED;
+}
+
+asmlinkage void ll_timer_interrupt(int irq, struct pt_regs *regs)
+{
+ irq_enter();
+ kstat_this_cpu.irqs[irq]++;
+
+ /* we keep interrupt disabled all the time */
+ timer_interrupt(irq, NULL, regs);
+
+ irq_exit();
+}
+
+asmlinkage void ll_local_timer_interrupt(int irq, struct pt_regs *regs)
+{
+ irq_enter();
+ if (smp_processor_id() != 0)
+ kstat_this_cpu.irqs[irq]++;
+
+ /* we keep interrupt disabled all the time */
+ local_timer_interrupt(irq, NULL, regs);
+
+ irq_exit();
+}
+
+/*
+ * time_init() - it does the following things.
+ *
+ * 1) board_time_init() -
+ * a) (optional) set up RTC routines,
+ * b) (optional) calibrate and set the mips_hpt_frequency
+ * (only needed if you intended to use fixed_rate_gettimeoffset
+ * or use cpu counter as timer interrupt source)
+ * 2) setup xtime based on rtc_get_time().
+ * 3) choose a appropriate gettimeoffset routine.
+ * 4) calculate a couple of cached variables for later usage
+ * 5) board_timer_setup() -
+ * a) (optional) over-write any choices made above by time_init().
+ * b) machine specific code should setup the timer irqaction.
+ * c) enable the timer interrupt
+ */
+
+void (*board_time_init)(void);
+void (*board_timer_setup)(struct irqaction *irq);
+
+unsigned int mips_hpt_frequency;
+
+static struct irqaction timer_irqaction = {
+ .handler = timer_interrupt,
+ .flags = SA_INTERRUPT,
+ .name = "timer",
+};
+
+static unsigned int __init calibrate_hpt(void)
+{
+ u64 frequency;
+ u32 hpt_start, hpt_end, hpt_count, hz;
+
+ const int loops = HZ / 10;
+ int log_2_loops = 0;
+ int i;
+
+ /*
+ * We want to calibrate for 0.1s, but to avoid a 64-bit
+ * division we round the number of loops up to the nearest
+ * power of 2.
+ */
+ while (loops > 1 << log_2_loops)
+ log_2_loops++;
+ i = 1 << log_2_loops;
+
+ /*
+ * Wait for a rising edge of the timer interrupt.
+ */
+ while (mips_timer_state());
+ while (!mips_timer_state());
+
+ /*
+ * Now see how many high precision timer ticks happen
+ * during the calculated number of periods between timer
+ * interrupts.
+ */
+ hpt_start = mips_hpt_read();
+ do {
+ while (mips_timer_state());
+ while (!mips_timer_state());
+ } while (--i);
+ hpt_end = mips_hpt_read();
+
+ hpt_count = hpt_end - hpt_start;
+ hz = HZ;
+ frequency = (u64)hpt_count * (u64)hz;
+
+ return frequency >> log_2_loops;
+}
+
+void __init time_init(void)
+{
+ if (board_time_init)
+ board_time_init();
+
+ if (!rtc_set_mmss)
+ rtc_set_mmss = rtc_set_time;
+
+ xtime.tv_sec = rtc_get_time();
+ xtime.tv_nsec = 0;
+
+ set_normalized_timespec(&wall_to_monotonic,
+ -xtime.tv_sec, -xtime.tv_nsec);
+
+ /* Choose appropriate high precision timer routines. */
+ if (!cpu_has_counter && !mips_hpt_read) {
+ /* No high precision timer -- sorry. */
+ mips_hpt_read = null_hpt_read;
+ mips_hpt_init = null_hpt_init;
+ } else if (!mips_hpt_frequency && !mips_timer_state) {
+ /* A high precision timer of unknown frequency. */
+ if (!mips_hpt_read) {
+ /* No external high precision timer -- use R4k. */
+ mips_hpt_read = c0_hpt_read;
+ mips_hpt_init = c0_hpt_init;
+ }
+
+ if ((current_cpu_data.isa_level == MIPS_CPU_ISA_M32) ||
+ (current_cpu_data.isa_level == MIPS_CPU_ISA_I) ||
+ (current_cpu_data.isa_level == MIPS_CPU_ISA_II))
+ /*
+ * We need to calibrate the counter but we don't have
+ * 64-bit division.
+ */
+ do_gettimeoffset = calibrate_div32_gettimeoffset;
+ else
+ /*
+ * We need to calibrate the counter but we *do* have
+ * 64-bit division.
+ */
+ do_gettimeoffset = calibrate_div64_gettimeoffset;
+ } else {
+ /* We know counter frequency. Or we can get it. */
+ if (!mips_hpt_read) {
+ /* No external high precision timer -- use R4k. */
+ mips_hpt_read = c0_hpt_read;
+
+ if (mips_timer_state)
+ mips_hpt_init = c0_hpt_init;
+ else {
+ /* No external timer interrupt -- use R4k. */
+ mips_hpt_init = c0_hpt_timer_init;
+ mips_timer_ack = c0_timer_ack;
+ }
+ }
+ if (!mips_hpt_frequency)
+ mips_hpt_frequency = calibrate_hpt();
+
+ do_gettimeoffset = fixed_rate_gettimeoffset;
+
+ /* Calculate cache parameters. */
+ cycles_per_jiffy = (mips_hpt_frequency + HZ / 2) / HZ;
+
+ /* sll32_usecs_per_cycle = 10^6 * 2^32 / mips_counter_freq */
+ do_div64_32(sll32_usecs_per_cycle,
+ 1000000, mips_hpt_frequency / 2,
+ mips_hpt_frequency);
+
+ /* Report the high precision timer rate for a reference. */
+ printk("Using %u.%03u MHz high precision timer.\n",
+ ((mips_hpt_frequency + 500) / 1000) / 1000,
+ ((mips_hpt_frequency + 500) / 1000) % 1000);
+ }
+
+ if (!mips_timer_ack)
+ /* No timer interrupt ack (e.g. i8254). */
+ mips_timer_ack = null_timer_ack;
+
+ /* This sets up the high precision timer for the first interrupt. */
+ mips_hpt_init(mips_hpt_read());
+
+ /*
+ * Call board specific timer interrupt setup.
+ *
+ * this pointer must be setup in machine setup routine.
+ *
+ * Even if a machine chooses to use a low-level timer interrupt,
+ * it still needs to setup the timer_irqaction.
+ * In that case, it might be better to set timer_irqaction.handler
+ * to be NULL function so that we are sure the high-level code
+ * is not invoked accidentally.
+ */
+ board_timer_setup(&timer_irqaction);
+}
+
+#define FEBRUARY 2
+#define STARTOFTIME 1970
+#define SECDAY 86400L
+#define SECYR (SECDAY * 365)
+#define leapyear(y) ((!((y) % 4) && ((y) % 100)) || !((y) % 400))
+#define days_in_year(y) (leapyear(y) ? 366 : 365)
+#define days_in_month(m) (month_days[(m) - 1])
+
+static int month_days[12] = {
+ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+};
+
+void to_tm(unsigned long tim, struct rtc_time *tm)
+{
+ long hms, day, gday;
+ int i;
+
+ gday = day = tim / SECDAY;
+ hms = tim % SECDAY;
+
+ /* Hours, minutes, seconds are easy */
+ tm->tm_hour = hms / 3600;
+ tm->tm_min = (hms % 3600) / 60;
+ tm->tm_sec = (hms % 3600) % 60;
+
+ /* Number of years in days */
+ for (i = STARTOFTIME; day >= days_in_year(i); i++)
+ day -= days_in_year(i);
+ tm->tm_year = i;
+
+ /* Number of months in days left */
+ if (leapyear(tm->tm_year))
+ days_in_month(FEBRUARY) = 29;
+ for (i = 1; day >= days_in_month(i); i++)
+ day -= days_in_month(i);
+ days_in_month(FEBRUARY) = 28;
+ tm->tm_mon = i - 1; /* tm_mon starts from 0 to 11 */
+
+ /* Days are what is left over (+1) from all that. */
+ tm->tm_mday = day + 1;
+
+ /*
+ * Determine the day of week
+ */
+ tm->tm_wday = (gday + 4) % 7; /* 1970/1/1 was Thursday */
+}
+
+EXPORT_SYMBOL(rtc_lock);
+EXPORT_SYMBOL(to_tm);
+EXPORT_SYMBOL(rtc_set_time);
+EXPORT_SYMBOL(rtc_get_time);
+
+unsigned long long sched_clock(void)
+{
+ return (unsigned long long)jiffies*(1000000000/HZ);
+}
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
new file mode 100644
index 0000000..56c36e4
--- /dev/null
+++ b/arch/mips/kernel/traps.c
@@ -0,0 +1,1062 @@
+/*
+ * 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) 1994 - 1999, 2000, 01 Ralf Baechle
+ * Copyright (C) 1995, 1996 Paul M. Antoine
+ * Copyright (C) 1998 Ulf Carlsson
+ * Copyright (C) 1999 Silicon Graphics, Inc.
+ * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2000, 01 MIPS Technologies, Inc.
+ * Copyright (C) 2002, 2003, 2004 Maciej W. Rozycki
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/spinlock.h>
+#include <linux/kallsyms.h>
+
+#include <asm/bootinfo.h>
+#include <asm/branch.h>
+#include <asm/break.h>
+#include <asm/cpu.h>
+#include <asm/fpu.h>
+#include <asm/module.h>
+#include <asm/pgtable.h>
+#include <asm/ptrace.h>
+#include <asm/sections.h>
+#include <asm/system.h>
+#include <asm/tlbdebug.h>
+#include <asm/traps.h>
+#include <asm/uaccess.h>
+#include <asm/mmu_context.h>
+#include <asm/watch.h>
+#include <asm/types.h>
+
+extern asmlinkage void handle_tlbm(void);
+extern asmlinkage void handle_tlbl(void);
+extern asmlinkage void handle_tlbs(void);
+extern asmlinkage void handle_adel(void);
+extern asmlinkage void handle_ades(void);
+extern asmlinkage void handle_ibe(void);
+extern asmlinkage void handle_dbe(void);
+extern asmlinkage void handle_sys(void);
+extern asmlinkage void handle_bp(void);
+extern asmlinkage void handle_ri(void);
+extern asmlinkage void handle_cpu(void);
+extern asmlinkage void handle_ov(void);
+extern asmlinkage void handle_tr(void);
+extern asmlinkage void handle_fpe(void);
+extern asmlinkage void handle_mdmx(void);
+extern asmlinkage void handle_watch(void);
+extern asmlinkage void handle_mcheck(void);
+extern asmlinkage void handle_reserved(void);
+
+extern int fpu_emulator_cop1Handler(int xcptno, struct pt_regs *xcp,
+ struct mips_fpu_soft_struct *ctx);
+
+void (*board_be_init)(void);
+int (*board_be_handler)(struct pt_regs *regs, int is_fixup);
+
+/*
+ * These constant is for searching for possible module text segments.
+ * MODULE_RANGE is a guess of how much space is likely to be vmalloced.
+ */
+#define MODULE_RANGE (8*1024*1024)
+
+/*
+ * This routine abuses get_user()/put_user() to reference pointers
+ * with at least a bit of error checking ...
+ */
+void show_stack(struct task_struct *task, unsigned long *sp)
+{
+ const int field = 2 * sizeof(unsigned long);
+ long stackdata;
+ int i;
+
+ if (!sp) {
+ if (task && task != current)
+ sp = (unsigned long *) task->thread.reg29;
+ else
+ sp = (unsigned long *) &sp;
+ }
+
+ printk("Stack :");
+ i = 0;
+ while ((unsigned long) sp & (PAGE_SIZE - 1)) {
+ if (i && ((i % (64 / field)) == 0))
+ printk("\n ");
+ if (i > 39) {
+ printk(" ...");
+ break;
+ }
+
+ if (__get_user(stackdata, sp++)) {
+ printk(" (Bad stack address)");
+ break;
+ }
+
+ printk(" %0*lx", field, stackdata);
+ i++;
+ }
+ printk("\n");
+}
+
+void show_trace(struct task_struct *task, unsigned long *stack)
+{
+ const int field = 2 * sizeof(unsigned long);
+ unsigned long addr;
+
+ if (!stack) {
+ if (task && task != current)
+ stack = (unsigned long *) task->thread.reg29;
+ else
+ stack = (unsigned long *) &stack;
+ }
+
+ printk("Call Trace:");
+#ifdef CONFIG_KALLSYMS
+ printk("\n");
+#endif
+ while (!kstack_end(stack)) {
+ addr = *stack++;
+ if (__kernel_text_address(addr)) {
+ printk(" [<%0*lx>] ", field, addr);
+ print_symbol("%s\n", addr);
+ }
+ }
+ printk("\n");
+}
+
+/*
+ * The architecture-independent dump_stack generator
+ */
+void dump_stack(void)
+{
+ unsigned long stack;
+
+ show_trace(current, &stack);
+}
+
+EXPORT_SYMBOL(dump_stack);
+
+void show_code(unsigned int *pc)
+{
+ long i;
+
+ printk("\nCode:");
+
+ for(i = -3 ; i < 6 ; i++) {
+ unsigned int insn;
+ if (__get_user(insn, pc + i)) {
+ printk(" (Bad address in epc)\n");
+ break;
+ }
+ printk("%c%08x%c", (i?' ':'<'), insn, (i?' ':'>'));
+ }
+}
+
+void show_regs(struct pt_regs *regs)
+{
+ const int field = 2 * sizeof(unsigned long);
+ unsigned int cause = regs->cp0_cause;
+ int i;
+
+ printk("Cpu %d\n", smp_processor_id());
+
+ /*
+ * Saved main processor registers
+ */
+ for (i = 0; i < 32; ) {
+ if ((i % 4) == 0)
+ printk("$%2d :", i);
+ if (i == 0)
+ printk(" %0*lx", field, 0UL);
+ else if (i == 26 || i == 27)
+ printk(" %*s", field, "");
+ else
+ printk(" %0*lx", field, regs->regs[i]);
+
+ i++;
+ if ((i % 4) == 0)
+ printk("\n");
+ }
+
+ printk("Hi : %0*lx\n", field, regs->hi);
+ printk("Lo : %0*lx\n", field, regs->lo);
+
+ /*
+ * Saved cp0 registers
+ */
+ printk("epc : %0*lx ", field, regs->cp0_epc);
+ print_symbol("%s ", regs->cp0_epc);
+ printk(" %s\n", print_tainted());
+ printk("ra : %0*lx ", field, regs->regs[31]);
+ print_symbol("%s\n", regs->regs[31]);
+
+ printk("Status: %08x ", (uint32_t) regs->cp0_status);
+
+ if (regs->cp0_status & ST0_KX)
+ printk("KX ");
+ if (regs->cp0_status & ST0_SX)
+ printk("SX ");
+ if (regs->cp0_status & ST0_UX)
+ printk("UX ");
+ switch (regs->cp0_status & ST0_KSU) {
+ case KSU_USER:
+ printk("USER ");
+ break;
+ case KSU_SUPERVISOR:
+ printk("SUPERVISOR ");
+ break;
+ case KSU_KERNEL:
+ printk("KERNEL ");
+ break;
+ default:
+ printk("BAD_MODE ");
+ break;
+ }
+ if (regs->cp0_status & ST0_ERL)
+ printk("ERL ");
+ if (regs->cp0_status & ST0_EXL)
+ printk("EXL ");
+ if (regs->cp0_status & ST0_IE)
+ printk("IE ");
+ printk("\n");
+
+ printk("Cause : %08x\n", cause);
+
+ cause = (cause & CAUSEF_EXCCODE) >> CAUSEB_EXCCODE;
+ if (1 <= cause && cause <= 5)
+ printk("BadVA : %0*lx\n", field, regs->cp0_badvaddr);
+
+ printk("PrId : %08x\n", read_c0_prid());
+}
+
+void show_registers(struct pt_regs *regs)
+{
+ show_regs(regs);
+ print_modules();
+ printk("Process %s (pid: %d, threadinfo=%p, task=%p)\n",
+ current->comm, current->pid, current_thread_info(), current);
+ show_stack(current, (long *) regs->regs[29]);
+ show_trace(current, (long *) regs->regs[29]);
+ show_code((unsigned int *) regs->cp0_epc);
+ printk("\n");
+}
+
+static DEFINE_SPINLOCK(die_lock);
+
+NORET_TYPE void __die(const char * str, struct pt_regs * regs,
+ const char * file, const char * func, unsigned long line)
+{
+ static int die_counter;
+
+ console_verbose();
+ spin_lock_irq(&die_lock);
+ printk("%s", str);
+ if (file && func)
+ printk(" in %s:%s, line %ld", file, func, line);
+ printk("[#%d]:\n", ++die_counter);
+ show_registers(regs);
+ spin_unlock_irq(&die_lock);
+ do_exit(SIGSEGV);
+}
+
+void __die_if_kernel(const char * str, struct pt_regs * regs,
+ const char * file, const char * func, unsigned long line)
+{
+ if (!user_mode(regs))
+ __die(str, regs, file, func, line);
+}
+
+extern const struct exception_table_entry __start___dbe_table[];
+extern const struct exception_table_entry __stop___dbe_table[];
+
+void __declare_dbe_table(void)
+{
+ __asm__ __volatile__(
+ ".section\t__dbe_table,\"a\"\n\t"
+ ".previous"
+ );
+}
+
+/* Given an address, look for it in the exception tables. */
+static const struct exception_table_entry *search_dbe_tables(unsigned long addr)
+{
+ const struct exception_table_entry *e;
+
+ e = search_extable(__start___dbe_table, __stop___dbe_table - 1, addr);
+ if (!e)
+ e = search_module_dbetables(addr);
+ return e;
+}
+
+asmlinkage void do_be(struct pt_regs *regs)
+{
+ const int field = 2 * sizeof(unsigned long);
+ const struct exception_table_entry *fixup = NULL;
+ int data = regs->cp0_cause & 4;
+ int action = MIPS_BE_FATAL;
+
+ /* XXX For now. Fixme, this searches the wrong table ... */
+ if (data && !user_mode(regs))
+ fixup = search_dbe_tables(exception_epc(regs));
+
+ if (fixup)
+ action = MIPS_BE_FIXUP;
+
+ if (board_be_handler)
+ action = board_be_handler(regs, fixup != 0);
+
+ switch (action) {
+ case MIPS_BE_DISCARD:
+ return;
+ case MIPS_BE_FIXUP:
+ if (fixup) {
+ regs->cp0_epc = fixup->nextinsn;
+ return;
+ }
+ break;
+ default:
+ break;
+ }
+
+ /*
+ * Assume it would be too dangerous to continue ...
+ */
+ printk(KERN_ALERT "%s bus error, epc == %0*lx, ra == %0*lx\n",
+ data ? "Data" : "Instruction",
+ field, regs->cp0_epc, field, regs->regs[31]);
+ die_if_kernel("Oops", regs);
+ force_sig(SIGBUS, current);
+}
+
+static inline int get_insn_opcode(struct pt_regs *regs, unsigned int *opcode)
+{
+ unsigned int *epc;
+
+ epc = (unsigned int *) regs->cp0_epc +
+ ((regs->cp0_cause & CAUSEF_BD) != 0);
+ if (!get_user(*opcode, epc))
+ return 0;
+
+ force_sig(SIGSEGV, current);
+ return 1;
+}
+
+/*
+ * ll/sc emulation
+ */
+
+#define OPCODE 0xfc000000
+#define BASE 0x03e00000
+#define RT 0x001f0000
+#define OFFSET 0x0000ffff
+#define LL 0xc0000000
+#define SC 0xe0000000
+
+/*
+ * The ll_bit is cleared by r*_switch.S
+ */
+
+unsigned long ll_bit;
+
+static struct task_struct *ll_task = NULL;
+
+static inline void simulate_ll(struct pt_regs *regs, unsigned int opcode)
+{
+ unsigned long value, *vaddr;
+ long offset;
+ int signal = 0;
+
+ /*
+ * analyse the ll instruction that just caused a ri exception
+ * and put the referenced address to addr.
+ */
+
+ /* sign extend offset */
+ offset = opcode & OFFSET;
+ offset <<= 16;
+ offset >>= 16;
+
+ vaddr = (unsigned long *)((long)(regs->regs[(opcode & BASE) >> 21]) + offset);
+
+ if ((unsigned long)vaddr & 3) {
+ signal = SIGBUS;
+ goto sig;
+ }
+ if (get_user(value, vaddr)) {
+ signal = SIGSEGV;
+ goto sig;
+ }
+
+ preempt_disable();
+
+ if (ll_task == NULL || ll_task == current) {
+ ll_bit = 1;
+ } else {
+ ll_bit = 0;
+ }
+ ll_task = current;
+
+ preempt_enable();
+
+ regs->regs[(opcode & RT) >> 16] = value;
+
+ compute_return_epc(regs);
+ return;
+
+sig:
+ force_sig(signal, current);
+}
+
+static inline void simulate_sc(struct pt_regs *regs, unsigned int opcode)
+{
+ unsigned long *vaddr, reg;
+ long offset;
+ int signal = 0;
+
+ /*
+ * analyse the sc instruction that just caused a ri exception
+ * and put the referenced address to addr.
+ */
+
+ /* sign extend offset */
+ offset = opcode & OFFSET;
+ offset <<= 16;
+ offset >>= 16;
+
+ vaddr = (unsigned long *)((long)(regs->regs[(opcode & BASE) >> 21]) + offset);
+ reg = (opcode & RT) >> 16;
+
+ if ((unsigned long)vaddr & 3) {
+ signal = SIGBUS;
+ goto sig;
+ }
+
+ preempt_disable();
+
+ if (ll_bit == 0 || ll_task != current) {
+ regs->regs[reg] = 0;
+ preempt_enable();
+ compute_return_epc(regs);
+ return;
+ }
+
+ preempt_enable();
+
+ if (put_user(regs->regs[reg], vaddr)) {
+ signal = SIGSEGV;
+ goto sig;
+ }
+
+ regs->regs[reg] = 1;
+
+ compute_return_epc(regs);
+ return;
+
+sig:
+ force_sig(signal, current);
+}
+
+/*
+ * ll uses the opcode of lwc0 and sc uses the opcode of swc0. That is both
+ * opcodes are supposed to result in coprocessor unusable exceptions if
+ * executed on ll/sc-less processors. That's the theory. In practice a
+ * few processors such as NEC's VR4100 throw reserved instruction exceptions
+ * instead, so we're doing the emulation thing in both exception handlers.
+ */
+static inline int simulate_llsc(struct pt_regs *regs)
+{
+ unsigned int opcode;
+
+ if (unlikely(get_insn_opcode(regs, &opcode)))
+ return -EFAULT;
+
+ if ((opcode & OPCODE) == LL) {
+ simulate_ll(regs, opcode);
+ return 0;
+ }
+ if ((opcode & OPCODE) == SC) {
+ simulate_sc(regs, opcode);
+ return 0;
+ }
+
+ return -EFAULT; /* Strange things going on ... */
+}
+
+asmlinkage void do_ov(struct pt_regs *regs)
+{
+ siginfo_t info;
+
+ info.si_code = FPE_INTOVF;
+ info.si_signo = SIGFPE;
+ info.si_errno = 0;
+ info.si_addr = (void *)regs->cp0_epc;
+ force_sig_info(SIGFPE, &info, current);
+}
+
+/*
+ * XXX Delayed fp exceptions when doing a lazy ctx switch XXX
+ */
+asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31)
+{
+ if (fcr31 & FPU_CSR_UNI_X) {
+ int sig;
+
+ preempt_disable();
+
+ /*
+ * Unimplemented operation exception. If we've got the full
+ * software emulator on-board, let's use it...
+ *
+ * Force FPU to dump state into task/thread context. We're
+ * moving a lot of data here for what is probably a single
+ * instruction, but the alternative is to pre-decode the FP
+ * register operands before invoking the emulator, which seems
+ * a bit extreme for what should be an infrequent event.
+ */
+ save_fp(current);
+
+ /* Run the emulator */
+ sig = fpu_emulator_cop1Handler (0, regs,
+ ¤t->thread.fpu.soft);
+
+ /*
+ * We can't allow the emulated instruction to leave any of
+ * the cause bit set in $fcr31.
+ */
+ current->thread.fpu.soft.fcr31 &= ~FPU_CSR_ALL_X;
+
+ /* Restore the hardware register state */
+ restore_fp(current);
+
+ preempt_enable();
+
+ /* If something went wrong, signal */
+ if (sig)
+ force_sig(sig, current);
+
+ return;
+ }
+
+ force_sig(SIGFPE, current);
+}
+
+asmlinkage void do_bp(struct pt_regs *regs)
+{
+ unsigned int opcode, bcode;
+ siginfo_t info;
+
+ die_if_kernel("Break instruction in kernel code", regs);
+
+ if (get_insn_opcode(regs, &opcode))
+ return;
+
+ /*
+ * There is the ancient bug in the MIPS assemblers that the break
+ * code starts left to bit 16 instead to bit 6 in the opcode.
+ * Gas is bug-compatible, but not always, grrr...
+ * We handle both cases with a simple heuristics. --macro
+ */
+ bcode = ((opcode >> 6) & ((1 << 20) - 1));
+ if (bcode < (1 << 10))
+ bcode <<= 10;
+
+ /*
+ * (A short test says that IRIX 5.3 sends SIGTRAP for all break
+ * insns, even for break codes that indicate arithmetic failures.
+ * Weird ...)
+ * But should we continue the brokenness??? --macro
+ */
+ switch (bcode) {
+ case BRK_OVERFLOW << 10:
+ case BRK_DIVZERO << 10:
+ if (bcode == (BRK_DIVZERO << 10))
+ info.si_code = FPE_INTDIV;
+ else
+ info.si_code = FPE_INTOVF;
+ info.si_signo = SIGFPE;
+ info.si_errno = 0;
+ info.si_addr = (void *)regs->cp0_epc;
+ force_sig_info(SIGFPE, &info, current);
+ break;
+ default:
+ force_sig(SIGTRAP, current);
+ }
+}
+
+asmlinkage void do_tr(struct pt_regs *regs)
+{
+ unsigned int opcode, tcode = 0;
+ siginfo_t info;
+
+ die_if_kernel("Trap instruction in kernel code", regs);
+
+ if (get_insn_opcode(regs, &opcode))
+ return;
+
+ /* Immediate versions don't provide a code. */
+ if (!(opcode & OPCODE))
+ tcode = ((opcode >> 6) & ((1 << 10) - 1));
+
+ /*
+ * (A short test says that IRIX 5.3 sends SIGTRAP for all trap
+ * insns, even for trap codes that indicate arithmetic failures.
+ * Weird ...)
+ * But should we continue the brokenness??? --macro
+ */
+ switch (tcode) {
+ case BRK_OVERFLOW:
+ case BRK_DIVZERO:
+ if (tcode == BRK_DIVZERO)
+ info.si_code = FPE_INTDIV;
+ else
+ info.si_code = FPE_INTOVF;
+ info.si_signo = SIGFPE;
+ info.si_errno = 0;
+ info.si_addr = (void *)regs->cp0_epc;
+ force_sig_info(SIGFPE, &info, current);
+ break;
+ default:
+ force_sig(SIGTRAP, current);
+ }
+}
+
+asmlinkage void do_ri(struct pt_regs *regs)
+{
+ die_if_kernel("Reserved instruction in kernel code", regs);
+
+ if (!cpu_has_llsc)
+ if (!simulate_llsc(regs))
+ return;
+
+ force_sig(SIGILL, current);
+}
+
+asmlinkage void do_cpu(struct pt_regs *regs)
+{
+ unsigned int cpid;
+
+ die_if_kernel("do_cpu invoked from kernel context!", regs);
+
+ cpid = (regs->cp0_cause >> CAUSEB_CE) & 3;
+
+ switch (cpid) {
+ case 0:
+ if (cpu_has_llsc)
+ break;
+
+ if (!simulate_llsc(regs))
+ return;
+ break;
+
+ case 1:
+ preempt_disable();
+
+ own_fpu();
+ if (used_math()) { /* Using the FPU again. */
+ restore_fp(current);
+ } else { /* First time FPU user. */
+ init_fpu();
+ set_used_math();
+ }
+
+ if (!cpu_has_fpu) {
+ int sig = fpu_emulator_cop1Handler(0, regs,
+ ¤t->thread.fpu.soft);
+ if (sig)
+ force_sig(sig, current);
+ }
+
+ preempt_enable();
+
+ return;
+
+ case 2:
+ case 3:
+ break;
+ }
+
+ force_sig(SIGILL, current);
+}
+
+asmlinkage void do_mdmx(struct pt_regs *regs)
+{
+ force_sig(SIGILL, current);
+}
+
+asmlinkage void do_watch(struct pt_regs *regs)
+{
+ /*
+ * We use the watch exception where available to detect stack
+ * overflows.
+ */
+ dump_tlb_all();
+ show_regs(regs);
+ panic("Caught WATCH exception - probably caused by stack overflow.");
+}
+
+asmlinkage void do_mcheck(struct pt_regs *regs)
+{
+ show_regs(regs);
+ dump_tlb_all();
+ /*
+ * Some chips may have other causes of machine check (e.g. SB1
+ * graduation timer)
+ */
+ panic("Caught Machine Check exception - %scaused by multiple "
+ "matching entries in the TLB.",
+ (regs->cp0_status & ST0_TS) ? "" : "not ");
+}
+
+asmlinkage void do_reserved(struct pt_regs *regs)
+{
+ /*
+ * Game over - no way to handle this if it ever occurs. Most probably
+ * caused by a new unknown cpu type or after another deadly
+ * hard/software error.
+ */
+ show_regs(regs);
+ panic("Caught reserved exception %ld - should not happen.",
+ (regs->cp0_cause & 0x7f) >> 2);
+}
+
+/*
+ * Some MIPS CPUs can enable/disable for cache parity detection, but do
+ * it different ways.
+ */
+static inline void parity_protection_init(void)
+{
+ switch (current_cpu_data.cputype) {
+ case CPU_24K:
+ /* 24K cache parity not currently implemented in FPGA */
+ printk(KERN_INFO "Disable cache parity protection for "
+ "MIPS 24K CPU.\n");
+ write_c0_ecc(read_c0_ecc() & ~0x80000000);
+ break;
+ case CPU_5KC:
+ /* Set the PE bit (bit 31) in the c0_ecc register. */
+ printk(KERN_INFO "Enable cache parity protection for "
+ "MIPS 5KC/24K CPUs.\n");
+ write_c0_ecc(read_c0_ecc() | 0x80000000);
+ break;
+ case CPU_20KC:
+ case CPU_25KF:
+ /* Clear the DE bit (bit 16) in the c0_status register. */
+ printk(KERN_INFO "Enable cache parity protection for "
+ "MIPS 20KC/25KF CPUs.\n");
+ clear_c0_status(ST0_DE);
+ break;
+ default:
+ break;
+ }
+}
+
+asmlinkage void cache_parity_error(void)
+{
+ const int field = 2 * sizeof(unsigned long);
+ unsigned int reg_val;
+
+ /* For the moment, report the problem and hang. */
+ printk("Cache error exception:\n");
+ printk("cp0_errorepc == %0*lx\n", field, read_c0_errorepc());
+ reg_val = read_c0_cacheerr();
+ printk("c0_cacheerr == %08x\n", reg_val);
+
+ printk("Decoded c0_cacheerr: %s cache fault in %s reference.\n",
+ reg_val & (1<<30) ? "secondary" : "primary",
+ reg_val & (1<<31) ? "data" : "insn");
+ printk("Error bits: %s%s%s%s%s%s%s\n",
+ reg_val & (1<<29) ? "ED " : "",
+ reg_val & (1<<28) ? "ET " : "",
+ reg_val & (1<<26) ? "EE " : "",
+ reg_val & (1<<25) ? "EB " : "",
+ reg_val & (1<<24) ? "EI " : "",
+ reg_val & (1<<23) ? "E1 " : "",
+ reg_val & (1<<22) ? "E0 " : "");
+ printk("IDX: 0x%08x\n", reg_val & ((1<<22)-1));
+
+#if defined(CONFIG_CPU_MIPS32) || defined (CONFIG_CPU_MIPS64)
+ if (reg_val & (1<<22))
+ printk("DErrAddr0: 0x%0*lx\n", field, read_c0_derraddr0());
+
+ if (reg_val & (1<<23))
+ printk("DErrAddr1: 0x%0*lx\n", field, read_c0_derraddr1());
+#endif
+
+ panic("Can't handle the cache error!");
+}
+
+/*
+ * SDBBP EJTAG debug exception handler.
+ * We skip the instruction and return to the next instruction.
+ */
+void ejtag_exception_handler(struct pt_regs *regs)
+{
+ const int field = 2 * sizeof(unsigned long);
+ unsigned long depc, old_epc;
+ unsigned int debug;
+
+ printk("SDBBP EJTAG debug exception - not handled yet, just ignored!\n");
+ depc = read_c0_depc();
+ debug = read_c0_debug();
+ printk("c0_depc = %0*lx, DEBUG = %08x\n", field, depc, debug);
+ if (debug & 0x80000000) {
+ /*
+ * In branch delay slot.
+ * We cheat a little bit here and use EPC to calculate the
+ * debug return address (DEPC). EPC is restored after the
+ * calculation.
+ */
+ old_epc = regs->cp0_epc;
+ regs->cp0_epc = depc;
+ __compute_return_epc(regs);
+ depc = regs->cp0_epc;
+ regs->cp0_epc = old_epc;
+ } else
+ depc += 4;
+ write_c0_depc(depc);
+
+#if 0
+ printk("\n\n----- Enable EJTAG single stepping ----\n\n");
+ write_c0_debug(debug | 0x100);
+#endif
+}
+
+/*
+ * NMI exception handler.
+ */
+void nmi_exception_handler(struct pt_regs *regs)
+{
+ printk("NMI taken!!!!\n");
+ die("NMI", regs);
+ while(1) ;
+}
+
+unsigned long exception_handlers[32];
+
+/*
+ * As a side effect of the way this is implemented we're limited
+ * to interrupt handlers in the address range from
+ * KSEG0 <= x < KSEG0 + 256mb on the Nevada. Oh well ...
+ */
+void *set_except_vector(int n, void *addr)
+{
+ unsigned long handler = (unsigned long) addr;
+ unsigned long old_handler = exception_handlers[n];
+
+ exception_handlers[n] = handler;
+ if (n == 0 && cpu_has_divec) {
+ *(volatile u32 *)(CAC_BASE + 0x200) = 0x08000000 |
+ (0x03ffffff & (handler >> 2));
+ flush_icache_range(CAC_BASE + 0x200, CAC_BASE + 0x204);
+ }
+ return (void *)old_handler;
+}
+
+/*
+ * This is used by native signal handling
+ */
+asmlinkage int (*save_fp_context)(struct sigcontext *sc);
+asmlinkage int (*restore_fp_context)(struct sigcontext *sc);
+
+extern asmlinkage int _save_fp_context(struct sigcontext *sc);
+extern asmlinkage int _restore_fp_context(struct sigcontext *sc);
+
+extern asmlinkage int fpu_emulator_save_context(struct sigcontext *sc);
+extern asmlinkage int fpu_emulator_restore_context(struct sigcontext *sc);
+
+static inline void signal_init(void)
+{
+ if (cpu_has_fpu) {
+ save_fp_context = _save_fp_context;
+ restore_fp_context = _restore_fp_context;
+ } else {
+ save_fp_context = fpu_emulator_save_context;
+ restore_fp_context = fpu_emulator_restore_context;
+ }
+}
+
+#ifdef CONFIG_MIPS32_COMPAT
+
+/*
+ * This is used by 32-bit signal stuff on the 64-bit kernel
+ */
+asmlinkage int (*save_fp_context32)(struct sigcontext32 *sc);
+asmlinkage int (*restore_fp_context32)(struct sigcontext32 *sc);
+
+extern asmlinkage int _save_fp_context32(struct sigcontext32 *sc);
+extern asmlinkage int _restore_fp_context32(struct sigcontext32 *sc);
+
+extern asmlinkage int fpu_emulator_save_context32(struct sigcontext32 *sc);
+extern asmlinkage int fpu_emulator_restore_context32(struct sigcontext32 *sc);
+
+static inline void signal32_init(void)
+{
+ if (cpu_has_fpu) {
+ save_fp_context32 = _save_fp_context32;
+ restore_fp_context32 = _restore_fp_context32;
+ } else {
+ save_fp_context32 = fpu_emulator_save_context32;
+ restore_fp_context32 = fpu_emulator_restore_context32;
+ }
+}
+#endif
+
+extern void cpu_cache_init(void);
+extern void tlb_init(void);
+
+void __init per_cpu_trap_init(void)
+{
+ unsigned int cpu = smp_processor_id();
+ unsigned int status_set = ST0_CU0;
+
+ /*
+ * Disable coprocessors and select 32-bit or 64-bit addressing
+ * and the 16/32 or 32/32 FPR register model. Reset the BEV
+ * flag that some firmware may have left set and the TS bit (for
+ * IP27). Set XX for ISA IV code to work.
+ */
+#ifdef CONFIG_MIPS64
+ status_set |= ST0_FR|ST0_KX|ST0_SX|ST0_UX;
+#endif
+ if (current_cpu_data.isa_level == MIPS_CPU_ISA_IV)
+ status_set |= ST0_XX;
+ change_c0_status(ST0_CU|ST0_FR|ST0_BEV|ST0_TS|ST0_KX|ST0_SX|ST0_UX,
+ status_set);
+
+ /*
+ * Some MIPS CPUs have a dedicated interrupt vector which reduces the
+ * interrupt processing overhead. Use it where available.
+ */
+ if (cpu_has_divec)
+ set_c0_cause(CAUSEF_IV);
+
+ cpu_data[cpu].asid_cache = ASID_FIRST_VERSION;
+ TLBMISS_HANDLER_SETUP();
+
+ atomic_inc(&init_mm.mm_count);
+ current->active_mm = &init_mm;
+ BUG_ON(current->mm);
+ enter_lazy_tlb(&init_mm, current);
+
+ cpu_cache_init();
+ tlb_init();
+}
+
+void __init trap_init(void)
+{
+ extern char except_vec3_generic, except_vec3_r4000;
+ extern char except_vec_ejtag_debug;
+ extern char except_vec4;
+ unsigned long i;
+
+ per_cpu_trap_init();
+
+ /*
+ * Copy the generic exception handlers to their final destination.
+ * This will be overriden later as suitable for a particular
+ * configuration.
+ */
+ memcpy((void *)(CAC_BASE + 0x180), &except_vec3_generic, 0x80);
+
+ /*
+ * Setup default vectors
+ */
+ for (i = 0; i <= 31; i++)
+ set_except_vector(i, handle_reserved);
+
+ /*
+ * Copy the EJTAG debug exception vector handler code to it's final
+ * destination.
+ */
+ if (cpu_has_ejtag)
+ memcpy((void *)(CAC_BASE + 0x300), &except_vec_ejtag_debug, 0x80);
+
+ /*
+ * Only some CPUs have the watch exceptions.
+ */
+ if (cpu_has_watch)
+ set_except_vector(23, handle_watch);
+
+ /*
+ * Some MIPS CPUs have a dedicated interrupt vector which reduces the
+ * interrupt processing overhead. Use it where available.
+ */
+ if (cpu_has_divec)
+ memcpy((void *)(CAC_BASE + 0x200), &except_vec4, 0x8);
+
+ /*
+ * Some CPUs can enable/disable for cache parity detection, but does
+ * it different ways.
+ */
+ parity_protection_init();
+
+ /*
+ * The Data Bus Errors / Instruction Bus Errors are signaled
+ * by external hardware. Therefore these two exceptions
+ * may have board specific handlers.
+ */
+ if (board_be_init)
+ board_be_init();
+
+ set_except_vector(1, handle_tlbm);
+ set_except_vector(2, handle_tlbl);
+ set_except_vector(3, handle_tlbs);
+
+ set_except_vector(4, handle_adel);
+ set_except_vector(5, handle_ades);
+
+ set_except_vector(6, handle_ibe);
+ set_except_vector(7, handle_dbe);
+
+ set_except_vector(8, handle_sys);
+ set_except_vector(9, handle_bp);
+ set_except_vector(10, handle_ri);
+ set_except_vector(11, handle_cpu);
+ set_except_vector(12, handle_ov);
+ set_except_vector(13, handle_tr);
+ set_except_vector(22, handle_mdmx);
+
+ if (cpu_has_fpu && !cpu_has_nofpuex)
+ set_except_vector(15, handle_fpe);
+
+ if (cpu_has_mcheck)
+ set_except_vector(24, handle_mcheck);
+
+ if (cpu_has_vce)
+ /* Special exception: R4[04]00 uses also the divec space. */
+ memcpy((void *)(CAC_BASE + 0x180), &except_vec3_r4000, 0x100);
+ else if (cpu_has_4kex)
+ memcpy((void *)(CAC_BASE + 0x180), &except_vec3_generic, 0x80);
+ else
+ memcpy((void *)(CAC_BASE + 0x080), &except_vec3_generic, 0x80);
+
+ if (current_cpu_data.cputype == CPU_R6000 ||
+ current_cpu_data.cputype == CPU_R6000A) {
+ /*
+ * The R6000 is the only R-series CPU that features a machine
+ * check exception (similar to the R4000 cache error) and
+ * unaligned ldc1/sdc1 exception. The handlers have not been
+ * written yet. Well, anyway there is no R6000 machine on the
+ * current list of targets for Linux/MIPS.
+ * (Duh, crap, there is someone with a triple R6k machine)
+ */
+ //set_except_vector(14, handle_mc);
+ //set_except_vector(15, handle_ndc);
+ }
+
+ signal_init();
+#ifdef CONFIG_MIPS32_COMPAT
+ signal32_init();
+#endif
+
+ flush_icache_range(CAC_BASE, CAC_BASE + 0x400);
+}
diff --git a/arch/mips/kernel/unaligned.c b/arch/mips/kernel/unaligned.c
new file mode 100644
index 0000000..3f24a1d
--- /dev/null
+++ b/arch/mips/kernel/unaligned.c
@@ -0,0 +1,550 @@
+/*
+ * Handle unaligned accesses by emulation.
+ *
+ * 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) 1996, 1998, 1999, 2002 by Ralf Baechle
+ * Copyright (C) 1999 Silicon Graphics, Inc.
+ *
+ * This file contains exception handler for address error exception with the
+ * special capability to execute faulting instructions in software. The
+ * handler does not try to handle the case when the program counter points
+ * to an address not aligned to a word boundary.
+ *
+ * Putting data to unaligned addresses is a bad practice even on Intel where
+ * only the performance is affected. Much worse is that such code is non-
+ * portable. Due to several programs that die on MIPS due to alignment
+ * problems I decided to implement this handler anyway though I originally
+ * didn't intend to do this at all for user code.
+ *
+ * For now I enable fixing of address errors by default to make life easier.
+ * I however intend to disable this somewhen in the future when the alignment
+ * problems with user programs have been fixed. For programmers this is the
+ * right way to go.
+ *
+ * Fixing address errors is a per process option. The option is inherited
+ * across fork(2) and execve(2) calls. If you really want to use the
+ * option in your user programs - I discourage the use of the software
+ * emulation strongly - use the following code in your userland stuff:
+ *
+ * #include <sys/sysmips.h>
+ *
+ * ...
+ * sysmips(MIPS_FIXADE, x);
+ * ...
+ *
+ * The argument x is 0 for disabling software emulation, enabled otherwise.
+ *
+ * Below a little program to play around with this feature.
+ *
+ * #include <stdio.h>
+ * #include <sys/sysmips.h>
+ *
+ * struct foo {
+ * unsigned char bar[8];
+ * };
+ *
+ * main(int argc, char *argv[])
+ * {
+ * struct foo x = {0, 1, 2, 3, 4, 5, 6, 7};
+ * unsigned int *p = (unsigned int *) (x.bar + 3);
+ * int i;
+ *
+ * if (argc > 1)
+ * sysmips(MIPS_FIXADE, atoi(argv[1]));
+ *
+ * printf("*p = %08lx\n", *p);
+ *
+ * *p = 0xdeadface;
+ *
+ * for(i = 0; i <= 7; i++)
+ * printf("%02x ", x.bar[i]);
+ * printf("\n");
+ * }
+ *
+ * Coprocessor loads are not supported; I think this case is unimportant
+ * in the practice.
+ *
+ * TODO: Handle ndc (attempted store to doubleword in uncached memory)
+ * exception for the R6000.
+ * A store crossing a page boundary might be executed only partially.
+ * Undo the partial store in this case.
+ */
+#include <linux/config.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/signal.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+
+#include <asm/asm.h>
+#include <asm/branch.h>
+#include <asm/byteorder.h>
+#include <asm/inst.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+
+#define STR(x) __STR(x)
+#define __STR(x) #x
+
+#ifdef CONFIG_PROC_FS
+unsigned long unaligned_instructions;
+#endif
+
+static inline int emulate_load_store_insn(struct pt_regs *regs,
+ void *addr, unsigned long pc,
+ unsigned long **regptr, unsigned long *newvalue)
+{
+ union mips_instruction insn;
+ unsigned long value;
+ unsigned int res;
+
+ regs->regs[0] = 0;
+ *regptr=NULL;
+
+ /*
+ * This load never faults.
+ */
+ __get_user(insn.word, (unsigned int *)pc);
+
+ switch (insn.i_format.opcode) {
+ /*
+ * These are instructions that a compiler doesn't generate. We
+ * can assume therefore that the code is MIPS-aware and
+ * really buggy. Emulating these instructions would break the
+ * semantics anyway.
+ */
+ case ll_op:
+ case lld_op:
+ case sc_op:
+ case scd_op:
+
+ /*
+ * For these instructions the only way to create an address
+ * error is an attempted access to kernel/supervisor address
+ * space.
+ */
+ case ldl_op:
+ case ldr_op:
+ case lwl_op:
+ case lwr_op:
+ case sdl_op:
+ case sdr_op:
+ case swl_op:
+ case swr_op:
+ case lb_op:
+ case lbu_op:
+ case sb_op:
+ goto sigbus;
+
+ /*
+ * The remaining opcodes are the ones that are really of interest.
+ */
+ case lh_op:
+ if (!access_ok(VERIFY_READ, addr, 2))
+ goto sigbus;
+
+ __asm__ __volatile__ (".set\tnoat\n"
+#ifdef __BIG_ENDIAN
+ "1:\tlb\t%0, 0(%2)\n"
+ "2:\tlbu\t$1, 1(%2)\n\t"
+#endif
+#ifdef __LITTLE_ENDIAN
+ "1:\tlb\t%0, 1(%2)\n"
+ "2:\tlbu\t$1, 0(%2)\n\t"
+#endif
+ "sll\t%0, 0x8\n\t"
+ "or\t%0, $1\n\t"
+ "li\t%1, 0\n"
+ "3:\t.set\tat\n\t"
+ ".section\t.fixup,\"ax\"\n\t"
+ "4:\tli\t%1, %3\n\t"
+ "j\t3b\n\t"
+ ".previous\n\t"
+ ".section\t__ex_table,\"a\"\n\t"
+ STR(PTR)"\t1b, 4b\n\t"
+ STR(PTR)"\t2b, 4b\n\t"
+ ".previous"
+ : "=&r" (value), "=r" (res)
+ : "r" (addr), "i" (-EFAULT));
+ if (res)
+ goto fault;
+ *newvalue = value;
+ *regptr = ®s->regs[insn.i_format.rt];
+ break;
+
+ case lw_op:
+ if (!access_ok(VERIFY_READ, addr, 4))
+ goto sigbus;
+
+ __asm__ __volatile__ (
+#ifdef __BIG_ENDIAN
+ "1:\tlwl\t%0, (%2)\n"
+ "2:\tlwr\t%0, 3(%2)\n\t"
+#endif
+#ifdef __LITTLE_ENDIAN
+ "1:\tlwl\t%0, 3(%2)\n"
+ "2:\tlwr\t%0, (%2)\n\t"
+#endif
+ "li\t%1, 0\n"
+ "3:\t.section\t.fixup,\"ax\"\n\t"
+ "4:\tli\t%1, %3\n\t"
+ "j\t3b\n\t"
+ ".previous\n\t"
+ ".section\t__ex_table,\"a\"\n\t"
+ STR(PTR)"\t1b, 4b\n\t"
+ STR(PTR)"\t2b, 4b\n\t"
+ ".previous"
+ : "=&r" (value), "=r" (res)
+ : "r" (addr), "i" (-EFAULT));
+ if (res)
+ goto fault;
+ *newvalue = value;
+ *regptr = ®s->regs[insn.i_format.rt];
+ break;
+
+ case lhu_op:
+ if (!access_ok(VERIFY_READ, addr, 2))
+ goto sigbus;
+
+ __asm__ __volatile__ (
+ ".set\tnoat\n"
+#ifdef __BIG_ENDIAN
+ "1:\tlbu\t%0, 0(%2)\n"
+ "2:\tlbu\t$1, 1(%2)\n\t"
+#endif
+#ifdef __LITTLE_ENDIAN
+ "1:\tlbu\t%0, 1(%2)\n"
+ "2:\tlbu\t$1, 0(%2)\n\t"
+#endif
+ "sll\t%0, 0x8\n\t"
+ "or\t%0, $1\n\t"
+ "li\t%1, 0\n"
+ "3:\t.set\tat\n\t"
+ ".section\t.fixup,\"ax\"\n\t"
+ "4:\tli\t%1, %3\n\t"
+ "j\t3b\n\t"
+ ".previous\n\t"
+ ".section\t__ex_table,\"a\"\n\t"
+ STR(PTR)"\t1b, 4b\n\t"
+ STR(PTR)"\t2b, 4b\n\t"
+ ".previous"
+ : "=&r" (value), "=r" (res)
+ : "r" (addr), "i" (-EFAULT));
+ if (res)
+ goto fault;
+ *newvalue = value;
+ *regptr = ®s->regs[insn.i_format.rt];
+ break;
+
+ case lwu_op:
+#ifdef CONFIG_MIPS64
+ /*
+ * A 32-bit kernel might be running on a 64-bit processor. But
+ * if we're on a 32-bit processor and an i-cache incoherency
+ * or race makes us see a 64-bit instruction here the sdl/sdr
+ * would blow up, so for now we don't handle unaligned 64-bit
+ * instructions on 32-bit kernels.
+ */
+ if (!access_ok(VERIFY_READ, addr, 4))
+ goto sigbus;
+
+ __asm__ __volatile__ (
+#ifdef __BIG_ENDIAN
+ "1:\tlwl\t%0, (%2)\n"
+ "2:\tlwr\t%0, 3(%2)\n\t"
+#endif
+#ifdef __LITTLE_ENDIAN
+ "1:\tlwl\t%0, 3(%2)\n"
+ "2:\tlwr\t%0, (%2)\n\t"
+#endif
+ "dsll\t%0, %0, 32\n\t"
+ "dsrl\t%0, %0, 32\n\t"
+ "li\t%1, 0\n"
+ "3:\t.section\t.fixup,\"ax\"\n\t"
+ "4:\tli\t%1, %3\n\t"
+ "j\t3b\n\t"
+ ".previous\n\t"
+ ".section\t__ex_table,\"a\"\n\t"
+ STR(PTR)"\t1b, 4b\n\t"
+ STR(PTR)"\t2b, 4b\n\t"
+ ".previous"
+ : "=&r" (value), "=r" (res)
+ : "r" (addr), "i" (-EFAULT));
+ if (res)
+ goto fault;
+ *newvalue = value;
+ *regptr = ®s->regs[insn.i_format.rt];
+ break;
+#endif /* CONFIG_MIPS64 */
+
+ /* Cannot handle 64-bit instructions in 32-bit kernel */
+ goto sigill;
+
+ case ld_op:
+#ifdef CONFIG_MIPS64
+ /*
+ * A 32-bit kernel might be running on a 64-bit processor. But
+ * if we're on a 32-bit processor and an i-cache incoherency
+ * or race makes us see a 64-bit instruction here the sdl/sdr
+ * would blow up, so for now we don't handle unaligned 64-bit
+ * instructions on 32-bit kernels.
+ */
+ if (!access_ok(VERIFY_READ, addr, 8))
+ goto sigbus;
+
+ __asm__ __volatile__ (
+#ifdef __BIG_ENDIAN
+ "1:\tldl\t%0, (%2)\n"
+ "2:\tldr\t%0, 7(%2)\n\t"
+#endif
+#ifdef __LITTLE_ENDIAN
+ "1:\tldl\t%0, 7(%2)\n"
+ "2:\tldr\t%0, (%2)\n\t"
+#endif
+ "li\t%1, 0\n"
+ "3:\t.section\t.fixup,\"ax\"\n\t"
+ "4:\tli\t%1, %3\n\t"
+ "j\t3b\n\t"
+ ".previous\n\t"
+ ".section\t__ex_table,\"a\"\n\t"
+ STR(PTR)"\t1b, 4b\n\t"
+ STR(PTR)"\t2b, 4b\n\t"
+ ".previous"
+ : "=&r" (value), "=r" (res)
+ : "r" (addr), "i" (-EFAULT));
+ if (res)
+ goto fault;
+ *newvalue = value;
+ *regptr = ®s->regs[insn.i_format.rt];
+ break;
+#endif /* CONFIG_MIPS64 */
+
+ /* Cannot handle 64-bit instructions in 32-bit kernel */
+ goto sigill;
+
+ case sh_op:
+ if (!access_ok(VERIFY_WRITE, addr, 2))
+ goto sigbus;
+
+ value = regs->regs[insn.i_format.rt];
+ __asm__ __volatile__ (
+#ifdef __BIG_ENDIAN
+ ".set\tnoat\n"
+ "1:\tsb\t%1, 1(%2)\n\t"
+ "srl\t$1, %1, 0x8\n"
+ "2:\tsb\t$1, 0(%2)\n\t"
+ ".set\tat\n\t"
+#endif
+#ifdef __LITTLE_ENDIAN
+ ".set\tnoat\n"
+ "1:\tsb\t%1, 0(%2)\n\t"
+ "srl\t$1,%1, 0x8\n"
+ "2:\tsb\t$1, 1(%2)\n\t"
+ ".set\tat\n\t"
+#endif
+ "li\t%0, 0\n"
+ "3:\n\t"
+ ".section\t.fixup,\"ax\"\n\t"
+ "4:\tli\t%0, %3\n\t"
+ "j\t3b\n\t"
+ ".previous\n\t"
+ ".section\t__ex_table,\"a\"\n\t"
+ STR(PTR)"\t1b, 4b\n\t"
+ STR(PTR)"\t2b, 4b\n\t"
+ ".previous"
+ : "=r" (res)
+ : "r" (value), "r" (addr), "i" (-EFAULT));
+ if (res)
+ goto fault;
+ break;
+
+ case sw_op:
+ if (!access_ok(VERIFY_WRITE, addr, 4))
+ goto sigbus;
+
+ value = regs->regs[insn.i_format.rt];
+ __asm__ __volatile__ (
+#ifdef __BIG_ENDIAN
+ "1:\tswl\t%1,(%2)\n"
+ "2:\tswr\t%1, 3(%2)\n\t"
+#endif
+#ifdef __LITTLE_ENDIAN
+ "1:\tswl\t%1, 3(%2)\n"
+ "2:\tswr\t%1, (%2)\n\t"
+#endif
+ "li\t%0, 0\n"
+ "3:\n\t"
+ ".section\t.fixup,\"ax\"\n\t"
+ "4:\tli\t%0, %3\n\t"
+ "j\t3b\n\t"
+ ".previous\n\t"
+ ".section\t__ex_table,\"a\"\n\t"
+ STR(PTR)"\t1b, 4b\n\t"
+ STR(PTR)"\t2b, 4b\n\t"
+ ".previous"
+ : "=r" (res)
+ : "r" (value), "r" (addr), "i" (-EFAULT));
+ if (res)
+ goto fault;
+ break;
+
+ case sd_op:
+#ifdef CONFIG_MIPS64
+ /*
+ * A 32-bit kernel might be running on a 64-bit processor. But
+ * if we're on a 32-bit processor and an i-cache incoherency
+ * or race makes us see a 64-bit instruction here the sdl/sdr
+ * would blow up, so for now we don't handle unaligned 64-bit
+ * instructions on 32-bit kernels.
+ */
+ if (!access_ok(VERIFY_WRITE, addr, 8))
+ goto sigbus;
+
+ value = regs->regs[insn.i_format.rt];
+ __asm__ __volatile__ (
+#ifdef __BIG_ENDIAN
+ "1:\tsdl\t%1,(%2)\n"
+ "2:\tsdr\t%1, 7(%2)\n\t"
+#endif
+#ifdef __LITTLE_ENDIAN
+ "1:\tsdl\t%1, 7(%2)\n"
+ "2:\tsdr\t%1, (%2)\n\t"
+#endif
+ "li\t%0, 0\n"
+ "3:\n\t"
+ ".section\t.fixup,\"ax\"\n\t"
+ "4:\tli\t%0, %3\n\t"
+ "j\t3b\n\t"
+ ".previous\n\t"
+ ".section\t__ex_table,\"a\"\n\t"
+ STR(PTR)"\t1b, 4b\n\t"
+ STR(PTR)"\t2b, 4b\n\t"
+ ".previous"
+ : "=r" (res)
+ : "r" (value), "r" (addr), "i" (-EFAULT));
+ if (res)
+ goto fault;
+ break;
+#endif /* CONFIG_MIPS64 */
+
+ /* Cannot handle 64-bit instructions in 32-bit kernel */
+ goto sigill;
+
+ case lwc1_op:
+ case ldc1_op:
+ case swc1_op:
+ case sdc1_op:
+ /*
+ * I herewith declare: this does not happen. So send SIGBUS.
+ */
+ goto sigbus;
+
+ case lwc2_op:
+ case ldc2_op:
+ case swc2_op:
+ case sdc2_op:
+ /*
+ * These are the coprocessor 2 load/stores. The current
+ * implementations don't use cp2 and cp2 should always be
+ * disabled in c0_status. So send SIGILL.
+ * (No longer true: The Sony Praystation uses cp2 for
+ * 3D matrix operations. Dunno if that thingy has a MMU ...)
+ */
+ default:
+ /*
+ * Pheeee... We encountered an yet unknown instruction or
+ * cache coherence problem. Die sucker, die ...
+ */
+ goto sigill;
+ }
+
+#ifdef CONFIG_PROC_FS
+ unaligned_instructions++;
+#endif
+
+ return 0;
+
+fault:
+ /* Did we have an exception handler installed? */
+ if (fixup_exception(regs))
+ return 1;
+
+ die_if_kernel ("Unhandled kernel unaligned access", regs);
+ send_sig(SIGSEGV, current, 1);
+
+ return 0;
+
+sigbus:
+ die_if_kernel("Unhandled kernel unaligned access", regs);
+ send_sig(SIGBUS, current, 1);
+
+ return 0;
+
+sigill:
+ die_if_kernel("Unhandled kernel unaligned access or invalid instruction", regs);
+ send_sig(SIGILL, current, 1);
+
+ return 0;
+}
+
+asmlinkage void do_ade(struct pt_regs *regs)
+{
+ unsigned long *regptr, newval;
+ extern int do_dsemulret(struct pt_regs *);
+ mm_segment_t seg;
+ unsigned long pc;
+
+ /*
+ * Address errors may be deliberately induced by the FPU emulator to
+ * retake control of the CPU after executing the instruction in the
+ * delay slot of an emulated branch.
+ */
+ /* Terminate if exception was recognized as a delay slot return */
+ if (do_dsemulret(regs))
+ return;
+
+ /* Otherwise handle as normal */
+
+ /*
+ * Did we catch a fault trying to load an instruction?
+ * Or are we running in MIPS16 mode?
+ */
+ if ((regs->cp0_badvaddr == regs->cp0_epc) || (regs->cp0_epc & 0x1))
+ goto sigbus;
+
+ pc = exception_epc(regs);
+ if ((current->thread.mflags & MF_FIXADE) == 0)
+ goto sigbus;
+
+ /*
+ * Do branch emulation only if we didn't forward the exception.
+ * This is all so but ugly ...
+ */
+ seg = get_fs();
+ if (!user_mode(regs))
+ set_fs(KERNEL_DS);
+ if (!emulate_load_store_insn(regs, (void *)regs->cp0_badvaddr, pc,
+ ®ptr, &newval)) {
+ compute_return_epc(regs);
+ /*
+ * Now that branch is evaluated, update the dest
+ * register if necessary
+ */
+ if (regptr)
+ *regptr = newval;
+ }
+ set_fs(seg);
+
+ return;
+
+sigbus:
+ die_if_kernel("Kernel unaligned instruction access", regs);
+ force_sig(SIGBUS, current);
+
+ /*
+ * XXX On return from the signal handler we should advance the epc
+ */
+}
diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S
new file mode 100644
index 0000000..e830d78
--- /dev/null
+++ b/arch/mips/kernel/vmlinux.lds.S
@@ -0,0 +1,183 @@
+#include <linux/config.h>
+#include <asm-generic/vmlinux.lds.h>
+
+#undef mips /* CPP really sucks for this job */
+#define mips mips
+OUTPUT_ARCH(mips)
+ENTRY(kernel_entry)
+jiffies = JIFFIES;
+SECTIONS
+{
+#ifdef CONFIG_BOOT_ELF64
+ /* Read-only sections, merged into text segment: */
+ /* . = 0xc000000000000000; */
+
+ /* This is the value for an Origin kernel, taken from an IRIX kernel. */
+ /* . = 0xc00000000001c000; */
+
+ /* Set the vaddr for the text segment to a value
+ >= 0xa800 0000 0001 9000 if no symmon is going to configured
+ >= 0xa800 0000 0030 0000 otherwise */
+
+ /* . = 0xa800000000300000; */
+ /* . = 0xa800000000300000; */
+ . = 0xffffffff80300000;
+#endif
+ . = LOADADDR;
+ /* read-only */
+ _text = .; /* Text and read-only data */
+ .text : {
+ *(.text)
+ SCHED_TEXT
+ LOCK_TEXT
+ *(.fixup)
+ *(.gnu.warning)
+ } =0
+
+ _etext = .; /* End of text section */
+
+ . = ALIGN(16); /* Exception table */
+ __start___ex_table = .;
+ __ex_table : { *(__ex_table) }
+ __stop___ex_table = .;
+
+ __start___dbe_table = .; /* Exception table for data bus errors */
+ __dbe_table : { *(__dbe_table) }
+ __stop___dbe_table = .;
+
+ RODATA
+
+ /* writeable */
+ .data : { /* Data */
+ . = . + DATAOFFSET; /* for CONFIG_MAPPED_KERNEL */
+ *(.data.init_task)
+
+ *(.data)
+
+ /* Align the initial ramdisk image (INITRD) on page boundaries. */
+ . = ALIGN(4096);
+ __rd_start = .;
+ *(.initrd)
+ . = ALIGN(4096);
+ __rd_end = .;
+
+ CONSTRUCTORS
+ }
+ _gp = . + 0x8000;
+ .lit8 : { *(.lit8) }
+ .lit4 : { *(.lit4) }
+ /* We want the small data sections together, so single-instruction offsets
+ can access them all, and initialized data all before uninitialized, so
+ we can shorten the on-disk segment size. */
+ .sdata : { *(.sdata) }
+
+ . = ALIGN(4096);
+ __nosave_begin = .;
+ .data_nosave : { *(.data.nosave) }
+ . = ALIGN(4096);
+ __nosave_end = .;
+
+ . = ALIGN(32);
+ .data.cacheline_aligned : { *(.data.cacheline_aligned) }
+
+ _edata = .; /* End of data section */
+
+ /* will be freed after init */
+ . = ALIGN(4096); /* Init code and data */
+ __init_begin = .;
+ .init.text : {
+ _sinittext = .;
+ *(.init.text)
+ _einittext = .;
+ }
+ .init.data : { *(.init.data) }
+ . = ALIGN(16);
+ __setup_start = .;
+ .init.setup : { *(.init.setup) }
+ __setup_end = .;
+
+ .early_initcall.init : {
+ __earlyinitcall_start = .;
+ *(.initcall.early1.init)
+ }
+ __earlyinitcall_end = .;
+
+ __initcall_start = .;
+ .initcall.init : {
+ *(.initcall1.init)
+ *(.initcall2.init)
+ *(.initcall3.init)
+ *(.initcall4.init)
+ *(.initcall5.init)
+ *(.initcall6.init)
+ *(.initcall7.init)
+ }
+ __initcall_end = .;
+
+ __con_initcall_start = .;
+ .con_initcall.init : { *(.con_initcall.init) }
+ __con_initcall_end = .;
+ SECURITY_INIT
+ . = ALIGN(4096);
+ __initramfs_start = .;
+ .init.ramfs : { *(.init.ramfs) }
+ __initramfs_end = .;
+ . = ALIGN(32);
+ __per_cpu_start = .;
+ .data.percpu : { *(.data.percpu) }
+ __per_cpu_end = .;
+ . = ALIGN(4096);
+ __init_end = .;
+ /* freed after init ends here */
+
+ __bss_start = .; /* BSS */
+ .sbss : {
+ *(.sbss)
+ *(.scommon)
+ }
+ .bss : {
+ *(.bss)
+ *(COMMON)
+ }
+ __bss_stop = .;
+
+ _end = . ;
+
+ /* Sections to be discarded */
+ /DISCARD/ : {
+ *(.exit.text)
+ *(.exit.data)
+ *(.exitcall.exit)
+
+ /* ABI crap starts here */
+ *(.comment)
+ *(.MIPS.options)
+ *(.note)
+ *(.options)
+ *(.pdr)
+ *(.reginfo)
+ *(.mdebug*)
+ }
+
+ /* This is the MIPS specific mdebug section. */
+ .mdebug : { *(.mdebug) }
+ /* These are needed for ELF backends which have not yet been
+ converted to the new style linker. */
+ .stab 0 : { *(.stab) }
+ .stabstr 0 : { *(.stabstr) }
+ /* DWARF debug sections.
+ Symbols in the .debug DWARF section are relative to the beginning of the
+ section so we begin .debug at 0. It's not clear yet what needs to happen
+ for the others. */
+ .debug 0 : { *(.debug) }
+ .debug_srcinfo 0 : { *(.debug_srcinfo) }
+ .debug_aranges 0 : { *(.debug_aranges) }
+ .debug_pubnames 0 : { *(.debug_pubnames) }
+ .debug_sfnames 0 : { *(.debug_sfnames) }
+ .line 0 : { *(.line) }
+ /* These must appear regardless of . */
+ .gptab.sdata : { *(.gptab.data) *(.gptab.sdata) }
+ .gptab.sbss : { *(.gptab.bss) *(.gptab.sbss) }
+ .comment : { *(.comment) }
+ .note : { *(.note) }
+}
diff --git a/arch/mips/lasat/Makefile b/arch/mips/lasat/Makefile
new file mode 100644
index 0000000..0d5aec4
--- /dev/null
+++ b/arch/mips/lasat/Makefile
@@ -0,0 +1,14 @@
+#
+# Makefile for the LASAT specific kernel interface routines under Linux.
+#
+
+obj-y += reset.o setup.o prom.o lasat_board.o \
+ at93c.o interrupt.o lasatIRQ.o
+
+obj-$(CONFIG_LASAT_SYSCTL) += sysctl.o
+obj-$(CONFIG_DS1603) += ds1603.o
+obj-$(CONFIG_PICVUE) += picvue.o
+obj-$(CONFIG_PICVUE_PROC) += picvue_proc.o
+
+clean:
+ make -C image clean
diff --git a/arch/mips/lasat/at93c.c b/arch/mips/lasat/at93c.c
new file mode 100644
index 0000000..f6add04
--- /dev/null
+++ b/arch/mips/lasat/at93c.c
@@ -0,0 +1,148 @@
+/*
+ * Atmel AT93C46 serial eeprom driver
+ *
+ * Brian Murphy <brian.murphy@eicon.com>
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <asm/lasat/lasat.h>
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include "at93c.h"
+
+#define AT93C_ADDR_SHIFT 7
+#define AT93C_ADDR_MAX ((1 << AT93C_ADDR_SHIFT) - 1)
+#define AT93C_RCMD (0x6 << AT93C_ADDR_SHIFT)
+#define AT93C_WCMD (0x5 << AT93C_ADDR_SHIFT)
+#define AT93C_WENCMD 0x260
+#define AT93C_WDSCMD 0x200
+
+struct at93c_defs *at93c;
+
+static void at93c_reg_write(u32 val)
+{
+ *at93c->reg = val;
+}
+
+static u32 at93c_reg_read(void)
+{
+ u32 tmp = *at93c->reg;
+ return tmp;
+}
+
+static u32 at93c_datareg_read(void)
+{
+ u32 tmp = *at93c->rdata_reg;
+ return tmp;
+}
+
+static void at93c_cycle_clk(u32 data)
+{
+ at93c_reg_write(data | at93c->clk);
+ lasat_ndelay(250);
+ at93c_reg_write(data & ~at93c->clk);
+ lasat_ndelay(250);
+}
+
+static void at93c_write_databit(u8 bit)
+{
+ u32 data = at93c_reg_read();
+ if (bit)
+ data |= 1 << at93c->wdata_shift;
+ else
+ data &= ~(1 << at93c->wdata_shift);
+
+ at93c_reg_write(data);
+ lasat_ndelay(100);
+ at93c_cycle_clk(data);
+}
+
+static unsigned int at93c_read_databit(void)
+{
+ u32 data;
+
+ at93c_cycle_clk(at93c_reg_read());
+ data = (at93c_datareg_read() >> at93c->rdata_shift) & 1;
+ return data;
+}
+
+static u8 at93c_read_byte(void)
+{
+ int i;
+ u8 data = 0;
+
+ for (i = 0; i<=7; i++) {
+ data <<= 1;
+ data |= at93c_read_databit();
+ }
+ return data;
+}
+
+static void at93c_write_bits(u32 data, int size)
+{
+ int i;
+ int shift = size - 1;
+ u32 mask = (1 << shift);
+
+ for (i = 0; i < size; i++) {
+ at93c_write_databit((data & mask) >> shift);
+ data <<= 1;
+ }
+}
+
+static void at93c_init_op(void)
+{
+ at93c_reg_write((at93c_reg_read() | at93c->cs) & ~at93c->clk & ~(1 << at93c->rdata_shift));
+ lasat_ndelay(50);
+}
+
+static void at93c_end_op(void)
+{
+ at93c_reg_write(at93c_reg_read() & ~at93c->cs);
+ lasat_ndelay(250);
+}
+
+static void at93c_wait(void)
+{
+ at93c_init_op();
+ while (!at93c_read_databit())
+ ;
+ at93c_end_op();
+};
+
+static void at93c_disable_wp(void)
+{
+ at93c_init_op();
+ at93c_write_bits(AT93C_WENCMD, 10);
+ at93c_end_op();
+}
+
+static void at93c_enable_wp(void)
+{
+ at93c_init_op();
+ at93c_write_bits(AT93C_WDSCMD, 10);
+ at93c_end_op();
+}
+
+u8 at93c_read(u8 addr)
+{
+ u8 byte;
+ at93c_init_op();
+ at93c_write_bits((addr & AT93C_ADDR_MAX)|AT93C_RCMD, 10);
+ byte = at93c_read_byte();
+ at93c_end_op();
+ return byte;
+}
+
+void at93c_write(u8 addr, u8 data)
+{
+ at93c_disable_wp();
+ at93c_init_op();
+ at93c_write_bits((addr & AT93C_ADDR_MAX)|AT93C_WCMD, 10);
+ at93c_write_bits(data, 8);
+ at93c_end_op();
+ at93c_wait();
+ at93c_enable_wp();
+}
diff --git a/arch/mips/lasat/at93c.h b/arch/mips/lasat/at93c.h
new file mode 100644
index 0000000..a912ac2
--- /dev/null
+++ b/arch/mips/lasat/at93c.h
@@ -0,0 +1,18 @@
+/*
+ * Atmel AT93C46 serial eeprom driver
+ *
+ * Brian Murphy <brian.murphy@eicon.com>
+ *
+ */
+
+extern struct at93c_defs {
+ volatile u32 *reg;
+ volatile u32 *rdata_reg;
+ int rdata_shift;
+ int wdata_shift;
+ u32 cs;
+ u32 clk;
+} *at93c;
+
+u8 at93c_read(u8 addr);
+void at93c_write(u8 addr, u8 data);
diff --git a/arch/mips/lasat/ds1603.c b/arch/mips/lasat/ds1603.c
new file mode 100644
index 0000000..7bbf6cf
--- /dev/null
+++ b/arch/mips/lasat/ds1603.c
@@ -0,0 +1,174 @@
+/*
+ * Dallas Semiconductors 1603 RTC driver
+ *
+ * Brian Murphy <brian@murphy.dk>
+ *
+ */
+#include <linux/kernel.h>
+#include <asm/lasat/lasat.h>
+#include <linux/delay.h>
+#include <asm/lasat/ds1603.h>
+
+#include "ds1603.h"
+
+#define READ_TIME_CMD 0x81
+#define SET_TIME_CMD 0x80
+#define TRIMMER_SET_CMD 0xC0
+#define TRIMMER_VALUE_MASK 0x38
+#define TRIMMER_SHIFT 3
+
+struct ds_defs *ds1603 = NULL;
+
+/* HW specific register functions */
+static void rtc_reg_write(unsigned long val)
+{
+ *ds1603->reg = val;
+}
+
+static unsigned long rtc_reg_read(void)
+{
+ unsigned long tmp = *ds1603->reg;
+ return tmp;
+}
+
+static unsigned long rtc_datareg_read(void)
+{
+ unsigned long tmp = *ds1603->data_reg;
+ return tmp;
+}
+
+static void rtc_nrst_high(void)
+{
+ rtc_reg_write(rtc_reg_read() | ds1603->rst);
+}
+
+static void rtc_nrst_low(void)
+{
+ rtc_reg_write(rtc_reg_read() & ~ds1603->rst);
+}
+
+static void rtc_cycle_clock(unsigned long data)
+{
+ data |= ds1603->clk;
+ rtc_reg_write(data);
+ lasat_ndelay(250);
+ if (ds1603->data_reversed)
+ data &= ~ds1603->data;
+ else
+ data |= ds1603->data;
+ data &= ~ds1603->clk;
+ rtc_reg_write(data);
+ lasat_ndelay(250 + ds1603->huge_delay);
+}
+
+static void rtc_write_databit(unsigned int bit)
+{
+ unsigned long data = rtc_reg_read();
+ if (ds1603->data_reversed)
+ bit = !bit;
+ if (bit)
+ data |= ds1603->data;
+ else
+ data &= ~ds1603->data;
+
+ rtc_reg_write(data);
+ lasat_ndelay(50 + ds1603->huge_delay);
+ rtc_cycle_clock(data);
+}
+
+static unsigned int rtc_read_databit(void)
+{
+ unsigned int data;
+
+ data = (rtc_datareg_read() & (1 << ds1603->data_read_shift))
+ >> ds1603->data_read_shift;
+ rtc_cycle_clock(rtc_reg_read());
+ return data;
+}
+
+static void rtc_write_byte(unsigned int byte)
+{
+ int i;
+
+ for (i = 0; i<=7; i++) {
+ rtc_write_databit(byte & 1L);
+ byte >>= 1;
+ }
+}
+
+static void rtc_write_word(unsigned long word)
+{
+ int i;
+
+ for (i = 0; i<=31; i++) {
+ rtc_write_databit(word & 1L);
+ word >>= 1;
+ }
+}
+
+static unsigned long rtc_read_word(void)
+{
+ int i;
+ unsigned long word = 0;
+ unsigned long shift = 0;
+
+ for (i = 0; i<=31; i++) {
+ word |= rtc_read_databit() << shift;
+ shift++;
+ }
+ return word;
+}
+
+static void rtc_init_op(void)
+{
+ rtc_nrst_high();
+
+ rtc_reg_write(rtc_reg_read() & ~ds1603->clk);
+
+ lasat_ndelay(50);
+}
+
+static void rtc_end_op(void)
+{
+ rtc_nrst_low();
+ lasat_ndelay(1000);
+}
+
+/* interface */
+unsigned long ds1603_read(void)
+{
+ unsigned long word;
+ rtc_init_op();
+ rtc_write_byte(READ_TIME_CMD);
+ word = rtc_read_word();
+ rtc_end_op();
+ return word;
+}
+
+int ds1603_set(unsigned long time)
+{
+ rtc_init_op();
+ rtc_write_byte(SET_TIME_CMD);
+ rtc_write_word(time);
+ rtc_end_op();
+
+ return 0;
+}
+
+void ds1603_set_trimmer(unsigned int trimval)
+{
+ rtc_init_op();
+ rtc_write_byte(((trimval << TRIMMER_SHIFT) & TRIMMER_VALUE_MASK)
+ | (TRIMMER_SET_CMD));
+ rtc_end_op();
+}
+
+void ds1603_disable(void)
+{
+ ds1603_set_trimmer(TRIMMER_DISABLE_RTC);
+}
+
+void ds1603_enable(void)
+{
+ ds1603_set_trimmer(TRIMMER_DEFAULT);
+}
diff --git a/arch/mips/lasat/ds1603.h b/arch/mips/lasat/ds1603.h
new file mode 100644
index 0000000..55f3b04
--- /dev/null
+++ b/arch/mips/lasat/ds1603.h
@@ -0,0 +1,33 @@
+/*
+ * Dallas Semiconductors 1603 RTC driver
+ *
+ * Brian Murphy <brian@murphy.dk>
+ *
+ */
+#ifndef __DS1603_H
+#define __DS1603_H
+
+struct ds_defs {
+ volatile u32 *reg;
+ volatile u32 *data_reg;
+ u32 rst;
+ u32 clk;
+ u32 data;
+ u32 data_read_shift;
+ char data_reversed;
+ u32 huge_delay;
+};
+
+extern struct ds_defs *ds1603;
+
+unsigned long ds1603_read(void);
+int ds1603_set(unsigned long);
+void ds1603_set_trimmer(unsigned int);
+void ds1603_enable(void);
+void ds1603_disable(void);
+void ds1603_init(struct ds_defs *);
+
+#define TRIMMER_DEFAULT 3
+#define TRIMMER_DISABLE_RTC 0
+
+#endif
diff --git a/arch/mips/lasat/image/Makefile b/arch/mips/lasat/image/Makefile
new file mode 100644
index 0000000..18b6430
--- /dev/null
+++ b/arch/mips/lasat/image/Makefile
@@ -0,0 +1,53 @@
+#
+# MAKEFILE FOR THE MIPS LINUX BOOTLOADER AND ROM DEBUGGER
+#
+# i-data Networks
+#
+# Author: Thomas Horsten <thh@i-data.com>
+#
+
+ifndef Version
+ Version = "$(USER)-test"
+endif
+
+MKLASATIMG = mklasatimg
+MKLASATIMG_ARCH = mq2,mqpro,sp100,sp200
+KERNEL_IMAGE = $(TOPDIR)/vmlinux
+KERNEL_START = $(shell $(NM) $(KERNEL_IMAGE) | grep " _text" | cut -f1 -d\ )
+KERNEL_ENTRY = $(shell $(NM) $(KERNEL_IMAGE) | grep kernel_entry | cut -f1 -d\ )
+
+LDSCRIPT= -L$(obj) -Tromscript.normal
+
+HEAD_DEFINES := -D_kernel_start=0x$(KERNEL_START) \
+ -D_kernel_entry=0x$(KERNEL_ENTRY) \
+ -D VERSION="\"$(Version)\"" \
+ -D TIMESTAMP=$(shell date +%s)
+
+$(obj)/head.o: $(obj)/head.S $(KERNEL_IMAGE)
+ $(CC) -fno-pic $(HEAD_DEFINES) -I$(TOPDIR)/include -c -o $@ $<
+
+OBJECTS = head.o kImage.o
+
+rom.sw: $(obj)/rom.sw
+
+$(obj)/rom.sw: $(obj)/rom.bin
+ $(MKLASATIMG) -o $@ -k $^ -m $(MKLASATIMG_ARCH)
+
+$(obj)/rom.bin: $(obj)/rom
+ $(OBJCOPY) -O binary -S $^ $@
+
+# Rule to make the bootloader
+$(obj)/rom: $(addprefix $(obj)/,$(OBJECTS))
+ $(LD) $(LDFLAGS) $(LDSCRIPT) -o $@ $^
+
+$(obj)/%.o: $(obj)/%.gz
+ $(LD) -r -o $@ -b binary $<
+
+$(obj)/%.gz: $(obj)/%.bin
+ gzip -cf -9 $< > $@
+
+$(obj)/kImage.bin: $(KERNEL_IMAGE)
+ $(OBJCOPY) -O binary -S $^ $@
+
+clean:
+ rm -f rom rom.bin rom.sw kImage.bin kImage.o
diff --git a/arch/mips/lasat/image/head.S b/arch/mips/lasat/image/head.S
new file mode 100644
index 0000000..426bd7d
--- /dev/null
+++ b/arch/mips/lasat/image/head.S
@@ -0,0 +1,31 @@
+#include <asm/lasat/head.h>
+
+ .text
+ .section .text.start, "ax"
+ .set noreorder
+ .set mips3
+
+ /* Magic words identifying a software image */
+ .word LASAT_K_MAGIC0_VAL
+ .word LASAT_K_MAGIC1_VAL
+
+ /* Image header version */
+ .word 0x00000002
+
+ /* image start and size */
+ .word _image_start
+ .word _image_size
+
+ /* start of kernel and entrypoint in uncompressed image */
+ .word _kernel_start
+ .word _kernel_entry
+
+ /* Here we have room for future flags */
+
+ .org 0x40
+reldate:
+ .word TIMESTAMP
+
+ .org 0x50
+release:
+ .string VERSION
diff --git a/arch/mips/lasat/image/romscript.normal b/arch/mips/lasat/image/romscript.normal
new file mode 100644
index 0000000..ca22336
--- /dev/null
+++ b/arch/mips/lasat/image/romscript.normal
@@ -0,0 +1,22 @@
+OUTPUT_ARCH(mips)
+
+SECTIONS
+{
+ .text :
+ {
+ *(.text.start)
+ }
+
+ /* Data in ROM */
+
+ .data ALIGN(0x10) :
+ {
+ *(.data)
+ }
+ _image_start = ADDR(.data);
+ _image_size = SIZEOF(.data);
+
+ .other : {
+ *(.*)
+ }
+}
diff --git a/arch/mips/lasat/interrupt.c b/arch/mips/lasat/interrupt.c
new file mode 100644
index 0000000..1148a2d
--- /dev/null
+++ b/arch/mips/lasat/interrupt.c
@@ -0,0 +1,160 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Routines for generic manipulation of the interrupts found on the
+ * Lasat boards.
+ */
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/kernel_stat.h>
+
+#include <asm/bootinfo.h>
+#include <asm/irq.h>
+#include <asm/lasat/lasatint.h>
+#include <asm/gdb-stub.h>
+
+static volatile int *lasat_int_status = NULL;
+static volatile int *lasat_int_mask = NULL;
+static volatile int lasat_int_mask_shift;
+
+extern asmlinkage void lasatIRQ(void);
+
+void disable_lasat_irq(unsigned int irq_nr)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+ *lasat_int_mask &= ~(1 << irq_nr) << lasat_int_mask_shift;
+ local_irq_restore(flags);
+}
+
+void enable_lasat_irq(unsigned int irq_nr)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+ *lasat_int_mask |= (1 << irq_nr) << lasat_int_mask_shift;
+ local_irq_restore(flags);
+}
+
+static unsigned int startup_lasat_irq(unsigned int irq)
+{
+ enable_lasat_irq(irq);
+
+ return 0; /* never anything pending */
+}
+
+#define shutdown_lasat_irq disable_lasat_irq
+
+#define mask_and_ack_lasat_irq disable_lasat_irq
+
+static void end_lasat_irq(unsigned int irq)
+{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+ enable_lasat_irq(irq);
+}
+
+static struct hw_interrupt_type lasat_irq_type = {
+ "Lasat",
+ startup_lasat_irq,
+ shutdown_lasat_irq,
+ enable_lasat_irq,
+ disable_lasat_irq,
+ mask_and_ack_lasat_irq,
+ end_lasat_irq,
+ NULL
+};
+
+static inline int ls1bit32(unsigned int x)
+{
+ int b = 31, s;
+
+ s = 16; if (x << 16 == 0) s = 0; b -= s; x <<= s;
+ s = 8; if (x << 8 == 0) s = 0; b -= s; x <<= s;
+ s = 4; if (x << 4 == 0) s = 0; b -= s; x <<= s;
+ s = 2; if (x << 2 == 0) s = 0; b -= s; x <<= s;
+ s = 1; if (x << 1 == 0) s = 0; b -= s;
+
+ return b;
+}
+
+static unsigned long (* get_int_status)(void);
+
+static unsigned long get_int_status_100(void)
+{
+ return *lasat_int_status & *lasat_int_mask;
+}
+
+static unsigned long get_int_status_200(void)
+{
+ unsigned long int_status;
+
+ int_status = *lasat_int_status;
+ int_status &= (int_status >> LASATINT_MASK_SHIFT_200) & 0xffff;
+ return int_status;
+}
+
+void lasat_hw0_irqdispatch(struct pt_regs *regs)
+{
+ unsigned long int_status;
+ int irq;
+
+ int_status = get_int_status();
+
+ /* if int_status == 0, then the interrupt has already been cleared */
+ if (int_status) {
+ irq = ls1bit32(int_status);
+
+ do_IRQ(irq, regs);
+ }
+}
+
+void __init arch_init_irq(void)
+{
+ int i;
+
+ switch (mips_machtype) {
+ case MACH_LASAT_100:
+ lasat_int_status = (void *)LASAT_INT_STATUS_REG_100;
+ lasat_int_mask = (void *)LASAT_INT_MASK_REG_100;
+ lasat_int_mask_shift = LASATINT_MASK_SHIFT_100;
+ get_int_status = get_int_status_100;
+ *lasat_int_mask = 0;
+ break;
+ case MACH_LASAT_200:
+ lasat_int_status = (void *)LASAT_INT_STATUS_REG_200;
+ lasat_int_mask = (void *)LASAT_INT_MASK_REG_200;
+ lasat_int_mask_shift = LASATINT_MASK_SHIFT_200;
+ get_int_status = get_int_status_200;
+ *lasat_int_mask &= 0xffff;
+ break;
+ default:
+ panic("arch_init_irq: mips_machtype incorrect");
+ }
+
+ /* Now safe to set the exception vector. */
+ set_except_vector(0, lasatIRQ);
+
+ for (i = 0; i <= LASATINT_END; i++) {
+ irq_desc[i].status = IRQ_DISABLED;
+ irq_desc[i].action = 0;
+ irq_desc[i].depth = 1;
+ irq_desc[i].handler = &lasat_irq_type;
+ }
+}
diff --git a/arch/mips/lasat/lasatIRQ.S b/arch/mips/lasat/lasatIRQ.S
new file mode 100644
index 0000000..2a2b0d0
--- /dev/null
+++ b/arch/mips/lasat/lasatIRQ.S
@@ -0,0 +1,69 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999, 2000 MIPS Technologies, Inc. All rights reserved.
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Interrupt exception dispatch code.
+ */
+#include <asm/asm.h>
+#include <asm/mipsregs.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+
+ .text
+ .set noreorder
+ .align 5
+ NESTED(lasatIRQ, PT_SIZE, sp)
+ .set noat
+ SAVE_ALL
+ CLI
+ .set at
+ .set noreorder
+
+ mfc0 s0, CP0_CAUSE # get irq mask
+
+ /* First we check for r4k counter/timer IRQ. */
+ andi a0, s0, CAUSEF_IP7
+ beq a0, zero, 1f
+ andi a0, s0, CAUSEF_IP2 # delay slot, check hw0 interrupt
+
+ /* Wheee, a timer interrupt. */
+ li a0, 7
+ jal ll_timer_interrupt
+ move a1, sp
+
+ j ret_from_irq
+ nop
+
+1:
+ /* Wheee, combined hardware level zero interrupt. */
+ jal lasat_hw0_irqdispatch
+ move a0, sp # delay slot
+
+ j ret_from_irq
+ nop # delay slot
+
+1:
+ /*
+ * Here by mistake? This is possible, what can happen is that by the
+ * time we take the exception the IRQ pin goes low, so just leave if
+ * this is the case.
+ */
+ move a1,s0
+ mfc0 a1, CP0_EPC
+
+ j ret_from_irq
+ nop
+ END(lasatIRQ)
diff --git a/arch/mips/lasat/lasat_board.c b/arch/mips/lasat/lasat_board.c
new file mode 100644
index 0000000..8c784bc
--- /dev/null
+++ b/arch/mips/lasat/lasat_board.c
@@ -0,0 +1,277 @@
+/*
+ * Thomas Horsten <thh@lasat.com>
+ * Copyright (C) 2000 LASAT Networks A/S.
+ *
+ * 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.
+ *
+ * Routines specific to the LASAT boards
+ */
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/crc32.h>
+#include <asm/lasat/lasat.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/ctype.h>
+#include <asm/bootinfo.h>
+#include <asm/addrspace.h>
+#include "at93c.h"
+/* New model description table */
+#include "lasat_models.h"
+
+#define EEPROM_CRC(data, len) (~0 ^ crc32(~0, data, len))
+
+struct lasat_info lasat_board_info;
+
+void update_bcastaddr(void);
+
+int EEPROMRead(unsigned int pos, unsigned char *data, int len)
+{
+ int i;
+
+ for (i=0; i<len; i++)
+ *data++ = at93c_read(pos++);
+
+ return 0;
+}
+int EEPROMWrite(unsigned int pos, unsigned char *data, int len)
+{
+ int i;
+
+ for (i=0; i<len; i++)
+ at93c_write(pos++, *data++);
+
+ return 0;
+}
+
+static void init_flash_sizes(void)
+{
+ int i;
+ unsigned long *lb = lasat_board_info.li_flashpart_base;
+ unsigned long *ls = lasat_board_info.li_flashpart_size;
+
+ ls[LASAT_MTD_BOOTLOADER] = 0x40000;
+ ls[LASAT_MTD_SERVICE] = 0xC0000;
+ ls[LASAT_MTD_NORMAL] = 0x100000;
+
+ if (mips_machtype == MACH_LASAT_100) {
+ lasat_board_info.li_flash_base = 0x1e000000;
+
+ lb[LASAT_MTD_BOOTLOADER] = 0x1e400000;
+
+ if (lasat_board_info.li_flash_size > 0x200000) {
+ ls[LASAT_MTD_CONFIG] = 0x100000;
+ ls[LASAT_MTD_FS] = 0x500000;
+ }
+ } else {
+ lasat_board_info.li_flash_base = 0x10000000;
+
+ if (lasat_board_info.li_flash_size < 0x1000000) {
+ lb[LASAT_MTD_BOOTLOADER] = 0x10000000;
+ ls[LASAT_MTD_CONFIG] = 0x100000;
+ if (lasat_board_info.li_flash_size >= 0x400000) {
+ ls[LASAT_MTD_FS] = lasat_board_info.li_flash_size - 0x300000;
+ }
+ }
+ }
+
+ for (i = 1; i < LASAT_MTD_LAST; i++)
+ lb[i] = lb[i-1] + ls[i-1];
+}
+
+int lasat_init_board_info(void)
+{
+ int c;
+ unsigned long crc;
+ unsigned long cfg0, cfg1;
+ const product_info_t *ppi;
+ int i_n_base_models = N_BASE_MODELS;
+ const char * const * i_txt_base_models = txt_base_models;
+ int i_n_prids = N_PRIDS;
+
+ memset(&lasat_board_info, 0, sizeof(lasat_board_info));
+
+ /* First read the EEPROM info */
+ EEPROMRead(0, (unsigned char *)&lasat_board_info.li_eeprom_info,
+ sizeof(struct lasat_eeprom_struct));
+
+ /* Check the CRC */
+ crc = EEPROM_CRC((unsigned char *)(&lasat_board_info.li_eeprom_info),
+ sizeof(struct lasat_eeprom_struct) - 4);
+
+ if (crc != lasat_board_info.li_eeprom_info.crc32) {
+ prom_printf("WARNING...\nWARNING...\nEEPROM CRC does not match calculated, attempting to soldier on...\n");
+ }
+
+ if (lasat_board_info.li_eeprom_info.version != LASAT_EEPROM_VERSION)
+ {
+ prom_printf("WARNING...\nWARNING...\nEEPROM version %d, wanted version %d, attempting to soldier on...\n",
+ (unsigned int)lasat_board_info.li_eeprom_info.version,
+ LASAT_EEPROM_VERSION);
+ }
+
+ cfg0 = lasat_board_info.li_eeprom_info.cfg[0];
+ cfg1 = lasat_board_info.li_eeprom_info.cfg[1];
+
+ if ( LASAT_W0_DSCTYPE(cfg0) != 1) {
+ prom_printf("WARNING...\nWARNING...\nInvalid configuration read from EEPROM, attempting to soldier on...");
+ }
+ /* We have a valid configuration */
+
+ switch (LASAT_W0_SDRAMBANKSZ(cfg0)) {
+ case 0:
+ lasat_board_info.li_memsize = 0x0800000;
+ break;
+ case 1:
+ lasat_board_info.li_memsize = 0x1000000;
+ break;
+ case 2:
+ lasat_board_info.li_memsize = 0x2000000;
+ break;
+ case 3:
+ lasat_board_info.li_memsize = 0x4000000;
+ break;
+ case 4:
+ lasat_board_info.li_memsize = 0x8000000;
+ break;
+ default:
+ lasat_board_info.li_memsize = 0;
+ }
+
+ switch (LASAT_W0_SDRAMBANKS(cfg0)) {
+ case 0:
+ break;
+ case 1:
+ lasat_board_info.li_memsize *= 2;
+ break;
+ default:
+ break;
+ }
+
+ switch (LASAT_W0_BUSSPEED(cfg0)) {
+ case 0x0:
+ lasat_board_info.li_bus_hz = 60000000;
+ break;
+ case 0x1:
+ lasat_board_info.li_bus_hz = 66000000;
+ break;
+ case 0x2:
+ lasat_board_info.li_bus_hz = 66666667;
+ break;
+ case 0x3:
+ lasat_board_info.li_bus_hz = 80000000;
+ break;
+ case 0x4:
+ lasat_board_info.li_bus_hz = 83333333;
+ break;
+ case 0x5:
+ lasat_board_info.li_bus_hz = 100000000;
+ break;
+ }
+
+ switch (LASAT_W0_CPUCLK(cfg0)) {
+ case 0x0:
+ lasat_board_info.li_cpu_hz =
+ lasat_board_info.li_bus_hz;
+ break;
+ case 0x1:
+ lasat_board_info.li_cpu_hz =
+ lasat_board_info.li_bus_hz +
+ (lasat_board_info.li_bus_hz >> 1);
+ break;
+ case 0x2:
+ lasat_board_info.li_cpu_hz =
+ lasat_board_info.li_bus_hz +
+ lasat_board_info.li_bus_hz;
+ break;
+ case 0x3:
+ lasat_board_info.li_cpu_hz =
+ lasat_board_info.li_bus_hz +
+ lasat_board_info.li_bus_hz +
+ (lasat_board_info.li_bus_hz >> 1);
+ break;
+ case 0x4:
+ lasat_board_info.li_cpu_hz =
+ lasat_board_info.li_bus_hz +
+ lasat_board_info.li_bus_hz +
+ lasat_board_info.li_bus_hz;
+ break;
+ }
+
+ /* Flash size */
+ switch (LASAT_W1_FLASHSIZE(cfg1)) {
+ case 0:
+ lasat_board_info.li_flash_size = 0x200000;
+ break;
+ case 1:
+ lasat_board_info.li_flash_size = 0x400000;
+ break;
+ case 2:
+ lasat_board_info.li_flash_size = 0x800000;
+ break;
+ case 3:
+ lasat_board_info.li_flash_size = 0x1000000;
+ break;
+ case 4:
+ lasat_board_info.li_flash_size = 0x2000000;
+ break;
+ }
+
+ init_flash_sizes();
+
+ lasat_board_info.li_bmid = LASAT_W0_BMID(cfg0);
+ lasat_board_info.li_prid = lasat_board_info.li_eeprom_info.prid;
+ if (lasat_board_info.li_prid == 0xffff || lasat_board_info.li_prid == 0)
+ lasat_board_info.li_prid = lasat_board_info.li_bmid;
+
+ /* Base model stuff */
+ if (lasat_board_info.li_bmid > i_n_base_models)
+ lasat_board_info.li_bmid = i_n_base_models;
+ strcpy(lasat_board_info.li_bmstr, i_txt_base_models[lasat_board_info.li_bmid]);
+
+ /* Product ID dependent values */
+ c = lasat_board_info.li_prid;
+ if (c >= i_n_prids) {
+ strcpy(lasat_board_info.li_namestr, "Unknown Model");
+ strcpy(lasat_board_info.li_typestr, "Unknown Type");
+ } else {
+ ppi = &vendor_info_table[0].vi_product_info[c];
+ strcpy(lasat_board_info.li_namestr, ppi->pi_name);
+ if (ppi->pi_type)
+ strcpy(lasat_board_info.li_typestr, ppi->pi_type);
+ else
+ sprintf(lasat_board_info.li_typestr, "%d",10*c);
+ }
+
+#if defined(CONFIG_INET) && defined(CONFIG_SYSCTL)
+ update_bcastaddr();
+#endif
+
+ return 0;
+}
+
+void lasat_write_eeprom_info(void)
+{
+ unsigned long crc;
+
+ /* Generate the CRC */
+ crc = EEPROM_CRC((unsigned char *)(&lasat_board_info.li_eeprom_info),
+ sizeof(struct lasat_eeprom_struct) - 4);
+ lasat_board_info.li_eeprom_info.crc32 = crc;
+
+ /* Write the EEPROM info */
+ EEPROMWrite(0, (unsigned char *)&lasat_board_info.li_eeprom_info,
+ sizeof(struct lasat_eeprom_struct));
+}
+
diff --git a/arch/mips/lasat/lasat_models.h b/arch/mips/lasat/lasat_models.h
new file mode 100644
index 0000000..ae0c5d0
--- /dev/null
+++ b/arch/mips/lasat/lasat_models.h
@@ -0,0 +1,63 @@
+/*
+ * Model description tables
+ */
+
+typedef struct product_info_t {
+ const char *pi_name;
+ const char *pi_type;
+} product_info_t;
+
+typedef struct vendor_info_t {
+ const char *vi_name;
+ const product_info_t *vi_product_info;
+} vendor_info_t;
+
+/*
+ * Base models
+ */
+static const char * const txt_base_models[] = {
+ "MQ 2", "MQ Pro", "SP 25", "SP 50", "SP 100", "SP 5000", "SP 7000", "SP 1000", "Unknown"
+};
+#define N_BASE_MODELS (sizeof(txt_base_models)/sizeof(char*)-1)
+
+/*
+ * Eicon Networks
+ */
+static const char txt_en_mq[] = "Masquerade";
+static const char txt_en_sp[] = "Safepipe";
+
+static const product_info_t product_info_eicon[] = {
+ { txt_en_mq, "II" }, /* 0 */
+ { txt_en_mq, "Pro" }, /* 1 */
+ { txt_en_sp, "25" }, /* 2 */
+ { txt_en_sp, "50" }, /* 3 */
+ { txt_en_sp, "100" }, /* 4 */
+ { txt_en_sp, "5000" }, /* 5 */
+ { txt_en_sp, "7000" }, /* 6 */
+ { txt_en_sp, "30" }, /* 7 */
+ { txt_en_sp, "5100" }, /* 8 */
+ { txt_en_sp, "7100" }, /* 9 */
+ { txt_en_sp, "1110" }, /* 10 */
+ { txt_en_sp, "3020" }, /* 11 */
+ { txt_en_sp, "3030" }, /* 12 */
+ { txt_en_sp, "5020" }, /* 13 */
+ { txt_en_sp, "5030" }, /* 14 */
+ { txt_en_sp, "1120" }, /* 15 */
+ { txt_en_sp, "1130" }, /* 16 */
+ { txt_en_sp, "6010" }, /* 17 */
+ { txt_en_sp, "6110" }, /* 18 */
+ { txt_en_sp, "6210" }, /* 19 */
+ { txt_en_sp, "1020" }, /* 20 */
+ { txt_en_sp, "1040" }, /* 21 */
+ { txt_en_sp, "1050" }, /* 22 */
+ { txt_en_sp, "1060" }, /* 23 */
+};
+#define N_PRIDS (sizeof(product_info_eicon)/sizeof(product_info_t))
+
+/*
+ * The vendor table
+ */
+static vendor_info_t const vendor_info_table[] = {
+ { "Eicon Networks", product_info_eicon },
+};
+#define N_VENDORS (sizeof(vendor_info_table)/sizeof(vendor_info_t))
diff --git a/arch/mips/lasat/picvue.c b/arch/mips/lasat/picvue.c
new file mode 100644
index 0000000..5637cd1
--- /dev/null
+++ b/arch/mips/lasat/picvue.c
@@ -0,0 +1,240 @@
+/*
+ * Picvue PVC160206 display driver
+ *
+ * Brian Murphy <brian@murphy.dk>
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <asm/bootinfo.h>
+#include <asm/lasat/lasat.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+
+#include "picvue.h"
+
+#define PVC_BUSY 0x80
+#define PVC_NLINES 2
+#define PVC_DISPMEM 80
+#define PVC_LINELEN PVC_DISPMEM / PVC_NLINES
+
+struct pvc_defs *picvue = NULL;
+
+DECLARE_MUTEX(pvc_sem);
+
+static void pvc_reg_write(u32 val)
+{
+ *picvue->reg = val;
+}
+
+static u32 pvc_reg_read(void)
+{
+ u32 tmp = *picvue->reg;
+ return tmp;
+}
+
+static void pvc_write_byte(u32 data, u8 byte)
+{
+ data |= picvue->e;
+ pvc_reg_write(data);
+ data &= ~picvue->data_mask;
+ data |= byte << picvue->data_shift;
+ pvc_reg_write(data);
+ ndelay(220);
+ pvc_reg_write(data & ~picvue->e);
+ ndelay(220);
+}
+
+static u8 pvc_read_byte(u32 data)
+{
+ u8 byte;
+
+ data |= picvue->e;
+ pvc_reg_write(data);
+ ndelay(220);
+ byte = (pvc_reg_read() & picvue->data_mask) >> picvue->data_shift;
+ data &= ~picvue->e;
+ pvc_reg_write(data);
+ ndelay(220);
+ return byte;
+}
+
+static u8 pvc_read_data(void)
+{
+ u32 data = pvc_reg_read();
+ u8 byte;
+ data |= picvue->rw;
+ data &= ~picvue->rs;
+ pvc_reg_write(data);
+ ndelay(40);
+ byte = pvc_read_byte(data);
+ data |= picvue->rs;
+ pvc_reg_write(data);
+ return byte;
+}
+
+#define TIMEOUT 1000
+static int pvc_wait(void)
+{
+ int i = TIMEOUT;
+ int err = 0;
+
+ while ((pvc_read_data() & PVC_BUSY) && i)
+ i--;
+ if (i == 0)
+ err = -ETIME;
+
+ return err;
+}
+
+#define MODE_INST 0
+#define MODE_DATA 1
+static void pvc_write(u8 byte, int mode)
+{
+ u32 data = pvc_reg_read();
+ data &= ~picvue->rw;
+ if (mode == MODE_DATA)
+ data |= picvue->rs;
+ else
+ data &= ~picvue->rs;
+ pvc_reg_write(data);
+ ndelay(40);
+ pvc_write_byte(data, byte);
+ if (mode == MODE_DATA)
+ data &= ~picvue->rs;
+ else
+ data |= picvue->rs;
+ pvc_reg_write(data);
+ pvc_wait();
+}
+
+void pvc_write_string(const unsigned char *str, u8 addr, int line)
+{
+ int i = 0;
+
+ if (line > 0 && (PVC_NLINES > 1))
+ addr += 0x40 * line;
+ pvc_write(0x80 | addr, MODE_INST);
+
+ while (*str != 0 && i < PVC_LINELEN) {
+ pvc_write(*str++, MODE_DATA);
+ i++;
+ }
+}
+
+void pvc_write_string_centered(const unsigned char *str, int line)
+{
+ int len = strlen(str);
+ u8 addr;
+
+ if (len > PVC_VISIBLE_CHARS)
+ addr = 0;
+ else
+ addr = (PVC_VISIBLE_CHARS - strlen(str))/2;
+
+ pvc_write_string(str, addr, line);
+}
+
+void pvc_dump_string(const unsigned char *str)
+{
+ int len = strlen(str);
+
+ pvc_write_string(str, 0, 0);
+ if (len > PVC_VISIBLE_CHARS)
+ pvc_write_string(&str[PVC_VISIBLE_CHARS], 0, 1);
+}
+
+#define BM_SIZE 8
+#define MAX_PROGRAMMABLE_CHARS 8
+int pvc_program_cg(int charnum, u8 bitmap[BM_SIZE])
+{
+ int i;
+ int addr;
+
+ if (charnum > MAX_PROGRAMMABLE_CHARS)
+ return -ENOENT;
+
+ addr = charnum * 8;
+ pvc_write(0x40 | addr, MODE_INST);
+
+ for (i=0; i<BM_SIZE; i++)
+ pvc_write(bitmap[i], MODE_DATA);
+ return 0;
+}
+
+#define FUNC_SET_CMD 0x20
+#define EIGHT_BYTE (1 << 4)
+#define FOUR_BYTE 0
+#define TWO_LINES (1 << 3)
+#define ONE_LINE 0
+#define LARGE_FONT (1 << 2)
+#define SMALL_FONT 0
+static void pvc_funcset(u8 cmd)
+{
+ pvc_write(FUNC_SET_CMD | (cmd & (EIGHT_BYTE|TWO_LINES|LARGE_FONT)), MODE_INST);
+}
+
+#define ENTRYMODE_CMD 0x4
+#define AUTO_INC (1 << 1)
+#define AUTO_DEC 0
+#define CURSOR_FOLLOWS_DISP (1 << 0)
+static void pvc_entrymode(u8 cmd)
+{
+ pvc_write(ENTRYMODE_CMD | (cmd & (AUTO_INC|CURSOR_FOLLOWS_DISP)), MODE_INST);
+}
+
+#define DISP_CNT_CMD 0x08
+#define DISP_OFF 0
+#define DISP_ON (1 << 2)
+#define CUR_ON (1 << 1)
+#define CUR_BLINK (1 << 0)
+void pvc_dispcnt(u8 cmd)
+{
+ pvc_write(DISP_CNT_CMD | (cmd & (DISP_ON|CUR_ON|CUR_BLINK)), MODE_INST);
+}
+
+#define MOVE_CMD 0x10
+#define DISPLAY (1 << 3)
+#define CURSOR 0
+#define RIGHT (1 << 2)
+#define LEFT 0
+void pvc_move(u8 cmd)
+{
+ pvc_write(MOVE_CMD | (cmd & (DISPLAY|RIGHT)), MODE_INST);
+}
+
+#define CLEAR_CMD 0x1
+void pvc_clear(void)
+{
+ pvc_write(CLEAR_CMD, MODE_INST);
+}
+
+#define HOME_CMD 0x2
+void pvc_home(void)
+{
+ pvc_write(HOME_CMD, MODE_INST);
+}
+
+int pvc_init(void)
+{
+ u8 cmd = EIGHT_BYTE;
+
+ if (PVC_NLINES == 2)
+ cmd |= (SMALL_FONT|TWO_LINES);
+ else
+ cmd |= (LARGE_FONT|ONE_LINE);
+ pvc_funcset(cmd);
+ pvc_dispcnt(DISP_ON);
+ pvc_entrymode(AUTO_INC);
+
+ pvc_clear();
+ pvc_write_string_centered("Display", 0);
+ pvc_write_string_centered("Initialized", 1);
+
+ return 0;
+}
+
+module_init(pvc_init);
+MODULE_LICENSE("GPL");
diff --git a/arch/mips/lasat/picvue.h b/arch/mips/lasat/picvue.h
new file mode 100644
index 0000000..74a3903
--- /dev/null
+++ b/arch/mips/lasat/picvue.h
@@ -0,0 +1,48 @@
+/*
+ * Picvue PVC160206 display driver
+ *
+ * Brian Murphy <brian.murphy@eicon.com>
+ *
+ */
+#include <asm/semaphore.h>
+
+struct pvc_defs {
+ volatile u32 *reg;
+ u32 data_shift;
+ u32 data_mask;
+ u32 e;
+ u32 rw;
+ u32 rs;
+};
+
+extern struct pvc_defs *picvue;
+
+#define PVC_NLINES 2
+#define PVC_DISPMEM 80
+#define PVC_LINELEN PVC_DISPMEM / PVC_NLINES
+#define PVC_VISIBLE_CHARS 16
+
+void pvc_write_string(const unsigned char *str, u8 addr, int line);
+void pvc_write_string_centered(const unsigned char *str, int line);
+void pvc_dump_string(const unsigned char *str);
+
+#define BM_SIZE 8
+#define MAX_PROGRAMMABLE_CHARS 8
+int pvc_program_cg(int charnum, u8 bitmap[BM_SIZE]);
+
+void pvc_dispcnt(u8 cmd);
+#define DISP_OFF 0
+#define DISP_ON (1 << 2)
+#define CUR_ON (1 << 1)
+#define CUR_BLINK (1 << 0)
+
+void pvc_move(u8 cmd);
+#define DISPLAY (1 << 3)
+#define CURSOR 0
+#define RIGHT (1 << 2)
+#define LEFT 0
+
+void pvc_clear(void);
+void pvc_home(void);
+
+extern struct semaphore pvc_sem;
diff --git a/arch/mips/lasat/picvue_proc.c b/arch/mips/lasat/picvue_proc.c
new file mode 100644
index 0000000..eaa2b46
--- /dev/null
+++ b/arch/mips/lasat/picvue_proc.c
@@ -0,0 +1,186 @@
+/*
+ * Picvue PVC160206 display driver
+ *
+ * Brian Murphy <brian.murphy@eicon.com>
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+
+#include <linux/proc_fs.h>
+#include <linux/interrupt.h>
+
+#include <linux/timer.h>
+
+#include "picvue.h"
+
+static char pvc_lines[PVC_NLINES][PVC_LINELEN+1];
+static int pvc_linedata[PVC_NLINES];
+static struct proc_dir_entry *pvc_display_dir;
+static char *pvc_linename[PVC_NLINES] = {"line1", "line2"};
+#define DISPLAY_DIR_NAME "display"
+static int scroll_dir = 0, scroll_interval = 0;
+
+static struct timer_list timer;
+
+static void pvc_display(unsigned long data) {
+ int i;
+
+ pvc_clear();
+ for (i=0; i<PVC_NLINES; i++)
+ pvc_write_string(pvc_lines[i], 0, i);
+}
+
+static DECLARE_TASKLET(pvc_display_tasklet, &pvc_display, 0);
+
+static int pvc_proc_read_line(char *page, char **start,
+ off_t off, int count,
+ int *eof, void *data)
+{
+ char *origpage = page;
+ int lineno = *(int *)data;
+
+ if (lineno < 0 || lineno > PVC_NLINES) {
+ printk("proc_read_line: invalid lineno %d\n", lineno);
+ return 0;
+ }
+
+ down(&pvc_sem);
+ page += sprintf(page, "%s\n", pvc_lines[lineno]);
+ up(&pvc_sem);
+
+ return page - origpage;
+}
+
+static int pvc_proc_write_line(struct file *file, const char *buffer,
+ unsigned long count, void *data)
+{
+ int origcount = count;
+ int lineno = *(int *)data;
+
+ if (lineno < 0 || lineno > PVC_NLINES) {
+ printk("proc_write_line: invalid lineno %d\n", lineno);
+ return origcount;
+ }
+
+ if (count > PVC_LINELEN)
+ count = PVC_LINELEN;
+
+ if (buffer[count-1] == '\n')
+ count--;
+
+ down(&pvc_sem);
+ strncpy(pvc_lines[lineno], buffer, count);
+ pvc_lines[lineno][count] = '\0';
+ up(&pvc_sem);
+
+ tasklet_schedule(&pvc_display_tasklet);
+
+ return origcount;
+}
+
+static int pvc_proc_write_scroll(struct file *file, const char *buffer,
+ unsigned long count, void *data)
+{
+ int origcount = count;
+ int cmd = simple_strtol(buffer, NULL, 10);
+
+ down(&pvc_sem);
+ if (scroll_interval != 0)
+ del_timer(&timer);
+
+ if (cmd == 0) {
+ scroll_dir = 0;
+ scroll_interval = 0;
+ } else {
+ if (cmd < 0) {
+ scroll_dir = -1;
+ scroll_interval = -cmd;
+ } else {
+ scroll_dir = 1;
+ scroll_interval = cmd;
+ }
+ add_timer(&timer);
+ }
+ up(&pvc_sem);
+
+ return origcount;
+}
+
+static int pvc_proc_read_scroll(char *page, char **start,
+ off_t off, int count,
+ int *eof, void *data)
+{
+ char *origpage = page;
+
+ down(&pvc_sem);
+ page += sprintf(page, "%d\n", scroll_dir * scroll_interval);
+ up(&pvc_sem);
+
+ return page - origpage;
+}
+
+
+void pvc_proc_timerfunc(unsigned long data)
+{
+ if (scroll_dir < 0)
+ pvc_move(DISPLAY|RIGHT);
+ else if (scroll_dir > 0)
+ pvc_move(DISPLAY|LEFT);
+
+ timer.expires = jiffies + scroll_interval;
+ add_timer(&timer);
+}
+
+static void pvc_proc_cleanup(void)
+{
+ int i;
+ for (i=0; i<PVC_NLINES; i++)
+ remove_proc_entry(pvc_linename[i], pvc_display_dir);
+ remove_proc_entry("scroll", pvc_display_dir);
+ remove_proc_entry(DISPLAY_DIR_NAME, NULL);
+
+ del_timer(&timer);
+}
+
+static int __init pvc_proc_init(void)
+{
+ struct proc_dir_entry *proc_entry;
+ int i;
+
+ pvc_display_dir = proc_mkdir(DISPLAY_DIR_NAME, NULL);
+ if (pvc_display_dir == NULL)
+ goto error;
+
+ for (i=0; i<PVC_NLINES; i++) {
+ strcpy(pvc_lines[i], "");
+ pvc_linedata[i] = i;
+ }
+ for (i=0; i<PVC_NLINES; i++) {
+ proc_entry = create_proc_entry(pvc_linename[i], 0644, pvc_display_dir);
+ if (proc_entry == NULL)
+ goto error;
+ proc_entry->read_proc = pvc_proc_read_line;
+ proc_entry->write_proc = pvc_proc_write_line;
+ proc_entry->data = &pvc_linedata[i];
+ }
+ proc_entry = create_proc_entry("scroll", 0644, pvc_display_dir);
+ if (proc_entry == NULL)
+ goto error;
+ proc_entry->write_proc = pvc_proc_write_scroll;
+ proc_entry->read_proc = pvc_proc_read_scroll;
+
+ init_timer(&timer);
+ timer.function = pvc_proc_timerfunc;
+
+ return 0;
+error:
+ pvc_proc_cleanup();
+ return -ENOMEM;
+}
+
+module_init(pvc_proc_init);
+module_exit(pvc_proc_cleanup);
+MODULE_LICENSE("GPL");
diff --git a/arch/mips/lasat/prom.c b/arch/mips/lasat/prom.c
new file mode 100644
index 0000000..ca62881
--- /dev/null
+++ b/arch/mips/lasat/prom.c
@@ -0,0 +1,143 @@
+/*
+ * PROM interface routines.
+ */
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/ctype.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/bootmem.h>
+#include <linux/ioport.h>
+#include <asm/bootinfo.h>
+#include <asm/lasat/lasat.h>
+#include <asm/cpu.h>
+
+#include "at93c.h"
+#include <asm/lasat/eeprom.h>
+#include "prom.h"
+
+#define RESET_VECTOR 0xbfc00000
+#define PROM_JUMP_TABLE_ENTRY(n) (*((u32 *)(RESET_VECTOR + 0x20) + n))
+#define PROM_DISPLAY_ADDR PROM_JUMP_TABLE_ENTRY(0)
+#define PROM_PUTC_ADDR PROM_JUMP_TABLE_ENTRY(1)
+#define PROM_MONITOR_ADDR PROM_JUMP_TABLE_ENTRY(2)
+
+static void null_prom_printf(const char * fmt, ...)
+{
+}
+
+static void null_prom_display(const char *string, int pos, int clear)
+{
+}
+
+static void null_prom_monitor(void)
+{
+}
+
+static void null_prom_putc(char c)
+{
+}
+
+/* these are functions provided by the bootloader */
+static void (* prom_putc)(char c) = null_prom_putc;
+void (* prom_printf)(const char * fmt, ...) = null_prom_printf;
+void (* prom_display)(const char *string, int pos, int clear) =
+ null_prom_display;
+void (* prom_monitor)(void) = null_prom_monitor;
+
+unsigned int lasat_ndelay_divider;
+
+#define PROM_PRINTFBUF_SIZE 256
+static char prom_printfbuf[PROM_PRINTFBUF_SIZE];
+
+static void real_prom_printf(const char * fmt, ...)
+{
+ va_list ap;
+ int len;
+ char *c = prom_printfbuf;
+ int i;
+
+ va_start(ap, fmt);
+ len = vsnprintf(prom_printfbuf, PROM_PRINTFBUF_SIZE, fmt, ap);
+ va_end(ap);
+
+ /* output overflowed the buffer */
+ if (len < 0 || len > PROM_PRINTFBUF_SIZE)
+ len = PROM_PRINTFBUF_SIZE;
+
+ for (i=0; i < len; i++) {
+ if (*c == '\n')
+ prom_putc('\r');
+ prom_putc(*c++);
+ }
+}
+
+static void setup_prom_vectors(void)
+{
+ u32 version = *(u32 *)(RESET_VECTOR + 0x90);
+
+ if (version >= 307) {
+ prom_display = (void *)PROM_DISPLAY_ADDR;
+ prom_putc = (void *)PROM_PUTC_ADDR;
+ prom_printf = real_prom_printf;
+ prom_monitor = (void *)PROM_MONITOR_ADDR;
+ }
+ prom_printf("prom vectors set up\n");
+}
+
+static struct at93c_defs at93c_defs[N_MACHTYPES] = {
+ {(void *)AT93C_REG_100, (void *)AT93C_RDATA_REG_100, AT93C_RDATA_SHIFT_100,
+ AT93C_WDATA_SHIFT_100, AT93C_CS_M_100, AT93C_CLK_M_100},
+ {(void *)AT93C_REG_200, (void *)AT93C_RDATA_REG_200, AT93C_RDATA_SHIFT_200,
+ AT93C_WDATA_SHIFT_200, AT93C_CS_M_200, AT93C_CLK_M_200},
+};
+
+void __init prom_init(void)
+{
+ int argc = fw_arg0;
+ char **argv = (char **) fw_arg1;
+
+ setup_prom_vectors();
+
+ if (current_cpu_data.cputype == CPU_R5000) {
+ prom_printf("LASAT 200 board\n");
+ mips_machtype = MACH_LASAT_200;
+ lasat_ndelay_divider = LASAT_200_DIVIDER;
+ } else {
+ prom_printf("LASAT 100 board\n");
+ mips_machtype = MACH_LASAT_100;
+ lasat_ndelay_divider = LASAT_100_DIVIDER;
+ }
+
+ at93c = &at93c_defs[mips_machtype];
+
+ lasat_init_board_info(); /* Read info from EEPROM */
+
+ mips_machgroup = MACH_GROUP_LASAT;
+
+ /* Get the command line */
+ if (argc > 0) {
+ strncpy(arcs_cmdline, argv[0], CL_SIZE-1);
+ arcs_cmdline[CL_SIZE-1] = '\0';
+ }
+
+ /* Set the I/O base address */
+ set_io_port_base(KSEG1);
+
+ /* Set memory regions */
+ ioport_resource.start = 0;
+ ioport_resource.end = 0xffffffff; /* Wrong, fixme. */
+
+ add_memory_region(0, lasat_board_info.li_memsize, BOOT_MEM_RAM);
+}
+
+unsigned long __init prom_free_prom_memory(void)
+{
+ return 0;
+}
+
+const char *get_system_type(void)
+{
+ return lasat_board_info.li_bmstr;
+}
diff --git a/arch/mips/lasat/prom.h b/arch/mips/lasat/prom.h
new file mode 100644
index 0000000..07be7bf
--- /dev/null
+++ b/arch/mips/lasat/prom.h
@@ -0,0 +1,6 @@
+#ifndef PROM_H
+#define PROM_H
+extern void (* prom_display)(const char *string, int pos, int clear);
+extern void (* prom_monitor)(void);
+extern void (* prom_printf)(const char * fmt, ...);
+#endif
diff --git a/arch/mips/lasat/reset.c b/arch/mips/lasat/reset.c
new file mode 100644
index 0000000..37e4912
--- /dev/null
+++ b/arch/mips/lasat/reset.c
@@ -0,0 +1,67 @@
+/*
+ * Thomas Horsten <thh@lasat.com>
+ * Copyright (C) 2000 LASAT Networks A/S.
+ *
+ * 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.
+ *
+ * Reset the LASAT board.
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <asm/reboot.h>
+#include <asm/system.h>
+#include <asm/lasat/lasat.h>
+#include "picvue.h"
+#include "prom.h"
+
+static void lasat_machine_restart(char *command);
+static void lasat_machine_halt(void);
+
+/* Used to set machine to boot in service mode via /proc interface */
+int lasat_boot_to_service = 0;
+
+static void lasat_machine_restart(char *command)
+{
+ local_irq_disable();
+
+ if (lasat_boot_to_service) {
+ printk("machine_restart: Rebooting to service mode\n");
+ *(volatile unsigned int *)0xa0000024 = 0xdeadbeef;
+ *(volatile unsigned int *)0xa00000fc = 0xfedeabba;
+ }
+ *lasat_misc->reset_reg = 0xbedead;
+ for (;;) ;
+}
+
+#define MESSAGE "System halted"
+static void lasat_machine_halt(void)
+{
+ local_irq_disable();
+
+ /* Disable interrupts and loop forever */
+ printk(KERN_NOTICE MESSAGE "\n");
+#ifdef CONFIG_PICVUE
+ pvc_clear();
+ pvc_write_string(MESSAGE, 0, 0);
+#endif
+ prom_monitor();
+ for (;;) ;
+}
+
+void lasat_reboot_setup(void)
+{
+ _machine_restart = lasat_machine_restart;
+ _machine_halt = lasat_machine_halt;
+ _machine_power_off = lasat_machine_halt;
+}
diff --git a/arch/mips/lasat/setup.c b/arch/mips/lasat/setup.c
new file mode 100644
index 0000000..e371ed5
--- /dev/null
+++ b/arch/mips/lasat/setup.c
@@ -0,0 +1,192 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999 MIPS Technologies, Inc. All rights reserved.
+ *
+ * Thomas Horsten <thh@lasat.com>
+ * Copyright (C) 2000 LASAT Networks A/S.
+ *
+ * Brian Murphy <brian@murphy.dk>
+ *
+ * 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.
+ *
+ * Lasat specific setup.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/tty.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+
+#include <asm/time.h>
+#include <asm/cpu.h>
+#include <asm/bootinfo.h>
+#include <asm/irq.h>
+#include <asm/serial.h>
+#include <asm/lasat/lasat.h>
+#include <asm/lasat/serial.h>
+
+#ifdef CONFIG_PICVUE
+#include <linux/notifier.h>
+#endif
+
+#include "ds1603.h"
+#include <asm/lasat/ds1603.h>
+#include <asm/lasat/picvue.h>
+#include <asm/lasat/eeprom.h>
+
+#include "prom.h"
+
+int lasat_command_line = 0;
+void lasatint_init(void);
+
+extern void lasat_reboot_setup(void);
+extern void pcisetup(void);
+extern void edhac_init(void *, void *, void *);
+extern void addrflt_init(void);
+
+struct lasat_misc lasat_misc_info[N_MACHTYPES] = {
+ {(void *)KSEG1ADDR(0x1c840000), (void *)KSEG1ADDR(0x1c800000), 2},
+ {(void *)KSEG1ADDR(0x11080000), (void *)KSEG1ADDR(0x11000000), 6}
+};
+
+struct lasat_misc *lasat_misc = NULL;
+
+#ifdef CONFIG_DS1603
+static struct ds_defs ds_defs[N_MACHTYPES] = {
+ { (void *)DS1603_REG_100, (void *)DS1603_REG_100,
+ DS1603_RST_100, DS1603_CLK_100, DS1603_DATA_100,
+ DS1603_DATA_SHIFT_100, 0, 0 },
+ { (void *)DS1603_REG_200, (void *)DS1603_DATA_REG_200,
+ DS1603_RST_200, DS1603_CLK_200, DS1603_DATA_200,
+ DS1603_DATA_READ_SHIFT_200, 1, 2000 }
+};
+#endif
+
+#ifdef CONFIG_PICVUE
+#include "picvue.h"
+static struct pvc_defs pvc_defs[N_MACHTYPES] = {
+ { (void *)PVC_REG_100, PVC_DATA_SHIFT_100, PVC_DATA_M_100,
+ PVC_E_100, PVC_RW_100, PVC_RS_100 },
+ { (void *)PVC_REG_200, PVC_DATA_SHIFT_200, PVC_DATA_M_200,
+ PVC_E_200, PVC_RW_200, PVC_RS_200 }
+};
+#endif
+
+static int lasat_panic_display(struct notifier_block *this,
+ unsigned long event, void *ptr)
+{
+#ifdef CONFIG_PICVUE
+ unsigned char *string = ptr;
+ if (string == NULL)
+ string = "Kernel Panic";
+ pvc_dump_string(string);
+#endif
+ return NOTIFY_DONE;
+}
+
+static int lasat_panic_prom_monitor(struct notifier_block *this,
+ unsigned long event, void *ptr)
+{
+ prom_monitor();
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block lasat_panic_block[] =
+{
+ { lasat_panic_display, NULL, INT_MAX },
+ { lasat_panic_prom_monitor, NULL, INT_MIN }
+};
+
+static void lasat_time_init(void)
+{
+ mips_hpt_frequency = lasat_board_info.li_cpu_hz / 2;
+}
+
+static void lasat_timer_setup(struct irqaction *irq)
+{
+
+ write_c0_compare(
+ read_c0_count() +
+ mips_hpt_frequency / HZ);
+ change_c0_status(ST0_IM, IE_IRQ0 | IE_IRQ5);
+}
+
+#define DYNAMIC_SERIAL_INIT
+#ifdef DYNAMIC_SERIAL_INIT
+void __init serial_init(void)
+{
+#ifdef CONFIG_SERIAL_8250
+ struct uart_port s;
+
+ memset(&s, 0, sizeof(s));
+
+ s.flags = STD_COM_FLAGS;
+ s.iotype = SERIAL_IO_MEM;
+
+ if (mips_machtype == MACH_LASAT_100) {
+ s.uartclk = LASAT_BASE_BAUD_100 * 16;
+ s.irq = LASATINT_UART_100;
+ s.regshift = LASAT_UART_REGS_SHIFT_100;
+ s.membase = (char *)KSEG1ADDR(LASAT_UART_REGS_BASE_100);
+ } else {
+ s.uartclk = LASAT_BASE_BAUD_200 * 16;
+ s.irq = LASATINT_UART_200;
+ s.regshift = LASAT_UART_REGS_SHIFT_200;
+ s.membase = (char *)KSEG1ADDR(LASAT_UART_REGS_BASE_200);
+ }
+
+ if (early_serial_setup(&s) != 0)
+ printk(KERN_ERR "Serial setup failed!\n");
+#endif
+}
+#endif
+
+static int __init lasat_setup(void)
+{
+ int i;
+ lasat_misc = &lasat_misc_info[mips_machtype];
+#ifdef CONFIG_PICVUE
+ picvue = &pvc_defs[mips_machtype];
+#endif
+
+ /* Set up panic notifier */
+ for (i = 0; i < sizeof(lasat_panic_block) / sizeof(struct notifier_block); i++)
+ notifier_chain_register(&panic_notifier_list, &lasat_panic_block[i]);
+
+ lasat_reboot_setup();
+
+ board_time_init = lasat_time_init;
+ board_timer_setup = lasat_timer_setup;
+
+#ifdef CONFIG_DS1603
+ ds1603 = &ds_defs[mips_machtype];
+ rtc_get_time = ds1603_read;
+ rtc_set_time = ds1603_set;
+#endif
+
+#ifdef DYNAMIC_SERIAL_INIT
+ serial_init();
+#endif
+ /* Switch from prom exception handler to normal mode */
+ change_c0_status(ST0_BEV,0);
+
+ prom_printf("Lasat specific initialization complete\n");
+
+ return 0;
+}
+
+early_initcall(lasat_setup);
diff --git a/arch/mips/lasat/sysctl.c b/arch/mips/lasat/sysctl.c
new file mode 100644
index 0000000..1c0cc62
--- /dev/null
+++ b/arch/mips/lasat/sysctl.c
@@ -0,0 +1,355 @@
+/*
+ * Thomas Horsten <thh@lasat.com>
+ * Copyright (C) 2000 LASAT Networks A/S.
+ *
+ * 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.
+ *
+ * Routines specific to the LASAT boards
+ */
+#include <linux/types.h>
+#include <asm/lasat/lasat.h>
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/sysctl.h>
+#include <linux/stddef.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/ctype.h>
+#include <linux/string.h>
+#include <linux/net.h>
+#include <linux/inet.h>
+#include <asm/uaccess.h>
+
+#include "sysctl.h"
+#include "ds1603.h"
+
+static DECLARE_MUTEX(lasat_info_sem);
+
+/* Strategy function to write EEPROM after changing string entry */
+int sysctl_lasatstring(ctl_table *table, int *name, int nlen,
+ void *oldval, size_t *oldlenp,
+ void *newval, size_t newlen, void **context)
+{
+ int r;
+ down(&lasat_info_sem);
+ r = sysctl_string(table, name,
+ nlen, oldval, oldlenp, newval, newlen, context);
+ if (r < 0) {
+ up(&lasat_info_sem);
+ return r;
+ }
+ if (newval && newlen) {
+ lasat_write_eeprom_info();
+ }
+ up(&lasat_info_sem);
+ return 1;
+}
+
+
+/* And the same for proc */
+int proc_dolasatstring(ctl_table *table, int write, struct file *filp,
+ void *buffer, size_t *lenp, loff_t *ppos)
+{
+ int r;
+ down(&lasat_info_sem);
+ r = proc_dostring(table, write, filp, buffer, lenp, ppos);
+ if ( (!write) || r) {
+ up(&lasat_info_sem);
+ return r;
+ }
+ lasat_write_eeprom_info();
+ up(&lasat_info_sem);
+ return 0;
+}
+
+/* proc function to write EEPROM after changing int entry */
+int proc_dolasatint(ctl_table *table, int write, struct file *filp,
+ void *buffer, size_t *lenp, loff_t *ppos)
+{
+ int r;
+ down(&lasat_info_sem);
+ r = proc_dointvec(table, write, filp, buffer, lenp, ppos);
+ if ( (!write) || r) {
+ up(&lasat_info_sem);
+ return r;
+ }
+ lasat_write_eeprom_info();
+ up(&lasat_info_sem);
+ return 0;
+}
+
+static int rtctmp;
+
+#ifdef CONFIG_DS1603
+/* proc function to read/write RealTime Clock */
+int proc_dolasatrtc(ctl_table *table, int write, struct file *filp,
+ void *buffer, size_t *lenp, loff_t *ppos)
+{
+ int r;
+ down(&lasat_info_sem);
+ if (!write) {
+ rtctmp = ds1603_read();
+ /* check for time < 0 and set to 0 */
+ if (rtctmp < 0)
+ rtctmp = 0;
+ }
+ r = proc_dointvec(table, write, filp, buffer, lenp, ppos);
+ if ( (!write) || r) {
+ up(&lasat_info_sem);
+ return r;
+ }
+ ds1603_set(rtctmp);
+ up(&lasat_info_sem);
+ return 0;
+}
+#endif
+
+/* Sysctl for setting the IP addresses */
+int sysctl_lasat_intvec(ctl_table *table, int *name, int nlen,
+ void *oldval, size_t *oldlenp,
+ void *newval, size_t newlen, void **context)
+{
+ int r;
+ down(&lasat_info_sem);
+ r = sysctl_intvec(table, name, nlen, oldval, oldlenp, newval, newlen, context);
+ if (r < 0) {
+ up(&lasat_info_sem);
+ return r;
+ }
+ if (newval && newlen) {
+ lasat_write_eeprom_info();
+ }
+ up(&lasat_info_sem);
+ return 1;
+}
+
+#ifdef CONFIG_DS1603
+/* Same for RTC */
+int sysctl_lasat_rtc(ctl_table *table, int *name, int nlen,
+ void *oldval, size_t *oldlenp,
+ void *newval, size_t newlen, void **context)
+{
+ int r;
+ down(&lasat_info_sem);
+ rtctmp = ds1603_read();
+ if (rtctmp < 0)
+ rtctmp = 0;
+ r = sysctl_intvec(table, name, nlen, oldval, oldlenp, newval, newlen, context);
+ if (r < 0) {
+ up(&lasat_info_sem);
+ return r;
+ }
+ if (newval && newlen) {
+ ds1603_set(rtctmp);
+ }
+ up(&lasat_info_sem);
+ return 1;
+}
+#endif
+
+#ifdef CONFIG_INET
+static char lasat_bcastaddr[16];
+
+void update_bcastaddr(void)
+{
+ unsigned int ip;
+
+ ip = (lasat_board_info.li_eeprom_info.ipaddr &
+ lasat_board_info.li_eeprom_info.netmask) |
+ ~lasat_board_info.li_eeprom_info.netmask;
+
+ sprintf(lasat_bcastaddr, "%d.%d.%d.%d",
+ (ip ) & 0xff,
+ (ip >> 8) & 0xff,
+ (ip >> 16) & 0xff,
+ (ip >> 24) & 0xff);
+}
+
+static char proc_lasat_ipbuf[32];
+/* Parsing of IP address */
+int proc_lasat_ip(ctl_table *table, int write, struct file *filp,
+ void *buffer, size_t *lenp, loff_t *ppos)
+{
+ int len;
+ unsigned int ip;
+ char *p, c;
+
+ if (!table->data || !table->maxlen || !*lenp ||
+ (*ppos && !write)) {
+ *lenp = 0;
+ return 0;
+ }
+
+ down(&lasat_info_sem);
+ if (write) {
+ len = 0;
+ p = buffer;
+ while (len < *lenp) {
+ if(get_user(c, p++)) {
+ up(&lasat_info_sem);
+ return -EFAULT;
+ }
+ if (c == 0 || c == '\n')
+ break;
+ len++;
+ }
+ if (len >= sizeof(proc_lasat_ipbuf)-1)
+ len = sizeof(proc_lasat_ipbuf) - 1;
+ if (copy_from_user(proc_lasat_ipbuf, buffer, len))
+ {
+ up(&lasat_info_sem);
+ return -EFAULT;
+ }
+ proc_lasat_ipbuf[len] = 0;
+ *ppos += *lenp;
+ /* Now see if we can convert it to a valid IP */
+ ip = in_aton(proc_lasat_ipbuf);
+ *(unsigned int *)(table->data) = ip;
+ lasat_write_eeprom_info();
+ } else {
+ ip = *(unsigned int *)(table->data);
+ sprintf(proc_lasat_ipbuf, "%d.%d.%d.%d",
+ (ip ) & 0xff,
+ (ip >> 8) & 0xff,
+ (ip >> 16) & 0xff,
+ (ip >> 24) & 0xff);
+ len = strlen(proc_lasat_ipbuf);
+ if (len > *lenp)
+ len = *lenp;
+ if (len)
+ if(copy_to_user(buffer, proc_lasat_ipbuf, len)) {
+ up(&lasat_info_sem);
+ return -EFAULT;
+ }
+ if (len < *lenp) {
+ if(put_user('\n', ((char *) buffer) + len)) {
+ up(&lasat_info_sem);
+ return -EFAULT;
+ }
+ len++;
+ }
+ *lenp = len;
+ *ppos += len;
+ }
+ update_bcastaddr();
+ up(&lasat_info_sem);
+ return 0;
+}
+#endif /* defined(CONFIG_INET) */
+
+static int sysctl_lasat_eeprom_value(ctl_table *table, int *name, int nlen,
+ void *oldval, size_t *oldlenp,
+ void *newval, size_t newlen,
+ void **context)
+{
+ int r;
+
+ down(&lasat_info_sem);
+ r = sysctl_intvec(table, name, nlen, oldval, oldlenp, newval, newlen, context);
+ if (r < 0) {
+ up(&lasat_info_sem);
+ return r;
+ }
+
+ if (newval && newlen)
+ {
+ if (name && *name == LASAT_PRID)
+ lasat_board_info.li_eeprom_info.prid = *(int*)newval;
+
+ lasat_write_eeprom_info();
+ lasat_init_board_info();
+ }
+ up(&lasat_info_sem);
+
+ return 0;
+}
+
+int proc_lasat_eeprom_value(ctl_table *table, int write, struct file *filp,
+ void *buffer, size_t *lenp, loff_t *ppos)
+{
+ int r;
+ down(&lasat_info_sem);
+ r = proc_dointvec(table, write, filp, buffer, lenp, ppos);
+ if ( (!write) || r) {
+ up(&lasat_info_sem);
+ return r;
+ }
+ if (filp && filp->f_dentry)
+ {
+ if (!strcmp(filp->f_dentry->d_name.name, "prid"))
+ lasat_board_info.li_eeprom_info.prid = lasat_board_info.li_prid;
+ if (!strcmp(filp->f_dentry->d_name.name, "debugaccess"))
+ lasat_board_info.li_eeprom_info.debugaccess = lasat_board_info.li_debugaccess;
+ }
+ lasat_write_eeprom_info();
+ up(&lasat_info_sem);
+ return 0;
+}
+
+extern int lasat_boot_to_service;
+
+#ifdef CONFIG_SYSCTL
+
+static ctl_table lasat_table[] = {
+ {LASAT_CPU_HZ, "cpu-hz", &lasat_board_info.li_cpu_hz, sizeof(int),
+ 0444, NULL, &proc_dointvec, &sysctl_intvec},
+ {LASAT_BUS_HZ, "bus-hz", &lasat_board_info.li_bus_hz, sizeof(int),
+ 0444, NULL, &proc_dointvec, &sysctl_intvec},
+ {LASAT_MODEL, "bmid", &lasat_board_info.li_bmid, sizeof(int),
+ 0444, NULL, &proc_dointvec, &sysctl_intvec},
+ {LASAT_PRID, "prid", &lasat_board_info.li_prid, sizeof(int),
+ 0644, NULL, &proc_lasat_eeprom_value, &sysctl_lasat_eeprom_value},
+#ifdef CONFIG_INET
+ {LASAT_IPADDR, "ipaddr", &lasat_board_info.li_eeprom_info.ipaddr, sizeof(int),
+ 0644, NULL, &proc_lasat_ip, &sysctl_lasat_intvec},
+ {LASAT_NETMASK, "netmask", &lasat_board_info.li_eeprom_info.netmask, sizeof(int),
+ 0644, NULL, &proc_lasat_ip, &sysctl_lasat_intvec},
+ {LASAT_BCAST, "bcastaddr", &lasat_bcastaddr,
+ sizeof(lasat_bcastaddr), 0600, NULL,
+ &proc_dostring, &sysctl_string},
+#endif
+ {LASAT_PASSWORD, "passwd_hash", &lasat_board_info.li_eeprom_info.passwd_hash, sizeof(lasat_board_info.li_eeprom_info.passwd_hash),
+ 0600, NULL, &proc_dolasatstring, &sysctl_lasatstring},
+ {LASAT_SBOOT, "boot-service", &lasat_boot_to_service, sizeof(int),
+ 0644, NULL, &proc_dointvec, &sysctl_intvec},
+#ifdef CONFIG_DS1603
+ {LASAT_RTC, "rtc", &rtctmp, sizeof(int),
+ 0644, NULL, &proc_dolasatrtc, &sysctl_lasat_rtc},
+#endif
+ {LASAT_NAMESTR, "namestr", &lasat_board_info.li_namestr, sizeof(lasat_board_info.li_namestr),
+ 0444, NULL, &proc_dostring, &sysctl_string},
+ {LASAT_TYPESTR, "typestr", &lasat_board_info.li_typestr, sizeof(lasat_board_info.li_typestr),
+ 0444, NULL, &proc_dostring, &sysctl_string},
+ {0}
+};
+
+#define CTL_LASAT 1 // CTL_ANY ???
+static ctl_table lasat_root_table[] = {
+ { CTL_LASAT, "lasat", NULL, 0, 0555, lasat_table },
+ { 0 }
+};
+
+static int __init lasat_register_sysctl(void)
+{
+ struct ctl_table_header *lasat_table_header;
+
+ lasat_table_header =
+ register_sysctl_table(lasat_root_table, 0);
+
+ return 0;
+}
+
+__initcall(lasat_register_sysctl);
+#endif /* CONFIG_SYSCTL */
diff --git a/arch/mips/lasat/sysctl.h b/arch/mips/lasat/sysctl.h
new file mode 100644
index 0000000..4d139d2
--- /dev/null
+++ b/arch/mips/lasat/sysctl.h
@@ -0,0 +1,24 @@
+/*
+ * LASAT sysctl values
+ */
+
+#ifndef _LASAT_SYSCTL_H
+#define _LASAT_SYSCTL_H
+
+/* /proc/sys/lasat */
+enum {
+ LASAT_CPU_HZ=1,
+ LASAT_BUS_HZ,
+ LASAT_MODEL,
+ LASAT_PRID,
+ LASAT_IPADDR,
+ LASAT_NETMASK,
+ LASAT_BCAST,
+ LASAT_PASSWORD,
+ LASAT_SBOOT,
+ LASAT_RTC,
+ LASAT_NAMESTR,
+ LASAT_TYPESTR,
+};
+
+#endif /* _LASAT_SYSCTL_H */
diff --git a/arch/mips/lib-32/Makefile b/arch/mips/lib-32/Makefile
new file mode 100644
index 0000000..fd6a2ba
--- /dev/null
+++ b/arch/mips/lib-32/Makefile
@@ -0,0 +1,25 @@
+#
+# Makefile for MIPS-specific library files..
+#
+
+lib-y += csum_partial.o memset.o watch.o
+
+obj-$(CONFIG_CPU_MIPS32) += dump_tlb.o
+obj-$(CONFIG_CPU_MIPS64) += dump_tlb.o
+obj-$(CONFIG_CPU_NEVADA) += dump_tlb.o
+obj-$(CONFIG_CPU_R10000) += dump_tlb.o
+obj-$(CONFIG_CPU_R3000) += r3k_dump_tlb.o
+obj-$(CONFIG_CPU_R4300) += dump_tlb.o
+obj-$(CONFIG_CPU_R4X00) += dump_tlb.o
+obj-$(CONFIG_CPU_R5000) += dump_tlb.o
+obj-$(CONFIG_CPU_R5432) += dump_tlb.o
+obj-$(CONFIG_CPU_R6000) +=
+obj-$(CONFIG_CPU_R8000) +=
+obj-$(CONFIG_CPU_RM7000) += dump_tlb.o
+obj-$(CONFIG_CPU_RM9000) += dump_tlb.o
+obj-$(CONFIG_CPU_SB1) += dump_tlb.o
+obj-$(CONFIG_CPU_TX39XX) += r3k_dump_tlb.o
+obj-$(CONFIG_CPU_TX49XX) += dump_tlb.o
+obj-$(CONFIG_CPU_VR41XX) += dump_tlb.o
+
+EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/lib-32/csum_partial.S b/arch/mips/lib-32/csum_partial.S
new file mode 100644
index 0000000..ea257db
--- /dev/null
+++ b/arch/mips/lib-32/csum_partial.S
@@ -0,0 +1,240 @@
+/*
+ * 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) 1998 Ralf Baechle
+ */
+#include <asm/asm.h>
+#include <asm/regdef.h>
+
+#define ADDC(sum,reg) \
+ addu sum, reg; \
+ sltu v1, sum, reg; \
+ addu sum, v1
+
+#define CSUM_BIGCHUNK(src, offset, sum, t0, t1, t2, t3) \
+ lw t0, (offset + 0x00)(src); \
+ lw t1, (offset + 0x04)(src); \
+ lw t2, (offset + 0x08)(src); \
+ lw t3, (offset + 0x0c)(src); \
+ ADDC(sum, t0); \
+ ADDC(sum, t1); \
+ ADDC(sum, t2); \
+ ADDC(sum, t3); \
+ lw t0, (offset + 0x10)(src); \
+ lw t1, (offset + 0x14)(src); \
+ lw t2, (offset + 0x18)(src); \
+ lw t3, (offset + 0x1c)(src); \
+ ADDC(sum, t0); \
+ ADDC(sum, t1); \
+ ADDC(sum, t2); \
+ ADDC(sum, t3); \
+
+/*
+ * a0: source address
+ * a1: length of the area to checksum
+ * a2: partial checksum
+ */
+
+#define src a0
+#define dest a1
+#define sum v0
+
+ .text
+ .set noreorder
+
+/* unknown src alignment and < 8 bytes to go */
+small_csumcpy:
+ move a1, t2
+
+ andi t0, a1, 4
+ beqz t0, 1f
+ andi t0, a1, 2
+
+ /* Still a full word to go */
+ ulw t1, (src)
+ addiu src, 4
+ ADDC(sum, t1)
+
+1: move t1, zero
+ beqz t0, 1f
+ andi t0, a1, 1
+
+ /* Still a halfword to go */
+ ulhu t1, (src)
+ addiu src, 2
+
+1: beqz t0, 1f
+ sll t1, t1, 16
+
+ lbu t2, (src)
+ nop
+
+#ifdef __MIPSEB__
+ sll t2, t2, 8
+#endif
+ or t1, t2
+
+1: ADDC(sum, t1)
+
+ /* fold checksum */
+ sll v1, sum, 16
+ addu sum, v1
+ sltu v1, sum, v1
+ srl sum, sum, 16
+ addu sum, v1
+
+ /* odd buffer alignment? */
+ beqz t7, 1f
+ nop
+ sll v1, sum, 8
+ srl sum, sum, 8
+ or sum, v1
+ andi sum, 0xffff
+1:
+ .set reorder
+ /* Add the passed partial csum. */
+ ADDC(sum, a2)
+ jr ra
+ .set noreorder
+
+/* ------------------------------------------------------------------------- */
+
+ .align 5
+LEAF(csum_partial)
+ move sum, zero
+ move t7, zero
+
+ sltiu t8, a1, 0x8
+ bnez t8, small_csumcpy /* < 8 bytes to copy */
+ move t2, a1
+
+ beqz a1, out
+ andi t7, src, 0x1 /* odd buffer? */
+
+hword_align:
+ beqz t7, word_align
+ andi t8, src, 0x2
+
+ lbu t0, (src)
+ subu a1, a1, 0x1
+#ifdef __MIPSEL__
+ sll t0, t0, 8
+#endif
+ ADDC(sum, t0)
+ addu src, src, 0x1
+ andi t8, src, 0x2
+
+word_align:
+ beqz t8, dword_align
+ sltiu t8, a1, 56
+
+ lhu t0, (src)
+ subu a1, a1, 0x2
+ ADDC(sum, t0)
+ sltiu t8, a1, 56
+ addu src, src, 0x2
+
+dword_align:
+ bnez t8, do_end_words
+ move t8, a1
+
+ andi t8, src, 0x4
+ beqz t8, qword_align
+ andi t8, src, 0x8
+
+ lw t0, 0x00(src)
+ subu a1, a1, 0x4
+ ADDC(sum, t0)
+ addu src, src, 0x4
+ andi t8, src, 0x8
+
+qword_align:
+ beqz t8, oword_align
+ andi t8, src, 0x10
+
+ lw t0, 0x00(src)
+ lw t1, 0x04(src)
+ subu a1, a1, 0x8
+ ADDC(sum, t0)
+ ADDC(sum, t1)
+ addu src, src, 0x8
+ andi t8, src, 0x10
+
+oword_align:
+ beqz t8, begin_movement
+ srl t8, a1, 0x7
+
+ lw t3, 0x08(src)
+ lw t4, 0x0c(src)
+ lw t0, 0x00(src)
+ lw t1, 0x04(src)
+ ADDC(sum, t3)
+ ADDC(sum, t4)
+ ADDC(sum, t0)
+ ADDC(sum, t1)
+ subu a1, a1, 0x10
+ addu src, src, 0x10
+ srl t8, a1, 0x7
+
+begin_movement:
+ beqz t8, 1f
+ andi t2, a1, 0x40
+
+move_128bytes:
+ CSUM_BIGCHUNK(src, 0x00, sum, t0, t1, t3, t4)
+ CSUM_BIGCHUNK(src, 0x20, sum, t0, t1, t3, t4)
+ CSUM_BIGCHUNK(src, 0x40, sum, t0, t1, t3, t4)
+ CSUM_BIGCHUNK(src, 0x60, sum, t0, t1, t3, t4)
+ subu t8, t8, 0x01
+ bnez t8, move_128bytes
+ addu src, src, 0x80
+
+1:
+ beqz t2, 1f
+ andi t2, a1, 0x20
+
+move_64bytes:
+ CSUM_BIGCHUNK(src, 0x00, sum, t0, t1, t3, t4)
+ CSUM_BIGCHUNK(src, 0x20, sum, t0, t1, t3, t4)
+ addu src, src, 0x40
+
+1:
+ beqz t2, do_end_words
+ andi t8, a1, 0x1c
+
+move_32bytes:
+ CSUM_BIGCHUNK(src, 0x00, sum, t0, t1, t3, t4)
+ andi t8, a1, 0x1c
+ addu src, src, 0x20
+
+do_end_words:
+ beqz t8, maybe_end_cruft
+ srl t8, t8, 0x2
+
+end_words:
+ lw t0, (src)
+ subu t8, t8, 0x1
+ ADDC(sum, t0)
+ bnez t8, end_words
+ addu src, src, 0x4
+
+maybe_end_cruft:
+ andi t2, a1, 0x3
+
+small_memcpy:
+ j small_csumcpy; move a1, t2
+ beqz t2, out
+ move a1, t2
+
+end_bytes:
+ lb t0, (src)
+ subu a1, a1, 0x1
+ bnez a2, end_bytes
+ addu src, src, 0x1
+
+out:
+ jr ra
+ move v0, sum
+ END(csum_partial)
diff --git a/arch/mips/lib-32/dump_tlb.c b/arch/mips/lib-32/dump_tlb.c
new file mode 100644
index 0000000..019ac8f
--- /dev/null
+++ b/arch/mips/lib-32/dump_tlb.c
@@ -0,0 +1,222 @@
+/*
+ * Dump R4x00 TLB for debugging purposes.
+ *
+ * Copyright (C) 1994, 1995 by Waldorf Electronics, written by Ralf Baechle.
+ * Copyright (C) 1999 by Silicon Graphics, Inc.
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+
+#include <asm/bootinfo.h>
+#include <asm/cachectl.h>
+#include <asm/cpu.h>
+#include <asm/mipsregs.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+
+static inline const char *msk2str(unsigned int mask)
+{
+ switch (mask) {
+ case PM_4K: return "4kb";
+ case PM_16K: return "16kb";
+ case PM_64K: return "64kb";
+ case PM_256K: return "256kb";
+#ifndef CONFIG_CPU_VR41XX
+ case PM_1M: return "1Mb";
+ case PM_4M: return "4Mb";
+ case PM_16M: return "16Mb";
+ case PM_64M: return "64Mb";
+ case PM_256M: return "256Mb";
+#endif
+ }
+
+ return "unknown";
+}
+
+#define BARRIER() \
+ __asm__ __volatile__( \
+ ".set\tnoreorder\n\t" \
+ "nop;nop;nop;nop;nop;nop;nop\n\t" \
+ ".set\treorder");
+
+void dump_tlb(int first, int last)
+{
+ unsigned int pagemask, c0, c1, asid;
+ unsigned long long entrylo0, entrylo1;
+ unsigned long entryhi;
+ int i;
+
+ asid = read_c0_entryhi() & 0xff;
+
+ printk("\n");
+ for (i = first; i <= last; i++) {
+ write_c0_index(i);
+ BARRIER();
+ tlb_read();
+ BARRIER();
+ pagemask = read_c0_pagemask();
+ entryhi = read_c0_entryhi();
+ entrylo0 = read_c0_entrylo0();
+ entrylo1 = read_c0_entrylo1();
+
+ /* Unused entries have a virtual address in KSEG0. */
+ if ((entryhi & 0xf0000000) != 0x80000000
+ && (entryhi & 0xff) == asid) {
+ /*
+ * Only print entries in use
+ */
+ printk("Index: %2d pgmask=%s ", i, msk2str(pagemask));
+
+ c0 = (entrylo0 >> 3) & 7;
+ c1 = (entrylo1 >> 3) & 7;
+
+ printk("va=%08lx asid=%02lx\n",
+ (entryhi & 0xffffe000), (entryhi & 0xff));
+ printk("\t\t\t[pa=%08Lx c=%d d=%d v=%d g=%Ld]\n",
+ (entrylo0 << 6) & PAGE_MASK, c0,
+ (entrylo0 & 4) ? 1 : 0,
+ (entrylo0 & 2) ? 1 : 0,
+ (entrylo0 & 1));
+ printk("\t\t\t[pa=%08Lx c=%d d=%d v=%d g=%Ld]\n",
+ (entrylo1 << 6) & PAGE_MASK, c1,
+ (entrylo1 & 4) ? 1 : 0,
+ (entrylo1 & 2) ? 1 : 0,
+ (entrylo1 & 1));
+ printk("\n");
+ }
+ }
+
+ write_c0_entryhi(asid);
+}
+
+void dump_tlb_all(void)
+{
+ dump_tlb(0, current_cpu_data.tlbsize - 1);
+}
+
+void dump_tlb_wired(void)
+{
+ int wired;
+
+ wired = read_c0_wired();
+ printk("Wired: %d", wired);
+ dump_tlb(0, read_c0_wired());
+}
+
+void dump_tlb_addr(unsigned long addr)
+{
+ unsigned int flags, oldpid;
+ int index;
+
+ local_irq_save(flags);
+ oldpid = read_c0_entryhi() & 0xff;
+ BARRIER();
+ write_c0_entryhi((addr & PAGE_MASK) | oldpid);
+ BARRIER();
+ tlb_probe();
+ BARRIER();
+ index = read_c0_index();
+ write_c0_entryhi(oldpid);
+ local_irq_restore(flags);
+
+ if (index < 0) {
+ printk("No entry for address 0x%08lx in TLB\n", addr);
+ return;
+ }
+
+ printk("Entry %d maps address 0x%08lx\n", index, addr);
+ dump_tlb(index, index);
+}
+
+void dump_tlb_nonwired(void)
+{
+ dump_tlb(read_c0_wired(), current_cpu_data.tlbsize - 1);
+}
+
+void dump_list_process(struct task_struct *t, void *address)
+{
+ pgd_t *page_dir, *pgd;
+ pmd_t *pmd;
+ pte_t *pte, page;
+ unsigned long addr, val;
+
+ addr = (unsigned long) address;
+
+ printk("Addr == %08lx\n", addr);
+ printk("task == %8p\n", t);
+ printk("task->mm == %8p\n", t->mm);
+ //printk("tasks->mm.pgd == %08x\n", (unsigned int) t->mm->pgd);
+
+ if (addr > KSEG0)
+ page_dir = pgd_offset_k(0);
+ else
+ page_dir = pgd_offset(t->mm, 0);
+ printk("page_dir == %08x\n", (unsigned int) page_dir);
+
+ if (addr > KSEG0)
+ pgd = pgd_offset_k(addr);
+ else
+ pgd = pgd_offset(t->mm, addr);
+ printk("pgd == %08x, ", (unsigned int) pgd);
+
+ pmd = pmd_offset(pgd, addr);
+ printk("pmd == %08x, ", (unsigned int) pmd);
+
+ pte = pte_offset(pmd, addr);
+ printk("pte == %08x, ", (unsigned int) pte);
+
+ page = *pte;
+#ifdef CONFIG_64BIT_PHYS_ADDR
+ printk("page == %08Lx\n", pte_val(page));
+#else
+ printk("page == %08lx\n", pte_val(page));
+#endif
+
+ val = pte_val(page);
+ if (val & _PAGE_PRESENT) printk("present ");
+ if (val & _PAGE_READ) printk("read ");
+ if (val & _PAGE_WRITE) printk("write ");
+ if (val & _PAGE_ACCESSED) printk("accessed ");
+ if (val & _PAGE_MODIFIED) printk("modified ");
+ if (val & _PAGE_R4KBUG) printk("r4kbug ");
+ if (val & _PAGE_GLOBAL) printk("global ");
+ if (val & _PAGE_VALID) printk("valid ");
+ printk("\n");
+}
+
+void dump_list_current(void *address)
+{
+ dump_list_process(current, address);
+}
+
+unsigned int vtop(void *address)
+{
+ pgd_t *pgd;
+ pmd_t *pmd;
+ pte_t *pte;
+ unsigned int addr, paddr;
+
+ addr = (unsigned long) address;
+ pgd = pgd_offset(current->mm, addr);
+ pmd = pmd_offset(pgd, addr);
+ pte = pte_offset(pmd, addr);
+ paddr = (KSEG1 | (unsigned int) pte_val(*pte)) & PAGE_MASK;
+ paddr |= (addr & ~PAGE_MASK);
+
+ return paddr;
+}
+
+void dump16(unsigned long *p)
+{
+ int i;
+
+ for (i = 0; i < 8; i++) {
+ printk("*%08lx == %08lx, ", (unsigned long)p, *p);
+ p++;
+ printk("*%08lx == %08lx\n", (unsigned long)p, *p);
+ p++;
+ }
+}
diff --git a/arch/mips/lib-32/memset.S b/arch/mips/lib-32/memset.S
new file mode 100644
index 0000000..ad9ff40
--- /dev/null
+++ b/arch/mips/lib-32/memset.S
@@ -0,0 +1,145 @@
+/*
+ * 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) 1998, 1999, 2000 by Ralf Baechle
+ * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
+ */
+#include <asm/asm.h>
+#include <asm/offset.h>
+#include <asm/regdef.h>
+
+#define EX(insn,reg,addr,handler) \
+9: insn reg, addr; \
+ .section __ex_table,"a"; \
+ PTR 9b, handler; \
+ .previous
+
+ .macro f_fill64 dst, offset, val, fixup
+ EX(LONG_S, \val, (\offset + 0 * LONGSIZE)(\dst), \fixup)
+ EX(LONG_S, \val, (\offset + 1 * LONGSIZE)(\dst), \fixup)
+ EX(LONG_S, \val, (\offset + 2 * LONGSIZE)(\dst), \fixup)
+ EX(LONG_S, \val, (\offset + 3 * LONGSIZE)(\dst), \fixup)
+ EX(LONG_S, \val, (\offset + 4 * LONGSIZE)(\dst), \fixup)
+ EX(LONG_S, \val, (\offset + 5 * LONGSIZE)(\dst), \fixup)
+ EX(LONG_S, \val, (\offset + 6 * LONGSIZE)(\dst), \fixup)
+ EX(LONG_S, \val, (\offset + 7 * LONGSIZE)(\dst), \fixup)
+ EX(LONG_S, \val, (\offset + 8 * LONGSIZE)(\dst), \fixup)
+ EX(LONG_S, \val, (\offset + 9 * LONGSIZE)(\dst), \fixup)
+ EX(LONG_S, \val, (\offset + 10 * LONGSIZE)(\dst), \fixup)
+ EX(LONG_S, \val, (\offset + 11 * LONGSIZE)(\dst), \fixup)
+ EX(LONG_S, \val, (\offset + 12 * LONGSIZE)(\dst), \fixup)
+ EX(LONG_S, \val, (\offset + 13 * LONGSIZE)(\dst), \fixup)
+ EX(LONG_S, \val, (\offset + 14 * LONGSIZE)(\dst), \fixup)
+ EX(LONG_S, \val, (\offset + 15 * LONGSIZE)(\dst), \fixup)
+ .endm
+
+/*
+ * memset(void *s, int c, size_t n)
+ *
+ * a0: start of area to clear
+ * a1: char to fill with
+ * a2: size of area to clear
+ */
+ .set noreorder
+ .align 5
+LEAF(memset)
+ beqz a1, 1f
+ move v0, a0 /* result */
+
+ andi a1, 0xff /* spread fillword */
+ sll t1, a1, 8
+ or a1, t1
+ sll t1, a1, 16
+ or a1, t1
+1:
+
+FEXPORT(__bzero)
+ sltiu t0, a2, LONGSIZE /* very small region? */
+ bnez t0, small_memset
+ andi t0, a0, LONGMASK /* aligned? */
+
+ beqz t0, 1f
+ PTR_SUBU t0, LONGSIZE /* alignment in bytes */
+
+#ifdef __MIPSEB__
+ EX(swl, a1, (a0), first_fixup) /* make word aligned */
+#endif
+#ifdef __MIPSEL__
+ EX(swr, a1, (a0), first_fixup) /* make word aligned */
+#endif
+ PTR_SUBU a0, t0 /* long align ptr */
+ PTR_ADDU a2, t0 /* correct size */
+
+1: ori t1, a2, 0x3f /* # of full blocks */
+ xori t1, 0x3f
+ beqz t1, memset_partial /* no block to fill */
+ andi t0, a2, 0x3c
+
+ PTR_ADDU t1, a0 /* end address */
+ .set reorder
+1: PTR_ADDIU a0, 64
+ f_fill64 a0, -64, a1, fwd_fixup
+ bne t1, a0, 1b
+ .set noreorder
+
+memset_partial:
+ PTR_LA t1, 2f /* where to start */
+ PTR_SUBU t1, t0
+ jr t1
+ PTR_ADDU a0, t0 /* dest ptr */
+
+ .set push
+ .set noreorder
+ .set nomacro
+ f_fill64 a0, -64, a1, partial_fixup /* ... but first do longs ... */
+2: .set pop
+ andi a2, LONGMASK /* At most one long to go */
+
+ beqz a2, 1f
+ PTR_ADDU a0, a2 /* What's left */
+#ifdef __MIPSEB__
+ EX(swr, a1, -1(a0), last_fixup)
+#endif
+#ifdef __MIPSEL__
+ EX(swl, a1, -1(a0), last_fixup)
+#endif
+1: jr ra
+ move a2, zero
+
+small_memset:
+ beqz a2, 2f
+ PTR_ADDU t1, a0, a2
+
+1: PTR_ADDIU a0, 1 /* fill bytewise */
+ bne t1, a0, 1b
+ sb a1, -1(a0)
+
+2: jr ra /* done */
+ move a2, zero
+ END(memset)
+
+first_fixup:
+ jr ra
+ nop
+
+fwd_fixup:
+ PTR_L t0, TI_TASK($28)
+ LONG_L t0, THREAD_BUADDR(t0)
+ andi a2, 0x3f
+ LONG_ADDU a2, t1
+ jr ra
+ LONG_SUBU a2, t0
+
+partial_fixup:
+ PTR_L t0, TI_TASK($28)
+ LONG_L t0, THREAD_BUADDR(t0)
+ andi a2, LONGMASK
+ LONG_ADDU a2, t1
+ jr ra
+ LONG_SUBU a2, t0
+
+last_fixup:
+ jr ra
+ andi v1, a2, LONGMASK
diff --git a/arch/mips/lib-32/r3k_dump_tlb.c b/arch/mips/lib-32/r3k_dump_tlb.c
new file mode 100644
index 0000000..a878224
--- /dev/null
+++ b/arch/mips/lib-32/r3k_dump_tlb.c
@@ -0,0 +1,176 @@
+/*
+ * Dump R3000 TLB for debugging purposes.
+ *
+ * Copyright (C) 1994, 1995 by Waldorf Electronics, written by Ralf Baechle.
+ * Copyright (C) 1999 by Silicon Graphics, Inc.
+ * Copyright (C) 1999 by Harald Koerfgen
+ */
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+
+#include <asm/bootinfo.h>
+#include <asm/cachectl.h>
+#include <asm/cpu.h>
+#include <asm/mipsregs.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+
+extern int r3k_have_wired_reg; /* defined in tlb-r3k.c */
+
+void dump_tlb(int first, int last)
+{
+ int i;
+ unsigned int asid;
+ unsigned long entryhi, entrylo0;
+
+ asid = read_c0_entryhi() & 0xfc0;
+
+ for (i = first; i <= last; i++) {
+ write_c0_index(i<<8);
+ __asm__ __volatile__(
+ ".set\tnoreorder\n\t"
+ "tlbr\n\t"
+ "nop\n\t"
+ ".set\treorder");
+ entryhi = read_c0_entryhi();
+ entrylo0 = read_c0_entrylo0();
+
+ /* Unused entries have a virtual address of KSEG0. */
+ if ((entryhi & 0xffffe000) != 0x80000000
+ && (entryhi & 0xfc0) == asid) {
+ /*
+ * Only print entries in use
+ */
+ printk("Index: %2d ", i);
+
+ printk("va=%08lx asid=%08lx"
+ " [pa=%06lx n=%d d=%d v=%d g=%d]",
+ (entryhi & 0xffffe000),
+ entryhi & 0xfc0,
+ entrylo0 & PAGE_MASK,
+ (entrylo0 & (1 << 11)) ? 1 : 0,
+ (entrylo0 & (1 << 10)) ? 1 : 0,
+ (entrylo0 & (1 << 9)) ? 1 : 0,
+ (entrylo0 & (1 << 8)) ? 1 : 0);
+ }
+ }
+ printk("\n");
+
+ write_c0_entryhi(asid);
+}
+
+void dump_tlb_all(void)
+{
+ dump_tlb(0, current_cpu_data.tlbsize - 1);
+}
+
+void dump_tlb_wired(void)
+{
+ int wired = r3k_have_wired_reg ? read_c0_wired() : 8;
+
+ printk("Wired: %d", wired);
+ dump_tlb(0, wired - 1);
+}
+
+void dump_tlb_addr(unsigned long addr)
+{
+ unsigned long flags, oldpid;
+ int index;
+
+ local_irq_save(flags);
+ oldpid = read_c0_entryhi() & 0xff;
+ write_c0_entryhi((addr & PAGE_MASK) | oldpid);
+ tlb_probe();
+ index = read_c0_index();
+ write_c0_entryhi(oldpid);
+ local_irq_restore(flags);
+
+ if (index < 0) {
+ printk("No entry for address 0x%08lx in TLB\n", addr);
+ return;
+ }
+
+ printk("Entry %d maps address 0x%08lx\n", index, addr);
+ dump_tlb(index, index);
+}
+
+void dump_tlb_nonwired(void)
+{
+ int wired = r3k_have_wired_reg ? read_c0_wired() : 8;
+ dump_tlb(wired, current_cpu_data.tlbsize - 1);
+}
+
+void dump_list_process(struct task_struct *t, void *address)
+{
+ pgd_t *page_dir, *pgd;
+ pmd_t *pmd;
+ pte_t *pte, page;
+ unsigned int addr;
+ unsigned long val;
+
+ addr = (unsigned int) address;
+
+ printk("Addr == %08x\n", addr);
+ printk("tasks->mm.pgd == %08x\n", (unsigned int) t->mm->pgd);
+
+ page_dir = pgd_offset(t->mm, 0);
+ printk("page_dir == %08x\n", (unsigned int) page_dir);
+
+ pgd = pgd_offset(t->mm, addr);
+ printk("pgd == %08x, ", (unsigned int) pgd);
+
+ pmd = pmd_offset(pgd, addr);
+ printk("pmd == %08x, ", (unsigned int) pmd);
+
+ pte = pte_offset(pmd, addr);
+ printk("pte == %08x, ", (unsigned int) pte);
+
+ page = *pte;
+ printk("page == %08x\n", (unsigned int) pte_val(page));
+
+ val = pte_val(page);
+ if (val & _PAGE_PRESENT) printk("present ");
+ if (val & _PAGE_READ) printk("read ");
+ if (val & _PAGE_WRITE) printk("write ");
+ if (val & _PAGE_ACCESSED) printk("accessed ");
+ if (val & _PAGE_MODIFIED) printk("modified ");
+ if (val & _PAGE_GLOBAL) printk("global ");
+ if (val & _PAGE_VALID) printk("valid ");
+ printk("\n");
+}
+
+void dump_list_current(void *address)
+{
+ dump_list_process(current, address);
+}
+
+unsigned int vtop(void *address)
+{
+ pgd_t *pgd;
+ pmd_t *pmd;
+ pte_t *pte;
+ unsigned int addr, paddr;
+
+ addr = (unsigned long) address;
+ pgd = pgd_offset(current->mm, addr);
+ pmd = pmd_offset(pgd, addr);
+ pte = pte_offset(pmd, addr);
+ paddr = (KSEG1 | (unsigned int) pte_val(*pte)) & PAGE_MASK;
+ paddr |= (addr & ~PAGE_MASK);
+
+ return paddr;
+}
+
+void dump16(unsigned long *p)
+{
+ int i;
+
+ for (i = 0; i < 8; i++) {
+ printk("*%08lx == %08lx, ", (unsigned long)p, *p);
+ p++;
+ printk("*%08lx == %08lx\n", (unsigned long)p, *p);
+ p++;
+ }
+}
diff --git a/arch/mips/lib-32/watch.S b/arch/mips/lib-32/watch.S
new file mode 100644
index 0000000..808b3af
--- /dev/null
+++ b/arch/mips/lib-32/watch.S
@@ -0,0 +1,60 @@
+/*
+ * 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.
+ *
+ * Kernel debug stuff to use the Watch registers.
+ * Useful to find stack overflows, dangling pointers etc.
+ *
+ * Copyright (C) 1995, 1996, 1999 by Ralf Baechle
+ */
+#include <asm/asm.h>
+#include <asm/mipsregs.h>
+#include <asm/regdef.h>
+
+ .set noreorder
+/*
+ * Parameter: a0 - logic address to watch
+ * Currently only KSEG0 addresses are allowed!
+ * a1 - set bit #1 to trap on load references
+ * bit #0 to trap on store references
+ * Results : none
+ */
+ LEAF(__watch_set)
+ li t0, 0x80000000
+ subu a0, t0
+ ori a0, 7
+ xori a0, 7
+ or a0, a1
+ mtc0 a0, CP0_WATCHLO
+ sw a0, watch_savelo
+
+ jr ra
+ mtc0 zero, CP0_WATCHHI
+ END(__watch_set)
+
+/*
+ * Parameter: none
+ * Results : none
+ */
+ LEAF(__watch_clear)
+ jr ra
+ mtc0 zero, CP0_WATCHLO
+ END(__watch_clear)
+
+/*
+ * Parameter: none
+ * Results : none
+ */
+ LEAF(__watch_reenable)
+ lw t0, watch_savelo
+ jr ra
+ mtc0 t0, CP0_WATCHLO
+ END(__watch_reenable)
+
+/*
+ * Saved value of the c0_watchlo register for watch_reenable()
+ */
+ .data
+watch_savelo: .word 0
+ .text
diff --git a/arch/mips/lib-64/Makefile b/arch/mips/lib-64/Makefile
new file mode 100644
index 0000000..fd6a2ba
--- /dev/null
+++ b/arch/mips/lib-64/Makefile
@@ -0,0 +1,25 @@
+#
+# Makefile for MIPS-specific library files..
+#
+
+lib-y += csum_partial.o memset.o watch.o
+
+obj-$(CONFIG_CPU_MIPS32) += dump_tlb.o
+obj-$(CONFIG_CPU_MIPS64) += dump_tlb.o
+obj-$(CONFIG_CPU_NEVADA) += dump_tlb.o
+obj-$(CONFIG_CPU_R10000) += dump_tlb.o
+obj-$(CONFIG_CPU_R3000) += r3k_dump_tlb.o
+obj-$(CONFIG_CPU_R4300) += dump_tlb.o
+obj-$(CONFIG_CPU_R4X00) += dump_tlb.o
+obj-$(CONFIG_CPU_R5000) += dump_tlb.o
+obj-$(CONFIG_CPU_R5432) += dump_tlb.o
+obj-$(CONFIG_CPU_R6000) +=
+obj-$(CONFIG_CPU_R8000) +=
+obj-$(CONFIG_CPU_RM7000) += dump_tlb.o
+obj-$(CONFIG_CPU_RM9000) += dump_tlb.o
+obj-$(CONFIG_CPU_SB1) += dump_tlb.o
+obj-$(CONFIG_CPU_TX39XX) += r3k_dump_tlb.o
+obj-$(CONFIG_CPU_TX49XX) += dump_tlb.o
+obj-$(CONFIG_CPU_VR41XX) += dump_tlb.o
+
+EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/lib-64/csum_partial.S b/arch/mips/lib-64/csum_partial.S
new file mode 100644
index 0000000..25aba66
--- /dev/null
+++ b/arch/mips/lib-64/csum_partial.S
@@ -0,0 +1,242 @@
+/*
+ * 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.
+ *
+ * Quick'n'dirty IP checksum ...
+ *
+ * Copyright (C) 1998, 1999 Ralf Baechle
+ * Copyright (C) 1999 Silicon Graphics, Inc.
+ */
+#include <asm/asm.h>
+#include <asm/regdef.h>
+
+#define ADDC(sum,reg) \
+ addu sum, reg; \
+ sltu v1, sum, reg; \
+ addu sum, v1
+
+#define CSUM_BIGCHUNK(src, offset, sum, t0, t1, t2, t3) \
+ lw t0, (offset + 0x00)(src); \
+ lw t1, (offset + 0x04)(src); \
+ lw t2, (offset + 0x08)(src); \
+ lw t3, (offset + 0x0c)(src); \
+ ADDC(sum, t0); \
+ ADDC(sum, t1); \
+ ADDC(sum, t2); \
+ ADDC(sum, t3); \
+ lw t0, (offset + 0x10)(src); \
+ lw t1, (offset + 0x14)(src); \
+ lw t2, (offset + 0x18)(src); \
+ lw t3, (offset + 0x1c)(src); \
+ ADDC(sum, t0); \
+ ADDC(sum, t1); \
+ ADDC(sum, t2); \
+ ADDC(sum, t3); \
+
+/*
+ * a0: source address
+ * a1: length of the area to checksum
+ * a2: partial checksum
+ */
+
+#define src a0
+#define sum v0
+
+ .text
+ .set noreorder
+
+/* unknown src alignment and < 8 bytes to go */
+small_csumcpy:
+ move a1, ta2
+
+ andi ta0, a1, 4
+ beqz ta0, 1f
+ andi ta0, a1, 2
+
+ /* Still a full word to go */
+ ulw ta1, (src)
+ daddiu src, 4
+ ADDC(sum, ta1)
+
+1: move ta1, zero
+ beqz ta0, 1f
+ andi ta0, a1, 1
+
+ /* Still a halfword to go */
+ ulhu ta1, (src)
+ daddiu src, 2
+
+1: beqz ta0, 1f
+ sll ta1, ta1, 16
+
+ lbu ta2, (src)
+ nop
+
+#ifdef __MIPSEB__
+ sll ta2, ta2, 8
+#endif
+ or ta1, ta2
+
+1: ADDC(sum, ta1)
+
+ /* fold checksum */
+ sll v1, sum, 16
+ addu sum, v1
+ sltu v1, sum, v1
+ srl sum, sum, 16
+ addu sum, v1
+
+ /* odd buffer alignment? */
+ beqz t3, 1f
+ nop
+ sll v1, sum, 8
+ srl sum, sum, 8
+ or sum, v1
+ andi sum, 0xffff
+1:
+ .set reorder
+ /* Add the passed partial csum. */
+ ADDC(sum, a2)
+ jr ra
+ .set noreorder
+
+/* ------------------------------------------------------------------------- */
+
+ .align 5
+LEAF(csum_partial)
+ move sum, zero
+ move t3, zero
+
+ sltiu t8, a1, 0x8
+ bnez t8, small_csumcpy /* < 8 bytes to copy */
+ move ta2, a1
+
+ beqz a1, out
+ andi t3, src, 0x1 /* odd buffer? */
+
+hword_align:
+ beqz t3, word_align
+ andi t8, src, 0x2
+
+ lbu ta0, (src)
+ dsubu a1, a1, 0x1
+#ifdef __MIPSEL__
+ sll ta0, ta0, 8
+#endif
+ ADDC(sum, ta0)
+ daddu src, src, 0x1
+ andi t8, src, 0x2
+
+word_align:
+ beqz t8, dword_align
+ sltiu t8, a1, 56
+
+ lhu ta0, (src)
+ dsubu a1, a1, 0x2
+ ADDC(sum, ta0)
+ sltiu t8, a1, 56
+ daddu src, src, 0x2
+
+dword_align:
+ bnez t8, do_end_words
+ move t8, a1
+
+ andi t8, src, 0x4
+ beqz t8, qword_align
+ andi t8, src, 0x8
+
+ lw ta0, 0x00(src)
+ dsubu a1, a1, 0x4
+ ADDC(sum, ta0)
+ daddu src, src, 0x4
+ andi t8, src, 0x8
+
+qword_align:
+ beqz t8, oword_align
+ andi t8, src, 0x10
+
+ lw ta0, 0x00(src)
+ lw ta1, 0x04(src)
+ dsubu a1, a1, 0x8
+ ADDC(sum, ta0)
+ ADDC(sum, ta1)
+ daddu src, src, 0x8
+ andi t8, src, 0x10
+
+oword_align:
+ beqz t8, begin_movement
+ dsrl t8, a1, 0x7
+
+ lw ta3, 0x08(src)
+ lw t0, 0x0c(src)
+ lw ta0, 0x00(src)
+ lw ta1, 0x04(src)
+ ADDC(sum, ta3)
+ ADDC(sum, t0)
+ ADDC(sum, ta0)
+ ADDC(sum, ta1)
+ dsubu a1, a1, 0x10
+ daddu src, src, 0x10
+ dsrl t8, a1, 0x7
+
+begin_movement:
+ beqz t8, 1f
+ andi ta2, a1, 0x40
+
+move_128bytes:
+ CSUM_BIGCHUNK(src, 0x00, sum, ta0, ta1, ta3, t0)
+ CSUM_BIGCHUNK(src, 0x20, sum, ta0, ta1, ta3, t0)
+ CSUM_BIGCHUNK(src, 0x40, sum, ta0, ta1, ta3, t0)
+ CSUM_BIGCHUNK(src, 0x60, sum, ta0, ta1, ta3, t0)
+ dsubu t8, t8, 0x01
+ bnez t8, move_128bytes
+ daddu src, src, 0x80
+
+1:
+ beqz ta2, 1f
+ andi ta2, a1, 0x20
+
+move_64bytes:
+ CSUM_BIGCHUNK(src, 0x00, sum, ta0, ta1, ta3, t0)
+ CSUM_BIGCHUNK(src, 0x20, sum, ta0, ta1, ta3, t0)
+ daddu src, src, 0x40
+
+1:
+ beqz ta2, do_end_words
+ andi t8, a1, 0x1c
+
+move_32bytes:
+ CSUM_BIGCHUNK(src, 0x00, sum, ta0, ta1, ta3, t0)
+ andi t8, a1, 0x1c
+ daddu src, src, 0x20
+
+do_end_words:
+ beqz t8, maybe_end_cruft
+ dsrl t8, t8, 0x2
+
+end_words:
+ lw ta0, (src)
+ dsubu t8, t8, 0x1
+ ADDC(sum, ta0)
+ bnez t8, end_words
+ daddu src, src, 0x4
+
+maybe_end_cruft:
+ andi ta2, a1, 0x3
+
+small_memcpy:
+ j small_csumcpy; move a1, ta2 /* XXX ??? */
+ beqz t2, out
+ move a1, ta2
+
+end_bytes:
+ lb ta0, (src)
+ dsubu a1, a1, 0x1
+ bnez a2, end_bytes
+ daddu src, src, 0x1
+
+out:
+ jr ra
+ move v0, sum
+ END(csum_partial)
diff --git a/arch/mips/lib-64/dump_tlb.c b/arch/mips/lib-64/dump_tlb.c
new file mode 100644
index 0000000..42f88e0
--- /dev/null
+++ b/arch/mips/lib-64/dump_tlb.c
@@ -0,0 +1,211 @@
+/*
+ * Dump R4x00 TLB for debugging purposes.
+ *
+ * Copyright (C) 1994, 1995 by Waldorf Electronics, written by Ralf Baechle.
+ * Copyright (C) 1999 by Silicon Graphics, Inc.
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+
+#include <asm/bootinfo.h>
+#include <asm/cachectl.h>
+#include <asm/cpu.h>
+#include <asm/mipsregs.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+
+static inline const char *msk2str(unsigned int mask)
+{
+ switch (mask) {
+ case PM_4K: return "4kb";
+ case PM_16K: return "16kb";
+ case PM_64K: return "64kb";
+ case PM_256K: return "256kb";
+#ifndef CONFIG_CPU_VR41XX
+ case PM_1M: return "1Mb";
+ case PM_4M: return "4Mb";
+ case PM_16M: return "16Mb";
+ case PM_64M: return "64Mb";
+ case PM_256M: return "256Mb";
+#endif
+ }
+
+ return "unknown";
+}
+
+#define BARRIER() \
+ __asm__ __volatile__( \
+ ".set\tnoreorder\n\t" \
+ "nop;nop;nop;nop;nop;nop;nop\n\t" \
+ ".set\treorder");
+
+void dump_tlb(int first, int last)
+{
+ unsigned long s_entryhi, entryhi, entrylo0, entrylo1, asid;
+ unsigned int s_index, pagemask, c0, c1, i;
+
+ s_entryhi = read_c0_entryhi();
+ s_index = read_c0_index();
+ asid = s_entryhi & 0xff;
+
+ for (i = first; i <= last; i++) {
+ write_c0_index(i);
+ BARRIER();
+ tlb_read();
+ BARRIER();
+ pagemask = read_c0_pagemask();
+ entryhi = read_c0_entryhi();
+ entrylo0 = read_c0_entrylo0();
+ entrylo1 = read_c0_entrylo1();
+
+ /* Unused entries have a virtual address of CKSEG0. */
+ if ((entryhi & ~0x1ffffUL) != CKSEG0
+ && (entryhi & 0xff) == asid) {
+ /*
+ * Only print entries in use
+ */
+ printk("Index: %2d pgmask=%s ", i, msk2str(pagemask));
+
+ c0 = (entrylo0 >> 3) & 7;
+ c1 = (entrylo1 >> 3) & 7;
+
+ printk("va=%011lx asid=%02lx\n",
+ (entryhi & ~0x1fffUL),
+ entryhi & 0xff);
+ printk("\t[pa=%011lx c=%d d=%d v=%d g=%ld] ",
+ (entrylo0 << 6) & PAGE_MASK, c0,
+ (entrylo0 & 4) ? 1 : 0,
+ (entrylo0 & 2) ? 1 : 0,
+ (entrylo0 & 1));
+ printk("[pa=%011lx c=%d d=%d v=%d g=%ld]\n",
+ (entrylo1 << 6) & PAGE_MASK, c1,
+ (entrylo1 & 4) ? 1 : 0,
+ (entrylo1 & 2) ? 1 : 0,
+ (entrylo1 & 1));
+ }
+ }
+ printk("\n");
+
+ write_c0_entryhi(s_entryhi);
+ write_c0_index(s_index);
+}
+
+void dump_tlb_all(void)
+{
+ dump_tlb(0, current_cpu_data.tlbsize - 1);
+}
+
+void dump_tlb_wired(void)
+{
+ int wired;
+
+ wired = read_c0_wired();
+ printk("Wired: %d", wired);
+ dump_tlb(0, read_c0_wired());
+}
+
+void dump_tlb_addr(unsigned long addr)
+{
+ unsigned int flags, oldpid;
+ int index;
+
+ local_irq_save(flags);
+ oldpid = read_c0_entryhi() & 0xff;
+ BARRIER();
+ write_c0_entryhi((addr & PAGE_MASK) | oldpid);
+ BARRIER();
+ tlb_probe();
+ BARRIER();
+ index = read_c0_index();
+ write_c0_entryhi(oldpid);
+ local_irq_restore(flags);
+
+ if (index < 0) {
+ printk("No entry for address 0x%08lx in TLB\n", addr);
+ return;
+ }
+
+ printk("Entry %d maps address 0x%08lx\n", index, addr);
+ dump_tlb(index, index);
+}
+
+void dump_tlb_nonwired(void)
+{
+ dump_tlb(read_c0_wired(), current_cpu_data.tlbsize - 1);
+}
+
+void dump_list_process(struct task_struct *t, void *address)
+{
+ pgd_t *page_dir, *pgd;
+ pmd_t *pmd;
+ pte_t *pte, page;
+ unsigned long addr, val;
+
+ addr = (unsigned long) address;
+
+ printk("Addr == %08lx\n", addr);
+ printk("tasks->mm.pgd == %08lx\n", (unsigned long) t->mm->pgd);
+
+ page_dir = pgd_offset(t->mm, 0);
+ printk("page_dir == %016lx\n", (unsigned long) page_dir);
+
+ pgd = pgd_offset(t->mm, addr);
+ printk("pgd == %016lx\n", (unsigned long) pgd);
+
+ pmd = pmd_offset(pgd, addr);
+ printk("pmd == %016lx\n", (unsigned long) pmd);
+
+ pte = pte_offset(pmd, addr);
+ printk("pte == %016lx\n", (unsigned long) pte);
+
+ page = *pte;
+ printk("page == %08lx\n", pte_val(page));
+
+ val = pte_val(page);
+ if (val & _PAGE_PRESENT) printk("present ");
+ if (val & _PAGE_READ) printk("read ");
+ if (val & _PAGE_WRITE) printk("write ");
+ if (val & _PAGE_ACCESSED) printk("accessed ");
+ if (val & _PAGE_MODIFIED) printk("modified ");
+ if (val & _PAGE_R4KBUG) printk("r4kbug ");
+ if (val & _PAGE_GLOBAL) printk("global ");
+ if (val & _PAGE_VALID) printk("valid ");
+ printk("\n");
+}
+
+void dump_list_current(void *address)
+{
+ dump_list_process(current, address);
+}
+
+unsigned int vtop(void *address)
+{
+ pgd_t *pgd;
+ pmd_t *pmd;
+ pte_t *pte;
+ unsigned int addr, paddr;
+
+ addr = (unsigned long) address;
+ pgd = pgd_offset(current->mm, addr);
+ pmd = pmd_offset(pgd, addr);
+ pte = pte_offset(pmd, addr);
+ paddr = (CKSEG1 | (unsigned int) pte_val(*pte)) & PAGE_MASK;
+ paddr |= (addr & ~PAGE_MASK);
+
+ return paddr;
+}
+
+void dump16(unsigned long *p)
+{
+ int i;
+
+ for (i = 0; i < 8; i++) {
+ printk("*%08lx == %08lx, ", (unsigned long)p, *p);
+ p++;
+ printk("*%08lx == %08lx\n", (unsigned long)p, *p);
+ p++;
+ }
+}
diff --git a/arch/mips/lib-64/memset.S b/arch/mips/lib-64/memset.S
new file mode 100644
index 0000000..242f197
--- /dev/null
+++ b/arch/mips/lib-64/memset.S
@@ -0,0 +1,142 @@
+/*
+ * 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) 1998, 1999, 2000 by Ralf Baechle
+ * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
+ */
+#include <asm/asm.h>
+#include <asm/offset.h>
+#include <asm/regdef.h>
+
+#define EX(insn,reg,addr,handler) \
+9: insn reg, addr; \
+ .section __ex_table,"a"; \
+ PTR 9b, handler; \
+ .previous
+
+ .macro f_fill64 dst, offset, val, fixup
+ EX(LONG_S, \val, (\offset + 0 * LONGSIZE)(\dst), \fixup)
+ EX(LONG_S, \val, (\offset + 1 * LONGSIZE)(\dst), \fixup)
+ EX(LONG_S, \val, (\offset + 2 * LONGSIZE)(\dst), \fixup)
+ EX(LONG_S, \val, (\offset + 3 * LONGSIZE)(\dst), \fixup)
+ EX(LONG_S, \val, (\offset + 4 * LONGSIZE)(\dst), \fixup)
+ EX(LONG_S, \val, (\offset + 5 * LONGSIZE)(\dst), \fixup)
+ EX(LONG_S, \val, (\offset + 6 * LONGSIZE)(\dst), \fixup)
+ EX(LONG_S, \val, (\offset + 7 * LONGSIZE)(\dst), \fixup)
+ .endm
+
+/*
+ * memset(void *s, int c, size_t n)
+ *
+ * a0: start of area to clear
+ * a1: char to fill with
+ * a2: size of area to clear
+ */
+ .set noreorder
+ .align 5
+LEAF(memset)
+ beqz a1, 1f
+ move v0, a0 /* result */
+
+ andi a1, 0xff /* spread fillword */
+ dsll t1, a1, 8
+ or a1, t1
+ dsll t1, a1, 16
+ or a1, t1
+ dsll t1, a1, 32
+ or a1, t1
+1:
+
+FEXPORT(__bzero)
+ sltiu t0, a2, LONGSIZE /* very small region? */
+ bnez t0, small_memset
+ andi t0, a0, LONGMASK /* aligned? */
+
+ beqz t0, 1f
+ PTR_SUBU t0, LONGSIZE /* alignment in bytes */
+
+#ifdef __MIPSEB__
+ EX(sdl, a1, (a0), first_fixup) /* make dword aligned */
+#endif
+#ifdef __MIPSEL__
+ EX(sdr, a1, (a0), first_fixup) /* make dword aligned */
+#endif
+ PTR_SUBU a0, t0 /* long align ptr */
+ PTR_ADDU a2, t0 /* correct size */
+
+1: ori t1, a2, 0x3f /* # of full blocks */
+ xori t1, 0x3f
+ beqz t1, memset_partial /* no block to fill */
+ andi t0, a2, 0x38
+
+ PTR_ADDU t1, a0 /* end address */
+ .set reorder
+1: PTR_ADDIU a0, 64
+ f_fill64 a0, -64, a1, fwd_fixup
+ bne t1, a0, 1b
+ .set noreorder
+
+memset_partial:
+ PTR_LA t1, 2f /* where to start */
+ .set noat
+ dsrl AT, t0, 1
+ PTR_SUBU t1, AT
+ .set noat
+ jr t1
+ PTR_ADDU a0, t0 /* dest ptr */
+
+ .set push
+ .set noreorder
+ .set nomacro
+ f_fill64 a0, -64, a1, partial_fixup /* ... but first do longs ... */
+2: .set pop
+ andi a2, LONGMASK /* At most one long to go */
+
+ beqz a2, 1f
+ PTR_ADDU a0, a2 /* What's left */
+#ifdef __MIPSEB__
+ EX(sdr, a1, -1(a0), last_fixup)
+#endif
+#ifdef __MIPSEL__
+ EX(sdl, a1, -1(a0), last_fixup)
+#endif
+1: jr ra
+ move a2, zero
+
+small_memset:
+ beqz a2, 2f
+ PTR_ADDU t1, a0, a2
+
+1: PTR_ADDIU a0, 1 /* fill bytewise */
+ bne t1, a0, 1b
+ sb a1, -1(a0)
+
+2: jr ra /* done */
+ move a2, zero
+ END(memset)
+
+first_fixup:
+ jr ra
+ nop
+
+fwd_fixup:
+ PTR_L t0, TI_TASK($28)
+ LONG_L t0, THREAD_BUADDR(t0)
+ andi a2, 0x3f
+ LONG_ADDU a2, t1
+ jr ra
+ LONG_SUBU a2, t0
+
+partial_fixup:
+ PTR_L t0, TI_TASK($28)
+ LONG_L t0, THREAD_BUADDR(t0)
+ andi a2, LONGMASK
+ LONG_ADDU a2, t1
+ jr ra
+ LONG_SUBU a2, t0
+
+last_fixup:
+ jr ra
+ andi v1, a2, LONGMASK
diff --git a/arch/mips/lib-64/watch.S b/arch/mips/lib-64/watch.S
new file mode 100644
index 0000000..f914340
--- /dev/null
+++ b/arch/mips/lib-64/watch.S
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ *
+ * Kernel debug stuff to use the Watch registers.
+ * Useful to find stack overflows, dangling pointers etc.
+ *
+ * Copyright (C) 1995, 1996, 1999, 2001 by Ralf Baechle
+ */
+#include <asm/asm.h>
+#include <asm/mipsregs.h>
+#include <asm/regdef.h>
+
+ .set noreorder
+/*
+ * Parameter: a0 - physical address to watch
+ * a1 - set bit #1 to trap on load references
+ * bit #0 to trap on store references
+ * Results : none
+ */
+ LEAF(__watch_set)
+ ori a0, 7
+ xori a0, 7
+ or a0, a1
+ mtc0 a0, CP0_WATCHLO
+ sd a0, watch_savelo
+ dsrl32 a0, a0, 0
+
+ jr ra
+ mtc0 zero, CP0_WATCHHI
+ END(__watch_set)
+
+/*
+ * Parameter: none
+ * Results : none
+ */
+ LEAF(__watch_clear)
+ jr ra
+ mtc0 zero, CP0_WATCHLO
+ END(__watch_clear)
+
+/*
+ * Parameter: none
+ * Results : none
+ */
+ LEAF(__watch_reenable)
+ ld t0, watch_savelo
+ jr ra
+ mtc0 t0, CP0_WATCHLO
+ END(__watch_reenable)
+
+/*
+ * Saved value of the c0_watchlo register for watch_reenable()
+ */
+ .local watch_savelo
+ .comm watch_savelo, 8, 8
diff --git a/arch/mips/lib/Makefile b/arch/mips/lib/Makefile
new file mode 100644
index 0000000..21b92b9
--- /dev/null
+++ b/arch/mips/lib/Makefile
@@ -0,0 +1,10 @@
+#
+# Makefile for MIPS-specific library files..
+#
+
+lib-y += csum_partial_copy.o dec_and_lock.o memcpy.o promlib.o \
+ strlen_user.o strncpy_user.o strnlen_user.o
+
+obj-y += iomap.o
+
+EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/lib/csum_partial_copy.c b/arch/mips/lib/csum_partial_copy.c
new file mode 100644
index 0000000..ffed0a6
--- /dev/null
+++ b/arch/mips/lib/csum_partial_copy.c
@@ -0,0 +1,49 @@
+/*
+ * 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) 1994, 1995 Waldorf Electronics GmbH
+ * Copyright (C) 1998, 1999 Ralf Baechle
+ */
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <asm/byteorder.h>
+#include <asm/string.h>
+#include <asm/uaccess.h>
+#include <net/checksum.h>
+
+/*
+ * copy while checksumming, otherwise like csum_partial
+ */
+unsigned int csum_partial_copy_nocheck(const unsigned char *src, unsigned char *dst,
+ int len, unsigned int sum)
+{
+ /*
+ * It's 2:30 am and I don't feel like doing it real ...
+ * This is lots slower than the real thing (tm)
+ */
+ sum = csum_partial(src, len, sum);
+ memcpy(dst, src, len);
+
+ return sum;
+}
+
+/*
+ * Copy from userspace and compute checksum. If we catch an exception
+ * then zero the rest of the buffer.
+ */
+unsigned int csum_partial_copy_from_user (const unsigned char *src, unsigned char *dst,
+ int len, unsigned int sum, int *err_ptr)
+{
+ int missing;
+
+ might_sleep();
+ missing = copy_from_user(dst, src, len);
+ if (missing) {
+ memset(dst + len - missing, 0, missing);
+ *err_ptr = -EFAULT;
+ }
+
+ return csum_partial(dst, len, sum);
+}
diff --git a/arch/mips/lib/dec_and_lock.c b/arch/mips/lib/dec_and_lock.c
new file mode 100644
index 0000000..e44e957
--- /dev/null
+++ b/arch/mips/lib/dec_and_lock.c
@@ -0,0 +1,55 @@
+/*
+ * MIPS version of atomic_dec_and_lock() using cmpxchg
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <asm/atomic.h>
+#include <asm/system.h>
+
+/*
+ * This is an implementation of the notion of "decrement a
+ * reference count, and return locked if it decremented to zero".
+ *
+ * This implementation can be used on any architecture that
+ * has a cmpxchg, and where atomic->value is an int holding
+ * the value of the atomic (i.e. the high bits aren't used
+ * for a lock or anything like that).
+ *
+ * N.B. ATOMIC_DEC_AND_LOCK gets defined in include/linux/spinlock.h
+ * if spinlocks are empty and thus atomic_dec_and_lock is defined
+ * to be atomic_dec_and_test - in that case we don't need it
+ * defined here as well.
+ */
+
+#ifndef ATOMIC_DEC_AND_LOCK
+int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock)
+{
+ int counter;
+ int newcount;
+
+ for (;;) {
+ counter = atomic_read(atomic);
+ newcount = counter - 1;
+ if (!newcount)
+ break; /* do it the slow way */
+
+ newcount = cmpxchg(&atomic->counter, counter, newcount);
+ if (newcount == counter)
+ return 0;
+ }
+
+ spin_lock(lock);
+ if (atomic_dec_and_test(atomic))
+ return 1;
+ spin_unlock(lock);
+ return 0;
+}
+
+EXPORT_SYMBOL(_atomic_dec_and_lock);
+#endif /* ATOMIC_DEC_AND_LOCK */
diff --git a/arch/mips/lib/iomap.c b/arch/mips/lib/iomap.c
new file mode 100644
index 0000000..b5d5fa8
--- /dev/null
+++ b/arch/mips/lib/iomap.c
@@ -0,0 +1,78 @@
+/*
+ * iomap.c, Memory Mapped I/O routines for MIPS architecture.
+ *
+ * This code is based on lib/iomap.c, by Linus Torvalds.
+ *
+ * Copyright (C) 2004-2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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 <linux/ioport.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+
+#include <asm/io.h>
+
+void __iomem *ioport_map(unsigned long port, unsigned int nr)
+{
+ unsigned long end;
+
+ end = port + nr - 1UL;
+ if (ioport_resource.start > port ||
+ ioport_resource.end < end || port > end)
+ return NULL;
+
+ return (void __iomem *)(mips_io_port_base + port);
+}
+
+void ioport_unmap(void __iomem *addr)
+{
+}
+EXPORT_SYMBOL(ioport_map);
+EXPORT_SYMBOL(ioport_unmap);
+
+void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
+{
+ unsigned long start, len, flags;
+
+ if (dev == NULL)
+ return NULL;
+
+ start = pci_resource_start(dev, bar);
+ len = pci_resource_len(dev, bar);
+ if (!start || !len)
+ return NULL;
+
+ if (maxlen != 0 && len > maxlen)
+ len = maxlen;
+
+ flags = pci_resource_flags(dev, bar);
+ if (flags & IORESOURCE_IO)
+ return ioport_map(start, len);
+ if (flags & IORESOURCE_MEM) {
+ if (flags & IORESOURCE_CACHEABLE)
+ return ioremap_cacheable_cow(start, len);
+ return ioremap_nocache(start, len);
+ }
+
+ return NULL;
+}
+
+void pci_iounmap(struct pci_dev *dev, void __iomem *addr)
+{
+ iounmap(addr);
+}
+EXPORT_SYMBOL(pci_iomap);
+EXPORT_SYMBOL(pci_iounmap);
diff --git a/arch/mips/lib/memcpy.S b/arch/mips/lib/memcpy.S
new file mode 100644
index 0000000..afa8eae
--- /dev/null
+++ b/arch/mips/lib/memcpy.S
@@ -0,0 +1,508 @@
+/*
+ * 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.
+ *
+ * Unified implementation of memcpy, memmove and the __copy_user backend.
+ *
+ * Copyright (C) 1998, 99, 2000, 01, 2002 Ralf Baechle (ralf@gnu.org)
+ * Copyright (C) 1999, 2000, 01, 2002 Silicon Graphics, Inc.
+ * Copyright (C) 2002 Broadcom, Inc.
+ * memcpy/copy_user author: Mark Vandevoorde
+ *
+ * Mnemonic names for arguments to memcpy/__copy_user
+ */
+#include <linux/config.h>
+#include <asm/asm.h>
+#include <asm/offset.h>
+#include <asm/regdef.h>
+
+#define dst a0
+#define src a1
+#define len a2
+
+/*
+ * Spec
+ *
+ * memcpy copies len bytes from src to dst and sets v0 to dst.
+ * It assumes that
+ * - src and dst don't overlap
+ * - src is readable
+ * - dst is writable
+ * memcpy uses the standard calling convention
+ *
+ * __copy_user copies up to len bytes from src to dst and sets a2 (len) to
+ * the number of uncopied bytes due to an exception caused by a read or write.
+ * __copy_user assumes that src and dst don't overlap, and that the call is
+ * implementing one of the following:
+ * copy_to_user
+ * - src is readable (no exceptions when reading src)
+ * copy_from_user
+ * - dst is writable (no exceptions when writing dst)
+ * __copy_user uses a non-standard calling convention; see
+ * include/asm-mips/uaccess.h
+ *
+ * When an exception happens on a load, the handler must
+ # ensure that all of the destination buffer is overwritten to prevent
+ * leaking information to user mode programs.
+ */
+
+/*
+ * Implementation
+ */
+
+/*
+ * The exception handler for loads requires that:
+ * 1- AT contain the address of the byte just past the end of the source
+ * of the copy,
+ * 2- src_entry <= src < AT, and
+ * 3- (dst - src) == (dst_entry - src_entry),
+ * The _entry suffix denotes values when __copy_user was called.
+ *
+ * (1) is set up up by uaccess.h and maintained by not writing AT in copy_user
+ * (2) is met by incrementing src by the number of bytes copied
+ * (3) is met by not doing loads between a pair of increments of dst and src
+ *
+ * The exception handlers for stores adjust len (if necessary) and return.
+ * These handlers do not need to overwrite any data.
+ *
+ * For __rmemcpy and memmove an exception is always a kernel bug, therefore
+ * they're not protected.
+ */
+
+#define EXC(inst_reg,addr,handler) \
+9: inst_reg, addr; \
+ .section __ex_table,"a"; \
+ PTR 9b, handler; \
+ .previous
+
+/*
+ * Only on the 64-bit kernel we can made use of 64-bit registers.
+ */
+#ifdef CONFIG_MIPS64
+#define USE_DOUBLE
+#endif
+
+#ifdef USE_DOUBLE
+
+#define LOAD ld
+#define LOADL ldl
+#define LOADR ldr
+#define STOREL sdl
+#define STORER sdr
+#define STORE sd
+#define ADD daddu
+#define SUB dsubu
+#define SRL dsrl
+#define SRA dsra
+#define SLL dsll
+#define SLLV dsllv
+#define SRLV dsrlv
+#define NBYTES 8
+#define LOG_NBYTES 3
+
+/*
+ * As we are sharing code base with the mips32 tree (which use the o32 ABI
+ * register definitions). We need to redefine the register definitions from
+ * the n64 ABI register naming to the o32 ABI register naming.
+ */
+#undef t0
+#undef t1
+#undef t2
+#undef t3
+#define t0 $8
+#define t1 $9
+#define t2 $10
+#define t3 $11
+#define t4 $12
+#define t5 $13
+#define t6 $14
+#define t7 $15
+
+#else
+
+#define LOAD lw
+#define LOADL lwl
+#define LOADR lwr
+#define STOREL swl
+#define STORER swr
+#define STORE sw
+#define ADD addu
+#define SUB subu
+#define SRL srl
+#define SLL sll
+#define SRA sra
+#define SLLV sllv
+#define SRLV srlv
+#define NBYTES 4
+#define LOG_NBYTES 2
+
+#endif /* USE_DOUBLE */
+
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+#define LDFIRST LOADR
+#define LDREST LOADL
+#define STFIRST STORER
+#define STREST STOREL
+#define SHIFT_DISCARD SLLV
+#else
+#define LDFIRST LOADL
+#define LDREST LOADR
+#define STFIRST STOREL
+#define STREST STORER
+#define SHIFT_DISCARD SRLV
+#endif
+
+#define FIRST(unit) ((unit)*NBYTES)
+#define REST(unit) (FIRST(unit)+NBYTES-1)
+#define UNIT(unit) FIRST(unit)
+
+#define ADDRMASK (NBYTES-1)
+
+ .text
+ .set noreorder
+ .set noat
+
+/*
+ * A combined memcpy/__copy_user
+ * __copy_user sets len to 0 for success; else to an upper bound of
+ * the number of uncopied bytes.
+ * memcpy sets v0 to dst.
+ */
+ .align 5
+LEAF(memcpy) /* a0=dst a1=src a2=len */
+ move v0, dst /* return value */
+__memcpy:
+FEXPORT(__copy_user)
+ /*
+ * Note: dst & src may be unaligned, len may be 0
+ * Temps
+ */
+#define rem t8
+
+ /*
+ * The "issue break"s below are very approximate.
+ * Issue delays for dcache fills will perturb the schedule, as will
+ * load queue full replay traps, etc.
+ *
+ * If len < NBYTES use byte operations.
+ */
+ PREF( 0, 0(src) )
+ PREF( 1, 0(dst) )
+ sltu t2, len, NBYTES
+ and t1, dst, ADDRMASK
+ PREF( 0, 1*32(src) )
+ PREF( 1, 1*32(dst) )
+ bnez t2, copy_bytes_checklen
+ and t0, src, ADDRMASK
+ PREF( 0, 2*32(src) )
+ PREF( 1, 2*32(dst) )
+ bnez t1, dst_unaligned
+ nop
+ bnez t0, src_unaligned_dst_aligned
+ /*
+ * use delay slot for fall-through
+ * src and dst are aligned; need to compute rem
+ */
+both_aligned:
+ SRL t0, len, LOG_NBYTES+3 # +3 for 8 units/iter
+ beqz t0, cleanup_both_aligned # len < 8*NBYTES
+ and rem, len, (8*NBYTES-1) # rem = len % (8*NBYTES)
+ PREF( 0, 3*32(src) )
+ PREF( 1, 3*32(dst) )
+ .align 4
+1:
+EXC( LOAD t0, UNIT(0)(src), l_exc)
+EXC( LOAD t1, UNIT(1)(src), l_exc_copy)
+EXC( LOAD t2, UNIT(2)(src), l_exc_copy)
+EXC( LOAD t3, UNIT(3)(src), l_exc_copy)
+ SUB len, len, 8*NBYTES
+EXC( LOAD t4, UNIT(4)(src), l_exc_copy)
+EXC( LOAD t7, UNIT(5)(src), l_exc_copy)
+EXC( STORE t0, UNIT(0)(dst), s_exc_p8u)
+EXC( STORE t1, UNIT(1)(dst), s_exc_p7u)
+EXC( LOAD t0, UNIT(6)(src), l_exc_copy)
+EXC( LOAD t1, UNIT(7)(src), l_exc_copy)
+ ADD src, src, 8*NBYTES
+ ADD dst, dst, 8*NBYTES
+EXC( STORE t2, UNIT(-6)(dst), s_exc_p6u)
+EXC( STORE t3, UNIT(-5)(dst), s_exc_p5u)
+EXC( STORE t4, UNIT(-4)(dst), s_exc_p4u)
+EXC( STORE t7, UNIT(-3)(dst), s_exc_p3u)
+EXC( STORE t0, UNIT(-2)(dst), s_exc_p2u)
+EXC( STORE t1, UNIT(-1)(dst), s_exc_p1u)
+ PREF( 0, 8*32(src) )
+ PREF( 1, 8*32(dst) )
+ bne len, rem, 1b
+ nop
+
+ /*
+ * len == rem == the number of bytes left to copy < 8*NBYTES
+ */
+cleanup_both_aligned:
+ beqz len, done
+ sltu t0, len, 4*NBYTES
+ bnez t0, less_than_4units
+ and rem, len, (NBYTES-1) # rem = len % NBYTES
+ /*
+ * len >= 4*NBYTES
+ */
+EXC( LOAD t0, UNIT(0)(src), l_exc)
+EXC( LOAD t1, UNIT(1)(src), l_exc_copy)
+EXC( LOAD t2, UNIT(2)(src), l_exc_copy)
+EXC( LOAD t3, UNIT(3)(src), l_exc_copy)
+ SUB len, len, 4*NBYTES
+ ADD src, src, 4*NBYTES
+EXC( STORE t0, UNIT(0)(dst), s_exc_p4u)
+EXC( STORE t1, UNIT(1)(dst), s_exc_p3u)
+EXC( STORE t2, UNIT(2)(dst), s_exc_p2u)
+EXC( STORE t3, UNIT(3)(dst), s_exc_p1u)
+ beqz len, done
+ ADD dst, dst, 4*NBYTES
+less_than_4units:
+ /*
+ * rem = len % NBYTES
+ */
+ beq rem, len, copy_bytes
+ nop
+1:
+EXC( LOAD t0, 0(src), l_exc)
+ ADD src, src, NBYTES
+ SUB len, len, NBYTES
+EXC( STORE t0, 0(dst), s_exc_p1u)
+ bne rem, len, 1b
+ ADD dst, dst, NBYTES
+
+ /*
+ * src and dst are aligned, need to copy rem bytes (rem < NBYTES)
+ * A loop would do only a byte at a time with possible branch
+ * mispredicts. Can't do an explicit LOAD dst,mask,or,STORE
+ * because can't assume read-access to dst. Instead, use
+ * STREST dst, which doesn't require read access to dst.
+ *
+ * This code should perform better than a simple loop on modern,
+ * wide-issue mips processors because the code has fewer branches and
+ * more instruction-level parallelism.
+ */
+#define bits t2
+ beqz len, done
+ ADD t1, dst, len # t1 is just past last byte of dst
+ li bits, 8*NBYTES
+ SLL rem, len, 3 # rem = number of bits to keep
+EXC( LOAD t0, 0(src), l_exc)
+ SUB bits, bits, rem # bits = number of bits to discard
+ SHIFT_DISCARD t0, t0, bits
+EXC( STREST t0, -1(t1), s_exc)
+ jr ra
+ move len, zero
+dst_unaligned:
+ /*
+ * dst is unaligned
+ * t0 = src & ADDRMASK
+ * t1 = dst & ADDRMASK; T1 > 0
+ * len >= NBYTES
+ *
+ * Copy enough bytes to align dst
+ * Set match = (src and dst have same alignment)
+ */
+#define match rem
+EXC( LDFIRST t3, FIRST(0)(src), l_exc)
+ ADD t2, zero, NBYTES
+EXC( LDREST t3, REST(0)(src), l_exc_copy)
+ SUB t2, t2, t1 # t2 = number of bytes copied
+ xor match, t0, t1
+EXC( STFIRST t3, FIRST(0)(dst), s_exc)
+ beq len, t2, done
+ SUB len, len, t2
+ ADD dst, dst, t2
+ beqz match, both_aligned
+ ADD src, src, t2
+
+src_unaligned_dst_aligned:
+ SRL t0, len, LOG_NBYTES+2 # +2 for 4 units/iter
+ PREF( 0, 3*32(src) )
+ beqz t0, cleanup_src_unaligned
+ and rem, len, (4*NBYTES-1) # rem = len % 4*NBYTES
+ PREF( 1, 3*32(dst) )
+1:
+/*
+ * Avoid consecutive LD*'s to the same register since some mips
+ * implementations can't issue them in the same cycle.
+ * It's OK to load FIRST(N+1) before REST(N) because the two addresses
+ * are to the same unit (unless src is aligned, but it's not).
+ */
+EXC( LDFIRST t0, FIRST(0)(src), l_exc)
+EXC( LDFIRST t1, FIRST(1)(src), l_exc_copy)
+ SUB len, len, 4*NBYTES
+EXC( LDREST t0, REST(0)(src), l_exc_copy)
+EXC( LDREST t1, REST(1)(src), l_exc_copy)
+EXC( LDFIRST t2, FIRST(2)(src), l_exc_copy)
+EXC( LDFIRST t3, FIRST(3)(src), l_exc_copy)
+EXC( LDREST t2, REST(2)(src), l_exc_copy)
+EXC( LDREST t3, REST(3)(src), l_exc_copy)
+ PREF( 0, 9*32(src) ) # 0 is PREF_LOAD (not streamed)
+ ADD src, src, 4*NBYTES
+#ifdef CONFIG_CPU_SB1
+ nop # improves slotting
+#endif
+EXC( STORE t0, UNIT(0)(dst), s_exc_p4u)
+EXC( STORE t1, UNIT(1)(dst), s_exc_p3u)
+EXC( STORE t2, UNIT(2)(dst), s_exc_p2u)
+EXC( STORE t3, UNIT(3)(dst), s_exc_p1u)
+ PREF( 1, 9*32(dst) ) # 1 is PREF_STORE (not streamed)
+ bne len, rem, 1b
+ ADD dst, dst, 4*NBYTES
+
+cleanup_src_unaligned:
+ beqz len, done
+ and rem, len, NBYTES-1 # rem = len % NBYTES
+ beq rem, len, copy_bytes
+ nop
+1:
+EXC( LDFIRST t0, FIRST(0)(src), l_exc)
+EXC( LDREST t0, REST(0)(src), l_exc_copy)
+ ADD src, src, NBYTES
+ SUB len, len, NBYTES
+EXC( STORE t0, 0(dst), s_exc_p1u)
+ bne len, rem, 1b
+ ADD dst, dst, NBYTES
+
+copy_bytes_checklen:
+ beqz len, done
+ nop
+copy_bytes:
+ /* 0 < len < NBYTES */
+#define COPY_BYTE(N) \
+EXC( lb t0, N(src), l_exc); \
+ SUB len, len, 1; \
+ beqz len, done; \
+EXC( sb t0, N(dst), s_exc_p1)
+
+ COPY_BYTE(0)
+ COPY_BYTE(1)
+#ifdef USE_DOUBLE
+ COPY_BYTE(2)
+ COPY_BYTE(3)
+ COPY_BYTE(4)
+ COPY_BYTE(5)
+#endif
+EXC( lb t0, NBYTES-2(src), l_exc)
+ SUB len, len, 1
+ jr ra
+EXC( sb t0, NBYTES-2(dst), s_exc_p1)
+done:
+ jr ra
+ nop
+ END(memcpy)
+
+l_exc_copy:
+ /*
+ * Copy bytes from src until faulting load address (or until a
+ * lb faults)
+ *
+ * When reached by a faulting LDFIRST/LDREST, THREAD_BUADDR($28)
+ * may be more than a byte beyond the last address.
+ * Hence, the lb below may get an exception.
+ *
+ * Assumes src < THREAD_BUADDR($28)
+ */
+ LOAD t0, TI_TASK($28)
+ nop
+ LOAD t0, THREAD_BUADDR(t0)
+1:
+EXC( lb t1, 0(src), l_exc)
+ ADD src, src, 1
+ sb t1, 0(dst) # can't fault -- we're copy_from_user
+ bne src, t0, 1b
+ ADD dst, dst, 1
+l_exc:
+ LOAD t0, TI_TASK($28)
+ nop
+ LOAD t0, THREAD_BUADDR(t0) # t0 is just past last good address
+ nop
+ SUB len, AT, t0 # len number of uncopied bytes
+ /*
+ * Here's where we rely on src and dst being incremented in tandem,
+ * See (3) above.
+ * dst += (fault addr - src) to put dst at first byte to clear
+ */
+ ADD dst, t0 # compute start address in a1
+ SUB dst, src
+ /*
+ * Clear len bytes starting at dst. Can't call __bzero because it
+ * might modify len. An inefficient loop for these rare times...
+ */
+ beqz len, done
+ SUB src, len, 1
+1: sb zero, 0(dst)
+ ADD dst, dst, 1
+ bnez src, 1b
+ SUB src, src, 1
+ jr ra
+ nop
+
+
+#define SEXC(n) \
+s_exc_p ## n ## u: \
+ jr ra; \
+ ADD len, len, n*NBYTES
+
+SEXC(8)
+SEXC(7)
+SEXC(6)
+SEXC(5)
+SEXC(4)
+SEXC(3)
+SEXC(2)
+SEXC(1)
+
+s_exc_p1:
+ jr ra
+ ADD len, len, 1
+s_exc:
+ jr ra
+ nop
+
+ .align 5
+LEAF(memmove)
+ ADD t0, a0, a2
+ ADD t1, a1, a2
+ sltu t0, a1, t0 # dst + len <= src -> memcpy
+ sltu t1, a0, t1 # dst >= src + len -> memcpy
+ and t0, t1
+ beqz t0, __memcpy
+ move v0, a0 /* return value */
+ beqz a2, r_out
+ END(memmove)
+
+ /* fall through to __rmemcpy */
+LEAF(__rmemcpy) /* a0=dst a1=src a2=len */
+ sltu t0, a1, a0
+ beqz t0, r_end_bytes_up # src >= dst
+ nop
+ ADD a0, a2 # dst = dst + len
+ ADD a1, a2 # src = src + len
+
+r_end_bytes:
+ lb t0, -1(a1)
+ SUB a2, a2, 0x1
+ sb t0, -1(a0)
+ SUB a1, a1, 0x1
+ bnez a2, r_end_bytes
+ SUB a0, a0, 0x1
+
+r_out:
+ jr ra
+ move a2, zero
+
+r_end_bytes_up:
+ lb t0, (a1)
+ SUB a2, a2, 0x1
+ sb t0, (a0)
+ ADD a1, a1, 0x1
+ bnez a2, r_end_bytes_up
+ ADD a0, a0, 0x1
+
+ jr ra
+ move a2, zero
+ END(__rmemcpy)
diff --git a/arch/mips/lib/promlib.c b/arch/mips/lib/promlib.c
new file mode 100644
index 0000000..dddfe98
--- /dev/null
+++ b/arch/mips/lib/promlib.c
@@ -0,0 +1,24 @@
+#include <stdarg.h>
+#include <linux/kernel.h>
+
+extern void prom_putchar(char);
+
+void prom_printf(char *fmt, ...)
+{
+ va_list args;
+ char ppbuf[1024];
+ char *bptr;
+
+ va_start(args, fmt);
+ vsprintf(ppbuf, fmt, args);
+
+ bptr = ppbuf;
+
+ while (*bptr != 0) {
+ if (*bptr == '\n')
+ prom_putchar('\r');
+
+ prom_putchar(*bptr++);
+ }
+ va_end(args);
+}
diff --git a/arch/mips/lib/strlen_user.S b/arch/mips/lib/strlen_user.S
new file mode 100644
index 0000000..07660e8
--- /dev/null
+++ b/arch/mips/lib/strlen_user.S
@@ -0,0 +1,39 @@
+/*
+ * 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) 1996, 1998, 1999, 2004 by Ralf Baechle
+ * Copyright (c) 1999 Silicon Graphics, Inc.
+ */
+#include <asm/asm.h>
+#include <asm/offset.h>
+#include <asm/regdef.h>
+
+#define EX(insn,reg,addr,handler) \
+9: insn reg, addr; \
+ .section __ex_table,"a"; \
+ PTR 9b, handler; \
+ .previous
+
+/*
+ * Return the size of a string (including the ending 0)
+ *
+ * Return 0 for error
+ */
+LEAF(__strlen_user_asm)
+ LONG_L v0, TI_ADDR_LIMIT($28) # pointer ok?
+ and v0, a0
+ bnez v0, fault
+
+FEXPORT(__strlen_user_nocheck_asm)
+ move v0, a0
+1: EX(lb, t0, (v0), fault)
+ PTR_ADDIU v0, 1
+ bnez t0, 1b
+ PTR_SUBU v0, a0
+ jr ra
+ END(__strlen_user_asm)
+
+fault: move v0, zero
+ jr ra
diff --git a/arch/mips/lib/strncpy_user.S b/arch/mips/lib/strncpy_user.S
new file mode 100644
index 0000000..14bed17
--- /dev/null
+++ b/arch/mips/lib/strncpy_user.S
@@ -0,0 +1,58 @@
+/*
+ * 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) 1996, 1999 by Ralf Baechle
+ */
+#include <linux/errno.h>
+#include <asm/asm.h>
+#include <asm/offset.h>
+#include <asm/regdef.h>
+
+#define EX(insn,reg,addr,handler) \
+9: insn reg, addr; \
+ .section __ex_table,"a"; \
+ PTR 9b, handler; \
+ .previous
+
+/*
+ * Returns: -EFAULT if exception before terminator, N if the entire
+ * buffer filled, else strlen.
+ */
+
+/*
+ * Ugly special case have to check: we might get passed a user space
+ * pointer which wraps into the kernel space. We don't deal with that. If
+ * it happens at most some bytes of the exceptions handlers will be copied.
+ */
+
+LEAF(__strncpy_from_user_asm)
+ LONG_L v0, TI_ADDR_LIMIT($28) # pointer ok?
+ and v0, a1
+ bnez v0, fault
+
+FEXPORT(__strncpy_from_user_nocheck_asm)
+ move v0, zero
+ move v1, a1
+ .set noreorder
+1: EX(lbu, t0, (v1), fault)
+ PTR_ADDIU v1, 1
+ beqz t0, 2f
+ sb t0, (a0)
+ PTR_ADDIU v0, 1
+ bne v0, a2, 1b
+ PTR_ADDIU a0, 1
+ .set reorder
+2: PTR_ADDU t0, a1, v0
+ xor t0, a1
+ bltz t0, fault
+ jr ra # return n
+ END(__strncpy_from_user_asm)
+
+fault: li v0, -EFAULT
+ jr ra
+
+ .section __ex_table,"a"
+ PTR 1b, fault
+ .previous
diff --git a/arch/mips/lib/strnlen_user.S b/arch/mips/lib/strnlen_user.S
new file mode 100644
index 0000000..6e7a8ee
--- /dev/null
+++ b/arch/mips/lib/strnlen_user.S
@@ -0,0 +1,45 @@
+/*
+ * 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) 1996, 1998, 1999, 2004 by Ralf Baechle
+ * Copyright (c) 1999 Silicon Graphics, Inc.
+ */
+#include <asm/asm.h>
+#include <asm/offset.h>
+#include <asm/regdef.h>
+
+#define EX(insn,reg,addr,handler) \
+9: insn reg, addr; \
+ .section __ex_table,"a"; \
+ PTR 9b, handler; \
+ .previous
+
+/*
+ * Return the size of a string including the ending NUL character upto a
+ * maximum of a1 or 0 in case of error.
+ *
+ * Note: for performance reasons we deliberately accept that a user may
+ * make strlen_user and strnlen_user access the first few KSEG0
+ * bytes. There's nothing secret there. On 64-bit accessing beyond
+ * the maximum is a tad hairier ...
+ */
+LEAF(__strnlen_user_asm)
+ LONG_L v0, TI_ADDR_LIMIT($28) # pointer ok?
+ and v0, a0
+ bnez v0, fault
+
+FEXPORT(__strnlen_user_nocheck_asm)
+ move v0, a0
+ PTR_ADDU a1, a0 # stop pointer
+1: beq v0, a1, 1f # limit reached?
+ EX(lb, t0, (v0), fault)
+ PTR_ADDU v0, 1
+ bnez t0, 1b
+1: PTR_SUBU v0, a0
+ jr ra
+ END(__strnlen_user_asm)
+
+fault: move v0, zero
+ jr ra
diff --git a/arch/mips/math-emu/Makefile b/arch/mips/math-emu/Makefile
new file mode 100644
index 0000000..121a848
--- /dev/null
+++ b/arch/mips/math-emu/Makefile
@@ -0,0 +1,11 @@
+#
+# Makefile for the Linux/MIPS kernel FPU emulation.
+#
+
+obj-y := cp1emu.o ieee754m.o ieee754d.o ieee754dp.o ieee754sp.o ieee754.o \
+ ieee754xcpt.o dp_frexp.o dp_modf.o dp_div.o dp_mul.o dp_sub.o \
+ dp_add.o dp_fsp.o dp_cmp.o dp_logb.o dp_scalb.o dp_simple.o \
+ dp_tint.o dp_fint.o dp_tlong.o dp_flong.o sp_frexp.o sp_modf.o \
+ sp_div.o sp_mul.o sp_sub.o sp_add.o sp_fdp.o sp_cmp.o sp_logb.o \
+ sp_scalb.o sp_simple.o sp_tint.o sp_fint.o sp_tlong.o sp_flong.o \
+ dp_sqrt.o sp_sqrt.o kernel_linkage.o dsemul.o
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
new file mode 100644
index 0000000..20a552b
--- /dev/null
+++ b/arch/mips/math-emu/cp1emu.c
@@ -0,0 +1,1322 @@
+/*
+ * cp1emu.c: a MIPS coprocessor 1 (fpu) instruction emulator
+ *
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.
+ * http://www.algor.co.uk
+ *
+ * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2000 MIPS Technologies, Inc.
+ *
+ * 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.
+ *
+ * A complete emulator for MIPS coprocessor 1 instructions. This is
+ * required for #float(switch) or #float(trap), where it catches all
+ * COP1 instructions via the "CoProcessor Unusable" exception.
+ *
+ * More surprisingly it is also required for #float(ieee), to help out
+ * the hardware fpu at the boundaries of the IEEE-754 representation
+ * (denormalised values, infinities, underflow, etc). It is made
+ * quite nasty because emulation of some non-COP1 instructions is
+ * required, e.g. in branch delay slots.
+ *
+ * Note if you know that you won't have an fpu, then you'll get much
+ * better performance by compiling with -msoft-float!
+ */
+#include <linux/sched.h>
+
+#include <asm/inst.h>
+#include <asm/bootinfo.h>
+#include <asm/cpu.h>
+#include <asm/cpu-features.h>
+#include <asm/processor.h>
+#include <asm/ptrace.h>
+#include <asm/signal.h>
+#include <asm/mipsregs.h>
+#include <asm/fpu_emulator.h>
+#include <asm/uaccess.h>
+#include <asm/branch.h>
+
+#include "ieee754.h"
+#include "dsemul.h"
+
+/* Strap kernel emulator for full MIPS IV emulation */
+
+#ifdef __mips
+#undef __mips
+#endif
+#define __mips 4
+
+/* Function which emulates a floating point instruction. */
+
+static int fpu_emu(struct pt_regs *, struct mips_fpu_soft_struct *,
+ mips_instruction);
+
+#if __mips >= 4 && __mips != 32
+static int fpux_emu(struct pt_regs *,
+ struct mips_fpu_soft_struct *, mips_instruction);
+#endif
+
+/* Further private data for which no space exists in mips_fpu_soft_struct */
+
+struct mips_fpu_emulator_private fpuemuprivate;
+
+/* Control registers */
+
+#define FPCREG_RID 0 /* $0 = revision id */
+#define FPCREG_CSR 31 /* $31 = csr */
+
+/* Convert Mips rounding mode (0..3) to IEEE library modes. */
+static const unsigned char ieee_rm[4] = {
+ IEEE754_RN, IEEE754_RZ, IEEE754_RU, IEEE754_RD
+};
+
+#if __mips >= 4
+/* convert condition code register number to csr bit */
+static const unsigned int fpucondbit[8] = {
+ FPU_CSR_COND0,
+ FPU_CSR_COND1,
+ FPU_CSR_COND2,
+ FPU_CSR_COND3,
+ FPU_CSR_COND4,
+ FPU_CSR_COND5,
+ FPU_CSR_COND6,
+ FPU_CSR_COND7
+};
+#endif
+
+
+/*
+ * Redundant with logic already in kernel/branch.c,
+ * embedded in compute_return_epc. At some point,
+ * a single subroutine should be used across both
+ * modules.
+ */
+static int isBranchInstr(mips_instruction * i)
+{
+ switch (MIPSInst_OPCODE(*i)) {
+ case spec_op:
+ switch (MIPSInst_FUNC(*i)) {
+ case jalr_op:
+ case jr_op:
+ return 1;
+ }
+ break;
+
+ case bcond_op:
+ switch (MIPSInst_RT(*i)) {
+ case bltz_op:
+ case bgez_op:
+ case bltzl_op:
+ case bgezl_op:
+ case bltzal_op:
+ case bgezal_op:
+ case bltzall_op:
+ case bgezall_op:
+ return 1;
+ }
+ break;
+
+ case j_op:
+ case jal_op:
+ case jalx_op:
+ case beq_op:
+ case bne_op:
+ case blez_op:
+ case bgtz_op:
+ case beql_op:
+ case bnel_op:
+ case blezl_op:
+ case bgtzl_op:
+ return 1;
+
+ case cop0_op:
+ case cop1_op:
+ case cop2_op:
+ case cop1x_op:
+ if (MIPSInst_RS(*i) == bc_op)
+ return 1;
+ break;
+ }
+
+ return 0;
+}
+
+/*
+ * In the Linux kernel, we support selection of FPR format on the
+ * basis of the Status.FR bit. This does imply that, if a full 32
+ * FPRs are desired, there needs to be a flip-flop that can be written
+ * to one at that bit position. In any case, O32 MIPS ABI uses
+ * only the even FPRs (Status.FR = 0).
+ */
+
+#define CP0_STATUS_FR_SUPPORT
+
+#ifdef CP0_STATUS_FR_SUPPORT
+#define FR_BIT ST0_FR
+#else
+#define FR_BIT 0
+#endif
+
+#define SIFROMREG(si,x) ((si) = \
+ (xcp->cp0_status & FR_BIT) || !(x & 1) ? \
+ (int)ctx->fpr[x] : \
+ (int)(ctx->fpr[x & ~1] >> 32 ))
+#define SITOREG(si,x) (ctx->fpr[x & ~((xcp->cp0_status & FR_BIT) == 0)] = \
+ (xcp->cp0_status & FR_BIT) || !(x & 1) ? \
+ ctx->fpr[x & ~1] >> 32 << 32 | (u32)(si) : \
+ ctx->fpr[x & ~1] << 32 >> 32 | (u64)(si) << 32)
+
+#define DIFROMREG(di,x) ((di) = \
+ ctx->fpr[x & ~((xcp->cp0_status & FR_BIT) == 0)])
+#define DITOREG(di,x) (ctx->fpr[x & ~((xcp->cp0_status & FR_BIT) == 0)] \
+ = (di))
+
+#define SPFROMREG(sp,x) SIFROMREG((sp).bits,x)
+#define SPTOREG(sp,x) SITOREG((sp).bits,x)
+#define DPFROMREG(dp,x) DIFROMREG((dp).bits,x)
+#define DPTOREG(dp,x) DITOREG((dp).bits,x)
+
+/*
+ * Emulate the single floating point instruction pointed at by EPC.
+ * Two instructions if the instruction is in a branch delay slot.
+ */
+
+static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx)
+{
+ mips_instruction ir;
+ vaddr_t emulpc, contpc;
+ unsigned int cond;
+
+ if (get_user(ir, (mips_instruction *) xcp->cp0_epc)) {
+ fpuemuprivate.stats.errors++;
+ return SIGBUS;
+ }
+
+ /* XXX NEC Vr54xx bug workaround */
+ if ((xcp->cp0_cause & CAUSEF_BD) && !isBranchInstr(&ir))
+ xcp->cp0_cause &= ~CAUSEF_BD;
+
+ if (xcp->cp0_cause & CAUSEF_BD) {
+ /*
+ * The instruction to be emulated is in a branch delay slot
+ * which means that we have to emulate the branch instruction
+ * BEFORE we do the cop1 instruction.
+ *
+ * This branch could be a COP1 branch, but in that case we
+ * would have had a trap for that instruction, and would not
+ * come through this route.
+ *
+ * Linux MIPS branch emulator operates on context, updating the
+ * cp0_epc.
+ */
+ emulpc = REG_TO_VA(xcp->cp0_epc + 4); /* Snapshot emulation target */
+
+ if (__compute_return_epc(xcp)) {
+#ifdef CP1DBG
+ printk("failed to emulate branch at %p\n",
+ REG_TO_VA(xcp->cp0_epc));
+#endif
+ return SIGILL;
+ }
+ if (get_user(ir, (mips_instruction *) emulpc)) {
+ fpuemuprivate.stats.errors++;
+ return SIGBUS;
+ }
+ /* __compute_return_epc() will have updated cp0_epc */
+ contpc = REG_TO_VA xcp->cp0_epc;
+ /* In order not to confuse ptrace() et al, tweak context */
+ xcp->cp0_epc = VA_TO_REG emulpc - 4;
+ }
+ else {
+ emulpc = REG_TO_VA xcp->cp0_epc;
+ contpc = REG_TO_VA(xcp->cp0_epc + 4);
+ }
+
+ emul:
+ fpuemuprivate.stats.emulated++;
+ switch (MIPSInst_OPCODE(ir)) {
+#ifndef SINGLE_ONLY_FPU
+ case ldc1_op:{
+ u64 *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)] +
+ MIPSInst_SIMM(ir));
+ u64 val;
+
+ fpuemuprivate.stats.loads++;
+ if (get_user(val, va)) {
+ fpuemuprivate.stats.errors++;
+ return SIGBUS;
+ }
+ DITOREG(val, MIPSInst_RT(ir));
+ break;
+ }
+
+ case sdc1_op:{
+ u64 *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)] +
+ MIPSInst_SIMM(ir));
+ u64 val;
+
+ fpuemuprivate.stats.stores++;
+ DIFROMREG(val, MIPSInst_RT(ir));
+ if (put_user(val, va)) {
+ fpuemuprivate.stats.errors++;
+ return SIGBUS;
+ }
+ break;
+ }
+#endif
+
+ case lwc1_op:{
+ u32 *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)] +
+ MIPSInst_SIMM(ir));
+ u32 val;
+
+ fpuemuprivate.stats.loads++;
+ if (get_user(val, va)) {
+ fpuemuprivate.stats.errors++;
+ return SIGBUS;
+ }
+#ifdef SINGLE_ONLY_FPU
+ if (MIPSInst_RT(ir) & 1) {
+ /* illegal register in single-float mode */
+ return SIGILL;
+ }
+#endif
+ SITOREG(val, MIPSInst_RT(ir));
+ break;
+ }
+
+ case swc1_op:{
+ u32 *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)] +
+ MIPSInst_SIMM(ir));
+ u32 val;
+
+ fpuemuprivate.stats.stores++;
+#ifdef SINGLE_ONLY_FPU
+ if (MIPSInst_RT(ir) & 1) {
+ /* illegal register in single-float mode */
+ return SIGILL;
+ }
+#endif
+ SIFROMREG(val, MIPSInst_RT(ir));
+ if (put_user(val, va)) {
+ fpuemuprivate.stats.errors++;
+ return SIGBUS;
+ }
+ break;
+ }
+
+ case cop1_op:
+ switch (MIPSInst_RS(ir)) {
+
+#if __mips64 && !defined(SINGLE_ONLY_FPU)
+ case dmfc_op:
+ /* copregister fs -> gpr[rt] */
+ if (MIPSInst_RT(ir) != 0) {
+ DIFROMREG(xcp->regs[MIPSInst_RT(ir)],
+ MIPSInst_RD(ir));
+ }
+ break;
+
+ case dmtc_op:
+ /* copregister fs <- rt */
+ DITOREG(xcp->regs[MIPSInst_RT(ir)], MIPSInst_RD(ir));
+ break;
+#endif
+
+ case mfc_op:
+ /* copregister rd -> gpr[rt] */
+#ifdef SINGLE_ONLY_FPU
+ if (MIPSInst_RD(ir) & 1) {
+ /* illegal register in single-float mode */
+ return SIGILL;
+ }
+#endif
+ if (MIPSInst_RT(ir) != 0) {
+ SIFROMREG(xcp->regs[MIPSInst_RT(ir)],
+ MIPSInst_RD(ir));
+ }
+ break;
+
+ case mtc_op:
+ /* copregister rd <- rt */
+#ifdef SINGLE_ONLY_FPU
+ if (MIPSInst_RD(ir) & 1) {
+ /* illegal register in single-float mode */
+ return SIGILL;
+ }
+#endif
+ SITOREG(xcp->regs[MIPSInst_RT(ir)], MIPSInst_RD(ir));
+ break;
+
+ case cfc_op:{
+ /* cop control register rd -> gpr[rt] */
+ u32 value;
+
+ if (ir == CP1UNDEF) {
+ return do_dsemulret(xcp);
+ }
+ if (MIPSInst_RD(ir) == FPCREG_CSR) {
+ value = ctx->fcr31;
+#ifdef CSRTRACE
+ printk("%p gpr[%d]<-csr=%08x\n",
+ REG_TO_VA(xcp->cp0_epc),
+ MIPSInst_RT(ir), value);
+#endif
+ }
+ else if (MIPSInst_RD(ir) == FPCREG_RID)
+ value = 0;
+ else
+ value = 0;
+ if (MIPSInst_RT(ir))
+ xcp->regs[MIPSInst_RT(ir)] = value;
+ break;
+ }
+
+ case ctc_op:{
+ /* copregister rd <- rt */
+ u32 value;
+
+ if (MIPSInst_RT(ir) == 0)
+ value = 0;
+ else
+ value = xcp->regs[MIPSInst_RT(ir)];
+
+ /* we only have one writable control reg
+ */
+ if (MIPSInst_RD(ir) == FPCREG_CSR) {
+#ifdef CSRTRACE
+ printk("%p gpr[%d]->csr=%08x\n",
+ REG_TO_VA(xcp->cp0_epc),
+ MIPSInst_RT(ir), value);
+#endif
+ ctx->fcr31 = value;
+ /* copy new rounding mode and
+ flush bit to ieee library state! */
+ ieee754_csr.nod = (ctx->fcr31 & 0x1000000) != 0;
+ ieee754_csr.rm = ieee_rm[value & 0x3];
+ }
+ if ((ctx->fcr31 >> 5) & ctx->fcr31 & FPU_CSR_ALL_E) {
+ return SIGFPE;
+ }
+ break;
+ }
+
+ case bc_op:{
+ int likely = 0;
+
+ if (xcp->cp0_cause & CAUSEF_BD)
+ return SIGILL;
+
+#if __mips >= 4
+ cond = ctx->fcr31 & fpucondbit[MIPSInst_RT(ir) >> 2];
+#else
+ cond = ctx->fcr31 & FPU_CSR_COND;
+#endif
+ switch (MIPSInst_RT(ir) & 3) {
+ case bcfl_op:
+ likely = 1;
+ case bcf_op:
+ cond = !cond;
+ break;
+ case bctl_op:
+ likely = 1;
+ case bct_op:
+ break;
+ default:
+ /* thats an illegal instruction */
+ return SIGILL;
+ }
+
+ xcp->cp0_cause |= CAUSEF_BD;
+ if (cond) {
+ /* branch taken: emulate dslot
+ * instruction
+ */
+ xcp->cp0_epc += 4;
+ contpc = REG_TO_VA
+ (xcp->cp0_epc +
+ (MIPSInst_SIMM(ir) << 2));
+
+ if (get_user(ir, (mips_instruction *)
+ REG_TO_VA xcp->cp0_epc)) {
+ fpuemuprivate.stats.errors++;
+ return SIGBUS;
+ }
+
+ switch (MIPSInst_OPCODE(ir)) {
+ case lwc1_op:
+ case swc1_op:
+#if (__mips >= 2 || __mips64) && !defined(SINGLE_ONLY_FPU)
+ case ldc1_op:
+ case sdc1_op:
+#endif
+ case cop1_op:
+#if __mips >= 4 && __mips != 32
+ case cop1x_op:
+#endif
+ /* its one of ours */
+ goto emul;
+#if __mips >= 4
+ case spec_op:
+ if (MIPSInst_FUNC(ir) == movc_op)
+ goto emul;
+ break;
+#endif
+ }
+
+ /*
+ * Single step the non-cp1
+ * instruction in the dslot
+ */
+ return mips_dsemul(xcp, ir, VA_TO_REG contpc);
+ }
+ else {
+ /* branch not taken */
+ if (likely) {
+ /*
+ * branch likely nullifies
+ * dslot if not taken
+ */
+ xcp->cp0_epc += 4;
+ contpc += 4;
+ /*
+ * else continue & execute
+ * dslot as normal insn
+ */
+ }
+ }
+ break;
+ }
+
+ default:
+ if (!(MIPSInst_RS(ir) & 0x10))
+ return SIGILL;
+ {
+ int sig;
+
+ /* a real fpu computation instruction */
+ if ((sig = fpu_emu(xcp, ctx, ir)))
+ return sig;
+ }
+ }
+ break;
+
+#if __mips >= 4 && __mips != 32
+ case cop1x_op:{
+ int sig;
+
+ if ((sig = fpux_emu(xcp, ctx, ir)))
+ return sig;
+ break;
+ }
+#endif
+
+#if __mips >= 4
+ case spec_op:
+ if (MIPSInst_FUNC(ir) != movc_op)
+ return SIGILL;
+ cond = fpucondbit[MIPSInst_RT(ir) >> 2];
+ if (((ctx->fcr31 & cond) != 0) == ((MIPSInst_RT(ir) & 1) != 0))
+ xcp->regs[MIPSInst_RD(ir)] =
+ xcp->regs[MIPSInst_RS(ir)];
+ break;
+#endif
+
+ default:
+ return SIGILL;
+ }
+
+ /* we did it !! */
+ xcp->cp0_epc = VA_TO_REG(contpc);
+ xcp->cp0_cause &= ~CAUSEF_BD;
+ return 0;
+}
+
+/*
+ * Conversion table from MIPS compare ops 48-63
+ * cond = ieee754dp_cmp(x,y,IEEE754_UN,sig);
+ */
+static const unsigned char cmptab[8] = {
+ 0, /* cmp_0 (sig) cmp_sf */
+ IEEE754_CUN, /* cmp_un (sig) cmp_ngle */
+ IEEE754_CEQ, /* cmp_eq (sig) cmp_seq */
+ IEEE754_CEQ | IEEE754_CUN, /* cmp_ueq (sig) cmp_ngl */
+ IEEE754_CLT, /* cmp_olt (sig) cmp_lt */
+ IEEE754_CLT | IEEE754_CUN, /* cmp_ult (sig) cmp_nge */
+ IEEE754_CLT | IEEE754_CEQ, /* cmp_ole (sig) cmp_le */
+ IEEE754_CLT | IEEE754_CEQ | IEEE754_CUN, /* cmp_ule (sig) cmp_ngt */
+};
+
+
+#if __mips >= 4 && __mips != 32
+
+/*
+ * Additional MIPS4 instructions
+ */
+
+#define DEF3OP(name, p, f1, f2, f3) \
+static ieee754##p fpemu_##p##_##name (ieee754##p r, ieee754##p s, \
+ ieee754##p t) \
+{ \
+ struct ieee754_csr ieee754_csr_save; \
+ s = f1 (s, t); \
+ ieee754_csr_save = ieee754_csr; \
+ s = f2 (s, r); \
+ ieee754_csr_save.cx |= ieee754_csr.cx; \
+ ieee754_csr_save.sx |= ieee754_csr.sx; \
+ s = f3 (s); \
+ ieee754_csr.cx |= ieee754_csr_save.cx; \
+ ieee754_csr.sx |= ieee754_csr_save.sx; \
+ return s; \
+}
+
+static ieee754dp fpemu_dp_recip(ieee754dp d)
+{
+ return ieee754dp_div(ieee754dp_one(0), d);
+}
+
+static ieee754dp fpemu_dp_rsqrt(ieee754dp d)
+{
+ return ieee754dp_div(ieee754dp_one(0), ieee754dp_sqrt(d));
+}
+
+static ieee754sp fpemu_sp_recip(ieee754sp s)
+{
+ return ieee754sp_div(ieee754sp_one(0), s);
+}
+
+static ieee754sp fpemu_sp_rsqrt(ieee754sp s)
+{
+ return ieee754sp_div(ieee754sp_one(0), ieee754sp_sqrt(s));
+}
+
+DEF3OP(madd, sp, ieee754sp_mul, ieee754sp_add,);
+DEF3OP(msub, sp, ieee754sp_mul, ieee754sp_sub,);
+DEF3OP(nmadd, sp, ieee754sp_mul, ieee754sp_add, ieee754sp_neg);
+DEF3OP(nmsub, sp, ieee754sp_mul, ieee754sp_sub, ieee754sp_neg);
+DEF3OP(madd, dp, ieee754dp_mul, ieee754dp_add,);
+DEF3OP(msub, dp, ieee754dp_mul, ieee754dp_sub,);
+DEF3OP(nmadd, dp, ieee754dp_mul, ieee754dp_add, ieee754dp_neg);
+DEF3OP(nmsub, dp, ieee754dp_mul, ieee754dp_sub, ieee754dp_neg);
+
+static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx,
+ mips_instruction ir)
+{
+ unsigned rcsr = 0; /* resulting csr */
+
+ fpuemuprivate.stats.cp1xops++;
+
+ switch (MIPSInst_FMA_FFMT(ir)) {
+ case s_fmt:{ /* 0 */
+
+ ieee754sp(*handler) (ieee754sp, ieee754sp, ieee754sp);
+ ieee754sp fd, fr, fs, ft;
+ u32 *va;
+ u32 val;
+
+ switch (MIPSInst_FUNC(ir)) {
+ case lwxc1_op:
+ va = REG_TO_VA(xcp->regs[MIPSInst_FR(ir)] +
+ xcp->regs[MIPSInst_FT(ir)]);
+
+ fpuemuprivate.stats.loads++;
+ if (get_user(val, va)) {
+ fpuemuprivate.stats.errors++;
+ return SIGBUS;
+ }
+#ifdef SINGLE_ONLY_FPU
+ if (MIPSInst_FD(ir) & 1) {
+ /* illegal register in single-float
+ * mode
+ */
+ return SIGILL;
+ }
+#endif
+ SITOREG(val, MIPSInst_FD(ir));
+ break;
+
+ case swxc1_op:
+ va = REG_TO_VA(xcp->regs[MIPSInst_FR(ir)] +
+ xcp->regs[MIPSInst_FT(ir)]);
+
+ fpuemuprivate.stats.stores++;
+#ifdef SINGLE_ONLY_FPU
+ if (MIPSInst_FS(ir) & 1) {
+ /* illegal register in single-float
+ * mode
+ */
+ return SIGILL;
+ }
+#endif
+
+ SIFROMREG(val, MIPSInst_FS(ir));
+ if (put_user(val, va)) {
+ fpuemuprivate.stats.errors++;
+ return SIGBUS;
+ }
+ break;
+
+ case madd_s_op:
+ handler = fpemu_sp_madd;
+ goto scoptop;
+ case msub_s_op:
+ handler = fpemu_sp_msub;
+ goto scoptop;
+ case nmadd_s_op:
+ handler = fpemu_sp_nmadd;
+ goto scoptop;
+ case nmsub_s_op:
+ handler = fpemu_sp_nmsub;
+ goto scoptop;
+
+ scoptop:
+ SPFROMREG(fr, MIPSInst_FR(ir));
+ SPFROMREG(fs, MIPSInst_FS(ir));
+ SPFROMREG(ft, MIPSInst_FT(ir));
+ fd = (*handler) (fr, fs, ft);
+ SPTOREG(fd, MIPSInst_FD(ir));
+
+ copcsr:
+ if (ieee754_cxtest(IEEE754_INEXACT))
+ rcsr |= FPU_CSR_INE_X | FPU_CSR_INE_S;
+ if (ieee754_cxtest(IEEE754_UNDERFLOW))
+ rcsr |= FPU_CSR_UDF_X | FPU_CSR_UDF_S;
+ if (ieee754_cxtest(IEEE754_OVERFLOW))
+ rcsr |= FPU_CSR_OVF_X | FPU_CSR_OVF_S;
+ if (ieee754_cxtest(IEEE754_INVALID_OPERATION))
+ rcsr |= FPU_CSR_INV_X | FPU_CSR_INV_S;
+
+ ctx->fcr31 = (ctx->fcr31 & ~FPU_CSR_ALL_X) | rcsr;
+ if (ieee754_csr.nod)
+ ctx->fcr31 |= 0x1000000;
+ if ((ctx->fcr31 >> 5) & ctx->fcr31 & FPU_CSR_ALL_E) {
+ /*printk ("SIGFPE: fpu csr = %08x\n",
+ ctx->fcr31); */
+ return SIGFPE;
+ }
+
+ break;
+
+ default:
+ return SIGILL;
+ }
+ break;
+ }
+
+#ifndef SINGLE_ONLY_FPU
+ case d_fmt:{ /* 1 */
+ ieee754dp(*handler) (ieee754dp, ieee754dp, ieee754dp);
+ ieee754dp fd, fr, fs, ft;
+ u64 *va;
+ u64 val;
+
+ switch (MIPSInst_FUNC(ir)) {
+ case ldxc1_op:
+ va = REG_TO_VA(xcp->regs[MIPSInst_FR(ir)] +
+ xcp->regs[MIPSInst_FT(ir)]);
+
+ fpuemuprivate.stats.loads++;
+ if (get_user(val, va)) {
+ fpuemuprivate.stats.errors++;
+ return SIGBUS;
+ }
+ DITOREG(val, MIPSInst_FD(ir));
+ break;
+
+ case sdxc1_op:
+ va = REG_TO_VA(xcp->regs[MIPSInst_FR(ir)] +
+ xcp->regs[MIPSInst_FT(ir)]);
+
+ fpuemuprivate.stats.stores++;
+ DIFROMREG(val, MIPSInst_FS(ir));
+ if (put_user(val, va)) {
+ fpuemuprivate.stats.errors++;
+ return SIGBUS;
+ }
+ break;
+
+ case madd_d_op:
+ handler = fpemu_dp_madd;
+ goto dcoptop;
+ case msub_d_op:
+ handler = fpemu_dp_msub;
+ goto dcoptop;
+ case nmadd_d_op:
+ handler = fpemu_dp_nmadd;
+ goto dcoptop;
+ case nmsub_d_op:
+ handler = fpemu_dp_nmsub;
+ goto dcoptop;
+
+ dcoptop:
+ DPFROMREG(fr, MIPSInst_FR(ir));
+ DPFROMREG(fs, MIPSInst_FS(ir));
+ DPFROMREG(ft, MIPSInst_FT(ir));
+ fd = (*handler) (fr, fs, ft);
+ DPTOREG(fd, MIPSInst_FD(ir));
+ goto copcsr;
+
+ default:
+ return SIGILL;
+ }
+ break;
+ }
+#endif
+
+ case 0x7: /* 7 */
+ if (MIPSInst_FUNC(ir) != pfetch_op) {
+ return SIGILL;
+ }
+ /* ignore prefx operation */
+ break;
+
+ default:
+ return SIGILL;
+ }
+
+ return 0;
+}
+#endif
+
+
+
+/*
+ * Emulate a single COP1 arithmetic instruction.
+ */
+static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx,
+ mips_instruction ir)
+{
+ int rfmt; /* resulting format */
+ unsigned rcsr = 0; /* resulting csr */
+ unsigned cond;
+ union {
+ ieee754dp d;
+ ieee754sp s;
+ int w;
+#if __mips64
+ s64 l;
+#endif
+ } rv; /* resulting value */
+
+ fpuemuprivate.stats.cp1ops++;
+ switch (rfmt = (MIPSInst_FFMT(ir) & 0xf)) {
+ case s_fmt:{ /* 0 */
+ union {
+ ieee754sp(*b) (ieee754sp, ieee754sp);
+ ieee754sp(*u) (ieee754sp);
+ } handler;
+
+ switch (MIPSInst_FUNC(ir)) {
+ /* binary ops */
+ case fadd_op:
+ handler.b = ieee754sp_add;
+ goto scopbop;
+ case fsub_op:
+ handler.b = ieee754sp_sub;
+ goto scopbop;
+ case fmul_op:
+ handler.b = ieee754sp_mul;
+ goto scopbop;
+ case fdiv_op:
+ handler.b = ieee754sp_div;
+ goto scopbop;
+
+ /* unary ops */
+#if __mips >= 2 || __mips64
+ case fsqrt_op:
+ handler.u = ieee754sp_sqrt;
+ goto scopuop;
+#endif
+#if __mips >= 4 && __mips != 32
+ case frsqrt_op:
+ handler.u = fpemu_sp_rsqrt;
+ goto scopuop;
+ case frecip_op:
+ handler.u = fpemu_sp_recip;
+ goto scopuop;
+#endif
+#if __mips >= 4
+ case fmovc_op:
+ cond = fpucondbit[MIPSInst_FT(ir) >> 2];
+ if (((ctx->fcr31 & cond) != 0) !=
+ ((MIPSInst_FT(ir) & 1) != 0))
+ return 0;
+ SPFROMREG(rv.s, MIPSInst_FS(ir));
+ break;
+ case fmovz_op:
+ if (xcp->regs[MIPSInst_FT(ir)] != 0)
+ return 0;
+ SPFROMREG(rv.s, MIPSInst_FS(ir));
+ break;
+ case fmovn_op:
+ if (xcp->regs[MIPSInst_FT(ir)] == 0)
+ return 0;
+ SPFROMREG(rv.s, MIPSInst_FS(ir));
+ break;
+#endif
+ case fabs_op:
+ handler.u = ieee754sp_abs;
+ goto scopuop;
+ case fneg_op:
+ handler.u = ieee754sp_neg;
+ goto scopuop;
+ case fmov_op:
+ /* an easy one */
+ SPFROMREG(rv.s, MIPSInst_FS(ir));
+ goto copcsr;
+
+ /* binary op on handler */
+ scopbop:
+ {
+ ieee754sp fs, ft;
+
+ SPFROMREG(fs, MIPSInst_FS(ir));
+ SPFROMREG(ft, MIPSInst_FT(ir));
+
+ rv.s = (*handler.b) (fs, ft);
+ goto copcsr;
+ }
+ scopuop:
+ {
+ ieee754sp fs;
+
+ SPFROMREG(fs, MIPSInst_FS(ir));
+ rv.s = (*handler.u) (fs);
+ goto copcsr;
+ }
+ copcsr:
+ if (ieee754_cxtest(IEEE754_INEXACT))
+ rcsr |= FPU_CSR_INE_X | FPU_CSR_INE_S;
+ if (ieee754_cxtest(IEEE754_UNDERFLOW))
+ rcsr |= FPU_CSR_UDF_X | FPU_CSR_UDF_S;
+ if (ieee754_cxtest(IEEE754_OVERFLOW))
+ rcsr |= FPU_CSR_OVF_X | FPU_CSR_OVF_S;
+ if (ieee754_cxtest(IEEE754_ZERO_DIVIDE))
+ rcsr |= FPU_CSR_DIV_X | FPU_CSR_DIV_S;
+ if (ieee754_cxtest(IEEE754_INVALID_OPERATION))
+ rcsr |= FPU_CSR_INV_X | FPU_CSR_INV_S;
+ break;
+
+ /* unary conv ops */
+ case fcvts_op:
+ return SIGILL; /* not defined */
+ case fcvtd_op:{
+#ifdef SINGLE_ONLY_FPU
+ return SIGILL; /* not defined */
+#else
+ ieee754sp fs;
+
+ SPFROMREG(fs, MIPSInst_FS(ir));
+ rv.d = ieee754dp_fsp(fs);
+ rfmt = d_fmt;
+ goto copcsr;
+ }
+#endif
+ case fcvtw_op:{
+ ieee754sp fs;
+
+ SPFROMREG(fs, MIPSInst_FS(ir));
+ rv.w = ieee754sp_tint(fs);
+ rfmt = w_fmt;
+ goto copcsr;
+ }
+
+#if __mips >= 2 || __mips64
+ case fround_op:
+ case ftrunc_op:
+ case fceil_op:
+ case ffloor_op:{
+ unsigned int oldrm = ieee754_csr.rm;
+ ieee754sp fs;
+
+ SPFROMREG(fs, MIPSInst_FS(ir));
+ ieee754_csr.rm = ieee_rm[MIPSInst_FUNC(ir) & 0x3];
+ rv.w = ieee754sp_tint(fs);
+ ieee754_csr.rm = oldrm;
+ rfmt = w_fmt;
+ goto copcsr;
+ }
+#endif /* __mips >= 2 */
+
+#if __mips64 && !defined(SINGLE_ONLY_FPU)
+ case fcvtl_op:{
+ ieee754sp fs;
+
+ SPFROMREG(fs, MIPSInst_FS(ir));
+ rv.l = ieee754sp_tlong(fs);
+ rfmt = l_fmt;
+ goto copcsr;
+ }
+
+ case froundl_op:
+ case ftruncl_op:
+ case fceill_op:
+ case ffloorl_op:{
+ unsigned int oldrm = ieee754_csr.rm;
+ ieee754sp fs;
+
+ SPFROMREG(fs, MIPSInst_FS(ir));
+ ieee754_csr.rm = ieee_rm[MIPSInst_FUNC(ir) & 0x3];
+ rv.l = ieee754sp_tlong(fs);
+ ieee754_csr.rm = oldrm;
+ rfmt = l_fmt;
+ goto copcsr;
+ }
+#endif /* __mips64 && !fpu(single) */
+
+ default:
+ if (MIPSInst_FUNC(ir) >= fcmp_op) {
+ unsigned cmpop = MIPSInst_FUNC(ir) - fcmp_op;
+ ieee754sp fs, ft;
+
+ SPFROMREG(fs, MIPSInst_FS(ir));
+ SPFROMREG(ft, MIPSInst_FT(ir));
+ rv.w = ieee754sp_cmp(fs, ft,
+ cmptab[cmpop & 0x7], cmpop & 0x8);
+ rfmt = -1;
+ if ((cmpop & 0x8) && ieee754_cxtest
+ (IEEE754_INVALID_OPERATION))
+ rcsr = FPU_CSR_INV_X | FPU_CSR_INV_S;
+ else
+ goto copcsr;
+
+ }
+ else {
+ return SIGILL;
+ }
+ break;
+ }
+ break;
+ }
+
+#ifndef SINGLE_ONLY_FPU
+ case d_fmt:{
+ union {
+ ieee754dp(*b) (ieee754dp, ieee754dp);
+ ieee754dp(*u) (ieee754dp);
+ } handler;
+
+ switch (MIPSInst_FUNC(ir)) {
+ /* binary ops */
+ case fadd_op:
+ handler.b = ieee754dp_add;
+ goto dcopbop;
+ case fsub_op:
+ handler.b = ieee754dp_sub;
+ goto dcopbop;
+ case fmul_op:
+ handler.b = ieee754dp_mul;
+ goto dcopbop;
+ case fdiv_op:
+ handler.b = ieee754dp_div;
+ goto dcopbop;
+
+ /* unary ops */
+#if __mips >= 2 || __mips64
+ case fsqrt_op:
+ handler.u = ieee754dp_sqrt;
+ goto dcopuop;
+#endif
+#if __mips >= 4 && __mips != 32
+ case frsqrt_op:
+ handler.u = fpemu_dp_rsqrt;
+ goto dcopuop;
+ case frecip_op:
+ handler.u = fpemu_dp_recip;
+ goto dcopuop;
+#endif
+#if __mips >= 4
+ case fmovc_op:
+ cond = fpucondbit[MIPSInst_FT(ir) >> 2];
+ if (((ctx->fcr31 & cond) != 0) !=
+ ((MIPSInst_FT(ir) & 1) != 0))
+ return 0;
+ DPFROMREG(rv.d, MIPSInst_FS(ir));
+ break;
+ case fmovz_op:
+ if (xcp->regs[MIPSInst_FT(ir)] != 0)
+ return 0;
+ DPFROMREG(rv.d, MIPSInst_FS(ir));
+ break;
+ case fmovn_op:
+ if (xcp->regs[MIPSInst_FT(ir)] == 0)
+ return 0;
+ DPFROMREG(rv.d, MIPSInst_FS(ir));
+ break;
+#endif
+ case fabs_op:
+ handler.u = ieee754dp_abs;
+ goto dcopuop;
+
+ case fneg_op:
+ handler.u = ieee754dp_neg;
+ goto dcopuop;
+
+ case fmov_op:
+ /* an easy one */
+ DPFROMREG(rv.d, MIPSInst_FS(ir));
+ goto copcsr;
+
+ /* binary op on handler */
+ dcopbop:{
+ ieee754dp fs, ft;
+
+ DPFROMREG(fs, MIPSInst_FS(ir));
+ DPFROMREG(ft, MIPSInst_FT(ir));
+
+ rv.d = (*handler.b) (fs, ft);
+ goto copcsr;
+ }
+ dcopuop:{
+ ieee754dp fs;
+
+ DPFROMREG(fs, MIPSInst_FS(ir));
+ rv.d = (*handler.u) (fs);
+ goto copcsr;
+ }
+
+ /* unary conv ops */
+ case fcvts_op:{
+ ieee754dp fs;
+
+ DPFROMREG(fs, MIPSInst_FS(ir));
+ rv.s = ieee754sp_fdp(fs);
+ rfmt = s_fmt;
+ goto copcsr;
+ }
+ case fcvtd_op:
+ return SIGILL; /* not defined */
+
+ case fcvtw_op:{
+ ieee754dp fs;
+
+ DPFROMREG(fs, MIPSInst_FS(ir));
+ rv.w = ieee754dp_tint(fs); /* wrong */
+ rfmt = w_fmt;
+ goto copcsr;
+ }
+
+#if __mips >= 2 || __mips64
+ case fround_op:
+ case ftrunc_op:
+ case fceil_op:
+ case ffloor_op:{
+ unsigned int oldrm = ieee754_csr.rm;
+ ieee754dp fs;
+
+ DPFROMREG(fs, MIPSInst_FS(ir));
+ ieee754_csr.rm = ieee_rm[MIPSInst_FUNC(ir) & 0x3];
+ rv.w = ieee754dp_tint(fs);
+ ieee754_csr.rm = oldrm;
+ rfmt = w_fmt;
+ goto copcsr;
+ }
+#endif
+
+#if __mips64 && !defined(SINGLE_ONLY_FPU)
+ case fcvtl_op:{
+ ieee754dp fs;
+
+ DPFROMREG(fs, MIPSInst_FS(ir));
+ rv.l = ieee754dp_tlong(fs);
+ rfmt = l_fmt;
+ goto copcsr;
+ }
+
+ case froundl_op:
+ case ftruncl_op:
+ case fceill_op:
+ case ffloorl_op:{
+ unsigned int oldrm = ieee754_csr.rm;
+ ieee754dp fs;
+
+ DPFROMREG(fs, MIPSInst_FS(ir));
+ ieee754_csr.rm = ieee_rm[MIPSInst_FUNC(ir) & 0x3];
+ rv.l = ieee754dp_tlong(fs);
+ ieee754_csr.rm = oldrm;
+ rfmt = l_fmt;
+ goto copcsr;
+ }
+#endif /* __mips >= 3 && !fpu(single) */
+
+ default:
+ if (MIPSInst_FUNC(ir) >= fcmp_op) {
+ unsigned cmpop = MIPSInst_FUNC(ir) - fcmp_op;
+ ieee754dp fs, ft;
+
+ DPFROMREG(fs, MIPSInst_FS(ir));
+ DPFROMREG(ft, MIPSInst_FT(ir));
+ rv.w = ieee754dp_cmp(fs, ft,
+ cmptab[cmpop & 0x7], cmpop & 0x8);
+ rfmt = -1;
+ if ((cmpop & 0x8)
+ &&
+ ieee754_cxtest
+ (IEEE754_INVALID_OPERATION))
+ rcsr = FPU_CSR_INV_X | FPU_CSR_INV_S;
+ else
+ goto copcsr;
+
+ }
+ else {
+ return SIGILL;
+ }
+ break;
+ }
+ break;
+ }
+#endif /* ifndef SINGLE_ONLY_FPU */
+
+ case w_fmt:{
+ ieee754sp fs;
+
+ switch (MIPSInst_FUNC(ir)) {
+ case fcvts_op:
+ /* convert word to single precision real */
+ SPFROMREG(fs, MIPSInst_FS(ir));
+ rv.s = ieee754sp_fint(fs.bits);
+ rfmt = s_fmt;
+ goto copcsr;
+#ifndef SINGLE_ONLY_FPU
+ case fcvtd_op:
+ /* convert word to double precision real */
+ SPFROMREG(fs, MIPSInst_FS(ir));
+ rv.d = ieee754dp_fint(fs.bits);
+ rfmt = d_fmt;
+ goto copcsr;
+#endif
+ default:
+ return SIGILL;
+ }
+ break;
+ }
+
+#if __mips64 && !defined(SINGLE_ONLY_FPU)
+ case l_fmt:{
+ switch (MIPSInst_FUNC(ir)) {
+ case fcvts_op:
+ /* convert long to single precision real */
+ rv.s = ieee754sp_flong(ctx->fpr[MIPSInst_FS(ir)]);
+ rfmt = s_fmt;
+ goto copcsr;
+ case fcvtd_op:
+ /* convert long to double precision real */
+ rv.d = ieee754dp_flong(ctx->fpr[MIPSInst_FS(ir)]);
+ rfmt = d_fmt;
+ goto copcsr;
+ default:
+ return SIGILL;
+ }
+ break;
+ }
+#endif
+
+ default:
+ return SIGILL;
+ }
+
+ /*
+ * Update the fpu CSR register for this operation.
+ * If an exception is required, generate a tidy SIGFPE exception,
+ * without updating the result register.
+ * Note: cause exception bits do not accumulate, they are rewritten
+ * for each op; only the flag/sticky bits accumulate.
+ */
+ ctx->fcr31 = (ctx->fcr31 & ~FPU_CSR_ALL_X) | rcsr;
+ if ((ctx->fcr31 >> 5) & ctx->fcr31 & FPU_CSR_ALL_E) {
+ /*printk ("SIGFPE: fpu csr = %08x\n",ctx->fcr31); */
+ return SIGFPE;
+ }
+
+ /*
+ * Now we can safely write the result back to the register file.
+ */
+ switch (rfmt) {
+ case -1:{
+#if __mips >= 4
+ cond = fpucondbit[MIPSInst_FD(ir) >> 2];
+#else
+ cond = FPU_CSR_COND;
+#endif
+ if (rv.w)
+ ctx->fcr31 |= cond;
+ else
+ ctx->fcr31 &= ~cond;
+ break;
+ }
+#ifndef SINGLE_ONLY_FPU
+ case d_fmt:
+ DPTOREG(rv.d, MIPSInst_FD(ir));
+ break;
+#endif
+ case s_fmt:
+ SPTOREG(rv.s, MIPSInst_FD(ir));
+ break;
+ case w_fmt:
+ SITOREG(rv.w, MIPSInst_FD(ir));
+ break;
+#if __mips64 && !defined(SINGLE_ONLY_FPU)
+ case l_fmt:
+ DITOREG(rv.l, MIPSInst_FD(ir));
+ break;
+#endif
+ default:
+ return SIGILL;
+ }
+
+ return 0;
+}
+
+int fpu_emulator_cop1Handler(int xcptno, struct pt_regs *xcp,
+ struct mips_fpu_soft_struct *ctx)
+{
+ gpreg_t oldepc, prevepc;
+ mips_instruction insn;
+ int sig = 0;
+
+ oldepc = xcp->cp0_epc;
+ do {
+ prevepc = xcp->cp0_epc;
+
+ if (get_user(insn, (mips_instruction *) xcp->cp0_epc)) {
+ fpuemuprivate.stats.errors++;
+ return SIGBUS;
+ }
+ if (insn == 0)
+ xcp->cp0_epc += 4; /* skip nops */
+ else {
+ /* Update ieee754_csr. Only relevant if we have a
+ h/w FPU */
+ ieee754_csr.nod = (ctx->fcr31 & 0x1000000) != 0;
+ ieee754_csr.rm = ieee_rm[ctx->fcr31 & 0x3];
+ ieee754_csr.cx = (ctx->fcr31 >> 12) & 0x1f;
+ sig = cop1Emulate(xcp, ctx);
+ }
+
+ if (cpu_has_fpu)
+ break;
+ if (sig)
+ break;
+
+ cond_resched();
+ } while (xcp->cp0_epc > prevepc);
+
+ /* SIGILL indicates a non-fpu instruction */
+ if (sig == SIGILL && xcp->cp0_epc != oldepc)
+ /* but if epc has advanced, then ignore it */
+ sig = 0;
+
+ return sig;
+}
diff --git a/arch/mips/math-emu/dp_add.c b/arch/mips/math-emu/dp_add.c
new file mode 100644
index 0000000..bcf73bb
--- /dev/null
+++ b/arch/mips/math-emu/dp_add.c
@@ -0,0 +1,183 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ * 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 "ieee754dp.h"
+
+ieee754dp ieee754dp_add(ieee754dp x, ieee754dp y)
+{
+ COMPXDP;
+ COMPYDP;
+
+ EXPLODEXDP;
+ EXPLODEYDP;
+
+ CLEARCX;
+
+ FLUSHXDP;
+ FLUSHYDP;
+
+ switch (CLPAIR(xc, yc)) {
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
+ SETCX(IEEE754_INVALID_OPERATION);
+ return ieee754dp_nanxcpt(ieee754dp_indef(), "add", x, y);
+
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
+ return y;
+
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
+ return x;
+
+
+ /* Infinity handling
+ */
+
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
+ if (xs == ys)
+ return x;
+ SETCX(IEEE754_INVALID_OPERATION);
+ return ieee754dp_xcpt(ieee754dp_indef(), "add", x, y);
+
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
+ return y;
+
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
+ return x;
+
+ /* Zero handling
+ */
+
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
+ if (xs == ys)
+ return x;
+ else
+ return ieee754dp_zero(ieee754_csr.rm ==
+ IEEE754_RD);
+
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
+ return x;
+
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
+ return y;
+
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
+ DPDNORMX;
+
+ /* FALL THROUGH */
+
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
+ DPDNORMY;
+ break;
+
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
+ DPDNORMX;
+ break;
+
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
+ break;
+ }
+ assert(xm & DP_HIDDEN_BIT);
+ assert(ym & DP_HIDDEN_BIT);
+
+ /* provide guard,round and stick bit space */
+ xm <<= 3;
+ ym <<= 3;
+
+ if (xe > ye) {
+ /* have to shift y fraction right to align
+ */
+ int s = xe - ye;
+ ym = XDPSRS(ym, s);
+ ye += s;
+ } else if (ye > xe) {
+ /* have to shift x fraction right to align
+ */
+ int s = ye - xe;
+ xm = XDPSRS(xm, s);
+ xe += s;
+ }
+ assert(xe == ye);
+ assert(xe <= DP_EMAX);
+
+ if (xs == ys) {
+ /* generate 28 bit result of adding two 27 bit numbers
+ * leaving result in xm,xs,xe
+ */
+ xm = xm + ym;
+ xe = xe;
+ xs = xs;
+
+ if (xm >> (DP_MBITS + 1 + 3)) { /* carry out */
+ xm = XDPSRS1(xm);
+ xe++;
+ }
+ } else {
+ if (xm >= ym) {
+ xm = xm - ym;
+ xe = xe;
+ xs = xs;
+ } else {
+ xm = ym - xm;
+ xe = xe;
+ xs = ys;
+ }
+ if (xm == 0)
+ return ieee754dp_zero(ieee754_csr.rm ==
+ IEEE754_RD);
+
+ /* normalize to rounding precision */
+ while ((xm >> (DP_MBITS + 3)) == 0) {
+ xm <<= 1;
+ xe--;
+ }
+
+ }
+ DPNORMRET2(xs, xe, xm, "add", x, y);
+}
diff --git a/arch/mips/math-emu/dp_cmp.c b/arch/mips/math-emu/dp_cmp.c
new file mode 100644
index 0000000..8ab4f32
--- /dev/null
+++ b/arch/mips/math-emu/dp_cmp.c
@@ -0,0 +1,67 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ * 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 "ieee754dp.h"
+
+int ieee754dp_cmp(ieee754dp x, ieee754dp y, int cmp, int sig)
+{
+ COMPXDP;
+ COMPYDP;
+
+ EXPLODEXDP;
+ EXPLODEYDP;
+ FLUSHXDP;
+ FLUSHYDP;
+ CLEARCX; /* Even clear inexact flag here */
+
+ if (ieee754dp_isnan(x) || ieee754dp_isnan(y)) {
+ if (sig || xc == IEEE754_CLASS_SNAN || yc == IEEE754_CLASS_SNAN)
+ SETCX(IEEE754_INVALID_OPERATION);
+ if (cmp & IEEE754_CUN)
+ return 1;
+ if (cmp & (IEEE754_CLT | IEEE754_CGT)) {
+ if (sig && SETANDTESTCX(IEEE754_INVALID_OPERATION))
+ return ieee754si_xcpt(0, "fcmpf", x);
+ }
+ return 0;
+ } else {
+ s64 vx = x.bits;
+ s64 vy = y.bits;
+
+ if (vx < 0)
+ vx = -vx ^ DP_SIGN_BIT;
+ if (vy < 0)
+ vy = -vy ^ DP_SIGN_BIT;
+
+ if (vx < vy)
+ return (cmp & IEEE754_CLT) != 0;
+ else if (vx == vy)
+ return (cmp & IEEE754_CEQ) != 0;
+ else
+ return (cmp & IEEE754_CGT) != 0;
+ }
+}
diff --git a/arch/mips/math-emu/dp_div.c b/arch/mips/math-emu/dp_div.c
new file mode 100644
index 0000000..6acedce
--- /dev/null
+++ b/arch/mips/math-emu/dp_div.c
@@ -0,0 +1,157 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ * 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 "ieee754dp.h"
+
+ieee754dp ieee754dp_div(ieee754dp x, ieee754dp y)
+{
+ COMPXDP;
+ COMPYDP;
+
+ EXPLODEXDP;
+ EXPLODEYDP;
+
+ CLEARCX;
+
+ FLUSHXDP;
+ FLUSHYDP;
+
+ switch (CLPAIR(xc, yc)) {
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
+ SETCX(IEEE754_INVALID_OPERATION);
+ return ieee754dp_nanxcpt(ieee754dp_indef(), "div", x, y);
+
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
+ return y;
+
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
+ return x;
+
+
+ /* Infinity handling
+ */
+
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
+ SETCX(IEEE754_INVALID_OPERATION);
+ return ieee754dp_xcpt(ieee754dp_indef(), "div", x, y);
+
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
+ return ieee754dp_zero(xs ^ ys);
+
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
+ return ieee754dp_inf(xs ^ ys);
+
+ /* Zero handling
+ */
+
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
+ SETCX(IEEE754_INVALID_OPERATION);
+ return ieee754dp_xcpt(ieee754dp_indef(), "div", x, y);
+
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
+ SETCX(IEEE754_ZERO_DIVIDE);
+ return ieee754dp_xcpt(ieee754dp_inf(xs ^ ys), "div", x, y);
+
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
+ return ieee754dp_zero(xs == ys ? 0 : 1);
+
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
+ DPDNORMX;
+
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
+ DPDNORMY;
+ break;
+
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
+ DPDNORMX;
+ break;
+
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
+ break;
+ }
+ assert(xm & DP_HIDDEN_BIT);
+ assert(ym & DP_HIDDEN_BIT);
+
+ /* provide rounding space */
+ xm <<= 3;
+ ym <<= 3;
+
+ {
+ /* now the dirty work */
+
+ u64 rm = 0;
+ int re = xe - ye;
+ u64 bm;
+
+ for (bm = DP_MBIT(DP_MBITS + 2); bm; bm >>= 1) {
+ if (xm >= ym) {
+ xm -= ym;
+ rm |= bm;
+ if (xm == 0)
+ break;
+ }
+ xm <<= 1;
+ }
+ rm <<= 1;
+ if (xm)
+ rm |= 1; /* have remainder, set sticky */
+
+ assert(rm);
+
+ /* normalise rm to rounding precision ?
+ */
+ while ((rm >> (DP_MBITS + 3)) == 0) {
+ rm <<= 1;
+ re--;
+ }
+
+ DPNORMRET2(xs == ys ? 0 : 1, re, rm, "div", x, y);
+ }
+}
diff --git a/arch/mips/math-emu/dp_fint.c b/arch/mips/math-emu/dp_fint.c
new file mode 100644
index 0000000..0065dea
--- /dev/null
+++ b/arch/mips/math-emu/dp_fint.c
@@ -0,0 +1,80 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ * 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 "ieee754dp.h"
+
+ieee754dp ieee754dp_fint(int x)
+{
+ COMPXDP;
+
+ CLEARCX;
+
+ xc = ( 0 ? xc : xc );
+
+ if (x == 0)
+ return ieee754dp_zero(0);
+ if (x == 1 || x == -1)
+ return ieee754dp_one(x < 0);
+ if (x == 10 || x == -10)
+ return ieee754dp_ten(x < 0);
+
+ xs = (x < 0);
+ if (xs) {
+ if (x == (1 << 31))
+ xm = ((unsigned) 1 << 31); /* max neg can't be safely negated */
+ else
+ xm = -x;
+ } else {
+ xm = x;
+ }
+
+#if 1
+ /* normalize - result can never be inexact or overflow */
+ xe = DP_MBITS;
+ while ((xm >> DP_MBITS) == 0) {
+ xm <<= 1;
+ xe--;
+ }
+ return builddp(xs, xe + DP_EBIAS, xm & ~DP_HIDDEN_BIT);
+#else
+ /* normalize */
+ xe = DP_MBITS + 3;
+ while ((xm >> (DP_MBITS + 3)) == 0) {
+ xm <<= 1;
+ xe--;
+ }
+ DPNORMRET1(xs, xe, xm, "fint", x);
+#endif
+}
+
+ieee754dp ieee754dp_funs(unsigned int u)
+{
+ if ((int) u < 0)
+ return ieee754dp_add(ieee754dp_1e31(),
+ ieee754dp_fint(u & ~(1 << 31)));
+ return ieee754dp_fint(u);
+}
diff --git a/arch/mips/math-emu/dp_flong.c b/arch/mips/math-emu/dp_flong.c
new file mode 100644
index 0000000..cb105b1
--- /dev/null
+++ b/arch/mips/math-emu/dp_flong.c
@@ -0,0 +1,78 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ * 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 "ieee754dp.h"
+
+ieee754dp ieee754dp_flong(s64 x)
+{
+ COMPXDP;
+
+ CLEARCX;
+
+ xc = ( 0 ? xc : xc );
+
+ if (x == 0)
+ return ieee754dp_zero(0);
+ if (x == 1 || x == -1)
+ return ieee754dp_one(x < 0);
+ if (x == 10 || x == -10)
+ return ieee754dp_ten(x < 0);
+
+ xs = (x < 0);
+ if (xs) {
+ if (x == (1ULL << 63))
+ xm = (1ULL << 63); /* max neg can't be safely negated */
+ else
+ xm = -x;
+ } else {
+ xm = x;
+ }
+
+ /* normalize */
+ xe = DP_MBITS + 3;
+ if (xm >> (DP_MBITS + 1 + 3)) {
+ /* shunt out overflow bits */
+ while (xm >> (DP_MBITS + 1 + 3)) {
+ XDPSRSX1();
+ }
+ } else {
+ /* normalize in grs extended double precision */
+ while ((xm >> (DP_MBITS + 3)) == 0) {
+ xm <<= 1;
+ xe--;
+ }
+ }
+ DPNORMRET1(xs, xe, xm, "dp_flong", x);
+}
+
+ieee754dp ieee754dp_fulong(u64 u)
+{
+ if ((s64) u < 0)
+ return ieee754dp_add(ieee754dp_1e63(),
+ ieee754dp_flong(u & ~(1ULL << 63)));
+ return ieee754dp_flong(u);
+}
diff --git a/arch/mips/math-emu/dp_frexp.c b/arch/mips/math-emu/dp_frexp.c
new file mode 100644
index 0000000..e650cb1
--- /dev/null
+++ b/arch/mips/math-emu/dp_frexp.c
@@ -0,0 +1,53 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ * 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 "ieee754dp.h"
+
+/* close to ieeep754dp_logb
+*/
+ieee754dp ieee754dp_frexp(ieee754dp x, int *eptr)
+{
+ COMPXDP;
+ CLEARCX;
+ EXPLODEXDP;
+
+ switch (xc) {
+ case IEEE754_CLASS_SNAN:
+ case IEEE754_CLASS_QNAN:
+ case IEEE754_CLASS_INF:
+ case IEEE754_CLASS_ZERO:
+ *eptr = 0;
+ return x;
+ case IEEE754_CLASS_DNORM:
+ DPDNORMX;
+ break;
+ case IEEE754_CLASS_NORM:
+ break;
+ }
+ *eptr = xe + 1;
+ return builddp(xs, -1 + DP_EBIAS, xm & ~DP_HIDDEN_BIT);
+}
diff --git a/arch/mips/math-emu/dp_fsp.c b/arch/mips/math-emu/dp_fsp.c
new file mode 100644
index 0000000..494d19a
--- /dev/null
+++ b/arch/mips/math-emu/dp_fsp.c
@@ -0,0 +1,74 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ * 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 "ieee754dp.h"
+
+ieee754dp ieee754dp_fsp(ieee754sp x)
+{
+ COMPXSP;
+
+ EXPLODEXSP;
+
+ CLEARCX;
+
+ FLUSHXSP;
+
+ switch (xc) {
+ case IEEE754_CLASS_SNAN:
+ SETCX(IEEE754_INVALID_OPERATION);
+ return ieee754dp_nanxcpt(ieee754dp_indef(), "fsp");
+ case IEEE754_CLASS_QNAN:
+ return ieee754dp_nanxcpt(builddp(xs,
+ DP_EMAX + 1 + DP_EBIAS,
+ ((u64) xm
+ << (DP_MBITS -
+ SP_MBITS))), "fsp",
+ x);
+ case IEEE754_CLASS_INF:
+ return ieee754dp_inf(xs);
+ case IEEE754_CLASS_ZERO:
+ return ieee754dp_zero(xs);
+ case IEEE754_CLASS_DNORM:
+ /* normalize */
+ while ((xm >> SP_MBITS) == 0) {
+ xm <<= 1;
+ xe--;
+ }
+ break;
+ case IEEE754_CLASS_NORM:
+ break;
+ }
+
+ /* CANT possibly overflow,underflow, or need rounding
+ */
+
+ /* drop the hidden bit */
+ xm &= ~SP_HIDDEN_BIT;
+
+ return builddp(xs, xe + DP_EBIAS,
+ (u64) xm << (DP_MBITS - SP_MBITS));
+}
diff --git a/arch/mips/math-emu/dp_logb.c b/arch/mips/math-emu/dp_logb.c
new file mode 100644
index 0000000..6033886
--- /dev/null
+++ b/arch/mips/math-emu/dp_logb.c
@@ -0,0 +1,54 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ * 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 "ieee754dp.h"
+
+ieee754dp ieee754dp_logb(ieee754dp x)
+{
+ COMPXDP;
+
+ CLEARCX;
+
+ EXPLODEXDP;
+
+ switch (xc) {
+ case IEEE754_CLASS_SNAN:
+ return ieee754dp_nanxcpt(x, "logb", x);
+ case IEEE754_CLASS_QNAN:
+ return x;
+ case IEEE754_CLASS_INF:
+ return ieee754dp_inf(0);
+ case IEEE754_CLASS_ZERO:
+ return ieee754dp_inf(1);
+ case IEEE754_CLASS_DNORM:
+ DPDNORMX;
+ break;
+ case IEEE754_CLASS_NORM:
+ break;
+ }
+ return ieee754dp_fint(xe);
+}
diff --git a/arch/mips/math-emu/dp_modf.c b/arch/mips/math-emu/dp_modf.c
new file mode 100644
index 0000000..25861a4
--- /dev/null
+++ b/arch/mips/math-emu/dp_modf.c
@@ -0,0 +1,80 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ * 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 "ieee754dp.h"
+
+/* modf function is always exact for a finite number
+*/
+ieee754dp ieee754dp_modf(ieee754dp x, ieee754dp * ip)
+{
+ COMPXDP;
+
+ CLEARCX;
+
+ EXPLODEXDP;
+
+ switch (xc) {
+ case IEEE754_CLASS_SNAN:
+ case IEEE754_CLASS_QNAN:
+ case IEEE754_CLASS_INF:
+ case IEEE754_CLASS_ZERO:
+ *ip = x;
+ return x;
+ case IEEE754_CLASS_DNORM:
+ /* far to small */
+ *ip = ieee754dp_zero(xs);
+ return x;
+ case IEEE754_CLASS_NORM:
+ break;
+ }
+ if (xe < 0) {
+ *ip = ieee754dp_zero(xs);
+ return x;
+ }
+ if (xe >= DP_MBITS) {
+ *ip = x;
+ return ieee754dp_zero(xs);
+ }
+ /* generate ipart mantissa by clearing bottom bits
+ */
+ *ip = builddp(xs, xe + DP_EBIAS,
+ ((xm >> (DP_MBITS - xe)) << (DP_MBITS - xe)) &
+ ~DP_HIDDEN_BIT);
+
+ /* generate fpart mantissa by clearing top bits
+ * and normalizing (must be able to normalize)
+ */
+ xm = (xm << (64 - (DP_MBITS - xe))) >> (64 - (DP_MBITS - xe));
+ if (xm == 0)
+ return ieee754dp_zero(xs);
+
+ while ((xm >> DP_MBITS) == 0) {
+ xm <<= 1;
+ xe--;
+ }
+ return builddp(xs, xe + DP_EBIAS, xm & ~DP_HIDDEN_BIT);
+}
diff --git a/arch/mips/math-emu/dp_mul.c b/arch/mips/math-emu/dp_mul.c
new file mode 100644
index 0000000..f237390
--- /dev/null
+++ b/arch/mips/math-emu/dp_mul.c
@@ -0,0 +1,177 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ * 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 "ieee754dp.h"
+
+ieee754dp ieee754dp_mul(ieee754dp x, ieee754dp y)
+{
+ COMPXDP;
+ COMPYDP;
+
+ EXPLODEXDP;
+ EXPLODEYDP;
+
+ CLEARCX;
+
+ FLUSHXDP;
+ FLUSHYDP;
+
+ switch (CLPAIR(xc, yc)) {
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
+ SETCX(IEEE754_INVALID_OPERATION);
+ return ieee754dp_nanxcpt(ieee754dp_indef(), "mul", x, y);
+
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
+ return y;
+
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
+ return x;
+
+
+ /* Infinity handling */
+
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
+ SETCX(IEEE754_INVALID_OPERATION);
+ return ieee754dp_xcpt(ieee754dp_indef(), "mul", x, y);
+
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
+ return ieee754dp_inf(xs ^ ys);
+
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
+ return ieee754dp_zero(xs ^ ys);
+
+
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
+ DPDNORMX;
+
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
+ DPDNORMY;
+ break;
+
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
+ DPDNORMX;
+ break;
+
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
+ break;
+ }
+ /* rm = xm * ym, re = xe+ye basicly */
+ assert(xm & DP_HIDDEN_BIT);
+ assert(ym & DP_HIDDEN_BIT);
+ {
+ int re = xe + ye;
+ int rs = xs ^ ys;
+ u64 rm;
+
+ /* shunt to top of word */
+ xm <<= 64 - (DP_MBITS + 1);
+ ym <<= 64 - (DP_MBITS + 1);
+
+ /* multiply 32bits xm,ym to give high 32bits rm with stickness
+ */
+
+ /* 32 * 32 => 64 */
+#define DPXMULT(x,y) ((u64)(x) * (u64)y)
+
+ {
+ unsigned lxm = xm;
+ unsigned hxm = xm >> 32;
+ unsigned lym = ym;
+ unsigned hym = ym >> 32;
+ u64 lrm;
+ u64 hrm;
+
+ lrm = DPXMULT(lxm, lym);
+ hrm = DPXMULT(hxm, hym);
+
+ {
+ u64 t = DPXMULT(lxm, hym);
+ {
+ u64 at =
+ lrm + (t << 32);
+ hrm += at < lrm;
+ lrm = at;
+ }
+ hrm = hrm + (t >> 32);
+ }
+
+ {
+ u64 t = DPXMULT(hxm, lym);
+ {
+ u64 at =
+ lrm + (t << 32);
+ hrm += at < lrm;
+ lrm = at;
+ }
+ hrm = hrm + (t >> 32);
+ }
+ rm = hrm | (lrm != 0);
+ }
+
+ /*
+ * sticky shift down to normal rounding precision
+ */
+ if ((s64) rm < 0) {
+ rm =
+ (rm >> (64 - (DP_MBITS + 1 + 3))) |
+ ((rm << (DP_MBITS + 1 + 3)) != 0);
+ re++;
+ } else {
+ rm =
+ (rm >> (64 - (DP_MBITS + 1 + 3 + 1))) |
+ ((rm << (DP_MBITS + 1 + 3 + 1)) != 0);
+ }
+ assert(rm & (DP_HIDDEN_BIT << 3));
+ DPNORMRET2(rs, re, rm, "mul", x, y);
+ }
+}
diff --git a/arch/mips/math-emu/dp_scalb.c b/arch/mips/math-emu/dp_scalb.c
new file mode 100644
index 0000000..b84e633
--- /dev/null
+++ b/arch/mips/math-emu/dp_scalb.c
@@ -0,0 +1,58 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ * 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 "ieee754dp.h"
+
+ieee754dp ieee754dp_scalb(ieee754dp x, int n)
+{
+ COMPXDP;
+
+ CLEARCX;
+
+ EXPLODEXDP;
+
+ switch (xc) {
+ case IEEE754_CLASS_SNAN:
+ return ieee754dp_nanxcpt(x, "scalb", x, n);
+ case IEEE754_CLASS_QNAN:
+ case IEEE754_CLASS_INF:
+ case IEEE754_CLASS_ZERO:
+ return x;
+ case IEEE754_CLASS_DNORM:
+ DPDNORMX;
+ break;
+ case IEEE754_CLASS_NORM:
+ break;
+ }
+ DPNORMRET2(xs, xe + n, xm << 3, "scalb", x, n);
+}
+
+
+ieee754dp ieee754dp_ldexp(ieee754dp x, int n)
+{
+ return ieee754dp_scalb(x, n);
+}
diff --git a/arch/mips/math-emu/dp_simple.c b/arch/mips/math-emu/dp_simple.c
new file mode 100644
index 0000000..495c1ac
--- /dev/null
+++ b/arch/mips/math-emu/dp_simple.c
@@ -0,0 +1,84 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ * 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 "ieee754dp.h"
+
+int ieee754dp_finite(ieee754dp x)
+{
+ return DPBEXP(x) != DP_EMAX + 1 + DP_EBIAS;
+}
+
+ieee754dp ieee754dp_copysign(ieee754dp x, ieee754dp y)
+{
+ CLEARCX;
+ DPSIGN(x) = DPSIGN(y);
+ return x;
+}
+
+
+ieee754dp ieee754dp_neg(ieee754dp x)
+{
+ COMPXDP;
+
+ EXPLODEXDP;
+ CLEARCX;
+ FLUSHXDP;
+
+ if (xc == IEEE754_CLASS_SNAN) {
+ SETCX(IEEE754_INVALID_OPERATION);
+ return ieee754dp_nanxcpt(ieee754dp_indef(), "neg");
+ }
+
+ if (ieee754dp_isnan(x)) /* but not infinity */
+ return ieee754dp_nanxcpt(x, "neg", x);
+
+ /* quick fix up */
+ DPSIGN(x) ^= 1;
+ return x;
+}
+
+
+ieee754dp ieee754dp_abs(ieee754dp x)
+{
+ COMPXDP;
+
+ EXPLODEXDP;
+ CLEARCX;
+ FLUSHXDP;
+
+ if (xc == IEEE754_CLASS_SNAN) {
+ SETCX(IEEE754_INVALID_OPERATION);
+ return ieee754dp_nanxcpt(ieee754dp_indef(), "neg");
+ }
+
+ if (ieee754dp_isnan(x)) /* but not infinity */
+ return ieee754dp_nanxcpt(x, "abs", x);
+
+ /* quick fix up */
+ DPSIGN(x) = 0;
+ return x;
+}
diff --git a/arch/mips/math-emu/dp_sqrt.c b/arch/mips/math-emu/dp_sqrt.c
new file mode 100644
index 0000000..c35e871
--- /dev/null
+++ b/arch/mips/math-emu/dp_sqrt.c
@@ -0,0 +1,165 @@
+/* IEEE754 floating point arithmetic
+ * double precision square root
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ * 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 "ieee754dp.h"
+
+static const unsigned table[] = {
+ 0, 1204, 3062, 5746, 9193, 13348, 18162, 23592,
+ 29598, 36145, 43202, 50740, 58733, 67158, 75992,
+ 85215, 83599, 71378, 60428, 50647, 41945, 34246,
+ 27478, 21581, 16499, 12183, 8588, 5674, 3403,
+ 1742, 661, 130
+};
+
+ieee754dp ieee754dp_sqrt(ieee754dp x)
+{
+ struct ieee754_csr oldcsr;
+ ieee754dp y, z, t;
+ unsigned scalx, yh;
+ COMPXDP;
+
+ EXPLODEXDP;
+ CLEARCX;
+ FLUSHXDP;
+
+ /* x == INF or NAN? */
+ switch (xc) {
+ case IEEE754_CLASS_QNAN:
+ /* sqrt(Nan) = Nan */
+ return ieee754dp_nanxcpt(x, "sqrt");
+ case IEEE754_CLASS_SNAN:
+ SETCX(IEEE754_INVALID_OPERATION);
+ return ieee754dp_nanxcpt(ieee754dp_indef(), "sqrt");
+ case IEEE754_CLASS_ZERO:
+ /* sqrt(0) = 0 */
+ return x;
+ case IEEE754_CLASS_INF:
+ if (xs) {
+ /* sqrt(-Inf) = Nan */
+ SETCX(IEEE754_INVALID_OPERATION);
+ return ieee754dp_nanxcpt(ieee754dp_indef(), "sqrt");
+ }
+ /* sqrt(+Inf) = Inf */
+ return x;
+ case IEEE754_CLASS_DNORM:
+ DPDNORMX;
+ /* fall through */
+ case IEEE754_CLASS_NORM:
+ if (xs) {
+ /* sqrt(-x) = Nan */
+ SETCX(IEEE754_INVALID_OPERATION);
+ return ieee754dp_nanxcpt(ieee754dp_indef(), "sqrt");
+ }
+ break;
+ }
+
+ /* save old csr; switch off INX enable & flag; set RN rounding */
+ oldcsr = ieee754_csr;
+ ieee754_csr.mx &= ~IEEE754_INEXACT;
+ ieee754_csr.sx &= ~IEEE754_INEXACT;
+ ieee754_csr.rm = IEEE754_RN;
+
+ /* adjust exponent to prevent overflow */
+ scalx = 0;
+ if (xe > 512) { /* x > 2**-512? */
+ xe -= 512; /* x = x / 2**512 */
+ scalx += 256;
+ } else if (xe < -512) { /* x < 2**-512? */
+ xe += 512; /* x = x * 2**512 */
+ scalx -= 256;
+ }
+
+ y = x = builddp(0, xe + DP_EBIAS, xm & ~DP_HIDDEN_BIT);
+
+ /* magic initial approximation to almost 8 sig. bits */
+ yh = y.bits >> 32;
+ yh = (yh >> 1) + 0x1ff80000;
+ yh = yh - table[(yh >> 15) & 31];
+ y.bits = ((u64) yh << 32) | (y.bits & 0xffffffff);
+
+ /* Heron's rule once with correction to improve to ~18 sig. bits */
+ /* t=x/y; y=y+t; py[n0]=py[n0]-0x00100006; py[n1]=0; */
+ t = ieee754dp_div(x, y);
+ y = ieee754dp_add(y, t);
+ y.bits -= 0x0010000600000000LL;
+ y.bits &= 0xffffffff00000000LL;
+
+ /* triple to almost 56 sig. bits: y ~= sqrt(x) to within 1 ulp */
+ /* t=y*y; z=t; pt[n0]+=0x00100000; t+=z; z=(x-z)*y; */
+ z = t = ieee754dp_mul(y, y);
+ t.parts.bexp += 0x001;
+ t = ieee754dp_add(t, z);
+ z = ieee754dp_mul(ieee754dp_sub(x, z), y);
+
+ /* t=z/(t+x) ; pt[n0]+=0x00100000; y+=t; */
+ t = ieee754dp_div(z, ieee754dp_add(t, x));
+ t.parts.bexp += 0x001;
+ y = ieee754dp_add(y, t);
+
+ /* twiddle last bit to force y correctly rounded */
+
+ /* set RZ, clear INEX flag */
+ ieee754_csr.rm = IEEE754_RZ;
+ ieee754_csr.sx &= ~IEEE754_INEXACT;
+
+ /* t=x/y; ...chopped quotient, possibly inexact */
+ t = ieee754dp_div(x, y);
+
+ if (ieee754_csr.sx & IEEE754_INEXACT || t.bits != y.bits) {
+
+ if (!(ieee754_csr.sx & IEEE754_INEXACT))
+ /* t = t-ulp */
+ t.bits -= 1;
+
+ /* add inexact to result status */
+ oldcsr.cx |= IEEE754_INEXACT;
+ oldcsr.sx |= IEEE754_INEXACT;
+
+ switch (oldcsr.rm) {
+ case IEEE754_RP:
+ y.bits += 1;
+ /* drop through */
+ case IEEE754_RN:
+ t.bits += 1;
+ break;
+ }
+
+ /* y=y+t; ...chopped sum */
+ y = ieee754dp_add(y, t);
+
+ /* adjust scalx for correctly rounded sqrt(x) */
+ scalx -= 1;
+ }
+
+ /* py[n0]=py[n0]+scalx; ...scale back y */
+ y.parts.bexp += scalx;
+
+ /* restore rounding mode, possibly set inexact */
+ ieee754_csr = oldcsr;
+
+ return y;
+}
diff --git a/arch/mips/math-emu/dp_sub.c b/arch/mips/math-emu/dp_sub.c
new file mode 100644
index 0000000..b30c5b1
--- /dev/null
+++ b/arch/mips/math-emu/dp_sub.c
@@ -0,0 +1,191 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ * 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 "ieee754dp.h"
+
+ieee754dp ieee754dp_sub(ieee754dp x, ieee754dp y)
+{
+ COMPXDP;
+ COMPYDP;
+
+ EXPLODEXDP;
+ EXPLODEYDP;
+
+ CLEARCX;
+
+ FLUSHXDP;
+ FLUSHYDP;
+
+ switch (CLPAIR(xc, yc)) {
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
+ SETCX(IEEE754_INVALID_OPERATION);
+ return ieee754dp_nanxcpt(ieee754dp_indef(), "sub", x, y);
+
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
+ return y;
+
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
+ return x;
+
+
+ /* Infinity handling
+ */
+
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
+ if (xs != ys)
+ return x;
+ SETCX(IEEE754_INVALID_OPERATION);
+ return ieee754dp_xcpt(ieee754dp_indef(), "sub", x, y);
+
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
+ return ieee754dp_inf(ys ^ 1);
+
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
+ return x;
+
+ /* Zero handling
+ */
+
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
+ if (xs != ys)
+ return x;
+ else
+ return ieee754dp_zero(ieee754_csr.rm ==
+ IEEE754_RD);
+
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
+ return x;
+
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
+ /* quick fix up */
+ DPSIGN(y) ^= 1;
+ return y;
+
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
+ DPDNORMX;
+ /* FAAL THOROUGH */
+
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
+ /* normalize ym,ye */
+ DPDNORMY;
+ break;
+
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
+ /* normalize xm,xe */
+ DPDNORMX;
+ break;
+
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
+ break;
+ }
+ /* flip sign of y and handle as add */
+ ys ^= 1;
+
+ assert(xm & DP_HIDDEN_BIT);
+ assert(ym & DP_HIDDEN_BIT);
+
+
+ /* provide guard,round and stick bit dpace */
+ xm <<= 3;
+ ym <<= 3;
+
+ if (xe > ye) {
+ /* have to shift y fraction right to align
+ */
+ int s = xe - ye;
+ ym = XDPSRS(ym, s);
+ ye += s;
+ } else if (ye > xe) {
+ /* have to shift x fraction right to align
+ */
+ int s = ye - xe;
+ xm = XDPSRS(xm, s);
+ xe += s;
+ }
+ assert(xe == ye);
+ assert(xe <= DP_EMAX);
+
+ if (xs == ys) {
+ /* generate 28 bit result of adding two 27 bit numbers
+ */
+ xm = xm + ym;
+ xe = xe;
+ xs = xs;
+
+ if (xm >> (DP_MBITS + 1 + 3)) { /* carry out */
+ xm = XDPSRS1(xm); /* shift preserving sticky */
+ xe++;
+ }
+ } else {
+ if (xm >= ym) {
+ xm = xm - ym;
+ xe = xe;
+ xs = xs;
+ } else {
+ xm = ym - xm;
+ xe = xe;
+ xs = ys;
+ }
+ if (xm == 0) {
+ if (ieee754_csr.rm == IEEE754_RD)
+ return ieee754dp_zero(1); /* round negative inf. => sign = -1 */
+ else
+ return ieee754dp_zero(0); /* other round modes => sign = 1 */
+ }
+
+ /* normalize to rounding precision
+ */
+ while ((xm >> (DP_MBITS + 3)) == 0) {
+ xm <<= 1;
+ xe--;
+ }
+ }
+ DPNORMRET2(xs, xe, xm, "sub", x, y);
+}
diff --git a/arch/mips/math-emu/dp_tint.c b/arch/mips/math-emu/dp_tint.c
new file mode 100644
index 0000000..77b2b7c
--- /dev/null
+++ b/arch/mips/math-emu/dp_tint.c
@@ -0,0 +1,124 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ * 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 <linux/kernel.h>
+#include "ieee754dp.h"
+
+int ieee754dp_tint(ieee754dp x)
+{
+ COMPXDP;
+
+ CLEARCX;
+
+ EXPLODEXDP;
+ FLUSHXDP;
+
+ switch (xc) {
+ case IEEE754_CLASS_SNAN:
+ case IEEE754_CLASS_QNAN:
+ case IEEE754_CLASS_INF:
+ SETCX(IEEE754_INVALID_OPERATION);
+ return ieee754si_xcpt(ieee754si_indef(), "dp_tint", x);
+ case IEEE754_CLASS_ZERO:
+ return 0;
+ case IEEE754_CLASS_DNORM:
+ case IEEE754_CLASS_NORM:
+ break;
+ }
+ if (xe > 31) {
+ /* Set invalid. We will only use overflow for floating
+ point overflow */
+ SETCX(IEEE754_INVALID_OPERATION);
+ return ieee754si_xcpt(ieee754si_indef(), "dp_tint", x);
+ }
+ /* oh gawd */
+ if (xe > DP_MBITS) {
+ xm <<= xe - DP_MBITS;
+ } else if (xe < DP_MBITS) {
+ u64 residue;
+ int round;
+ int sticky;
+ int odd;
+
+ if (xe < -1) {
+ residue = xm;
+ round = 0;
+ sticky = residue != 0;
+ xm = 0;
+ }
+ else {
+ residue = xm << (64 - DP_MBITS + xe);
+ round = (residue >> 63) != 0;
+ sticky = (residue << 1) != 0;
+ xm >>= DP_MBITS - xe;
+ }
+ /* Note: At this point upper 32 bits of xm are guaranteed
+ to be zero */
+ odd = (xm & 0x1) != 0x0;
+ switch (ieee754_csr.rm) {
+ case IEEE754_RN:
+ if (round && (sticky || odd))
+ xm++;
+ break;
+ case IEEE754_RZ:
+ break;
+ case IEEE754_RU: /* toward +Infinity */
+ if ((round || sticky) && !xs)
+ xm++;
+ break;
+ case IEEE754_RD: /* toward -Infinity */
+ if ((round || sticky) && xs)
+ xm++;
+ break;
+ }
+ /* look for valid corner case 0x80000000 */
+ if ((xm >> 31) != 0 && (xs == 0 || xm != 0x80000000)) {
+ /* This can happen after rounding */
+ SETCX(IEEE754_INVALID_OPERATION);
+ return ieee754si_xcpt(ieee754si_indef(), "dp_tint", x);
+ }
+ if (round || sticky)
+ SETCX(IEEE754_INEXACT);
+ }
+ if (xs)
+ return -xm;
+ else
+ return xm;
+}
+
+
+unsigned int ieee754dp_tuns(ieee754dp x)
+{
+ ieee754dp hb = ieee754dp_1e31();
+
+ /* what if x < 0 ?? */
+ if (ieee754dp_lt(x, hb))
+ return (unsigned) ieee754dp_tint(x);
+
+ return (unsigned) ieee754dp_tint(ieee754dp_sub(x, hb)) |
+ ((unsigned) 1 << 31);
+}
diff --git a/arch/mips/math-emu/dp_tlong.c b/arch/mips/math-emu/dp_tlong.c
new file mode 100644
index 0000000..d71113e
--- /dev/null
+++ b/arch/mips/math-emu/dp_tlong.c
@@ -0,0 +1,127 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ * 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 "ieee754dp.h"
+
+s64 ieee754dp_tlong(ieee754dp x)
+{
+ COMPXDP;
+
+ CLEARCX;
+
+ EXPLODEXDP;
+ FLUSHXDP;
+
+ switch (xc) {
+ case IEEE754_CLASS_SNAN:
+ case IEEE754_CLASS_QNAN:
+ case IEEE754_CLASS_INF:
+ SETCX(IEEE754_INVALID_OPERATION);
+ return ieee754di_xcpt(ieee754di_indef(), "dp_tlong", x);
+ case IEEE754_CLASS_ZERO:
+ return 0;
+ case IEEE754_CLASS_DNORM:
+ case IEEE754_CLASS_NORM:
+ break;
+ }
+ if (xe >= 63) {
+ /* look for valid corner case */
+ if (xe == 63 && xs && xm == DP_HIDDEN_BIT)
+ return -0x8000000000000000LL;
+ /* Set invalid. We will only use overflow for floating
+ point overflow */
+ SETCX(IEEE754_INVALID_OPERATION);
+ return ieee754di_xcpt(ieee754di_indef(), "dp_tlong", x);
+ }
+ /* oh gawd */
+ if (xe > DP_MBITS) {
+ xm <<= xe - DP_MBITS;
+ } else if (xe < DP_MBITS) {
+ u64 residue;
+ int round;
+ int sticky;
+ int odd;
+
+ if (xe < -1) {
+ residue = xm;
+ round = 0;
+ sticky = residue != 0;
+ xm = 0;
+ }
+ else {
+ /* Shifting a u64 64 times does not work,
+ * so we do it in two steps. Be aware that xe
+ * may be -1 */
+ residue = xm << (xe + 1);
+ residue <<= 63 - DP_MBITS;
+ round = (residue >> 63) != 0;
+ sticky = (residue << 1) != 0;
+ xm >>= DP_MBITS - xe;
+ }
+ odd = (xm & 0x1) != 0x0;
+ switch (ieee754_csr.rm) {
+ case IEEE754_RN:
+ if (round && (sticky || odd))
+ xm++;
+ break;
+ case IEEE754_RZ:
+ break;
+ case IEEE754_RU: /* toward +Infinity */
+ if ((round || sticky) && !xs)
+ xm++;
+ break;
+ case IEEE754_RD: /* toward -Infinity */
+ if ((round || sticky) && xs)
+ xm++;
+ break;
+ }
+ if ((xm >> 63) != 0) {
+ /* This can happen after rounding */
+ SETCX(IEEE754_INVALID_OPERATION);
+ return ieee754di_xcpt(ieee754di_indef(), "dp_tlong", x);
+ }
+ if (round || sticky)
+ SETCX(IEEE754_INEXACT);
+ }
+ if (xs)
+ return -xm;
+ else
+ return xm;
+}
+
+
+u64 ieee754dp_tulong(ieee754dp x)
+{
+ ieee754dp hb = ieee754dp_1e63();
+
+ /* what if x < 0 ?? */
+ if (ieee754dp_lt(x, hb))
+ return (u64) ieee754dp_tlong(x);
+
+ return (u64) ieee754dp_tlong(ieee754dp_sub(x, hb)) |
+ (1ULL << 63);
+}
diff --git a/arch/mips/math-emu/dsemul.c b/arch/mips/math-emu/dsemul.c
new file mode 100644
index 0000000..aa989c2
--- /dev/null
+++ b/arch/mips/math-emu/dsemul.c
@@ -0,0 +1,172 @@
+#include <linux/compiler.h>
+#include <linux/mm.h>
+#include <linux/signal.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+
+#include <asm/asm.h>
+#include <asm/bootinfo.h>
+#include <asm/byteorder.h>
+#include <asm/cpu.h>
+#include <asm/inst.h>
+#include <asm/processor.h>
+#include <asm/uaccess.h>
+#include <asm/branch.h>
+#include <asm/mipsregs.h>
+#include <asm/system.h>
+#include <asm/cacheflush.h>
+
+#include <asm/fpu_emulator.h>
+
+#include "ieee754.h"
+#include "dsemul.h"
+
+/* Strap kernel emulator for full MIPS IV emulation */
+
+#ifdef __mips
+#undef __mips
+#endif
+#define __mips 4
+
+extern struct mips_fpu_emulator_private fpuemuprivate;
+
+
+/*
+ * Emulate the arbritrary instruction ir at xcp->cp0_epc. Required when
+ * we have to emulate the instruction in a COP1 branch delay slot. Do
+ * not change cp0_epc due to the instruction
+ *
+ * According to the spec:
+ * 1) it shouldnt be a branch :-)
+ * 2) it can be a COP instruction :-(
+ * 3) if we are tring to run a protected memory space we must take
+ * special care on memory access instructions :-(
+ */
+
+/*
+ * "Trampoline" return routine to catch exception following
+ * execution of delay-slot instruction execution.
+ */
+
+struct emuframe {
+ mips_instruction emul;
+ mips_instruction badinst;
+ mips_instruction cookie;
+ gpreg_t epc;
+};
+
+int mips_dsemul(struct pt_regs *regs, mips_instruction ir, gpreg_t cpc)
+{
+ extern asmlinkage void handle_dsemulret(void);
+ mips_instruction *dsemul_insns;
+ struct emuframe *fr;
+ int err;
+
+ if (ir == 0) { /* a nop is easy */
+ regs->cp0_epc = cpc;
+ regs->cp0_cause &= ~CAUSEF_BD;
+ return 0;
+ }
+#ifdef DSEMUL_TRACE
+ printk("dsemul %lx %lx\n", regs->cp0_epc, cpc);
+
+#endif
+
+ /*
+ * The strategy is to push the instruction onto the user stack
+ * and put a trap after it which we can catch and jump to
+ * the required address any alternative apart from full
+ * instruction emulation!!.
+ *
+ * Algorithmics used a system call instruction, and
+ * borrowed that vector. MIPS/Linux version is a bit
+ * more heavyweight in the interests of portability and
+ * multiprocessor support. For Linux we generate a
+ * an unaligned access and force an address error exception.
+ *
+ * For embedded systems (stand-alone) we prefer to use a
+ * non-existing CP1 instruction. This prevents us from emulating
+ * branches, but gives us a cleaner interface to the exception
+ * handler (single entry point).
+ */
+
+ /* Ensure that the two instructions are in the same cache line */
+ dsemul_insns = (mips_instruction *) REG_TO_VA ((regs->regs[29] - sizeof(struct emuframe)) & ~0x7);
+ fr = (struct emuframe *) dsemul_insns;
+
+ /* Verify that the stack pointer is not competely insane */
+ if (unlikely(!access_ok(VERIFY_WRITE, fr, sizeof(struct emuframe))))
+ return SIGBUS;
+
+ err = __put_user(ir, &fr->emul);
+ err |= __put_user((mips_instruction)BADINST, &fr->badinst);
+ err |= __put_user((mips_instruction)BD_COOKIE, &fr->cookie);
+ err |= __put_user(cpc, &fr->epc);
+
+ if (unlikely(err)) {
+ fpuemuprivate.stats.errors++;
+ return SIGBUS;
+ }
+
+ regs->cp0_epc = VA_TO_REG & fr->emul;
+
+ flush_cache_sigtramp((unsigned long)&fr->badinst);
+
+ return SIGILL; /* force out of emulation loop */
+}
+
+int do_dsemulret(struct pt_regs *xcp)
+{
+ struct emuframe *fr;
+ gpreg_t epc;
+ u32 insn, cookie;
+ int err = 0;
+
+ fr = (struct emuframe *) (xcp->cp0_epc - sizeof(mips_instruction));
+
+ /*
+ * If we can't even access the area, something is very wrong, but we'll
+ * leave that to the default handling
+ */
+ if (!access_ok(VERIFY_READ, fr, sizeof(struct emuframe)))
+ return 0;
+
+ /*
+ * Do some sanity checking on the stackframe:
+ *
+ * - Is the instruction pointed to by the EPC an BADINST?
+ * - Is the following memory word the BD_COOKIE?
+ */
+ err = __get_user(insn, &fr->badinst);
+ err |= __get_user(cookie, &fr->cookie);
+
+ if (unlikely(err || (insn != BADINST) || (cookie != BD_COOKIE))) {
+ fpuemuprivate.stats.errors++;
+ return 0;
+ }
+
+ /*
+ * At this point, we are satisfied that it's a BD emulation trap. Yes,
+ * a user might have deliberately put two malformed and useless
+ * instructions in a row in his program, in which case he's in for a
+ * nasty surprise - the next instruction will be treated as a
+ * continuation address! Alas, this seems to be the only way that we
+ * can handle signals, recursion, and longjmps() in the context of
+ * emulating the branch delay instruction.
+ */
+
+#ifdef DSEMUL_TRACE
+ printk("dsemulret\n");
+#endif
+ if (__get_user(epc, &fr->epc)) { /* Saved EPC */
+ /* This is not a good situation to be in */
+ force_sig(SIGBUS, current);
+
+ return 0;
+ }
+
+ /* Set EPC to return to post-branch instruction */
+ xcp->cp0_epc = epc;
+
+ return 1;
+}
diff --git a/arch/mips/math-emu/dsemul.h b/arch/mips/math-emu/dsemul.h
new file mode 100644
index 0000000..dbd85f9
--- /dev/null
+++ b/arch/mips/math-emu/dsemul.h
@@ -0,0 +1,23 @@
+typedef long gpreg_t;
+typedef void *vaddr_t;
+
+#define REG_TO_VA (vaddr_t)
+#define VA_TO_REG (gpreg_t)
+
+int mips_dsemul(struct pt_regs *regs, mips_instruction ir, gpreg_t cpc);
+int do_dsemulret(struct pt_regs *xcp);
+
+/* Instruction which will always cause an address error */
+#define AdELOAD 0x8c000001 /* lw $0,1($0) */
+/* Instruction which will plainly cause a CP1 exception when FPU is disabled */
+#define CP1UNDEF 0x44400001 /* cfc1 $0,$0 undef */
+
+/* Instruction inserted following the badinst to further tag the sequence */
+#define BD_COOKIE 0x0000bd36 /* tne $0,$0 with baggage */
+
+/* Setup which instruction to use for trampoline */
+#ifdef STANDALONE_EMULATOR
+#define BADINST CP1UNDEF
+#else
+#define BADINST AdELOAD
+#endif
diff --git a/arch/mips/math-emu/ieee754.c b/arch/mips/math-emu/ieee754.c
new file mode 100644
index 0000000..f0a364a
--- /dev/null
+++ b/arch/mips/math-emu/ieee754.c
@@ -0,0 +1,138 @@
+/* ieee754 floating point arithmetic
+ * single and double precision
+ *
+ * BUGS
+ * not much dp done
+ * doesn't generate IEEE754_INEXACT
+ *
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ * 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 "ieee754int.h"
+
+#define DP_EBIAS 1023
+#define DP_EMIN (-1022)
+#define DP_EMAX 1023
+
+#define SP_EBIAS 127
+#define SP_EMIN (-126)
+#define SP_EMAX 127
+
+/* indexed by class */
+const char *const ieee754_cname[] = {
+ "Normal",
+ "Zero",
+ "Denormal",
+ "Infinity",
+ "QNaN",
+ "SNaN",
+};
+
+/* the control status register
+*/
+struct ieee754_csr ieee754_csr;
+
+/* special constants
+*/
+
+
+#if (defined(BYTE_ORDER) && BYTE_ORDER == LITTLE_ENDIAN) || defined(__MIPSEL__)
+#define SPSTR(s,b,m) {m,b,s}
+#define DPSTR(s,b,mh,ml) {ml,mh,b,s}
+#endif
+
+#ifdef __MIPSEB__
+#define SPSTR(s,b,m) {s,b,m}
+#define DPSTR(s,b,mh,ml) {s,b,mh,ml}
+#endif
+
+const struct ieee754dp_konst __ieee754dp_spcvals[] = {
+ DPSTR(0, DP_EMIN - 1 + DP_EBIAS, 0, 0), /* + zero */
+ DPSTR(1, DP_EMIN - 1 + DP_EBIAS, 0, 0), /* - zero */
+ DPSTR(0, DP_EBIAS, 0, 0), /* + 1.0 */
+ DPSTR(1, DP_EBIAS, 0, 0), /* - 1.0 */
+ DPSTR(0, 3 + DP_EBIAS, 0x40000, 0), /* + 10.0 */
+ DPSTR(1, 3 + DP_EBIAS, 0x40000, 0), /* - 10.0 */
+ DPSTR(0, DP_EMAX + 1 + DP_EBIAS, 0, 0), /* + infinity */
+ DPSTR(1, DP_EMAX + 1 + DP_EBIAS, 0, 0), /* - infinity */
+ DPSTR(0,DP_EMAX+1+DP_EBIAS,0x7FFFF,0xFFFFFFFF), /* + indef quiet Nan */
+ DPSTR(0, DP_EMAX + DP_EBIAS, 0xFFFFF, 0xFFFFFFFF), /* + max */
+ DPSTR(1, DP_EMAX + DP_EBIAS, 0xFFFFF, 0xFFFFFFFF), /* - max */
+ DPSTR(0, DP_EMIN + DP_EBIAS, 0, 0), /* + min normal */
+ DPSTR(1, DP_EMIN + DP_EBIAS, 0, 0), /* - min normal */
+ DPSTR(0, DP_EMIN - 1 + DP_EBIAS, 0, 1), /* + min denormal */
+ DPSTR(1, DP_EMIN - 1 + DP_EBIAS, 0, 1), /* - min denormal */
+ DPSTR(0, 31 + DP_EBIAS, 0, 0), /* + 1.0e31 */
+ DPSTR(0, 63 + DP_EBIAS, 0, 0), /* + 1.0e63 */
+};
+
+const struct ieee754sp_konst __ieee754sp_spcvals[] = {
+ SPSTR(0, SP_EMIN - 1 + SP_EBIAS, 0), /* + zero */
+ SPSTR(1, SP_EMIN - 1 + SP_EBIAS, 0), /* - zero */
+ SPSTR(0, SP_EBIAS, 0), /* + 1.0 */
+ SPSTR(1, SP_EBIAS, 0), /* - 1.0 */
+ SPSTR(0, 3 + SP_EBIAS, 0x200000), /* + 10.0 */
+ SPSTR(1, 3 + SP_EBIAS, 0x200000), /* - 10.0 */
+ SPSTR(0, SP_EMAX + 1 + SP_EBIAS, 0), /* + infinity */
+ SPSTR(1, SP_EMAX + 1 + SP_EBIAS, 0), /* - infinity */
+ SPSTR(0,SP_EMAX+1+SP_EBIAS,0x3FFFFF), /* + indef quiet Nan */
+ SPSTR(0, SP_EMAX + SP_EBIAS, 0x7FFFFF), /* + max normal */
+ SPSTR(1, SP_EMAX + SP_EBIAS, 0x7FFFFF), /* - max normal */
+ SPSTR(0, SP_EMIN + SP_EBIAS, 0), /* + min normal */
+ SPSTR(1, SP_EMIN + SP_EBIAS, 0), /* - min normal */
+ SPSTR(0, SP_EMIN - 1 + SP_EBIAS, 1), /* + min denormal */
+ SPSTR(1, SP_EMIN - 1 + SP_EBIAS, 1), /* - min denormal */
+ SPSTR(0, 31 + SP_EBIAS, 0), /* + 1.0e31 */
+ SPSTR(0, 63 + SP_EBIAS, 0), /* + 1.0e63 */
+};
+
+
+int ieee754si_xcpt(int r, const char *op, ...)
+{
+ struct ieee754xctx ax;
+
+ if (!TSTX())
+ return r;
+ ax.op = op;
+ ax.rt = IEEE754_RT_SI;
+ ax.rv.si = r;
+ va_start(ax.ap, op);
+ ieee754_xcpt(&ax);
+ return ax.rv.si;
+}
+
+s64 ieee754di_xcpt(s64 r, const char *op, ...)
+{
+ struct ieee754xctx ax;
+
+ if (!TSTX())
+ return r;
+ ax.op = op;
+ ax.rt = IEEE754_RT_DI;
+ ax.rv.di = r;
+ va_start(ax.ap, op);
+ ieee754_xcpt(&ax);
+ return ax.rv.di;
+}
diff --git a/arch/mips/math-emu/ieee754.h b/arch/mips/math-emu/ieee754.h
new file mode 100644
index 0000000..b8772f4
--- /dev/null
+++ b/arch/mips/math-emu/ieee754.h
@@ -0,0 +1,489 @@
+/* single and double precision fp ops
+ * missing extended precision.
+*/
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ * 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.
+ *
+ * ########################################################################
+ */
+
+/**************************************************************************
+ * Nov 7, 2000
+ * Modification to allow integration with Linux kernel
+ *
+ * Kevin D. Kissell, kevink@mips.com and Carsten Langgard, carstenl@mips.com
+ * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
+ *************************************************************************/
+
+#ifdef __KERNEL__
+/* Going from Algorithmics to Linux native environment, add this */
+#include <linux/types.h>
+
+/*
+ * Not very pretty, but the Linux kernel's normal va_list definition
+ * does not allow it to be used as a structure element, as it is here.
+ */
+#ifndef _STDARG_H
+#include <stdarg.h>
+#endif
+
+#else
+
+/* Note that __KERNEL__ is taken to mean Linux kernel */
+
+#if #system(OpenBSD)
+#include <machine/types.h>
+#endif
+#include <machine/endian.h>
+
+#endif /* __KERNEL__ */
+
+#if (defined(BYTE_ORDER) && BYTE_ORDER == LITTLE_ENDIAN) || defined(__MIPSEL__)
+struct ieee754dp_konst {
+ unsigned mantlo:32;
+ unsigned manthi:20;
+ unsigned bexp:11;
+ unsigned sign:1;
+};
+struct ieee754sp_konst {
+ unsigned mant:23;
+ unsigned bexp:8;
+ unsigned sign:1;
+};
+
+typedef union _ieee754dp {
+ struct ieee754dp_konst oparts;
+ struct {
+ u64 mant:52;
+ unsigned int bexp:11;
+ unsigned int sign:1;
+ } parts;
+ u64 bits;
+ double d;
+} ieee754dp;
+
+typedef union _ieee754sp {
+ struct ieee754sp_konst parts;
+ float f;
+ u32 bits;
+} ieee754sp;
+#endif
+
+#if (defined(BYTE_ORDER) && BYTE_ORDER == BIG_ENDIAN) || defined(__MIPSEB__)
+struct ieee754dp_konst {
+ unsigned sign:1;
+ unsigned bexp:11;
+ unsigned manthi:20;
+ unsigned mantlo:32;
+};
+typedef union _ieee754dp {
+ struct ieee754dp_konst oparts;
+ struct {
+ unsigned int sign:1;
+ unsigned int bexp:11;
+ u64 mant:52;
+ } parts;
+ double d;
+ u64 bits;
+} ieee754dp;
+
+struct ieee754sp_konst {
+ unsigned sign:1;
+ unsigned bexp:8;
+ unsigned mant:23;
+};
+
+typedef union _ieee754sp {
+ struct ieee754sp_konst parts;
+ float f;
+ u32 bits;
+} ieee754sp;
+#endif
+
+/*
+ * single precision (often aka float)
+*/
+int ieee754sp_finite(ieee754sp x);
+int ieee754sp_class(ieee754sp x);
+
+ieee754sp ieee754sp_abs(ieee754sp x);
+ieee754sp ieee754sp_neg(ieee754sp x);
+ieee754sp ieee754sp_scalb(ieee754sp x, int);
+ieee754sp ieee754sp_logb(ieee754sp x);
+
+/* x with sign of y */
+ieee754sp ieee754sp_copysign(ieee754sp x, ieee754sp y);
+
+ieee754sp ieee754sp_add(ieee754sp x, ieee754sp y);
+ieee754sp ieee754sp_sub(ieee754sp x, ieee754sp y);
+ieee754sp ieee754sp_mul(ieee754sp x, ieee754sp y);
+ieee754sp ieee754sp_div(ieee754sp x, ieee754sp y);
+
+ieee754sp ieee754sp_fint(int x);
+ieee754sp ieee754sp_funs(unsigned x);
+ieee754sp ieee754sp_flong(s64 x);
+ieee754sp ieee754sp_fulong(u64 x);
+ieee754sp ieee754sp_fdp(ieee754dp x);
+
+int ieee754sp_tint(ieee754sp x);
+unsigned int ieee754sp_tuns(ieee754sp x);
+s64 ieee754sp_tlong(ieee754sp x);
+u64 ieee754sp_tulong(ieee754sp x);
+
+int ieee754sp_cmp(ieee754sp x, ieee754sp y, int cop, int sig);
+/*
+ * basic sp math
+ */
+ieee754sp ieee754sp_modf(ieee754sp x, ieee754sp * ip);
+ieee754sp ieee754sp_frexp(ieee754sp x, int *exp);
+ieee754sp ieee754sp_ldexp(ieee754sp x, int exp);
+
+ieee754sp ieee754sp_ceil(ieee754sp x);
+ieee754sp ieee754sp_floor(ieee754sp x);
+ieee754sp ieee754sp_trunc(ieee754sp x);
+
+ieee754sp ieee754sp_sqrt(ieee754sp x);
+
+/*
+ * double precision (often aka double)
+*/
+int ieee754dp_finite(ieee754dp x);
+int ieee754dp_class(ieee754dp x);
+
+/* x with sign of y */
+ieee754dp ieee754dp_copysign(ieee754dp x, ieee754dp y);
+
+ieee754dp ieee754dp_add(ieee754dp x, ieee754dp y);
+ieee754dp ieee754dp_sub(ieee754dp x, ieee754dp y);
+ieee754dp ieee754dp_mul(ieee754dp x, ieee754dp y);
+ieee754dp ieee754dp_div(ieee754dp x, ieee754dp y);
+
+ieee754dp ieee754dp_abs(ieee754dp x);
+ieee754dp ieee754dp_neg(ieee754dp x);
+ieee754dp ieee754dp_scalb(ieee754dp x, int);
+
+/* return exponent as integer in floating point format
+ */
+ieee754dp ieee754dp_logb(ieee754dp x);
+
+ieee754dp ieee754dp_fint(int x);
+ieee754dp ieee754dp_funs(unsigned x);
+ieee754dp ieee754dp_flong(s64 x);
+ieee754dp ieee754dp_fulong(u64 x);
+ieee754dp ieee754dp_fsp(ieee754sp x);
+
+ieee754dp ieee754dp_ceil(ieee754dp x);
+ieee754dp ieee754dp_floor(ieee754dp x);
+ieee754dp ieee754dp_trunc(ieee754dp x);
+
+int ieee754dp_tint(ieee754dp x);
+unsigned int ieee754dp_tuns(ieee754dp x);
+s64 ieee754dp_tlong(ieee754dp x);
+u64 ieee754dp_tulong(ieee754dp x);
+
+int ieee754dp_cmp(ieee754dp x, ieee754dp y, int cop, int sig);
+/*
+ * basic sp math
+ */
+ieee754dp ieee754dp_modf(ieee754dp x, ieee754dp * ip);
+ieee754dp ieee754dp_frexp(ieee754dp x, int *exp);
+ieee754dp ieee754dp_ldexp(ieee754dp x, int exp);
+
+ieee754dp ieee754dp_ceil(ieee754dp x);
+ieee754dp ieee754dp_floor(ieee754dp x);
+ieee754dp ieee754dp_trunc(ieee754dp x);
+
+ieee754dp ieee754dp_sqrt(ieee754dp x);
+
+
+
+/* 5 types of floating point number
+*/
+#define IEEE754_CLASS_NORM 0x00
+#define IEEE754_CLASS_ZERO 0x01
+#define IEEE754_CLASS_DNORM 0x02
+#define IEEE754_CLASS_INF 0x03
+#define IEEE754_CLASS_SNAN 0x04
+#define IEEE754_CLASS_QNAN 0x05
+extern const char *const ieee754_cname[];
+
+/* exception numbers */
+#define IEEE754_INEXACT 0x01
+#define IEEE754_UNDERFLOW 0x02
+#define IEEE754_OVERFLOW 0x04
+#define IEEE754_ZERO_DIVIDE 0x08
+#define IEEE754_INVALID_OPERATION 0x10
+
+/* cmp operators
+*/
+#define IEEE754_CLT 0x01
+#define IEEE754_CEQ 0x02
+#define IEEE754_CGT 0x04
+#define IEEE754_CUN 0x08
+
+/* rounding mode
+*/
+#define IEEE754_RN 0 /* round to nearest */
+#define IEEE754_RZ 1 /* round toward zero */
+#define IEEE754_RD 2 /* round toward -Infinity */
+#define IEEE754_RU 3 /* round toward +Infinity */
+
+/* other naming */
+#define IEEE754_RM IEEE754_RD
+#define IEEE754_RP IEEE754_RU
+
+/* "normal" comparisons
+*/
+static __inline int ieee754sp_eq(ieee754sp x, ieee754sp y)
+{
+ return ieee754sp_cmp(x, y, IEEE754_CEQ, 0);
+}
+
+static __inline int ieee754sp_ne(ieee754sp x, ieee754sp y)
+{
+ return ieee754sp_cmp(x, y,
+ IEEE754_CLT | IEEE754_CGT | IEEE754_CUN, 0);
+}
+
+static __inline int ieee754sp_lt(ieee754sp x, ieee754sp y)
+{
+ return ieee754sp_cmp(x, y, IEEE754_CLT, 0);
+}
+
+static __inline int ieee754sp_le(ieee754sp x, ieee754sp y)
+{
+ return ieee754sp_cmp(x, y, IEEE754_CLT | IEEE754_CEQ, 0);
+}
+
+static __inline int ieee754sp_gt(ieee754sp x, ieee754sp y)
+{
+ return ieee754sp_cmp(x, y, IEEE754_CGT, 0);
+}
+
+
+static __inline int ieee754sp_ge(ieee754sp x, ieee754sp y)
+{
+ return ieee754sp_cmp(x, y, IEEE754_CGT | IEEE754_CEQ, 0);
+}
+
+static __inline int ieee754dp_eq(ieee754dp x, ieee754dp y)
+{
+ return ieee754dp_cmp(x, y, IEEE754_CEQ, 0);
+}
+
+static __inline int ieee754dp_ne(ieee754dp x, ieee754dp y)
+{
+ return ieee754dp_cmp(x, y,
+ IEEE754_CLT | IEEE754_CGT | IEEE754_CUN, 0);
+}
+
+static __inline int ieee754dp_lt(ieee754dp x, ieee754dp y)
+{
+ return ieee754dp_cmp(x, y, IEEE754_CLT, 0);
+}
+
+static __inline int ieee754dp_le(ieee754dp x, ieee754dp y)
+{
+ return ieee754dp_cmp(x, y, IEEE754_CLT | IEEE754_CEQ, 0);
+}
+
+static __inline int ieee754dp_gt(ieee754dp x, ieee754dp y)
+{
+ return ieee754dp_cmp(x, y, IEEE754_CGT, 0);
+}
+
+static __inline int ieee754dp_ge(ieee754dp x, ieee754dp y)
+{
+ return ieee754dp_cmp(x, y, IEEE754_CGT | IEEE754_CEQ, 0);
+}
+
+
+/* like strtod
+*/
+ieee754dp ieee754dp_fstr(const char *s, char **endp);
+char *ieee754dp_tstr(ieee754dp x, int prec, int fmt, int af);
+
+
+/* the control status register
+*/
+struct ieee754_csr {
+ unsigned pad:13;
+ unsigned nod:1; /* set 1 for no denormalised numbers */
+ unsigned cx:5; /* exceptions this operation */
+ unsigned mx:5; /* exception enable mask */
+ unsigned sx:5; /* exceptions total */
+ unsigned rm:2; /* current rounding mode */
+};
+extern struct ieee754_csr ieee754_csr;
+
+static __inline unsigned ieee754_getrm(void)
+{
+ return (ieee754_csr.rm);
+}
+static __inline unsigned ieee754_setrm(unsigned rm)
+{
+ return (ieee754_csr.rm = rm);
+}
+
+/*
+ * get current exceptions
+ */
+static __inline unsigned ieee754_getcx(void)
+{
+ return (ieee754_csr.cx);
+}
+
+/* test for current exception condition
+ */
+static __inline int ieee754_cxtest(unsigned n)
+{
+ return (ieee754_csr.cx & n);
+}
+
+/*
+ * get sticky exceptions
+ */
+static __inline unsigned ieee754_getsx(void)
+{
+ return (ieee754_csr.sx);
+}
+
+/* clear sticky conditions
+*/
+static __inline unsigned ieee754_clrsx(void)
+{
+ return (ieee754_csr.sx = 0);
+}
+
+/* test for sticky exception condition
+ */
+static __inline int ieee754_sxtest(unsigned n)
+{
+ return (ieee754_csr.sx & n);
+}
+
+/* debugging */
+ieee754sp ieee754sp_dump(char *s, ieee754sp x);
+ieee754dp ieee754dp_dump(char *s, ieee754dp x);
+
+#define IEEE754_SPCVAL_PZERO 0
+#define IEEE754_SPCVAL_NZERO 1
+#define IEEE754_SPCVAL_PONE 2
+#define IEEE754_SPCVAL_NONE 3
+#define IEEE754_SPCVAL_PTEN 4
+#define IEEE754_SPCVAL_NTEN 5
+#define IEEE754_SPCVAL_PINFINITY 6
+#define IEEE754_SPCVAL_NINFINITY 7
+#define IEEE754_SPCVAL_INDEF 8
+#define IEEE754_SPCVAL_PMAX 9 /* +max norm */
+#define IEEE754_SPCVAL_NMAX 10 /* -max norm */
+#define IEEE754_SPCVAL_PMIN 11 /* +min norm */
+#define IEEE754_SPCVAL_NMIN 12 /* +min norm */
+#define IEEE754_SPCVAL_PMIND 13 /* +min denorm */
+#define IEEE754_SPCVAL_NMIND 14 /* +min denorm */
+#define IEEE754_SPCVAL_P1E31 15 /* + 1.0e31 */
+#define IEEE754_SPCVAL_P1E63 16 /* + 1.0e63 */
+
+extern const struct ieee754dp_konst __ieee754dp_spcvals[];
+extern const struct ieee754sp_konst __ieee754sp_spcvals[];
+#define ieee754dp_spcvals ((const ieee754dp *)__ieee754dp_spcvals)
+#define ieee754sp_spcvals ((const ieee754sp *)__ieee754sp_spcvals)
+
+/* return infinity with given sign
+*/
+#define ieee754dp_inf(sn) \
+ (ieee754dp_spcvals[IEEE754_SPCVAL_PINFINITY+(sn)])
+#define ieee754dp_zero(sn) \
+ (ieee754dp_spcvals[IEEE754_SPCVAL_PZERO+(sn)])
+#define ieee754dp_one(sn) \
+ (ieee754dp_spcvals[IEEE754_SPCVAL_PONE+(sn)])
+#define ieee754dp_ten(sn) \
+ (ieee754dp_spcvals[IEEE754_SPCVAL_PTEN+(sn)])
+#define ieee754dp_indef() \
+ (ieee754dp_spcvals[IEEE754_SPCVAL_INDEF])
+#define ieee754dp_max(sn) \
+ (ieee754dp_spcvals[IEEE754_SPCVAL_PMAX+(sn)])
+#define ieee754dp_min(sn) \
+ (ieee754dp_spcvals[IEEE754_SPCVAL_PMIN+(sn)])
+#define ieee754dp_mind(sn) \
+ (ieee754dp_spcvals[IEEE754_SPCVAL_PMIND+(sn)])
+#define ieee754dp_1e31() \
+ (ieee754dp_spcvals[IEEE754_SPCVAL_P1E31])
+#define ieee754dp_1e63() \
+ (ieee754dp_spcvals[IEEE754_SPCVAL_P1E63])
+
+#define ieee754sp_inf(sn) \
+ (ieee754sp_spcvals[IEEE754_SPCVAL_PINFINITY+(sn)])
+#define ieee754sp_zero(sn) \
+ (ieee754sp_spcvals[IEEE754_SPCVAL_PZERO+(sn)])
+#define ieee754sp_one(sn) \
+ (ieee754sp_spcvals[IEEE754_SPCVAL_PONE+(sn)])
+#define ieee754sp_ten(sn) \
+ (ieee754sp_spcvals[IEEE754_SPCVAL_PTEN+(sn)])
+#define ieee754sp_indef() \
+ (ieee754sp_spcvals[IEEE754_SPCVAL_INDEF])
+#define ieee754sp_max(sn) \
+ (ieee754sp_spcvals[IEEE754_SPCVAL_PMAX+(sn)])
+#define ieee754sp_min(sn) \
+ (ieee754sp_spcvals[IEEE754_SPCVAL_PMIN+(sn)])
+#define ieee754sp_mind(sn) \
+ (ieee754sp_spcvals[IEEE754_SPCVAL_PMIND+(sn)])
+#define ieee754sp_1e31() \
+ (ieee754sp_spcvals[IEEE754_SPCVAL_P1E31])
+#define ieee754sp_1e63() \
+ (ieee754sp_spcvals[IEEE754_SPCVAL_P1E63])
+
+/* indefinite integer value
+*/
+#define ieee754si_indef() INT_MAX
+#ifdef LONG_LONG_MAX
+#define ieee754di_indef() LONG_LONG_MAX
+#else
+#define ieee754di_indef() ((s64)(~0ULL>>1))
+#endif
+
+/* IEEE exception context, passed to handler */
+struct ieee754xctx {
+ const char *op; /* operation name */
+ int rt; /* result type */
+ union {
+ ieee754sp sp; /* single precision */
+ ieee754dp dp; /* double precision */
+#ifdef IEEE854_XP
+ ieee754xp xp; /* extended precision */
+#endif
+ int si; /* standard signed integer (32bits) */
+ s64 di; /* extended signed integer (64bits) */
+ } rv; /* default result format implied by op */
+ va_list ap;
+};
+
+/* result types for xctx.rt */
+#define IEEE754_RT_SP 0
+#define IEEE754_RT_DP 1
+#define IEEE754_RT_XP 2
+#define IEEE754_RT_SI 3
+#define IEEE754_RT_DI 4
+
+extern void ieee754_xcpt(struct ieee754xctx *xcp);
+
+/* compat */
+#define ieee754dp_fix(x) ieee754dp_tint(x)
+#define ieee754sp_fix(x) ieee754sp_tint(x)
diff --git a/arch/mips/math-emu/ieee754d.c b/arch/mips/math-emu/ieee754d.c
new file mode 100644
index 0000000..7e900f3
--- /dev/null
+++ b/arch/mips/math-emu/ieee754d.c
@@ -0,0 +1,138 @@
+/*
+ * Some debug functions
+ *
+ * MIPS floating point support
+ *
+ * Copyright (C) 1994-2000 Algorithmics Ltd.
+ * http://www.algor.co.uk
+ *
+ * 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.
+ *
+ * Nov 7, 2000
+ * Modified to build and operate in Linux kernel environment.
+ *
+ * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
+ */
+
+#include <linux/kernel.h>
+#include "ieee754.h"
+
+#define DP_EBIAS 1023
+#define DP_EMIN (-1022)
+#define DP_EMAX 1023
+#define DP_FBITS 52
+
+#define SP_EBIAS 127
+#define SP_EMIN (-126)
+#define SP_EMAX 127
+#define SP_FBITS 23
+
+#define DP_MBIT(x) ((u64)1 << (x))
+#define DP_HIDDEN_BIT DP_MBIT(DP_FBITS)
+#define DP_SIGN_BIT DP_MBIT(63)
+
+
+#define SP_MBIT(x) ((u32)1 << (x))
+#define SP_HIDDEN_BIT SP_MBIT(SP_FBITS)
+#define SP_SIGN_BIT SP_MBIT(31)
+
+
+#define SPSIGN(sp) (sp.parts.sign)
+#define SPBEXP(sp) (sp.parts.bexp)
+#define SPMANT(sp) (sp.parts.mant)
+
+#define DPSIGN(dp) (dp.parts.sign)
+#define DPBEXP(dp) (dp.parts.bexp)
+#define DPMANT(dp) (dp.parts.mant)
+
+ieee754dp ieee754dp_dump(char *m, ieee754dp x)
+{
+ int i;
+
+ printk("%s", m);
+ printk("<%08x,%08x>\n", (unsigned) (x.bits >> 32),
+ (unsigned) x.bits);
+ printk("\t=");
+ switch (ieee754dp_class(x)) {
+ case IEEE754_CLASS_QNAN:
+ case IEEE754_CLASS_SNAN:
+ printk("Nan %c", DPSIGN(x) ? '-' : '+');
+ for (i = DP_FBITS - 1; i >= 0; i--)
+ printk("%c", DPMANT(x) & DP_MBIT(i) ? '1' : '0');
+ break;
+ case IEEE754_CLASS_INF:
+ printk("%cInfinity", DPSIGN(x) ? '-' : '+');
+ break;
+ case IEEE754_CLASS_ZERO:
+ printk("%cZero", DPSIGN(x) ? '-' : '+');
+ break;
+ case IEEE754_CLASS_DNORM:
+ printk("%c0.", DPSIGN(x) ? '-' : '+');
+ for (i = DP_FBITS - 1; i >= 0; i--)
+ printk("%c", DPMANT(x) & DP_MBIT(i) ? '1' : '0');
+ printk("e%d", DPBEXP(x) - DP_EBIAS);
+ break;
+ case IEEE754_CLASS_NORM:
+ printk("%c1.", DPSIGN(x) ? '-' : '+');
+ for (i = DP_FBITS - 1; i >= 0; i--)
+ printk("%c", DPMANT(x) & DP_MBIT(i) ? '1' : '0');
+ printk("e%d", DPBEXP(x) - DP_EBIAS);
+ break;
+ default:
+ printk("Illegal/Unknown IEEE754 value class");
+ }
+ printk("\n");
+ return x;
+}
+
+ieee754sp ieee754sp_dump(char *m, ieee754sp x)
+{
+ int i;
+
+ printk("%s=", m);
+ printk("<%08x>\n", (unsigned) x.bits);
+ printk("\t=");
+ switch (ieee754sp_class(x)) {
+ case IEEE754_CLASS_QNAN:
+ case IEEE754_CLASS_SNAN:
+ printk("Nan %c", SPSIGN(x) ? '-' : '+');
+ for (i = SP_FBITS - 1; i >= 0; i--)
+ printk("%c", SPMANT(x) & SP_MBIT(i) ? '1' : '0');
+ break;
+ case IEEE754_CLASS_INF:
+ printk("%cInfinity", SPSIGN(x) ? '-' : '+');
+ break;
+ case IEEE754_CLASS_ZERO:
+ printk("%cZero", SPSIGN(x) ? '-' : '+');
+ break;
+ case IEEE754_CLASS_DNORM:
+ printk("%c0.", SPSIGN(x) ? '-' : '+');
+ for (i = SP_FBITS - 1; i >= 0; i--)
+ printk("%c", SPMANT(x) & SP_MBIT(i) ? '1' : '0');
+ printk("e%d", SPBEXP(x) - SP_EBIAS);
+ break;
+ case IEEE754_CLASS_NORM:
+ printk("%c1.", SPSIGN(x) ? '-' : '+');
+ for (i = SP_FBITS - 1; i >= 0; i--)
+ printk("%c", SPMANT(x) & SP_MBIT(i) ? '1' : '0');
+ printk("e%d", SPBEXP(x) - SP_EBIAS);
+ break;
+ default:
+ printk("Illegal/Unknown IEEE754 value class");
+ }
+ printk("\n");
+ return x;
+}
+
diff --git a/arch/mips/math-emu/ieee754dp.c b/arch/mips/math-emu/ieee754dp.c
new file mode 100644
index 0000000..3e214aa
--- /dev/null
+++ b/arch/mips/math-emu/ieee754dp.c
@@ -0,0 +1,243 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ * 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 "ieee754dp.h"
+
+int ieee754dp_class(ieee754dp x)
+{
+ COMPXDP;
+ EXPLODEXDP;
+ return xc;
+}
+
+int ieee754dp_isnan(ieee754dp x)
+{
+ return ieee754dp_class(x) >= IEEE754_CLASS_SNAN;
+}
+
+int ieee754dp_issnan(ieee754dp x)
+{
+ assert(ieee754dp_isnan(x));
+ return ((DPMANT(x) & DP_MBIT(DP_MBITS-1)) == DP_MBIT(DP_MBITS-1));
+}
+
+
+ieee754dp ieee754dp_xcpt(ieee754dp r, const char *op, ...)
+{
+ struct ieee754xctx ax;
+ if (!TSTX())
+ return r;
+
+ ax.op = op;
+ ax.rt = IEEE754_RT_DP;
+ ax.rv.dp = r;
+ va_start(ax.ap, op);
+ ieee754_xcpt(&ax);
+ return ax.rv.dp;
+}
+
+ieee754dp ieee754dp_nanxcpt(ieee754dp r, const char *op, ...)
+{
+ struct ieee754xctx ax;
+
+ assert(ieee754dp_isnan(r));
+
+ if (!ieee754dp_issnan(r)) /* QNAN does not cause invalid op !! */
+ return r;
+
+ if (!SETANDTESTCX(IEEE754_INVALID_OPERATION)) {
+ /* not enabled convert to a quiet NaN */
+ DPMANT(r) &= (~DP_MBIT(DP_MBITS-1));
+ if (ieee754dp_isnan(r))
+ return r;
+ else
+ return ieee754dp_indef();
+ }
+
+ ax.op = op;
+ ax.rt = 0;
+ ax.rv.dp = r;
+ va_start(ax.ap, op);
+ ieee754_xcpt(&ax);
+ return ax.rv.dp;
+}
+
+ieee754dp ieee754dp_bestnan(ieee754dp x, ieee754dp y)
+{
+ assert(ieee754dp_isnan(x));
+ assert(ieee754dp_isnan(y));
+
+ if (DPMANT(x) > DPMANT(y))
+ return x;
+ else
+ return y;
+}
+
+
+static u64 get_rounding(int sn, u64 xm)
+{
+ /* inexact must round of 3 bits
+ */
+ if (xm & (DP_MBIT(3) - 1)) {
+ switch (ieee754_csr.rm) {
+ case IEEE754_RZ:
+ break;
+ case IEEE754_RN:
+ xm += 0x3 + ((xm >> 3) & 1);
+ /* xm += (xm&0x8)?0x4:0x3 */
+ break;
+ case IEEE754_RU: /* toward +Infinity */
+ if (!sn) /* ?? */
+ xm += 0x8;
+ break;
+ case IEEE754_RD: /* toward -Infinity */
+ if (sn) /* ?? */
+ xm += 0x8;
+ break;
+ }
+ }
+ return xm;
+}
+
+
+/* generate a normal/denormal number with over,under handling
+ * sn is sign
+ * xe is an unbiased exponent
+ * xm is 3bit extended precision value.
+ */
+ieee754dp ieee754dp_format(int sn, int xe, u64 xm)
+{
+ assert(xm); /* we don't gen exact zeros (probably should) */
+
+ assert((xm >> (DP_MBITS + 1 + 3)) == 0); /* no execess */
+ assert(xm & (DP_HIDDEN_BIT << 3));
+
+ if (xe < DP_EMIN) {
+ /* strip lower bits */
+ int es = DP_EMIN - xe;
+
+ if (ieee754_csr.nod) {
+ SETCX(IEEE754_UNDERFLOW);
+ SETCX(IEEE754_INEXACT);
+
+ switch(ieee754_csr.rm) {
+ case IEEE754_RN:
+ return ieee754dp_zero(sn);
+ case IEEE754_RZ:
+ return ieee754dp_zero(sn);
+ case IEEE754_RU: /* toward +Infinity */
+ if(sn == 0)
+ return ieee754dp_min(0);
+ else
+ return ieee754dp_zero(1);
+ case IEEE754_RD: /* toward -Infinity */
+ if(sn == 0)
+ return ieee754dp_zero(0);
+ else
+ return ieee754dp_min(1);
+ }
+ }
+
+ if (xe == DP_EMIN - 1
+ && get_rounding(sn, xm) >> (DP_MBITS + 1 + 3))
+ {
+ /* Not tiny after rounding */
+ SETCX(IEEE754_INEXACT);
+ xm = get_rounding(sn, xm);
+ xm >>= 1;
+ /* Clear grs bits */
+ xm &= ~(DP_MBIT(3) - 1);
+ xe++;
+ }
+ else {
+ /* sticky right shift es bits
+ */
+ xm = XDPSRS(xm, es);
+ xe += es;
+ assert((xm & (DP_HIDDEN_BIT << 3)) == 0);
+ assert(xe == DP_EMIN);
+ }
+ }
+ if (xm & (DP_MBIT(3) - 1)) {
+ SETCX(IEEE754_INEXACT);
+ if ((xm & (DP_HIDDEN_BIT << 3)) == 0) {
+ SETCX(IEEE754_UNDERFLOW);
+ }
+
+ /* inexact must round of 3 bits
+ */
+ xm = get_rounding(sn, xm);
+ /* adjust exponent for rounding add overflowing
+ */
+ if (xm >> (DP_MBITS + 3 + 1)) {
+ /* add causes mantissa overflow */
+ xm >>= 1;
+ xe++;
+ }
+ }
+ /* strip grs bits */
+ xm >>= 3;
+
+ assert((xm >> (DP_MBITS + 1)) == 0); /* no execess */
+ assert(xe >= DP_EMIN);
+
+ if (xe > DP_EMAX) {
+ SETCX(IEEE754_OVERFLOW);
+ SETCX(IEEE754_INEXACT);
+ /* -O can be table indexed by (rm,sn) */
+ switch (ieee754_csr.rm) {
+ case IEEE754_RN:
+ return ieee754dp_inf(sn);
+ case IEEE754_RZ:
+ return ieee754dp_max(sn);
+ case IEEE754_RU: /* toward +Infinity */
+ if (sn == 0)
+ return ieee754dp_inf(0);
+ else
+ return ieee754dp_max(1);
+ case IEEE754_RD: /* toward -Infinity */
+ if (sn == 0)
+ return ieee754dp_max(0);
+ else
+ return ieee754dp_inf(1);
+ }
+ }
+ /* gen norm/denorm/zero */
+
+ if ((xm & DP_HIDDEN_BIT) == 0) {
+ /* we underflow (tiny/zero) */
+ assert(xe == DP_EMIN);
+ if (ieee754_csr.mx & IEEE754_UNDERFLOW)
+ SETCX(IEEE754_UNDERFLOW);
+ return builddp(sn, DP_EMIN - 1 + DP_EBIAS, xm);
+ } else {
+ assert((xm >> (DP_MBITS + 1)) == 0); /* no execess */
+ assert(xm & DP_HIDDEN_BIT);
+
+ return builddp(sn, xe + DP_EBIAS, xm & ~DP_HIDDEN_BIT);
+ }
+}
diff --git a/arch/mips/math-emu/ieee754dp.h b/arch/mips/math-emu/ieee754dp.h
new file mode 100644
index 0000000..a37370d
--- /dev/null
+++ b/arch/mips/math-emu/ieee754dp.h
@@ -0,0 +1,83 @@
+/*
+ * IEEE754 floating point
+ * double precision internal header file
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ * 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 "ieee754int.h"
+
+#define assert(expr) ((void)0)
+
+/* 3bit extended double precision sticky right shift */
+#define XDPSRS(v,rs) \
+ ((rs > (DP_MBITS+3))?1:((v) >> (rs)) | ((v) << (64-(rs)) != 0))
+
+#define XDPSRSX1() \
+ (xe++, (xm = (xm >> 1) | (xm & 1)))
+
+#define XDPSRS1(v) \
+ (((v) >> 1) | ((v) & 1))
+
+/* convert denormal to normalized with extended exponent */
+#define DPDNORMx(m,e) \
+ while( (m >> DP_MBITS) == 0) { m <<= 1; e--; }
+#define DPDNORMX DPDNORMx(xm,xe)
+#define DPDNORMY DPDNORMx(ym,ye)
+
+static __inline ieee754dp builddp(int s, int bx, u64 m)
+{
+ ieee754dp r;
+
+ assert((s) == 0 || (s) == 1);
+ assert((bx) >= DP_EMIN - 1 + DP_EBIAS
+ && (bx) <= DP_EMAX + 1 + DP_EBIAS);
+ assert(((m) >> DP_MBITS) == 0);
+
+ r.parts.sign = s;
+ r.parts.bexp = bx;
+ r.parts.mant = m;
+ return r;
+}
+
+extern int ieee754dp_isnan(ieee754dp);
+extern int ieee754dp_issnan(ieee754dp);
+extern int ieee754si_xcpt(int, const char *, ...);
+extern s64 ieee754di_xcpt(s64, const char *, ...);
+extern ieee754dp ieee754dp_xcpt(ieee754dp, const char *, ...);
+extern ieee754dp ieee754dp_nanxcpt(ieee754dp, const char *, ...);
+extern ieee754dp ieee754dp_bestnan(ieee754dp, ieee754dp);
+extern ieee754dp ieee754dp_format(int, int, u64);
+
+
+#define DPNORMRET2(s,e,m,name,a0,a1) \
+{ \
+ ieee754dp V = ieee754dp_format(s,e,m); \
+ if(TSTX()) \
+ return ieee754dp_xcpt(V,name,a0,a1); \
+ else \
+ return V; \
+}
+
+#define DPNORMRET1(s,e,m,name,a0) DPNORMRET2(s,e,m,name,a0,a0)
diff --git a/arch/mips/math-emu/ieee754int.h b/arch/mips/math-emu/ieee754int.h
new file mode 100644
index 0000000..4a5a81d
--- /dev/null
+++ b/arch/mips/math-emu/ieee754int.h
@@ -0,0 +1,165 @@
+/*
+ * IEEE754 floating point
+ * common internal header file
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ * 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 "ieee754.h"
+
+#define DP_EBIAS 1023
+#define DP_EMIN (-1022)
+#define DP_EMAX 1023
+#define DP_MBITS 52
+
+#define SP_EBIAS 127
+#define SP_EMIN (-126)
+#define SP_EMAX 127
+#define SP_MBITS 23
+
+#define DP_MBIT(x) ((u64)1 << (x))
+#define DP_HIDDEN_BIT DP_MBIT(DP_MBITS)
+#define DP_SIGN_BIT DP_MBIT(63)
+
+#define SP_MBIT(x) ((u32)1 << (x))
+#define SP_HIDDEN_BIT SP_MBIT(SP_MBITS)
+#define SP_SIGN_BIT SP_MBIT(31)
+
+
+#define SPSIGN(sp) (sp.parts.sign)
+#define SPBEXP(sp) (sp.parts.bexp)
+#define SPMANT(sp) (sp.parts.mant)
+
+#define DPSIGN(dp) (dp.parts.sign)
+#define DPBEXP(dp) (dp.parts.bexp)
+#define DPMANT(dp) (dp.parts.mant)
+
+#define CLPAIR(x,y) ((x)*6+(y))
+
+#define CLEARCX \
+ (ieee754_csr.cx = 0)
+
+#define SETCX(x) \
+ (ieee754_csr.cx |= (x),ieee754_csr.sx |= (x))
+
+#define SETANDTESTCX(x) \
+ (SETCX(x),ieee754_csr.mx & (x))
+
+#define TSTX() \
+ (ieee754_csr.cx & ieee754_csr.mx)
+
+
+#define COMPXSP \
+ unsigned xm; int xe; int xs; int xc
+
+#define COMPYSP \
+ unsigned ym; int ye; int ys; int yc
+
+#define EXPLODESP(v,vc,vs,ve,vm) \
+{\
+ vs = SPSIGN(v);\
+ ve = SPBEXP(v);\
+ vm = SPMANT(v);\
+ if(ve == SP_EMAX+1+SP_EBIAS){\
+ if(vm == 0)\
+ vc = IEEE754_CLASS_INF;\
+ else if(vm & SP_MBIT(SP_MBITS-1)) \
+ vc = IEEE754_CLASS_SNAN;\
+ else \
+ vc = IEEE754_CLASS_QNAN;\
+ } else if(ve == SP_EMIN-1+SP_EBIAS) {\
+ if(vm) {\
+ ve = SP_EMIN;\
+ vc = IEEE754_CLASS_DNORM;\
+ } else\
+ vc = IEEE754_CLASS_ZERO;\
+ } else {\
+ ve -= SP_EBIAS;\
+ vm |= SP_HIDDEN_BIT;\
+ vc = IEEE754_CLASS_NORM;\
+ }\
+}
+#define EXPLODEXSP EXPLODESP(x,xc,xs,xe,xm)
+#define EXPLODEYSP EXPLODESP(y,yc,ys,ye,ym)
+
+
+#define COMPXDP \
+u64 xm; int xe; int xs; int xc
+
+#define COMPYDP \
+u64 ym; int ye; int ys; int yc
+
+#define EXPLODEDP(v,vc,vs,ve,vm) \
+{\
+ vm = DPMANT(v);\
+ vs = DPSIGN(v);\
+ ve = DPBEXP(v);\
+ if(ve == DP_EMAX+1+DP_EBIAS){\
+ if(vm == 0)\
+ vc = IEEE754_CLASS_INF;\
+ else if(vm & DP_MBIT(DP_MBITS-1)) \
+ vc = IEEE754_CLASS_SNAN;\
+ else \
+ vc = IEEE754_CLASS_QNAN;\
+ } else if(ve == DP_EMIN-1+DP_EBIAS) {\
+ if(vm) {\
+ ve = DP_EMIN;\
+ vc = IEEE754_CLASS_DNORM;\
+ } else\
+ vc = IEEE754_CLASS_ZERO;\
+ } else {\
+ ve -= DP_EBIAS;\
+ vm |= DP_HIDDEN_BIT;\
+ vc = IEEE754_CLASS_NORM;\
+ }\
+}
+#define EXPLODEXDP EXPLODEDP(x,xc,xs,xe,xm)
+#define EXPLODEYDP EXPLODEDP(y,yc,ys,ye,ym)
+
+#define FLUSHDP(v,vc,vs,ve,vm) \
+ if(vc==IEEE754_CLASS_DNORM) {\
+ if(ieee754_csr.nod) {\
+ SETCX(IEEE754_INEXACT);\
+ vc = IEEE754_CLASS_ZERO;\
+ ve = DP_EMIN-1+DP_EBIAS;\
+ vm = 0;\
+ v = ieee754dp_zero(vs);\
+ }\
+ }
+
+#define FLUSHSP(v,vc,vs,ve,vm) \
+ if(vc==IEEE754_CLASS_DNORM) {\
+ if(ieee754_csr.nod) {\
+ SETCX(IEEE754_INEXACT);\
+ vc = IEEE754_CLASS_ZERO;\
+ ve = SP_EMIN-1+SP_EBIAS;\
+ vm = 0;\
+ v = ieee754sp_zero(vs);\
+ }\
+ }
+
+#define FLUSHXDP FLUSHDP(x,xc,xs,xe,xm)
+#define FLUSHYDP FLUSHDP(y,yc,ys,ye,ym)
+#define FLUSHXSP FLUSHSP(x,xc,xs,xe,xm)
+#define FLUSHYSP FLUSHSP(y,yc,ys,ye,ym)
diff --git a/arch/mips/math-emu/ieee754m.c b/arch/mips/math-emu/ieee754m.c
new file mode 100644
index 0000000..d66896c
--- /dev/null
+++ b/arch/mips/math-emu/ieee754m.c
@@ -0,0 +1,56 @@
+/*
+ * floor, trunc, ceil
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ * 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 "ieee754.h"
+
+ieee754dp ieee754dp_floor(ieee754dp x)
+{
+ ieee754dp i;
+
+ if (ieee754dp_lt(ieee754dp_modf(x, &i), ieee754dp_zero(0)))
+ return ieee754dp_sub(i, ieee754dp_one(0));
+ else
+ return i;
+}
+
+ieee754dp ieee754dp_ceil(ieee754dp x)
+{
+ ieee754dp i;
+
+ if (ieee754dp_gt(ieee754dp_modf(x, &i), ieee754dp_zero(0)))
+ return ieee754dp_add(i, ieee754dp_one(0));
+ else
+ return i;
+}
+
+ieee754dp ieee754dp_trunc(ieee754dp x)
+{
+ ieee754dp i;
+
+ (void) ieee754dp_modf(x, &i);
+ return i;
+}
diff --git a/arch/mips/math-emu/ieee754sp.c b/arch/mips/math-emu/ieee754sp.c
new file mode 100644
index 0000000..adda851
--- /dev/null
+++ b/arch/mips/math-emu/ieee754sp.c
@@ -0,0 +1,243 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ * 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 "ieee754sp.h"
+
+int ieee754sp_class(ieee754sp x)
+{
+ COMPXSP;
+ EXPLODEXSP;
+ return xc;
+}
+
+int ieee754sp_isnan(ieee754sp x)
+{
+ return ieee754sp_class(x) >= IEEE754_CLASS_SNAN;
+}
+
+int ieee754sp_issnan(ieee754sp x)
+{
+ assert(ieee754sp_isnan(x));
+ return (SPMANT(x) & SP_MBIT(SP_MBITS-1));
+}
+
+
+ieee754sp ieee754sp_xcpt(ieee754sp r, const char *op, ...)
+{
+ struct ieee754xctx ax;
+
+ if (!TSTX())
+ return r;
+
+ ax.op = op;
+ ax.rt = IEEE754_RT_SP;
+ ax.rv.sp = r;
+ va_start(ax.ap, op);
+ ieee754_xcpt(&ax);
+ return ax.rv.sp;
+}
+
+ieee754sp ieee754sp_nanxcpt(ieee754sp r, const char *op, ...)
+{
+ struct ieee754xctx ax;
+
+ assert(ieee754sp_isnan(r));
+
+ if (!ieee754sp_issnan(r)) /* QNAN does not cause invalid op !! */
+ return r;
+
+ if (!SETANDTESTCX(IEEE754_INVALID_OPERATION)) {
+ /* not enabled convert to a quiet NaN */
+ SPMANT(r) &= (~SP_MBIT(SP_MBITS-1));
+ if (ieee754sp_isnan(r))
+ return r;
+ else
+ return ieee754sp_indef();
+ }
+
+ ax.op = op;
+ ax.rt = 0;
+ ax.rv.sp = r;
+ va_start(ax.ap, op);
+ ieee754_xcpt(&ax);
+ return ax.rv.sp;
+}
+
+ieee754sp ieee754sp_bestnan(ieee754sp x, ieee754sp y)
+{
+ assert(ieee754sp_isnan(x));
+ assert(ieee754sp_isnan(y));
+
+ if (SPMANT(x) > SPMANT(y))
+ return x;
+ else
+ return y;
+}
+
+
+static unsigned get_rounding(int sn, unsigned xm)
+{
+ /* inexact must round of 3 bits
+ */
+ if (xm & (SP_MBIT(3) - 1)) {
+ switch (ieee754_csr.rm) {
+ case IEEE754_RZ:
+ break;
+ case IEEE754_RN:
+ xm += 0x3 + ((xm >> 3) & 1);
+ /* xm += (xm&0x8)?0x4:0x3 */
+ break;
+ case IEEE754_RU: /* toward +Infinity */
+ if (!sn) /* ?? */
+ xm += 0x8;
+ break;
+ case IEEE754_RD: /* toward -Infinity */
+ if (sn) /* ?? */
+ xm += 0x8;
+ break;
+ }
+ }
+ return xm;
+}
+
+
+/* generate a normal/denormal number with over,under handling
+ * sn is sign
+ * xe is an unbiased exponent
+ * xm is 3bit extended precision value.
+ */
+ieee754sp ieee754sp_format(int sn, int xe, unsigned xm)
+{
+ assert(xm); /* we don't gen exact zeros (probably should) */
+
+ assert((xm >> (SP_MBITS + 1 + 3)) == 0); /* no execess */
+ assert(xm & (SP_HIDDEN_BIT << 3));
+
+ if (xe < SP_EMIN) {
+ /* strip lower bits */
+ int es = SP_EMIN - xe;
+
+ if (ieee754_csr.nod) {
+ SETCX(IEEE754_UNDERFLOW);
+ SETCX(IEEE754_INEXACT);
+
+ switch(ieee754_csr.rm) {
+ case IEEE754_RN:
+ return ieee754sp_zero(sn);
+ case IEEE754_RZ:
+ return ieee754sp_zero(sn);
+ case IEEE754_RU: /* toward +Infinity */
+ if(sn == 0)
+ return ieee754sp_min(0);
+ else
+ return ieee754sp_zero(1);
+ case IEEE754_RD: /* toward -Infinity */
+ if(sn == 0)
+ return ieee754sp_zero(0);
+ else
+ return ieee754sp_min(1);
+ }
+ }
+
+ if (xe == SP_EMIN - 1
+ && get_rounding(sn, xm) >> (SP_MBITS + 1 + 3))
+ {
+ /* Not tiny after rounding */
+ SETCX(IEEE754_INEXACT);
+ xm = get_rounding(sn, xm);
+ xm >>= 1;
+ /* Clear grs bits */
+ xm &= ~(SP_MBIT(3) - 1);
+ xe++;
+ }
+ else {
+ /* sticky right shift es bits
+ */
+ SPXSRSXn(es);
+ assert((xm & (SP_HIDDEN_BIT << 3)) == 0);
+ assert(xe == SP_EMIN);
+ }
+ }
+ if (xm & (SP_MBIT(3) - 1)) {
+ SETCX(IEEE754_INEXACT);
+ if ((xm & (SP_HIDDEN_BIT << 3)) == 0) {
+ SETCX(IEEE754_UNDERFLOW);
+ }
+
+ /* inexact must round of 3 bits
+ */
+ xm = get_rounding(sn, xm);
+ /* adjust exponent for rounding add overflowing
+ */
+ if (xm >> (SP_MBITS + 1 + 3)) {
+ /* add causes mantissa overflow */
+ xm >>= 1;
+ xe++;
+ }
+ }
+ /* strip grs bits */
+ xm >>= 3;
+
+ assert((xm >> (SP_MBITS + 1)) == 0); /* no execess */
+ assert(xe >= SP_EMIN);
+
+ if (xe > SP_EMAX) {
+ SETCX(IEEE754_OVERFLOW);
+ SETCX(IEEE754_INEXACT);
+ /* -O can be table indexed by (rm,sn) */
+ switch (ieee754_csr.rm) {
+ case IEEE754_RN:
+ return ieee754sp_inf(sn);
+ case IEEE754_RZ:
+ return ieee754sp_max(sn);
+ case IEEE754_RU: /* toward +Infinity */
+ if (sn == 0)
+ return ieee754sp_inf(0);
+ else
+ return ieee754sp_max(1);
+ case IEEE754_RD: /* toward -Infinity */
+ if (sn == 0)
+ return ieee754sp_max(0);
+ else
+ return ieee754sp_inf(1);
+ }
+ }
+ /* gen norm/denorm/zero */
+
+ if ((xm & SP_HIDDEN_BIT) == 0) {
+ /* we underflow (tiny/zero) */
+ assert(xe == SP_EMIN);
+ if (ieee754_csr.mx & IEEE754_UNDERFLOW)
+ SETCX(IEEE754_UNDERFLOW);
+ return buildsp(sn, SP_EMIN - 1 + SP_EBIAS, xm);
+ } else {
+ assert((xm >> (SP_MBITS + 1)) == 0); /* no execess */
+ assert(xm & SP_HIDDEN_BIT);
+
+ return buildsp(sn, xe + SP_EBIAS, xm & ~SP_HIDDEN_BIT);
+ }
+}
diff --git a/arch/mips/math-emu/ieee754sp.h b/arch/mips/math-emu/ieee754sp.h
new file mode 100644
index 0000000..ae82f51
--- /dev/null
+++ b/arch/mips/math-emu/ieee754sp.h
@@ -0,0 +1,89 @@
+/*
+ * IEEE754 floating point
+ * double precision internal header file
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ * 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 "ieee754int.h"
+
+#define assert(expr) ((void)0)
+
+/* 3bit extended single precision sticky right shift */
+#define SPXSRSXn(rs) \
+ (xe += rs, \
+ xm = (rs > (SP_MBITS+3))?1:((xm) >> (rs)) | ((xm) << (32-(rs)) != 0))
+
+#define SPXSRSX1() \
+ (xe++, (xm = (xm >> 1) | (xm & 1)))
+
+#define SPXSRSYn(rs) \
+ (ye+=rs, \
+ ym = (rs > (SP_MBITS+3))?1:((ym) >> (rs)) | ((ym) << (32-(rs)) != 0))
+
+#define SPXSRSY1() \
+ (ye++, (ym = (ym >> 1) | (ym & 1)))
+
+/* convert denormal to normalized with extended exponent */
+#define SPDNORMx(m,e) \
+ while( (m >> SP_MBITS) == 0) { m <<= 1; e--; }
+#define SPDNORMX SPDNORMx(xm,xe)
+#define SPDNORMY SPDNORMx(ym,ye)
+
+static __inline ieee754sp buildsp(int s, int bx, unsigned m)
+{
+ ieee754sp r;
+
+ assert((s) == 0 || (s) == 1);
+ assert((bx) >= SP_EMIN - 1 + SP_EBIAS
+ && (bx) <= SP_EMAX + 1 + SP_EBIAS);
+ assert(((m) >> SP_MBITS) == 0);
+
+ r.parts.sign = s;
+ r.parts.bexp = bx;
+ r.parts.mant = m;
+
+ return r;
+}
+
+extern int ieee754sp_isnan(ieee754sp);
+extern int ieee754sp_issnan(ieee754sp);
+extern int ieee754si_xcpt(int, const char *, ...);
+extern s64 ieee754di_xcpt(s64, const char *, ...);
+extern ieee754sp ieee754sp_xcpt(ieee754sp, const char *, ...);
+extern ieee754sp ieee754sp_nanxcpt(ieee754sp, const char *, ...);
+extern ieee754sp ieee754sp_bestnan(ieee754sp, ieee754sp);
+extern ieee754sp ieee754sp_format(int, int, unsigned);
+
+
+#define SPNORMRET2(s,e,m,name,a0,a1) \
+{ \
+ ieee754sp V = ieee754sp_format(s,e,m); \
+ if(TSTX()) \
+ return ieee754sp_xcpt(V,name,a0,a1); \
+ else \
+ return V; \
+}
+
+#define SPNORMRET1(s,e,m,name,a0) SPNORMRET2(s,e,m,name,a0,a0)
diff --git a/arch/mips/math-emu/ieee754xcpt.c b/arch/mips/math-emu/ieee754xcpt.c
new file mode 100644
index 0000000..7d8ef89
--- /dev/null
+++ b/arch/mips/math-emu/ieee754xcpt.c
@@ -0,0 +1,49 @@
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ * 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.
+ *
+ * ########################################################################
+ */
+
+/**************************************************************************
+ * Nov 7, 2000
+ * Added preprocessor hacks to map to Linux kernel diagnostics.
+ *
+ * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
+ *************************************************************************/
+
+#include <linux/kernel.h>
+#include "ieee754.h"
+
+/*
+ * Very naff exception handler (you can plug in your own and
+ * override this).
+ */
+
+static const char *const rtnames[] = {
+ "sp", "dp", "xp", "si", "di"
+};
+
+void ieee754_xcpt(struct ieee754xctx *xcp)
+{
+ printk(KERN_DEBUG "floating point exception in \"%s\", type=%s\n",
+ xcp->op, rtnames[xcp->rt]);
+}
+
diff --git a/arch/mips/math-emu/kernel_linkage.c b/arch/mips/math-emu/kernel_linkage.c
new file mode 100644
index 0000000..04397fec
--- /dev/null
+++ b/arch/mips/math-emu/kernel_linkage.c
@@ -0,0 +1,125 @@
+/*
+ * Kevin D. Kissell, kevink@mips and Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Routines corresponding to Linux kernel FP context
+ * manipulation primitives for the Algorithmics MIPS
+ * FPU Emulator
+ */
+#include <linux/config.h>
+#include <linux/sched.h>
+#include <asm/processor.h>
+#include <asm/signal.h>
+#include <asm/uaccess.h>
+
+#include <asm/fpu_emulator.h>
+
+extern struct mips_fpu_emulator_private fpuemuprivate;
+
+#define SIGNALLING_NAN 0x7ff800007ff80000LL
+
+void fpu_emulator_init_fpu(void)
+{
+ static int first = 1;
+ int i;
+
+ if (first) {
+ first = 0;
+ printk("Algorithmics/MIPS FPU Emulator v1.5\n");
+ }
+
+ current->thread.fpu.soft.fcr31 = 0;
+ for (i = 0; i < 32; i++) {
+ current->thread.fpu.soft.fpr[i] = SIGNALLING_NAN;
+ }
+}
+
+
+/*
+ * Emulator context save/restore to/from a signal context
+ * presumed to be on the user stack, and therefore accessed
+ * with appropriate macros from uaccess.h
+ */
+
+int fpu_emulator_save_context(struct sigcontext *sc)
+{
+ int i;
+ int err = 0;
+
+ for (i = 0; i < 32; i++) {
+ err |=
+ __put_user(current->thread.fpu.soft.fpr[i],
+ &sc->sc_fpregs[i]);
+ }
+ err |= __put_user(current->thread.fpu.soft.fcr31, &sc->sc_fpc_csr);
+ err |= __put_user(fpuemuprivate.eir, &sc->sc_fpc_eir);
+
+ return err;
+}
+
+int fpu_emulator_restore_context(struct sigcontext *sc)
+{
+ int i;
+ int err = 0;
+
+ for (i = 0; i < 32; i++) {
+ err |=
+ __get_user(current->thread.fpu.soft.fpr[i],
+ &sc->sc_fpregs[i]);
+ }
+ err |= __get_user(current->thread.fpu.soft.fcr31, &sc->sc_fpc_csr);
+ err |= __get_user(fpuemuprivate.eir, &sc->sc_fpc_eir);
+
+ return err;
+}
+
+#ifdef CONFIG_MIPS64
+/*
+ * This is the o32 version
+ */
+
+int fpu_emulator_save_context32(struct sigcontext32 *sc)
+{
+ int i;
+ int err = 0;
+
+ for (i = 0; i < 32; i+=2) {
+ err |=
+ __put_user(current->thread.fpu.soft.fpr[i],
+ &sc->sc_fpregs[i]);
+ }
+ err |= __put_user(current->thread.fpu.soft.fcr31, &sc->sc_fpc_csr);
+ err |= __put_user(fpuemuprivate.eir, &sc->sc_fpc_eir);
+
+ return err;
+}
+
+int fpu_emulator_restore_context32(struct sigcontext32 *sc)
+{
+ int i;
+ int err = 0;
+
+ for (i = 0; i < 32; i+=2) {
+ err |=
+ __get_user(current->thread.fpu.soft.fpr[i],
+ &sc->sc_fpregs[i]);
+ }
+ err |= __get_user(current->thread.fpu.soft.fcr31, &sc->sc_fpc_csr);
+ err |= __get_user(fpuemuprivate.eir, &sc->sc_fpc_eir);
+
+ return err;
+}
+#endif
diff --git a/arch/mips/math-emu/sp_add.c b/arch/mips/math-emu/sp_add.c
new file mode 100644
index 0000000..d8c4211
--- /dev/null
+++ b/arch/mips/math-emu/sp_add.c
@@ -0,0 +1,177 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ * 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 "ieee754sp.h"
+
+ieee754sp ieee754sp_add(ieee754sp x, ieee754sp y)
+{
+ COMPXSP;
+ COMPYSP;
+
+ EXPLODEXSP;
+ EXPLODEYSP;
+
+ CLEARCX;
+
+ FLUSHXSP;
+ FLUSHYSP;
+
+ switch (CLPAIR(xc, yc)) {
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
+ SETCX(IEEE754_INVALID_OPERATION);
+ return ieee754sp_nanxcpt(ieee754sp_indef(), "add", x, y);
+
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
+ return y;
+
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
+ return x;
+
+
+ /* Infinity handling
+ */
+
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
+ if (xs == ys)
+ return x;
+ SETCX(IEEE754_INVALID_OPERATION);
+ return ieee754sp_xcpt(ieee754sp_indef(), "add", x, y);
+
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
+ return y;
+
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
+ return x;
+
+ /* Zero handling
+ */
+
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
+ if (xs == ys)
+ return x;
+ else
+ return ieee754sp_zero(ieee754_csr.rm ==
+ IEEE754_RD);
+
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
+ return x;
+
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
+ return y;
+
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
+ SPDNORMX;
+
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
+ SPDNORMY;
+ break;
+
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
+ SPDNORMX;
+ break;
+
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
+ break;
+ }
+ assert(xm & SP_HIDDEN_BIT);
+ assert(ym & SP_HIDDEN_BIT);
+
+ /* provide guard,round and stick bit space */
+ xm <<= 3;
+ ym <<= 3;
+
+ if (xe > ye) {
+ /* have to shift y fraction right to align
+ */
+ int s = xe - ye;
+ SPXSRSYn(s);
+ } else if (ye > xe) {
+ /* have to shift x fraction right to align
+ */
+ int s = ye - xe;
+ SPXSRSXn(s);
+ }
+ assert(xe == ye);
+ assert(xe <= SP_EMAX);
+
+ if (xs == ys) {
+ /* generate 28 bit result of adding two 27 bit numbers
+ * leaving result in xm,xs,xe
+ */
+ xm = xm + ym;
+ xe = xe;
+ xs = xs;
+
+ if (xm >> (SP_MBITS + 1 + 3)) { /* carry out */
+ SPXSRSX1();
+ }
+ } else {
+ if (xm >= ym) {
+ xm = xm - ym;
+ xe = xe;
+ xs = xs;
+ } else {
+ xm = ym - xm;
+ xe = xe;
+ xs = ys;
+ }
+ if (xm == 0)
+ return ieee754sp_zero(ieee754_csr.rm ==
+ IEEE754_RD);
+
+ /* normalize in extended single precision */
+ while ((xm >> (SP_MBITS + 3)) == 0) {
+ xm <<= 1;
+ xe--;
+ }
+
+ }
+ SPNORMRET2(xs, xe, xm, "add", x, y);
+}
diff --git a/arch/mips/math-emu/sp_cmp.c b/arch/mips/math-emu/sp_cmp.c
new file mode 100644
index 0000000..d3eff6b
--- /dev/null
+++ b/arch/mips/math-emu/sp_cmp.c
@@ -0,0 +1,67 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ * 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 "ieee754sp.h"
+
+int ieee754sp_cmp(ieee754sp x, ieee754sp y, int cmp, int sig)
+{
+ COMPXSP;
+ COMPYSP;
+
+ EXPLODEXSP;
+ EXPLODEYSP;
+ FLUSHXSP;
+ FLUSHYSP;
+ CLEARCX; /* Even clear inexact flag here */
+
+ if (ieee754sp_isnan(x) || ieee754sp_isnan(y)) {
+ if (sig || xc == IEEE754_CLASS_SNAN || yc == IEEE754_CLASS_SNAN)
+ SETCX(IEEE754_INVALID_OPERATION);
+ if (cmp & IEEE754_CUN)
+ return 1;
+ if (cmp & (IEEE754_CLT | IEEE754_CGT)) {
+ if (sig && SETANDTESTCX(IEEE754_INVALID_OPERATION))
+ return ieee754si_xcpt(0, "fcmpf", x);
+ }
+ return 0;
+ } else {
+ int vx = x.bits;
+ int vy = y.bits;
+
+ if (vx < 0)
+ vx = -vx ^ SP_SIGN_BIT;
+ if (vy < 0)
+ vy = -vy ^ SP_SIGN_BIT;
+
+ if (vx < vy)
+ return (cmp & IEEE754_CLT) != 0;
+ else if (vx == vy)
+ return (cmp & IEEE754_CEQ) != 0;
+ else
+ return (cmp & IEEE754_CGT) != 0;
+ }
+}
diff --git a/arch/mips/math-emu/sp_div.c b/arch/mips/math-emu/sp_div.c
new file mode 100644
index 0000000..2b437fc
--- /dev/null
+++ b/arch/mips/math-emu/sp_div.c
@@ -0,0 +1,157 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ * 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 "ieee754sp.h"
+
+ieee754sp ieee754sp_div(ieee754sp x, ieee754sp y)
+{
+ COMPXSP;
+ COMPYSP;
+
+ EXPLODEXSP;
+ EXPLODEYSP;
+
+ CLEARCX;
+
+ FLUSHXSP;
+ FLUSHYSP;
+
+ switch (CLPAIR(xc, yc)) {
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
+ SETCX(IEEE754_INVALID_OPERATION);
+ return ieee754sp_nanxcpt(ieee754sp_indef(), "div", x, y);
+
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
+ return y;
+
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
+ return x;
+
+
+ /* Infinity handling
+ */
+
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
+ SETCX(IEEE754_INVALID_OPERATION);
+ return ieee754sp_xcpt(ieee754sp_indef(), "div", x, y);
+
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
+ return ieee754sp_zero(xs ^ ys);
+
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
+ return ieee754sp_inf(xs ^ ys);
+
+ /* Zero handling
+ */
+
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
+ SETCX(IEEE754_INVALID_OPERATION);
+ return ieee754sp_xcpt(ieee754sp_indef(), "div", x, y);
+
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
+ SETCX(IEEE754_ZERO_DIVIDE);
+ return ieee754sp_xcpt(ieee754sp_inf(xs ^ ys), "div", x, y);
+
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
+ return ieee754sp_zero(xs == ys ? 0 : 1);
+
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
+ SPDNORMX;
+
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
+ SPDNORMY;
+ break;
+
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
+ SPDNORMX;
+ break;
+
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
+ break;
+ }
+ assert(xm & SP_HIDDEN_BIT);
+ assert(ym & SP_HIDDEN_BIT);
+
+ /* provide rounding space */
+ xm <<= 3;
+ ym <<= 3;
+
+ {
+ /* now the dirty work */
+
+ unsigned rm = 0;
+ int re = xe - ye;
+ unsigned bm;
+
+ for (bm = SP_MBIT(SP_MBITS + 2); bm; bm >>= 1) {
+ if (xm >= ym) {
+ xm -= ym;
+ rm |= bm;
+ if (xm == 0)
+ break;
+ }
+ xm <<= 1;
+ }
+ rm <<= 1;
+ if (xm)
+ rm |= 1; /* have remainder, set sticky */
+
+ assert(rm);
+
+ /* normalise rm to rounding precision ?
+ */
+ while ((rm >> (SP_MBITS + 3)) == 0) {
+ rm <<= 1;
+ re--;
+ }
+
+ SPNORMRET2(xs == ys ? 0 : 1, re, rm, "div", x, y);
+ }
+}
diff --git a/arch/mips/math-emu/sp_fdp.c b/arch/mips/math-emu/sp_fdp.c
new file mode 100644
index 0000000..4093723
--- /dev/null
+++ b/arch/mips/math-emu/sp_fdp.c
@@ -0,0 +1,77 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ * 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 "ieee754sp.h"
+
+ieee754sp ieee754sp_fdp(ieee754dp x)
+{
+ COMPXDP;
+ ieee754sp nan;
+
+ EXPLODEXDP;
+
+ CLEARCX;
+
+ FLUSHXDP;
+
+ switch (xc) {
+ case IEEE754_CLASS_SNAN:
+ SETCX(IEEE754_INVALID_OPERATION);
+ return ieee754sp_nanxcpt(ieee754sp_indef(), "fdp");
+ case IEEE754_CLASS_QNAN:
+ nan = buildsp(xs, SP_EMAX + 1 + SP_EBIAS, (u32)
+ (xm >> (DP_MBITS - SP_MBITS)));
+ if (!ieee754sp_isnan(nan))
+ nan = ieee754sp_indef();
+ return ieee754sp_nanxcpt(nan, "fdp", x);
+ case IEEE754_CLASS_INF:
+ return ieee754sp_inf(xs);
+ case IEEE754_CLASS_ZERO:
+ return ieee754sp_zero(xs);
+ case IEEE754_CLASS_DNORM:
+ /* can't possibly be sp representable */
+ SETCX(IEEE754_UNDERFLOW);
+ SETCX(IEEE754_INEXACT);
+ if ((ieee754_csr.rm == IEEE754_RU && !xs) ||
+ (ieee754_csr.rm == IEEE754_RD && xs))
+ return ieee754sp_xcpt(ieee754sp_mind(xs), "fdp", x);
+ return ieee754sp_xcpt(ieee754sp_zero(xs), "fdp", x);
+ case IEEE754_CLASS_NORM:
+ break;
+ }
+
+ {
+ u32 rm;
+
+ /* convert from DP_MBITS to SP_MBITS+3 with sticky right shift
+ */
+ rm = (xm >> (DP_MBITS - (SP_MBITS + 3))) |
+ ((xm << (64 - (DP_MBITS - (SP_MBITS + 3)))) != 0);
+
+ SPNORMRET1(xs, xe, rm, "fdp", x);
+ }
+}
diff --git a/arch/mips/math-emu/sp_fint.c b/arch/mips/math-emu/sp_fint.c
new file mode 100644
index 0000000..42d9ed4
--- /dev/null
+++ b/arch/mips/math-emu/sp_fint.c
@@ -0,0 +1,80 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ * 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 "ieee754sp.h"
+
+ieee754sp ieee754sp_fint(int x)
+{
+ COMPXSP;
+
+ CLEARCX;
+
+ xc = ( 0 ? xc : xc );
+
+ if (x == 0)
+ return ieee754sp_zero(0);
+ if (x == 1 || x == -1)
+ return ieee754sp_one(x < 0);
+ if (x == 10 || x == -10)
+ return ieee754sp_ten(x < 0);
+
+ xs = (x < 0);
+ if (xs) {
+ if (x == (1 << 31))
+ xm = ((unsigned) 1 << 31); /* max neg can't be safely negated */
+ else
+ xm = -x;
+ } else {
+ xm = x;
+ }
+ xe = SP_MBITS + 3;
+
+ if (xm >> (SP_MBITS + 1 + 3)) {
+ /* shunt out overflow bits
+ */
+ while (xm >> (SP_MBITS + 1 + 3)) {
+ SPXSRSX1();
+ }
+ } else {
+ /* normalize in grs extended single precision
+ */
+ while ((xm >> (SP_MBITS + 3)) == 0) {
+ xm <<= 1;
+ xe--;
+ }
+ }
+ SPNORMRET1(xs, xe, xm, "fint", x);
+}
+
+
+ieee754sp ieee754sp_funs(unsigned int u)
+{
+ if ((int) u < 0)
+ return ieee754sp_add(ieee754sp_1e31(),
+ ieee754sp_fint(u & ~(1 << 31)));
+ return ieee754sp_fint(u);
+}
diff --git a/arch/mips/math-emu/sp_flong.c b/arch/mips/math-emu/sp_flong.c
new file mode 100644
index 0000000..1e26795
--- /dev/null
+++ b/arch/mips/math-emu/sp_flong.c
@@ -0,0 +1,79 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ * 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 "ieee754sp.h"
+
+ieee754sp ieee754sp_flong(s64 x)
+{
+ COMPXDP; /* <--- need 64-bit mantissa temp */
+
+ CLEARCX;
+
+ xc = ( 0 ? xc : xc );
+
+ if (x == 0)
+ return ieee754sp_zero(0);
+ if (x == 1 || x == -1)
+ return ieee754sp_one(x < 0);
+ if (x == 10 || x == -10)
+ return ieee754sp_ten(x < 0);
+
+ xs = (x < 0);
+ if (xs) {
+ if (x == (1ULL << 63))
+ xm = (1ULL << 63); /* max neg can't be safely negated */
+ else
+ xm = -x;
+ } else {
+ xm = x;
+ }
+ xe = SP_MBITS + 3;
+
+ if (xm >> (SP_MBITS + 1 + 3)) {
+ /* shunt out overflow bits
+ */
+ while (xm >> (SP_MBITS + 1 + 3)) {
+ SPXSRSX1();
+ }
+ } else {
+ /* normalize in grs extended single precision */
+ while ((xm >> (SP_MBITS + 3)) == 0) {
+ xm <<= 1;
+ xe--;
+ }
+ }
+ SPNORMRET1(xs, xe, xm, "sp_flong", x);
+}
+
+
+ieee754sp ieee754sp_fulong(u64 u)
+{
+ if ((s64) u < 0)
+ return ieee754sp_add(ieee754sp_1e63(),
+ ieee754sp_flong(u & ~(1ULL << 63)));
+ return ieee754sp_flong(u);
+}
diff --git a/arch/mips/math-emu/sp_frexp.c b/arch/mips/math-emu/sp_frexp.c
new file mode 100644
index 0000000..359c648
--- /dev/null
+++ b/arch/mips/math-emu/sp_frexp.c
@@ -0,0 +1,53 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ * 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 "ieee754sp.h"
+
+/* close to ieeep754sp_logb
+*/
+ieee754sp ieee754sp_frexp(ieee754sp x, int *eptr)
+{
+ COMPXSP;
+ CLEARCX;
+ EXPLODEXSP;
+
+ switch (xc) {
+ case IEEE754_CLASS_SNAN:
+ case IEEE754_CLASS_QNAN:
+ case IEEE754_CLASS_INF:
+ case IEEE754_CLASS_ZERO:
+ *eptr = 0;
+ return x;
+ case IEEE754_CLASS_DNORM:
+ SPDNORMX;
+ break;
+ case IEEE754_CLASS_NORM:
+ break;
+ }
+ *eptr = xe + 1;
+ return buildsp(xs, -1 + SP_EBIAS, xm & ~SP_HIDDEN_BIT);
+}
diff --git a/arch/mips/math-emu/sp_logb.c b/arch/mips/math-emu/sp_logb.c
new file mode 100644
index 0000000..3c33721
--- /dev/null
+++ b/arch/mips/math-emu/sp_logb.c
@@ -0,0 +1,54 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ * 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 "ieee754sp.h"
+
+ieee754sp ieee754sp_logb(ieee754sp x)
+{
+ COMPXSP;
+
+ CLEARCX;
+
+ EXPLODEXSP;
+
+ switch (xc) {
+ case IEEE754_CLASS_SNAN:
+ return ieee754sp_nanxcpt(x, "logb", x);
+ case IEEE754_CLASS_QNAN:
+ return x;
+ case IEEE754_CLASS_INF:
+ return ieee754sp_inf(0);
+ case IEEE754_CLASS_ZERO:
+ return ieee754sp_inf(1);
+ case IEEE754_CLASS_DNORM:
+ SPDNORMX;
+ break;
+ case IEEE754_CLASS_NORM:
+ break;
+ }
+ return ieee754sp_fint(xe);
+}
diff --git a/arch/mips/math-emu/sp_modf.c b/arch/mips/math-emu/sp_modf.c
new file mode 100644
index 0000000..4b1dbac
--- /dev/null
+++ b/arch/mips/math-emu/sp_modf.c
@@ -0,0 +1,80 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ * 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 "ieee754sp.h"
+
+/* modf function is always exact for a finite number
+*/
+ieee754sp ieee754sp_modf(ieee754sp x, ieee754sp * ip)
+{
+ COMPXSP;
+
+ CLEARCX;
+
+ EXPLODEXSP;
+
+ switch (xc) {
+ case IEEE754_CLASS_SNAN:
+ case IEEE754_CLASS_QNAN:
+ case IEEE754_CLASS_INF:
+ case IEEE754_CLASS_ZERO:
+ *ip = x;
+ return x;
+ case IEEE754_CLASS_DNORM:
+ /* far to small */
+ *ip = ieee754sp_zero(xs);
+ return x;
+ case IEEE754_CLASS_NORM:
+ break;
+ }
+ if (xe < 0) {
+ *ip = ieee754sp_zero(xs);
+ return x;
+ }
+ if (xe >= SP_MBITS) {
+ *ip = x;
+ return ieee754sp_zero(xs);
+ }
+ /* generate ipart mantissa by clearing bottom bits
+ */
+ *ip = buildsp(xs, xe + SP_EBIAS,
+ ((xm >> (SP_MBITS - xe)) << (SP_MBITS - xe)) &
+ ~SP_HIDDEN_BIT);
+
+ /* generate fpart mantissa by clearing top bits
+ * and normalizing (must be able to normalize)
+ */
+ xm = (xm << (32 - (SP_MBITS - xe))) >> (32 - (SP_MBITS - xe));
+ if (xm == 0)
+ return ieee754sp_zero(xs);
+
+ while ((xm >> SP_MBITS) == 0) {
+ xm <<= 1;
+ xe--;
+ }
+ return buildsp(xs, xe + SP_EBIAS, xm & ~SP_HIDDEN_BIT);
+}
diff --git a/arch/mips/math-emu/sp_mul.c b/arch/mips/math-emu/sp_mul.c
new file mode 100644
index 0000000..3f070f8
--- /dev/null
+++ b/arch/mips/math-emu/sp_mul.c
@@ -0,0 +1,171 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ * 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 "ieee754sp.h"
+
+ieee754sp ieee754sp_mul(ieee754sp x, ieee754sp y)
+{
+ COMPXSP;
+ COMPYSP;
+
+ EXPLODEXSP;
+ EXPLODEYSP;
+
+ CLEARCX;
+
+ FLUSHXSP;
+ FLUSHYSP;
+
+ switch (CLPAIR(xc, yc)) {
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
+ SETCX(IEEE754_INVALID_OPERATION);
+ return ieee754sp_nanxcpt(ieee754sp_indef(), "mul", x, y);
+
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
+ return y;
+
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
+ return x;
+
+
+ /* Infinity handling */
+
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
+ SETCX(IEEE754_INVALID_OPERATION);
+ return ieee754sp_xcpt(ieee754sp_indef(), "mul", x, y);
+
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
+ return ieee754sp_inf(xs ^ ys);
+
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
+ return ieee754sp_zero(xs ^ ys);
+
+
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
+ SPDNORMX;
+
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
+ SPDNORMY;
+ break;
+
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
+ SPDNORMX;
+ break;
+
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
+ break;
+ }
+ /* rm = xm * ym, re = xe+ye basicly */
+ assert(xm & SP_HIDDEN_BIT);
+ assert(ym & SP_HIDDEN_BIT);
+
+ {
+ int re = xe + ye;
+ int rs = xs ^ ys;
+ unsigned rm;
+
+ /* shunt to top of word */
+ xm <<= 32 - (SP_MBITS + 1);
+ ym <<= 32 - (SP_MBITS + 1);
+
+ /* multiply 32bits xm,ym to give high 32bits rm with stickness
+ */
+ {
+ unsigned short lxm = xm & 0xffff;
+ unsigned short hxm = xm >> 16;
+ unsigned short lym = ym & 0xffff;
+ unsigned short hym = ym >> 16;
+ unsigned lrm;
+ unsigned hrm;
+
+ lrm = lxm * lym; /* 16 * 16 => 32 */
+ hrm = hxm * hym; /* 16 * 16 => 32 */
+
+ {
+ unsigned t = lxm * hym; /* 16 * 16 => 32 */
+ {
+ unsigned at = lrm + (t << 16);
+ hrm += at < lrm;
+ lrm = at;
+ }
+ hrm = hrm + (t >> 16);
+ }
+
+ {
+ unsigned t = hxm * lym; /* 16 * 16 => 32 */
+ {
+ unsigned at = lrm + (t << 16);
+ hrm += at < lrm;
+ lrm = at;
+ }
+ hrm = hrm + (t >> 16);
+ }
+ rm = hrm | (lrm != 0);
+ }
+
+ /*
+ * sticky shift down to normal rounding precision
+ */
+ if ((int) rm < 0) {
+ rm = (rm >> (32 - (SP_MBITS + 1 + 3))) |
+ ((rm << (SP_MBITS + 1 + 3)) != 0);
+ re++;
+ } else {
+ rm = (rm >> (32 - (SP_MBITS + 1 + 3 + 1))) |
+ ((rm << (SP_MBITS + 1 + 3 + 1)) != 0);
+ }
+ assert(rm & (SP_HIDDEN_BIT << 3));
+
+ SPNORMRET2(rs, re, rm, "mul", x, y);
+ }
+}
diff --git a/arch/mips/math-emu/sp_scalb.c b/arch/mips/math-emu/sp_scalb.c
new file mode 100644
index 0000000..44ceb87
--- /dev/null
+++ b/arch/mips/math-emu/sp_scalb.c
@@ -0,0 +1,58 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ * 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 "ieee754sp.h"
+
+ieee754sp ieee754sp_scalb(ieee754sp x, int n)
+{
+ COMPXSP;
+
+ CLEARCX;
+
+ EXPLODEXSP;
+
+ switch (xc) {
+ case IEEE754_CLASS_SNAN:
+ return ieee754sp_nanxcpt(x, "scalb", x, n);
+ case IEEE754_CLASS_QNAN:
+ case IEEE754_CLASS_INF:
+ case IEEE754_CLASS_ZERO:
+ return x;
+ case IEEE754_CLASS_DNORM:
+ SPDNORMX;
+ break;
+ case IEEE754_CLASS_NORM:
+ break;
+ }
+ SPNORMRET2(xs, xe + n, xm << 3, "scalb", x, n);
+}
+
+
+ieee754sp ieee754sp_ldexp(ieee754sp x, int n)
+{
+ return ieee754sp_scalb(x, n);
+}
diff --git a/arch/mips/math-emu/sp_simple.c b/arch/mips/math-emu/sp_simple.c
new file mode 100644
index 0000000..c809830
--- /dev/null
+++ b/arch/mips/math-emu/sp_simple.c
@@ -0,0 +1,84 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ * 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 "ieee754sp.h"
+
+int ieee754sp_finite(ieee754sp x)
+{
+ return SPBEXP(x) != SP_EMAX + 1 + SP_EBIAS;
+}
+
+ieee754sp ieee754sp_copysign(ieee754sp x, ieee754sp y)
+{
+ CLEARCX;
+ SPSIGN(x) = SPSIGN(y);
+ return x;
+}
+
+
+ieee754sp ieee754sp_neg(ieee754sp x)
+{
+ COMPXSP;
+
+ EXPLODEXSP;
+ CLEARCX;
+ FLUSHXSP;
+
+ if (xc == IEEE754_CLASS_SNAN) {
+ SETCX(IEEE754_INVALID_OPERATION);
+ return ieee754sp_nanxcpt(ieee754sp_indef(), "neg");
+ }
+
+ if (ieee754sp_isnan(x)) /* but not infinity */
+ return ieee754sp_nanxcpt(x, "neg", x);
+
+ /* quick fix up */
+ SPSIGN(x) ^= 1;
+ return x;
+}
+
+
+ieee754sp ieee754sp_abs(ieee754sp x)
+{
+ COMPXSP;
+
+ EXPLODEXSP;
+ CLEARCX;
+ FLUSHXSP;
+
+ if (xc == IEEE754_CLASS_SNAN) {
+ SETCX(IEEE754_INVALID_OPERATION);
+ return ieee754sp_nanxcpt(ieee754sp_indef(), "abs");
+ }
+
+ if (ieee754sp_isnan(x)) /* but not infinity */
+ return ieee754sp_nanxcpt(x, "abs", x);
+
+ /* quick fix up */
+ SPSIGN(x) = 0;
+ return x;
+}
diff --git a/arch/mips/math-emu/sp_sqrt.c b/arch/mips/math-emu/sp_sqrt.c
new file mode 100644
index 0000000..8a934b9
--- /dev/null
+++ b/arch/mips/math-emu/sp_sqrt.c
@@ -0,0 +1,117 @@
+/* IEEE754 floating point arithmetic
+ * single precision square root
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ * 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 "ieee754sp.h"
+
+ieee754sp ieee754sp_sqrt(ieee754sp x)
+{
+ int ix, s, q, m, t, i;
+ unsigned int r;
+ COMPXSP;
+
+ /* take care of Inf and NaN */
+
+ EXPLODEXSP;
+ CLEARCX;
+ FLUSHXSP;
+
+ /* x == INF or NAN? */
+ switch (xc) {
+ case IEEE754_CLASS_QNAN:
+ /* sqrt(Nan) = Nan */
+ return ieee754sp_nanxcpt(x, "sqrt");
+ case IEEE754_CLASS_SNAN:
+ SETCX(IEEE754_INVALID_OPERATION);
+ return ieee754sp_nanxcpt(ieee754sp_indef(), "sqrt");
+ case IEEE754_CLASS_ZERO:
+ /* sqrt(0) = 0 */
+ return x;
+ case IEEE754_CLASS_INF:
+ if (xs) {
+ /* sqrt(-Inf) = Nan */
+ SETCX(IEEE754_INVALID_OPERATION);
+ return ieee754sp_nanxcpt(ieee754sp_indef(), "sqrt");
+ }
+ /* sqrt(+Inf) = Inf */
+ return x;
+ case IEEE754_CLASS_DNORM:
+ case IEEE754_CLASS_NORM:
+ if (xs) {
+ /* sqrt(-x) = Nan */
+ SETCX(IEEE754_INVALID_OPERATION);
+ return ieee754sp_nanxcpt(ieee754sp_indef(), "sqrt");
+ }
+ break;
+ }
+
+ ix = x.bits;
+
+ /* normalize x */
+ m = (ix >> 23);
+ if (m == 0) { /* subnormal x */
+ for (i = 0; (ix & 0x00800000) == 0; i++)
+ ix <<= 1;
+ m -= i - 1;
+ }
+ m -= 127; /* unbias exponent */
+ ix = (ix & 0x007fffff) | 0x00800000;
+ if (m & 1) /* odd m, double x to make it even */
+ ix += ix;
+ m >>= 1; /* m = [m/2] */
+
+ /* generate sqrt(x) bit by bit */
+ ix += ix;
+ q = s = 0; /* q = sqrt(x) */
+ r = 0x01000000; /* r = moving bit from right to left */
+
+ while (r != 0) {
+ t = s + r;
+ if (t <= ix) {
+ s = t + r;
+ ix -= t;
+ q += r;
+ }
+ ix += ix;
+ r >>= 1;
+ }
+
+ if (ix != 0) {
+ SETCX(IEEE754_INEXACT);
+ switch (ieee754_csr.rm) {
+ case IEEE754_RP:
+ q += 2;
+ break;
+ case IEEE754_RN:
+ q += (q & 1);
+ break;
+ }
+ }
+ ix = (q >> 1) + 0x3f000000;
+ ix += (m << 23);
+ x.bits = ix;
+ return x;
+}
diff --git a/arch/mips/math-emu/sp_sub.c b/arch/mips/math-emu/sp_sub.c
new file mode 100644
index 0000000..dbb802c
--- /dev/null
+++ b/arch/mips/math-emu/sp_sub.c
@@ -0,0 +1,184 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ * 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 "ieee754sp.h"
+
+ieee754sp ieee754sp_sub(ieee754sp x, ieee754sp y)
+{
+ COMPXSP;
+ COMPYSP;
+
+ EXPLODEXSP;
+ EXPLODEYSP;
+
+ CLEARCX;
+
+ FLUSHXSP;
+ FLUSHYSP;
+
+ switch (CLPAIR(xc, yc)) {
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
+ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
+ SETCX(IEEE754_INVALID_OPERATION);
+ return ieee754sp_nanxcpt(ieee754sp_indef(), "sub", x, y);
+
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
+ return y;
+
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
+ return x;
+
+
+ /* Infinity handling
+ */
+
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
+ if (xs != ys)
+ return x;
+ SETCX(IEEE754_INVALID_OPERATION);
+ return ieee754sp_xcpt(ieee754sp_indef(), "sub", x, y);
+
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
+ return ieee754sp_inf(ys ^ 1);
+
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
+ return x;
+
+ /* Zero handling
+ */
+
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
+ if (xs != ys)
+ return x;
+ else
+ return ieee754sp_zero(ieee754_csr.rm ==
+ IEEE754_RD);
+
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
+ return x;
+
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
+ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
+ /* quick fix up */
+ DPSIGN(y) ^= 1;
+ return y;
+
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
+ SPDNORMX;
+
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
+ SPDNORMY;
+ break;
+
+ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
+ SPDNORMX;
+ break;
+
+ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
+ break;
+ }
+ /* flip sign of y and handle as add */
+ ys ^= 1;
+
+ assert(xm & SP_HIDDEN_BIT);
+ assert(ym & SP_HIDDEN_BIT);
+
+
+ /* provide guard,round and stick bit space */
+ xm <<= 3;
+ ym <<= 3;
+
+ if (xe > ye) {
+ /* have to shift y fraction right to align
+ */
+ int s = xe - ye;
+ SPXSRSYn(s);
+ } else if (ye > xe) {
+ /* have to shift x fraction right to align
+ */
+ int s = ye - xe;
+ SPXSRSXn(s);
+ }
+ assert(xe == ye);
+ assert(xe <= SP_EMAX);
+
+ if (xs == ys) {
+ /* generate 28 bit result of adding two 27 bit numbers
+ */
+ xm = xm + ym;
+ xe = xe;
+ xs = xs;
+
+ if (xm >> (SP_MBITS + 1 + 3)) { /* carry out */
+ SPXSRSX1(); /* shift preserving sticky */
+ }
+ } else {
+ if (xm >= ym) {
+ xm = xm - ym;
+ xe = xe;
+ xs = xs;
+ } else {
+ xm = ym - xm;
+ xe = xe;
+ xs = ys;
+ }
+ if (xm == 0) {
+ if (ieee754_csr.rm == IEEE754_RD)
+ return ieee754sp_zero(1); /* round negative inf. => sign = -1 */
+ else
+ return ieee754sp_zero(0); /* other round modes => sign = 1 */
+ }
+ /* normalize to rounding precision
+ */
+ while ((xm >> (SP_MBITS + 3)) == 0) {
+ xm <<= 1;
+ xe--;
+ }
+ }
+ SPNORMRET2(xs, xe, xm, "sub", x, y);
+}
diff --git a/arch/mips/math-emu/sp_tint.c b/arch/mips/math-emu/sp_tint.c
new file mode 100644
index 0000000..1d73d2a
--- /dev/null
+++ b/arch/mips/math-emu/sp_tint.c
@@ -0,0 +1,128 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ * 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 <linux/kernel.h>
+#include "ieee754sp.h"
+
+int ieee754sp_tint(ieee754sp x)
+{
+ COMPXSP;
+
+ CLEARCX;
+
+ EXPLODEXSP;
+ FLUSHXSP;
+
+ switch (xc) {
+ case IEEE754_CLASS_SNAN:
+ case IEEE754_CLASS_QNAN:
+ case IEEE754_CLASS_INF:
+ SETCX(IEEE754_INVALID_OPERATION);
+ return ieee754si_xcpt(ieee754si_indef(), "sp_tint", x);
+ case IEEE754_CLASS_ZERO:
+ return 0;
+ case IEEE754_CLASS_DNORM:
+ case IEEE754_CLASS_NORM:
+ break;
+ }
+ if (xe >= 31) {
+ /* look for valid corner case */
+ if (xe == 31 && xs && xm == SP_HIDDEN_BIT)
+ return -0x80000000;
+ /* Set invalid. We will only use overflow for floating
+ point overflow */
+ SETCX(IEEE754_INVALID_OPERATION);
+ return ieee754si_xcpt(ieee754si_indef(), "sp_tint", x);
+ }
+ /* oh gawd */
+ if (xe > SP_MBITS) {
+ xm <<= xe - SP_MBITS;
+ } else {
+ u32 residue;
+ int round;
+ int sticky;
+ int odd;
+
+ if (xe < -1) {
+ residue = xm;
+ round = 0;
+ sticky = residue != 0;
+ xm = 0;
+ }
+ else {
+ /* Shifting a u32 32 times does not work,
+ * so we do it in two steps. Be aware that xe
+ * may be -1 */
+ residue = xm << (xe + 1);
+ residue <<= 31 - SP_MBITS;
+ round = (residue >> 31) != 0;
+ sticky = (residue << 1) != 0;
+ xm >>= SP_MBITS - xe;
+ }
+ odd = (xm & 0x1) != 0x0;
+ switch (ieee754_csr.rm) {
+ case IEEE754_RN:
+ if (round && (sticky || odd))
+ xm++;
+ break;
+ case IEEE754_RZ:
+ break;
+ case IEEE754_RU: /* toward +Infinity */
+ if ((round || sticky) && !xs)
+ xm++;
+ break;
+ case IEEE754_RD: /* toward -Infinity */
+ if ((round || sticky) && xs)
+ xm++;
+ break;
+ }
+ if ((xm >> 31) != 0) {
+ /* This can happen after rounding */
+ SETCX(IEEE754_INVALID_OPERATION);
+ return ieee754si_xcpt(ieee754si_indef(), "sp_tint", x);
+ }
+ if (round || sticky)
+ SETCX(IEEE754_INEXACT);
+ }
+ if (xs)
+ return -xm;
+ else
+ return xm;
+}
+
+
+unsigned int ieee754sp_tuns(ieee754sp x)
+{
+ ieee754sp hb = ieee754sp_1e31();
+
+ /* what if x < 0 ?? */
+ if (ieee754sp_lt(x, hb))
+ return (unsigned) ieee754sp_tint(x);
+
+ return (unsigned) ieee754sp_tint(ieee754sp_sub(x, hb)) |
+ ((unsigned) 1 << 31);
+}
diff --git a/arch/mips/math-emu/sp_tlong.c b/arch/mips/math-emu/sp_tlong.c
new file mode 100644
index 0000000..4be21aa
--- /dev/null
+++ b/arch/mips/math-emu/sp_tlong.c
@@ -0,0 +1,123 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ * 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 "ieee754sp.h"
+
+s64 ieee754sp_tlong(ieee754sp x)
+{
+ COMPXDP; /* <-- need 64-bit mantissa tmp */
+
+ CLEARCX;
+
+ EXPLODEXSP;
+ FLUSHXSP;
+
+ switch (xc) {
+ case IEEE754_CLASS_SNAN:
+ case IEEE754_CLASS_QNAN:
+ case IEEE754_CLASS_INF:
+ SETCX(IEEE754_INVALID_OPERATION);
+ return ieee754di_xcpt(ieee754di_indef(), "sp_tlong", x);
+ case IEEE754_CLASS_ZERO:
+ return 0;
+ case IEEE754_CLASS_DNORM:
+ case IEEE754_CLASS_NORM:
+ break;
+ }
+ if (xe >= 63) {
+ /* look for valid corner case */
+ if (xe == 63 && xs && xm == SP_HIDDEN_BIT)
+ return -0x8000000000000000LL;
+ /* Set invalid. We will only use overflow for floating
+ point overflow */
+ SETCX(IEEE754_INVALID_OPERATION);
+ return ieee754di_xcpt(ieee754di_indef(), "sp_tlong", x);
+ }
+ /* oh gawd */
+ if (xe > SP_MBITS) {
+ xm <<= xe - SP_MBITS;
+ } else if (xe < SP_MBITS) {
+ u32 residue;
+ int round;
+ int sticky;
+ int odd;
+
+ if (xe < -1) {
+ residue = xm;
+ round = 0;
+ sticky = residue != 0;
+ xm = 0;
+ }
+ else {
+ residue = xm << (32 - SP_MBITS + xe);
+ round = (residue >> 31) != 0;
+ sticky = (residue << 1) != 0;
+ xm >>= SP_MBITS - xe;
+ }
+ odd = (xm & 0x1) != 0x0;
+ switch (ieee754_csr.rm) {
+ case IEEE754_RN:
+ if (round && (sticky || odd))
+ xm++;
+ break;
+ case IEEE754_RZ:
+ break;
+ case IEEE754_RU: /* toward +Infinity */
+ if ((round || sticky) && !xs)
+ xm++;
+ break;
+ case IEEE754_RD: /* toward -Infinity */
+ if ((round || sticky) && xs)
+ xm++;
+ break;
+ }
+ if ((xm >> 63) != 0) {
+ /* This can happen after rounding */
+ SETCX(IEEE754_INVALID_OPERATION);
+ return ieee754di_xcpt(ieee754di_indef(), "sp_tlong", x);
+ }
+ if (round || sticky)
+ SETCX(IEEE754_INEXACT);
+ }
+ if (xs)
+ return -xm;
+ else
+ return xm;
+}
+
+
+u64 ieee754sp_tulong(ieee754sp x)
+{
+ ieee754sp hb = ieee754sp_1e63();
+
+ /* what if x < 0 ?? */
+ if (ieee754sp_lt(x, hb))
+ return (u64) ieee754sp_tlong(x);
+
+ return (u64) ieee754sp_tlong(ieee754sp_sub(x, hb)) |
+ (1ULL << 63);
+}
diff --git a/arch/mips/mips-boards/atlas/Makefile b/arch/mips/mips-boards/atlas/Makefile
new file mode 100644
index 0000000..d8dab75
--- /dev/null
+++ b/arch/mips/mips-boards/atlas/Makefile
@@ -0,0 +1,20 @@
+#
+# Carsten Langgaard, carstenl@mips.com
+# Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
+#
+# This program is free software; you can distribute it and/or modify it
+# under the terms of the GNU General Public License (Version 2) as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+#
+
+obj-y := atlas_int.o atlas_setup.o
+obj-$(CONFIG_KGDB) += atlas_gdb.o
diff --git a/arch/mips/mips-boards/atlas/atlas_gdb.c b/arch/mips/mips-boards/atlas/atlas_gdb.c
new file mode 100644
index 0000000..fb65280
--- /dev/null
+++ b/arch/mips/mips-boards/atlas/atlas_gdb.c
@@ -0,0 +1,97 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * This is the interface to the remote debugger stub.
+ */
+#include <asm/io.h>
+#include <asm/mips-boards/atlas.h>
+#include <asm/mips-boards/saa9730_uart.h>
+
+#define INB(a) inb((unsigned long)a)
+#define OUTB(x,a) outb(x,(unsigned long)a)
+
+/*
+ * This is the interface to the remote debugger stub
+ * if the Philips part is used for the debug port,
+ * called from the platform setup code.
+ */
+void *saa9730_base = (void *)ATLAS_SAA9730_REG;
+
+static int saa9730_kgdb_active = 0;
+
+#define SAA9730_BAUDCLOCK(baud) (((ATLAS_SAA9730_BAUDCLOCK/(baud))/16)-1)
+
+int saa9730_kgdb_hook(int speed)
+{
+ int baudclock;
+ t_uart_saa9730_regmap *kgdb_uart = (t_uart_saa9730_regmap *)(saa9730_base + SAA9730_UART_REGS_ADDR);
+
+ /*
+ * Clear all interrupts
+ */
+ (void) INB(&kgdb_uart->Lsr);
+ (void) INB(&kgdb_uart->Msr);
+ (void) INB(&kgdb_uart->Thr_Rbr);
+ (void) INB(&kgdb_uart->Iir_Fcr);
+
+ /*
+ * Now, initialize the UART
+ */
+ /* 8 data bits, one stop bit, no parity */
+ OUTB(SAA9730_LCR_DATA8, &kgdb_uart->Lcr);
+
+ baudclock = SAA9730_BAUDCLOCK(speed);
+
+ OUTB((baudclock >> 16) & 0xff, &kgdb_uart->BaudDivMsb);
+ OUTB( baudclock & 0xff, &kgdb_uart->BaudDivLsb);
+
+ /* Set RTS/DTR active */
+ OUTB(SAA9730_MCR_DTR | SAA9730_MCR_RTS, &kgdb_uart->Mcr);
+ saa9730_kgdb_active = 1;
+
+ return speed;
+}
+
+int saa9730_putDebugChar(char c)
+{
+ t_uart_saa9730_regmap *kgdb_uart = (t_uart_saa9730_regmap *)(saa9730_base + SAA9730_UART_REGS_ADDR);
+
+ if (!saa9730_kgdb_active) { /* need to init device first */
+ return 0;
+ }
+
+ while (!(INB(&kgdb_uart->Lsr) & SAA9730_LSR_THRE))
+ ;
+ OUTB(c, &kgdb_uart->Thr_Rbr);
+
+ return 1;
+}
+
+char saa9730_getDebugChar(void)
+{
+ t_uart_saa9730_regmap *kgdb_uart = (t_uart_saa9730_regmap *)(saa9730_base + SAA9730_UART_REGS_ADDR);
+ char c;
+
+ if (!saa9730_kgdb_active) { /* need to init device first */
+ return 0;
+ }
+ while (!(INB(&kgdb_uart->Lsr) & SAA9730_LSR_DR))
+ ;
+
+ c = INB(&kgdb_uart->Thr_Rbr);
+ return(c);
+}
diff --git a/arch/mips/mips-boards/atlas/atlas_int.c b/arch/mips/mips-boards/atlas/atlas_int.c
new file mode 100644
index 0000000..8f1d875
--- /dev/null
+++ b/arch/mips/mips-boards/atlas/atlas_int.c
@@ -0,0 +1,142 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
+ *
+ * ########################################################################
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ *
+ * Routines for generic manipulation of the interrupts found on the MIPS
+ * Atlas board.
+ *
+ */
+#include <linux/compiler.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/kernel_stat.h>
+
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/mips-boards/atlas.h>
+#include <asm/mips-boards/atlasint.h>
+#include <asm/gdb-stub.h>
+
+
+static struct atlas_ictrl_regs *atlas_hw0_icregs;
+
+extern asmlinkage void mipsIRQ(void);
+
+#if 0
+#define DEBUG_INT(x...) printk(x)
+#else
+#define DEBUG_INT(x...)
+#endif
+
+void disable_atlas_irq(unsigned int irq_nr)
+{
+ atlas_hw0_icregs->intrsten = (1 << (irq_nr-ATLASINT_BASE));
+ iob();
+}
+
+void enable_atlas_irq(unsigned int irq_nr)
+{
+ atlas_hw0_icregs->intseten = (1 << (irq_nr-ATLASINT_BASE));
+ iob();
+}
+
+static unsigned int startup_atlas_irq(unsigned int irq)
+{
+ enable_atlas_irq(irq);
+ return 0; /* never anything pending */
+}
+
+#define shutdown_atlas_irq disable_atlas_irq
+
+#define mask_and_ack_atlas_irq disable_atlas_irq
+
+static void end_atlas_irq(unsigned int irq)
+{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+ enable_atlas_irq(irq);
+}
+
+static struct hw_interrupt_type atlas_irq_type = {
+ "Atlas",
+ startup_atlas_irq,
+ shutdown_atlas_irq,
+ enable_atlas_irq,
+ disable_atlas_irq,
+ mask_and_ack_atlas_irq,
+ end_atlas_irq,
+ NULL
+};
+
+static inline int ls1bit32(unsigned int x)
+{
+ int b = 31, s;
+
+ s = 16; if (x << 16 == 0) s = 0; b -= s; x <<= s;
+ s = 8; if (x << 8 == 0) s = 0; b -= s; x <<= s;
+ s = 4; if (x << 4 == 0) s = 0; b -= s; x <<= s;
+ s = 2; if (x << 2 == 0) s = 0; b -= s; x <<= s;
+ s = 1; if (x << 1 == 0) s = 0; b -= s;
+
+ return b;
+}
+
+void atlas_hw0_irqdispatch(struct pt_regs *regs)
+{
+ unsigned long int_status;
+ int irq;
+
+ int_status = atlas_hw0_icregs->intstatus;
+
+ /* if int_status == 0, then the interrupt has already been cleared */
+ if (unlikely(int_status == 0))
+ return;
+
+ irq = ATLASINT_BASE + ls1bit32(int_status);
+
+ DEBUG_INT("atlas_hw0_irqdispatch: irq=%d\n", irq);
+
+ do_IRQ(irq, regs);
+}
+
+void __init arch_init_irq(void)
+{
+ int i;
+
+ atlas_hw0_icregs = (struct atlas_ictrl_regs *)ioremap (ATLAS_ICTRL_REGS_BASE, sizeof(struct atlas_ictrl_regs *));
+
+ /*
+ * Mask out all interrupt by writing "1" to all bit position in
+ * the interrupt reset reg.
+ */
+ atlas_hw0_icregs->intrsten = 0xffffffff;
+
+ /* Now safe to set the exception vector. */
+ set_except_vector(0, mipsIRQ);
+
+ for (i = ATLASINT_BASE; i <= ATLASINT_END; i++) {
+ irq_desc[i].status = IRQ_DISABLED;
+ irq_desc[i].action = 0;
+ irq_desc[i].depth = 1;
+ irq_desc[i].handler = &atlas_irq_type;
+ spin_lock_init(&irq_desc[i].lock);
+ }
+}
diff --git a/arch/mips/mips-boards/atlas/atlas_setup.c b/arch/mips/mips-boards/atlas/atlas_setup.c
new file mode 100644
index 0000000..0a1dd9b
--- /dev/null
+++ b/arch/mips/mips-boards/atlas/atlas_setup.c
@@ -0,0 +1,95 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/tty.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+
+#include <asm/cpu.h>
+#include <asm/bootinfo.h>
+#include <asm/irq.h>
+#include <asm/mips-boards/generic.h>
+#include <asm/mips-boards/prom.h>
+#include <asm/mips-boards/atlas.h>
+#include <asm/mips-boards/atlasint.h>
+#include <asm/time.h>
+#include <asm/traps.h>
+
+extern void mips_reboot_setup(void);
+extern void mips_time_init(void);
+extern void mips_timer_setup(struct irqaction *irq);
+extern unsigned long mips_rtc_get_time(void);
+
+#ifdef CONFIG_KGDB
+extern void kgdb_config(void);
+#endif
+
+static void __init serial_init(void);
+
+const char *get_system_type(void)
+{
+ return "MIPS Atlas";
+}
+
+static int __init atlas_setup(void)
+{
+ ioport_resource.end = 0x7fffffff;
+
+ serial_init ();
+
+#ifdef CONFIG_KGDB
+ kgdb_config();
+#endif
+ mips_reboot_setup();
+
+ board_time_init = mips_time_init;
+ board_timer_setup = mips_timer_setup;
+ rtc_get_time = mips_rtc_get_time;
+
+ return 0;
+}
+
+early_initcall(atlas_setup);
+
+static void __init serial_init(void)
+{
+#ifdef CONFIG_SERIAL_8250
+ struct uart_port s;
+
+ memset(&s, 0, sizeof(s));
+
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+ s.iobase = ATLAS_UART_REGS_BASE;
+#else
+ s.iobase = ATLAS_UART_REGS_BASE+3;
+#endif
+ s.irq = ATLASINT_UART;
+ s.uartclk = ATLAS_BASE_BAUD * 16;
+ s.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ;
+ s.iotype = SERIAL_IO_PORT;
+ s.regshift = 3;
+
+ if (early_serial_setup(&s) != 0) {
+ printk(KERN_ERR "Serial setup failed!\n");
+ }
+#endif
+}
diff --git a/arch/mips/mips-boards/generic/Makefile b/arch/mips/mips-boards/generic/Makefile
new file mode 100644
index 0000000..b21bc68
--- /dev/null
+++ b/arch/mips/mips-boards/generic/Makefile
@@ -0,0 +1,26 @@
+#
+# Carsten Langgaard, carstenl@mips.com
+# Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
+#
+# This program is free software; you can distribute it and/or modify it
+# under the terms of the GNU General Public License (Version 2) as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+#
+# Makefile for the MIPS boards generic routines under Linux.
+#
+
+obj-y := mipsIRQ.o reset.o display.o init.o memory.o \
+ printf.o cmdline.o time.o
+obj-$(CONFIG_PCI) += pci.o
+obj-$(CONFIG_KGDB) += gdb_hook.o
+
+EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/mips-boards/generic/cmdline.c b/arch/mips/mips-boards/generic/cmdline.c
new file mode 100644
index 0000000..1871c30
--- /dev/null
+++ b/arch/mips/mips-boards/generic/cmdline.c
@@ -0,0 +1,59 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Kernel command line creation using the prom monitor (YAMON) argc/argv.
+ */
+#include <linux/init.h>
+#include <linux/string.h>
+
+#include <asm/bootinfo.h>
+
+extern int prom_argc;
+extern int *_prom_argv;
+
+/*
+ * YAMON (32-bit PROM) pass arguments and environment as 32-bit pointer.
+ * This macro take care of sign extension.
+ */
+#define prom_argv(index) ((char *)(long)_prom_argv[(index)])
+
+char * __init prom_getcmdline(void)
+{
+ return &(arcs_cmdline[0]);
+}
+
+
+void __init prom_init_cmdline(void)
+{
+ char *cp;
+ int actr;
+
+ actr = 1; /* Always ignore argv[0] */
+
+ cp = &(arcs_cmdline[0]);
+ while(actr < prom_argc) {
+ strcpy(cp, prom_argv(actr));
+ cp += strlen(prom_argv(actr));
+ *cp++ = ' ';
+ actr++;
+ }
+ if (cp != &(arcs_cmdline[0])) {
+ /* get rid of trailing space */
+ --cp;
+ *cp = '\0';
+ }
+}
diff --git a/arch/mips/mips-boards/generic/display.c b/arch/mips/mips-boards/generic/display.c
new file mode 100644
index 0000000..f653946
--- /dev/null
+++ b/arch/mips/mips-boards/generic/display.c
@@ -0,0 +1,39 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Display routines for display messages in MIPS boards ascii display.
+ */
+
+#include <linux/compiler.h>
+#include <asm/io.h>
+#include <asm/mips-boards/generic.h>
+
+void mips_display_message(const char *str)
+{
+ static volatile unsigned int *display = NULL;
+ int i;
+
+ if (unlikely(display == NULL))
+ display = (volatile unsigned int *)ioremap(ASCII_DISPLAY_POS_BASE, 16*sizeof(int));
+
+ for (i = 0; i <= 14; i=i+2) {
+ if (*str)
+ display[i] = *str++;
+ else
+ display[i] = ' ';
+ }
+}
diff --git a/arch/mips/mips-boards/generic/gdb_hook.c b/arch/mips/mips-boards/generic/gdb_hook.c
new file mode 100644
index 0000000..91a2ccb
--- /dev/null
+++ b/arch/mips/mips-boards/generic/gdb_hook.c
@@ -0,0 +1,133 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * This is the interface to the remote debugger stub.
+ */
+#include <linux/types.h>
+#include <linux/serial.h>
+#include <linux/serialP.h>
+#include <linux/serial_reg.h>
+
+#include <asm/serial.h>
+#include <asm/io.h>
+
+static struct serial_state rs_table[RS_TABLE_SIZE] = {
+ SERIAL_PORT_DFNS /* Defined in serial.h */
+};
+
+static struct async_struct kdb_port_info = {0};
+
+int (*generic_putDebugChar)(char);
+char (*generic_getDebugChar)(void);
+
+static __inline__ unsigned int serial_in(struct async_struct *info, int offset)
+{
+ return inb(info->port + offset);
+}
+
+static __inline__ void serial_out(struct async_struct *info, int offset,
+ int value)
+{
+ outb(value, info->port+offset);
+}
+
+int rs_kgdb_hook(int tty_no, int speed) {
+ int t;
+ struct serial_state *ser = &rs_table[tty_no];
+
+ kdb_port_info.state = ser;
+ kdb_port_info.magic = SERIAL_MAGIC;
+ kdb_port_info.port = ser->port;
+ kdb_port_info.flags = ser->flags;
+
+ /*
+ * Clear all interrupts
+ */
+ serial_in(&kdb_port_info, UART_LSR);
+ serial_in(&kdb_port_info, UART_RX);
+ serial_in(&kdb_port_info, UART_IIR);
+ serial_in(&kdb_port_info, UART_MSR);
+
+ /*
+ * Now, initialize the UART
+ */
+ serial_out(&kdb_port_info, UART_LCR, UART_LCR_WLEN8); /* reset DLAB */
+ if (kdb_port_info.flags & ASYNC_FOURPORT) {
+ kdb_port_info.MCR = UART_MCR_DTR | UART_MCR_RTS;
+ t = UART_MCR_DTR | UART_MCR_OUT1;
+ } else {
+ kdb_port_info.MCR
+ = UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2;
+ t = UART_MCR_DTR | UART_MCR_RTS;
+ }
+
+ kdb_port_info.MCR = t; /* no interrupts, please */
+ serial_out(&kdb_port_info, UART_MCR, kdb_port_info.MCR);
+
+ /*
+ * and set the speed of the serial port
+ */
+ if (speed == 0)
+ speed = 9600;
+
+ t = kdb_port_info.state->baud_base / speed;
+ /* set DLAB */
+ serial_out(&kdb_port_info, UART_LCR, UART_LCR_WLEN8 | UART_LCR_DLAB);
+ serial_out(&kdb_port_info, UART_DLL, t & 0xff);/* LS of divisor */
+ serial_out(&kdb_port_info, UART_DLM, t >> 8); /* MS of divisor */
+ /* reset DLAB */
+ serial_out(&kdb_port_info, UART_LCR, UART_LCR_WLEN8);
+
+ return speed;
+}
+
+int putDebugChar(char c)
+{
+ return generic_putDebugChar(c);
+}
+
+char getDebugChar(void)
+{
+ return generic_getDebugChar();
+}
+
+int rs_putDebugChar(char c)
+{
+
+ if (!kdb_port_info.state) { /* need to init device first */
+ return 0;
+ }
+
+ while ((serial_in(&kdb_port_info, UART_LSR) & UART_LSR_THRE) == 0)
+ ;
+
+ serial_out(&kdb_port_info, UART_TX, c);
+
+ return 1;
+}
+
+char rs_getDebugChar(void)
+{
+ if (!kdb_port_info.state) { /* need to init device first */
+ return 0;
+ }
+
+ while (!(serial_in(&kdb_port_info, UART_LSR) & 1))
+ ;
+
+ return serial_in(&kdb_port_info, UART_RX);
+}
diff --git a/arch/mips/mips-boards/generic/init.c b/arch/mips/mips-boards/generic/init.c
new file mode 100644
index 0000000..31caf06
--- /dev/null
+++ b/arch/mips/mips-boards/generic/init.c
@@ -0,0 +1,343 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * PROM library initialisation code.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+
+#include <asm/io.h>
+#include <asm/bootinfo.h>
+#include <asm/mips-boards/prom.h>
+#include <asm/mips-boards/generic.h>
+#ifdef CONFIG_MIPS_GT64120
+#include <asm/gt64120.h>
+#endif
+#include <asm/mips-boards/msc01_pci.h>
+#include <asm/mips-boards/bonito64.h>
+#ifdef CONFIG_MIPS_MALTA
+#include <asm/mips-boards/malta.h>
+#endif
+
+#ifdef CONFIG_KGDB
+extern int rs_kgdb_hook(int, int);
+extern int rs_putDebugChar(char);
+extern char rs_getDebugChar(void);
+extern int saa9730_kgdb_hook(int);
+extern int saa9730_putDebugChar(char);
+extern char saa9730_getDebugChar(void);
+#endif
+
+int prom_argc;
+int *_prom_argv, *_prom_envp;
+
+/*
+ * YAMON (32-bit PROM) pass arguments and environment as 32-bit pointer.
+ * This macro take care of sign extension, if running in 64-bit mode.
+ */
+#define prom_envp(index) ((char *)(long)_prom_envp[(index)])
+
+int init_debug = 0;
+
+unsigned int mips_revision_corid;
+
+/* Bonito64 system controller register base. */
+unsigned long _pcictrl_bonito;
+unsigned long _pcictrl_bonito_pcicfg;
+
+/* GT64120 system controller register base */
+unsigned long _pcictrl_gt64120;
+
+/* MIPS System controller register base */
+unsigned long _pcictrl_msc;
+
+char *prom_getenv(char *envname)
+{
+ /*
+ * Return a pointer to the given environment variable.
+ * In 64-bit mode: we're using 64-bit pointers, but all pointers
+ * in the PROM structures are only 32-bit, so we need some
+ * workarounds, if we are running in 64-bit mode.
+ */
+ int i, index=0;
+
+ i = strlen(envname);
+
+ while (prom_envp(index)) {
+ if(strncmp(envname, prom_envp(index), i) == 0) {
+ return(prom_envp(index+1));
+ }
+ index += 2;
+ }
+
+ return NULL;
+}
+
+static inline unsigned char str2hexnum(unsigned char c)
+{
+ if (c >= '0' && c <= '9')
+ return c - '0';
+ if (c >= 'a' && c <= 'f')
+ return c - 'a' + 10;
+ return 0; /* foo */
+}
+
+static inline void str2eaddr(unsigned char *ea, unsigned char *str)
+{
+ int i;
+
+ for (i = 0; i < 6; i++) {
+ unsigned char num;
+
+ if((*str == '.') || (*str == ':'))
+ str++;
+ num = str2hexnum(*str++) << 4;
+ num |= (str2hexnum(*str++));
+ ea[i] = num;
+ }
+}
+
+int get_ethernet_addr(char *ethernet_addr)
+{
+ char *ethaddr_str;
+
+ ethaddr_str = prom_getenv("ethaddr");
+ if (!ethaddr_str) {
+ printk("ethaddr not set in boot prom\n");
+ return -1;
+ }
+ str2eaddr(ethernet_addr, ethaddr_str);
+
+ if (init_debug > 1) {
+ int i;
+ printk("get_ethernet_addr: ");
+ for (i=0; i<5; i++)
+ printk("%02x:", (unsigned char)*(ethernet_addr+i));
+ printk("%02x\n", *(ethernet_addr+i));
+ }
+
+ return 0;
+}
+
+#ifdef CONFIG_SERIAL_8250_CONSOLE
+static void __init console_config(void)
+{
+ char console_string[40];
+ int baud = 0;
+ char parity = '\0', bits = '\0', flow = '\0';
+ char *s;
+
+ if ((strstr(prom_getcmdline(), "console=ttyS")) == NULL) {
+ s = prom_getenv("modetty0");
+ if (s) {
+ while (*s >= '0' && *s <= '9')
+ baud = baud*10 + *s++ - '0';
+ if (*s == ',') s++;
+ if (*s) parity = *s++;
+ if (*s == ',') s++;
+ if (*s) bits = *s++;
+ if (*s == ',') s++;
+ if (*s == 'h') flow = 'r';
+ }
+ if (baud == 0)
+ baud = 38400;
+ if (parity != 'n' && parity != 'o' && parity != 'e')
+ parity = 'n';
+ if (bits != '7' && bits != '8')
+ bits = '8';
+ if (flow == '\0')
+ flow = 'r';
+ sprintf (console_string, " console=ttyS0,%d%c%c%c", baud, parity, bits, flow);
+ strcat (prom_getcmdline(), console_string);
+ prom_printf("Config serial console:%s\n", console_string);
+ }
+}
+#endif
+
+#ifdef CONFIG_KGDB
+void __init kgdb_config (void)
+{
+ extern int (*generic_putDebugChar)(char);
+ extern char (*generic_getDebugChar)(void);
+ char *argptr;
+ int line, speed;
+
+ argptr = prom_getcmdline();
+ if ((argptr = strstr(argptr, "kgdb=ttyS")) != NULL) {
+ argptr += strlen("kgdb=ttyS");
+ if (*argptr != '0' && *argptr != '1')
+ printk("KGDB: Unknown serial line /dev/ttyS%c, "
+ "falling back to /dev/ttyS1\n", *argptr);
+ line = *argptr == '0' ? 0 : 1;
+ printk("KGDB: Using serial line /dev/ttyS%d for session\n", line);
+
+ speed = 0;
+ if (*++argptr == ',')
+ {
+ int c;
+ while ((c = *++argptr) && ('0' <= c && c <= '9'))
+ speed = speed * 10 + c - '0';
+ }
+#ifdef CONFIG_MIPS_ATLAS
+ if (line == 1) {
+ speed = saa9730_kgdb_hook(speed);
+ generic_putDebugChar = saa9730_putDebugChar;
+ generic_getDebugChar = saa9730_getDebugChar;
+ }
+ else
+#endif
+ {
+ speed = rs_kgdb_hook(line, speed);
+ generic_putDebugChar = rs_putDebugChar;
+ generic_getDebugChar = rs_getDebugChar;
+ }
+
+ prom_printf("KGDB: Using serial line /dev/ttyS%d at %d for session, "
+ "please connect your debugger\n", line ? 1 : 0, speed);
+
+ {
+ char *s;
+ for (s = "Please connect GDB to this port\r\n"; *s; )
+ generic_putDebugChar (*s++);
+ }
+
+ kgdb_enabled = 1;
+ /* Breakpoint is invoked after interrupts are initialised */
+ }
+}
+#endif
+
+void __init prom_init(void)
+{
+ prom_argc = fw_arg0;
+ _prom_argv = (int *) fw_arg1;
+ _prom_envp = (int *) fw_arg2;
+
+ mips_display_message("LINUX");
+
+#ifdef CONFIG_MIPS_SEAD
+ set_io_port_base(KSEG1);
+#else
+ /*
+ * early setup of _pcictrl_bonito so that we can determine
+ * the system controller on a CORE_EMUL board
+ */
+ _pcictrl_bonito = (unsigned long)ioremap(BONITO_REG_BASE, BONITO_REG_SIZE);
+
+ mips_revision_corid = MIPS_REVISION_CORID;
+
+ if (mips_revision_corid == MIPS_REVISION_CORID_CORE_EMUL) {
+ if (BONITO_PCIDID == 0x0001df53 ||
+ BONITO_PCIDID == 0x0003df53)
+ mips_revision_corid = MIPS_REVISION_CORID_CORE_EMUL_BON;
+ else
+ mips_revision_corid = MIPS_REVISION_CORID_CORE_EMUL_MSC;
+ }
+ switch(mips_revision_corid) {
+ case MIPS_REVISION_CORID_QED_RM5261:
+ case MIPS_REVISION_CORID_CORE_LV:
+ case MIPS_REVISION_CORID_CORE_FPGA:
+ case MIPS_REVISION_CORID_CORE_FPGAR2:
+ /*
+ * Setup the North bridge to do Master byte-lane swapping
+ * when running in bigendian.
+ */
+ _pcictrl_gt64120 = (unsigned long)ioremap(MIPS_GT_BASE, 0x2000);
+
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+ GT_WRITE(GT_PCI0_CMD_OFS, GT_PCI0_CMD_MBYTESWAP_BIT |
+ GT_PCI0_CMD_SBYTESWAP_BIT);
+#else
+ GT_WRITE(GT_PCI0_CMD_OFS, 0);
+#endif
+
+#ifdef CONFIG_MIPS_MALTA
+ set_io_port_base(MALTA_GT_PORT_BASE);
+#else
+ set_io_port_base((unsigned long)ioremap(0, 0x20000000));
+#endif
+ break;
+
+ case MIPS_REVISION_CORID_CORE_EMUL_BON:
+ case MIPS_REVISION_CORID_BONITO64:
+ case MIPS_REVISION_CORID_CORE_20K:
+ _pcictrl_bonito_pcicfg = (unsigned long)ioremap(BONITO_PCICFG_BASE, BONITO_PCICFG_SIZE);
+
+ /*
+ * Disable Bonito IOBC.
+ */
+ BONITO_PCIMEMBASECFG = BONITO_PCIMEMBASECFG &
+ ~(BONITO_PCIMEMBASECFG_MEMBASE0_CACHED |
+ BONITO_PCIMEMBASECFG_MEMBASE1_CACHED);
+
+ /*
+ * Setup the North bridge to do Master byte-lane swapping
+ * when running in bigendian.
+ */
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+ BONITO_BONGENCFG = BONITO_BONGENCFG &
+ ~(BONITO_BONGENCFG_MSTRBYTESWAP |
+ BONITO_BONGENCFG_BYTESWAP);
+#else
+ BONITO_BONGENCFG = BONITO_BONGENCFG |
+ BONITO_BONGENCFG_MSTRBYTESWAP |
+ BONITO_BONGENCFG_BYTESWAP;
+#endif
+
+#ifdef CONFIG_MIPS_MALTA
+ set_io_port_base(MALTA_BONITO_PORT_BASE);
+#else
+ set_io_port_base((unsigned long)ioremap(0, 0x20000000));
+#endif
+ break;
+
+ case MIPS_REVISION_CORID_CORE_MSC:
+ case MIPS_REVISION_CORID_CORE_FPGA2:
+ case MIPS_REVISION_CORID_CORE_EMUL_MSC:
+ _pcictrl_msc = (unsigned long)ioremap(MIPS_MSC01_PCI_REG_BASE, 0x2000);
+
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+ MSC_WRITE(MSC01_PCI_SWAP, MSC01_PCI_SWAP_NOSWAP);
+#else
+ MSC_WRITE(MSC01_PCI_SWAP,
+ MSC01_PCI_SWAP_BYTESWAP << MSC01_PCI_SWAP_IO_SHF |
+ MSC01_PCI_SWAP_BYTESWAP << MSC01_PCI_SWAP_MEM_SHF |
+ MSC01_PCI_SWAP_BYTESWAP << MSC01_PCI_SWAP_BAR0_SHF);
+#endif
+
+#ifdef CONFIG_MIPS_MALTA
+ set_io_port_base(MALTA_MSC_PORT_BASE);
+#else
+ set_io_port_base((unsigned long)ioremap(0, 0x20000000));
+#endif
+ break;
+
+ default:
+ /* Unknown Core card */
+ mips_display_message("CC Error");
+ while(1); /* We die here... */
+ }
+#endif
+ prom_printf("\nLINUX started...\n");
+ prom_init_cmdline();
+ prom_meminit();
+#ifdef CONFIG_SERIAL_8250_CONSOLE
+ console_config();
+#endif
+}
diff --git a/arch/mips/mips-boards/generic/memory.c b/arch/mips/mips-boards/generic/memory.c
new file mode 100644
index 0000000..5ae2b43
--- /dev/null
+++ b/arch/mips/mips-boards/generic/memory.c
@@ -0,0 +1,173 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * PROM library functions for acquiring/using memory descriptors given to
+ * us from the YAMON.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/bootmem.h>
+
+#include <asm/bootinfo.h>
+#include <asm/page.h>
+
+#include <asm/mips-boards/prom.h>
+
+/*#define DEBUG*/
+
+enum yamon_memtypes {
+ yamon_dontuse,
+ yamon_prom,
+ yamon_free,
+};
+struct prom_pmemblock mdesc[PROM_MAX_PMEMBLOCKS];
+
+#ifdef DEBUG
+static char *mtypes[3] = {
+ "Dont use memory",
+ "YAMON PROM memory",
+ "Free memmory",
+};
+#endif
+
+/* References to section boundaries */
+extern char _end;
+
+#define PFN_ALIGN(x) (((unsigned long)(x) + (PAGE_SIZE - 1)) & PAGE_MASK)
+
+
+struct prom_pmemblock * __init prom_getmdesc(void)
+{
+ char *memsize_str;
+ unsigned int memsize;
+
+ memsize_str = prom_getenv("memsize");
+ if (!memsize_str) {
+ prom_printf("memsize not set in boot prom, set to default (32Mb)\n");
+ memsize = 0x02000000;
+ } else {
+#ifdef DEBUG
+ prom_printf("prom_memsize = %s\n", memsize_str);
+#endif
+ memsize = simple_strtol(memsize_str, NULL, 0);
+ }
+
+ memset(mdesc, 0, sizeof(mdesc));
+
+ mdesc[0].type = yamon_dontuse;
+ mdesc[0].base = 0x00000000;
+ mdesc[0].size = 0x00001000;
+
+ mdesc[1].type = yamon_prom;
+ mdesc[1].base = 0x00001000;
+ mdesc[1].size = 0x000ef000;
+
+#ifdef CONFIG_MIPS_MALTA
+ /*
+ * The area 0x000f0000-0x000fffff is allocated for BIOS memory by the
+ * south bridge and PCI access always forwarded to the ISA Bus and
+ * BIOSCS# is always generated.
+ * This mean that this area can't be used as DMA memory for PCI
+ * devices.
+ */
+ mdesc[2].type = yamon_dontuse;
+ mdesc[2].base = 0x000f0000;
+ mdesc[2].size = 0x00010000;
+#else
+ mdesc[2].type = yamon_prom;
+ mdesc[2].base = 0x000f0000;
+ mdesc[2].size = 0x00010000;
+#endif
+
+ mdesc[3].type = yamon_dontuse;
+ mdesc[3].base = 0x00100000;
+ mdesc[3].size = CPHYSADDR(PFN_ALIGN(&_end)) - mdesc[3].base;
+
+ mdesc[4].type = yamon_free;
+ mdesc[4].base = CPHYSADDR(PFN_ALIGN(&_end));
+ mdesc[4].size = memsize - mdesc[4].base;
+
+ return &mdesc[0];
+}
+
+static int __init prom_memtype_classify (unsigned int type)
+{
+ switch (type) {
+ case yamon_free:
+ return BOOT_MEM_RAM;
+ case yamon_prom:
+ return BOOT_MEM_ROM_DATA;
+ default:
+ return BOOT_MEM_RESERVED;
+ }
+}
+
+void __init prom_meminit(void)
+{
+ struct prom_pmemblock *p;
+
+#ifdef DEBUG
+ prom_printf("YAMON MEMORY DESCRIPTOR dump:\n");
+ p = prom_getmdesc();
+ while (p->size) {
+ int i = 0;
+ prom_printf("[%d,%p]: base<%08lx> size<%08lx> type<%s>\n",
+ i, p, p->base, p->size, mtypes[p->type]);
+ p++;
+ i++;
+ }
+#endif
+ p = prom_getmdesc();
+
+ while (p->size) {
+ long type;
+ unsigned long base, size;
+
+ type = prom_memtype_classify (p->type);
+ base = p->base;
+ size = p->size;
+
+ add_memory_region(base, size, type);
+ p++;
+ }
+}
+
+unsigned long __init prom_free_prom_memory(void)
+{
+ unsigned long freed = 0;
+ unsigned long addr;
+ int i;
+
+ for (i = 0; i < boot_mem_map.nr_map; i++) {
+ if (boot_mem_map.map[i].type != BOOT_MEM_ROM_DATA)
+ continue;
+
+ addr = boot_mem_map.map[i].addr;
+ while (addr < boot_mem_map.map[i].addr
+ + boot_mem_map.map[i].size) {
+ ClearPageReserved(virt_to_page(__va(addr)));
+ set_page_count(virt_to_page(__va(addr)), 1);
+ free_page((unsigned long)__va(addr));
+ addr += PAGE_SIZE;
+ freed += PAGE_SIZE;
+ }
+ }
+ printk("Freeing prom memory: %ldkb freed\n", freed >> 10);
+
+ return freed;
+}
diff --git a/arch/mips/mips-boards/generic/mipsIRQ.S b/arch/mips/mips-boards/generic/mipsIRQ.S
new file mode 100644
index 0000000..131f49b
--- /dev/null
+++ b/arch/mips/mips-boards/generic/mipsIRQ.S
@@ -0,0 +1,153 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999, 2000 MIPS Technologies, Inc. All rights reserved.
+ *
+ * ########################################################################
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ *
+ * Interrupt exception dispatch code.
+ *
+ */
+#include <linux/config.h>
+
+#include <asm/asm.h>
+#include <asm/mipsregs.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+
+/* A lot of complication here is taken away because:
+ *
+ * 1) We handle one interrupt and return, sitting in a loop and moving across
+ * all the pending IRQ bits in the cause register is _NOT_ the answer, the
+ * common case is one pending IRQ so optimize in that direction.
+ *
+ * 2) We need not check against bits in the status register IRQ mask, that
+ * would make this routine slow as hell.
+ *
+ * 3) Linux only thinks in terms of all IRQs on or all IRQs off, nothing in
+ * between like BSD spl() brain-damage.
+ *
+ * Furthermore, the IRQs on the MIPS board look basically (barring software
+ * IRQs which we don't use at all and all external interrupt sources are
+ * combined together on hardware interrupt 0 (MIPS IRQ 2)) like:
+ *
+ * MIPS IRQ Source
+ * -------- ------
+ * 0 Software (ignored)
+ * 1 Software (ignored)
+ * 2 Combined hardware interrupt (hw0)
+ * 3 Hardware (ignored)
+ * 4 Hardware (ignored)
+ * 5 Hardware (ignored)
+ * 6 Hardware (ignored)
+ * 7 R4k timer (what we use)
+ *
+ * Note: On the SEAD board thing are a little bit different.
+ * Here IRQ 2 (hw0) is wired to the UART0 and IRQ 3 (hw1) is wired
+ * wired to UART1.
+ *
+ * We handle the IRQ according to _our_ priority which is:
+ *
+ * Highest ---- R4k Timer
+ * Lowest ---- Combined hardware interrupt
+ *
+ * then we just return, if multiple IRQs are pending then we will just take
+ * another exception, big deal.
+ */
+
+ .text
+ .set noreorder
+ .set noat
+ .align 5
+ NESTED(mipsIRQ, PT_SIZE, sp)
+ SAVE_ALL
+ CLI
+ .set at
+
+ mfc0 s0, CP0_CAUSE # get irq bits
+ mfc0 s1, CP0_STATUS # get irq mask
+ and s0, s1
+
+ /* First we check for r4k counter/timer IRQ. */
+ andi a0, s0, CAUSEF_IP7
+ beq a0, zero, 1f
+ andi a0, s0, CAUSEF_IP2 # delay slot, check hw0 interrupt
+
+ /* Wheee, a timer interrupt. */
+ move a0, sp
+ jal mips_timer_interrupt
+ nop
+
+ j ret_from_irq
+ nop
+
+1:
+#if defined(CONFIG_MIPS_SEAD)
+ beq a0, zero, 1f
+ andi a0, s0, CAUSEF_IP3 # delay slot, check hw1 interrupt
+#else
+ beq a0, zero, 1f # delay slot, check hw3 interrupt
+ andi a0, s0, CAUSEF_IP5
+#endif
+
+ /* Wheee, combined hardware level zero interrupt. */
+#if defined(CONFIG_MIPS_ATLAS)
+ jal atlas_hw0_irqdispatch
+#elif defined(CONFIG_MIPS_MALTA)
+ jal malta_hw0_irqdispatch
+#elif defined(CONFIG_MIPS_SEAD)
+ jal sead_hw0_irqdispatch
+#else
+#error "MIPS board not supported\n"
+#endif
+ move a0, sp # delay slot
+
+ j ret_from_irq
+ nop # delay slot
+
+1:
+#if defined(CONFIG_MIPS_SEAD)
+ beq a0, zero, 1f
+ andi a0, s0, CAUSEF_IP5 # delay slot, check hw3 interrupt
+ jal sead_hw1_irqdispatch
+ move a0, sp # delay slot
+ j ret_from_irq
+ nop # delay slot
+1:
+#endif
+#if defined(CONFIG_MIPS_MALTA)
+ beq a0, zero, 1f # check hw3 (coreHI) interrupt
+ nop
+ jal corehi_irqdispatch
+ move a0, sp
+ j ret_from_irq
+ nop
+1:
+#endif
+ /*
+ * Here by mistake? This is possible, what can happen is that by the
+ * time we take the exception the IRQ pin goes low, so just leave if
+ * this is the case.
+ */
+ move a1,s0
+ PRINT("Got interrupt: c0_cause = %08x\n")
+ mfc0 a1, CP0_EPC
+ PRINT("c0_epc = %08x\n")
+
+ j ret_from_irq
+ nop
+ END(mipsIRQ)
diff --git a/arch/mips/mips-boards/generic/pci.c b/arch/mips/mips-boards/generic/pci.c
new file mode 100644
index 0000000..92c34bd
--- /dev/null
+++ b/arch/mips/mips-boards/generic/pci.c
@@ -0,0 +1,163 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999, 2000 MIPS Technologies, Inc. All rights reserved.
+ *
+ * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org)
+ *
+ * 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.
+ *
+ * MIPS boards specific PCI support.
+ */
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/mips-boards/generic.h>
+#include <asm/gt64120.h>
+#include <asm/mips-boards/bonito64.h>
+#include <asm/mips-boards/msc01_pci.h>
+#ifdef CONFIG_MIPS_MALTA
+#include <asm/mips-boards/malta.h>
+#endif
+
+static struct resource bonito64_mem_resource = {
+ .name = "Bonito PCI MEM",
+ .start = 0x10000000UL,
+ .end = 0x1bffffffUL,
+ .flags = IORESOURCE_MEM,
+};
+
+static struct resource bonito64_io_resource = {
+ .name = "Bonito IO MEM",
+ .start = 0x00002000UL, /* avoid conflicts with YAMON allocated I/O addresses */
+ .end = 0x000fffffUL,
+ .flags = IORESOURCE_IO,
+};
+
+static struct resource gt64120_mem_resource = {
+ .name = "GT64120 PCI MEM",
+ .start = 0x10000000UL,
+ .end = 0x1bdfffffUL,
+ .flags = IORESOURCE_MEM,
+};
+
+static struct resource gt64120_io_resource = {
+ .name = "GT64120 IO MEM",
+#ifdef CONFIG_MIPS_ATLAS
+ .start = 0x18000000UL,
+ .end = 0x181fffffUL,
+#endif
+#ifdef CONFIG_MIPS_MALTA
+ .start = 0x00002000UL,
+ .end = 0x001fffffUL,
+#endif
+ .flags = IORESOURCE_IO,
+};
+
+static struct resource msc_mem_resource = {
+ .name = "MSC PCI MEM",
+ .start = 0x10000000UL,
+ .end = 0x1fffffffUL,
+ .flags = IORESOURCE_MEM,
+};
+
+static struct resource msc_io_resource = {
+ .name = "MSC IO MEM",
+ .start = 0x00002000UL,
+ .end = 0x007fffffUL,
+ .flags = IORESOURCE_IO,
+};
+
+extern struct pci_ops bonito64_pci_ops;
+extern struct pci_ops gt64120_pci_ops;
+extern struct pci_ops msc_pci_ops;
+
+static struct pci_controller bonito64_controller = {
+ .pci_ops = &bonito64_pci_ops,
+ .io_resource = &bonito64_io_resource,
+ .mem_resource = &bonito64_mem_resource,
+ .mem_offset = 0x10000000UL,
+ .io_offset = 0x00000000UL,
+};
+
+static struct pci_controller gt64120_controller = {
+ .pci_ops = >64120_pci_ops,
+ .io_resource = >64120_io_resource,
+ .mem_resource = >64120_mem_resource,
+ .mem_offset = 0x00000000UL,
+ .io_offset = 0x00000000UL,
+};
+
+static struct pci_controller msc_controller = {
+ .pci_ops = &msc_pci_ops,
+ .io_resource = &msc_io_resource,
+ .mem_resource = &msc_mem_resource,
+ .mem_offset = 0x10000000UL,
+ .io_offset = 0x00000000UL,
+};
+
+static int __init pcibios_init(void)
+{
+ struct pci_controller *controller;
+
+ switch (mips_revision_corid) {
+ case MIPS_REVISION_CORID_QED_RM5261:
+ case MIPS_REVISION_CORID_CORE_LV:
+ case MIPS_REVISION_CORID_CORE_FPGA:
+ case MIPS_REVISION_CORID_CORE_FPGAR2:
+ /*
+ * Due to a bug in the Galileo system controller, we need
+ * to setup the PCI BAR for the Galileo internal registers.
+ * This should be done in the bios/bootprom and will be
+ * fixed in a later revision of YAMON (the MIPS boards
+ * boot prom).
+ */
+ GT_WRITE(GT_PCI0_CFGADDR_OFS,
+ (0 << GT_PCI0_CFGADDR_BUSNUM_SHF) | /* Local bus */
+ (0 << GT_PCI0_CFGADDR_DEVNUM_SHF) | /* GT64120 dev */
+ (0 << GT_PCI0_CFGADDR_FUNCTNUM_SHF) | /* Function 0*/
+ ((0x20/4) << GT_PCI0_CFGADDR_REGNUM_SHF) | /* BAR 4*/
+ GT_PCI0_CFGADDR_CONFIGEN_BIT );
+
+ /* Perform the write */
+ GT_WRITE(GT_PCI0_CFGDATA_OFS, CPHYSADDR(MIPS_GT_BASE));
+
+ controller = >64120_controller;
+ break;
+
+ case MIPS_REVISION_CORID_BONITO64:
+ case MIPS_REVISION_CORID_CORE_20K:
+ case MIPS_REVISION_CORID_CORE_EMUL_BON:
+ controller = &bonito64_controller;
+ break;
+
+ case MIPS_REVISION_CORID_CORE_MSC:
+ case MIPS_REVISION_CORID_CORE_FPGA2:
+ case MIPS_REVISION_CORID_CORE_EMUL_MSC:
+ controller = &msc_controller;
+ break;
+ default:
+ return 1;
+ }
+
+ ioport_resource.end = controller->io_resource->end;
+
+ register_pci_controller (controller);
+
+ return 0;
+}
+
+early_initcall(pcibios_init);
diff --git a/arch/mips/mips-boards/generic/printf.c b/arch/mips/mips-boards/generic/printf.c
new file mode 100644
index 0000000..2c1ab1f
--- /dev/null
+++ b/arch/mips/mips-boards/generic/printf.c
@@ -0,0 +1,79 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Putting things on the screen/serial line using YAMONs facilities.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/serial_reg.h>
+#include <linux/spinlock.h>
+#include <asm/io.h>
+
+#ifdef CONFIG_MIPS_ATLAS
+#include <asm/mips-boards/atlas.h>
+
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+#define PORT(offset) (ATLAS_UART_REGS_BASE + ((offset)<<3))
+#else
+#define PORT(offset) (ATLAS_UART_REGS_BASE + 3 + ((offset)<<3))
+#endif
+
+#elif defined(CONFIG_MIPS_SEAD)
+
+#include <asm/mips-boards/sead.h>
+
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+#define PORT(offset) (SEAD_UART0_REGS_BASE + ((offset)<<3))
+#else
+#define PORT(offset) (SEAD_UART0_REGS_BASE + 3 + ((offset)<<3))
+#endif
+
+#else
+
+#define PORT(offset) (0x3f8 + (offset))
+
+#endif
+
+static inline unsigned int serial_in(int offset)
+{
+ return inb(PORT(offset));
+}
+
+static inline void serial_out(int offset, int value)
+{
+ outb(value, PORT(offset));
+}
+
+int prom_putchar(char c)
+{
+ while ((serial_in(UART_LSR) & UART_LSR_THRE) == 0)
+ ;
+
+ serial_out(UART_TX, c);
+
+ return 1;
+}
+
+char prom_getchar(void)
+{
+ while (!(serial_in(UART_LSR) & UART_LSR_DR))
+ ;
+
+ return serial_in(UART_RX);
+}
+
diff --git a/arch/mips/mips-boards/generic/reset.c b/arch/mips/mips-boards/generic/reset.c
new file mode 100644
index 0000000..9fdec74
--- /dev/null
+++ b/arch/mips/mips-boards/generic/reset.c
@@ -0,0 +1,73 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
+ *
+ * ########################################################################
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ *
+ * Reset the MIPS boards.
+ *
+ */
+#include <linux/config.h>
+
+#include <asm/io.h>
+#include <asm/reboot.h>
+#include <asm/mips-boards/generic.h>
+#if defined(CONFIG_MIPS_ATLAS)
+#include <asm/mips-boards/atlas.h>
+#endif
+
+static void mips_machine_restart(char *command);
+static void mips_machine_halt(void);
+#if defined(CONFIG_MIPS_ATLAS)
+static void atlas_machine_power_off(void);
+#endif
+
+static void mips_machine_restart(char *command)
+{
+ volatile unsigned int *softres_reg = (unsigned int *)ioremap (SOFTRES_REG, sizeof(unsigned int));
+
+ *softres_reg = GORESET;
+}
+
+static void mips_machine_halt(void)
+{
+ volatile unsigned int *softres_reg = (unsigned int *)ioremap (SOFTRES_REG, sizeof(unsigned int));
+
+ *softres_reg = GORESET;
+}
+
+#if defined(CONFIG_MIPS_ATLAS)
+static void atlas_machine_power_off(void)
+{
+ volatile unsigned int *psustby_reg = (unsigned int *)ioremap(ATLAS_PSUSTBY_REG, sizeof(unsigned int));
+
+ *psustby_reg = ATLAS_GOSTBY;
+}
+#endif
+
+void mips_reboot_setup(void)
+{
+ _machine_restart = mips_machine_restart;
+ _machine_halt = mips_machine_halt;
+#if defined(CONFIG_MIPS_ATLAS)
+ _machine_power_off = atlas_machine_power_off;
+#endif
+#if defined(CONFIG_MIPS_MALTA) || defined(CONFIG_MIPS_SEAD)
+ _machine_power_off = mips_machine_halt;
+#endif
+}
diff --git a/arch/mips/mips-boards/generic/time.c b/arch/mips/mips-boards/generic/time.c
new file mode 100644
index 0000000..fe7fc17
--- /dev/null
+++ b/arch/mips/mips-boards/generic/time.c
@@ -0,0 +1,167 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Setting up the clock on the MIPS boards.
+ */
+
+#include <linux/types.h>
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/kernel_stat.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/time.h>
+#include <linux/timex.h>
+#include <linux/mc146818rtc.h>
+
+#include <asm/mipsregs.h>
+#include <asm/ptrace.h>
+#include <asm/div64.h>
+#include <asm/cpu.h>
+#include <asm/time.h>
+#include <asm/mc146818-time.h>
+
+#include <asm/mips-boards/generic.h>
+#include <asm/mips-boards/prom.h>
+
+unsigned long cpu_khz;
+
+#if defined(CONFIG_MIPS_SEAD)
+#define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ5)
+#else
+#define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5)
+#endif
+
+#if defined(CONFIG_MIPS_ATLAS)
+static char display_string[] = " LINUX ON ATLAS ";
+#endif
+#if defined(CONFIG_MIPS_MALTA)
+static char display_string[] = " LINUX ON MALTA ";
+#endif
+#if defined(CONFIG_MIPS_SEAD)
+static char display_string[] = " LINUX ON SEAD ";
+#endif
+static unsigned int display_count = 0;
+#define MAX_DISPLAY_COUNT (sizeof(display_string) - 8)
+
+#define MIPS_CPU_TIMER_IRQ (NR_IRQS-1)
+
+static unsigned int timer_tick_count=0;
+
+void mips_timer_interrupt(struct pt_regs *regs)
+{
+ if ((timer_tick_count++ % HZ) == 0) {
+ mips_display_message(&display_string[display_count++]);
+ if (display_count == MAX_DISPLAY_COUNT)
+ display_count = 0;
+
+ }
+
+ ll_timer_interrupt(MIPS_CPU_TIMER_IRQ, regs);
+}
+
+/*
+ * Estimate CPU frequency. Sets mips_counter_frequency as a side-effect
+ */
+static unsigned int __init estimate_cpu_frequency(void)
+{
+ unsigned int prid = read_c0_prid() & 0xffff00;
+ unsigned int count;
+
+#ifdef CONFIG_MIPS_SEAD
+ /*
+ * The SEAD board doesn't have a real time clock, so we can't
+ * really calculate the timer frequency
+ * For now we hardwire the SEAD board frequency to 12MHz.
+ */
+
+ if ((prid == (PRID_COMP_MIPS | PRID_IMP_20KC)) ||
+ (prid == (PRID_COMP_MIPS | PRID_IMP_25KF)))
+ count = 12000000;
+ else
+ count = 6000000;
+#endif
+#if defined(CONFIG_MIPS_ATLAS) || defined(CONFIG_MIPS_MALTA)
+ unsigned int flags;
+
+ local_irq_save(flags);
+
+ /* Start counter exactly on falling edge of update flag */
+ while (CMOS_READ(RTC_REG_A) & RTC_UIP);
+ while (!(CMOS_READ(RTC_REG_A) & RTC_UIP));
+
+ /* Start r4k counter. */
+ write_c0_count(0);
+
+ /* Read counter exactly on falling edge of update flag */
+ while (CMOS_READ(RTC_REG_A) & RTC_UIP);
+ while (!(CMOS_READ(RTC_REG_A) & RTC_UIP));
+
+ count = read_c0_count();
+
+ /* restore interrupts */
+ local_irq_restore(flags);
+#endif
+
+ mips_hpt_frequency = count;
+ if ((prid != (PRID_COMP_MIPS | PRID_IMP_20KC)) &&
+ (prid != (PRID_COMP_MIPS | PRID_IMP_25KF)))
+ count *= 2;
+
+ count += 5000; /* round */
+ count -= count%10000;
+
+ return count;
+}
+
+unsigned long __init mips_rtc_get_time(void)
+{
+ return mc146818_get_cmos_time();
+}
+
+void __init mips_time_init(void)
+{
+ unsigned int est_freq, flags;
+
+ local_irq_save(flags);
+
+#if defined(CONFIG_MIPS_ATLAS) || defined(CONFIG_MIPS_MALTA)
+ /* Set Data mode - binary. */
+ CMOS_WRITE(CMOS_READ(RTC_CONTROL) | RTC_DM_BINARY, RTC_CONTROL);
+#endif
+
+ est_freq = estimate_cpu_frequency ();
+
+ printk("CPU frequency %d.%02d MHz\n", est_freq/1000000,
+ (est_freq%1000000)*100/1000000);
+
+ cpu_khz = est_freq / 1000;
+
+ local_irq_restore(flags);
+}
+
+void __init mips_timer_setup(struct irqaction *irq)
+{
+ /* we are using the cpu counter for timer interrupts */
+ irq->handler = no_action; /* we use our own handler */
+ setup_irq(MIPS_CPU_TIMER_IRQ, irq);
+
+ /* to generate the first timer interrupt */
+ write_c0_compare (read_c0_count() + mips_hpt_frequency/HZ);
+ set_c0_status(ALLINTS);
+}
diff --git a/arch/mips/mips-boards/malta/Makefile b/arch/mips/mips-boards/malta/Makefile
new file mode 100644
index 0000000..fd4c143
--- /dev/null
+++ b/arch/mips/mips-boards/malta/Makefile
@@ -0,0 +1,22 @@
+#
+# Carsten Langgaard, carstenl@mips.com
+# Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
+#
+# This program is free software; you can distribute it and/or modify it
+# under the terms of the GNU General Public License (Version 2) as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+#
+# Makefile for the MIPS Malta specific kernel interface routines
+# under Linux.
+#
+
+obj-y := malta_int.o malta_setup.o
diff --git a/arch/mips/mips-boards/malta/malta_int.c b/arch/mips/mips-boards/malta/malta_int.c
new file mode 100644
index 0000000..dd2db35
--- /dev/null
+++ b/arch/mips/mips-boards/malta/malta_int.c
@@ -0,0 +1,187 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2000, 2001, 2004 MIPS Technologies, Inc.
+ * Copyright (C) 2001 Ralf Baechle
+ *
+ * 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.
+ *
+ * Routines for generic manipulation of the interrupts found on the MIPS
+ * Malta board.
+ * The interrupt controller is located in the South Bridge a PIIX4 device
+ * with two internal 82C95 interrupt controllers.
+ */
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/kernel_stat.h>
+#include <linux/random.h>
+
+#include <asm/i8259.h>
+#include <asm/io.h>
+#include <asm/mips-boards/malta.h>
+#include <asm/mips-boards/maltaint.h>
+#include <asm/mips-boards/piix4.h>
+#include <asm/gt64120.h>
+#include <asm/mips-boards/generic.h>
+#include <asm/mips-boards/msc01_pci.h>
+
+extern asmlinkage void mipsIRQ(void);
+
+static DEFINE_SPINLOCK(mips_irq_lock);
+
+static inline int mips_pcibios_iack(void)
+{
+ int irq;
+ u32 dummy;
+
+ /*
+ * Determine highest priority pending interrupt by performing
+ * a PCI Interrupt Acknowledge cycle.
+ */
+ switch(mips_revision_corid) {
+ case MIPS_REVISION_CORID_CORE_MSC:
+ case MIPS_REVISION_CORID_CORE_FPGA2:
+ case MIPS_REVISION_CORID_CORE_EMUL_MSC:
+ MSC_READ(MSC01_PCI_IACK, irq);
+ irq &= 0xff;
+ break;
+ case MIPS_REVISION_CORID_QED_RM5261:
+ case MIPS_REVISION_CORID_CORE_LV:
+ case MIPS_REVISION_CORID_CORE_FPGA:
+ case MIPS_REVISION_CORID_CORE_FPGAR2:
+ irq = GT_READ(GT_PCI0_IACK_OFS);
+ irq &= 0xff;
+ break;
+ case MIPS_REVISION_CORID_BONITO64:
+ case MIPS_REVISION_CORID_CORE_20K:
+ case MIPS_REVISION_CORID_CORE_EMUL_BON:
+ /* The following will generate a PCI IACK cycle on the
+ * Bonito controller. It's a little bit kludgy, but it
+ * was the easiest way to implement it in hardware at
+ * the given time.
+ */
+ BONITO_PCIMAP_CFG = 0x20000;
+
+ /* Flush Bonito register block */
+ dummy = BONITO_PCIMAP_CFG;
+ iob(); /* sync */
+
+ irq = *(volatile u32 *)(_pcictrl_bonito_pcicfg);
+ iob(); /* sync */
+ irq &= 0xff;
+ BONITO_PCIMAP_CFG = 0;
+ break;
+ default:
+ printk("Unknown Core card, don't know the system controller.\n");
+ return -1;
+ }
+ return irq;
+}
+
+static inline int get_int(int *irq)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&mips_irq_lock, flags);
+
+ *irq = mips_pcibios_iack();
+
+ /*
+ * IRQ7 is used to detect spurious interrupts.
+ * The interrupt acknowledge cycle returns IRQ7, if no
+ * interrupts is requested.
+ * We can differentiate between this situation and a
+ * "Normal" IRQ7 by reading the ISR.
+ */
+ if (*irq == 7)
+ {
+ outb(PIIX4_OCW3_SEL | PIIX4_OCW3_ISR,
+ PIIX4_ICTLR1_OCW3);
+ if (!(inb(PIIX4_ICTLR1_OCW3) & (1 << 7))) {
+ spin_unlock_irqrestore(&mips_irq_lock, flags);
+ printk("We got a spurious interrupt from PIIX4.\n");
+ atomic_inc(&irq_err_count);
+ return -1; /* Spurious interrupt. */
+ }
+ }
+
+ spin_unlock_irqrestore(&mips_irq_lock, flags);
+
+ return 0;
+}
+
+void malta_hw0_irqdispatch(struct pt_regs *regs)
+{
+ int irq;
+
+ if (get_int(&irq))
+ return; /* interrupt has already been cleared */
+
+ do_IRQ(irq, regs);
+}
+
+void corehi_irqdispatch(struct pt_regs *regs)
+{
+ unsigned int data,datahi;
+
+ /* Mask out corehi interrupt. */
+ clear_c0_status(IE_IRQ3);
+
+ printk("CoreHI interrupt, shouldn't happen, so we die here!!!\n");
+ printk("epc : %08lx\nStatus: %08lx\nCause : %08lx\nbadVaddr : %08lx\n"
+, regs->cp0_epc, regs->cp0_status, regs->cp0_cause, regs->cp0_badvaddr);
+ switch(mips_revision_corid) {
+ case MIPS_REVISION_CORID_CORE_MSC:
+ case MIPS_REVISION_CORID_CORE_FPGA2:
+ case MIPS_REVISION_CORID_CORE_EMUL_MSC:
+ break;
+ case MIPS_REVISION_CORID_QED_RM5261:
+ case MIPS_REVISION_CORID_CORE_LV:
+ case MIPS_REVISION_CORID_CORE_FPGA:
+ case MIPS_REVISION_CORID_CORE_FPGAR2:
+ data = GT_READ(GT_INTRCAUSE_OFS);
+ printk("GT_INTRCAUSE = %08x\n", data);
+ data = GT_READ(GT_CPUERR_ADDRLO_OFS);
+ datahi = GT_READ(GT_CPUERR_ADDRHI_OFS);
+ printk("GT_CPUERR_ADDR = %02x%08x\n", datahi, data);
+ break;
+ case MIPS_REVISION_CORID_BONITO64:
+ case MIPS_REVISION_CORID_CORE_20K:
+ case MIPS_REVISION_CORID_CORE_EMUL_BON:
+ data = BONITO_INTISR;
+ printk("BONITO_INTISR = %08x\n", data);
+ data = BONITO_INTEN;
+ printk("BONITO_INTEN = %08x\n", data);
+ data = BONITO_INTPOL;
+ printk("BONITO_INTPOL = %08x\n", data);
+ data = BONITO_INTEDGE;
+ printk("BONITO_INTEDGE = %08x\n", data);
+ data = BONITO_INTSTEER;
+ printk("BONITO_INTSTEER = %08x\n", data);
+ data = BONITO_PCICMD;
+ printk("BONITO_PCICMD = %08x\n", data);
+ break;
+ }
+
+ /* We die here*/
+ die("CoreHi interrupt", regs);
+}
+
+void __init arch_init_irq(void)
+{
+ set_except_vector(0, mipsIRQ);
+ init_i8259_irqs();
+}
diff --git a/arch/mips/mips-boards/malta/malta_setup.c b/arch/mips/mips-boards/malta/malta_setup.c
new file mode 100644
index 0000000..3377e66
--- /dev/null
+++ b/arch/mips/mips-boards/malta/malta_setup.c
@@ -0,0 +1,231 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/pci.h>
+#include <linux/tty.h>
+
+#ifdef CONFIG_MTD
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/physmap.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/map.h>
+#endif
+
+#include <asm/cpu.h>
+#include <asm/bootinfo.h>
+#include <asm/irq.h>
+#include <asm/mips-boards/generic.h>
+#include <asm/mips-boards/prom.h>
+#include <asm/mips-boards/malta.h>
+#include <asm/mips-boards/maltaint.h>
+#include <asm/dma.h>
+#include <asm/time.h>
+#include <asm/traps.h>
+#ifdef CONFIG_VT
+#include <linux/console.h>
+#endif
+
+extern void mips_reboot_setup(void);
+extern void mips_time_init(void);
+extern void mips_timer_setup(struct irqaction *irq);
+extern unsigned long mips_rtc_get_time(void);
+
+#ifdef CONFIG_KGDB
+extern void kgdb_config(void);
+#endif
+
+struct resource standard_io_resources[] = {
+ { "dma1", 0x00, 0x1f, IORESOURCE_BUSY },
+ { "timer", 0x40, 0x5f, IORESOURCE_BUSY },
+ { "keyboard", 0x60, 0x6f, IORESOURCE_BUSY },
+ { "dma page reg", 0x80, 0x8f, IORESOURCE_BUSY },
+ { "dma2", 0xc0, 0xdf, IORESOURCE_BUSY },
+};
+
+#ifdef CONFIG_MTD
+static struct mtd_partition malta_mtd_partitions[] = {
+ {
+ .name = "YAMON",
+ .offset = 0x0,
+ .size = 0x100000,
+ .mask_flags = MTD_WRITEABLE
+ },
+ {
+ .name = "User FS",
+ .offset = 0x100000,
+ .size = 0x2e0000
+ },
+ {
+ .name = "Board Config",
+ .offset = 0x3e0000,
+ .size = 0x020000,
+ .mask_flags = MTD_WRITEABLE
+ }
+};
+
+#define number_partitions (sizeof(malta_mtd_partitions)/sizeof(struct mtd_partition))
+#endif
+
+const char *get_system_type(void)
+{
+ return "MIPS Malta";
+}
+
+#ifdef CONFIG_BLK_DEV_FD
+void __init fd_activate(void)
+{
+ /*
+ * Activate Floppy Controller in the SMSC FDC37M817 Super I/O
+ * Controller.
+ * Done by YAMON 2.00 onwards
+ */
+ /* Entering config state. */
+ SMSC_WRITE(SMSC_CONFIG_ENTER, SMSC_CONFIG_REG);
+
+ /* Activate floppy controller. */
+ SMSC_WRITE(SMSC_CONFIG_DEVNUM, SMSC_CONFIG_REG);
+ SMSC_WRITE(SMSC_CONFIG_DEVNUM_FLOPPY, SMSC_DATA_REG);
+ SMSC_WRITE(SMSC_CONFIG_ACTIVATE, SMSC_CONFIG_REG);
+ SMSC_WRITE(SMSC_CONFIG_ACTIVATE_ENABLE, SMSC_DATA_REG);
+
+ /* Exit config state. */
+ SMSC_WRITE(SMSC_CONFIG_EXIT, SMSC_CONFIG_REG);
+}
+#endif
+
+static int __init malta_setup(void)
+{
+ unsigned int i;
+
+ /* Request I/O space for devices used on the Malta board. */
+ for (i = 0; i < ARRAY_SIZE(standard_io_resources); i++)
+ request_resource(&ioport_resource, standard_io_resources+i);
+
+ /*
+ * Enable DMA channel 4 (cascade channel) in the PIIX4 south bridge.
+ */
+ enable_dma(4);
+
+#ifdef CONFIG_KGDB
+ kgdb_config ();
+#endif
+
+ if ((mips_revision_corid == MIPS_REVISION_CORID_BONITO64) ||
+ (mips_revision_corid == MIPS_REVISION_CORID_CORE_20K) ||
+ (mips_revision_corid == MIPS_REVISION_CORID_CORE_EMUL_BON)) {
+ char *argptr;
+
+ argptr = prom_getcmdline();
+ if (strstr(argptr, "debug")) {
+ BONITO_BONGENCFG |= BONITO_BONGENCFG_DEBUGMODE;
+ printk ("Enabled Bonito debug mode\n");
+ }
+ else
+ BONITO_BONGENCFG &= ~BONITO_BONGENCFG_DEBUGMODE;
+
+#ifdef CONFIG_DMA_COHERENT
+ if (BONITO_PCICACHECTRL & BONITO_PCICACHECTRL_CPUCOH_PRES) {
+ BONITO_PCICACHECTRL |= BONITO_PCICACHECTRL_CPUCOH_EN;
+ printk("Enabled Bonito CPU coherency\n");
+
+ argptr = prom_getcmdline();
+ if (strstr(argptr, "iobcuncached")) {
+ BONITO_PCICACHECTRL &= ~BONITO_PCICACHECTRL_IOBCCOH_EN;
+ BONITO_PCIMEMBASECFG = BONITO_PCIMEMBASECFG &
+ ~(BONITO_PCIMEMBASECFG_MEMBASE0_CACHED |
+ BONITO_PCIMEMBASECFG_MEMBASE1_CACHED);
+ printk("Disabled Bonito IOBC coherency\n");
+ }
+ else {
+ BONITO_PCICACHECTRL |= BONITO_PCICACHECTRL_IOBCCOH_EN;
+ BONITO_PCIMEMBASECFG |=
+ (BONITO_PCIMEMBASECFG_MEMBASE0_CACHED |
+ BONITO_PCIMEMBASECFG_MEMBASE1_CACHED);
+ printk("Disabled Bonito IOBC coherency\n");
+ }
+ }
+ else
+ panic("Hardware DMA cache coherency not supported");
+
+#endif
+ }
+#ifdef CONFIG_DMA_COHERENT
+ else {
+ panic("Hardware DMA cache coherency not supported");
+ }
+#endif
+
+#ifdef CONFIG_BLK_DEV_IDE
+ /* Check PCI clock */
+ {
+ int jmpr = (*((volatile unsigned int *)ioremap(MALTA_JMPRS_REG, sizeof(unsigned int))) >> 2) & 0x07;
+ static const int pciclocks[] __initdata = {
+ 33, 20, 25, 30, 12, 16, 37, 10
+ };
+ int pciclock = pciclocks[jmpr];
+ char *argptr = prom_getcmdline();
+
+ if (pciclock != 33 && !strstr (argptr, "idebus=")) {
+ printk("WARNING: PCI clock is %dMHz, setting idebus\n", pciclock);
+ argptr += strlen(argptr);
+ sprintf (argptr, " idebus=%d", pciclock);
+ if (pciclock < 20 || pciclock > 66)
+ printk ("WARNING: IDE timing calculations will be incorrect\n");
+ }
+ }
+#endif
+#ifdef CONFIG_BLK_DEV_FD
+ fd_activate ();
+#endif
+#ifdef CONFIG_VT
+#if defined(CONFIG_VGA_CONSOLE)
+ screen_info = (struct screen_info) {
+ 0, 25, /* orig-x, orig-y */
+ 0, /* unused */
+ 0, /* orig-video-page */
+ 0, /* orig-video-mode */
+ 80, /* orig-video-cols */
+ 0,0,0, /* ega_ax, ega_bx, ega_cx */
+ 25, /* orig-video-lines */
+ VIDEO_TYPE_VGAC, /* orig-video-isVGA */
+ 16 /* orig-video-points */
+ };
+#endif
+#endif
+
+#ifdef CONFIG_MTD
+ /*
+ * Support for MTD on Malta. Use the generic physmap driver
+ */
+ physmap_configure(0x1e000000, 0x400000, 4, NULL);
+ physmap_set_partitions(malta_mtd_partitions, number_partitions);
+#endif
+
+ mips_reboot_setup();
+
+ board_time_init = mips_time_init;
+ board_timer_setup = mips_timer_setup;
+ rtc_get_time = mips_rtc_get_time;
+
+ return 0;
+}
+
+early_initcall(malta_setup);
diff --git a/arch/mips/mips-boards/sead/Makefile b/arch/mips/mips-boards/sead/Makefile
new file mode 100644
index 0000000..224bb84
--- /dev/null
+++ b/arch/mips/mips-boards/sead/Makefile
@@ -0,0 +1,26 @@
+#
+# Carsten Langgaard, carstenl@mips.com
+# Copyright (C) 2002 MIPS Technologies, Inc. All rights reserved.
+#
+# ########################################################################
+#
+# This program is free software; you can distribute it and/or modify it
+# under the terms of the GNU General Public License (Version 2) as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+#
+# #######################################################################
+#
+# Makefile for the MIPS SEAD specific kernel interface routines
+# under Linux.
+#
+
+obj-y := sead_int.o sead_setup.o
diff --git a/arch/mips/mips-boards/sead/sead_int.c b/arch/mips/mips-boards/sead/sead_int.c
new file mode 100644
index 0000000..e510965
--- /dev/null
+++ b/arch/mips/mips-boards/sead/sead_int.c
@@ -0,0 +1,51 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2002 MIPS Technologies, Inc. All rights reserved.
+ * Copyright (C) 2003 Ralf Baechle (ralf@linux-mips.org)
+ *
+ * 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.
+ *
+ * Routines for generic manipulation of the interrupts found on the MIPS
+ * Sead board.
+ */
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+
+#include <asm/mips-boards/seadint.h>
+
+extern asmlinkage void mipsIRQ(void);
+
+asmlinkage void sead_hw0_irqdispatch(struct pt_regs *regs)
+{
+ do_IRQ(SEADINT_UART0, regs);
+}
+
+asmlinkage void sead_hw1_irqdispatch(struct pt_regs *regs)
+{
+ do_IRQ(SEADINT_UART1, regs);
+}
+
+void __init arch_init_irq(void)
+{
+ /*
+ * Mask out all interrupt
+ */
+ clear_c0_status(0x0000ff00);
+
+ /* Now safe to set the exception vector. */
+ set_except_vector(0, mipsIRQ);
+
+ mips_cpu_irq_init(0);
+}
diff --git a/arch/mips/mips-boards/sead/sead_setup.c b/arch/mips/mips-boards/sead/sead_setup.c
new file mode 100644
index 0000000..29892b8
--- /dev/null
+++ b/arch/mips/mips-boards/sead/sead_setup.c
@@ -0,0 +1,84 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2002 MIPS Technologies, Inc. All rights reserved.
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * SEAD specific setup.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/tty.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+
+#include <asm/cpu.h>
+#include <asm/bootinfo.h>
+#include <asm/irq.h>
+#include <asm/mips-boards/generic.h>
+#include <asm/mips-boards/prom.h>
+#include <asm/mips-boards/sead.h>
+#include <asm/mips-boards/seadint.h>
+#include <asm/time.h>
+
+extern void mips_reboot_setup(void);
+extern void mips_time_init(void);
+extern void mips_timer_setup(struct irqaction *irq);
+
+static void __init serial_init(void);
+
+const char *get_system_type(void)
+{
+ return "MIPS SEAD";
+}
+
+static void __init sead_setup(void)
+{
+ ioport_resource.end = 0x7fffffff;
+
+ serial_init ();
+
+ board_time_init = mips_time_init;
+ board_timer_setup = mips_timer_setup;
+
+ mips_reboot_setup();
+}
+
+early_initcall(sead_setup);
+
+static void __init serial_init(void)
+{
+#ifdef CONFIG_SERIAL_8250
+ struct uart_port s;
+
+ memset(&s, 0, sizeof(s));
+
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+ s.iobase = SEAD_UART0_REGS_BASE;
+#else
+ s.iobase = SEAD_UART0_REGS_BASE+3;
+#endif
+ s.irq = SEADINT_UART0;
+ s.uartclk = SEAD_BASE_BAUD * 16;
+ s.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ;
+ s.iotype = 0;
+ s.regshift = 3;
+
+ if (early_serial_setup(&s) != 0) {
+ printk(KERN_ERR "Serial setup failed!\n");
+ }
+#endif
+}
diff --git a/arch/mips/mm/Makefile b/arch/mips/mm/Makefile
new file mode 100644
index 0000000..f61e038
--- /dev/null
+++ b/arch/mips/mm/Makefile
@@ -0,0 +1,44 @@
+#
+# Makefile for the Linux/MIPS-specific parts of the memory manager.
+#
+
+obj-y += cache.o extable.o fault.o init.o pgtable.o \
+ tlbex.o tlbex-fault.o
+
+obj-$(CONFIG_MIPS32) += ioremap.o pgtable-32.o
+obj-$(CONFIG_MIPS64) += pgtable-64.o
+obj-$(CONFIG_HIGHMEM) += highmem.o
+
+obj-$(CONFIG_CPU_MIPS32) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
+obj-$(CONFIG_CPU_MIPS64) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
+obj-$(CONFIG_CPU_NEVADA) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
+obj-$(CONFIG_CPU_R10000) += c-r4k.o cex-gen.o pg-r4k.o tlb-andes.o
+obj-$(CONFIG_CPU_R3000) += c-r3k.o tlb-r3k.o pg-r4k.o
+obj-$(CONFIG_CPU_R4300) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
+obj-$(CONFIG_CPU_R4X00) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
+obj-$(CONFIG_CPU_R5000) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
+obj-$(CONFIG_CPU_R5432) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
+obj-$(CONFIG_CPU_R8000) += c-r4k.o cex-gen.o pg-r4k.o tlb-r8k.o
+obj-$(CONFIG_CPU_RM7000) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
+obj-$(CONFIG_CPU_RM9000) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
+obj-$(CONFIG_CPU_SB1) += c-sb1.o cerr-sb1.o cex-sb1.o pg-sb1.o \
+ tlb-sb1.o
+obj-$(CONFIG_CPU_TX39XX) += c-tx39.o pg-r4k.o tlb-r3k.o
+obj-$(CONFIG_CPU_TX49XX) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
+obj-$(CONFIG_CPU_VR41XX) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
+
+obj-$(CONFIG_IP22_CPU_SCACHE) += sc-ip22.o
+obj-$(CONFIG_R5000_CPU_SCACHE) += sc-r5k.o
+obj-$(CONFIG_RM7000_CPU_SCACHE) += sc-rm7k.o
+
+#
+# Choose one DMA coherency model
+#
+ifndef CONFIG_OWN_DMA
+obj-$(CONFIG_DMA_COHERENT) += dma-coherent.o
+obj-$(CONFIG_DMA_NONCOHERENT) += dma-noncoherent.o
+endif
+obj-$(CONFIG_DMA_IP27) += dma-ip27.o
+obj-$(CONFIG_DMA_IP32) += dma-ip32.o
+
+EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/mm/c-r3k.c b/arch/mips/mm/c-r3k.c
new file mode 100644
index 0000000..c659f99
--- /dev/null
+++ b/arch/mips/mm/c-r3k.c
@@ -0,0 +1,349 @@
+/*
+ * r2300.c: R2000 and R3000 specific mmu/cache code.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ *
+ * with a lot of changes to make this thing work for R3000s
+ * Tx39XX R4k style caches added. HK
+ * Copyright (C) 1998, 1999, 2000 Harald Koerfgen
+ * Copyright (C) 1998 Gleb Raiko & Vladimir Roganov
+ * Copyright (C) 2001, 2004 Maciej W. Rozycki
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/mmu_context.h>
+#include <asm/system.h>
+#include <asm/isadep.h>
+#include <asm/io.h>
+#include <asm/bootinfo.h>
+#include <asm/cpu.h>
+
+static unsigned long icache_size, dcache_size; /* Size in bytes */
+static unsigned long icache_lsize, dcache_lsize; /* Size in bytes */
+
+#undef DEBUG_CACHE
+
+unsigned long __init r3k_cache_size(unsigned long ca_flags)
+{
+ unsigned long flags, status, dummy, size;
+ volatile unsigned long *p;
+
+ p = (volatile unsigned long *) KSEG0;
+
+ flags = read_c0_status();
+
+ /* isolate cache space */
+ write_c0_status((ca_flags|flags)&~ST0_IEC);
+
+ *p = 0xa5a55a5a;
+ dummy = *p;
+ status = read_c0_status();
+
+ if (dummy != 0xa5a55a5a || (status & ST0_CM)) {
+ size = 0;
+ } else {
+ for (size = 128; size <= 0x40000; size <<= 1)
+ *(p + size) = 0;
+ *p = -1;
+ for (size = 128;
+ (size <= 0x40000) && (*(p + size) == 0);
+ size <<= 1)
+ ;
+ if (size > 0x40000)
+ size = 0;
+ }
+
+ write_c0_status(flags);
+
+ return size * sizeof(*p);
+}
+
+unsigned long __init r3k_cache_lsize(unsigned long ca_flags)
+{
+ unsigned long flags, status, lsize, i;
+ volatile unsigned long *p;
+
+ p = (volatile unsigned long *) KSEG0;
+
+ flags = read_c0_status();
+
+ /* isolate cache space */
+ write_c0_status((ca_flags|flags)&~ST0_IEC);
+
+ for (i = 0; i < 128; i++)
+ *(p + i) = 0;
+ *(volatile unsigned char *)p = 0;
+ for (lsize = 1; lsize < 128; lsize <<= 1) {
+ *(p + lsize);
+ status = read_c0_status();
+ if (!(status & ST0_CM))
+ break;
+ }
+ for (i = 0; i < 128; i += lsize)
+ *(volatile unsigned char *)(p + i) = 0;
+
+ write_c0_status(flags);
+
+ return lsize * sizeof(*p);
+}
+
+static void __init r3k_probe_cache(void)
+{
+ dcache_size = r3k_cache_size(ST0_ISC);
+ if (dcache_size)
+ dcache_lsize = r3k_cache_lsize(ST0_ISC);
+
+ icache_size = r3k_cache_size(ST0_ISC|ST0_SWC);
+ if (icache_size)
+ icache_lsize = r3k_cache_lsize(ST0_ISC|ST0_SWC);
+}
+
+static void r3k_flush_icache_range(unsigned long start, unsigned long end)
+{
+ unsigned long size, i, flags;
+ volatile unsigned char *p;
+
+ size = end - start;
+ if (size > icache_size || KSEGX(start) != KSEG0) {
+ start = KSEG0;
+ size = icache_size;
+ }
+ p = (char *)start;
+
+ flags = read_c0_status();
+
+ /* isolate cache space */
+ write_c0_status((ST0_ISC|ST0_SWC|flags)&~ST0_IEC);
+
+ for (i = 0; i < size; i += 0x080) {
+ asm ( "sb\t$0, 0x000(%0)\n\t"
+ "sb\t$0, 0x004(%0)\n\t"
+ "sb\t$0, 0x008(%0)\n\t"
+ "sb\t$0, 0x00c(%0)\n\t"
+ "sb\t$0, 0x010(%0)\n\t"
+ "sb\t$0, 0x014(%0)\n\t"
+ "sb\t$0, 0x018(%0)\n\t"
+ "sb\t$0, 0x01c(%0)\n\t"
+ "sb\t$0, 0x020(%0)\n\t"
+ "sb\t$0, 0x024(%0)\n\t"
+ "sb\t$0, 0x028(%0)\n\t"
+ "sb\t$0, 0x02c(%0)\n\t"
+ "sb\t$0, 0x030(%0)\n\t"
+ "sb\t$0, 0x034(%0)\n\t"
+ "sb\t$0, 0x038(%0)\n\t"
+ "sb\t$0, 0x03c(%0)\n\t"
+ "sb\t$0, 0x040(%0)\n\t"
+ "sb\t$0, 0x044(%0)\n\t"
+ "sb\t$0, 0x048(%0)\n\t"
+ "sb\t$0, 0x04c(%0)\n\t"
+ "sb\t$0, 0x050(%0)\n\t"
+ "sb\t$0, 0x054(%0)\n\t"
+ "sb\t$0, 0x058(%0)\n\t"
+ "sb\t$0, 0x05c(%0)\n\t"
+ "sb\t$0, 0x060(%0)\n\t"
+ "sb\t$0, 0x064(%0)\n\t"
+ "sb\t$0, 0x068(%0)\n\t"
+ "sb\t$0, 0x06c(%0)\n\t"
+ "sb\t$0, 0x070(%0)\n\t"
+ "sb\t$0, 0x074(%0)\n\t"
+ "sb\t$0, 0x078(%0)\n\t"
+ "sb\t$0, 0x07c(%0)\n\t"
+ : : "r" (p) );
+ p += 0x080;
+ }
+
+ write_c0_status(flags);
+}
+
+static void r3k_flush_dcache_range(unsigned long start, unsigned long end)
+{
+ unsigned long size, i, flags;
+ volatile unsigned char *p;
+
+ size = end - start;
+ if (size > dcache_size || KSEGX(start) != KSEG0) {
+ start = KSEG0;
+ size = dcache_size;
+ }
+ p = (char *)start;
+
+ flags = read_c0_status();
+
+ /* isolate cache space */
+ write_c0_status((ST0_ISC|flags)&~ST0_IEC);
+
+ for (i = 0; i < size; i += 0x080) {
+ asm ( "sb\t$0, 0x000(%0)\n\t"
+ "sb\t$0, 0x004(%0)\n\t"
+ "sb\t$0, 0x008(%0)\n\t"
+ "sb\t$0, 0x00c(%0)\n\t"
+ "sb\t$0, 0x010(%0)\n\t"
+ "sb\t$0, 0x014(%0)\n\t"
+ "sb\t$0, 0x018(%0)\n\t"
+ "sb\t$0, 0x01c(%0)\n\t"
+ "sb\t$0, 0x020(%0)\n\t"
+ "sb\t$0, 0x024(%0)\n\t"
+ "sb\t$0, 0x028(%0)\n\t"
+ "sb\t$0, 0x02c(%0)\n\t"
+ "sb\t$0, 0x030(%0)\n\t"
+ "sb\t$0, 0x034(%0)\n\t"
+ "sb\t$0, 0x038(%0)\n\t"
+ "sb\t$0, 0x03c(%0)\n\t"
+ "sb\t$0, 0x040(%0)\n\t"
+ "sb\t$0, 0x044(%0)\n\t"
+ "sb\t$0, 0x048(%0)\n\t"
+ "sb\t$0, 0x04c(%0)\n\t"
+ "sb\t$0, 0x050(%0)\n\t"
+ "sb\t$0, 0x054(%0)\n\t"
+ "sb\t$0, 0x058(%0)\n\t"
+ "sb\t$0, 0x05c(%0)\n\t"
+ "sb\t$0, 0x060(%0)\n\t"
+ "sb\t$0, 0x064(%0)\n\t"
+ "sb\t$0, 0x068(%0)\n\t"
+ "sb\t$0, 0x06c(%0)\n\t"
+ "sb\t$0, 0x070(%0)\n\t"
+ "sb\t$0, 0x074(%0)\n\t"
+ "sb\t$0, 0x078(%0)\n\t"
+ "sb\t$0, 0x07c(%0)\n\t"
+ : : "r" (p) );
+ p += 0x080;
+ }
+
+ write_c0_status(flags);
+}
+
+static inline unsigned long get_phys_page (unsigned long addr,
+ struct mm_struct *mm)
+{
+ pgd_t *pgd;
+ pmd_t *pmd;
+ pte_t *pte;
+ unsigned long physpage;
+
+ pgd = pgd_offset(mm, addr);
+ pmd = pmd_offset(pgd, addr);
+ pte = pte_offset(pmd, addr);
+
+ if ((physpage = pte_val(*pte)) & _PAGE_VALID)
+ return KSEG0ADDR(physpage & PAGE_MASK);
+
+ return 0;
+}
+
+static inline void r3k_flush_cache_all(void)
+{
+}
+
+static inline void r3k___flush_cache_all(void)
+{
+ r3k_flush_dcache_range(KSEG0, KSEG0 + dcache_size);
+ r3k_flush_icache_range(KSEG0, KSEG0 + icache_size);
+}
+
+static void r3k_flush_cache_mm(struct mm_struct *mm)
+{
+}
+
+static void r3k_flush_cache_range(struct vm_area_struct *vma,
+ unsigned long start, unsigned long end)
+{
+}
+
+static void r3k_flush_cache_page(struct vm_area_struct *vma, unsigned long page, unsigned long pfn)
+{
+}
+
+static void r3k_flush_data_cache_page(unsigned long addr)
+{
+}
+
+static void r3k_flush_icache_page(struct vm_area_struct *vma, struct page *page)
+{
+ struct mm_struct *mm = vma->vm_mm;
+ unsigned long physpage;
+
+ if (cpu_context(smp_processor_id(), mm) == 0)
+ return;
+
+ if (!(vma->vm_flags & VM_EXEC))
+ return;
+
+#ifdef DEBUG_CACHE
+ printk("cpage[%d,%08lx]", cpu_context(smp_processor_id(), mm), page);
+#endif
+
+ physpage = (unsigned long) page_address(page);
+ if (physpage)
+ r3k_flush_icache_range(physpage, physpage + PAGE_SIZE);
+}
+
+static void r3k_flush_cache_sigtramp(unsigned long addr)
+{
+ unsigned long flags;
+
+#ifdef DEBUG_CACHE
+ printk("csigtramp[%08lx]", addr);
+#endif
+
+ flags = read_c0_status();
+
+ write_c0_status(flags&~ST0_IEC);
+
+ /* Fill the TLB to avoid an exception with caches isolated. */
+ asm ( "lw\t$0, 0x000(%0)\n\t"
+ "lw\t$0, 0x004(%0)\n\t"
+ : : "r" (addr) );
+
+ write_c0_status((ST0_ISC|ST0_SWC|flags)&~ST0_IEC);
+
+ asm ( "sb\t$0, 0x000(%0)\n\t"
+ "sb\t$0, 0x004(%0)\n\t"
+ : : "r" (addr) );
+
+ write_c0_status(flags);
+}
+
+static void r3k_dma_cache_wback_inv(unsigned long start, unsigned long size)
+{
+ /* Catch bad driver code */
+ BUG_ON(size == 0);
+
+ iob();
+ r3k_flush_dcache_range(start, start + size);
+}
+
+void __init ld_mmu_r23000(void)
+{
+ extern void build_clear_page(void);
+ extern void build_copy_page(void);
+
+ r3k_probe_cache();
+
+ flush_cache_all = r3k_flush_cache_all;
+ __flush_cache_all = r3k___flush_cache_all;
+ flush_cache_mm = r3k_flush_cache_mm;
+ flush_cache_range = r3k_flush_cache_range;
+ flush_cache_page = r3k_flush_cache_page;
+ flush_icache_page = r3k_flush_icache_page;
+ flush_icache_range = r3k_flush_icache_range;
+
+ flush_cache_sigtramp = r3k_flush_cache_sigtramp;
+ flush_data_cache_page = r3k_flush_data_cache_page;
+
+ _dma_cache_wback_inv = r3k_dma_cache_wback_inv;
+ _dma_cache_wback = r3k_dma_cache_wback_inv;
+ _dma_cache_inv = r3k_dma_cache_wback_inv;
+
+ printk("Primary instruction cache %ldkB, linesize %ld bytes.\n",
+ icache_size >> 10, icache_lsize);
+ printk("Primary data cache %ldkB, linesize %ld bytes.\n",
+ dcache_size >> 10, dcache_lsize);
+
+ build_clear_page();
+ build_copy_page();
+}
diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
new file mode 100644
index 0000000..a03ebb2
--- /dev/null
+++ b/arch/mips/mm/c-r4k.c
@@ -0,0 +1,1260 @@
+/*
+ * 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) 1996 David S. Miller (dm@engr.sgi.com)
+ * Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Ralf Baechle (ralf@gnu.org)
+ * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/bitops.h>
+
+#include <asm/bcache.h>
+#include <asm/bootinfo.h>
+#include <asm/cacheops.h>
+#include <asm/cpu.h>
+#include <asm/cpu-features.h>
+#include <asm/io.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/r4kcache.h>
+#include <asm/system.h>
+#include <asm/mmu_context.h>
+#include <asm/war.h>
+
+static unsigned long icache_size, dcache_size, scache_size;
+
+/*
+ * Dummy cache handling routines for machines without boardcaches
+ */
+static void no_sc_noop(void) {}
+
+static struct bcache_ops no_sc_ops = {
+ .bc_enable = (void *)no_sc_noop,
+ .bc_disable = (void *)no_sc_noop,
+ .bc_wback_inv = (void *)no_sc_noop,
+ .bc_inv = (void *)no_sc_noop
+};
+
+struct bcache_ops *bcops = &no_sc_ops;
+
+#define cpu_is_r4600_v1_x() ((read_c0_prid() & 0xfffffff0) == 0x2010)
+#define cpu_is_r4600_v2_x() ((read_c0_prid() & 0xfffffff0) == 0x2020)
+
+#define R4600_HIT_CACHEOP_WAR_IMPL \
+do { \
+ if (R4600_V2_HIT_CACHEOP_WAR && cpu_is_r4600_v2_x()) \
+ *(volatile unsigned long *)CKSEG1; \
+ if (R4600_V1_HIT_CACHEOP_WAR) \
+ __asm__ __volatile__("nop;nop;nop;nop"); \
+} while (0)
+
+static void (*r4k_blast_dcache_page)(unsigned long addr);
+
+static inline void r4k_blast_dcache_page_dc32(unsigned long addr)
+{
+ R4600_HIT_CACHEOP_WAR_IMPL;
+ blast_dcache32_page(addr);
+}
+
+static inline void r4k_blast_dcache_page_setup(void)
+{
+ unsigned long dc_lsize = cpu_dcache_line_size();
+
+ if (dc_lsize == 16)
+ r4k_blast_dcache_page = blast_dcache16_page;
+ else if (dc_lsize == 32)
+ r4k_blast_dcache_page = r4k_blast_dcache_page_dc32;
+}
+
+static void (* r4k_blast_dcache_page_indexed)(unsigned long addr);
+
+static inline void r4k_blast_dcache_page_indexed_setup(void)
+{
+ unsigned long dc_lsize = cpu_dcache_line_size();
+
+ if (dc_lsize == 16)
+ r4k_blast_dcache_page_indexed = blast_dcache16_page_indexed;
+ else if (dc_lsize == 32)
+ r4k_blast_dcache_page_indexed = blast_dcache32_page_indexed;
+}
+
+static void (* r4k_blast_dcache)(void);
+
+static inline void r4k_blast_dcache_setup(void)
+{
+ unsigned long dc_lsize = cpu_dcache_line_size();
+
+ if (dc_lsize == 16)
+ r4k_blast_dcache = blast_dcache16;
+ else if (dc_lsize == 32)
+ r4k_blast_dcache = blast_dcache32;
+}
+
+/* force code alignment (used for TX49XX_ICACHE_INDEX_INV_WAR) */
+#define JUMP_TO_ALIGN(order) \
+ __asm__ __volatile__( \
+ "b\t1f\n\t" \
+ ".align\t" #order "\n\t" \
+ "1:\n\t" \
+ )
+#define CACHE32_UNROLL32_ALIGN JUMP_TO_ALIGN(10) /* 32 * 32 = 1024 */
+#define CACHE32_UNROLL32_ALIGN2 JUMP_TO_ALIGN(11)
+
+static inline void blast_r4600_v1_icache32(void)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+ blast_icache32();
+ local_irq_restore(flags);
+}
+
+static inline void tx49_blast_icache32(void)
+{
+ unsigned long start = INDEX_BASE;
+ unsigned long end = start + current_cpu_data.icache.waysize;
+ unsigned long ws_inc = 1UL << current_cpu_data.icache.waybit;
+ unsigned long ws_end = current_cpu_data.icache.ways <<
+ current_cpu_data.icache.waybit;
+ unsigned long ws, addr;
+
+ CACHE32_UNROLL32_ALIGN2;
+ /* I'm in even chunk. blast odd chunks */
+ for (ws = 0; ws < ws_end; ws += ws_inc)
+ for (addr = start + 0x400; addr < end; addr += 0x400 * 2)
+ cache32_unroll32(addr|ws,Index_Invalidate_I);
+ CACHE32_UNROLL32_ALIGN;
+ /* I'm in odd chunk. blast even chunks */
+ for (ws = 0; ws < ws_end; ws += ws_inc)
+ for (addr = start; addr < end; addr += 0x400 * 2)
+ cache32_unroll32(addr|ws,Index_Invalidate_I);
+}
+
+static inline void blast_icache32_r4600_v1_page_indexed(unsigned long page)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+ blast_icache32_page_indexed(page);
+ local_irq_restore(flags);
+}
+
+static inline void tx49_blast_icache32_page_indexed(unsigned long page)
+{
+ unsigned long start = page;
+ unsigned long end = start + PAGE_SIZE;
+ unsigned long ws_inc = 1UL << current_cpu_data.icache.waybit;
+ unsigned long ws_end = current_cpu_data.icache.ways <<
+ current_cpu_data.icache.waybit;
+ unsigned long ws, addr;
+
+ CACHE32_UNROLL32_ALIGN2;
+ /* I'm in even chunk. blast odd chunks */
+ for (ws = 0; ws < ws_end; ws += ws_inc)
+ for (addr = start + 0x400; addr < end; addr += 0x400 * 2)
+ cache32_unroll32(addr|ws,Index_Invalidate_I);
+ CACHE32_UNROLL32_ALIGN;
+ /* I'm in odd chunk. blast even chunks */
+ for (ws = 0; ws < ws_end; ws += ws_inc)
+ for (addr = start; addr < end; addr += 0x400 * 2)
+ cache32_unroll32(addr|ws,Index_Invalidate_I);
+}
+
+static void (* r4k_blast_icache_page)(unsigned long addr);
+
+static inline void r4k_blast_icache_page_setup(void)
+{
+ unsigned long ic_lsize = cpu_icache_line_size();
+
+ if (ic_lsize == 16)
+ r4k_blast_icache_page = blast_icache16_page;
+ else if (ic_lsize == 32)
+ r4k_blast_icache_page = blast_icache32_page;
+ else if (ic_lsize == 64)
+ r4k_blast_icache_page = blast_icache64_page;
+}
+
+
+static void (* r4k_blast_icache_page_indexed)(unsigned long addr);
+
+static inline void r4k_blast_icache_page_indexed_setup(void)
+{
+ unsigned long ic_lsize = cpu_icache_line_size();
+
+ if (ic_lsize == 16)
+ r4k_blast_icache_page_indexed = blast_icache16_page_indexed;
+ else if (ic_lsize == 32) {
+ if (TX49XX_ICACHE_INDEX_INV_WAR)
+ r4k_blast_icache_page_indexed =
+ tx49_blast_icache32_page_indexed;
+ else if (R4600_V1_INDEX_ICACHEOP_WAR && cpu_is_r4600_v1_x())
+ r4k_blast_icache_page_indexed =
+ blast_icache32_r4600_v1_page_indexed;
+ else
+ r4k_blast_icache_page_indexed =
+ blast_icache32_page_indexed;
+ } else if (ic_lsize == 64)
+ r4k_blast_icache_page_indexed = blast_icache64_page_indexed;
+}
+
+static void (* r4k_blast_icache)(void);
+
+static inline void r4k_blast_icache_setup(void)
+{
+ unsigned long ic_lsize = cpu_icache_line_size();
+
+ if (ic_lsize == 16)
+ r4k_blast_icache = blast_icache16;
+ else if (ic_lsize == 32) {
+ if (R4600_V1_INDEX_ICACHEOP_WAR && cpu_is_r4600_v1_x())
+ r4k_blast_icache = blast_r4600_v1_icache32;
+ else if (TX49XX_ICACHE_INDEX_INV_WAR)
+ r4k_blast_icache = tx49_blast_icache32;
+ else
+ r4k_blast_icache = blast_icache32;
+ } else if (ic_lsize == 64)
+ r4k_blast_icache = blast_icache64;
+}
+
+static void (* r4k_blast_scache_page)(unsigned long addr);
+
+static inline void r4k_blast_scache_page_setup(void)
+{
+ unsigned long sc_lsize = cpu_scache_line_size();
+
+ if (sc_lsize == 16)
+ r4k_blast_scache_page = blast_scache16_page;
+ else if (sc_lsize == 32)
+ r4k_blast_scache_page = blast_scache32_page;
+ else if (sc_lsize == 64)
+ r4k_blast_scache_page = blast_scache64_page;
+ else if (sc_lsize == 128)
+ r4k_blast_scache_page = blast_scache128_page;
+}
+
+static void (* r4k_blast_scache_page_indexed)(unsigned long addr);
+
+static inline void r4k_blast_scache_page_indexed_setup(void)
+{
+ unsigned long sc_lsize = cpu_scache_line_size();
+
+ if (sc_lsize == 16)
+ r4k_blast_scache_page_indexed = blast_scache16_page_indexed;
+ else if (sc_lsize == 32)
+ r4k_blast_scache_page_indexed = blast_scache32_page_indexed;
+ else if (sc_lsize == 64)
+ r4k_blast_scache_page_indexed = blast_scache64_page_indexed;
+ else if (sc_lsize == 128)
+ r4k_blast_scache_page_indexed = blast_scache128_page_indexed;
+}
+
+static void (* r4k_blast_scache)(void);
+
+static inline void r4k_blast_scache_setup(void)
+{
+ unsigned long sc_lsize = cpu_scache_line_size();
+
+ if (sc_lsize == 16)
+ r4k_blast_scache = blast_scache16;
+ else if (sc_lsize == 32)
+ r4k_blast_scache = blast_scache32;
+ else if (sc_lsize == 64)
+ r4k_blast_scache = blast_scache64;
+ else if (sc_lsize == 128)
+ r4k_blast_scache = blast_scache128;
+}
+
+/*
+ * This is former mm's flush_cache_all() which really should be
+ * flush_cache_vunmap these days ...
+ */
+static inline void local_r4k_flush_cache_all(void * args)
+{
+ r4k_blast_dcache();
+ r4k_blast_icache();
+}
+
+static void r4k_flush_cache_all(void)
+{
+ if (!cpu_has_dc_aliases)
+ return;
+
+ on_each_cpu(local_r4k_flush_cache_all, NULL, 1, 1);
+}
+
+static inline void local_r4k___flush_cache_all(void * args)
+{
+ r4k_blast_dcache();
+ r4k_blast_icache();
+
+ switch (current_cpu_data.cputype) {
+ case CPU_R4000SC:
+ case CPU_R4000MC:
+ case CPU_R4400SC:
+ case CPU_R4400MC:
+ case CPU_R10000:
+ case CPU_R12000:
+ r4k_blast_scache();
+ }
+}
+
+static void r4k___flush_cache_all(void)
+{
+ on_each_cpu(local_r4k___flush_cache_all, NULL, 1, 1);
+}
+
+static inline void local_r4k_flush_cache_range(void * args)
+{
+ struct vm_area_struct *vma = args;
+ int exec;
+
+ if (!(cpu_context(smp_processor_id(), vma->vm_mm)))
+ return;
+
+ exec = vma->vm_flags & VM_EXEC;
+ if (cpu_has_dc_aliases || exec)
+ r4k_blast_dcache();
+ if (exec)
+ r4k_blast_icache();
+}
+
+static void r4k_flush_cache_range(struct vm_area_struct *vma,
+ unsigned long start, unsigned long end)
+{
+ on_each_cpu(local_r4k_flush_cache_range, vma, 1, 1);
+}
+
+static inline void local_r4k_flush_cache_mm(void * args)
+{
+ struct mm_struct *mm = args;
+
+ if (!cpu_context(smp_processor_id(), mm))
+ return;
+
+ r4k_blast_dcache();
+ r4k_blast_icache();
+
+ /*
+ * Kludge alert. For obscure reasons R4000SC and R4400SC go nuts if we
+ * only flush the primary caches but R10000 and R12000 behave sane ...
+ */
+ if (current_cpu_data.cputype == CPU_R4000SC ||
+ current_cpu_data.cputype == CPU_R4000MC ||
+ current_cpu_data.cputype == CPU_R4400SC ||
+ current_cpu_data.cputype == CPU_R4400MC)
+ r4k_blast_scache();
+}
+
+static void r4k_flush_cache_mm(struct mm_struct *mm)
+{
+ if (!cpu_has_dc_aliases)
+ return;
+
+ on_each_cpu(local_r4k_flush_cache_mm, mm, 1, 1);
+}
+
+struct flush_cache_page_args {
+ struct vm_area_struct *vma;
+ unsigned long page;
+};
+
+static inline void local_r4k_flush_cache_page(void *args)
+{
+ struct flush_cache_page_args *fcp_args = args;
+ struct vm_area_struct *vma = fcp_args->vma;
+ unsigned long page = fcp_args->page;
+ int exec = vma->vm_flags & VM_EXEC;
+ struct mm_struct *mm = vma->vm_mm;
+ pgd_t *pgdp;
+ pmd_t *pmdp;
+ pte_t *ptep;
+
+ page &= PAGE_MASK;
+ pgdp = pgd_offset(mm, page);
+ pmdp = pmd_offset(pgdp, page);
+ ptep = pte_offset(pmdp, page);
+
+ /*
+ * If the page isn't marked valid, the page cannot possibly be
+ * in the cache.
+ */
+ if (!(pte_val(*ptep) & _PAGE_PRESENT))
+ return;
+
+ /*
+ * Doing flushes for another ASID than the current one is
+ * too difficult since stupid R4k caches do a TLB translation
+ * for every cache flush operation. So we do indexed flushes
+ * in that case, which doesn't overly flush the cache too much.
+ */
+ if ((mm == current->active_mm) && (pte_val(*ptep) & _PAGE_VALID)) {
+ if (cpu_has_dc_aliases || (exec && !cpu_has_ic_fills_f_dc)) {
+ r4k_blast_dcache_page(page);
+ if (exec && !cpu_icache_snoops_remote_store)
+ r4k_blast_scache_page(page);
+ }
+ if (exec)
+ r4k_blast_icache_page(page);
+
+ return;
+ }
+
+ /*
+ * Do indexed flush, too much work to get the (possible) TLB refills
+ * to work correctly.
+ */
+ page = INDEX_BASE + (page & (dcache_size - 1));
+ if (cpu_has_dc_aliases || (exec && !cpu_has_ic_fills_f_dc)) {
+ r4k_blast_dcache_page_indexed(page);
+ if (exec && !cpu_icache_snoops_remote_store)
+ r4k_blast_scache_page_indexed(page);
+ }
+ if (exec) {
+ if (cpu_has_vtag_icache) {
+ int cpu = smp_processor_id();
+
+ if (cpu_context(cpu, vma->vm_mm) != 0)
+ drop_mmu_context(vma->vm_mm, cpu);
+ } else
+ r4k_blast_icache_page_indexed(page);
+ }
+}
+
+static void r4k_flush_cache_page(struct vm_area_struct *vma, unsigned long page, unsigned long pfn)
+{
+ struct flush_cache_page_args args;
+
+ /*
+ * If ownes no valid ASID yet, cannot possibly have gotten
+ * this page into the cache.
+ */
+ if (cpu_context(smp_processor_id(), vma->vm_mm) == 0)
+ return;
+
+ args.vma = vma;
+ args.page = page;
+
+ on_each_cpu(local_r4k_flush_cache_page, &args, 1, 1);
+}
+
+static inline void local_r4k_flush_data_cache_page(void * addr)
+{
+ r4k_blast_dcache_page((unsigned long) addr);
+}
+
+static void r4k_flush_data_cache_page(unsigned long addr)
+{
+ on_each_cpu(local_r4k_flush_data_cache_page, (void *) addr, 1, 1);
+}
+
+struct flush_icache_range_args {
+ unsigned long start;
+ unsigned long end;
+};
+
+static inline void local_r4k_flush_icache_range(void *args)
+{
+ struct flush_icache_range_args *fir_args = args;
+ unsigned long dc_lsize = current_cpu_data.dcache.linesz;
+ unsigned long ic_lsize = current_cpu_data.icache.linesz;
+ unsigned long sc_lsize = current_cpu_data.scache.linesz;
+ unsigned long start = fir_args->start;
+ unsigned long end = fir_args->end;
+ unsigned long addr, aend;
+
+ if (!cpu_has_ic_fills_f_dc) {
+ if (end - start > dcache_size) {
+ r4k_blast_dcache();
+ } else {
+ addr = start & ~(dc_lsize - 1);
+ aend = (end - 1) & ~(dc_lsize - 1);
+
+ while (1) {
+ /* Hit_Writeback_Inv_D */
+ protected_writeback_dcache_line(addr);
+ if (addr == aend)
+ break;
+ addr += dc_lsize;
+ }
+ }
+
+ if (!cpu_icache_snoops_remote_store) {
+ if (end - start > scache_size) {
+ r4k_blast_scache();
+ } else {
+ addr = start & ~(sc_lsize - 1);
+ aend = (end - 1) & ~(sc_lsize - 1);
+
+ while (1) {
+ /* Hit_Writeback_Inv_D */
+ protected_writeback_scache_line(addr);
+ if (addr == aend)
+ break;
+ addr += sc_lsize;
+ }
+ }
+ }
+ }
+
+ if (end - start > icache_size)
+ r4k_blast_icache();
+ else {
+ addr = start & ~(ic_lsize - 1);
+ aend = (end - 1) & ~(ic_lsize - 1);
+ while (1) {
+ /* Hit_Invalidate_I */
+ protected_flush_icache_line(addr);
+ if (addr == aend)
+ break;
+ addr += ic_lsize;
+ }
+ }
+}
+
+static void r4k_flush_icache_range(unsigned long start, unsigned long end)
+{
+ struct flush_icache_range_args args;
+
+ args.start = start;
+ args.end = end;
+
+ on_each_cpu(local_r4k_flush_icache_range, &args, 1, 1);
+}
+
+/*
+ * Ok, this seriously sucks. We use them to flush a user page but don't
+ * know the virtual address, so we have to blast away the whole icache
+ * which is significantly more expensive than the real thing. Otoh we at
+ * least know the kernel address of the page so we can flush it
+ * selectivly.
+ */
+
+struct flush_icache_page_args {
+ struct vm_area_struct *vma;
+ struct page *page;
+};
+
+static inline void local_r4k_flush_icache_page(void *args)
+{
+ struct flush_icache_page_args *fip_args = args;
+ struct vm_area_struct *vma = fip_args->vma;
+ struct page *page = fip_args->page;
+
+ /*
+ * Tricky ... Because we don't know the virtual address we've got the
+ * choice of either invalidating the entire primary and secondary
+ * caches or invalidating the secondary caches also. With the subset
+ * enforcment on R4000SC, R4400SC, R10000 and R12000 invalidating the
+ * secondary cache will result in any entries in the primary caches
+ * also getting invalidated which hopefully is a bit more economical.
+ */
+ if (cpu_has_subset_pcaches) {
+ unsigned long addr = (unsigned long) page_address(page);
+
+ r4k_blast_scache_page(addr);
+ ClearPageDcacheDirty(page);
+
+ return;
+ }
+
+ if (!cpu_has_ic_fills_f_dc) {
+ unsigned long addr = (unsigned long) page_address(page);
+ r4k_blast_dcache_page(addr);
+ if (!cpu_icache_snoops_remote_store)
+ r4k_blast_scache_page(addr);
+ ClearPageDcacheDirty(page);
+ }
+
+ /*
+ * We're not sure of the virtual address(es) involved here, so
+ * we have to flush the entire I-cache.
+ */
+ if (cpu_has_vtag_icache) {
+ int cpu = smp_processor_id();
+
+ if (cpu_context(cpu, vma->vm_mm) != 0)
+ drop_mmu_context(vma->vm_mm, cpu);
+ } else
+ r4k_blast_icache();
+}
+
+static void r4k_flush_icache_page(struct vm_area_struct *vma,
+ struct page *page)
+{
+ struct flush_icache_page_args args;
+
+ /*
+ * If there's no context yet, or the page isn't executable, no I-cache
+ * flush is needed.
+ */
+ if (!(vma->vm_flags & VM_EXEC))
+ return;
+
+ args.vma = vma;
+ args.page = page;
+
+ on_each_cpu(local_r4k_flush_icache_page, &args, 1, 1);
+}
+
+
+#ifdef CONFIG_DMA_NONCOHERENT
+
+static void r4k_dma_cache_wback_inv(unsigned long addr, unsigned long size)
+{
+ unsigned long end, a;
+
+ /* Catch bad driver code */
+ BUG_ON(size == 0);
+
+ if (cpu_has_subset_pcaches) {
+ unsigned long sc_lsize = current_cpu_data.scache.linesz;
+
+ if (size >= scache_size) {
+ r4k_blast_scache();
+ return;
+ }
+
+ a = addr & ~(sc_lsize - 1);
+ end = (addr + size - 1) & ~(sc_lsize - 1);
+ while (1) {
+ flush_scache_line(a); /* Hit_Writeback_Inv_SD */
+ if (a == end)
+ break;
+ a += sc_lsize;
+ }
+ return;
+ }
+
+ /*
+ * Either no secondary cache or the available caches don't have the
+ * subset property so we have to flush the primary caches
+ * explicitly
+ */
+ if (size >= dcache_size) {
+ r4k_blast_dcache();
+ } else {
+ unsigned long dc_lsize = current_cpu_data.dcache.linesz;
+
+ R4600_HIT_CACHEOP_WAR_IMPL;
+ a = addr & ~(dc_lsize - 1);
+ end = (addr + size - 1) & ~(dc_lsize - 1);
+ while (1) {
+ flush_dcache_line(a); /* Hit_Writeback_Inv_D */
+ if (a == end)
+ break;
+ a += dc_lsize;
+ }
+ }
+
+ bc_wback_inv(addr, size);
+}
+
+static void r4k_dma_cache_inv(unsigned long addr, unsigned long size)
+{
+ unsigned long end, a;
+
+ /* Catch bad driver code */
+ BUG_ON(size == 0);
+
+ if (cpu_has_subset_pcaches) {
+ unsigned long sc_lsize = current_cpu_data.scache.linesz;
+
+ if (size >= scache_size) {
+ r4k_blast_scache();
+ return;
+ }
+
+ a = addr & ~(sc_lsize - 1);
+ end = (addr + size - 1) & ~(sc_lsize - 1);
+ while (1) {
+ flush_scache_line(a); /* Hit_Writeback_Inv_SD */
+ if (a == end)
+ break;
+ a += sc_lsize;
+ }
+ return;
+ }
+
+ if (size >= dcache_size) {
+ r4k_blast_dcache();
+ } else {
+ unsigned long dc_lsize = current_cpu_data.dcache.linesz;
+
+ R4600_HIT_CACHEOP_WAR_IMPL;
+ a = addr & ~(dc_lsize - 1);
+ end = (addr + size - 1) & ~(dc_lsize - 1);
+ while (1) {
+ flush_dcache_line(a); /* Hit_Writeback_Inv_D */
+ if (a == end)
+ break;
+ a += dc_lsize;
+ }
+ }
+
+ bc_inv(addr, size);
+}
+#endif /* CONFIG_DMA_NONCOHERENT */
+
+/*
+ * While we're protected against bad userland addresses we don't care
+ * very much about what happens in that case. Usually a segmentation
+ * fault will dump the process later on anyway ...
+ */
+static void local_r4k_flush_cache_sigtramp(void * arg)
+{
+ unsigned long ic_lsize = current_cpu_data.icache.linesz;
+ unsigned long dc_lsize = current_cpu_data.dcache.linesz;
+ unsigned long sc_lsize = current_cpu_data.scache.linesz;
+ unsigned long addr = (unsigned long) arg;
+
+ R4600_HIT_CACHEOP_WAR_IMPL;
+ protected_writeback_dcache_line(addr & ~(dc_lsize - 1));
+ if (!cpu_icache_snoops_remote_store)
+ protected_writeback_scache_line(addr & ~(sc_lsize - 1));
+ protected_flush_icache_line(addr & ~(ic_lsize - 1));
+ if (MIPS4K_ICACHE_REFILL_WAR) {
+ __asm__ __volatile__ (
+ ".set push\n\t"
+ ".set noat\n\t"
+ ".set mips3\n\t"
+#ifdef CONFIG_MIPS32
+ "la $at,1f\n\t"
+#endif
+#ifdef CONFIG_MIPS64
+ "dla $at,1f\n\t"
+#endif
+ "cache %0,($at)\n\t"
+ "nop; nop; nop\n"
+ "1:\n\t"
+ ".set pop"
+ :
+ : "i" (Hit_Invalidate_I));
+ }
+ if (MIPS_CACHE_SYNC_WAR)
+ __asm__ __volatile__ ("sync");
+}
+
+static void r4k_flush_cache_sigtramp(unsigned long addr)
+{
+ on_each_cpu(local_r4k_flush_cache_sigtramp, (void *) addr, 1, 1);
+}
+
+static void r4k_flush_icache_all(void)
+{
+ if (cpu_has_vtag_icache)
+ r4k_blast_icache();
+}
+
+static inline void rm7k_erratum31(void)
+{
+ const unsigned long ic_lsize = 32;
+ unsigned long addr;
+
+ /* RM7000 erratum #31. The icache is screwed at startup. */
+ write_c0_taglo(0);
+ write_c0_taghi(0);
+
+ for (addr = INDEX_BASE; addr <= INDEX_BASE + 4096; addr += ic_lsize) {
+ __asm__ __volatile__ (
+ ".set noreorder\n\t"
+ ".set mips3\n\t"
+ "cache\t%1, 0(%0)\n\t"
+ "cache\t%1, 0x1000(%0)\n\t"
+ "cache\t%1, 0x2000(%0)\n\t"
+ "cache\t%1, 0x3000(%0)\n\t"
+ "cache\t%2, 0(%0)\n\t"
+ "cache\t%2, 0x1000(%0)\n\t"
+ "cache\t%2, 0x2000(%0)\n\t"
+ "cache\t%2, 0x3000(%0)\n\t"
+ "cache\t%1, 0(%0)\n\t"
+ "cache\t%1, 0x1000(%0)\n\t"
+ "cache\t%1, 0x2000(%0)\n\t"
+ "cache\t%1, 0x3000(%0)\n\t"
+ ".set\tmips0\n\t"
+ ".set\treorder\n\t"
+ :
+ : "r" (addr), "i" (Index_Store_Tag_I), "i" (Fill));
+ }
+}
+
+static char *way_string[] __initdata = { NULL, "direct mapped", "2-way",
+ "3-way", "4-way", "5-way", "6-way", "7-way", "8-way"
+};
+
+static void __init probe_pcache(void)
+{
+ struct cpuinfo_mips *c = ¤t_cpu_data;
+ unsigned int config = read_c0_config();
+ unsigned int prid = read_c0_prid();
+ unsigned long config1;
+ unsigned int lsize;
+
+ switch (c->cputype) {
+ case CPU_R4600: /* QED style two way caches? */
+ case CPU_R4700:
+ case CPU_R5000:
+ case CPU_NEVADA:
+ icache_size = 1 << (12 + ((config & CONF_IC) >> 9));
+ c->icache.linesz = 16 << ((config & CONF_IB) >> 5);
+ c->icache.ways = 2;
+ c->icache.waybit = ffs(icache_size/2) - 1;
+
+ dcache_size = 1 << (12 + ((config & CONF_DC) >> 6));
+ c->dcache.linesz = 16 << ((config & CONF_DB) >> 4);
+ c->dcache.ways = 2;
+ c->dcache.waybit= ffs(dcache_size/2) - 1;
+
+ c->options |= MIPS_CPU_CACHE_CDEX_P;
+ break;
+
+ case CPU_R5432:
+ case CPU_R5500:
+ icache_size = 1 << (12 + ((config & CONF_IC) >> 9));
+ c->icache.linesz = 16 << ((config & CONF_IB) >> 5);
+ c->icache.ways = 2;
+ c->icache.waybit= 0;
+
+ dcache_size = 1 << (12 + ((config & CONF_DC) >> 6));
+ c->dcache.linesz = 16 << ((config & CONF_DB) >> 4);
+ c->dcache.ways = 2;
+ c->dcache.waybit = 0;
+
+ c->options |= MIPS_CPU_CACHE_CDEX_P;
+ break;
+
+ case CPU_TX49XX:
+ icache_size = 1 << (12 + ((config & CONF_IC) >> 9));
+ c->icache.linesz = 16 << ((config & CONF_IB) >> 5);
+ c->icache.ways = 4;
+ c->icache.waybit= 0;
+
+ dcache_size = 1 << (12 + ((config & CONF_DC) >> 6));
+ c->dcache.linesz = 16 << ((config & CONF_DB) >> 4);
+ c->dcache.ways = 4;
+ c->dcache.waybit = 0;
+
+ c->options |= MIPS_CPU_CACHE_CDEX_P;
+ break;
+
+ case CPU_R4000PC:
+ case CPU_R4000SC:
+ case CPU_R4000MC:
+ case CPU_R4400PC:
+ case CPU_R4400SC:
+ case CPU_R4400MC:
+ case CPU_R4300:
+ icache_size = 1 << (12 + ((config & CONF_IC) >> 9));
+ c->icache.linesz = 16 << ((config & CONF_IB) >> 5);
+ c->icache.ways = 1;
+ c->icache.waybit = 0; /* doesn't matter */
+
+ dcache_size = 1 << (12 + ((config & CONF_DC) >> 6));
+ c->dcache.linesz = 16 << ((config & CONF_DB) >> 4);
+ c->dcache.ways = 1;
+ c->dcache.waybit = 0; /* does not matter */
+
+ c->options |= MIPS_CPU_CACHE_CDEX_P;
+ break;
+
+ case CPU_R10000:
+ case CPU_R12000:
+ icache_size = 1 << (12 + ((config & R10K_CONF_IC) >> 29));
+ c->icache.linesz = 64;
+ c->icache.ways = 2;
+ c->icache.waybit = 0;
+
+ dcache_size = 1 << (12 + ((config & R10K_CONF_DC) >> 26));
+ c->dcache.linesz = 32;
+ c->dcache.ways = 2;
+ c->dcache.waybit = 0;
+
+ c->options |= MIPS_CPU_PREFETCH;
+ break;
+
+ case CPU_VR4133:
+ write_c0_config(config & ~CONF_EB);
+ case CPU_VR4131:
+ /* Workaround for cache instruction bug of VR4131 */
+ if (c->processor_id == 0x0c80U || c->processor_id == 0x0c81U ||
+ c->processor_id == 0x0c82U) {
+ config &= ~0x00000030U;
+ config |= 0x00410000U;
+ write_c0_config(config);
+ }
+ icache_size = 1 << (10 + ((config & CONF_IC) >> 9));
+ c->icache.linesz = 16 << ((config & CONF_IB) >> 5);
+ c->icache.ways = 2;
+ c->icache.waybit = ffs(icache_size/2) - 1;
+
+ dcache_size = 1 << (10 + ((config & CONF_DC) >> 6));
+ c->dcache.linesz = 16 << ((config & CONF_DB) >> 4);
+ c->dcache.ways = 2;
+ c->dcache.waybit = ffs(dcache_size/2) - 1;
+
+ c->options |= MIPS_CPU_CACHE_CDEX_P;
+ break;
+
+ case CPU_VR41XX:
+ case CPU_VR4111:
+ case CPU_VR4121:
+ case CPU_VR4122:
+ case CPU_VR4181:
+ case CPU_VR4181A:
+ icache_size = 1 << (10 + ((config & CONF_IC) >> 9));
+ c->icache.linesz = 16 << ((config & CONF_IB) >> 5);
+ c->icache.ways = 1;
+ c->icache.waybit = 0; /* doesn't matter */
+
+ dcache_size = 1 << (10 + ((config & CONF_DC) >> 6));
+ c->dcache.linesz = 16 << ((config & CONF_DB) >> 4);
+ c->dcache.ways = 1;
+ c->dcache.waybit = 0; /* does not matter */
+
+ c->options |= MIPS_CPU_CACHE_CDEX_P;
+ break;
+
+ case CPU_RM7000:
+ rm7k_erratum31();
+
+ case CPU_RM9000:
+ icache_size = 1 << (12 + ((config & CONF_IC) >> 9));
+ c->icache.linesz = 16 << ((config & CONF_IB) >> 5);
+ c->icache.ways = 4;
+ c->icache.waybit = ffs(icache_size / c->icache.ways) - 1;
+
+ dcache_size = 1 << (12 + ((config & CONF_DC) >> 6));
+ c->dcache.linesz = 16 << ((config & CONF_DB) >> 4);
+ c->dcache.ways = 4;
+ c->dcache.waybit = ffs(dcache_size / c->dcache.ways) - 1;
+
+#if !defined(CONFIG_SMP) || !defined(RM9000_CDEX_SMP_WAR)
+ c->options |= MIPS_CPU_CACHE_CDEX_P;
+#endif
+ c->options |= MIPS_CPU_PREFETCH;
+ break;
+
+ default:
+ if (!(config & MIPS_CONF_M))
+ panic("Don't know how to probe P-caches on this cpu.");
+
+ /*
+ * So we seem to be a MIPS32 or MIPS64 CPU
+ * So let's probe the I-cache ...
+ */
+ config1 = read_c0_config1();
+
+ if ((lsize = ((config1 >> 19) & 7)))
+ c->icache.linesz = 2 << lsize;
+ else
+ c->icache.linesz = lsize;
+ c->icache.sets = 64 << ((config1 >> 22) & 7);
+ c->icache.ways = 1 + ((config1 >> 16) & 7);
+
+ icache_size = c->icache.sets *
+ c->icache.ways *
+ c->icache.linesz;
+ c->icache.waybit = ffs(icache_size/c->icache.ways) - 1;
+
+ if (config & 0x8) /* VI bit */
+ c->icache.flags |= MIPS_CACHE_VTAG;
+
+ /*
+ * Now probe the MIPS32 / MIPS64 data cache.
+ */
+ c->dcache.flags = 0;
+
+ if ((lsize = ((config1 >> 10) & 7)))
+ c->dcache.linesz = 2 << lsize;
+ else
+ c->dcache.linesz= lsize;
+ c->dcache.sets = 64 << ((config1 >> 13) & 7);
+ c->dcache.ways = 1 + ((config1 >> 7) & 7);
+
+ dcache_size = c->dcache.sets *
+ c->dcache.ways *
+ c->dcache.linesz;
+ c->dcache.waybit = ffs(dcache_size/c->dcache.ways) - 1;
+
+ c->options |= MIPS_CPU_PREFETCH;
+ break;
+ }
+
+ /*
+ * Processor configuration sanity check for the R4000SC erratum
+ * #5. With page sizes larger than 32kB there is no possibility
+ * to get a VCE exception anymore so we don't care about this
+ * misconfiguration. The case is rather theoretical anyway;
+ * presumably no vendor is shipping his hardware in the "bad"
+ * configuration.
+ */
+ if ((prid & 0xff00) == PRID_IMP_R4000 && (prid & 0xff) < 0x40 &&
+ !(config & CONF_SC) && c->icache.linesz != 16 &&
+ PAGE_SIZE <= 0x8000)
+ panic("Improper R4000SC processor configuration detected");
+
+ /* compute a couple of other cache variables */
+ c->icache.waysize = icache_size / c->icache.ways;
+ c->dcache.waysize = dcache_size / c->dcache.ways;
+
+ c->icache.sets = icache_size / (c->icache.linesz * c->icache.ways);
+ c->dcache.sets = dcache_size / (c->dcache.linesz * c->dcache.ways);
+
+ /*
+ * R10000 and R12000 P-caches are odd in a positive way. They're 32kB
+ * 2-way virtually indexed so normally would suffer from aliases. So
+ * normally they'd suffer from aliases but magic in the hardware deals
+ * with that for us so we don't need to take care ourselves.
+ */
+ if (c->cputype != CPU_R10000 && c->cputype != CPU_R12000)
+ if (c->dcache.waysize > PAGE_SIZE)
+ c->dcache.flags |= MIPS_CACHE_ALIASES;
+
+ switch (c->cputype) {
+ case CPU_20KC:
+ /*
+ * Some older 20Kc chips doesn't have the 'VI' bit in
+ * the config register.
+ */
+ c->icache.flags |= MIPS_CACHE_VTAG;
+ break;
+
+ case CPU_AU1500:
+ c->icache.flags |= MIPS_CACHE_IC_F_DC;
+ break;
+ }
+
+ printk("Primary instruction cache %ldkB, %s, %s, linesize %d bytes.\n",
+ icache_size >> 10,
+ cpu_has_vtag_icache ? "virtually tagged" : "physically tagged",
+ way_string[c->icache.ways], c->icache.linesz);
+
+ printk("Primary data cache %ldkB, %s, linesize %d bytes.\n",
+ dcache_size >> 10, way_string[c->dcache.ways], c->dcache.linesz);
+}
+
+/*
+ * If you even _breathe_ on this function, look at the gcc output and make sure
+ * it does not pop things on and off the stack for the cache sizing loop that
+ * executes in KSEG1 space or else you will crash and burn badly. You have
+ * been warned.
+ */
+static int __init probe_scache(void)
+{
+ extern unsigned long stext;
+ unsigned long flags, addr, begin, end, pow2;
+ unsigned int config = read_c0_config();
+ struct cpuinfo_mips *c = ¤t_cpu_data;
+ int tmp;
+
+ if (config & CONF_SC)
+ return 0;
+
+ begin = (unsigned long) &stext;
+ begin &= ~((4 * 1024 * 1024) - 1);
+ end = begin + (4 * 1024 * 1024);
+
+ /*
+ * This is such a bitch, you'd think they would make it easy to do
+ * this. Away you daemons of stupidity!
+ */
+ local_irq_save(flags);
+
+ /* Fill each size-multiple cache line with a valid tag. */
+ pow2 = (64 * 1024);
+ for (addr = begin; addr < end; addr = (begin + pow2)) {
+ unsigned long *p = (unsigned long *) addr;
+ __asm__ __volatile__("nop" : : "r" (*p)); /* whee... */
+ pow2 <<= 1;
+ }
+
+ /* Load first line with zero (therefore invalid) tag. */
+ write_c0_taglo(0);
+ write_c0_taghi(0);
+ __asm__ __volatile__("nop; nop; nop; nop;"); /* avoid the hazard */
+ cache_op(Index_Store_Tag_I, begin);
+ cache_op(Index_Store_Tag_D, begin);
+ cache_op(Index_Store_Tag_SD, begin);
+
+ /* Now search for the wrap around point. */
+ pow2 = (128 * 1024);
+ tmp = 0;
+ for (addr = begin + (128 * 1024); addr < end; addr = begin + pow2) {
+ cache_op(Index_Load_Tag_SD, addr);
+ __asm__ __volatile__("nop; nop; nop; nop;"); /* hazard... */
+ if (!read_c0_taglo())
+ break;
+ pow2 <<= 1;
+ }
+ local_irq_restore(flags);
+ addr -= begin;
+
+ scache_size = addr;
+ c->scache.linesz = 16 << ((config & R4K_CONF_SB) >> 22);
+ c->scache.ways = 1;
+ c->dcache.waybit = 0; /* does not matter */
+
+ return 1;
+}
+
+typedef int (*probe_func_t)(unsigned long);
+extern int r5k_sc_init(void);
+extern int rm7k_sc_init(void);
+
+static void __init setup_scache(void)
+{
+ struct cpuinfo_mips *c = ¤t_cpu_data;
+ unsigned int config = read_c0_config();
+ probe_func_t probe_scache_kseg1;
+ int sc_present = 0;
+
+ /*
+ * Do the probing thing on R4000SC and R4400SC processors. Other
+ * processors don't have a S-cache that would be relevant to the
+ * Linux memory managment.
+ */
+ switch (c->cputype) {
+ case CPU_R4000SC:
+ case CPU_R4000MC:
+ case CPU_R4400SC:
+ case CPU_R4400MC:
+ probe_scache_kseg1 = (probe_func_t) (CKSEG1ADDR(&probe_scache));
+ sc_present = probe_scache_kseg1(config);
+ if (sc_present)
+ c->options |= MIPS_CPU_CACHE_CDEX_S;
+ break;
+
+ case CPU_R10000:
+ case CPU_R12000:
+ scache_size = 0x80000 << ((config & R10K_CONF_SS) >> 16);
+ c->scache.linesz = 64 << ((config >> 13) & 1);
+ c->scache.ways = 2;
+ c->scache.waybit= 0;
+ sc_present = 1;
+ break;
+
+ case CPU_R5000:
+ case CPU_NEVADA:
+#ifdef CONFIG_R5000_CPU_SCACHE
+ r5k_sc_init();
+#endif
+ return;
+
+ case CPU_RM7000:
+ case CPU_RM9000:
+#ifdef CONFIG_RM7000_CPU_SCACHE
+ rm7k_sc_init();
+#endif
+ return;
+
+ default:
+ sc_present = 0;
+ }
+
+ if (!sc_present)
+ return;
+
+ if ((c->isa_level == MIPS_CPU_ISA_M32 ||
+ c->isa_level == MIPS_CPU_ISA_M64) &&
+ !(c->scache.flags & MIPS_CACHE_NOT_PRESENT))
+ panic("Dunno how to handle MIPS32 / MIPS64 second level cache");
+
+ /* compute a couple of other cache variables */
+ c->scache.waysize = scache_size / c->scache.ways;
+
+ c->scache.sets = scache_size / (c->scache.linesz * c->scache.ways);
+
+ printk("Unified secondary cache %ldkB %s, linesize %d bytes.\n",
+ scache_size >> 10, way_string[c->scache.ways], c->scache.linesz);
+
+ c->options |= MIPS_CPU_SUBSET_CACHES;
+}
+
+static inline void coherency_setup(void)
+{
+ change_c0_config(CONF_CM_CMASK, CONF_CM_DEFAULT);
+
+ /*
+ * c0_status.cu=0 specifies that updates by the sc instruction use
+ * the coherency mode specified by the TLB; 1 means cachable
+ * coherent update on write will be used. Not all processors have
+ * this bit and; some wire it to zero, others like Toshiba had the
+ * silly idea of putting something else there ...
+ */
+ switch (current_cpu_data.cputype) {
+ case CPU_R4000PC:
+ case CPU_R4000SC:
+ case CPU_R4000MC:
+ case CPU_R4400PC:
+ case CPU_R4400SC:
+ case CPU_R4400MC:
+ clear_c0_config(CONF_CU);
+ break;
+ }
+}
+
+void __init ld_mmu_r4xx0(void)
+{
+ extern void build_clear_page(void);
+ extern void build_copy_page(void);
+ extern char except_vec2_generic;
+ struct cpuinfo_mips *c = ¤t_cpu_data;
+
+ /* Default cache error handler for R4000 and R5000 family */
+ memcpy((void *)(CAC_BASE + 0x100), &except_vec2_generic, 0x80);
+ memcpy((void *)(UNCAC_BASE + 0x100), &except_vec2_generic, 0x80);
+
+ probe_pcache();
+ setup_scache();
+
+ if (c->dcache.sets * c->dcache.ways > PAGE_SIZE)
+ c->dcache.flags |= MIPS_CACHE_ALIASES;
+
+ r4k_blast_dcache_page_setup();
+ r4k_blast_dcache_page_indexed_setup();
+ r4k_blast_dcache_setup();
+ r4k_blast_icache_page_setup();
+ r4k_blast_icache_page_indexed_setup();
+ r4k_blast_icache_setup();
+ r4k_blast_scache_page_setup();
+ r4k_blast_scache_page_indexed_setup();
+ r4k_blast_scache_setup();
+
+ /*
+ * Some MIPS32 and MIPS64 processors have physically indexed caches.
+ * This code supports virtually indexed processors and will be
+ * unnecessarily inefficient on physically indexed processors.
+ */
+ shm_align_mask = max_t( unsigned long,
+ c->dcache.sets * c->dcache.linesz - 1,
+ PAGE_SIZE - 1);
+
+ flush_cache_all = r4k_flush_cache_all;
+ __flush_cache_all = r4k___flush_cache_all;
+ flush_cache_mm = r4k_flush_cache_mm;
+ flush_cache_page = r4k_flush_cache_page;
+ flush_icache_page = r4k_flush_icache_page;
+ flush_cache_range = r4k_flush_cache_range;
+
+ flush_cache_sigtramp = r4k_flush_cache_sigtramp;
+ flush_icache_all = r4k_flush_icache_all;
+ flush_data_cache_page = r4k_flush_data_cache_page;
+ flush_icache_range = r4k_flush_icache_range;
+
+#ifdef CONFIG_DMA_NONCOHERENT
+ _dma_cache_wback_inv = r4k_dma_cache_wback_inv;
+ _dma_cache_wback = r4k_dma_cache_wback_inv;
+ _dma_cache_inv = r4k_dma_cache_inv;
+#endif
+
+ __flush_cache_all();
+ coherency_setup();
+
+ build_clear_page();
+ build_copy_page();
+}
diff --git a/arch/mips/mm/c-sb1.c b/arch/mips/mm/c-sb1.c
new file mode 100644
index 0000000..ab30afd
--- /dev/null
+++ b/arch/mips/mm/c-sb1.c
@@ -0,0 +1,558 @@
+/*
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ * Copyright (C) 1997, 2001 Ralf Baechle (ralf@gnu.org)
+ * Copyright (C) 2000, 2001, 2002, 2003 Broadcom Corporation
+ * Copyright (C) 2004 Maciej W. Rozycki
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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 <linux/config.h>
+#include <linux/init.h>
+
+#include <asm/asm.h>
+#include <asm/bootinfo.h>
+#include <asm/cacheops.h>
+#include <asm/cpu.h>
+#include <asm/mipsregs.h>
+#include <asm/mmu_context.h>
+#include <asm/uaccess.h>
+
+extern void sb1_dma_init(void);
+
+/* These are probed at ld_mmu time */
+static unsigned long icache_size;
+static unsigned long dcache_size;
+
+static unsigned short icache_line_size;
+static unsigned short dcache_line_size;
+
+static unsigned int icache_index_mask;
+static unsigned int dcache_index_mask;
+
+static unsigned short icache_assoc;
+static unsigned short dcache_assoc;
+
+static unsigned short icache_sets;
+static unsigned short dcache_sets;
+
+static unsigned int icache_range_cutoff;
+static unsigned int dcache_range_cutoff;
+
+/*
+ * The dcache is fully coherent to the system, with one
+ * big caveat: the instruction stream. In other words,
+ * if we miss in the icache, and have dirty data in the
+ * L1 dcache, then we'll go out to memory (or the L2) and
+ * get the not-as-recent data.
+ *
+ * So the only time we have to flush the dcache is when
+ * we're flushing the icache. Since the L2 is fully
+ * coherent to everything, including I/O, we never have
+ * to flush it
+ */
+
+#define cache_set_op(op, addr) \
+ __asm__ __volatile__( \
+ " .set noreorder \n" \
+ " .set mips64\n\t \n" \
+ " cache %0, (0<<13)(%1) \n" \
+ " cache %0, (1<<13)(%1) \n" \
+ " cache %0, (2<<13)(%1) \n" \
+ " cache %0, (3<<13)(%1) \n" \
+ " .set mips0 \n" \
+ " .set reorder" \
+ : \
+ : "i" (op), "r" (addr))
+
+#define sync() \
+ __asm__ __volatile( \
+ " .set mips64\n\t \n" \
+ " sync \n" \
+ " .set mips0")
+
+#define mispredict() \
+ __asm__ __volatile__( \
+ " bnezl $0, 1f \n" /* Force mispredict */ \
+ "1: \n");
+
+/*
+ * Writeback and invalidate the entire dcache
+ */
+static inline void __sb1_writeback_inv_dcache_all(void)
+{
+ unsigned long addr = 0;
+
+ while (addr < dcache_line_size * dcache_sets) {
+ cache_set_op(Index_Writeback_Inv_D, addr);
+ addr += dcache_line_size;
+ }
+}
+
+/*
+ * Writeback and invalidate a range of the dcache. The addresses are
+ * virtual, and since we're using index ops and bit 12 is part of both
+ * the virtual frame and physical index, we have to clear both sets
+ * (bit 12 set and cleared).
+ */
+static inline void __sb1_writeback_inv_dcache_range(unsigned long start,
+ unsigned long end)
+{
+ unsigned long index;
+
+ start &= ~(dcache_line_size - 1);
+ end = (end + dcache_line_size - 1) & ~(dcache_line_size - 1);
+
+ while (start != end) {
+ index = start & dcache_index_mask;
+ cache_set_op(Index_Writeback_Inv_D, index);
+ cache_set_op(Index_Writeback_Inv_D, index ^ (1<<12));
+ start += dcache_line_size;
+ }
+ sync();
+}
+
+/*
+ * Writeback and invalidate a range of the dcache. With physical
+ * addresseses, we don't have to worry about possible bit 12 aliasing.
+ * XXXKW is it worth turning on KX and using hit ops with xkphys?
+ */
+static inline void __sb1_writeback_inv_dcache_phys_range(unsigned long start,
+ unsigned long end)
+{
+ start &= ~(dcache_line_size - 1);
+ end = (end + dcache_line_size - 1) & ~(dcache_line_size - 1);
+
+ while (start != end) {
+ cache_set_op(Index_Writeback_Inv_D, start & dcache_index_mask);
+ start += dcache_line_size;
+ }
+ sync();
+}
+
+
+/*
+ * Invalidate the entire icache
+ */
+static inline void __sb1_flush_icache_all(void)
+{
+ unsigned long addr = 0;
+
+ while (addr < icache_line_size * icache_sets) {
+ cache_set_op(Index_Invalidate_I, addr);
+ addr += icache_line_size;
+ }
+}
+
+/*
+ * Flush the icache for a given physical page. Need to writeback the
+ * dcache first, then invalidate the icache. If the page isn't
+ * executable, nothing is required.
+ */
+static void local_sb1_flush_cache_page(struct vm_area_struct *vma, unsigned long addr, unsigned long pfn)
+{
+ int cpu = smp_processor_id();
+
+#ifndef CONFIG_SMP
+ if (!(vma->vm_flags & VM_EXEC))
+ return;
+#endif
+
+ __sb1_writeback_inv_dcache_range(addr, addr + PAGE_SIZE);
+
+ /*
+ * Bumping the ASID is probably cheaper than the flush ...
+ */
+ if (cpu_context(cpu, vma->vm_mm) != 0)
+ drop_mmu_context(vma->vm_mm, cpu);
+}
+
+#ifdef CONFIG_SMP
+struct flush_cache_page_args {
+ struct vm_area_struct *vma;
+ unsigned long addr;
+ unsigned long pfn;
+};
+
+static void sb1_flush_cache_page_ipi(void *info)
+{
+ struct flush_cache_page_args *args = info;
+
+ local_sb1_flush_cache_page(args->vma, args->addr, args->pfn);
+}
+
+/* Dirty dcache could be on another CPU, so do the IPIs */
+static void sb1_flush_cache_page(struct vm_area_struct *vma, unsigned long addr, unsigned long pfn)
+{
+ struct flush_cache_page_args args;
+
+ if (!(vma->vm_flags & VM_EXEC))
+ return;
+
+ addr &= PAGE_MASK;
+ args.vma = vma;
+ args.addr = addr;
+ args.pfn = pfn;
+ on_each_cpu(sb1_flush_cache_page_ipi, (void *) &args, 1, 1);
+}
+#else
+void sb1_flush_cache_page(struct vm_area_struct *vma, unsigned long addr, unsigned long pfn)
+ __attribute__((alias("local_sb1_flush_cache_page")));
+#endif
+
+/*
+ * Invalidate a range of the icache. The addresses are virtual, and
+ * the cache is virtually indexed and tagged. However, we don't
+ * necessarily have the right ASID context, so use index ops instead
+ * of hit ops.
+ */
+static inline void __sb1_flush_icache_range(unsigned long start,
+ unsigned long end)
+{
+ start &= ~(icache_line_size - 1);
+ end = (end + icache_line_size - 1) & ~(icache_line_size - 1);
+
+ while (start != end) {
+ cache_set_op(Index_Invalidate_I, start & icache_index_mask);
+ start += icache_line_size;
+ }
+ mispredict();
+ sync();
+}
+
+
+/*
+ * Invalidate all caches on this CPU
+ */
+static void local_sb1___flush_cache_all(void)
+{
+ __sb1_writeback_inv_dcache_all();
+ __sb1_flush_icache_all();
+}
+
+#ifdef CONFIG_SMP
+void sb1___flush_cache_all_ipi(void *ignored)
+ __attribute__((alias("local_sb1___flush_cache_all")));
+
+static void sb1___flush_cache_all(void)
+{
+ on_each_cpu(sb1___flush_cache_all_ipi, 0, 1, 1);
+}
+#else
+void sb1___flush_cache_all(void)
+ __attribute__((alias("local_sb1___flush_cache_all")));
+#endif
+
+/*
+ * When flushing a range in the icache, we have to first writeback
+ * the dcache for the same range, so new ifetches will see any
+ * data that was dirty in the dcache.
+ *
+ * The start/end arguments are Kseg addresses (possibly mapped Kseg).
+ */
+
+static void local_sb1_flush_icache_range(unsigned long start,
+ unsigned long end)
+{
+ /* Just wb-inv the whole dcache if the range is big enough */
+ if ((end - start) > dcache_range_cutoff)
+ __sb1_writeback_inv_dcache_all();
+ else
+ __sb1_writeback_inv_dcache_range(start, end);
+
+ /* Just flush the whole icache if the range is big enough */
+ if ((end - start) > icache_range_cutoff)
+ __sb1_flush_icache_all();
+ else
+ __sb1_flush_icache_range(start, end);
+}
+
+#ifdef CONFIG_SMP
+struct flush_icache_range_args {
+ unsigned long start;
+ unsigned long end;
+};
+
+static void sb1_flush_icache_range_ipi(void *info)
+{
+ struct flush_icache_range_args *args = info;
+
+ local_sb1_flush_icache_range(args->start, args->end);
+}
+
+void sb1_flush_icache_range(unsigned long start, unsigned long end)
+{
+ struct flush_icache_range_args args;
+
+ args.start = start;
+ args.end = end;
+ on_each_cpu(sb1_flush_icache_range_ipi, &args, 1, 1);
+}
+#else
+void sb1_flush_icache_range(unsigned long start, unsigned long end)
+ __attribute__((alias("local_sb1_flush_icache_range")));
+#endif
+
+/*
+ * Flush the icache for a given physical page. Need to writeback the
+ * dcache first, then invalidate the icache. If the page isn't
+ * executable, nothing is required.
+ */
+static void local_sb1_flush_icache_page(struct vm_area_struct *vma,
+ struct page *page)
+{
+ unsigned long start;
+ int cpu = smp_processor_id();
+
+#ifndef CONFIG_SMP
+ if (!(vma->vm_flags & VM_EXEC))
+ return;
+#endif
+
+ /* Need to writeback any dirty data for that page, we have the PA */
+ start = (unsigned long)(page-mem_map) << PAGE_SHIFT;
+ __sb1_writeback_inv_dcache_phys_range(start, start + PAGE_SIZE);
+ /*
+ * If there's a context, bump the ASID (cheaper than a flush,
+ * since we don't know VAs!)
+ */
+ if (cpu_context(cpu, vma->vm_mm) != 0) {
+ drop_mmu_context(vma->vm_mm, cpu);
+ }
+}
+
+#ifdef CONFIG_SMP
+struct flush_icache_page_args {
+ struct vm_area_struct *vma;
+ struct page *page;
+};
+
+static void sb1_flush_icache_page_ipi(void *info)
+{
+ struct flush_icache_page_args *args = info;
+ local_sb1_flush_icache_page(args->vma, args->page);
+}
+
+/* Dirty dcache could be on another CPU, so do the IPIs */
+static void sb1_flush_icache_page(struct vm_area_struct *vma,
+ struct page *page)
+{
+ struct flush_icache_page_args args;
+
+ if (!(vma->vm_flags & VM_EXEC))
+ return;
+ args.vma = vma;
+ args.page = page;
+ on_each_cpu(sb1_flush_icache_page_ipi, (void *) &args, 1, 1);
+}
+#else
+void sb1_flush_icache_page(struct vm_area_struct *vma, struct page *page)
+ __attribute__((alias("local_sb1_flush_icache_page")));
+#endif
+
+/*
+ * A signal trampoline must fit into a single cacheline.
+ */
+static void local_sb1_flush_cache_sigtramp(unsigned long addr)
+{
+ cache_set_op(Index_Writeback_Inv_D, addr & dcache_index_mask);
+ cache_set_op(Index_Writeback_Inv_D, (addr ^ (1<<12)) & dcache_index_mask);
+ cache_set_op(Index_Invalidate_I, addr & icache_index_mask);
+ mispredict();
+}
+
+#ifdef CONFIG_SMP
+static void sb1_flush_cache_sigtramp_ipi(void *info)
+{
+ unsigned long iaddr = (unsigned long) info;
+ local_sb1_flush_cache_sigtramp(iaddr);
+}
+
+static void sb1_flush_cache_sigtramp(unsigned long addr)
+{
+ on_each_cpu(sb1_flush_cache_sigtramp_ipi, (void *) addr, 1, 1);
+}
+#else
+void sb1_flush_cache_sigtramp(unsigned long addr)
+ __attribute__((alias("local_sb1_flush_cache_sigtramp")));
+#endif
+
+
+/*
+ * Anything that just flushes dcache state can be ignored, as we're always
+ * coherent in dcache space. This is just a dummy function that all the
+ * nop'ed routines point to
+ */
+static void sb1_nop(void)
+{
+}
+
+/*
+ * Cache set values (from the mips64 spec)
+ * 0 - 64
+ * 1 - 128
+ * 2 - 256
+ * 3 - 512
+ * 4 - 1024
+ * 5 - 2048
+ * 6 - 4096
+ * 7 - Reserved
+ */
+
+static unsigned int decode_cache_sets(unsigned int config_field)
+{
+ if (config_field == 7) {
+ /* JDCXXX - Find a graceful way to abort. */
+ return 0;
+ }
+ return (1<<(config_field + 6));
+}
+
+/*
+ * Cache line size values (from the mips64 spec)
+ * 0 - No cache present.
+ * 1 - 4 bytes
+ * 2 - 8 bytes
+ * 3 - 16 bytes
+ * 4 - 32 bytes
+ * 5 - 64 bytes
+ * 6 - 128 bytes
+ * 7 - Reserved
+ */
+
+static unsigned int decode_cache_line_size(unsigned int config_field)
+{
+ if (config_field == 0) {
+ return 0;
+ } else if (config_field == 7) {
+ /* JDCXXX - Find a graceful way to abort. */
+ return 0;
+ }
+ return (1<<(config_field + 1));
+}
+
+/*
+ * Relevant bits of the config1 register format (from the MIPS32/MIPS64 specs)
+ *
+ * 24:22 Icache sets per way
+ * 21:19 Icache line size
+ * 18:16 Icache Associativity
+ * 15:13 Dcache sets per way
+ * 12:10 Dcache line size
+ * 9:7 Dcache Associativity
+ */
+
+static char *way_string[] = {
+ "direct mapped", "2-way", "3-way", "4-way",
+ "5-way", "6-way", "7-way", "8-way",
+};
+
+static __init void probe_cache_sizes(void)
+{
+ u32 config1;
+
+ config1 = read_c0_config1();
+ icache_line_size = decode_cache_line_size((config1 >> 19) & 0x7);
+ dcache_line_size = decode_cache_line_size((config1 >> 10) & 0x7);
+ icache_sets = decode_cache_sets((config1 >> 22) & 0x7);
+ dcache_sets = decode_cache_sets((config1 >> 13) & 0x7);
+ icache_assoc = ((config1 >> 16) & 0x7) + 1;
+ dcache_assoc = ((config1 >> 7) & 0x7) + 1;
+ icache_size = icache_line_size * icache_sets * icache_assoc;
+ dcache_size = dcache_line_size * dcache_sets * dcache_assoc;
+ /* Need to remove non-index bits for index ops */
+ icache_index_mask = (icache_sets - 1) * icache_line_size;
+ dcache_index_mask = (dcache_sets - 1) * dcache_line_size;
+ /*
+ * These are for choosing range (index ops) versus all.
+ * icache flushes all ways for each set, so drop icache_assoc.
+ * dcache flushes all ways and each setting of bit 12 for each
+ * index, so drop dcache_assoc and halve the dcache_sets.
+ */
+ icache_range_cutoff = icache_sets * icache_line_size;
+ dcache_range_cutoff = (dcache_sets / 2) * icache_line_size;
+
+ printk("Primary instruction cache %ldkB, %s, linesize %d bytes.\n",
+ icache_size >> 10, way_string[icache_assoc - 1],
+ icache_line_size);
+ printk("Primary data cache %ldkB, %s, linesize %d bytes.\n",
+ dcache_size >> 10, way_string[dcache_assoc - 1],
+ dcache_line_size);
+}
+
+/*
+ * This is called from loadmmu.c. We have to set up all the
+ * memory management function pointers, as well as initialize
+ * the caches and tlbs
+ */
+void ld_mmu_sb1(void)
+{
+ extern char except_vec2_sb1;
+ extern char handle_vec2_sb1;
+
+ /* Special cache error handler for SB1 */
+ memcpy((void *)(CAC_BASE + 0x100), &except_vec2_sb1, 0x80);
+ memcpy((void *)(UNCAC_BASE + 0x100), &except_vec2_sb1, 0x80);
+ memcpy((void *)CKSEG1ADDR(&handle_vec2_sb1), &handle_vec2_sb1, 0x80);
+
+ probe_cache_sizes();
+
+#ifdef CONFIG_SIBYTE_DMA_PAGEOPS
+ sb1_dma_init();
+#endif
+
+ /*
+ * None of these are needed for the SB1 - the Dcache is
+ * physically indexed and tagged, so no virtual aliasing can
+ * occur
+ */
+ flush_cache_range = (void *) sb1_nop;
+ flush_cache_mm = (void (*)(struct mm_struct *))sb1_nop;
+ flush_cache_all = sb1_nop;
+
+ /* These routines are for Icache coherence with the Dcache */
+ flush_icache_range = sb1_flush_icache_range;
+ flush_icache_page = sb1_flush_icache_page;
+ flush_icache_all = __sb1_flush_icache_all; /* local only */
+
+ /* This implies an Icache flush too, so can't be nop'ed */
+ flush_cache_page = sb1_flush_cache_page;
+
+ flush_cache_sigtramp = sb1_flush_cache_sigtramp;
+ flush_data_cache_page = (void *) sb1_nop;
+
+ /* Full flush */
+ __flush_cache_all = sb1___flush_cache_all;
+
+ change_c0_config(CONF_CM_CMASK, CONF_CM_DEFAULT);
+
+ /*
+ * This is the only way to force the update of K0 to complete
+ * before subsequent instruction fetch.
+ */
+ __asm__ __volatile__(
+ ".set push \n"
+ " .set noat \n"
+ " .set noreorder \n"
+ " .set mips3 \n"
+ " " STR(PTR_LA) " $1, 1f \n"
+ " " STR(MTC0) " $1, $14 \n"
+ " eret \n"
+ "1: .set pop"
+ :
+ :
+ : "memory");
+
+ flush_cache_all();
+}
diff --git a/arch/mips/mm/c-tx39.c b/arch/mips/mm/c-tx39.c
new file mode 100644
index 0000000..ff5afab
--- /dev/null
+++ b/arch/mips/mm/c-tx39.c
@@ -0,0 +1,493 @@
+/*
+ * r2300.c: R2000 and R3000 specific mmu/cache code.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ *
+ * with a lot of changes to make this thing work for R3000s
+ * Tx39XX R4k style caches added. HK
+ * Copyright (C) 1998, 1999, 2000 Harald Koerfgen
+ * Copyright (C) 1998 Gleb Raiko & Vladimir Roganov
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+
+#include <asm/cacheops.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/mmu_context.h>
+#include <asm/system.h>
+#include <asm/isadep.h>
+#include <asm/io.h>
+#include <asm/bootinfo.h>
+#include <asm/cpu.h>
+
+/* For R3000 cores with R4000 style caches */
+static unsigned long icache_size, dcache_size; /* Size in bytes */
+
+#include <asm/r4kcache.h>
+
+extern int r3k_have_wired_reg; /* in r3k-tlb.c */
+
+/* This sequence is required to ensure icache is disabled immediately */
+#define TX39_STOP_STREAMING() \
+__asm__ __volatile__( \
+ ".set push\n\t" \
+ ".set noreorder\n\t" \
+ "b 1f\n\t" \
+ "nop\n\t" \
+ "1:\n\t" \
+ ".set pop" \
+ )
+
+/* TX39H-style cache flush routines. */
+static void tx39h_flush_icache_all(void)
+{
+ unsigned long start = KSEG0;
+ unsigned long end = (start + icache_size);
+ unsigned long flags, config;
+
+ /* disable icache (set ICE#) */
+ local_irq_save(flags);
+ config = read_c0_conf();
+ write_c0_conf(config & ~TX39_CONF_ICE);
+ TX39_STOP_STREAMING();
+
+ /* invalidate icache */
+ while (start < end) {
+ cache16_unroll32(start, Index_Invalidate_I);
+ start += 0x200;
+ }
+
+ write_c0_conf(config);
+ local_irq_restore(flags);
+}
+
+static void tx39h_dma_cache_wback_inv(unsigned long addr, unsigned long size)
+{
+ unsigned long end, a;
+ unsigned long dc_lsize = current_cpu_data.dcache.linesz;
+
+ /* Catch bad driver code */
+ BUG_ON(size == 0);
+
+ iob();
+ a = addr & ~(dc_lsize - 1);
+ end = (addr + size - 1) & ~(dc_lsize - 1);
+ while (1) {
+ invalidate_dcache_line(a); /* Hit_Invalidate_D */
+ if (a == end) break;
+ a += dc_lsize;
+ }
+}
+
+
+/* TX39H2,TX39H3 */
+static inline void tx39_blast_dcache_page(unsigned long addr)
+{
+ if (current_cpu_data.cputype != CPU_TX3912)
+ blast_dcache16_page(addr);
+}
+
+static inline void tx39_blast_dcache_page_indexed(unsigned long addr)
+{
+ blast_dcache16_page_indexed(addr);
+}
+
+static inline void tx39_blast_dcache(void)
+{
+ blast_dcache16();
+}
+
+static inline void tx39_blast_icache_page(unsigned long addr)
+{
+ unsigned long flags, config;
+ /* disable icache (set ICE#) */
+ local_irq_save(flags);
+ config = read_c0_conf();
+ write_c0_conf(config & ~TX39_CONF_ICE);
+ TX39_STOP_STREAMING();
+ blast_icache16_page(addr);
+ write_c0_conf(config);
+ local_irq_restore(flags);
+}
+
+static inline void tx39_blast_icache_page_indexed(unsigned long addr)
+{
+ unsigned long flags, config;
+ /* disable icache (set ICE#) */
+ local_irq_save(flags);
+ config = read_c0_conf();
+ write_c0_conf(config & ~TX39_CONF_ICE);
+ TX39_STOP_STREAMING();
+ blast_icache16_page_indexed(addr);
+ write_c0_conf(config);
+ local_irq_restore(flags);
+}
+
+static inline void tx39_blast_icache(void)
+{
+ unsigned long flags, config;
+ /* disable icache (set ICE#) */
+ local_irq_save(flags);
+ config = read_c0_conf();
+ write_c0_conf(config & ~TX39_CONF_ICE);
+ TX39_STOP_STREAMING();
+ blast_icache16();
+ write_c0_conf(config);
+ local_irq_restore(flags);
+}
+
+static inline void tx39_flush_cache_all(void)
+{
+ if (!cpu_has_dc_aliases)
+ return;
+
+ tx39_blast_dcache();
+ tx39_blast_icache();
+}
+
+static inline void tx39___flush_cache_all(void)
+{
+ tx39_blast_dcache();
+ tx39_blast_icache();
+}
+
+static void tx39_flush_cache_mm(struct mm_struct *mm)
+{
+ if (!cpu_has_dc_aliases)
+ return;
+
+ if (cpu_context(smp_processor_id(), mm) != 0) {
+ tx39_flush_cache_all();
+ }
+}
+
+static void tx39_flush_cache_range(struct vm_area_struct *vma,
+ unsigned long start, unsigned long end)
+{
+ struct mm_struct *mm = vma->vm_mm;
+
+ if (!cpu_has_dc_aliases)
+ return;
+
+ if (cpu_context(smp_processor_id(), mm) != 0) {
+ tx39_blast_dcache();
+ tx39_blast_icache();
+ }
+}
+
+static void tx39_flush_cache_page(struct vm_area_struct *vma, unsigned long page, unsigned long pfn)
+{
+ int exec = vma->vm_flags & VM_EXEC;
+ struct mm_struct *mm = vma->vm_mm;
+ pgd_t *pgdp;
+ pmd_t *pmdp;
+ pte_t *ptep;
+
+ /*
+ * If ownes no valid ASID yet, cannot possibly have gotten
+ * this page into the cache.
+ */
+ if (cpu_context(smp_processor_id(), mm) == 0)
+ return;
+
+ page &= PAGE_MASK;
+ pgdp = pgd_offset(mm, page);
+ pmdp = pmd_offset(pgdp, page);
+ ptep = pte_offset(pmdp, page);
+
+ /*
+ * If the page isn't marked valid, the page cannot possibly be
+ * in the cache.
+ */
+ if (!(pte_val(*ptep) & _PAGE_PRESENT))
+ return;
+
+ /*
+ * Doing flushes for another ASID than the current one is
+ * too difficult since stupid R4k caches do a TLB translation
+ * for every cache flush operation. So we do indexed flushes
+ * in that case, which doesn't overly flush the cache too much.
+ */
+ if ((mm == current->active_mm) && (pte_val(*ptep) & _PAGE_VALID)) {
+ if (cpu_has_dc_aliases || exec)
+ tx39_blast_dcache_page(page);
+ if (exec)
+ tx39_blast_icache_page(page);
+
+ return;
+ }
+
+ /*
+ * Do indexed flush, too much work to get the (possible) TLB refills
+ * to work correctly.
+ */
+ page = (KSEG0 + (page & (dcache_size - 1)));
+ if (cpu_has_dc_aliases || exec)
+ tx39_blast_dcache_page_indexed(page);
+ if (exec)
+ tx39_blast_icache_page_indexed(page);
+}
+
+static void tx39_flush_data_cache_page(unsigned long addr)
+{
+ tx39_blast_dcache_page(addr);
+}
+
+static void tx39_flush_icache_range(unsigned long start, unsigned long end)
+{
+ unsigned long dc_lsize = current_cpu_data.dcache.linesz;
+ unsigned long addr, aend;
+
+ if (end - start > dcache_size)
+ tx39_blast_dcache();
+ else {
+ addr = start & ~(dc_lsize - 1);
+ aend = (end - 1) & ~(dc_lsize - 1);
+
+ while (1) {
+ /* Hit_Writeback_Inv_D */
+ protected_writeback_dcache_line(addr);
+ if (addr == aend)
+ break;
+ addr += dc_lsize;
+ }
+ }
+
+ if (end - start > icache_size)
+ tx39_blast_icache();
+ else {
+ unsigned long flags, config;
+ addr = start & ~(dc_lsize - 1);
+ aend = (end - 1) & ~(dc_lsize - 1);
+ /* disable icache (set ICE#) */
+ local_irq_save(flags);
+ config = read_c0_conf();
+ write_c0_conf(config & ~TX39_CONF_ICE);
+ TX39_STOP_STREAMING();
+ while (1) {
+ /* Hit_Invalidate_I */
+ protected_flush_icache_line(addr);
+ if (addr == aend)
+ break;
+ addr += dc_lsize;
+ }
+ write_c0_conf(config);
+ local_irq_restore(flags);
+ }
+}
+
+/*
+ * Ok, this seriously sucks. We use them to flush a user page but don't
+ * know the virtual address, so we have to blast away the whole icache
+ * which is significantly more expensive than the real thing. Otoh we at
+ * least know the kernel address of the page so we can flush it
+ * selectivly.
+ */
+static void tx39_flush_icache_page(struct vm_area_struct *vma, struct page *page)
+{
+ unsigned long addr;
+ /*
+ * If there's no context yet, or the page isn't executable, no icache
+ * flush is needed.
+ */
+ if (!(vma->vm_flags & VM_EXEC))
+ return;
+
+ addr = (unsigned long) page_address(page);
+ tx39_blast_dcache_page(addr);
+
+ /*
+ * We're not sure of the virtual address(es) involved here, so
+ * we have to flush the entire I-cache.
+ */
+ tx39_blast_icache();
+}
+
+static void tx39_dma_cache_wback_inv(unsigned long addr, unsigned long size)
+{
+ unsigned long end, a;
+
+ if (((size | addr) & (PAGE_SIZE - 1)) == 0) {
+ end = addr + size;
+ do {
+ tx39_blast_dcache_page(addr);
+ addr += PAGE_SIZE;
+ } while(addr != end);
+ } else if (size > dcache_size) {
+ tx39_blast_dcache();
+ } else {
+ unsigned long dc_lsize = current_cpu_data.dcache.linesz;
+ a = addr & ~(dc_lsize - 1);
+ end = (addr + size - 1) & ~(dc_lsize - 1);
+ while (1) {
+ flush_dcache_line(a); /* Hit_Writeback_Inv_D */
+ if (a == end) break;
+ a += dc_lsize;
+ }
+ }
+}
+
+static void tx39_dma_cache_inv(unsigned long addr, unsigned long size)
+{
+ unsigned long end, a;
+
+ if (((size | addr) & (PAGE_SIZE - 1)) == 0) {
+ end = addr + size;
+ do {
+ tx39_blast_dcache_page(addr);
+ addr += PAGE_SIZE;
+ } while(addr != end);
+ } else if (size > dcache_size) {
+ tx39_blast_dcache();
+ } else {
+ unsigned long dc_lsize = current_cpu_data.dcache.linesz;
+ a = addr & ~(dc_lsize - 1);
+ end = (addr + size - 1) & ~(dc_lsize - 1);
+ while (1) {
+ invalidate_dcache_line(a); /* Hit_Invalidate_D */
+ if (a == end) break;
+ a += dc_lsize;
+ }
+ }
+}
+
+static void tx39_flush_cache_sigtramp(unsigned long addr)
+{
+ unsigned long ic_lsize = current_cpu_data.icache.linesz;
+ unsigned long dc_lsize = current_cpu_data.dcache.linesz;
+ unsigned long config;
+ unsigned long flags;
+
+ protected_writeback_dcache_line(addr & ~(dc_lsize - 1));
+
+ /* disable icache (set ICE#) */
+ local_irq_save(flags);
+ config = read_c0_conf();
+ write_c0_conf(config & ~TX39_CONF_ICE);
+ TX39_STOP_STREAMING();
+ protected_flush_icache_line(addr & ~(ic_lsize - 1));
+ write_c0_conf(config);
+ local_irq_restore(flags);
+}
+
+static __init void tx39_probe_cache(void)
+{
+ unsigned long config;
+
+ config = read_c0_conf();
+
+ icache_size = 1 << (10 + ((config & TX39_CONF_ICS_MASK) >>
+ TX39_CONF_ICS_SHIFT));
+ dcache_size = 1 << (10 + ((config & TX39_CONF_DCS_MASK) >>
+ TX39_CONF_DCS_SHIFT));
+
+ current_cpu_data.icache.linesz = 16;
+ switch (current_cpu_data.cputype) {
+ case CPU_TX3912:
+ current_cpu_data.icache.ways = 1;
+ current_cpu_data.dcache.ways = 1;
+ current_cpu_data.dcache.linesz = 4;
+ break;
+
+ case CPU_TX3927:
+ current_cpu_data.icache.ways = 2;
+ current_cpu_data.dcache.ways = 2;
+ current_cpu_data.dcache.linesz = 16;
+ break;
+
+ case CPU_TX3922:
+ default:
+ current_cpu_data.icache.ways = 1;
+ current_cpu_data.dcache.ways = 1;
+ current_cpu_data.dcache.linesz = 16;
+ break;
+ }
+}
+
+void __init ld_mmu_tx39(void)
+{
+ extern void build_clear_page(void);
+ extern void build_copy_page(void);
+ unsigned long config;
+
+ config = read_c0_conf();
+ config &= ~TX39_CONF_WBON;
+ write_c0_conf(config);
+
+ tx39_probe_cache();
+
+ switch (current_cpu_data.cputype) {
+ case CPU_TX3912:
+ /* TX39/H core (writethru direct-map cache) */
+ flush_cache_all = tx39h_flush_icache_all;
+ __flush_cache_all = tx39h_flush_icache_all;
+ flush_cache_mm = (void *) tx39h_flush_icache_all;
+ flush_cache_range = (void *) tx39h_flush_icache_all;
+ flush_cache_page = (void *) tx39h_flush_icache_all;
+ flush_icache_page = (void *) tx39h_flush_icache_all;
+ flush_icache_range = (void *) tx39h_flush_icache_all;
+
+ flush_cache_sigtramp = (void *) tx39h_flush_icache_all;
+ flush_data_cache_page = (void *) tx39h_flush_icache_all;
+
+ _dma_cache_wback_inv = tx39h_dma_cache_wback_inv;
+
+ shm_align_mask = PAGE_SIZE - 1;
+
+ break;
+
+ case CPU_TX3922:
+ case CPU_TX3927:
+ default:
+ /* TX39/H2,H3 core (writeback 2way-set-associative cache) */
+ r3k_have_wired_reg = 1;
+ write_c0_wired(0); /* set 8 on reset... */
+ /* board-dependent init code may set WBON */
+
+ flush_cache_all = tx39_flush_cache_all;
+ __flush_cache_all = tx39___flush_cache_all;
+ flush_cache_mm = tx39_flush_cache_mm;
+ flush_cache_range = tx39_flush_cache_range;
+ flush_cache_page = tx39_flush_cache_page;
+ flush_icache_page = tx39_flush_icache_page;
+ flush_icache_range = tx39_flush_icache_range;
+
+ flush_cache_sigtramp = tx39_flush_cache_sigtramp;
+ flush_data_cache_page = tx39_flush_data_cache_page;
+
+ _dma_cache_wback_inv = tx39_dma_cache_wback_inv;
+ _dma_cache_wback = tx39_dma_cache_wback_inv;
+ _dma_cache_inv = tx39_dma_cache_inv;
+
+ shm_align_mask = max_t(unsigned long,
+ (dcache_size / current_cpu_data.dcache.ways) - 1,
+ PAGE_SIZE - 1);
+
+ break;
+ }
+
+ current_cpu_data.icache.waysize = icache_size / current_cpu_data.icache.ways;
+ current_cpu_data.dcache.waysize = dcache_size / current_cpu_data.dcache.ways;
+
+ current_cpu_data.icache.sets =
+ current_cpu_data.icache.waysize / current_cpu_data.icache.linesz;
+ current_cpu_data.dcache.sets =
+ current_cpu_data.dcache.waysize / current_cpu_data.dcache.linesz;
+
+ if (current_cpu_data.dcache.waysize > PAGE_SIZE)
+ current_cpu_data.dcache.flags |= MIPS_CACHE_ALIASES;
+
+ current_cpu_data.icache.waybit = 0;
+ current_cpu_data.dcache.waybit = 0;
+
+ printk("Primary instruction cache %ldkB, linesize %d bytes\n",
+ icache_size >> 10, current_cpu_data.icache.linesz);
+ printk("Primary data cache %ldkB, linesize %d bytes\n",
+ dcache_size >> 10, current_cpu_data.dcache.linesz);
+
+ build_clear_page();
+ build_copy_page();
+}
diff --git a/arch/mips/mm/cache.c b/arch/mips/mm/cache.c
new file mode 100644
index 0000000..1d95cdb
--- /dev/null
+++ b/arch/mips/mm/cache.c
@@ -0,0 +1,157 @@
+/*
+ * 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) 1994 - 2003 by Ralf Baechle
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+
+#include <asm/cacheflush.h>
+#include <asm/processor.h>
+#include <asm/cpu.h>
+#include <asm/cpu-features.h>
+
+/* Cache operations. */
+void (*flush_cache_all)(void);
+void (*__flush_cache_all)(void);
+void (*flush_cache_mm)(struct mm_struct *mm);
+void (*flush_cache_range)(struct vm_area_struct *vma, unsigned long start,
+ unsigned long end);
+void (*flush_cache_page)(struct vm_area_struct *vma, unsigned long page, unsigned long pfn);
+void (*flush_icache_range)(unsigned long start, unsigned long end);
+void (*flush_icache_page)(struct vm_area_struct *vma, struct page *page);
+
+/* MIPS specific cache operations */
+void (*flush_cache_sigtramp)(unsigned long addr);
+void (*flush_data_cache_page)(unsigned long addr);
+void (*flush_icache_all)(void);
+
+#ifdef CONFIG_DMA_NONCOHERENT
+
+/* DMA cache operations. */
+void (*_dma_cache_wback_inv)(unsigned long start, unsigned long size);
+void (*_dma_cache_wback)(unsigned long start, unsigned long size);
+void (*_dma_cache_inv)(unsigned long start, unsigned long size);
+
+EXPORT_SYMBOL(_dma_cache_wback_inv);
+EXPORT_SYMBOL(_dma_cache_wback);
+EXPORT_SYMBOL(_dma_cache_inv);
+
+#endif /* CONFIG_DMA_NONCOHERENT */
+
+/*
+ * We could optimize the case where the cache argument is not BCACHE but
+ * that seems very atypical use ...
+ */
+asmlinkage int sys_cacheflush(unsigned long addr, unsigned long int bytes,
+ unsigned int cache)
+{
+ if (!access_ok(VERIFY_WRITE, (void *) addr, bytes))
+ return -EFAULT;
+
+ flush_icache_range(addr, addr + bytes);
+
+ return 0;
+}
+
+void __flush_dcache_page(struct page *page)
+{
+ struct address_space *mapping = page_mapping(page);
+ unsigned long addr;
+
+ if (mapping && !mapping_mapped(mapping)) {
+ SetPageDcacheDirty(page);
+ return;
+ }
+
+ /*
+ * We could delay the flush for the !page_mapping case too. But that
+ * case is for exec env/arg pages and those are %99 certainly going to
+ * get faulted into the tlb (and thus flushed) anyways.
+ */
+ addr = (unsigned long) page_address(page);
+ flush_data_cache_page(addr);
+}
+
+EXPORT_SYMBOL(__flush_dcache_page);
+
+void __update_cache(struct vm_area_struct *vma, unsigned long address,
+ pte_t pte)
+{
+ struct page *page;
+ unsigned long pfn, addr;
+
+ pfn = pte_pfn(pte);
+ if (pfn_valid(pfn) && (page = pfn_to_page(pfn), page_mapping(page)) &&
+ Page_dcache_dirty(page)) {
+ if (pages_do_alias((unsigned long)page_address(page),
+ address & PAGE_MASK)) {
+ addr = (unsigned long) page_address(page);
+ flush_data_cache_page(addr);
+ }
+
+ ClearPageDcacheDirty(page);
+ }
+}
+
+extern void ld_mmu_r23000(void);
+extern void ld_mmu_r4xx0(void);
+extern void ld_mmu_tx39(void);
+extern void ld_mmu_r6000(void);
+extern void ld_mmu_tfp(void);
+extern void ld_mmu_andes(void);
+extern void ld_mmu_sb1(void);
+
+void __init cpu_cache_init(void)
+{
+ if (cpu_has_4ktlb) {
+#if defined(CONFIG_CPU_R4X00) || defined(CONFIG_CPU_VR41XX) || \
+ defined(CONFIG_CPU_R4300) || defined(CONFIG_CPU_R5000) || \
+ defined(CONFIG_CPU_NEVADA) || defined(CONFIG_CPU_R5432) || \
+ defined(CONFIG_CPU_R5500) || defined(CONFIG_CPU_MIPS32) || \
+ defined(CONFIG_CPU_MIPS64) || defined(CONFIG_CPU_TX49XX) || \
+ defined(CONFIG_CPU_RM7000) || defined(CONFIG_CPU_RM9000)
+ ld_mmu_r4xx0();
+#endif
+ } else switch (current_cpu_data.cputype) {
+#ifdef CONFIG_CPU_R3000
+ case CPU_R2000:
+ case CPU_R3000:
+ case CPU_R3000A:
+ case CPU_R3081E:
+ ld_mmu_r23000();
+ break;
+#endif
+#ifdef CONFIG_CPU_TX39XX
+ case CPU_TX3912:
+ case CPU_TX3922:
+ case CPU_TX3927:
+ ld_mmu_tx39();
+ break;
+#endif
+#ifdef CONFIG_CPU_R10000
+ case CPU_R10000:
+ case CPU_R12000:
+ ld_mmu_r4xx0();
+ break;
+#endif
+#ifdef CONFIG_CPU_SB1
+ case CPU_SB1:
+ ld_mmu_sb1();
+ break;
+#endif
+
+ case CPU_R8000:
+ panic("R8000 is unsupported");
+ break;
+
+ default:
+ panic("Yeee, unsupported cache architecture.");
+ }
+}
diff --git a/arch/mips/mm/cerr-sb1.c b/arch/mips/mm/cerr-sb1.c
new file mode 100644
index 0000000..13d96d6
--- /dev/null
+++ b/arch/mips/mm/cerr-sb1.c
@@ -0,0 +1,543 @@
+/*
+ * Copyright (C) 2001,2002,2003 Broadcom Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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 <linux/config.h>
+#include <linux/sched.h>
+#include <asm/mipsregs.h>
+#include <asm/sibyte/sb1250.h>
+
+#ifndef CONFIG_SIBYTE_BUS_WATCHER
+#include <asm/io.h>
+#include <asm/sibyte/sb1250_regs.h>
+#include <asm/sibyte/sb1250_scd.h>
+#endif
+
+/* SB1 definitions */
+
+/* XXX should come from config1 XXX */
+#define SB1_CACHE_INDEX_MASK 0x1fe0
+
+#define CP0_ERRCTL_RECOVERABLE (1 << 31)
+#define CP0_ERRCTL_DCACHE (1 << 30)
+#define CP0_ERRCTL_ICACHE (1 << 29)
+#define CP0_ERRCTL_MULTIBUS (1 << 23)
+#define CP0_ERRCTL_MC_TLB (1 << 15)
+#define CP0_ERRCTL_MC_TIMEOUT (1 << 14)
+
+#define CP0_CERRI_TAG_PARITY (1 << 29)
+#define CP0_CERRI_DATA_PARITY (1 << 28)
+#define CP0_CERRI_EXTERNAL (1 << 26)
+
+#define CP0_CERRI_IDX_VALID(c) (!((c) & CP0_CERRI_EXTERNAL))
+#define CP0_CERRI_DATA (CP0_CERRI_DATA_PARITY)
+
+#define CP0_CERRD_MULTIPLE (1 << 31)
+#define CP0_CERRD_TAG_STATE (1 << 30)
+#define CP0_CERRD_TAG_ADDRESS (1 << 29)
+#define CP0_CERRD_DATA_SBE (1 << 28)
+#define CP0_CERRD_DATA_DBE (1 << 27)
+#define CP0_CERRD_EXTERNAL (1 << 26)
+#define CP0_CERRD_LOAD (1 << 25)
+#define CP0_CERRD_STORE (1 << 24)
+#define CP0_CERRD_FILLWB (1 << 23)
+#define CP0_CERRD_COHERENCY (1 << 22)
+#define CP0_CERRD_DUPTAG (1 << 21)
+
+#define CP0_CERRD_DPA_VALID(c) (!((c) & CP0_CERRD_EXTERNAL))
+#define CP0_CERRD_IDX_VALID(c) \
+ (((c) & (CP0_CERRD_LOAD | CP0_CERRD_STORE)) ? (!((c) & CP0_CERRD_EXTERNAL)) : 0)
+#define CP0_CERRD_CAUSES \
+ (CP0_CERRD_LOAD | CP0_CERRD_STORE | CP0_CERRD_FILLWB | CP0_CERRD_COHERENCY | CP0_CERRD_DUPTAG)
+#define CP0_CERRD_TYPES \
+ (CP0_CERRD_TAG_STATE | CP0_CERRD_TAG_ADDRESS | CP0_CERRD_DATA_SBE | CP0_CERRD_DATA_DBE | CP0_CERRD_EXTERNAL)
+#define CP0_CERRD_DATA (CP0_CERRD_DATA_SBE | CP0_CERRD_DATA_DBE)
+
+static uint32_t extract_ic(unsigned short addr, int data);
+static uint32_t extract_dc(unsigned short addr, int data);
+
+static inline void breakout_errctl(unsigned int val)
+{
+ if (val & CP0_ERRCTL_RECOVERABLE)
+ prom_printf(" recoverable");
+ if (val & CP0_ERRCTL_DCACHE)
+ prom_printf(" dcache");
+ if (val & CP0_ERRCTL_ICACHE)
+ prom_printf(" icache");
+ if (val & CP0_ERRCTL_MULTIBUS)
+ prom_printf(" multiple-buserr");
+ prom_printf("\n");
+}
+
+static inline void breakout_cerri(unsigned int val)
+{
+ if (val & CP0_CERRI_TAG_PARITY)
+ prom_printf(" tag-parity");
+ if (val & CP0_CERRI_DATA_PARITY)
+ prom_printf(" data-parity");
+ if (val & CP0_CERRI_EXTERNAL)
+ prom_printf(" external");
+ prom_printf("\n");
+}
+
+static inline void breakout_cerrd(unsigned int val)
+{
+ switch (val & CP0_CERRD_CAUSES) {
+ case CP0_CERRD_LOAD:
+ prom_printf(" load,");
+ break;
+ case CP0_CERRD_STORE:
+ prom_printf(" store,");
+ break;
+ case CP0_CERRD_FILLWB:
+ prom_printf(" fill/wb,");
+ break;
+ case CP0_CERRD_COHERENCY:
+ prom_printf(" coherency,");
+ break;
+ case CP0_CERRD_DUPTAG:
+ prom_printf(" duptags,");
+ break;
+ default:
+ prom_printf(" NO CAUSE,");
+ break;
+ }
+ if (!(val & CP0_CERRD_TYPES))
+ prom_printf(" NO TYPE");
+ else {
+ if (val & CP0_CERRD_MULTIPLE)
+ prom_printf(" multi-err");
+ if (val & CP0_CERRD_TAG_STATE)
+ prom_printf(" tag-state");
+ if (val & CP0_CERRD_TAG_ADDRESS)
+ prom_printf(" tag-address");
+ if (val & CP0_CERRD_DATA_SBE)
+ prom_printf(" data-SBE");
+ if (val & CP0_CERRD_DATA_DBE)
+ prom_printf(" data-DBE");
+ if (val & CP0_CERRD_EXTERNAL)
+ prom_printf(" external");
+ }
+ prom_printf("\n");
+}
+
+#ifndef CONFIG_SIBYTE_BUS_WATCHER
+
+static void check_bus_watcher(void)
+{
+ uint32_t status, l2_err, memio_err;
+
+ /* Destructive read, clears register and interrupt */
+ status = csr_in32(IOADDR(A_SCD_BUS_ERR_STATUS));
+ /* Bit 31 is always on, but there's no #define for that */
+ if (status & ~(1UL << 31)) {
+ l2_err = csr_in32(IOADDR(A_BUS_L2_ERRORS));
+ memio_err = csr_in32(IOADDR(A_BUS_MEM_IO_ERRORS));
+ prom_printf("Bus watcher error counters: %08x %08x\n", l2_err, memio_err);
+ prom_printf("\nLast recorded signature:\n");
+ prom_printf("Request %02x from %d, answered by %d with Dcode %d\n",
+ (unsigned int)(G_SCD_BERR_TID(status) & 0x3f),
+ (int)(G_SCD_BERR_TID(status) >> 6),
+ (int)G_SCD_BERR_RID(status),
+ (int)G_SCD_BERR_DCODE(status));
+ } else {
+ prom_printf("Bus watcher indicates no error\n");
+ }
+}
+#else
+extern void check_bus_watcher(void);
+#endif
+
+asmlinkage void sb1_cache_error(void)
+{
+ uint64_t cerr_dpa;
+ uint32_t errctl, cerr_i, cerr_d, dpalo, dpahi, eepc, res;
+
+ prom_printf("Cache error exception on CPU %x:\n",
+ (read_c0_prid() >> 25) & 0x7);
+
+ __asm__ __volatile__ (
+ " .set push\n\t"
+ " .set mips64\n\t"
+ " .set noat\n\t"
+ " mfc0 %0, $26\n\t"
+ " mfc0 %1, $27\n\t"
+ " mfc0 %2, $27, 1\n\t"
+ " dmfc0 $1, $27, 3\n\t"
+ " dsrl32 %3, $1, 0 \n\t"
+ " sll %4, $1, 0 \n\t"
+ " mfc0 %5, $30\n\t"
+ " .set pop"
+ : "=r" (errctl), "=r" (cerr_i), "=r" (cerr_d),
+ "=r" (dpahi), "=r" (dpalo), "=r" (eepc));
+
+ cerr_dpa = (((uint64_t)dpahi) << 32) | dpalo;
+ prom_printf(" c0_errorepc == %08x\n", eepc);
+ prom_printf(" c0_errctl == %08x", errctl);
+ breakout_errctl(errctl);
+ if (errctl & CP0_ERRCTL_ICACHE) {
+ prom_printf(" c0_cerr_i == %08x", cerr_i);
+ breakout_cerri(cerr_i);
+ if (CP0_CERRI_IDX_VALID(cerr_i)) {
+ /* Check index of EPC, allowing for delay slot */
+ if (((eepc & SB1_CACHE_INDEX_MASK) != (cerr_i & SB1_CACHE_INDEX_MASK)) &&
+ ((eepc & SB1_CACHE_INDEX_MASK) != ((cerr_i & SB1_CACHE_INDEX_MASK) - 4)))
+ prom_printf(" cerr_i idx doesn't match eepc\n");
+ else {
+ res = extract_ic(cerr_i & SB1_CACHE_INDEX_MASK,
+ (cerr_i & CP0_CERRI_DATA) != 0);
+ if (!(res & cerr_i))
+ prom_printf("...didn't see indicated icache problem\n");
+ }
+ }
+ }
+ if (errctl & CP0_ERRCTL_DCACHE) {
+ prom_printf(" c0_cerr_d == %08x", cerr_d);
+ breakout_cerrd(cerr_d);
+ if (CP0_CERRD_DPA_VALID(cerr_d)) {
+ prom_printf(" c0_cerr_dpa == %010llx\n", cerr_dpa);
+ if (!CP0_CERRD_IDX_VALID(cerr_d)) {
+ res = extract_dc(cerr_dpa & SB1_CACHE_INDEX_MASK,
+ (cerr_d & CP0_CERRD_DATA) != 0);
+ if (!(res & cerr_d))
+ prom_printf("...didn't see indicated dcache problem\n");
+ } else {
+ if ((cerr_dpa & SB1_CACHE_INDEX_MASK) != (cerr_d & SB1_CACHE_INDEX_MASK))
+ prom_printf(" cerr_d idx doesn't match cerr_dpa\n");
+ else {
+ res = extract_dc(cerr_d & SB1_CACHE_INDEX_MASK,
+ (cerr_d & CP0_CERRD_DATA) != 0);
+ if (!(res & cerr_d))
+ prom_printf("...didn't see indicated problem\n");
+ }
+ }
+ }
+ }
+
+ check_bus_watcher();
+
+ while (1);
+ /*
+ * This tends to make things get really ugly; let's just stall instead.
+ * panic("Can't handle the cache error!");
+ */
+}
+
+
+/* Parity lookup table. */
+static const uint8_t parity[256] = {
+ 0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,
+ 1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,
+ 1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,
+ 0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,
+ 1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,
+ 0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,
+ 0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,
+ 1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0
+};
+
+/* Masks to select bits for Hamming parity, mask_72_64[i] for bit[i] */
+static const uint64_t mask_72_64[8] = {
+ 0x0738C808099264FFULL,
+ 0x38C808099264FF07ULL,
+ 0xC808099264FF0738ULL,
+ 0x08099264FF0738C8ULL,
+ 0x099264FF0738C808ULL,
+ 0x9264FF0738C80809ULL,
+ 0x64FF0738C8080992ULL,
+ 0xFF0738C808099264ULL
+};
+
+/* Calculate the parity on a range of bits */
+static char range_parity(uint64_t dword, int max, int min)
+{
+ char parity = 0;
+ int i;
+ dword >>= min;
+ for (i=max-min; i>=0; i--) {
+ if (dword & 0x1)
+ parity = !parity;
+ dword >>= 1;
+ }
+ return parity;
+}
+
+/* Calculate the 4-bit even byte-parity for an instruction */
+static unsigned char inst_parity(uint32_t word)
+{
+ int i, j;
+ char parity = 0;
+ for (j=0; j<4; j++) {
+ char byte_parity = 0;
+ for (i=0; i<8; i++) {
+ if (word & 0x80000000)
+ byte_parity = !byte_parity;
+ word <<= 1;
+ }
+ parity <<= 1;
+ parity |= byte_parity;
+ }
+ return parity;
+}
+
+static uint32_t extract_ic(unsigned short addr, int data)
+{
+ unsigned short way;
+ int valid;
+ uint64_t taglo, va, tlo_tmp;
+ uint32_t taghi, taglolo, taglohi;
+ uint8_t lru;
+ int res = 0;
+
+ prom_printf("Icache index 0x%04x ", addr);
+ for (way = 0; way < 4; way++) {
+ /* Index-load-tag-I */
+ __asm__ __volatile__ (
+ " .set push \n\t"
+ " .set noreorder \n\t"
+ " .set mips64 \n\t"
+ " .set noat \n\t"
+ " cache 4, 0(%3) \n\t"
+ " mfc0 %0, $29 \n\t"
+ " dmfc0 $1, $28 \n\t"
+ " dsrl32 %1, $1, 0 \n\t"
+ " sll %2, $1, 0 \n\t"
+ " .set pop"
+ : "=r" (taghi), "=r" (taglohi), "=r" (taglolo)
+ : "r" ((way << 13) | addr));
+
+ taglo = ((unsigned long long)taglohi << 32) | taglolo;
+ if (way == 0) {
+ lru = (taghi >> 14) & 0xff;
+ prom_printf("[Bank %d Set 0x%02x] LRU > %d %d %d %d > MRU\n",
+ ((addr >> 5) & 0x3), /* bank */
+ ((addr >> 7) & 0x3f), /* index */
+ (lru & 0x3),
+ ((lru >> 2) & 0x3),
+ ((lru >> 4) & 0x3),
+ ((lru >> 6) & 0x3));
+ }
+ va = (taglo & 0xC0000FFFFFFFE000ULL) | addr;
+ if ((taglo & (1 << 31)) && (((taglo >> 62) & 0x3) == 3))
+ va |= 0x3FFFF00000000000ULL;
+ valid = ((taghi >> 29) & 1);
+ if (valid) {
+ tlo_tmp = taglo & 0xfff3ff;
+ if (((taglo >> 10) & 1) ^ range_parity(tlo_tmp, 23, 0)) {
+ prom_printf(" ** bad parity in VTag0/G/ASID\n");
+ res |= CP0_CERRI_TAG_PARITY;
+ }
+ if (((taglo >> 11) & 1) ^ range_parity(taglo, 63, 24)) {
+ prom_printf(" ** bad parity in R/VTag1\n");
+ res |= CP0_CERRI_TAG_PARITY;
+ }
+ }
+ if (valid ^ ((taghi >> 27) & 1)) {
+ prom_printf(" ** bad parity for valid bit\n");
+ res |= CP0_CERRI_TAG_PARITY;
+ }
+ prom_printf(" %d [VA %016llx] [Vld? %d] raw tags: %08X-%016llX\n",
+ way, va, valid, taghi, taglo);
+
+ if (data) {
+ uint32_t datahi, insta, instb;
+ uint8_t predecode;
+ int offset;
+
+ /* (hit all banks and ways) */
+ for (offset = 0; offset < 4; offset++) {
+ /* Index-load-data-I */
+ __asm__ __volatile__ (
+ " .set push\n\t"
+ " .set noreorder\n\t"
+ " .set mips64\n\t"
+ " .set noat\n\t"
+ " cache 6, 0(%3) \n\t"
+ " mfc0 %0, $29, 1\n\t"
+ " dmfc0 $1, $28, 1\n\t"
+ " dsrl32 %1, $1, 0 \n\t"
+ " sll %2, $1, 0 \n\t"
+ " .set pop \n"
+ : "=r" (datahi), "=r" (insta), "=r" (instb)
+ : "r" ((way << 13) | addr | (offset << 3)));
+ predecode = (datahi >> 8) & 0xff;
+ if (((datahi >> 16) & 1) != (uint32_t)range_parity(predecode, 7, 0)) {
+ prom_printf(" ** bad parity in predecode\n");
+ res |= CP0_CERRI_DATA_PARITY;
+ }
+ /* XXXKW should/could check predecode bits themselves */
+ if (((datahi >> 4) & 0xf) ^ inst_parity(insta)) {
+ prom_printf(" ** bad parity in instruction a\n");
+ res |= CP0_CERRI_DATA_PARITY;
+ }
+ if ((datahi & 0xf) ^ inst_parity(instb)) {
+ prom_printf(" ** bad parity in instruction b\n");
+ res |= CP0_CERRI_DATA_PARITY;
+ }
+ prom_printf(" %05X-%08X%08X", datahi, insta, instb);
+ }
+ prom_printf("\n");
+ }
+ }
+ return res;
+}
+
+/* Compute the ECC for a data doubleword */
+static uint8_t dc_ecc(uint64_t dword)
+{
+ uint64_t t;
+ uint32_t w;
+ uint8_t p;
+ int i;
+
+ p = 0;
+ for (i = 7; i >= 0; i--)
+ {
+ p <<= 1;
+ t = dword & mask_72_64[i];
+ w = (uint32_t)(t >> 32);
+ p ^= (parity[w>>24] ^ parity[(w>>16) & 0xFF]
+ ^ parity[(w>>8) & 0xFF] ^ parity[w & 0xFF]);
+ w = (uint32_t)(t & 0xFFFFFFFF);
+ p ^= (parity[w>>24] ^ parity[(w>>16) & 0xFF]
+ ^ parity[(w>>8) & 0xFF] ^ parity[w & 0xFF]);
+ }
+ return p;
+}
+
+struct dc_state {
+ unsigned char val;
+ char *name;
+};
+
+static struct dc_state dc_states[] = {
+ { 0x00, "INVALID" },
+ { 0x0f, "COH-SHD" },
+ { 0x13, "NCO-E-C" },
+ { 0x19, "NCO-E-D" },
+ { 0x16, "COH-E-C" },
+ { 0x1c, "COH-E-D" },
+ { 0xff, "*ERROR*" }
+};
+
+#define DC_TAG_VALID(state) \
+ (((state) == 0xf) || ((state) == 0x13) || ((state) == 0x19) || ((state == 0x16)) || ((state) == 0x1c))
+
+static char *dc_state_str(unsigned char state)
+{
+ struct dc_state *dsc = dc_states;
+ while (dsc->val != 0xff) {
+ if (dsc->val == state)
+ break;
+ dsc++;
+ }
+ return dsc->name;
+}
+
+static uint32_t extract_dc(unsigned short addr, int data)
+{
+ int valid, way;
+ unsigned char state;
+ uint64_t taglo, pa;
+ uint32_t taghi, taglolo, taglohi;
+ uint8_t ecc, lru;
+ int res = 0;
+
+ prom_printf("Dcache index 0x%04x ", addr);
+ for (way = 0; way < 4; way++) {
+ __asm__ __volatile__ (
+ " .set push\n\t"
+ " .set noreorder\n\t"
+ " .set mips64\n\t"
+ " .set noat\n\t"
+ " cache 5, 0(%3)\n\t" /* Index-load-tag-D */
+ " mfc0 %0, $29, 2\n\t"
+ " dmfc0 $1, $28, 2\n\t"
+ " dsrl32 %1, $1, 0\n\t"
+ " sll %2, $1, 0\n\t"
+ " .set pop"
+ : "=r" (taghi), "=r" (taglohi), "=r" (taglolo)
+ : "r" ((way << 13) | addr));
+
+ taglo = ((unsigned long long)taglohi << 32) | taglolo;
+ pa = (taglo & 0xFFFFFFE000ULL) | addr;
+ if (way == 0) {
+ lru = (taghi >> 14) & 0xff;
+ prom_printf("[Bank %d Set 0x%02x] LRU > %d %d %d %d > MRU\n",
+ ((addr >> 11) & 0x2) | ((addr >> 5) & 1), /* bank */
+ ((addr >> 6) & 0x3f), /* index */
+ (lru & 0x3),
+ ((lru >> 2) & 0x3),
+ ((lru >> 4) & 0x3),
+ ((lru >> 6) & 0x3));
+ }
+ state = (taghi >> 25) & 0x1f;
+ valid = DC_TAG_VALID(state);
+ prom_printf(" %d [PA %010llx] [state %s (%02x)] raw tags: %08X-%016llX\n",
+ way, pa, dc_state_str(state), state, taghi, taglo);
+ if (valid) {
+ if (((taglo >> 11) & 1) ^ range_parity(taglo, 39, 26)) {
+ prom_printf(" ** bad parity in PTag1\n");
+ res |= CP0_CERRD_TAG_ADDRESS;
+ }
+ if (((taglo >> 10) & 1) ^ range_parity(taglo, 25, 13)) {
+ prom_printf(" ** bad parity in PTag0\n");
+ res |= CP0_CERRD_TAG_ADDRESS;
+ }
+ } else {
+ res |= CP0_CERRD_TAG_STATE;
+ }
+
+ if (data) {
+ uint64_t datalo;
+ uint32_t datalohi, datalolo, datahi;
+ int offset;
+
+ for (offset = 0; offset < 4; offset++) {
+ /* Index-load-data-D */
+ __asm__ __volatile__ (
+ " .set push\n\t"
+ " .set noreorder\n\t"
+ " .set mips64\n\t"
+ " .set noat\n\t"
+ " cache 7, 0(%3)\n\t" /* Index-load-data-D */
+ " mfc0 %0, $29, 3\n\t"
+ " dmfc0 $1, $28, 3\n\t"
+ " dsrl32 %1, $1, 0 \n\t"
+ " sll %2, $1, 0 \n\t"
+ " .set pop"
+ : "=r" (datahi), "=r" (datalohi), "=r" (datalolo)
+ : "r" ((way << 13) | addr | (offset << 3)));
+ datalo = ((unsigned long long)datalohi << 32) | datalolo;
+ ecc = dc_ecc(datalo);
+ if (ecc != datahi) {
+ int bits = 0;
+ prom_printf(" ** bad ECC (%02x %02x) ->",
+ datahi, ecc);
+ ecc ^= datahi;
+ while (ecc) {
+ if (ecc & 1) bits++;
+ ecc >>= 1;
+ }
+ res |= (bits == 1) ? CP0_CERRD_DATA_SBE : CP0_CERRD_DATA_DBE;
+ }
+ prom_printf(" %02X-%016llX", datahi, datalo);
+ }
+ prom_printf("\n");
+ }
+ }
+ return res;
+}
diff --git a/arch/mips/mm/cex-gen.S b/arch/mips/mm/cex-gen.S
new file mode 100644
index 0000000..e743622
--- /dev/null
+++ b/arch/mips/mm/cex-gen.S
@@ -0,0 +1,42 @@
+/*
+ * 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 - 1999 Ralf Baechle
+ * Copyright (C) 1999 Silicon Graphics, Inc.
+ *
+ * Cache error handler
+ */
+#include <asm/asm.h>
+#include <asm/regdef.h>
+#include <asm/mipsregs.h>
+#include <asm/stackframe.h>
+
+/*
+ * Game over. Go to the button. Press gently. Swear where allowed by
+ * legislation.
+ */
+ LEAF(except_vec2_generic)
+ .set noreorder
+ .set noat
+ .set mips0
+ /*
+ * This is a very bad place to be. Our cache error
+ * detection has triggered. If we have write-back data
+ * in the cache, we may not be able to recover. As a
+ * first-order desperate measure, turn off KSEG0 cacheing.
+ */
+ mfc0 k0,CP0_CONFIG
+ li k1,~CONF_CM_CMASK
+ and k0,k0,k1
+ ori k0,k0,CONF_CM_UNCACHED
+ mtc0 k0,CP0_CONFIG
+ /* Give it a few cycles to sink in... */
+ nop
+ nop
+ nop
+
+ j cache_parity_error
+ nop
+ END(except_vec2_generic)
diff --git a/arch/mips/mm/cex-sb1.S b/arch/mips/mm/cex-sb1.S
new file mode 100644
index 0000000..2c3a23a
--- /dev/null
+++ b/arch/mips/mm/cex-sb1.S
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2001,2002,2003 Broadcom Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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 <linux/init.h>
+
+#include <asm/asm.h>
+#include <asm/regdef.h>
+#include <asm/mipsregs.h>
+#include <asm/stackframe.h>
+#include <asm/cacheops.h>
+#include <asm/sibyte/board.h>
+
+#define C0_ERRCTL $26 /* CP0: Error info */
+#define C0_CERR_I $27 /* CP0: Icache error */
+#define C0_CERR_D $27,1 /* CP0: Dcache error */
+
+ /*
+ * Based on SiByte sample software cache-err/cerr.S
+ * CVS revision 1.8. Only the 'unrecoverable' case
+ * is changed.
+ */
+
+ __INIT
+
+ .set mips64
+ .set noreorder
+ .set noat
+
+ /*
+ * sb1_cerr_vec: code to be copied to the Cache Error
+ * Exception vector. The code must be pushed out to memory
+ * (either by copying to Kseg0 and Kseg1 both, or by flushing
+ * the L1 and L2) since it is fetched as 0xa0000100.
+ *
+ * NOTE: Be sure this handler is at most 28 instructions long
+ * since the final 16 bytes of the exception vector memory
+ * (0x170-0x17f) are used to preserve k0, k1, and ra.
+ */
+
+LEAF(except_vec2_sb1)
+ /*
+ * If this error is recoverable, we need to exit the handler
+ * without having dirtied any registers. To do this,
+ * save/restore k0 and k1 from low memory (Useg is direct
+ * mapped while ERL=1). Note that we can't save to a
+ * CPU-specific location without ruining a register in the
+ * process. This means we are vulnerable to data corruption
+ * whenever the handler is reentered by a second CPU.
+ */
+ sd k0,0x170($0)
+ sd k1,0x178($0)
+
+ /*
+ * M_ERRCTL_RECOVERABLE is bit 31, which makes it easy to tell
+ * if we can fast-path out of here for a h/w-recovered error.
+ */
+ mfc0 k1,C0_ERRCTL
+ bgtz k1,attempt_recovery
+ sll k0,k1,1
+
+recovered_dcache:
+ /*
+ * Unlock CacheErr-D (which in turn unlocks CacheErr-DPA).
+ * Ought to log the occurence of this recovered dcache error.
+ */
+ b recovered
+ mtc0 $0,C0_CERR_D
+
+attempt_recovery:
+ /*
+ * k0 has C0_ERRCTL << 1, which puts 'DC' at bit 31. Any
+ * Dcache errors we can recover from will take more extensive
+ * processing. For now, they are considered "unrecoverable".
+ * Note that 'DC' becoming set (outside of ERL mode) will
+ * cause 'IC' to clear; so if there's an Icache error, we'll
+ * only find out about it if we recover from this error and
+ * continue executing.
+ */
+ bltz k0,unrecoverable
+ sll k0,1
+
+ /*
+ * k0 has C0_ERRCTL << 2, which puts 'IC' at bit 31. If an
+ * Icache error isn't indicated, I'm not sure why we got here.
+ * Consider that case "unrecoverable" for now.
+ */
+ bgez k0,unrecoverable
+
+attempt_icache_recovery:
+ /*
+ * External icache errors are due to uncorrectable ECC errors
+ * in the L2 cache or Memory Controller and cannot be
+ * recovered here.
+ */
+ mfc0 k0,C0_CERR_I /* delay slot */
+ li k1,1 << 26 /* ICACHE_EXTERNAL */
+ and k1,k0
+ bnez k1,unrecoverable
+ andi k0,0x1fe0
+
+ /*
+ * Since the error is internal, the 'IDX' field from
+ * CacheErr-I is valid and we can just invalidate all blocks
+ * in that set.
+ */
+ cache Index_Invalidate_I,(0<<13)(k0)
+ cache Index_Invalidate_I,(1<<13)(k0)
+ cache Index_Invalidate_I,(2<<13)(k0)
+ cache Index_Invalidate_I,(3<<13)(k0)
+
+ /* Ought to log this recovered icache error */
+
+recovered:
+ /* Restore the saved registers */
+ ld k0,0x170($0)
+ ld k1,0x178($0)
+ eret
+
+unrecoverable:
+ /* Unrecoverable Icache or Dcache error; log it and/or fail */
+ j handle_vec2_sb1
+ nop
+
+END(except_vec2_sb1)
+
+ __FINIT
+
+ LEAF(handle_vec2_sb1)
+ mfc0 k0,CP0_CONFIG
+ li k1,~CONF_CM_CMASK
+ and k0,k0,k1
+ ori k0,k0,CONF_CM_UNCACHED
+ mtc0 k0,CP0_CONFIG
+
+ SSNOP
+ SSNOP
+ SSNOP
+ SSNOP
+ bnezl $0, 1f
+1:
+ mfc0 k0, CP0_STATUS
+ sll k0, k0, 3 # check CU0 (kernel?)
+ bltz k0, 2f
+ nop
+
+ /* Get a valid Kseg0 stack pointer. Any task's stack pointer
+ * will do, although if we ever want to resume execution we
+ * better not have corrupted any state. */
+ get_saved_sp
+ move sp, k1
+
+2:
+ j sb1_cache_error
+ nop
+
+ END(handle_vec2_sb1)
diff --git a/arch/mips/mm/dma-coherent.c b/arch/mips/mm/dma-coherent.c
new file mode 100644
index 0000000..97a50d3
--- /dev/null
+++ b/arch/mips/mm/dma-coherent.c
@@ -0,0 +1,255 @@
+/*
+ * 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) 2000 Ani Joshi <ajoshi@unixbox.com>
+ * Copyright (C) 2000, 2001 Ralf Baechle <ralf@gnu.org>
+ * swiped from i386, and cloned for MIPS by Geert, polished by Ralf.
+ */
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/pci.h>
+
+#include <asm/cache.h>
+#include <asm/io.h>
+
+void *dma_alloc_noncoherent(struct device *dev, size_t size,
+ dma_addr_t * dma_handle, int gfp)
+{
+ void *ret;
+ /* ignore region specifiers */
+ gfp &= ~(__GFP_DMA | __GFP_HIGHMEM);
+
+ if (dev == NULL || (dev->coherent_dma_mask < 0xffffffff))
+ gfp |= GFP_DMA;
+ ret = (void *) __get_free_pages(gfp, get_order(size));
+
+ if (ret != NULL) {
+ memset(ret, 0, size);
+ *dma_handle = virt_to_phys(ret);
+ }
+
+ return ret;
+}
+
+EXPORT_SYMBOL(dma_alloc_noncoherent);
+
+void *dma_alloc_coherent(struct device *dev, size_t size,
+ dma_addr_t * dma_handle, int gfp)
+ __attribute__((alias("dma_alloc_noncoherent")));
+
+EXPORT_SYMBOL(dma_alloc_coherent);
+
+void dma_free_noncoherent(struct device *dev, size_t size, void *vaddr,
+ dma_addr_t dma_handle)
+{
+ unsigned long addr = (unsigned long) vaddr;
+
+ free_pages(addr, get_order(size));
+}
+
+EXPORT_SYMBOL(dma_free_noncoherent);
+
+void dma_free_coherent(struct device *dev, size_t size, void *vaddr,
+ dma_addr_t dma_handle) __attribute__((alias("dma_free_noncoherent")));
+
+EXPORT_SYMBOL(dma_free_coherent);
+
+dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size,
+ enum dma_data_direction direction)
+{
+ BUG_ON(direction == DMA_NONE);
+
+ return __pa(ptr);
+}
+
+EXPORT_SYMBOL(dma_map_single);
+
+void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
+ enum dma_data_direction direction)
+{
+ BUG_ON(direction == DMA_NONE);
+}
+
+EXPORT_SYMBOL(dma_unmap_single);
+
+int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
+ enum dma_data_direction direction)
+{
+ int i;
+
+ BUG_ON(direction == DMA_NONE);
+
+ for (i = 0; i < nents; i++, sg++) {
+ sg->dma_address = (dma_addr_t)page_to_phys(sg->page) + sg->offset;
+ }
+
+ return nents;
+}
+
+EXPORT_SYMBOL(dma_map_sg);
+
+dma_addr_t dma_map_page(struct device *dev, struct page *page,
+ unsigned long offset, size_t size, enum dma_data_direction direction)
+{
+ BUG_ON(direction == DMA_NONE);
+
+ return page_to_phys(page) + offset;
+}
+
+EXPORT_SYMBOL(dma_map_page);
+
+void dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
+ enum dma_data_direction direction)
+{
+ BUG_ON(direction == DMA_NONE);
+}
+
+EXPORT_SYMBOL(dma_unmap_page);
+
+void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
+ enum dma_data_direction direction)
+{
+ BUG_ON(direction == DMA_NONE);
+}
+
+EXPORT_SYMBOL(dma_unmap_sg);
+
+void dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle,
+ size_t size, enum dma_data_direction direction)
+{
+ BUG_ON(direction == DMA_NONE);
+}
+
+EXPORT_SYMBOL(dma_sync_single_for_cpu);
+
+void dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle,
+ size_t size, enum dma_data_direction direction)
+{
+ BUG_ON(direction == DMA_NONE);
+}
+
+EXPORT_SYMBOL(dma_sync_single_for_device);
+
+void dma_sync_single_range_for_cpu(struct device *dev, dma_addr_t dma_handle,
+ unsigned long offset, size_t size,
+ enum dma_data_direction direction)
+{
+ BUG_ON(direction == DMA_NONE);
+}
+
+EXPORT_SYMBOL(dma_sync_single_range_for_cpu);
+
+void dma_sync_single_range_for_device(struct device *dev, dma_addr_t dma_handle,
+ unsigned long offset, size_t size,
+ enum dma_data_direction direction)
+{
+ BUG_ON(direction == DMA_NONE);
+}
+
+EXPORT_SYMBOL(dma_sync_single_range_for_device);
+
+void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems,
+ enum dma_data_direction direction)
+{
+ BUG_ON(direction == DMA_NONE);
+}
+
+EXPORT_SYMBOL(dma_sync_sg_for_cpu);
+
+void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems,
+ enum dma_data_direction direction)
+{
+ BUG_ON(direction == DMA_NONE);
+}
+
+EXPORT_SYMBOL(dma_sync_sg_for_device);
+
+int dma_mapping_error(dma_addr_t dma_addr)
+{
+ return 0;
+}
+
+EXPORT_SYMBOL(dma_mapping_error);
+
+int dma_supported(struct device *dev, u64 mask)
+{
+ /*
+ * we fall back to GFP_DMA when the mask isn't all 1s,
+ * so we can't guarantee allocations that must be
+ * within a tighter range than GFP_DMA..
+ */
+ if (mask < 0x00ffffff)
+ return 0;
+
+ return 1;
+}
+
+EXPORT_SYMBOL(dma_supported);
+
+int dma_is_consistent(dma_addr_t dma_addr)
+{
+ return 1;
+}
+
+EXPORT_SYMBOL(dma_is_consistent);
+
+void dma_cache_sync(void *vaddr, size_t size,
+ enum dma_data_direction direction)
+{
+ BUG_ON(direction == DMA_NONE);
+}
+
+EXPORT_SYMBOL(dma_cache_sync);
+
+/* The DAC routines are a PCIism.. */
+
+#ifdef CONFIG_PCI
+
+#include <linux/pci.h>
+
+dma64_addr_t pci_dac_page_to_dma(struct pci_dev *pdev,
+ struct page *page, unsigned long offset, int direction)
+{
+ return (dma64_addr_t)page_to_phys(page) + offset;
+}
+
+EXPORT_SYMBOL(pci_dac_page_to_dma);
+
+struct page *pci_dac_dma_to_page(struct pci_dev *pdev,
+ dma64_addr_t dma_addr)
+{
+ return mem_map + (dma_addr >> PAGE_SHIFT);
+}
+
+EXPORT_SYMBOL(pci_dac_dma_to_page);
+
+unsigned long pci_dac_dma_to_offset(struct pci_dev *pdev,
+ dma64_addr_t dma_addr)
+{
+ return dma_addr & ~PAGE_MASK;
+}
+
+EXPORT_SYMBOL(pci_dac_dma_to_offset);
+
+void pci_dac_dma_sync_single_for_cpu(struct pci_dev *pdev,
+ dma64_addr_t dma_addr, size_t len, int direction)
+{
+ BUG_ON(direction == PCI_DMA_NONE);
+}
+
+EXPORT_SYMBOL(pci_dac_dma_sync_single_for_cpu);
+
+void pci_dac_dma_sync_single_for_device(struct pci_dev *pdev,
+ dma64_addr_t dma_addr, size_t len, int direction)
+{
+ BUG_ON(direction == PCI_DMA_NONE);
+}
+
+EXPORT_SYMBOL(pci_dac_dma_sync_single_for_device);
+
+#endif /* CONFIG_PCI */
diff --git a/arch/mips/mm/dma-ip27.c b/arch/mips/mm/dma-ip27.c
new file mode 100644
index 0000000..aa7c94b
--- /dev/null
+++ b/arch/mips/mm/dma-ip27.c
@@ -0,0 +1,257 @@
+/*
+ * 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) 2000 Ani Joshi <ajoshi@unixbox.com>
+ * Copyright (C) 2000, 2001 Ralf Baechle <ralf@gnu.org>
+ * swiped from i386, and cloned for MIPS by Geert, polished by Ralf.
+ */
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/pci.h>
+
+#include <asm/cache.h>
+#include <asm/pci/bridge.h>
+
+#define pdev_to_baddr(pdev, addr) \
+ (BRIDGE_CONTROLLER(pdev->bus)->baddr + (addr))
+#define dev_to_baddr(dev, addr) \
+ pdev_to_baddr(to_pci_dev(dev), (addr))
+
+void *dma_alloc_noncoherent(struct device *dev, size_t size,
+ dma_addr_t * dma_handle, int gfp)
+{
+ void *ret;
+
+ /* ignore region specifiers */
+ gfp &= ~(__GFP_DMA | __GFP_HIGHMEM);
+
+ if (dev == NULL || (dev->coherent_dma_mask < 0xffffffff))
+ gfp |= GFP_DMA;
+ ret = (void *) __get_free_pages(gfp, get_order(size));
+
+ if (ret != NULL) {
+ memset(ret, 0, size);
+ *dma_handle = dev_to_baddr(dev, virt_to_phys(ret));
+ }
+
+ return ret;
+}
+
+EXPORT_SYMBOL(dma_alloc_noncoherent);
+
+void *dma_alloc_coherent(struct device *dev, size_t size,
+ dma_addr_t * dma_handle, int gfp)
+ __attribute__((alias("dma_alloc_noncoherent")));
+
+EXPORT_SYMBOL(dma_alloc_coherent);
+
+void dma_free_noncoherent(struct device *dev, size_t size, void *vaddr,
+ dma_addr_t dma_handle)
+{
+ unsigned long addr = (unsigned long) vaddr;
+
+ free_pages(addr, get_order(size));
+}
+
+EXPORT_SYMBOL(dma_free_noncoherent);
+
+void dma_free_coherent(struct device *dev, size_t size, void *vaddr,
+ dma_addr_t dma_handle) __attribute__((alias("dma_free_noncoherent")));
+
+EXPORT_SYMBOL(dma_free_coherent);
+
+dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size,
+ enum dma_data_direction direction)
+{
+ BUG_ON(direction == DMA_NONE);
+
+ return dev_to_baddr(dev, __pa(ptr));
+}
+
+EXPORT_SYMBOL(dma_map_single);
+
+void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
+ enum dma_data_direction direction)
+{
+ BUG_ON(direction == DMA_NONE);
+}
+
+EXPORT_SYMBOL(dma_unmap_single);
+
+int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
+ enum dma_data_direction direction)
+{
+ int i;
+
+ BUG_ON(direction == DMA_NONE);
+
+ for (i = 0; i < nents; i++, sg++) {
+ sg->dma_address = (dma_addr_t) dev_to_baddr(dev,
+ page_to_phys(sg->page) + sg->offset);
+ }
+
+ return nents;
+}
+
+EXPORT_SYMBOL(dma_map_sg);
+
+dma_addr_t dma_map_page(struct device *dev, struct page *page,
+ unsigned long offset, size_t size, enum dma_data_direction direction)
+{
+ BUG_ON(direction == DMA_NONE);
+
+ return dev_to_baddr(dev, page_to_phys(page) + offset);
+}
+
+EXPORT_SYMBOL(dma_map_page);
+
+void dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
+ enum dma_data_direction direction)
+{
+ BUG_ON(direction == DMA_NONE);
+}
+
+EXPORT_SYMBOL(dma_unmap_page);
+
+void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
+ enum dma_data_direction direction)
+{
+ BUG_ON(direction == DMA_NONE);
+}
+
+EXPORT_SYMBOL(dma_unmap_sg);
+
+void dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size,
+ enum dma_data_direction direction)
+{
+ BUG_ON(direction == DMA_NONE);
+}
+
+EXPORT_SYMBOL(dma_sync_single_for_cpu);
+
+void dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, size_t size,
+ enum dma_data_direction direction)
+{
+ BUG_ON(direction == DMA_NONE);
+}
+
+EXPORT_SYMBOL(dma_sync_single_for_device);
+
+void dma_sync_single_range_for_cpu(struct device *dev, dma_addr_t dma_handle,
+ unsigned long offset, size_t size,
+ enum dma_data_direction direction)
+{
+ BUG_ON(direction == DMA_NONE);
+}
+
+EXPORT_SYMBOL(dma_sync_single_range_for_cpu);
+
+void dma_sync_single_range_for_device(struct device *dev, dma_addr_t dma_handle,
+ unsigned long offset, size_t size,
+ enum dma_data_direction direction)
+{
+ BUG_ON(direction == DMA_NONE);
+}
+
+EXPORT_SYMBOL(dma_sync_single_range_for_device);
+
+void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems,
+ enum dma_data_direction direction)
+{
+ BUG_ON(direction == DMA_NONE);
+}
+
+EXPORT_SYMBOL(dma_sync_sg_for_cpu);
+
+void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems,
+ enum dma_data_direction direction)
+{
+ BUG_ON(direction == DMA_NONE);
+}
+
+EXPORT_SYMBOL(dma_sync_sg_for_device);
+
+int dma_mapping_error(dma_addr_t dma_addr)
+{
+ return 0;
+}
+
+EXPORT_SYMBOL(dma_mapping_error);
+
+int dma_supported(struct device *dev, u64 mask)
+{
+ /*
+ * we fall back to GFP_DMA when the mask isn't all 1s,
+ * so we can't guarantee allocations that must be
+ * within a tighter range than GFP_DMA..
+ */
+ if (mask < 0x00ffffff)
+ return 0;
+
+ return 1;
+}
+
+EXPORT_SYMBOL(dma_supported);
+
+int dma_is_consistent(dma_addr_t dma_addr)
+{
+ return 1;
+}
+
+EXPORT_SYMBOL(dma_is_consistent);
+
+void dma_cache_sync(void *vaddr, size_t size,
+ enum dma_data_direction direction)
+{
+ BUG_ON(direction == DMA_NONE);
+}
+
+EXPORT_SYMBOL(dma_cache_sync);
+
+dma64_addr_t pci_dac_page_to_dma(struct pci_dev *pdev,
+ struct page *page, unsigned long offset, int direction)
+{
+ dma64_addr_t addr = page_to_phys(page) + offset;
+
+ return (dma64_addr_t) pdev_to_baddr(pdev, addr);
+}
+
+EXPORT_SYMBOL(pci_dac_page_to_dma);
+
+struct page *pci_dac_dma_to_page(struct pci_dev *pdev,
+ dma64_addr_t dma_addr)
+{
+ struct bridge_controller *bc = BRIDGE_CONTROLLER(pdev->bus);
+
+ return pfn_to_page((dma_addr - bc->baddr) >> PAGE_SHIFT);
+}
+
+EXPORT_SYMBOL(pci_dac_dma_to_page);
+
+unsigned long pci_dac_dma_to_offset(struct pci_dev *pdev,
+ dma64_addr_t dma_addr)
+{
+ return dma_addr & ~PAGE_MASK;
+}
+
+EXPORT_SYMBOL(pci_dac_dma_to_offset);
+
+void pci_dac_dma_sync_single_for_cpu(struct pci_dev *pdev,
+ dma64_addr_t dma_addr, size_t len, int direction)
+{
+ BUG_ON(direction == PCI_DMA_NONE);
+}
+
+EXPORT_SYMBOL(pci_dac_dma_sync_single_for_cpu);
+
+void pci_dac_dma_sync_single_for_device(struct pci_dev *pdev,
+ dma64_addr_t dma_addr, size_t len, int direction)
+{
+ BUG_ON(direction == PCI_DMA_NONE);
+}
+
+EXPORT_SYMBOL(pci_dac_dma_sync_single_for_device);
diff --git a/arch/mips/mm/dma-ip32.c b/arch/mips/mm/dma-ip32.c
new file mode 100644
index 0000000..2cbe196
--- /dev/null
+++ b/arch/mips/mm/dma-ip32.c
@@ -0,0 +1,382 @@
+/*
+ * 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) 2000 Ani Joshi <ajoshi@unixbox.com>
+ * Copyright (C) 2000, 2001 Ralf Baechle <ralf@gnu.org>
+ * Copyright (C) 2005 Ilya A. Volynets-Evenbakh <ilya@total-knowledge.com>
+ * swiped from i386, and cloned for MIPS by Geert, polished by Ralf.
+ * IP32 changes by Ilya.
+ */
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/dma-mapping.h>
+
+#include <asm/cache.h>
+#include <asm/io.h>
+#include <asm/ip32/crime.h>
+
+/*
+ * Warning on the terminology - Linux calls an uncached area coherent;
+ * MIPS terminology calls memory areas with hardware maintained coherency
+ * coherent.
+ */
+
+/*
+ * Few notes.
+ * 1. CPU sees memory as two chunks: 0-256M@0x0, and the rest @0x40000000+256M
+ * 2. PCI sees memory as one big chunk @0x0 (or we could use 0x40000000 for native-endian)
+ * 3. All other devices see memory as one big chunk at 0x40000000
+ * 4. Non-PCI devices will pass NULL as struct device*
+ * Thus we translate differently, depending on device.
+ */
+
+#define RAM_OFFSET_MASK 0x3fffffff
+
+void *dma_alloc_noncoherent(struct device *dev, size_t size,
+ dma_addr_t * dma_handle, int gfp)
+{
+ void *ret;
+ /* ignore region specifiers */
+ gfp &= ~(__GFP_DMA | __GFP_HIGHMEM);
+
+ if (dev == NULL || (dev->coherent_dma_mask < 0xffffffff))
+ gfp |= GFP_DMA;
+ ret = (void *) __get_free_pages(gfp, get_order(size));
+
+ if (ret != NULL) {
+ unsigned long addr = virt_to_phys(ret)&RAM_OFFSET_MASK;
+ memset(ret, 0, size);
+ if(dev==NULL)
+ addr+= CRIME_HI_MEM_BASE;
+ *dma_handle = addr;
+ }
+
+ return ret;
+}
+
+EXPORT_SYMBOL(dma_alloc_noncoherent);
+
+void *dma_alloc_coherent(struct device *dev, size_t size,
+ dma_addr_t * dma_handle, int gfp)
+{
+ void *ret;
+
+ ret = dma_alloc_noncoherent(dev, size, dma_handle, gfp);
+ if (ret) {
+ dma_cache_wback_inv((unsigned long) ret, size);
+ ret = UNCAC_ADDR(ret);
+ }
+
+ return ret;
+}
+
+EXPORT_SYMBOL(dma_alloc_coherent);
+
+void dma_free_noncoherent(struct device *dev, size_t size, void *vaddr,
+ dma_addr_t dma_handle)
+{
+ free_pages((unsigned long) vaddr, get_order(size));
+}
+
+EXPORT_SYMBOL(dma_free_noncoherent);
+
+void dma_free_coherent(struct device *dev, size_t size, void *vaddr,
+ dma_addr_t dma_handle)
+{
+ unsigned long addr = (unsigned long) vaddr;
+
+ addr = CAC_ADDR(addr);
+ free_pages(addr, get_order(size));
+}
+
+EXPORT_SYMBOL(dma_free_coherent);
+
+static inline void __dma_sync(unsigned long addr, size_t size,
+ enum dma_data_direction direction)
+{
+ switch (direction) {
+ case DMA_TO_DEVICE:
+ dma_cache_wback(addr, size);
+ break;
+
+ case DMA_FROM_DEVICE:
+ dma_cache_inv(addr, size);
+ break;
+
+ case DMA_BIDIRECTIONAL:
+ dma_cache_wback_inv(addr, size);
+ break;
+
+ default:
+ BUG();
+ }
+}
+
+dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size,
+ enum dma_data_direction direction)
+{
+ unsigned long addr = (unsigned long) ptr;
+
+ switch (direction) {
+ case DMA_TO_DEVICE:
+ dma_cache_wback(addr, size);
+ break;
+
+ case DMA_FROM_DEVICE:
+ dma_cache_inv(addr, size);
+ break;
+
+ case DMA_BIDIRECTIONAL:
+ dma_cache_wback_inv(addr, size);
+ break;
+
+ default:
+ BUG();
+ }
+
+ addr = virt_to_phys(ptr)&RAM_OFFSET_MASK;;
+ if(dev == NULL)
+ addr+=CRIME_HI_MEM_BASE;
+ return (dma_addr_t)addr;
+}
+
+EXPORT_SYMBOL(dma_map_single);
+
+void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
+ enum dma_data_direction direction)
+{
+ switch (direction) {
+ case DMA_TO_DEVICE:
+ break;
+
+ case DMA_FROM_DEVICE:
+ break;
+
+ case DMA_BIDIRECTIONAL:
+ break;
+
+ default:
+ BUG();
+ }
+}
+
+EXPORT_SYMBOL(dma_unmap_single);
+
+int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
+ enum dma_data_direction direction)
+{
+ int i;
+
+ BUG_ON(direction == DMA_NONE);
+
+ for (i = 0; i < nents; i++, sg++) {
+ unsigned long addr;
+
+ addr = (unsigned long) page_address(sg->page)+sg->offset;
+ if (addr)
+ __dma_sync(addr, sg->length, direction);
+ addr = __pa(addr)&RAM_OFFSET_MASK;;
+ if(dev == NULL)
+ addr += CRIME_HI_MEM_BASE;
+ sg->dma_address = (dma_addr_t)addr;
+ }
+
+ return nents;
+}
+
+EXPORT_SYMBOL(dma_map_sg);
+
+dma_addr_t dma_map_page(struct device *dev, struct page *page,
+ unsigned long offset, size_t size, enum dma_data_direction direction)
+{
+ unsigned long addr;
+
+ BUG_ON(direction == DMA_NONE);
+
+ addr = (unsigned long) page_address(page) + offset;
+ dma_cache_wback_inv(addr, size);
+ addr = __pa(addr)&RAM_OFFSET_MASK;;
+ if(dev == NULL)
+ addr += CRIME_HI_MEM_BASE;
+
+ return (dma_addr_t)addr;
+}
+
+EXPORT_SYMBOL(dma_map_page);
+
+void dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
+ enum dma_data_direction direction)
+{
+ BUG_ON(direction == DMA_NONE);
+
+ if (direction != DMA_TO_DEVICE) {
+ unsigned long addr;
+
+ dma_address&=RAM_OFFSET_MASK;
+ addr = dma_address + PAGE_OFFSET;
+ if(dma_address>=256*1024*1024)
+ addr+=CRIME_HI_MEM_BASE;
+ dma_cache_wback_inv(addr, size);
+ }
+}
+
+EXPORT_SYMBOL(dma_unmap_page);
+
+void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
+ enum dma_data_direction direction)
+{
+ unsigned long addr;
+ int i;
+
+ BUG_ON(direction == DMA_NONE);
+
+ if (direction == DMA_TO_DEVICE)
+ return;
+
+ for (i = 0; i < nhwentries; i++, sg++) {
+ addr = (unsigned long) page_address(sg->page);
+ if (!addr)
+ continue;
+ dma_cache_wback_inv(addr + sg->offset, sg->length);
+ }
+}
+
+EXPORT_SYMBOL(dma_unmap_sg);
+
+void dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle,
+ size_t size, enum dma_data_direction direction)
+{
+ unsigned long addr;
+
+ BUG_ON(direction == DMA_NONE);
+
+ dma_handle&=RAM_OFFSET_MASK;
+ addr = dma_handle + PAGE_OFFSET;
+ if(dma_handle>=256*1024*1024)
+ addr+=CRIME_HI_MEM_BASE;
+ __dma_sync(addr, size, direction);
+}
+
+EXPORT_SYMBOL(dma_sync_single_for_cpu);
+
+void dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle,
+ size_t size, enum dma_data_direction direction)
+{
+ unsigned long addr;
+
+ BUG_ON(direction == DMA_NONE);
+
+ dma_handle&=RAM_OFFSET_MASK;
+ addr = dma_handle + PAGE_OFFSET;
+ if(dma_handle>=256*1024*1024)
+ addr+=CRIME_HI_MEM_BASE;
+ __dma_sync(addr, size, direction);
+}
+
+EXPORT_SYMBOL(dma_sync_single_for_device);
+
+void dma_sync_single_range_for_cpu(struct device *dev, dma_addr_t dma_handle,
+ unsigned long offset, size_t size, enum dma_data_direction direction)
+{
+ unsigned long addr;
+
+ BUG_ON(direction == DMA_NONE);
+
+ dma_handle&=RAM_OFFSET_MASK;
+ addr = dma_handle + offset + PAGE_OFFSET;
+ if(dma_handle>=256*1024*1024)
+ addr+=CRIME_HI_MEM_BASE;
+ __dma_sync(addr, size, direction);
+}
+
+EXPORT_SYMBOL(dma_sync_single_range_for_cpu);
+
+void dma_sync_single_range_for_device(struct device *dev, dma_addr_t dma_handle,
+ unsigned long offset, size_t size, enum dma_data_direction direction)
+{
+ unsigned long addr;
+
+ BUG_ON(direction == DMA_NONE);
+
+ dma_handle&=RAM_OFFSET_MASK;
+ addr = dma_handle + offset + PAGE_OFFSET;
+ if(dma_handle>=256*1024*1024)
+ addr+=CRIME_HI_MEM_BASE;
+ __dma_sync(addr, size, direction);
+}
+
+EXPORT_SYMBOL(dma_sync_single_range_for_device);
+
+void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems,
+ enum dma_data_direction direction)
+{
+ int i;
+
+ BUG_ON(direction == DMA_NONE);
+
+ /* Make sure that gcc doesn't leave the empty loop body. */
+ for (i = 0; i < nelems; i++, sg++)
+ __dma_sync((unsigned long)page_address(sg->page),
+ sg->length, direction);
+}
+
+EXPORT_SYMBOL(dma_sync_sg_for_cpu);
+
+void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems,
+ enum dma_data_direction direction)
+{
+ int i;
+
+ BUG_ON(direction == DMA_NONE);
+
+ /* Make sure that gcc doesn't leave the empty loop body. */
+ for (i = 0; i < nelems; i++, sg++)
+ __dma_sync((unsigned long)page_address(sg->page),
+ sg->length, direction);
+}
+
+EXPORT_SYMBOL(dma_sync_sg_for_device);
+
+int dma_mapping_error(dma_addr_t dma_addr)
+{
+ return 0;
+}
+
+EXPORT_SYMBOL(dma_mapping_error);
+
+int dma_supported(struct device *dev, u64 mask)
+{
+ /*
+ * we fall back to GFP_DMA when the mask isn't all 1s,
+ * so we can't guarantee allocations that must be
+ * within a tighter range than GFP_DMA..
+ */
+ if (mask < 0x00ffffff)
+ return 0;
+
+ return 1;
+}
+
+EXPORT_SYMBOL(dma_supported);
+
+int dma_is_consistent(dma_addr_t dma_addr)
+{
+ return 1;
+}
+
+EXPORT_SYMBOL(dma_is_consistent);
+
+void dma_cache_sync(void *vaddr, size_t size, enum dma_data_direction direction)
+{
+ if (direction == DMA_NONE)
+ return;
+
+ dma_cache_wback_inv((unsigned long)vaddr, size);
+}
+
+EXPORT_SYMBOL(dma_cache_sync);
+
diff --git a/arch/mips/mm/dma-noncoherent.c b/arch/mips/mm/dma-noncoherent.c
new file mode 100644
index 0000000..9895e32
--- /dev/null
+++ b/arch/mips/mm/dma-noncoherent.c
@@ -0,0 +1,400 @@
+/*
+ * 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) 2000 Ani Joshi <ajoshi@unixbox.com>
+ * Copyright (C) 2000, 2001 Ralf Baechle <ralf@gnu.org>
+ * swiped from i386, and cloned for MIPS by Geert, polished by Ralf.
+ */
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/dma-mapping.h>
+
+#include <asm/cache.h>
+#include <asm/io.h>
+
+/*
+ * Warning on the terminology - Linux calls an uncached area coherent;
+ * MIPS terminology calls memory areas with hardware maintained coherency
+ * coherent.
+ */
+
+void *dma_alloc_noncoherent(struct device *dev, size_t size,
+ dma_addr_t * dma_handle, int gfp)
+{
+ void *ret;
+ /* ignore region specifiers */
+ gfp &= ~(__GFP_DMA | __GFP_HIGHMEM);
+
+ if (dev == NULL || (dev->coherent_dma_mask < 0xffffffff))
+ gfp |= GFP_DMA;
+ ret = (void *) __get_free_pages(gfp, get_order(size));
+
+ if (ret != NULL) {
+ memset(ret, 0, size);
+ *dma_handle = virt_to_phys(ret);
+ }
+
+ return ret;
+}
+
+EXPORT_SYMBOL(dma_alloc_noncoherent);
+
+void *dma_alloc_coherent(struct device *dev, size_t size,
+ dma_addr_t * dma_handle, int gfp)
+{
+ void *ret;
+
+ ret = dma_alloc_noncoherent(dev, size, dma_handle, gfp);
+ if (ret) {
+ dma_cache_wback_inv((unsigned long) ret, size);
+ ret = UNCAC_ADDR(ret);
+ }
+
+ return ret;
+}
+
+EXPORT_SYMBOL(dma_alloc_coherent);
+
+void dma_free_noncoherent(struct device *dev, size_t size, void *vaddr,
+ dma_addr_t dma_handle)
+{
+ free_pages((unsigned long) vaddr, get_order(size));
+}
+
+EXPORT_SYMBOL(dma_free_noncoherent);
+
+void dma_free_coherent(struct device *dev, size_t size, void *vaddr,
+ dma_addr_t dma_handle)
+{
+ unsigned long addr = (unsigned long) vaddr;
+
+ addr = CAC_ADDR(addr);
+ free_pages(addr, get_order(size));
+}
+
+EXPORT_SYMBOL(dma_free_coherent);
+
+static inline void __dma_sync(unsigned long addr, size_t size,
+ enum dma_data_direction direction)
+{
+ switch (direction) {
+ case DMA_TO_DEVICE:
+ dma_cache_wback(addr, size);
+ break;
+
+ case DMA_FROM_DEVICE:
+ dma_cache_inv(addr, size);
+ break;
+
+ case DMA_BIDIRECTIONAL:
+ dma_cache_wback_inv(addr, size);
+ break;
+
+ default:
+ BUG();
+ }
+}
+
+dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size,
+ enum dma_data_direction direction)
+{
+ unsigned long addr = (unsigned long) ptr;
+
+ switch (direction) {
+ case DMA_TO_DEVICE:
+ dma_cache_wback(addr, size);
+ break;
+
+ case DMA_FROM_DEVICE:
+ dma_cache_inv(addr, size);
+ break;
+
+ case DMA_BIDIRECTIONAL:
+ dma_cache_wback_inv(addr, size);
+ break;
+
+ default:
+ BUG();
+ }
+
+ return virt_to_phys(ptr);
+}
+
+EXPORT_SYMBOL(dma_map_single);
+
+void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
+ enum dma_data_direction direction)
+{
+ unsigned long addr;
+ addr = dma_addr + PAGE_OFFSET;
+
+ switch (direction) {
+ case DMA_TO_DEVICE:
+ //dma_cache_wback(addr, size);
+ break;
+
+ case DMA_FROM_DEVICE:
+ //dma_cache_inv(addr, size);
+ break;
+
+ case DMA_BIDIRECTIONAL:
+ //dma_cache_wback_inv(addr, size);
+ break;
+
+ default:
+ BUG();
+ }
+}
+
+EXPORT_SYMBOL(dma_unmap_single);
+
+int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
+ enum dma_data_direction direction)
+{
+ int i;
+
+ BUG_ON(direction == DMA_NONE);
+
+ for (i = 0; i < nents; i++, sg++) {
+ unsigned long addr;
+
+ addr = (unsigned long) page_address(sg->page);
+ if (addr)
+ __dma_sync(addr + sg->offset, sg->length, direction);
+ sg->dma_address = (dma_addr_t)
+ (page_to_phys(sg->page) + sg->offset);
+ }
+
+ return nents;
+}
+
+EXPORT_SYMBOL(dma_map_sg);
+
+dma_addr_t dma_map_page(struct device *dev, struct page *page,
+ unsigned long offset, size_t size, enum dma_data_direction direction)
+{
+ unsigned long addr;
+
+ BUG_ON(direction == DMA_NONE);
+
+ addr = (unsigned long) page_address(page) + offset;
+ dma_cache_wback_inv(addr, size);
+
+ return page_to_phys(page) + offset;
+}
+
+EXPORT_SYMBOL(dma_map_page);
+
+void dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
+ enum dma_data_direction direction)
+{
+ BUG_ON(direction == DMA_NONE);
+
+ if (direction != DMA_TO_DEVICE) {
+ unsigned long addr;
+
+ addr = dma_address + PAGE_OFFSET;
+ dma_cache_wback_inv(addr, size);
+ }
+}
+
+EXPORT_SYMBOL(dma_unmap_page);
+
+void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
+ enum dma_data_direction direction)
+{
+ unsigned long addr;
+ int i;
+
+ BUG_ON(direction == DMA_NONE);
+
+ if (direction == DMA_TO_DEVICE)
+ return;
+
+ for (i = 0; i < nhwentries; i++, sg++) {
+ addr = (unsigned long) page_address(sg->page);
+ if (!addr)
+ continue;
+ dma_cache_wback_inv(addr + sg->offset, sg->length);
+ }
+}
+
+EXPORT_SYMBOL(dma_unmap_sg);
+
+void dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle,
+ size_t size, enum dma_data_direction direction)
+{
+ unsigned long addr;
+
+ BUG_ON(direction == DMA_NONE);
+
+ addr = dma_handle + PAGE_OFFSET;
+ __dma_sync(addr, size, direction);
+}
+
+EXPORT_SYMBOL(dma_sync_single_for_cpu);
+
+void dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle,
+ size_t size, enum dma_data_direction direction)
+{
+ unsigned long addr;
+
+ BUG_ON(direction == DMA_NONE);
+
+ addr = dma_handle + PAGE_OFFSET;
+ __dma_sync(addr, size, direction);
+}
+
+EXPORT_SYMBOL(dma_sync_single_for_device);
+
+void dma_sync_single_range_for_cpu(struct device *dev, dma_addr_t dma_handle,
+ unsigned long offset, size_t size, enum dma_data_direction direction)
+{
+ unsigned long addr;
+
+ BUG_ON(direction == DMA_NONE);
+
+ addr = dma_handle + offset + PAGE_OFFSET;
+ __dma_sync(addr, size, direction);
+}
+
+EXPORT_SYMBOL(dma_sync_single_range_for_cpu);
+
+void dma_sync_single_range_for_device(struct device *dev, dma_addr_t dma_handle,
+ unsigned long offset, size_t size, enum dma_data_direction direction)
+{
+ unsigned long addr;
+
+ BUG_ON(direction == DMA_NONE);
+
+ addr = dma_handle + offset + PAGE_OFFSET;
+ __dma_sync(addr, size, direction);
+}
+
+EXPORT_SYMBOL(dma_sync_single_range_for_device);
+
+void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems,
+ enum dma_data_direction direction)
+{
+ int i;
+
+ BUG_ON(direction == DMA_NONE);
+
+ /* Make sure that gcc doesn't leave the empty loop body. */
+ for (i = 0; i < nelems; i++, sg++)
+ __dma_sync((unsigned long)page_address(sg->page),
+ sg->length, direction);
+}
+
+EXPORT_SYMBOL(dma_sync_sg_for_cpu);
+
+void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems,
+ enum dma_data_direction direction)
+{
+ int i;
+
+ BUG_ON(direction == DMA_NONE);
+
+ /* Make sure that gcc doesn't leave the empty loop body. */
+ for (i = 0; i < nelems; i++, sg++)
+ __dma_sync((unsigned long)page_address(sg->page),
+ sg->length, direction);
+}
+
+EXPORT_SYMBOL(dma_sync_sg_for_device);
+
+int dma_mapping_error(dma_addr_t dma_addr)
+{
+ return 0;
+}
+
+EXPORT_SYMBOL(dma_mapping_error);
+
+int dma_supported(struct device *dev, u64 mask)
+{
+ /*
+ * we fall back to GFP_DMA when the mask isn't all 1s,
+ * so we can't guarantee allocations that must be
+ * within a tighter range than GFP_DMA..
+ */
+ if (mask < 0x00ffffff)
+ return 0;
+
+ return 1;
+}
+
+EXPORT_SYMBOL(dma_supported);
+
+int dma_is_consistent(dma_addr_t dma_addr)
+{
+ return 1;
+}
+
+EXPORT_SYMBOL(dma_is_consistent);
+
+void dma_cache_sync(void *vaddr, size_t size, enum dma_data_direction direction)
+{
+ if (direction == DMA_NONE)
+ return;
+
+ dma_cache_wback_inv((unsigned long)vaddr, size);
+}
+
+EXPORT_SYMBOL(dma_cache_sync);
+
+/* The DAC routines are a PCIism.. */
+
+#ifdef CONFIG_PCI
+
+#include <linux/pci.h>
+
+dma64_addr_t pci_dac_page_to_dma(struct pci_dev *pdev,
+ struct page *page, unsigned long offset, int direction)
+{
+ return (dma64_addr_t)page_to_phys(page) + offset;
+}
+
+EXPORT_SYMBOL(pci_dac_page_to_dma);
+
+struct page *pci_dac_dma_to_page(struct pci_dev *pdev,
+ dma64_addr_t dma_addr)
+{
+ return mem_map + (dma_addr >> PAGE_SHIFT);
+}
+
+EXPORT_SYMBOL(pci_dac_dma_to_page);
+
+unsigned long pci_dac_dma_to_offset(struct pci_dev *pdev,
+ dma64_addr_t dma_addr)
+{
+ return dma_addr & ~PAGE_MASK;
+}
+
+EXPORT_SYMBOL(pci_dac_dma_to_offset);
+
+void pci_dac_dma_sync_single_for_cpu(struct pci_dev *pdev,
+ dma64_addr_t dma_addr, size_t len, int direction)
+{
+ BUG_ON(direction == PCI_DMA_NONE);
+
+ dma_cache_wback_inv(dma_addr + PAGE_OFFSET, len);
+}
+
+EXPORT_SYMBOL(pci_dac_dma_sync_single_for_cpu);
+
+void pci_dac_dma_sync_single_for_device(struct pci_dev *pdev,
+ dma64_addr_t dma_addr, size_t len, int direction)
+{
+ BUG_ON(direction == PCI_DMA_NONE);
+
+ dma_cache_wback_inv(dma_addr + PAGE_OFFSET, len);
+}
+
+EXPORT_SYMBOL(pci_dac_dma_sync_single_for_device);
+
+#endif /* CONFIG_PCI */
diff --git a/arch/mips/mm/extable.c b/arch/mips/mm/extable.c
new file mode 100644
index 0000000..297fb9f
--- /dev/null
+++ b/arch/mips/mm/extable.c
@@ -0,0 +1,21 @@
+/*
+ * linux/arch/mips/mm/extable.c
+ */
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <asm/branch.h>
+#include <asm/uaccess.h>
+
+int fixup_exception(struct pt_regs *regs)
+{
+ const struct exception_table_entry *fixup;
+
+ fixup = search_exception_tables(exception_epc(regs));
+ if (fixup) {
+ regs->cp0_epc = fixup->nextinsn;
+
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/arch/mips/mm/fault.c b/arch/mips/mm/fault.c
new file mode 100644
index 0000000..ec8077c
--- /dev/null
+++ b/arch/mips/mm/fault.c
@@ -0,0 +1,236 @@
+/*
+ * 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 <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/ptrace.h>
+#include <linux/mman.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/vt_kern.h> /* For unblank_screen() */
+#include <linux/module.h>
+
+#include <asm/branch.h>
+#include <asm/mmu_context.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+#include <asm/ptrace.h>
+
+/*
+ * 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;
+ }
+}
diff --git a/arch/mips/mm/highmem.c b/arch/mips/mm/highmem.c
new file mode 100644
index 0000000..dd5e2e3
--- /dev/null
+++ b/arch/mips/mm/highmem.c
@@ -0,0 +1,103 @@
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/highmem.h>
+#include <asm/tlbflush.h>
+
+void *__kmap(struct page *page)
+{
+ void *addr;
+
+ might_sleep();
+ if (!PageHighMem(page))
+ return page_address(page);
+ addr = kmap_high(page);
+ flush_tlb_one((unsigned long)addr);
+
+ return addr;
+}
+
+void __kunmap(struct page *page)
+{
+ if (in_interrupt())
+ BUG();
+ if (!PageHighMem(page))
+ return;
+ kunmap_high(page);
+}
+
+/*
+ * kmap_atomic/kunmap_atomic is significantly faster than kmap/kunmap because
+ * no global lock is needed and because the kmap code must perform a global TLB
+ * invalidation when the kmap pool wraps.
+ *
+ * However when holding an atomic kmap is is not legal to sleep, so atomic
+ * kmaps are appropriate for short, tight code paths only.
+ */
+
+void *__kmap_atomic(struct page *page, enum km_type type)
+{
+ enum fixed_addresses idx;
+ unsigned long vaddr;
+
+ /* even !CONFIG_PREEMPT needs this, for in_atomic in do_page_fault */
+ inc_preempt_count();
+ if (!PageHighMem(page))
+ return page_address(page);
+
+ idx = type + KM_TYPE_NR*smp_processor_id();
+ vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
+#ifdef CONFIG_DEBUG_HIGHMEM
+ if (!pte_none(*(kmap_pte-idx)))
+ BUG();
+#endif
+ set_pte(kmap_pte-idx, mk_pte(page, kmap_prot));
+ local_flush_tlb_one((unsigned long)vaddr);
+
+ return (void*) vaddr;
+}
+
+void __kunmap_atomic(void *kvaddr, enum km_type type)
+{
+#ifdef CONFIG_DEBUG_HIGHMEM
+ unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK;
+ enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id();
+
+ if (vaddr < FIXADDR_START) { // FIXME
+ dec_preempt_count();
+ preempt_check_resched();
+ return;
+ }
+
+ if (vaddr != __fix_to_virt(FIX_KMAP_BEGIN+idx))
+ BUG();
+
+ /*
+ * force other mappings to Oops if they'll try to access
+ * this pte without first remap it
+ */
+ pte_clear(&init_mm, vaddr, kmap_pte-idx);
+ local_flush_tlb_one(vaddr);
+#endif
+
+ dec_preempt_count();
+ preempt_check_resched();
+}
+
+struct page *__kmap_atomic_to_page(void *ptr)
+{
+ unsigned long idx, vaddr = (unsigned long)ptr;
+ pte_t *pte;
+
+ if (vaddr < FIXADDR_START)
+ return virt_to_page(ptr);
+
+ idx = virt_to_fix(vaddr);
+ pte = kmap_pte - (idx - FIX_KMAP_BEGIN);
+ return pte_page(*pte);
+}
+
+EXPORT_SYMBOL(__kmap);
+EXPORT_SYMBOL(__kunmap);
+EXPORT_SYMBOL(__kmap_atomic);
+EXPORT_SYMBOL(__kunmap_atomic);
+EXPORT_SYMBOL(__kmap_atomic_to_page);
diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c
new file mode 100644
index 0000000..b027ce7
--- /dev/null
+++ b/arch/mips/mm/init.c
@@ -0,0 +1,304 @@
+/*
+ * 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) 1994 - 2000 Ralf Baechle
+ * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
+ * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/pagemap.h>
+#include <linux/ptrace.h>
+#include <linux/mman.h>
+#include <linux/mm.h>
+#include <linux/bootmem.h>
+#include <linux/highmem.h>
+#include <linux/swap.h>
+
+#include <asm/bootinfo.h>
+#include <asm/cachectl.h>
+#include <asm/cpu.h>
+#include <asm/dma.h>
+#include <asm/mmu_context.h>
+#include <asm/sections.h>
+#include <asm/pgtable.h>
+#include <asm/pgalloc.h>
+#include <asm/tlb.h>
+
+DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
+
+unsigned long highstart_pfn, highend_pfn;
+
+/*
+ * We have up to 8 empty zeroed pages so we can map one of the right colour
+ * when needed. This is necessary only on R4000 / R4400 SC and MC versions
+ * where we have to avoid VCED / VECI exceptions for good performance at
+ * any price. Since page is never written to after the initialization we
+ * don't have to care about aliases on other CPUs.
+ */
+unsigned long empty_zero_page, zero_page_mask;
+
+/*
+ * Not static inline because used by IP27 special magic initialization code
+ */
+unsigned long setup_zero_pages(void)
+{
+ unsigned long order, size;
+ struct page *page;
+
+ if (cpu_has_vce)
+ order = 3;
+ else
+ order = 0;
+
+ empty_zero_page = __get_free_pages(GFP_KERNEL | __GFP_ZERO, order);
+ if (!empty_zero_page)
+ panic("Oh boy, that early out of memory?");
+
+ page = virt_to_page(empty_zero_page);
+ while (page < virt_to_page(empty_zero_page + (PAGE_SIZE << order))) {
+ set_bit(PG_reserved, &page->flags);
+ set_page_count(page, 0);
+ page++;
+ }
+
+ size = PAGE_SIZE << order;
+ zero_page_mask = (size - 1) & PAGE_MASK;
+
+ return 1UL << order;
+}
+
+#ifdef CONFIG_HIGHMEM
+pte_t *kmap_pte;
+pgprot_t kmap_prot;
+
+#define kmap_get_fixmap_pte(vaddr) \
+ pte_offset_kernel(pmd_offset(pgd_offset_k(vaddr), (vaddr)), (vaddr))
+
+static void __init kmap_init(void)
+{
+ unsigned long kmap_vstart;
+
+ /* cache the first kmap pte */
+ kmap_vstart = __fix_to_virt(FIX_KMAP_BEGIN);
+ kmap_pte = kmap_get_fixmap_pte(kmap_vstart);
+
+ kmap_prot = PAGE_KERNEL;
+}
+
+#ifdef CONFIG_MIPS64
+static void __init fixrange_init(unsigned long start, unsigned long end,
+ pgd_t *pgd_base)
+{
+ pgd_t *pgd;
+ pmd_t *pmd;
+ pte_t *pte;
+ int i, j;
+ unsigned long vaddr;
+
+ vaddr = start;
+ i = __pgd_offset(vaddr);
+ j = __pmd_offset(vaddr);
+ pgd = pgd_base + i;
+
+ for ( ; (i < PTRS_PER_PGD) && (vaddr != end); pgd++, i++) {
+ pmd = (pmd_t *)pgd;
+ for (; (j < PTRS_PER_PMD) && (vaddr != end); pmd++, j++) {
+ if (pmd_none(*pmd)) {
+ pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
+ set_pmd(pmd, __pmd(pte));
+ if (pte != pte_offset_kernel(pmd, 0))
+ BUG();
+ }
+ vaddr += PMD_SIZE;
+ }
+ j = 0;
+ }
+}
+#endif /* CONFIG_MIPS64 */
+#endif /* CONFIG_HIGHMEM */
+
+#ifndef CONFIG_DISCONTIGMEM
+extern void pagetable_init(void);
+
+void __init paging_init(void)
+{
+ unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0};
+ unsigned long max_dma, high, low;
+
+ pagetable_init();
+
+#ifdef CONFIG_HIGHMEM
+ kmap_init();
+#endif
+
+ max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
+ low = max_low_pfn;
+ high = highend_pfn;
+
+#ifdef CONFIG_ISA
+ if (low < max_dma)
+ zones_size[ZONE_DMA] = low;
+ else {
+ zones_size[ZONE_DMA] = max_dma;
+ zones_size[ZONE_NORMAL] = low - max_dma;
+ }
+#else
+ zones_size[ZONE_DMA] = low;
+#endif
+#ifdef CONFIG_HIGHMEM
+ if (cpu_has_dc_aliases) {
+ printk(KERN_WARNING "This processor doesn't support highmem.");
+ if (high - low)
+ printk(" %ldk highmem ignored", high - low);
+ printk("\n");
+ } else
+ zones_size[ZONE_HIGHMEM] = high - low;
+#endif
+
+ free_area_init(zones_size);
+}
+
+#define PFN_UP(x) (((x) + PAGE_SIZE - 1) >> PAGE_SHIFT)
+#define PFN_DOWN(x) ((x) >> PAGE_SHIFT)
+
+static inline int page_is_ram(unsigned long pagenr)
+{
+ int i;
+
+ for (i = 0; i < boot_mem_map.nr_map; i++) {
+ unsigned long addr, end;
+
+ if (boot_mem_map.map[i].type != BOOT_MEM_RAM)
+ /* not usable memory */
+ continue;
+
+ addr = PFN_UP(boot_mem_map.map[i].addr);
+ end = PFN_DOWN(boot_mem_map.map[i].addr +
+ boot_mem_map.map[i].size);
+
+ if (pagenr >= addr && pagenr < end)
+ return 1;
+ }
+
+ return 0;
+}
+
+void __init mem_init(void)
+{
+ unsigned long codesize, reservedpages, datasize, initsize;
+ unsigned long tmp, ram;
+
+#ifdef CONFIG_HIGHMEM
+#ifdef CONFIG_DISCONTIGMEM
+#error "CONFIG_HIGHMEM and CONFIG_DISCONTIGMEM dont work together yet"
+#endif
+ max_mapnr = num_physpages = highend_pfn;
+#else
+ max_mapnr = num_physpages = max_low_pfn;
+#endif
+ high_memory = (void *) __va(max_low_pfn << PAGE_SHIFT);
+
+ totalram_pages += free_all_bootmem();
+ totalram_pages -= setup_zero_pages(); /* Setup zeroed pages. */
+
+ reservedpages = ram = 0;
+ for (tmp = 0; tmp < max_low_pfn; tmp++)
+ if (page_is_ram(tmp)) {
+ ram++;
+ if (PageReserved(mem_map+tmp))
+ reservedpages++;
+ }
+
+#ifdef CONFIG_HIGHMEM
+ for (tmp = highstart_pfn; tmp < highend_pfn; tmp++) {
+ struct page *page = mem_map + tmp;
+
+ if (!page_is_ram(tmp)) {
+ SetPageReserved(page);
+ continue;
+ }
+ ClearPageReserved(page);
+#ifdef CONFIG_LIMITED_DMA
+ set_page_address(page, lowmem_page_address(page));
+#endif
+ set_bit(PG_highmem, &page->flags);
+ set_page_count(page, 1);
+ __free_page(page);
+ totalhigh_pages++;
+ }
+ totalram_pages += totalhigh_pages;
+#endif
+
+ codesize = (unsigned long) &_etext - (unsigned long) &_text;
+ datasize = (unsigned long) &_edata - (unsigned long) &_etext;
+ initsize = (unsigned long) &__init_end - (unsigned long) &__init_begin;
+
+ printk(KERN_INFO "Memory: %luk/%luk available (%ldk kernel code, "
+ "%ldk reserved, %ldk data, %ldk init, %ldk highmem)\n",
+ (unsigned long) nr_free_pages() << (PAGE_SHIFT-10),
+ ram << (PAGE_SHIFT-10),
+ codesize >> 10,
+ reservedpages << (PAGE_SHIFT-10),
+ datasize >> 10,
+ initsize >> 10,
+ (unsigned long) (totalhigh_pages << (PAGE_SHIFT-10)));
+}
+#endif /* !CONFIG_DISCONTIGMEM */
+
+#ifdef CONFIG_BLK_DEV_INITRD
+void free_initrd_mem(unsigned long start, unsigned long end)
+{
+#ifdef CONFIG_MIPS64
+ /* Switch from KSEG0 to XKPHYS addresses */
+ start = (unsigned long)phys_to_virt(CPHYSADDR(start));
+ end = (unsigned long)phys_to_virt(CPHYSADDR(end));
+#endif
+ if (start < end)
+ printk(KERN_INFO "Freeing initrd memory: %ldk freed\n",
+ (end - start) >> 10);
+
+ for (; start < end; start += PAGE_SIZE) {
+ ClearPageReserved(virt_to_page(start));
+ set_page_count(virt_to_page(start), 1);
+ free_page(start);
+ totalram_pages++;
+ }
+}
+#endif
+
+extern unsigned long prom_free_prom_memory(void);
+
+void free_initmem(void)
+{
+ unsigned long addr, page, freed;
+
+ freed = prom_free_prom_memory();
+
+ addr = (unsigned long) &__init_begin;
+ while (addr < (unsigned long) &__init_end) {
+#ifdef CONFIG_MIPS64
+ page = PAGE_OFFSET | CPHYSADDR(addr);
+#else
+ page = addr;
+#endif
+ ClearPageReserved(virt_to_page(page));
+ set_page_count(virt_to_page(page), 1);
+ free_page(page);
+ totalram_pages++;
+ freed += PAGE_SIZE;
+ addr += PAGE_SIZE;
+ }
+ printk(KERN_INFO "Freeing unused kernel memory: %ldk freed\n",
+ freed >> 10);
+}
diff --git a/arch/mips/mm/ioremap.c b/arch/mips/mm/ioremap.c
new file mode 100644
index 0000000..adf3522
--- /dev/null
+++ b/arch/mips/mm/ioremap.c
@@ -0,0 +1,202 @@
+/*
+ * 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.
+ *
+ * (C) Copyright 1995 1996 Linus Torvalds
+ * (C) Copyright 2001, 2002 Ralf Baechle
+ */
+#include <linux/module.h>
+#include <asm/addrspace.h>
+#include <asm/byteorder.h>
+
+#include <linux/vmalloc.h>
+#include <asm/cacheflush.h>
+#include <asm/io.h>
+#include <asm/tlbflush.h>
+
+static inline void remap_area_pte(pte_t * pte, unsigned long address,
+ phys_t size, phys_t phys_addr, unsigned long flags)
+{
+ phys_t end;
+ unsigned long pfn;
+ pgprot_t pgprot = __pgprot(_PAGE_GLOBAL | _PAGE_PRESENT | __READABLE
+ | __WRITEABLE | flags);
+
+ address &= ~PMD_MASK;
+ end = address + size;
+ if (end > PMD_SIZE)
+ end = PMD_SIZE;
+ if (address >= end)
+ BUG();
+ pfn = phys_addr >> PAGE_SHIFT;
+ do {
+ if (!pte_none(*pte)) {
+ printk("remap_area_pte: page already exists\n");
+ BUG();
+ }
+ set_pte(pte, pfn_pte(pfn, pgprot));
+ address += PAGE_SIZE;
+ pfn++;
+ pte++;
+ } while (address && (address < end));
+}
+
+static inline int remap_area_pmd(pmd_t * pmd, unsigned long address,
+ phys_t size, phys_t phys_addr, unsigned long flags)
+{
+ phys_t end;
+
+ address &= ~PGDIR_MASK;
+ end = address + size;
+ if (end > PGDIR_SIZE)
+ end = PGDIR_SIZE;
+ phys_addr -= address;
+ if (address >= end)
+ BUG();
+ do {
+ pte_t * pte = pte_alloc_kernel(&init_mm, pmd, address);
+ if (!pte)
+ return -ENOMEM;
+ remap_area_pte(pte, address, end - address, address + phys_addr, flags);
+ address = (address + PMD_SIZE) & PMD_MASK;
+ pmd++;
+ } while (address && (address < end));
+ return 0;
+}
+
+static int remap_area_pages(unsigned long address, phys_t phys_addr,
+ phys_t size, unsigned long flags)
+{
+ int error;
+ pgd_t * dir;
+ unsigned long end = address + size;
+
+ phys_addr -= address;
+ dir = pgd_offset(&init_mm, address);
+ flush_cache_all();
+ if (address >= end)
+ BUG();
+ spin_lock(&init_mm.page_table_lock);
+ do {
+ pmd_t *pmd;
+ pmd = pmd_alloc(&init_mm, dir, address);
+ error = -ENOMEM;
+ if (!pmd)
+ break;
+ if (remap_area_pmd(pmd, address, end - address,
+ phys_addr + address, flags))
+ break;
+ error = 0;
+ address = (address + PGDIR_SIZE) & PGDIR_MASK;
+ dir++;
+ } while (address && (address < end));
+ spin_unlock(&init_mm.page_table_lock);
+ flush_tlb_all();
+ return error;
+}
+
+/*
+ * Allow physical addresses to be fixed up to help 36 bit peripherals.
+ */
+phys_t __attribute__ ((weak))
+fixup_bigphys_addr(phys_t phys_addr, phys_t size)
+{
+ return phys_addr;
+}
+
+/*
+ * Generic mapping function (not visible outside):
+ */
+
+/*
+ * Remap an arbitrary physical address space into the kernel virtual
+ * address space. Needed when the kernel wants to access high addresses
+ * directly.
+ *
+ * NOTE! We need to allow non-page-aligned mappings too: we will obviously
+ * have to convert them into an offset in a page-aligned mapping, but the
+ * caller shouldn't need to know that small detail.
+ */
+
+#define IS_LOW512(addr) (!((phys_t)(addr) & (phys_t) ~0x1fffffffULL))
+
+void * __ioremap(phys_t phys_addr, phys_t size, unsigned long flags)
+{
+ struct vm_struct * area;
+ unsigned long offset;
+ phys_t last_addr;
+ void * addr;
+
+ phys_addr = fixup_bigphys_addr(phys_addr, size);
+
+ /* Don't allow wraparound or zero size */
+ last_addr = phys_addr + size - 1;
+ if (!size || last_addr < phys_addr)
+ return NULL;
+
+ /*
+ * Map uncached objects in the low 512mb of address space using KSEG1,
+ * otherwise map using page tables.
+ */
+ if (IS_LOW512(phys_addr) && IS_LOW512(last_addr) &&
+ flags == _CACHE_UNCACHED)
+ return (void *) KSEG1ADDR(phys_addr);
+
+ /*
+ * Don't allow anybody to remap normal RAM that we're using..
+ */
+ if (phys_addr < virt_to_phys(high_memory)) {
+ char *t_addr, *t_end;
+ struct page *page;
+
+ t_addr = __va(phys_addr);
+ t_end = t_addr + (size - 1);
+
+ for(page = virt_to_page(t_addr); page <= virt_to_page(t_end); page++)
+ if(!PageReserved(page))
+ return NULL;
+ }
+
+ /*
+ * Mappings have to be page-aligned
+ */
+ offset = phys_addr & ~PAGE_MASK;
+ phys_addr &= PAGE_MASK;
+ size = PAGE_ALIGN(last_addr + 1) - phys_addr;
+
+ /*
+ * Ok, go for it..
+ */
+ area = get_vm_area(size, VM_IOREMAP);
+ if (!area)
+ return NULL;
+ addr = area->addr;
+ if (remap_area_pages((unsigned long) addr, phys_addr, size, flags)) {
+ vunmap(addr);
+ return NULL;
+ }
+
+ return (void *) (offset + (char *)addr);
+}
+
+#define IS_KSEG1(addr) (((unsigned long)(addr) & ~0x1fffffffUL) == KSEG1)
+
+void __iounmap(volatile void __iomem *addr)
+{
+ struct vm_struct *p;
+
+ if (IS_KSEG1(addr))
+ return;
+
+ p = remove_vm_area((void *) (PAGE_MASK & (unsigned long __force) addr));
+ if (!p) {
+ printk(KERN_ERR "iounmap: bad address %p\n", addr);
+ return;
+ }
+
+ kfree(p);
+}
+
+EXPORT_SYMBOL(__ioremap);
+EXPORT_SYMBOL(__iounmap);
diff --git a/arch/mips/mm/pg-r4k.c b/arch/mips/mm/pg-r4k.c
new file mode 100644
index 0000000..9f8b165
--- /dev/null
+++ b/arch/mips/mm/pg-r4k.c
@@ -0,0 +1,489 @@
+/*
+ * 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) 2003, 04, 05 Ralf Baechle (ralf@linux-mips.org)
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/proc_fs.h>
+
+#include <asm/cacheops.h>
+#include <asm/inst.h>
+#include <asm/io.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/prefetch.h>
+#include <asm/system.h>
+#include <asm/bootinfo.h>
+#include <asm/mipsregs.h>
+#include <asm/mmu_context.h>
+#include <asm/cpu.h>
+#include <asm/war.h>
+
+#define half_scache_line_size() (cpu_scache_line_size() >> 1)
+
+/*
+ * Maximum sizes:
+ *
+ * R4000 128 bytes S-cache: 0x58 bytes
+ * R4600 v1.7: 0x5c bytes
+ * R4600 v2.0: 0x60 bytes
+ * With prefetching, 16 byte strides 0xa0 bytes
+ */
+
+static unsigned int clear_page_array[0x130 / 4];
+
+void clear_page(void * page) __attribute__((alias("clear_page_array")));
+
+EXPORT_SYMBOL(clear_page);
+
+/*
+ * Maximum sizes:
+ *
+ * R4000 128 bytes S-cache: 0x11c bytes
+ * R4600 v1.7: 0x080 bytes
+ * R4600 v2.0: 0x07c bytes
+ * With prefetching, 16 byte strides 0x0b8 bytes
+ */
+static unsigned int copy_page_array[0x148 / 4];
+
+void copy_page(void *to, void *from) __attribute__((alias("copy_page_array")));
+
+EXPORT_SYMBOL(copy_page);
+
+/*
+ * This is suboptimal for 32-bit kernels; we assume that R10000 is only used
+ * with 64-bit kernels. The prefetch offsets have been experimentally tuned
+ * an Origin 200.
+ */
+static int pref_offset_clear __initdata = 512;
+static int pref_offset_copy __initdata = 256;
+
+static unsigned int pref_src_mode __initdata;
+static unsigned int pref_dst_mode __initdata;
+
+static int load_offset __initdata;
+static int store_offset __initdata;
+
+static unsigned int __initdata *dest, *epc;
+
+static unsigned int instruction_pending;
+static union mips_instruction delayed_mi;
+
+static void __init emit_instruction(union mips_instruction mi)
+{
+ if (instruction_pending)
+ *epc++ = delayed_mi.word;
+
+ instruction_pending = 1;
+ delayed_mi = mi;
+}
+
+static inline void flush_delay_slot_or_nop(void)
+{
+ if (instruction_pending) {
+ *epc++ = delayed_mi.word;
+ instruction_pending = 0;
+ return;
+ }
+
+ *epc++ = 0;
+}
+
+static inline unsigned int *label(void)
+{
+ if (instruction_pending) {
+ *epc++ = delayed_mi.word;
+ instruction_pending = 0;
+ }
+
+ return epc;
+}
+
+static inline void build_insn_word(unsigned int word)
+{
+ union mips_instruction mi;
+
+ mi.word = word;
+
+ emit_instruction(mi);
+}
+
+static inline void build_nop(void)
+{
+ build_insn_word(0); /* nop */
+}
+
+static inline void build_src_pref(int advance)
+{
+ if (!(load_offset & (cpu_dcache_line_size() - 1))) {
+ union mips_instruction mi;
+
+ mi.i_format.opcode = pref_op;
+ mi.i_format.rs = 5; /* $a1 */
+ mi.i_format.rt = pref_src_mode;
+ mi.i_format.simmediate = load_offset + advance;
+
+ emit_instruction(mi);
+ }
+}
+
+static inline void __build_load_reg(int reg)
+{
+ union mips_instruction mi;
+ unsigned int width;
+
+ if (cpu_has_64bit_gp_regs) {
+ mi.i_format.opcode = ld_op;
+ width = 8;
+ } else {
+ mi.i_format.opcode = lw_op;
+ width = 4;
+ }
+ mi.i_format.rs = 5; /* $a1 */
+ mi.i_format.rt = reg; /* $reg */
+ mi.i_format.simmediate = load_offset;
+
+ load_offset += width;
+ emit_instruction(mi);
+}
+
+static inline void build_load_reg(int reg)
+{
+ if (cpu_has_prefetch)
+ build_src_pref(pref_offset_copy);
+
+ __build_load_reg(reg);
+}
+
+static inline void build_dst_pref(int advance)
+{
+ if (!(store_offset & (cpu_dcache_line_size() - 1))) {
+ union mips_instruction mi;
+
+ mi.i_format.opcode = pref_op;
+ mi.i_format.rs = 4; /* $a0 */
+ mi.i_format.rt = pref_dst_mode;
+ mi.i_format.simmediate = store_offset + advance;
+
+ emit_instruction(mi);
+ }
+}
+
+static inline void build_cdex_s(void)
+{
+ union mips_instruction mi;
+
+ if ((store_offset & (cpu_scache_line_size() - 1)))
+ return;
+
+ mi.c_format.opcode = cache_op;
+ mi.c_format.rs = 4; /* $a0 */
+ mi.c_format.c_op = 3; /* Create Dirty Exclusive */
+ mi.c_format.cache = 3; /* Secondary Data Cache */
+ mi.c_format.simmediate = store_offset;
+
+ emit_instruction(mi);
+}
+
+static inline void build_cdex_p(void)
+{
+ union mips_instruction mi;
+
+ if (store_offset & (cpu_dcache_line_size() - 1))
+ return;
+
+ if (R4600_V1_HIT_CACHEOP_WAR && ((read_c0_prid() & 0xfff0) == 0x2010)) {
+ build_nop();
+ build_nop();
+ build_nop();
+ build_nop();
+ }
+
+ if (R4600_V2_HIT_CACHEOP_WAR && ((read_c0_prid() & 0xfff0) == 0x2020))
+ build_insn_word(0x8c200000); /* lw $zero, ($at) */
+
+ mi.c_format.opcode = cache_op;
+ mi.c_format.rs = 4; /* $a0 */
+ mi.c_format.c_op = 3; /* Create Dirty Exclusive */
+ mi.c_format.cache = 1; /* Data Cache */
+ mi.c_format.simmediate = store_offset;
+
+ emit_instruction(mi);
+}
+
+static void __init __build_store_reg(int reg)
+{
+ union mips_instruction mi;
+ unsigned int width;
+
+ if (cpu_has_64bit_gp_regs ||
+ (cpu_has_64bit_zero_reg && reg == 0)) {
+ mi.i_format.opcode = sd_op;
+ width = 8;
+ } else {
+ mi.i_format.opcode = sw_op;
+ width = 4;
+ }
+ mi.i_format.rs = 4; /* $a0 */
+ mi.i_format.rt = reg; /* $reg */
+ mi.i_format.simmediate = store_offset;
+
+ store_offset += width;
+ emit_instruction(mi);
+}
+
+static inline void build_store_reg(int reg)
+{
+ if (cpu_has_prefetch)
+ if (reg)
+ build_dst_pref(pref_offset_copy);
+ else
+ build_dst_pref(pref_offset_clear);
+ else if (cpu_has_cache_cdex_s)
+ build_cdex_s();
+ else if (cpu_has_cache_cdex_p)
+ build_cdex_p();
+
+ __build_store_reg(reg);
+}
+
+static inline void build_addiu_a2_a0(unsigned long offset)
+{
+ union mips_instruction mi;
+
+ BUG_ON(offset > 0x7fff);
+
+ mi.i_format.opcode = cpu_has_64bit_gp_regs ? daddiu_op : addiu_op;
+ mi.i_format.rs = 4; /* $a0 */
+ mi.i_format.rt = 6; /* $a2 */
+ mi.i_format.simmediate = offset;
+
+ emit_instruction(mi);
+}
+
+static inline void build_addiu_a1(unsigned long offset)
+{
+ union mips_instruction mi;
+
+ BUG_ON(offset > 0x7fff);
+
+ mi.i_format.opcode = cpu_has_64bit_gp_regs ? daddiu_op : addiu_op;
+ mi.i_format.rs = 5; /* $a1 */
+ mi.i_format.rt = 5; /* $a1 */
+ mi.i_format.simmediate = offset;
+
+ load_offset -= offset;
+
+ emit_instruction(mi);
+}
+
+static inline void build_addiu_a0(unsigned long offset)
+{
+ union mips_instruction mi;
+
+ BUG_ON(offset > 0x7fff);
+
+ mi.i_format.opcode = cpu_has_64bit_gp_regs ? daddiu_op : addiu_op;
+ mi.i_format.rs = 4; /* $a0 */
+ mi.i_format.rt = 4; /* $a0 */
+ mi.i_format.simmediate = offset;
+
+ store_offset -= offset;
+
+ emit_instruction(mi);
+}
+
+static inline void build_bne(unsigned int *dest)
+{
+ union mips_instruction mi;
+
+ mi.i_format.opcode = bne_op;
+ mi.i_format.rs = 6; /* $a2 */
+ mi.i_format.rt = 4; /* $a0 */
+ mi.i_format.simmediate = dest - epc - 1;
+
+ *epc++ = mi.word;
+ flush_delay_slot_or_nop();
+}
+
+static inline void build_jr_ra(void)
+{
+ union mips_instruction mi;
+
+ mi.r_format.opcode = spec_op;
+ mi.r_format.rs = 31;
+ mi.r_format.rt = 0;
+ mi.r_format.rd = 0;
+ mi.r_format.re = 0;
+ mi.r_format.func = jr_op;
+
+ *epc++ = mi.word;
+ flush_delay_slot_or_nop();
+}
+
+void __init build_clear_page(void)
+{
+ unsigned int loop_start;
+
+ epc = (unsigned int *) &clear_page_array;
+ instruction_pending = 0;
+ store_offset = 0;
+
+ if (cpu_has_prefetch) {
+ switch (current_cpu_data.cputype) {
+ case CPU_RM9000:
+ /*
+ * As a workaround for erratum G105 which make the
+ * PrepareForStore hint unusable we fall back to
+ * StoreRetained on the RM9000. Once it is known which
+ * versions of the RM9000 we'll be able to condition-
+ * alize this.
+ */
+
+ case CPU_R10000:
+ case CPU_R12000:
+ pref_src_mode = Pref_LoadStreamed;
+ pref_dst_mode = Pref_StoreStreamed;
+ break;
+
+ default:
+ pref_src_mode = Pref_LoadStreamed;
+ pref_dst_mode = Pref_PrepareForStore;
+ break;
+ }
+ }
+
+ build_addiu_a2_a0(PAGE_SIZE - (cpu_has_prefetch ? pref_offset_clear : 0));
+
+ if (R4600_V2_HIT_CACHEOP_WAR && ((read_c0_prid() & 0xfff0) == 0x2020))
+ build_insn_word(0x3c01a000); /* lui $at, 0xa000 */
+
+dest = label();
+ do {
+ build_store_reg(0);
+ build_store_reg(0);
+ build_store_reg(0);
+ build_store_reg(0);
+ } while (store_offset < half_scache_line_size());
+ build_addiu_a0(2 * store_offset);
+ loop_start = store_offset;
+ do {
+ build_store_reg(0);
+ build_store_reg(0);
+ build_store_reg(0);
+ build_store_reg(0);
+ } while ((store_offset - loop_start) < half_scache_line_size());
+ build_bne(dest);
+
+ if (cpu_has_prefetch && pref_offset_clear) {
+ build_addiu_a2_a0(pref_offset_clear);
+ dest = label();
+ loop_start = store_offset;
+ do {
+ __build_store_reg(0);
+ __build_store_reg(0);
+ __build_store_reg(0);
+ __build_store_reg(0);
+ } while ((store_offset - loop_start) < half_scache_line_size());
+ build_addiu_a0(2 * store_offset);
+ loop_start = store_offset;
+ do {
+ __build_store_reg(0);
+ __build_store_reg(0);
+ __build_store_reg(0);
+ __build_store_reg(0);
+ } while ((store_offset - loop_start) < half_scache_line_size());
+ build_bne(dest);
+ }
+
+ build_jr_ra();
+
+ flush_icache_range((unsigned long)&clear_page_array,
+ (unsigned long) epc);
+
+ BUG_ON(epc > clear_page_array + ARRAY_SIZE(clear_page_array));
+}
+
+void __init build_copy_page(void)
+{
+ unsigned int loop_start;
+
+ epc = (unsigned int *) ©_page_array;
+ store_offset = load_offset = 0;
+ instruction_pending = 0;
+
+ build_addiu_a2_a0(PAGE_SIZE - (cpu_has_prefetch ? pref_offset_copy : 0));
+
+ if (R4600_V2_HIT_CACHEOP_WAR && ((read_c0_prid() & 0xfff0) == 0x2020))
+ build_insn_word(0x3c01a000); /* lui $at, 0xa000 */
+
+dest = label();
+ loop_start = store_offset;
+ do {
+ build_load_reg( 8);
+ build_load_reg( 9);
+ build_load_reg(10);
+ build_load_reg(11);
+ build_store_reg( 8);
+ build_store_reg( 9);
+ build_store_reg(10);
+ build_store_reg(11);
+ } while ((store_offset - loop_start) < half_scache_line_size());
+ build_addiu_a0(2 * store_offset);
+ build_addiu_a1(2 * load_offset);
+ loop_start = store_offset;
+ do {
+ build_load_reg( 8);
+ build_load_reg( 9);
+ build_load_reg(10);
+ build_load_reg(11);
+ build_store_reg( 8);
+ build_store_reg( 9);
+ build_store_reg(10);
+ build_store_reg(11);
+ } while ((store_offset - loop_start) < half_scache_line_size());
+ build_bne(dest);
+
+ if (cpu_has_prefetch && pref_offset_copy) {
+ build_addiu_a2_a0(pref_offset_copy);
+ dest = label();
+ loop_start = store_offset;
+ do {
+ __build_load_reg( 8);
+ __build_load_reg( 9);
+ __build_load_reg(10);
+ __build_load_reg(11);
+ __build_store_reg( 8);
+ __build_store_reg( 9);
+ __build_store_reg(10);
+ __build_store_reg(11);
+ } while ((store_offset - loop_start) < half_scache_line_size());
+ build_addiu_a0(2 * store_offset);
+ build_addiu_a1(2 * load_offset);
+ loop_start = store_offset;
+ do {
+ __build_load_reg( 8);
+ __build_load_reg( 9);
+ __build_load_reg(10);
+ __build_load_reg(11);
+ __build_store_reg( 8);
+ __build_store_reg( 9);
+ __build_store_reg(10);
+ __build_store_reg(11);
+ } while ((store_offset - loop_start) < half_scache_line_size());
+ build_bne(dest);
+ }
+
+ build_jr_ra();
+
+ flush_icache_range((unsigned long)©_page_array,
+ (unsigned long) epc);
+
+ BUG_ON(epc > copy_page_array + ARRAY_SIZE(copy_page_array));
+}
diff --git a/arch/mips/mm/pg-sb1.c b/arch/mips/mm/pg-sb1.c
new file mode 100644
index 0000000..59d131b
--- /dev/null
+++ b/arch/mips/mm/pg-sb1.c
@@ -0,0 +1,287 @@
+/*
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ * Copyright (C) 1997, 2001 Ralf Baechle (ralf@gnu.org)
+ * Copyright (C) 2000 SiByte, Inc.
+ * Copyright (C) 2005 Thiemo Seufer
+ *
+ * Written by Justin Carlson of SiByte, Inc.
+ * and Kip Walker of Broadcom Corp.
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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 <linux/config.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/smp.h>
+
+#include <asm/io.h>
+#include <asm/sibyte/sb1250.h>
+#include <asm/sibyte/sb1250_regs.h>
+#include <asm/sibyte/sb1250_dma.h>
+
+#ifdef CONFIG_SB1_PASS_1_WORKAROUNDS
+#define SB1_PREF_LOAD_STREAMED_HINT "0"
+#define SB1_PREF_STORE_STREAMED_HINT "1"
+#else
+#define SB1_PREF_LOAD_STREAMED_HINT "4"
+#define SB1_PREF_STORE_STREAMED_HINT "5"
+#endif
+
+static inline void clear_page_cpu(void *page)
+{
+ unsigned char *addr = (unsigned char *) page;
+ unsigned char *end = addr + PAGE_SIZE;
+
+ /*
+ * JDCXXX - This should be bottlenecked by the write buffer, but these
+ * things tend to be mildly unpredictable...should check this on the
+ * performance model
+ *
+ * We prefetch 4 lines ahead. We're also "cheating" slightly here...
+ * since we know we're on an SB1, we force the assembler to take
+ * 64-bit operands to speed things up
+ */
+ __asm__ __volatile__(
+ " .set push \n"
+ " .set mips4 \n"
+ " .set noreorder \n"
+#ifdef CONFIG_CPU_HAS_PREFETCH
+ " daddiu %0, %0, 128 \n"
+ " pref " SB1_PREF_STORE_STREAMED_HINT ", -128(%0) \n" /* Prefetch the first 4 lines */
+ " pref " SB1_PREF_STORE_STREAMED_HINT ", -96(%0) \n"
+ " pref " SB1_PREF_STORE_STREAMED_HINT ", -64(%0) \n"
+ " pref " SB1_PREF_STORE_STREAMED_HINT ", -32(%0) \n"
+ "1: sd $0, -128(%0) \n" /* Throw out a cacheline of 0's */
+ " sd $0, -120(%0) \n"
+ " sd $0, -112(%0) \n"
+ " sd $0, -104(%0) \n"
+ " daddiu %0, %0, 32 \n"
+ " bnel %0, %1, 1b \n"
+ " pref " SB1_PREF_STORE_STREAMED_HINT ", -32(%0) \n"
+ " daddiu %0, %0, -128 \n"
+#endif
+ " sd $0, 0(%0) \n" /* Throw out a cacheline of 0's */
+ "1: sd $0, 8(%0) \n"
+ " sd $0, 16(%0) \n"
+ " sd $0, 24(%0) \n"
+ " daddiu %0, %0, 32 \n"
+ " bnel %0, %1, 1b \n"
+ " sd $0, 0(%0) \n"
+ " .set pop \n"
+ : "+r" (addr)
+ : "r" (end)
+ : "memory");
+}
+
+static inline void copy_page_cpu(void *to, void *from)
+{
+ unsigned char *src = (unsigned char *)from;
+ unsigned char *dst = (unsigned char *)to;
+ unsigned char *end = src + PAGE_SIZE;
+
+ /*
+ * The pref's used here are using "streaming" hints, which cause the
+ * copied data to be kicked out of the cache sooner. A page copy often
+ * ends up copying a lot more data than is commonly used, so this seems
+ * to make sense in terms of reducing cache pollution, but I've no real
+ * performance data to back this up
+ */
+ __asm__ __volatile__(
+ " .set push \n"
+ " .set mips4 \n"
+ " .set noreorder \n"
+#ifdef CONFIG_CPU_HAS_PREFETCH
+ " daddiu %0, %0, 128 \n"
+ " daddiu %1, %1, 128 \n"
+ " pref " SB1_PREF_LOAD_STREAMED_HINT ", -128(%0)\n" /* Prefetch the first 4 lines */
+ " pref " SB1_PREF_STORE_STREAMED_HINT ", -128(%1)\n"
+ " pref " SB1_PREF_LOAD_STREAMED_HINT ", -96(%0)\n"
+ " pref " SB1_PREF_STORE_STREAMED_HINT ", -96(%1)\n"
+ " pref " SB1_PREF_LOAD_STREAMED_HINT ", -64(%0)\n"
+ " pref " SB1_PREF_STORE_STREAMED_HINT ", -64(%1)\n"
+ " pref " SB1_PREF_LOAD_STREAMED_HINT ", -32(%0)\n"
+ "1: pref " SB1_PREF_STORE_STREAMED_HINT ", -32(%1)\n"
+# ifdef CONFIG_MIPS64
+ " ld $8, -128(%0) \n" /* Block copy a cacheline */
+ " ld $9, -120(%0) \n"
+ " ld $10, -112(%0) \n"
+ " ld $11, -104(%0) \n"
+ " sd $8, -128(%1) \n"
+ " sd $9, -120(%1) \n"
+ " sd $10, -112(%1) \n"
+ " sd $11, -104(%1) \n"
+# else
+ " lw $2, -128(%0) \n" /* Block copy a cacheline */
+ " lw $3, -124(%0) \n"
+ " lw $6, -120(%0) \n"
+ " lw $7, -116(%0) \n"
+ " lw $8, -112(%0) \n"
+ " lw $9, -108(%0) \n"
+ " lw $10, -104(%0) \n"
+ " lw $11, -100(%0) \n"
+ " sw $2, -128(%1) \n"
+ " sw $3, -124(%1) \n"
+ " sw $6, -120(%1) \n"
+ " sw $7, -116(%1) \n"
+ " sw $8, -112(%1) \n"
+ " sw $9, -108(%1) \n"
+ " sw $10, -104(%1) \n"
+ " sw $11, -100(%1) \n"
+# endif
+ " daddiu %0, %0, 32 \n"
+ " daddiu %1, %1, 32 \n"
+ " bnel %0, %2, 1b \n"
+ " pref " SB1_PREF_LOAD_STREAMED_HINT ", -32(%0)\n"
+ " daddiu %0, %0, -128 \n"
+ " daddiu %1, %1, -128 \n"
+#endif
+#ifdef CONFIG_MIPS64
+ " ld $8, 0(%0) \n" /* Block copy a cacheline */
+ "1: ld $9, 8(%0) \n"
+ " ld $10, 16(%0) \n"
+ " ld $11, 24(%0) \n"
+ " sd $8, 0(%1) \n"
+ " sd $9, 8(%1) \n"
+ " sd $10, 16(%1) \n"
+ " sd $11, 24(%1) \n"
+#else
+ " lw $2, 0(%0) \n" /* Block copy a cacheline */
+ "1: lw $3, 4(%0) \n"
+ " lw $6, 8(%0) \n"
+ " lw $7, 12(%0) \n"
+ " lw $8, 16(%0) \n"
+ " lw $9, 20(%0) \n"
+ " lw $10, 24(%0) \n"
+ " lw $11, 28(%0) \n"
+ " sw $2, 0(%1) \n"
+ " sw $3, 4(%1) \n"
+ " sw $6, 8(%1) \n"
+ " sw $7, 12(%1) \n"
+ " sw $8, 16(%1) \n"
+ " sw $9, 20(%1) \n"
+ " sw $10, 24(%1) \n"
+ " sw $11, 28(%1) \n"
+#endif
+ " daddiu %0, %0, 32 \n"
+ " daddiu %1, %1, 32 \n"
+ " bnel %0, %2, 1b \n"
+#ifdef CONFIG_MIPS64
+ " ld $8, 0(%0) \n"
+#else
+ " lw $2, 0(%0) \n"
+#endif
+ " .set pop \n"
+ : "+r" (src), "+r" (dst)
+ : "r" (end)
+#ifdef CONFIG_MIPS64
+ : "$8","$9","$10","$11","memory");
+#else
+ : "$2","$3","$6","$7","$8","$9","$10","$11","memory");
+#endif
+}
+
+
+#ifdef CONFIG_SIBYTE_DMA_PAGEOPS
+
+/*
+ * Pad descriptors to cacheline, since each is exclusively owned by a
+ * particular CPU.
+ */
+typedef struct dmadscr_s {
+ u64 dscr_a;
+ u64 dscr_b;
+ u64 pad_a;
+ u64 pad_b;
+} dmadscr_t;
+
+static dmadscr_t page_descr[NR_CPUS] __attribute__((aligned(SMP_CACHE_BYTES)));
+
+void sb1_dma_init(void)
+{
+ int cpu = smp_processor_id();
+ u64 base_val = CPHYSADDR(&page_descr[cpu]) | V_DM_DSCR_BASE_RINGSZ(1);
+
+ bus_writeq(base_val,
+ (void *)IOADDR(A_DM_REGISTER(cpu, R_DM_DSCR_BASE)));
+ bus_writeq(base_val | M_DM_DSCR_BASE_RESET,
+ (void *)IOADDR(A_DM_REGISTER(cpu, R_DM_DSCR_BASE)));
+ bus_writeq(base_val | M_DM_DSCR_BASE_ENABL,
+ (void *)IOADDR(A_DM_REGISTER(cpu, R_DM_DSCR_BASE)));
+}
+
+void clear_page(void *page)
+{
+ int cpu = smp_processor_id();
+
+ /* if the page is above Kseg0, use old way */
+ if ((long)KSEGX(page) != (long)CKSEG0)
+ return clear_page_cpu(page);
+
+ page_descr[cpu].dscr_a = CPHYSADDR(page) | M_DM_DSCRA_ZERO_MEM | M_DM_DSCRA_L2C_DEST | M_DM_DSCRA_INTERRUPT;
+ page_descr[cpu].dscr_b = V_DM_DSCRB_SRC_LENGTH(PAGE_SIZE);
+ bus_writeq(1, (void *)IOADDR(A_DM_REGISTER(cpu, R_DM_DSCR_COUNT)));
+
+ /*
+ * Don't really want to do it this way, but there's no
+ * reliable way to delay completion detection.
+ */
+ while (!(bus_readq((void *)(IOADDR(A_DM_REGISTER(cpu, R_DM_DSCR_BASE_DEBUG)) &
+ M_DM_DSCR_BASE_INTERRUPT))))
+ ;
+ bus_readq((void *)IOADDR(A_DM_REGISTER(cpu, R_DM_DSCR_BASE)));
+}
+
+void copy_page(void *to, void *from)
+{
+ unsigned long from_phys = CPHYSADDR(from);
+ unsigned long to_phys = CPHYSADDR(to);
+ int cpu = smp_processor_id();
+
+ /* if either page is above Kseg0, use old way */
+ if ((long)KSEGX(to) != (long)CKSEG0
+ || (long)KSEGX(from) != (long)CKSEG0)
+ return copy_page_cpu(to, from);
+
+ page_descr[cpu].dscr_a = CPHYSADDR(to_phys) | M_DM_DSCRA_L2C_DEST | M_DM_DSCRA_INTERRUPT;
+ page_descr[cpu].dscr_b = CPHYSADDR(from_phys) | V_DM_DSCRB_SRC_LENGTH(PAGE_SIZE);
+ bus_writeq(1, (void *)IOADDR(A_DM_REGISTER(cpu, R_DM_DSCR_COUNT)));
+
+ /*
+ * Don't really want to do it this way, but there's no
+ * reliable way to delay completion detection.
+ */
+ while (!(bus_readq((void *)(IOADDR(A_DM_REGISTER(cpu, R_DM_DSCR_BASE_DEBUG)) &
+ M_DM_DSCR_BASE_INTERRUPT))))
+ ;
+ bus_readq((void *)IOADDR(A_DM_REGISTER(cpu, R_DM_DSCR_BASE)));
+}
+
+#else /* !CONFIG_SIBYTE_DMA_PAGEOPS */
+
+void clear_page(void *page)
+{
+ return clear_page_cpu(page);
+}
+
+void copy_page(void *to, void *from)
+{
+ return copy_page_cpu(to, from);
+}
+
+#endif /* !CONFIG_SIBYTE_DMA_PAGEOPS */
+
+EXPORT_SYMBOL(clear_page);
+EXPORT_SYMBOL(copy_page);
diff --git a/arch/mips/mm/pgtable-32.c b/arch/mips/mm/pgtable-32.c
new file mode 100644
index 0000000..4f07f81
--- /dev/null
+++ b/arch/mips/mm/pgtable-32.c
@@ -0,0 +1,97 @@
+/*
+ * 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) 2003 by Ralf Baechle
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/bootmem.h>
+#include <linux/highmem.h>
+#include <asm/pgtable.h>
+
+void pgd_init(unsigned long page)
+{
+ unsigned long *p = (unsigned long *) page;
+ int i;
+
+ for (i = 0; i < USER_PTRS_PER_PGD; i+=8) {
+ p[i + 0] = (unsigned long) invalid_pte_table;
+ p[i + 1] = (unsigned long) invalid_pte_table;
+ p[i + 2] = (unsigned long) invalid_pte_table;
+ p[i + 3] = (unsigned long) invalid_pte_table;
+ p[i + 4] = (unsigned long) invalid_pte_table;
+ p[i + 5] = (unsigned long) invalid_pte_table;
+ p[i + 6] = (unsigned long) invalid_pte_table;
+ p[i + 7] = (unsigned long) invalid_pte_table;
+ }
+}
+
+#ifdef CONFIG_HIGHMEM
+static void __init fixrange_init (unsigned long start, unsigned long end,
+ pgd_t *pgd_base)
+{
+ pgd_t *pgd;
+ pmd_t *pmd;
+ pte_t *pte;
+ int i, j;
+ unsigned long vaddr;
+
+ vaddr = start;
+ i = __pgd_offset(vaddr);
+ j = __pmd_offset(vaddr);
+ pgd = pgd_base + i;
+
+ for ( ; (i < PTRS_PER_PGD) && (vaddr != end); pgd++, i++) {
+ pmd = (pmd_t *)pgd;
+ for (; (j < PTRS_PER_PMD) && (vaddr != end); pmd++, j++) {
+ if (pmd_none(*pmd)) {
+ pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
+ set_pmd(pmd, __pmd((unsigned long)pte));
+ if (pte != pte_offset_kernel(pmd, 0))
+ BUG();
+ }
+ vaddr += PMD_SIZE;
+ }
+ j = 0;
+ }
+}
+#endif
+
+void __init pagetable_init(void)
+{
+#ifdef CONFIG_HIGHMEM
+ unsigned long vaddr;
+ pgd_t *pgd, *pgd_base;
+ pmd_t *pmd;
+ pte_t *pte;
+#endif
+
+ /* Initialize the entire pgd. */
+ pgd_init((unsigned long)swapper_pg_dir);
+ pgd_init((unsigned long)swapper_pg_dir
+ + sizeof(pgd_t) * USER_PTRS_PER_PGD);
+
+#ifdef CONFIG_HIGHMEM
+ pgd_base = swapper_pg_dir;
+
+ /*
+ * Fixed mappings:
+ */
+ vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK;
+ fixrange_init(vaddr, 0, pgd_base);
+
+ /*
+ * Permanent kmaps:
+ */
+ vaddr = PKMAP_BASE;
+ fixrange_init(vaddr, vaddr + PAGE_SIZE*LAST_PKMAP, pgd_base);
+
+ pgd = swapper_pg_dir + __pgd_offset(vaddr);
+ pmd = pmd_offset(pgd, vaddr);
+ pte = pte_offset_kernel(pmd, vaddr);
+ pkmap_page_table = pte;
+#endif
+}
diff --git a/arch/mips/mm/pgtable-64.c b/arch/mips/mm/pgtable-64.c
new file mode 100644
index 0000000..44b5e97f
--- /dev/null
+++ b/arch/mips/mm/pgtable-64.c
@@ -0,0 +1,58 @@
+/*
+ * 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) 1999, 2000 by Silicon Graphics
+ * Copyright (C) 2003 by Ralf Baechle
+ */
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <asm/pgtable.h>
+
+void pgd_init(unsigned long page)
+{
+ unsigned long *p, *end;
+
+ p = (unsigned long *) page;
+ end = p + PTRS_PER_PGD;
+
+ while (p < end) {
+ p[0] = (unsigned long) invalid_pmd_table;
+ p[1] = (unsigned long) invalid_pmd_table;
+ p[2] = (unsigned long) invalid_pmd_table;
+ p[3] = (unsigned long) invalid_pmd_table;
+ p[4] = (unsigned long) invalid_pmd_table;
+ p[5] = (unsigned long) invalid_pmd_table;
+ p[6] = (unsigned long) invalid_pmd_table;
+ p[7] = (unsigned long) invalid_pmd_table;
+ p += 8;
+ }
+}
+
+void pmd_init(unsigned long addr, unsigned long pagetable)
+{
+ unsigned long *p, *end;
+
+ p = (unsigned long *) addr;
+ end = p + PTRS_PER_PMD;
+
+ while (p < end) {
+ p[0] = (unsigned long)pagetable;
+ p[1] = (unsigned long)pagetable;
+ p[2] = (unsigned long)pagetable;
+ p[3] = (unsigned long)pagetable;
+ p[4] = (unsigned long)pagetable;
+ p[5] = (unsigned long)pagetable;
+ p[6] = (unsigned long)pagetable;
+ p[7] = (unsigned long)pagetable;
+ p += 8;
+ }
+}
+
+void __init pagetable_init(void)
+{
+ /* Initialize the entire pgd. */
+ pgd_init((unsigned long)swapper_pg_dir);
+ pmd_init((unsigned long)invalid_pmd_table, (unsigned long)invalid_pte_table);
+}
diff --git a/arch/mips/mm/pgtable.c b/arch/mips/mm/pgtable.c
new file mode 100644
index 0000000..3b88fde
--- /dev/null
+++ b/arch/mips/mm/pgtable.c
@@ -0,0 +1,36 @@
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/swap.h>
+
+void show_mem(void)
+{
+#ifndef CONFIG_DISCONTIGMEM /* XXX(hch): later.. */
+ int pfn, total = 0, reserved = 0;
+ int shared = 0, cached = 0;
+ int highmem = 0;
+ struct page *page;
+
+ printk("Mem-info:\n");
+ show_free_areas();
+ printk("Free swap: %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
+ pfn = max_mapnr;
+ while (pfn-- > 0) {
+ page = pfn_to_page(pfn);
+ total++;
+ if (PageHighMem(page))
+ highmem++;
+ if (PageReserved(page))
+ reserved++;
+ else if (PageSwapCache(page))
+ cached++;
+ else if (page_count(page))
+ shared += page_count(page) - 1;
+ }
+ printk("%d pages of RAM\n", total);
+ printk("%d pages of HIGHMEM\n",highmem);
+ printk("%d reserved pages\n",reserved);
+ printk("%d pages shared\n",shared);
+ printk("%d pages swap cached\n",cached);
+#endif
+}
diff --git a/arch/mips/mm/sc-ip22.c b/arch/mips/mm/sc-ip22.c
new file mode 100644
index 0000000..d236cf8
--- /dev/null
+++ b/arch/mips/mm/sc-ip22.c
@@ -0,0 +1,177 @@
+/*
+ * sc-ip22.c: Indy cache management functions.
+ *
+ * Copyright (C) 1997, 2001 Ralf Baechle (ralf@gnu.org),
+ * derived from r4xx0.c by David S. Miller (dm@engr.sgi.com).
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+
+#include <asm/bcache.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include <asm/bootinfo.h>
+#include <asm/sgi/ip22.h>
+#include <asm/sgi/mc.h>
+
+/* Secondary cache size in bytes, if present. */
+static unsigned long scache_size;
+
+#undef DEBUG_CACHE
+
+#define SC_SIZE 0x00080000
+#define SC_LINE 32
+#define CI_MASK (SC_SIZE - SC_LINE)
+#define SC_INDEX(n) ((n) & CI_MASK)
+
+static inline void indy_sc_wipe(unsigned long first, unsigned long last)
+{
+ unsigned long tmp;
+
+ __asm__ __volatile__(
+ ".set\tpush\t\t\t# indy_sc_wipe\n\t"
+ ".set\tnoreorder\n\t"
+ ".set\tmips3\n\t"
+ ".set\tnoat\n\t"
+ "mfc0\t%2, $12\n\t"
+ "li\t$1, 0x80\t\t\t# Go 64 bit\n\t"
+ "mtc0\t$1, $12\n\t"
+
+ "dli\t$1, 0x9000000080000000\n\t"
+ "or\t%0, $1\t\t\t# first line to flush\n\t"
+ "or\t%1, $1\t\t\t# last line to flush\n\t"
+ ".set\tat\n\t"
+
+ "1:\tsw\t$0, 0(%0)\n\t"
+ "bne\t%0, %1, 1b\n\t"
+ " daddu\t%0, 32\n\t"
+
+ "mtc0\t%2, $12\t\t\t# Back to 32 bit\n\t"
+ "nop; nop; nop; nop;\n\t"
+ ".set\tpop"
+ : "=r" (first), "=r" (last), "=&r" (tmp)
+ : "0" (first), "1" (last));
+}
+
+static void indy_sc_wback_invalidate(unsigned long addr, unsigned long size)
+{
+ unsigned long first_line, last_line;
+ unsigned long flags;
+
+#ifdef DEBUG_CACHE
+ printk("indy_sc_wback_invalidate[%08lx,%08lx]", addr, size);
+#endif
+
+ /* Catch bad driver code */
+ BUG_ON(size == 0);
+
+ /* Which lines to flush? */
+ first_line = SC_INDEX(addr);
+ last_line = SC_INDEX(addr + size - 1);
+
+ local_irq_save(flags);
+ if (first_line <= last_line) {
+ indy_sc_wipe(first_line, last_line);
+ goto out;
+ }
+
+ indy_sc_wipe(first_line, SC_SIZE - SC_LINE);
+ indy_sc_wipe(0, last_line);
+out:
+ local_irq_restore(flags);
+}
+
+static void indy_sc_enable(void)
+{
+ unsigned long addr, tmp1, tmp2;
+
+ /* This is really cool... */
+#ifdef DEBUG_CACHE
+ printk("Enabling R4600 SCACHE\n");
+#endif
+ __asm__ __volatile__(
+ ".set\tpush\n\t"
+ ".set\tnoreorder\n\t"
+ ".set\tmips3\n\t"
+ "mfc0\t%2, $12\n\t"
+ "nop; nop; nop; nop;\n\t"
+ "li\t%1, 0x80\n\t"
+ "mtc0\t%1, $12\n\t"
+ "nop; nop; nop; nop;\n\t"
+ "li\t%0, 0x1\n\t"
+ "dsll\t%0, 31\n\t"
+ "lui\t%1, 0x9000\n\t"
+ "dsll32\t%1, 0\n\t"
+ "or\t%0, %1, %0\n\t"
+ "sb\t$0, 0(%0)\n\t"
+ "mtc0\t$0, $12\n\t"
+ "nop; nop; nop; nop;\n\t"
+ "mtc0\t%2, $12\n\t"
+ "nop; nop; nop; nop;\n\t"
+ ".set\tpop"
+ : "=r" (tmp1), "=r" (tmp2), "=r" (addr));
+}
+
+static void indy_sc_disable(void)
+{
+ unsigned long tmp1, tmp2, tmp3;
+
+#ifdef DEBUG_CACHE
+ printk("Disabling R4600 SCACHE\n");
+#endif
+ __asm__ __volatile__(
+ ".set\tpush\n\t"
+ ".set\tnoreorder\n\t"
+ ".set\tmips3\n\t"
+ "li\t%0, 0x1\n\t"
+ "dsll\t%0, 31\n\t"
+ "lui\t%1, 0x9000\n\t"
+ "dsll32\t%1, 0\n\t"
+ "or\t%0, %1, %0\n\t"
+ "mfc0\t%2, $12\n\t"
+ "nop; nop; nop; nop\n\t"
+ "li\t%1, 0x80\n\t"
+ "mtc0\t%1, $12\n\t"
+ "nop; nop; nop; nop\n\t"
+ "sh\t$0, 0(%0)\n\t"
+ "mtc0\t$0, $12\n\t"
+ "nop; nop; nop; nop\n\t"
+ "mtc0\t%2, $12\n\t"
+ "nop; nop; nop; nop\n\t"
+ ".set\tpop"
+ : "=r" (tmp1), "=r" (tmp2), "=r" (tmp3));
+}
+
+static inline int __init indy_sc_probe(void)
+{
+ unsigned int size = ip22_eeprom_read(&sgimc->eeprom, 17);
+ if (size == 0)
+ return 0;
+
+ size <<= PAGE_SHIFT;
+ printk(KERN_INFO "R4600/R5000 SCACHE size %dK, linesize 32 bytes.\n",
+ size >> 10);
+ scache_size = size;
+
+ return 1;
+}
+
+/* XXX Check with wje if the Indy caches can differenciate between
+ writeback + invalidate and just invalidate. */
+struct bcache_ops indy_sc_ops = {
+ .bc_enable = indy_sc_enable,
+ .bc_disable = indy_sc_disable,
+ .bc_wback_inv = indy_sc_wback_invalidate,
+ .bc_inv = indy_sc_wback_invalidate
+};
+
+void __init indy_sc_init(void)
+{
+ if (indy_sc_probe()) {
+ indy_sc_enable();
+ bcops = &indy_sc_ops;
+ }
+}
diff --git a/arch/mips/mm/sc-r5k.c b/arch/mips/mm/sc-r5k.c
new file mode 100644
index 0000000..d35b6c1
--- /dev/null
+++ b/arch/mips/mm/sc-r5k.c
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 1997, 2001 Ralf Baechle (ralf@gnu.org),
+ * derived from r4xx0.c by David S. Miller (dm@engr.sgi.com).
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+
+#include <asm/mipsregs.h>
+#include <asm/bcache.h>
+#include <asm/cacheops.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include <asm/mmu_context.h>
+#include <asm/r4kcache.h>
+
+/* Secondary cache size in bytes, if present. */
+static unsigned long scache_size;
+
+#define SC_LINE 32
+#define SC_PAGE (128*SC_LINE)
+
+static inline void blast_r5000_scache(void)
+{
+ unsigned long start = INDEX_BASE;
+ unsigned long end = start + scache_size;
+
+ while(start < end) {
+ cache_op(R5K_Page_Invalidate_S, start);
+ start += SC_PAGE;
+ }
+}
+
+static void r5k_dma_cache_inv_sc(unsigned long addr, unsigned long size)
+{
+ unsigned long end, a;
+
+ /* Catch bad driver code */
+ BUG_ON(size == 0);
+
+ if (size >= scache_size) {
+ blast_r5000_scache();
+ return;
+ }
+
+ /* On the R5000 secondary cache we cannot
+ * invalidate less than a page at a time.
+ * The secondary cache is physically indexed, write-through.
+ */
+ a = addr & ~(SC_PAGE - 1);
+ end = (addr + size - 1) & ~(SC_PAGE - 1);
+ while (a <= end) {
+ cache_op(R5K_Page_Invalidate_S, a);
+ a += SC_PAGE;
+ }
+}
+
+static void r5k_sc_enable(void)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+ set_c0_config(R5K_CONF_SE);
+ blast_r5000_scache();
+ local_irq_restore(flags);
+}
+
+static void r5k_sc_disable(void)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+ blast_r5000_scache();
+ clear_c0_config(R5K_CONF_SE);
+ local_irq_restore(flags);
+}
+
+static inline int __init r5k_sc_probe(void)
+{
+ unsigned long config = read_c0_config();
+
+ if (config & CONF_SC)
+ return(0);
+
+ scache_size = (512 * 1024) << ((config & R5K_CONF_SS) >> 20);
+
+ printk("R5000 SCACHE size %ldkB, linesize 32 bytes.\n",
+ scache_size >> 10);
+
+ return 1;
+}
+
+static struct bcache_ops r5k_sc_ops = {
+ .bc_enable = r5k_sc_enable,
+ .bc_disable = r5k_sc_disable,
+ .bc_wback_inv = r5k_dma_cache_inv_sc,
+ .bc_inv = r5k_dma_cache_inv_sc
+};
+
+void __init r5k_sc_init(void)
+{
+ if (r5k_sc_probe()) {
+ r5k_sc_enable();
+ bcops = &r5k_sc_ops;
+ }
+}
diff --git a/arch/mips/mm/sc-rm7k.c b/arch/mips/mm/sc-rm7k.c
new file mode 100644
index 0000000..4e92f93
--- /dev/null
+++ b/arch/mips/mm/sc-rm7k.c
@@ -0,0 +1,193 @@
+/*
+ * sc-rm7k.c: RM7000 cache management functions.
+ *
+ * Copyright (C) 1997, 2001, 2003, 2004 Ralf Baechle (ralf@linux-mips.org)
+ */
+
+#undef DEBUG
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+
+#include <asm/addrspace.h>
+#include <asm/bcache.h>
+#include <asm/cacheops.h>
+#include <asm/mipsregs.h>
+#include <asm/processor.h>
+
+/* Primary cache parameters. */
+#define sc_lsize 32
+#define tc_pagesize (32*128)
+
+/* Secondary cache parameters. */
+#define scache_size (256*1024) /* Fixed to 256KiB on RM7000 */
+
+extern unsigned long icache_way_size, dcache_way_size;
+
+#include <asm/r4kcache.h>
+
+int rm7k_tcache_enabled;
+
+/*
+ * Writeback and invalidate the primary cache dcache before DMA.
+ * (XXX These need to be fixed ...)
+ */
+static void rm7k_sc_wback_inv(unsigned long addr, unsigned long size)
+{
+ unsigned long end, a;
+
+ pr_debug("rm7k_sc_wback_inv[%08lx,%08lx]", addr, size);
+
+ /* Catch bad driver code */
+ BUG_ON(size == 0);
+
+ a = addr & ~(sc_lsize - 1);
+ end = (addr + size - 1) & ~(sc_lsize - 1);
+ while (1) {
+ flush_scache_line(a); /* Hit_Writeback_Inv_SD */
+ if (a == end)
+ break;
+ a += sc_lsize;
+ }
+
+ if (!rm7k_tcache_enabled)
+ return;
+
+ a = addr & ~(tc_pagesize - 1);
+ end = (addr + size - 1) & ~(tc_pagesize - 1);
+ while(1) {
+ invalidate_tcache_page(a); /* Page_Invalidate_T */
+ if (a == end)
+ break;
+ a += tc_pagesize;
+ }
+}
+
+static void rm7k_sc_inv(unsigned long addr, unsigned long size)
+{
+ unsigned long end, a;
+
+ pr_debug("rm7k_sc_inv[%08lx,%08lx]", addr, size);
+
+ /* Catch bad driver code */
+ BUG_ON(size == 0);
+
+ a = addr & ~(sc_lsize - 1);
+ end = (addr + size - 1) & ~(sc_lsize - 1);
+ while (1) {
+ invalidate_scache_line(a); /* Hit_Invalidate_SD */
+ if (a == end)
+ break;
+ a += sc_lsize;
+ }
+
+ if (!rm7k_tcache_enabled)
+ return;
+
+ a = addr & ~(tc_pagesize - 1);
+ end = (addr + size - 1) & ~(tc_pagesize - 1);
+ while(1) {
+ invalidate_tcache_page(a); /* Page_Invalidate_T */
+ if (a == end)
+ break;
+ a += tc_pagesize;
+ }
+}
+
+/*
+ * This function is executed in the uncached segment CKSEG1.
+ * It must not touch the stack, because the stack pointer still points
+ * into CKSEG0.
+ *
+ * Three options:
+ * - Write it in assembly and guarantee that we don't use the stack.
+ * - Disable caching for CKSEG0 before calling it.
+ * - Pray that GCC doesn't randomly start using the stack.
+ *
+ * This being Linux, we obviously take the least sane of those options -
+ * following DaveM's lead in c-r4k.c
+ *
+ * It seems we get our kicks from relying on unguaranteed behaviour in GCC
+ */
+static __init void __rm7k_sc_enable(void)
+{
+ int i;
+
+ set_c0_config(1 << 3); /* CONF_SE */
+
+ write_c0_taglo(0);
+ write_c0_taghi(0);
+
+ for (i = 0; i < scache_size; i += sc_lsize) {
+ __asm__ __volatile__ (
+ ".set noreorder\n\t"
+ ".set mips3\n\t"
+ "cache %1, (%0)\n\t"
+ ".set mips0\n\t"
+ ".set reorder"
+ :
+ : "r" (KSEG0ADDR(i)), "i" (Index_Store_Tag_SD));
+ }
+}
+
+static __init void rm7k_sc_enable(void)
+{
+ void (*func)(void) = (void *) KSEG1ADDR(&__rm7k_sc_enable);
+
+ if (read_c0_config() & 0x08) /* CONF_SE */
+ return;
+
+ printk(KERN_INFO "Enabling secondary cache...");
+ func();
+}
+
+static void rm7k_sc_disable(void)
+{
+ clear_c0_config(1<<3); /* CONF_SE */
+}
+
+struct bcache_ops rm7k_sc_ops = {
+ .bc_enable = rm7k_sc_enable,
+ .bc_disable = rm7k_sc_disable,
+ .bc_wback_inv = rm7k_sc_wback_inv,
+ .bc_inv = rm7k_sc_inv
+};
+
+void __init rm7k_sc_init(void)
+{
+ unsigned int config = read_c0_config();
+
+ if ((config >> 31) & 1) /* Bit 31 set -> no S-Cache */
+ return;
+
+ printk(KERN_INFO "Secondary cache size %dK, linesize %d bytes.\n",
+ (scache_size >> 10), sc_lsize);
+
+ if (!((config >> 3) & 1)) /* CONF_SE */
+ rm7k_sc_enable();
+
+ /*
+ * While we're at it let's deal with the tertiary cache.
+ */
+ if (!((config >> 17) & 1)) {
+
+ /*
+ * We can't enable the L3 cache yet. There may be board-specific
+ * magic necessary to turn it on, and blindly asking the CPU to
+ * start using it would may give cache errors.
+ *
+ * Also, board-specific knowledge may allow us to use the
+ * CACHE Flash_Invalidate_T instruction if the tag RAM supports
+ * it, and may specify the size of the L3 cache so we don't have
+ * to probe it.
+ */
+ printk(KERN_INFO "Tertiary cache present, %s enabled\n",
+ config&(1<<12) ? "already" : "not (yet)");
+
+ if ((config >> 12) & 1)
+ rm7k_tcache_enabled = 1;
+ }
+
+ bcops = &rm7k_sc_ops;
+}
diff --git a/arch/mips/mm/tlb-andes.c b/arch/mips/mm/tlb-andes.c
new file mode 100644
index 0000000..167e08e
--- /dev/null
+++ b/arch/mips/mm/tlb-andes.c
@@ -0,0 +1,257 @@
+/*
+ * 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) 1997, 1998, 1999 Ralf Baechle (ralf@gnu.org)
+ * Copyright (C) 1999 Silicon Graphics, Inc.
+ * Copyright (C) 2000 Kanoj Sarcar (kanoj@sgi.com)
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include <asm/mmu_context.h>
+
+extern void build_tlb_refill_handler(void);
+
+#define NTLB_ENTRIES 64
+#define NTLB_ENTRIES_HALF 32
+
+void local_flush_tlb_all(void)
+{
+ unsigned long flags;
+ unsigned long old_ctx;
+ unsigned long entry;
+
+ local_irq_save(flags);
+ /* Save old context and create impossible VPN2 value */
+ old_ctx = read_c0_entryhi() & ASID_MASK;
+ write_c0_entryhi(CKSEG0);
+ write_c0_entrylo0(0);
+ write_c0_entrylo1(0);
+
+ entry = read_c0_wired();
+
+ /* Blast 'em all away. */
+ while (entry < NTLB_ENTRIES) {
+ write_c0_index(entry);
+ tlb_write_indexed();
+ entry++;
+ }
+ write_c0_entryhi(old_ctx);
+ local_irq_restore(flags);
+}
+
+void local_flush_tlb_mm(struct mm_struct *mm)
+{
+ int cpu = smp_processor_id();
+ if (cpu_context(cpu, mm) != 0) {
+ drop_mmu_context(mm,cpu);
+ }
+}
+
+void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
+ unsigned long end)
+{
+ struct mm_struct *mm = vma->vm_mm;
+ int cpu = smp_processor_id();
+
+ if (cpu_context(cpu, mm) != 0) {
+ unsigned long flags;
+ int size;
+
+ local_irq_save(flags);
+ size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
+ size = (size + 1) >> 1;
+ if (size <= NTLB_ENTRIES_HALF) {
+ int oldpid = (read_c0_entryhi() & ASID_MASK);
+ int newpid = (cpu_context(smp_processor_id(), mm)
+ & ASID_MASK);
+
+ start &= (PAGE_MASK << 1);
+ end += ((PAGE_SIZE << 1) - 1);
+ end &= (PAGE_MASK << 1);
+ while(start < end) {
+ int idx;
+
+ write_c0_entryhi(start | newpid);
+ start += (PAGE_SIZE << 1);
+ tlb_probe();
+ idx = read_c0_index();
+ write_c0_entrylo0(0);
+ write_c0_entrylo1(0);
+ write_c0_entryhi(CKSEG0);
+ if(idx < 0)
+ continue;
+ tlb_write_indexed();
+ }
+ write_c0_entryhi(oldpid);
+ } else {
+ drop_mmu_context(mm, cpu);
+ }
+ local_irq_restore(flags);
+ }
+}
+
+void local_flush_tlb_kernel_range(unsigned long start, unsigned long end)
+{
+ unsigned long flags;
+ int size;
+
+ size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
+ size = (size + 1) >> 1;
+
+ local_irq_save(flags);
+ if (size <= NTLB_ENTRIES_HALF) {
+ int pid = read_c0_entryhi();
+
+ start &= (PAGE_MASK << 1);
+ end += ((PAGE_SIZE << 1) - 1);
+ end &= (PAGE_MASK << 1);
+
+ while (start < end) {
+ int idx;
+
+ write_c0_entryhi(start);
+ start += (PAGE_SIZE << 1);
+ tlb_probe();
+ idx = read_c0_index();
+ write_c0_entrylo0(0);
+ write_c0_entrylo1(0);
+ write_c0_entryhi(CKSEG0 + (idx << (PAGE_SHIFT+1)));
+ if (idx < 0)
+ continue;
+ tlb_write_indexed();
+ }
+ write_c0_entryhi(pid);
+ } else {
+ local_flush_tlb_all();
+ }
+ local_irq_restore(flags);
+}
+
+void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
+{
+ if (cpu_context(smp_processor_id(), vma->vm_mm) != 0) {
+ unsigned long flags;
+ int oldpid, newpid, idx;
+
+ newpid = (cpu_context(smp_processor_id(), vma->vm_mm) &
+ ASID_MASK);
+ page &= (PAGE_MASK << 1);
+ local_irq_save(flags);
+ oldpid = (read_c0_entryhi() & ASID_MASK);
+ write_c0_entryhi(page | newpid);
+ tlb_probe();
+ idx = read_c0_index();
+ write_c0_entrylo0(0);
+ write_c0_entrylo1(0);
+ write_c0_entryhi(CKSEG0);
+ if (idx < 0)
+ goto finish;
+ tlb_write_indexed();
+
+ finish:
+ write_c0_entryhi(oldpid);
+ local_irq_restore(flags);
+ }
+}
+
+/*
+ * This one is only used for pages with the global bit set so we don't care
+ * much about the ASID.
+ */
+void local_flush_tlb_one(unsigned long page)
+{
+ unsigned long flags;
+ int oldpid, idx;
+
+ local_irq_save(flags);
+ page &= (PAGE_MASK << 1);
+ oldpid = read_c0_entryhi() & 0xff;
+ write_c0_entryhi(page);
+ tlb_probe();
+ idx = read_c0_index();
+ write_c0_entrylo0(0);
+ write_c0_entrylo1(0);
+ if (idx >= 0) {
+ /* Make sure all entries differ. */
+ write_c0_entryhi(CKSEG0+(idx<<(PAGE_SHIFT+1)));
+ tlb_write_indexed();
+ }
+ write_c0_entryhi(oldpid);
+
+ local_irq_restore(flags);
+}
+
+/* XXX Simplify this. On the R10000 writing a TLB entry for an virtual
+ address that already exists will overwrite the old entry and not result
+ in TLB malfunction or TLB shutdown. */
+void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte)
+{
+ unsigned long flags;
+ pgd_t *pgdp;
+ pmd_t *pmdp;
+ pte_t *ptep;
+ int idx, pid;
+
+ /*
+ * Handle debugger faulting in for debugee.
+ */
+ if (current->active_mm != vma->vm_mm)
+ return;
+
+ pid = read_c0_entryhi() & ASID_MASK;
+
+ if ((pid != (cpu_context(smp_processor_id(), vma->vm_mm) & ASID_MASK))
+ || (cpu_context(smp_processor_id(), vma->vm_mm) == 0)) {
+ printk(KERN_WARNING
+ "%s: Wheee, bogus tlbpid mmpid=%d tlbpid=%d\n",
+ __FUNCTION__, (int) (cpu_context(smp_processor_id(),
+ vma->vm_mm) & ASID_MASK), pid);
+ }
+
+ local_irq_save(flags);
+ address &= (PAGE_MASK << 1);
+ write_c0_entryhi(address | (pid));
+ pgdp = pgd_offset(vma->vm_mm, address);
+ tlb_probe();
+ pmdp = pmd_offset(pgdp, address);
+ idx = read_c0_index();
+ ptep = pte_offset_map(pmdp, address);
+ write_c0_entrylo0(pte_val(*ptep++) >> 6);
+ write_c0_entrylo1(pte_val(*ptep) >> 6);
+ write_c0_entryhi(address | pid);
+ if (idx < 0) {
+ tlb_write_random();
+ } else {
+ tlb_write_indexed();
+ }
+ write_c0_entryhi(pid);
+ local_irq_restore(flags);
+}
+
+void __init tlb_init(void)
+{
+ /*
+ * You should never change this register:
+ * - On R4600 1.7 the tlbp never hits for pages smaller than
+ * the value in the c0_pagemask register.
+ * - The entire mm handling assumes the c0_pagemask register to
+ * be set for 4kb pages.
+ */
+ write_c0_pagemask(PM_4K);
+ write_c0_wired(0);
+ write_c0_framemask(0);
+
+ /* From this point on the ARC firmware is dead. */
+ local_flush_tlb_all();
+
+ /* Did I tell you that ARC SUCKS? */
+
+ build_tlb_refill_handler();
+}
diff --git a/arch/mips/mm/tlb-r3k.c b/arch/mips/mm/tlb-r3k.c
new file mode 100644
index 0000000..7948e9a
--- /dev/null
+++ b/arch/mips/mm/tlb-r3k.c
@@ -0,0 +1,289 @@
+/*
+ * r2300.c: R2000 and R3000 specific mmu/cache code.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ *
+ * with a lot of changes to make this thing work for R3000s
+ * Tx39XX R4k style caches added. HK
+ * Copyright (C) 1998, 1999, 2000 Harald Koerfgen
+ * Copyright (C) 1998 Gleb Raiko & Vladimir Roganov
+ * Copyright (C) 2002 Ralf Baechle
+ * Copyright (C) 2002 Maciej W. Rozycki
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/mmu_context.h>
+#include <asm/system.h>
+#include <asm/isadep.h>
+#include <asm/io.h>
+#include <asm/bootinfo.h>
+#include <asm/cpu.h>
+
+#undef DEBUG_TLB
+
+extern void build_tlb_refill_handler(void);
+
+/* CP0 hazard avoidance. */
+#define BARRIER \
+ __asm__ __volatile__( \
+ ".set push\n\t" \
+ ".set noreorder\n\t" \
+ "nop\n\t" \
+ ".set pop\n\t")
+
+int r3k_have_wired_reg; /* should be in cpu_data? */
+
+/* TLB operations. */
+void local_flush_tlb_all(void)
+{
+ unsigned long flags;
+ unsigned long old_ctx;
+ int entry;
+
+#ifdef DEBUG_TLB
+ printk("[tlball]");
+#endif
+
+ local_irq_save(flags);
+ old_ctx = read_c0_entryhi() & ASID_MASK;
+ write_c0_entrylo0(0);
+ entry = r3k_have_wired_reg ? read_c0_wired() : 8;
+ for (; entry < current_cpu_data.tlbsize; entry++) {
+ write_c0_index(entry << 8);
+ write_c0_entryhi((entry | 0x80000) << 12);
+ BARRIER;
+ tlb_write_indexed();
+ }
+ write_c0_entryhi(old_ctx);
+ local_irq_restore(flags);
+}
+
+void local_flush_tlb_mm(struct mm_struct *mm)
+{
+ int cpu = smp_processor_id();
+
+ if (cpu_context(cpu, mm) != 0) {
+#ifdef DEBUG_TLB
+ printk("[tlbmm<%lu>]", (unsigned long)cpu_context(cpu, mm));
+#endif
+ drop_mmu_context(mm, cpu);
+ }
+}
+
+void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
+ unsigned long end)
+{
+ struct mm_struct *mm = vma->vm_mm;
+ int cpu = smp_processor_id();
+
+ if (cpu_context(cpu, mm) != 0) {
+ unsigned long flags;
+ int size;
+
+#ifdef DEBUG_TLB
+ printk("[tlbrange<%lu,0x%08lx,0x%08lx>]",
+ cpu_context(cpu, mm) & ASID_MASK, start, end);
+#endif
+ local_irq_save(flags);
+ size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
+ if (size <= current_cpu_data.tlbsize) {
+ int oldpid = read_c0_entryhi() & ASID_MASK;
+ int newpid = cpu_context(cpu, mm) & ASID_MASK;
+
+ start &= PAGE_MASK;
+ end += PAGE_SIZE - 1;
+ end &= PAGE_MASK;
+ while (start < end) {
+ int idx;
+
+ write_c0_entryhi(start | newpid);
+ start += PAGE_SIZE; /* BARRIER */
+ tlb_probe();
+ idx = read_c0_index();
+ write_c0_entrylo0(0);
+ write_c0_entryhi(KSEG0);
+ if (idx < 0) /* BARRIER */
+ continue;
+ tlb_write_indexed();
+ }
+ write_c0_entryhi(oldpid);
+ } else {
+ drop_mmu_context(mm, cpu);
+ }
+ local_irq_restore(flags);
+ }
+}
+
+void local_flush_tlb_kernel_range(unsigned long start, unsigned long end)
+{
+ unsigned long flags;
+ int size;
+
+#ifdef DEBUG_TLB
+ printk("[tlbrange<%lu,0x%08lx,0x%08lx>]", start, end);
+#endif
+ local_irq_save(flags);
+ size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
+ if (size <= current_cpu_data.tlbsize) {
+ int pid = read_c0_entryhi();
+
+ start &= PAGE_MASK;
+ end += PAGE_SIZE - 1;
+ end &= PAGE_MASK;
+
+ while (start < end) {
+ int idx;
+
+ write_c0_entryhi(start);
+ start += PAGE_SIZE; /* BARRIER */
+ tlb_probe();
+ idx = read_c0_index();
+ write_c0_entrylo0(0);
+ write_c0_entryhi(KSEG0);
+ if (idx < 0) /* BARRIER */
+ continue;
+ tlb_write_indexed();
+ }
+ write_c0_entryhi(pid);
+ } else {
+ local_flush_tlb_all();
+ }
+ local_irq_restore(flags);
+}
+
+void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
+{
+ int cpu = smp_processor_id();
+
+ if (!vma || cpu_context(cpu, vma->vm_mm) != 0) {
+ unsigned long flags;
+ int oldpid, newpid, idx;
+
+#ifdef DEBUG_TLB
+ printk("[tlbpage<%lu,0x%08lx>]", cpu_context(cpu, vma->vm_mm), page);
+#endif
+ newpid = cpu_context(cpu, vma->vm_mm) & ASID_MASK;
+ page &= PAGE_MASK;
+ local_irq_save(flags);
+ oldpid = read_c0_entryhi() & ASID_MASK;
+ write_c0_entryhi(page | newpid);
+ BARRIER;
+ tlb_probe();
+ idx = read_c0_index();
+ write_c0_entrylo0(0);
+ write_c0_entryhi(KSEG0);
+ if (idx < 0) /* BARRIER */
+ goto finish;
+ tlb_write_indexed();
+
+finish:
+ write_c0_entryhi(oldpid);
+ local_irq_restore(flags);
+ }
+}
+
+void __update_tlb(struct vm_area_struct *vma, unsigned long address, pte_t pte)
+{
+ unsigned long flags;
+ int idx, pid;
+
+ /*
+ * Handle debugger faulting in for debugee.
+ */
+ if (current->active_mm != vma->vm_mm)
+ return;
+
+ pid = read_c0_entryhi() & ASID_MASK;
+
+#ifdef DEBUG_TLB
+ if ((pid != (cpu_context(cpu, vma->vm_mm) & ASID_MASK)) || (cpu_context(cpu, vma->vm_mm) == 0)) {
+ printk("update_mmu_cache: Wheee, bogus tlbpid mmpid=%lu tlbpid=%d\n",
+ (cpu_context(cpu, vma->vm_mm)), pid);
+ }
+#endif
+
+ local_irq_save(flags);
+ address &= PAGE_MASK;
+ write_c0_entryhi(address | pid);
+ BARRIER;
+ tlb_probe();
+ idx = read_c0_index();
+ write_c0_entrylo0(pte_val(pte));
+ write_c0_entryhi(address | pid);
+ if (idx < 0) { /* BARRIER */
+ tlb_write_random();
+ } else {
+ tlb_write_indexed();
+ }
+ write_c0_entryhi(pid);
+ local_irq_restore(flags);
+}
+
+void __init add_wired_entry(unsigned long entrylo0, unsigned long entrylo1,
+ unsigned long entryhi, unsigned long pagemask)
+{
+ unsigned long flags;
+ unsigned long old_ctx;
+ static unsigned long wired = 0;
+
+ if (r3k_have_wired_reg) { /* TX39XX */
+ unsigned long old_pagemask;
+ unsigned long w;
+
+#ifdef DEBUG_TLB
+ printk("[tlbwired<entry lo0 %8x, hi %8x\n, pagemask %8x>]\n",
+ entrylo0, entryhi, pagemask);
+#endif
+
+ local_irq_save(flags);
+ /* Save old context and create impossible VPN2 value */
+ old_ctx = read_c0_entryhi() & ASID_MASK;
+ old_pagemask = read_c0_pagemask();
+ w = read_c0_wired();
+ write_c0_wired(w + 1);
+ if (read_c0_wired() != w + 1) {
+ printk("[tlbwired] No WIRED reg?\n");
+ return;
+ }
+ write_c0_index(w << 8);
+ write_c0_pagemask(pagemask);
+ write_c0_entryhi(entryhi);
+ write_c0_entrylo0(entrylo0);
+ BARRIER;
+ tlb_write_indexed();
+
+ write_c0_entryhi(old_ctx);
+ write_c0_pagemask(old_pagemask);
+ local_flush_tlb_all();
+ local_irq_restore(flags);
+
+ } else if (wired < 8) {
+#ifdef DEBUG_TLB
+ printk("[tlbwired<entry lo0 %8x, hi %8x\n>]\n",
+ entrylo0, entryhi);
+#endif
+
+ local_irq_save(flags);
+ old_ctx = read_c0_entryhi() & ASID_MASK;
+ write_c0_entrylo0(entrylo0);
+ write_c0_entryhi(entryhi);
+ write_c0_index(wired);
+ wired++; /* BARRIER */
+ tlb_write_indexed();
+ write_c0_entryhi(old_ctx);
+ local_flush_tlb_all();
+ local_irq_restore(flags);
+ }
+}
+
+void __init tlb_init(void)
+{
+ local_flush_tlb_all();
+
+ build_tlb_refill_handler();
+}
diff --git a/arch/mips/mm/tlb-r4k.c b/arch/mips/mm/tlb-r4k.c
new file mode 100644
index 0000000..59d38bc
--- /dev/null
+++ b/arch/mips/mm/tlb-r4k.c
@@ -0,0 +1,419 @@
+/*
+ * 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) 1996 David S. Miller (dm@engr.sgi.com)
+ * Copyright (C) 1997, 1998, 1999, 2000 Ralf Baechle ralf@gnu.org
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2002 MIPS Technologies, Inc. All rights reserved.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+
+#include <asm/cpu.h>
+#include <asm/bootinfo.h>
+#include <asm/mmu_context.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+
+extern void build_tlb_refill_handler(void);
+
+/* CP0 hazard avoidance. */
+#define BARRIER __asm__ __volatile__(".set noreorder\n\t" \
+ "nop; nop; nop; nop; nop; nop;\n\t" \
+ ".set reorder\n\t")
+
+void local_flush_tlb_all(void)
+{
+ unsigned long flags;
+ unsigned long old_ctx;
+ int entry;
+
+ local_irq_save(flags);
+ /* Save old context and create impossible VPN2 value */
+ old_ctx = read_c0_entryhi();
+ write_c0_entrylo0(0);
+ write_c0_entrylo1(0);
+
+ entry = read_c0_wired();
+
+ /* Blast 'em all away. */
+ while (entry < current_cpu_data.tlbsize) {
+ /*
+ * Make sure all entries differ. If they're not different
+ * MIPS32 will take revenge ...
+ */
+ write_c0_entryhi(CKSEG0 + (entry << (PAGE_SHIFT + 1)));
+ write_c0_index(entry);
+ mtc0_tlbw_hazard();
+ tlb_write_indexed();
+ entry++;
+ }
+ tlbw_use_hazard();
+ write_c0_entryhi(old_ctx);
+ local_irq_restore(flags);
+}
+
+void local_flush_tlb_mm(struct mm_struct *mm)
+{
+ int cpu = smp_processor_id();
+
+ if (cpu_context(cpu, mm) != 0)
+ drop_mmu_context(mm,cpu);
+}
+
+void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
+ unsigned long end)
+{
+ struct mm_struct *mm = vma->vm_mm;
+ int cpu = smp_processor_id();
+
+ if (cpu_context(cpu, mm) != 0) {
+ unsigned long flags;
+ int size;
+
+ local_irq_save(flags);
+ size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
+ size = (size + 1) >> 1;
+ if (size <= current_cpu_data.tlbsize/2) {
+ int oldpid = read_c0_entryhi();
+ int newpid = cpu_asid(cpu, mm);
+
+ start &= (PAGE_MASK << 1);
+ end += ((PAGE_SIZE << 1) - 1);
+ end &= (PAGE_MASK << 1);
+ while (start < end) {
+ int idx;
+
+ write_c0_entryhi(start | newpid);
+ start += (PAGE_SIZE << 1);
+ mtc0_tlbw_hazard();
+ tlb_probe();
+ BARRIER;
+ idx = read_c0_index();
+ write_c0_entrylo0(0);
+ write_c0_entrylo1(0);
+ if (idx < 0)
+ continue;
+ /* Make sure all entries differ. */
+ write_c0_entryhi(CKSEG0 +
+ (idx << (PAGE_SHIFT + 1)));
+ mtc0_tlbw_hazard();
+ tlb_write_indexed();
+ }
+ tlbw_use_hazard();
+ write_c0_entryhi(oldpid);
+ } else {
+ drop_mmu_context(mm, cpu);
+ }
+ local_irq_restore(flags);
+ }
+}
+
+void local_flush_tlb_kernel_range(unsigned long start, unsigned long end)
+{
+ unsigned long flags;
+ int size;
+
+ local_irq_save(flags);
+ size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
+ size = (size + 1) >> 1;
+ if (size <= current_cpu_data.tlbsize / 2) {
+ int pid = read_c0_entryhi();
+
+ start &= (PAGE_MASK << 1);
+ end += ((PAGE_SIZE << 1) - 1);
+ end &= (PAGE_MASK << 1);
+
+ while (start < end) {
+ int idx;
+
+ write_c0_entryhi(start);
+ start += (PAGE_SIZE << 1);
+ mtc0_tlbw_hazard();
+ tlb_probe();
+ BARRIER;
+ idx = read_c0_index();
+ write_c0_entrylo0(0);
+ write_c0_entrylo1(0);
+ if (idx < 0)
+ continue;
+ /* Make sure all entries differ. */
+ write_c0_entryhi(CKSEG0 + (idx << (PAGE_SHIFT + 1)));
+ mtc0_tlbw_hazard();
+ tlb_write_indexed();
+ }
+ tlbw_use_hazard();
+ write_c0_entryhi(pid);
+ } else {
+ local_flush_tlb_all();
+ }
+ local_irq_restore(flags);
+}
+
+void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
+{
+ int cpu = smp_processor_id();
+
+ if (cpu_context(cpu, vma->vm_mm) != 0) {
+ unsigned long flags;
+ int oldpid, newpid, idx;
+
+ newpid = cpu_asid(cpu, vma->vm_mm);
+ page &= (PAGE_MASK << 1);
+ local_irq_save(flags);
+ oldpid = read_c0_entryhi();
+ write_c0_entryhi(page | newpid);
+ mtc0_tlbw_hazard();
+ tlb_probe();
+ BARRIER;
+ idx = read_c0_index();
+ write_c0_entrylo0(0);
+ write_c0_entrylo1(0);
+ if (idx < 0)
+ goto finish;
+ /* Make sure all entries differ. */
+ write_c0_entryhi(CKSEG0 + (idx << (PAGE_SHIFT + 1)));
+ mtc0_tlbw_hazard();
+ tlb_write_indexed();
+ tlbw_use_hazard();
+
+ finish:
+ write_c0_entryhi(oldpid);
+ local_irq_restore(flags);
+ }
+}
+
+/*
+ * This one is only used for pages with the global bit set so we don't care
+ * much about the ASID.
+ */
+void local_flush_tlb_one(unsigned long page)
+{
+ unsigned long flags;
+ int oldpid, idx;
+
+ local_irq_save(flags);
+ page &= (PAGE_MASK << 1);
+ oldpid = read_c0_entryhi();
+ write_c0_entryhi(page);
+ mtc0_tlbw_hazard();
+ tlb_probe();
+ BARRIER;
+ idx = read_c0_index();
+ write_c0_entrylo0(0);
+ write_c0_entrylo1(0);
+ if (idx >= 0) {
+ /* Make sure all entries differ. */
+ write_c0_entryhi(CKSEG0 + (idx << (PAGE_SHIFT + 1)));
+ mtc0_tlbw_hazard();
+ tlb_write_indexed();
+ tlbw_use_hazard();
+ }
+ write_c0_entryhi(oldpid);
+
+ local_irq_restore(flags);
+}
+
+/*
+ * We will need multiple versions of update_mmu_cache(), one that just
+ * updates the TLB with the new pte(s), and another which also checks
+ * for the R4k "end of page" hardware bug and does the needy.
+ */
+void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte)
+{
+ unsigned long flags;
+ pgd_t *pgdp;
+ pmd_t *pmdp;
+ pte_t *ptep;
+ int idx, pid;
+
+ /*
+ * Handle debugger faulting in for debugee.
+ */
+ if (current->active_mm != vma->vm_mm)
+ return;
+
+ pid = read_c0_entryhi() & ASID_MASK;
+
+ local_irq_save(flags);
+ address &= (PAGE_MASK << 1);
+ write_c0_entryhi(address | pid);
+ pgdp = pgd_offset(vma->vm_mm, address);
+ mtc0_tlbw_hazard();
+ tlb_probe();
+ BARRIER;
+ pmdp = pmd_offset(pgdp, address);
+ idx = read_c0_index();
+ ptep = pte_offset_map(pmdp, address);
+
+ #if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32)
+ write_c0_entrylo0(ptep->pte_high);
+ ptep++;
+ write_c0_entrylo1(ptep->pte_high);
+#else
+ write_c0_entrylo0(pte_val(*ptep++) >> 6);
+ write_c0_entrylo1(pte_val(*ptep) >> 6);
+#endif
+ write_c0_entryhi(address | pid);
+ mtc0_tlbw_hazard();
+ if (idx < 0)
+ tlb_write_random();
+ else
+ tlb_write_indexed();
+ tlbw_use_hazard();
+ write_c0_entryhi(pid);
+ local_irq_restore(flags);
+}
+
+#if 0
+static void r4k_update_mmu_cache_hwbug(struct vm_area_struct * vma,
+ unsigned long address, pte_t pte)
+{
+ unsigned long flags;
+ unsigned int asid;
+ pgd_t *pgdp;
+ pmd_t *pmdp;
+ pte_t *ptep;
+ int idx;
+
+ local_irq_save(flags);
+ address &= (PAGE_MASK << 1);
+ asid = read_c0_entryhi() & ASID_MASK;
+ write_c0_entryhi(address | asid);
+ pgdp = pgd_offset(vma->vm_mm, address);
+ mtc0_tlbw_hazard();
+ tlb_probe();
+ BARRIER;
+ pmdp = pmd_offset(pgdp, address);
+ idx = read_c0_index();
+ ptep = pte_offset_map(pmdp, address);
+ write_c0_entrylo0(pte_val(*ptep++) >> 6);
+ write_c0_entrylo1(pte_val(*ptep) >> 6);
+ mtc0_tlbw_hazard();
+ if (idx < 0)
+ tlb_write_random();
+ else
+ tlb_write_indexed();
+ tlbw_use_hazard();
+ local_irq_restore(flags);
+}
+#endif
+
+void __init add_wired_entry(unsigned long entrylo0, unsigned long entrylo1,
+ unsigned long entryhi, unsigned long pagemask)
+{
+ unsigned long flags;
+ unsigned long wired;
+ unsigned long old_pagemask;
+ unsigned long old_ctx;
+
+ local_irq_save(flags);
+ /* Save old context and create impossible VPN2 value */
+ old_ctx = read_c0_entryhi();
+ old_pagemask = read_c0_pagemask();
+ wired = read_c0_wired();
+ write_c0_wired(wired + 1);
+ write_c0_index(wired);
+ BARRIER;
+ write_c0_pagemask(pagemask);
+ write_c0_entryhi(entryhi);
+ write_c0_entrylo0(entrylo0);
+ write_c0_entrylo1(entrylo1);
+ mtc0_tlbw_hazard();
+ tlb_write_indexed();
+ tlbw_use_hazard();
+
+ write_c0_entryhi(old_ctx);
+ BARRIER;
+ write_c0_pagemask(old_pagemask);
+ local_flush_tlb_all();
+ local_irq_restore(flags);
+}
+
+/*
+ * Used for loading TLB entries before trap_init() has started, when we
+ * don't actually want to add a wired entry which remains throughout the
+ * lifetime of the system
+ */
+
+static int temp_tlb_entry __initdata;
+
+__init int add_temporary_entry(unsigned long entrylo0, unsigned long entrylo1,
+ unsigned long entryhi, unsigned long pagemask)
+{
+ int ret = 0;
+ unsigned long flags;
+ unsigned long wired;
+ unsigned long old_pagemask;
+ unsigned long old_ctx;
+
+ local_irq_save(flags);
+ /* Save old context and create impossible VPN2 value */
+ old_ctx = read_c0_entryhi();
+ old_pagemask = read_c0_pagemask();
+ wired = read_c0_wired();
+ if (--temp_tlb_entry < wired) {
+ printk(KERN_WARNING "No TLB space left for add_temporary_entry\n");
+ ret = -ENOSPC;
+ goto out;
+ }
+
+ write_c0_index(temp_tlb_entry);
+ write_c0_pagemask(pagemask);
+ write_c0_entryhi(entryhi);
+ write_c0_entrylo0(entrylo0);
+ write_c0_entrylo1(entrylo1);
+ mtc0_tlbw_hazard();
+ tlb_write_indexed();
+ tlbw_use_hazard();
+
+ write_c0_entryhi(old_ctx);
+ write_c0_pagemask(old_pagemask);
+out:
+ local_irq_restore(flags);
+ return ret;
+}
+
+static void __init probe_tlb(unsigned long config)
+{
+ struct cpuinfo_mips *c = ¤t_cpu_data;
+ unsigned int reg;
+
+ /*
+ * If this isn't a MIPS32 / MIPS64 compliant CPU. Config 1 register
+ * is not supported, we assume R4k style. Cpu probing already figured
+ * out the number of tlb entries.
+ */
+ if ((c->processor_id & 0xff0000) == PRID_COMP_LEGACY)
+ return;
+
+ reg = read_c0_config1();
+ if (!((config >> 7) & 3))
+ panic("No TLB present");
+
+ c->tlbsize = ((reg >> 25) & 0x3f) + 1;
+}
+
+void __init tlb_init(void)
+{
+ unsigned int config = read_c0_config();
+
+ /*
+ * You should never change this register:
+ * - On R4600 1.7 the tlbp never hits for pages smaller than
+ * the value in the c0_pagemask register.
+ * - The entire mm handling assumes the c0_pagemask register to
+ * be set for 4kb pages.
+ */
+ probe_tlb(config);
+ write_c0_pagemask(PM_DEFAULT_MASK);
+ write_c0_wired(0);
+ temp_tlb_entry = current_cpu_data.tlbsize - 1;
+ local_flush_tlb_all();
+
+ build_tlb_refill_handler();
+}
diff --git a/arch/mips/mm/tlb-r8k.c b/arch/mips/mm/tlb-r8k.c
new file mode 100644
index 0000000..1bfb091
--- /dev/null
+++ b/arch/mips/mm/tlb-r8k.c
@@ -0,0 +1,250 @@
+/*
+ * 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) 1996 David S. Miller (dm@engr.sgi.com)
+ * Copyright (C) 1997, 1998, 1999, 2000 Ralf Baechle ralf@gnu.org
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2002 MIPS Technologies, Inc. All rights reserved.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+
+#include <asm/cpu.h>
+#include <asm/bootinfo.h>
+#include <asm/mmu_context.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+
+extern void build_tlb_refill_handler(void);
+
+#define TFP_TLB_SIZE 384
+#define TFP_TLB_SET_SHIFT 7
+
+/* CP0 hazard avoidance. */
+#define BARRIER __asm__ __volatile__(".set noreorder\n\t" \
+ "nop; nop; nop; nop; nop; nop;\n\t" \
+ ".set reorder\n\t")
+
+void local_flush_tlb_all(void)
+{
+ unsigned long flags;
+ unsigned long old_ctx;
+ int entry;
+
+ local_irq_save(flags);
+ /* Save old context and create impossible VPN2 value */
+ old_ctx = read_c0_entryhi();
+ write_c0_entrylo(0);
+
+ for (entry = 0; entry < TFP_TLB_SIZE; entry++) {
+ write_c0_tlbset(entry >> TFP_TLB_SET_SHIFT);
+ write_c0_vaddr(entry << PAGE_SHIFT);
+ write_c0_entryhi(CKSEG0 + (entry << (PAGE_SHIFT + 1)));
+ mtc0_tlbw_hazard();
+ tlb_write();
+ }
+ tlbw_use_hazard();
+ write_c0_entryhi(old_ctx);
+ local_irq_restore(flags);
+}
+
+void local_flush_tlb_mm(struct mm_struct *mm)
+{
+ int cpu = smp_processor_id();
+
+ if (cpu_context(cpu, mm) != 0)
+ drop_mmu_context(mm,cpu);
+}
+
+void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
+ unsigned long end)
+{
+ struct mm_struct *mm = vma->vm_mm;
+ int cpu = smp_processor_id();
+ unsigned long flags;
+ int oldpid, newpid, size;
+
+ if (!cpu_context(cpu, mm))
+ return;
+
+ size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
+ size = (size + 1) >> 1;
+
+ local_irq_save(flags);
+
+ if (size > TFP_TLB_SIZE / 2) {
+ drop_mmu_context(mm, cpu);
+ goto out_restore;
+ }
+
+ oldpid = read_c0_entryhi();
+ newpid = cpu_asid(cpu, mm);
+
+ write_c0_entrylo(0);
+
+ start &= PAGE_MASK;
+ end += (PAGE_SIZE - 1);
+ end &= PAGE_MASK;
+ while (start < end) {
+ signed long idx;
+
+ write_c0_vaddr(start);
+ write_c0_entryhi(start);
+ start += PAGE_SIZE;
+ tlb_probe();
+ idx = read_c0_tlbset();
+ if (idx < 0)
+ continue;
+
+ write_c0_entryhi(CKSEG0 + (idx << (PAGE_SHIFT + 1)));
+ tlb_write();
+ }
+ write_c0_entryhi(oldpid);
+
+out_restore:
+ local_irq_restore(flags);
+}
+
+/* Usable for KV1 addresses only! */
+void local_flush_tlb_kernel_range(unsigned long start, unsigned long end)
+{
+ unsigned long flags;
+ int size;
+
+ size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
+ size = (size + 1) >> 1;
+
+ if (size > TFP_TLB_SIZE / 2) {
+ local_flush_tlb_all();
+ return;
+ }
+
+ local_irq_save(flags);
+
+ write_c0_entrylo(0);
+
+ start &= PAGE_MASK;
+ end += (PAGE_SIZE - 1);
+ end &= PAGE_MASK;
+ while (start < end) {
+ signed long idx;
+
+ write_c0_vaddr(start);
+ write_c0_entryhi(start);
+ start += PAGE_SIZE;
+ tlb_probe();
+ idx = read_c0_tlbset();
+ if (idx < 0)
+ continue;
+
+ write_c0_entryhi(CKSEG0 + (idx << (PAGE_SHIFT + 1)));
+ tlb_write();
+ }
+
+ local_irq_restore(flags);
+}
+
+void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
+{
+ int cpu = smp_processor_id();
+ unsigned long flags;
+ int oldpid, newpid;
+ signed long idx;
+
+ if (!cpu_context(cpu, vma->vm_mm))
+ return;
+
+ newpid = cpu_asid(cpu, vma->vm_mm);
+ page &= PAGE_MASK;
+ local_irq_save(flags);
+ oldpid = read_c0_entryhi();
+ write_c0_vaddr(page);
+ write_c0_entryhi(newpid);
+ tlb_probe();
+ idx = read_c0_tlbset();
+ if (idx < 0)
+ goto finish;
+
+ write_c0_entrylo(0);
+ write_c0_entryhi(CKSEG0 + (idx << (PAGE_SHIFT + 1)));
+ tlb_write();
+
+finish:
+ write_c0_entryhi(oldpid);
+ local_irq_restore(flags);
+}
+
+/*
+ * We will need multiple versions of update_mmu_cache(), one that just
+ * updates the TLB with the new pte(s), and another which also checks
+ * for the R4k "end of page" hardware bug and does the needy.
+ */
+void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte)
+{
+ unsigned long flags;
+ pgd_t *pgdp;
+ pmd_t *pmdp;
+ pte_t *ptep;
+ int pid;
+
+ /*
+ * Handle debugger faulting in for debugee.
+ */
+ if (current->active_mm != vma->vm_mm)
+ return;
+
+ pid = read_c0_entryhi() & ASID_MASK;
+
+ local_irq_save(flags);
+ address &= PAGE_MASK;
+ write_c0_vaddr(address);
+ write_c0_entryhi(pid);
+ pgdp = pgd_offset(vma->vm_mm, address);
+ pmdp = pmd_offset(pgdp, address);
+ ptep = pte_offset_map(pmdp, address);
+ tlb_probe();
+
+ write_c0_entrylo(pte_val(*ptep++) >> 6);
+ tlb_write();
+
+ write_c0_entryhi(pid);
+ local_irq_restore(flags);
+}
+
+static void __init probe_tlb(unsigned long config)
+{
+ struct cpuinfo_mips *c = ¤t_cpu_data;
+
+ c->tlbsize = 3 * 128; /* 3 sets each 128 entries */
+}
+
+void __init tlb_init(void)
+{
+ unsigned int config = read_c0_config();
+ unsigned long status;
+
+ probe_tlb(config);
+
+ status = read_c0_status();
+ status &= ~(ST0_UPS | ST0_KPS);
+#ifdef CONFIG_PAGE_SIZE_4KB
+ status |= (TFP_PAGESIZE_4K << 32) | (TFP_PAGESIZE_4K << 36);
+#elif defined(CONFIG_PAGE_SIZE_8KB)
+ status |= (TFP_PAGESIZE_8K << 32) | (TFP_PAGESIZE_8K << 36);
+#elif defined(CONFIG_PAGE_SIZE_16KB)
+ status |= (TFP_PAGESIZE_16K << 32) | (TFP_PAGESIZE_16K << 36);
+#elif defined(CONFIG_PAGE_SIZE_64KB)
+ status |= (TFP_PAGESIZE_64K << 32) | (TFP_PAGESIZE_64K << 36);
+#endif
+ write_c0_status(status);
+
+ write_c0_wired(0);
+
+ local_flush_tlb_all();
+
+ build_tlb_refill_handler();
+}
diff --git a/arch/mips/mm/tlb-sb1.c b/arch/mips/mm/tlb-sb1.c
new file mode 100644
index 0000000..6256caf
--- /dev/null
+++ b/arch/mips/mm/tlb-sb1.c
@@ -0,0 +1,376 @@
+/*
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ * Copyright (C) 1997, 2001 Ralf Baechle (ralf@gnu.org)
+ * Copyright (C) 2000, 2001, 2002, 2003 Broadcom Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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 <linux/init.h>
+#include <asm/mmu_context.h>
+#include <asm/bootinfo.h>
+#include <asm/cpu.h>
+
+extern void build_tlb_refill_handler(void);
+
+#define UNIQUE_ENTRYHI(idx) (CKSEG0 + ((idx) << (PAGE_SHIFT + 1)))
+
+/* Dump the current entry* and pagemask registers */
+static inline void dump_cur_tlb_regs(void)
+{
+ unsigned int entryhihi, entryhilo, entrylo0hi, entrylo0lo, entrylo1hi;
+ unsigned int entrylo1lo, pagemask;
+
+ __asm__ __volatile__ (
+ ".set push \n"
+ ".set noreorder \n"
+ ".set mips64 \n"
+ ".set noat \n"
+ " tlbr \n"
+ " dmfc0 $1, $10 \n"
+ " dsrl32 %0, $1, 0 \n"
+ " sll %1, $1, 0 \n"
+ " dmfc0 $1, $2 \n"
+ " dsrl32 %2, $1, 0 \n"
+ " sll %3, $1, 0 \n"
+ " dmfc0 $1, $3 \n"
+ " dsrl32 %4, $1, 0 \n"
+ " sll %5, $1, 0 \n"
+ " mfc0 %6, $5 \n"
+ ".set pop \n"
+ : "=r" (entryhihi), "=r" (entryhilo),
+ "=r" (entrylo0hi), "=r" (entrylo0lo),
+ "=r" (entrylo1hi), "=r" (entrylo1lo),
+ "=r" (pagemask));
+
+ printk("%08X%08X %08X%08X %08X%08X %08X",
+ entryhihi, entryhilo,
+ entrylo0hi, entrylo0lo,
+ entrylo1hi, entrylo1lo,
+ pagemask);
+}
+
+void sb1_dump_tlb(void)
+{
+ unsigned long old_ctx;
+ unsigned long flags;
+ int entry;
+ local_irq_save(flags);
+ old_ctx = read_c0_entryhi();
+ printk("Current TLB registers state:\n"
+ " EntryHi EntryLo0 EntryLo1 PageMask Index\n"
+ "--------------------------------------------------------------------\n");
+ dump_cur_tlb_regs();
+ printk(" %08X\n", read_c0_index());
+ printk("\n\nFull TLB Dump:\n"
+ "Idx EntryHi EntryLo0 EntryLo1 PageMask\n"
+ "--------------------------------------------------------------\n");
+ for (entry = 0; entry < current_cpu_data.tlbsize; entry++) {
+ write_c0_index(entry);
+ printk("\n%02i ", entry);
+ dump_cur_tlb_regs();
+ }
+ printk("\n");
+ write_c0_entryhi(old_ctx);
+ local_irq_restore(flags);
+}
+
+void local_flush_tlb_all(void)
+{
+ unsigned long flags;
+ unsigned long old_ctx;
+ int entry;
+
+ local_irq_save(flags);
+ /* Save old context and create impossible VPN2 value */
+ old_ctx = read_c0_entryhi() & ASID_MASK;
+ write_c0_entrylo0(0);
+ write_c0_entrylo1(0);
+
+ entry = read_c0_wired();
+ while (entry < current_cpu_data.tlbsize) {
+ write_c0_entryhi(UNIQUE_ENTRYHI(entry));
+ write_c0_index(entry);
+ tlb_write_indexed();
+ entry++;
+ }
+ write_c0_entryhi(old_ctx);
+ local_irq_restore(flags);
+}
+
+
+/*
+ * Use a bogus region of memory (starting at 0) to sanitize the TLB's.
+ * Use increments of the maximum page size (16MB), and check for duplicate
+ * entries before doing a given write. Then, when we're safe from collisions
+ * with the firmware, go back and give all the entries invalid addresses with
+ * the normal flush routine. Wired entries will be killed as well!
+ */
+static void __init sb1_sanitize_tlb(void)
+{
+ int entry;
+ long addr = 0;
+
+ long inc = 1<<24; /* 16MB */
+ /* Save old context and create impossible VPN2 value */
+ write_c0_entrylo0(0);
+ write_c0_entrylo1(0);
+ for (entry = 0; entry < current_cpu_data.tlbsize; entry++) {
+ do {
+ addr += inc;
+ write_c0_entryhi(addr);
+ tlb_probe();
+ } while ((int)(read_c0_index()) >= 0);
+ write_c0_index(entry);
+ tlb_write_indexed();
+ }
+ /* Now that we know we're safe from collisions, we can safely flush
+ the TLB with the "normal" routine. */
+ local_flush_tlb_all();
+}
+
+void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
+ unsigned long end)
+{
+ struct mm_struct *mm = vma->vm_mm;
+ unsigned long flags;
+ int cpu;
+
+ local_irq_save(flags);
+ cpu = smp_processor_id();
+ if (cpu_context(cpu, mm) != 0) {
+ int size;
+ size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
+ size = (size + 1) >> 1;
+ if (size <= (current_cpu_data.tlbsize/2)) {
+ int oldpid = read_c0_entryhi() & ASID_MASK;
+ int newpid = cpu_asid(cpu, mm);
+
+ start &= (PAGE_MASK << 1);
+ end += ((PAGE_SIZE << 1) - 1);
+ end &= (PAGE_MASK << 1);
+ while (start < end) {
+ int idx;
+
+ write_c0_entryhi(start | newpid);
+ start += (PAGE_SIZE << 1);
+ tlb_probe();
+ idx = read_c0_index();
+ write_c0_entrylo0(0);
+ write_c0_entrylo1(0);
+ write_c0_entryhi(UNIQUE_ENTRYHI(idx));
+ if (idx < 0)
+ continue;
+ tlb_write_indexed();
+ }
+ write_c0_entryhi(oldpid);
+ } else {
+ drop_mmu_context(mm, cpu);
+ }
+ }
+ local_irq_restore(flags);
+}
+
+void local_flush_tlb_kernel_range(unsigned long start, unsigned long end)
+{
+ unsigned long flags;
+ int size;
+
+ size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
+ size = (size + 1) >> 1;
+
+ local_irq_save(flags);
+ if (size <= (current_cpu_data.tlbsize/2)) {
+ int pid = read_c0_entryhi();
+
+ start &= (PAGE_MASK << 1);
+ end += ((PAGE_SIZE << 1) - 1);
+ end &= (PAGE_MASK << 1);
+
+ while (start < end) {
+ int idx;
+
+ write_c0_entryhi(start);
+ start += (PAGE_SIZE << 1);
+ tlb_probe();
+ idx = read_c0_index();
+ write_c0_entrylo0(0);
+ write_c0_entrylo1(0);
+ write_c0_entryhi(UNIQUE_ENTRYHI(idx));
+ if (idx < 0)
+ continue;
+ tlb_write_indexed();
+ }
+ write_c0_entryhi(pid);
+ } else {
+ local_flush_tlb_all();
+ }
+ local_irq_restore(flags);
+}
+
+void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
+{
+ unsigned long flags;
+ int cpu = smp_processor_id();
+
+ local_irq_save(flags);
+ if (cpu_context(cpu, vma->vm_mm) != 0) {
+ int oldpid, newpid, idx;
+ newpid = cpu_asid(cpu, vma->vm_mm);
+ page &= (PAGE_MASK << 1);
+ oldpid = read_c0_entryhi() & ASID_MASK;
+ write_c0_entryhi(page | newpid);
+ tlb_probe();
+ idx = read_c0_index();
+ write_c0_entrylo0(0);
+ write_c0_entrylo1(0);
+ if (idx < 0)
+ goto finish;
+ /* Make sure all entries differ. */
+ write_c0_entryhi(UNIQUE_ENTRYHI(idx));
+ tlb_write_indexed();
+ finish:
+ write_c0_entryhi(oldpid);
+ }
+ local_irq_restore(flags);
+}
+
+/*
+ * Remove one kernel space TLB entry. This entry is assumed to be marked
+ * global so we don't do the ASID thing.
+ */
+void local_flush_tlb_one(unsigned long page)
+{
+ unsigned long flags;
+ int oldpid, idx;
+
+ page &= (PAGE_MASK << 1);
+ oldpid = read_c0_entryhi() & ASID_MASK;
+
+ local_irq_save(flags);
+ write_c0_entryhi(page);
+ tlb_probe();
+ idx = read_c0_index();
+ if (idx >= 0) {
+ /* Make sure all entries differ. */
+ write_c0_entryhi(UNIQUE_ENTRYHI(idx));
+ write_c0_entrylo0(0);
+ write_c0_entrylo1(0);
+ tlb_write_indexed();
+ }
+
+ write_c0_entryhi(oldpid);
+ local_irq_restore(flags);
+}
+
+/* All entries common to a mm share an asid. To effectively flush
+ these entries, we just bump the asid. */
+void local_flush_tlb_mm(struct mm_struct *mm)
+{
+ int cpu;
+
+ preempt_disable();
+
+ cpu = smp_processor_id();
+
+ if (cpu_context(cpu, mm) != 0) {
+ drop_mmu_context(mm, cpu);
+ }
+
+ preempt_enable();
+}
+
+/* Stolen from mips32 routines */
+
+void __update_tlb(struct vm_area_struct *vma, unsigned long address, pte_t pte)
+{
+ unsigned long flags;
+ pgd_t *pgdp;
+ pmd_t *pmdp;
+ pte_t *ptep;
+ int idx, pid;
+
+ /*
+ * Handle debugger faulting in for debugee.
+ */
+ if (current->active_mm != vma->vm_mm)
+ return;
+
+ local_irq_save(flags);
+
+ pid = read_c0_entryhi() & ASID_MASK;
+ address &= (PAGE_MASK << 1);
+ write_c0_entryhi(address | (pid));
+ pgdp = pgd_offset(vma->vm_mm, address);
+ tlb_probe();
+ pmdp = pmd_offset(pgdp, address);
+ idx = read_c0_index();
+ ptep = pte_offset_map(pmdp, address);
+ write_c0_entrylo0(pte_val(*ptep++) >> 6);
+ write_c0_entrylo1(pte_val(*ptep) >> 6);
+ if (idx < 0) {
+ tlb_write_random();
+ } else {
+ tlb_write_indexed();
+ }
+ local_irq_restore(flags);
+}
+
+void __init add_wired_entry(unsigned long entrylo0, unsigned long entrylo1,
+ unsigned long entryhi, unsigned long pagemask)
+{
+ unsigned long flags;
+ unsigned long wired;
+ unsigned long old_pagemask;
+ unsigned long old_ctx;
+
+ local_irq_save(flags);
+ old_ctx = read_c0_entryhi() & 0xff;
+ old_pagemask = read_c0_pagemask();
+ wired = read_c0_wired();
+ write_c0_wired(wired + 1);
+ write_c0_index(wired);
+
+ write_c0_pagemask(pagemask);
+ write_c0_entryhi(entryhi);
+ write_c0_entrylo0(entrylo0);
+ write_c0_entrylo1(entrylo1);
+ tlb_write_indexed();
+
+ write_c0_entryhi(old_ctx);
+ write_c0_pagemask(old_pagemask);
+
+ local_flush_tlb_all();
+ local_irq_restore(flags);
+}
+
+/*
+ * This is called from loadmmu.c. We have to set up all the
+ * memory management function pointers, as well as initialize
+ * the caches and tlbs
+ */
+void tlb_init(void)
+{
+ write_c0_pagemask(PM_DEFAULT_MASK);
+ write_c0_wired(0);
+
+ /*
+ * We don't know what state the firmware left the TLB's in, so this is
+ * the ultra-conservative way to flush the TLB's and avoid machine
+ * check exceptions due to duplicate TLB entries
+ */
+ sb1_sanitize_tlb();
+
+ build_tlb_refill_handler();
+}
diff --git a/arch/mips/mm/tlbex-fault.S b/arch/mips/mm/tlbex-fault.S
new file mode 100644
index 0000000..9e7f417
--- /dev/null
+++ b/arch/mips/mm/tlbex-fault.S
@@ -0,0 +1,28 @@
+/*
+ * 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) 1999 Ralf Baechle
+ * Copyright (C) 1999 Silicon Graphics, Inc.
+ */
+#include <asm/mipsregs.h>
+#include <asm/page.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+
+ .macro tlb_do_page_fault, write
+ NESTED(tlb_do_page_fault_\write, PT_SIZE, sp)
+ SAVE_ALL
+ MFC0 a2, CP0_BADVADDR
+ KMODE
+ move a0, sp
+ REG_S a2, PT_BVADDR(sp)
+ li a1, \write
+ jal do_page_fault
+ j ret_from_exception
+ END(tlb_do_page_fault_\write)
+ .endm
+
+ tlb_do_page_fault 0
+ tlb_do_page_fault 1
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
new file mode 100644
index 0000000..87e229f
--- /dev/null
+++ b/arch/mips/mm/tlbex.c
@@ -0,0 +1,1815 @@
+/*
+ * 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.
+ *
+ * Synthesize TLB refill handlers at runtime.
+ *
+ * Copyright (C) 2004,2005 by Thiemo Seufer
+ */
+
+#include <stdarg.h>
+
+#include <linux/config.h>
+#include <linux/mm.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/init.h>
+
+#include <asm/pgtable.h>
+#include <asm/cacheflush.h>
+#include <asm/mmu_context.h>
+#include <asm/inst.h>
+#include <asm/elf.h>
+#include <asm/smp.h>
+#include <asm/war.h>
+
+/* #define DEBUG_TLB */
+
+static __init int __attribute__((unused)) r45k_bvahwbug(void)
+{
+ /* XXX: We should probe for the presence of this bug, but we don't. */
+ return 0;
+}
+
+static __init int __attribute__((unused)) r4k_250MHZhwbug(void)
+{
+ /* XXX: We should probe for the presence of this bug, but we don't. */
+ return 0;
+}
+
+static __init int __attribute__((unused)) bcm1250_m3_war(void)
+{
+ return BCM1250_M3_WAR;
+}
+
+static __init int __attribute__((unused)) r10000_llsc_war(void)
+{
+ return R10000_LLSC_WAR;
+}
+
+/*
+ * A little micro-assembler, intended for TLB refill handler
+ * synthesizing. It is intentionally kept simple, does only support
+ * a subset of instructions, and does not try to hide pipeline effects
+ * like branch delay slots.
+ */
+
+enum fields
+{
+ RS = 0x001,
+ RT = 0x002,
+ RD = 0x004,
+ RE = 0x008,
+ SIMM = 0x010,
+ UIMM = 0x020,
+ BIMM = 0x040,
+ JIMM = 0x080,
+ FUNC = 0x100,
+};
+
+#define OP_MASK 0x2f
+#define OP_SH 26
+#define RS_MASK 0x1f
+#define RS_SH 21
+#define RT_MASK 0x1f
+#define RT_SH 16
+#define RD_MASK 0x1f
+#define RD_SH 11
+#define RE_MASK 0x1f
+#define RE_SH 6
+#define IMM_MASK 0xffff
+#define IMM_SH 0
+#define JIMM_MASK 0x3ffffff
+#define JIMM_SH 0
+#define FUNC_MASK 0x2f
+#define FUNC_SH 0
+
+enum opcode {
+ insn_invalid,
+ insn_addu, insn_addiu, insn_and, insn_andi, insn_beq,
+ insn_beql, insn_bgez, insn_bgezl, insn_bltz, insn_bltzl,
+ insn_bne, insn_daddu, insn_daddiu, insn_dmfc0, insn_dmtc0,
+ insn_dsll, insn_dsll32, insn_dsra, insn_dsrl, insn_dsrl32,
+ insn_dsubu, insn_eret, insn_j, insn_jal, insn_jr, insn_ld,
+ insn_ll, insn_lld, insn_lui, insn_lw, insn_mfc0, insn_mtc0,
+ insn_ori, insn_rfe, insn_sc, insn_scd, insn_sd, insn_sll,
+ insn_sra, insn_srl, insn_subu, insn_sw, insn_tlbp, insn_tlbwi,
+ insn_tlbwr, insn_xor, insn_xori
+};
+
+struct insn {
+ enum opcode opcode;
+ u32 match;
+ enum fields fields;
+};
+
+/* This macro sets the non-variable bits of an instruction. */
+#define M(a, b, c, d, e, f) \
+ ((a) << OP_SH \
+ | (b) << RS_SH \
+ | (c) << RT_SH \
+ | (d) << RD_SH \
+ | (e) << RE_SH \
+ | (f) << FUNC_SH)
+
+static __initdata struct insn insn_table[] = {
+ { insn_addiu, M(addiu_op,0,0,0,0,0), RS | RT | SIMM },
+ { insn_addu, M(spec_op,0,0,0,0,addu_op), RS | RT | RD },
+ { insn_and, M(spec_op,0,0,0,0,and_op), RS | RT | RD },
+ { insn_andi, M(andi_op,0,0,0,0,0), RS | RT | UIMM },
+ { insn_beq, M(beq_op,0,0,0,0,0), RS | RT | BIMM },
+ { insn_beql, M(beql_op,0,0,0,0,0), RS | RT | BIMM },
+ { insn_bgez, M(bcond_op,0,bgez_op,0,0,0), RS | BIMM },
+ { insn_bgezl, M(bcond_op,0,bgezl_op,0,0,0), RS | BIMM },
+ { insn_bltz, M(bcond_op,0,bltz_op,0,0,0), RS | BIMM },
+ { insn_bltzl, M(bcond_op,0,bltzl_op,0,0,0), RS | BIMM },
+ { insn_bne, M(bne_op,0,0,0,0,0), RS | RT | BIMM },
+ { insn_daddiu, M(daddiu_op,0,0,0,0,0), RS | RT | SIMM },
+ { insn_daddu, M(spec_op,0,0,0,0,daddu_op), RS | RT | RD },
+ { insn_dmfc0, M(cop0_op,dmfc_op,0,0,0,0), RT | RD },
+ { insn_dmtc0, M(cop0_op,dmtc_op,0,0,0,0), RT | RD },
+ { insn_dsll, M(spec_op,0,0,0,0,dsll_op), RT | RD | RE },
+ { insn_dsll32, M(spec_op,0,0,0,0,dsll32_op), RT | RD | RE },
+ { insn_dsra, M(spec_op,0,0,0,0,dsra_op), RT | RD | RE },
+ { insn_dsrl, M(spec_op,0,0,0,0,dsrl_op), RT | RD | RE },
+ { insn_dsrl32, M(spec_op,0,0,0,0,dsrl32_op), RT | RD | RE },
+ { insn_dsubu, M(spec_op,0,0,0,0,dsubu_op), RS | RT | RD },
+ { insn_eret, M(cop0_op,cop_op,0,0,0,eret_op), 0 },
+ { insn_j, M(j_op,0,0,0,0,0), JIMM },
+ { insn_jal, M(jal_op,0,0,0,0,0), JIMM },
+ { insn_jr, M(spec_op,0,0,0,0,jr_op), RS },
+ { insn_ld, M(ld_op,0,0,0,0,0), RS | RT | SIMM },
+ { insn_ll, M(ll_op,0,0,0,0,0), RS | RT | SIMM },
+ { insn_lld, M(lld_op,0,0,0,0,0), RS | RT | SIMM },
+ { insn_lui, M(lui_op,0,0,0,0,0), RT | SIMM },
+ { insn_lw, M(lw_op,0,0,0,0,0), RS | RT | SIMM },
+ { insn_mfc0, M(cop0_op,mfc_op,0,0,0,0), RT | RD },
+ { insn_mtc0, M(cop0_op,mtc_op,0,0,0,0), RT | RD },
+ { insn_ori, M(ori_op,0,0,0,0,0), RS | RT | UIMM },
+ { insn_rfe, M(cop0_op,cop_op,0,0,0,rfe_op), 0 },
+ { insn_sc, M(sc_op,0,0,0,0,0), RS | RT | SIMM },
+ { insn_scd, M(scd_op,0,0,0,0,0), RS | RT | SIMM },
+ { insn_sd, M(sd_op,0,0,0,0,0), RS | RT | SIMM },
+ { insn_sll, M(spec_op,0,0,0,0,sll_op), RT | RD | RE },
+ { insn_sra, M(spec_op,0,0,0,0,sra_op), RT | RD | RE },
+ { insn_srl, M(spec_op,0,0,0,0,srl_op), RT | RD | RE },
+ { insn_subu, M(spec_op,0,0,0,0,subu_op), RS | RT | RD },
+ { insn_sw, M(sw_op,0,0,0,0,0), RS | RT | SIMM },
+ { insn_tlbp, M(cop0_op,cop_op,0,0,0,tlbp_op), 0 },
+ { insn_tlbwi, M(cop0_op,cop_op,0,0,0,tlbwi_op), 0 },
+ { insn_tlbwr, M(cop0_op,cop_op,0,0,0,tlbwr_op), 0 },
+ { insn_xor, M(spec_op,0,0,0,0,xor_op), RS | RT | RD },
+ { insn_xori, M(xori_op,0,0,0,0,0), RS | RT | UIMM },
+ { insn_invalid, 0, 0 }
+};
+
+#undef M
+
+static __init u32 build_rs(u32 arg)
+{
+ if (arg & ~RS_MASK)
+ printk(KERN_WARNING "TLB synthesizer field overflow\n");
+
+ return (arg & RS_MASK) << RS_SH;
+}
+
+static __init u32 build_rt(u32 arg)
+{
+ if (arg & ~RT_MASK)
+ printk(KERN_WARNING "TLB synthesizer field overflow\n");
+
+ return (arg & RT_MASK) << RT_SH;
+}
+
+static __init u32 build_rd(u32 arg)
+{
+ if (arg & ~RD_MASK)
+ printk(KERN_WARNING "TLB synthesizer field overflow\n");
+
+ return (arg & RD_MASK) << RD_SH;
+}
+
+static __init u32 build_re(u32 arg)
+{
+ if (arg & ~RE_MASK)
+ printk(KERN_WARNING "TLB synthesizer field overflow\n");
+
+ return (arg & RE_MASK) << RE_SH;
+}
+
+static __init u32 build_simm(s32 arg)
+{
+ if (arg > 0x7fff || arg < -0x8000)
+ printk(KERN_WARNING "TLB synthesizer field overflow\n");
+
+ return arg & 0xffff;
+}
+
+static __init u32 build_uimm(u32 arg)
+{
+ if (arg & ~IMM_MASK)
+ printk(KERN_WARNING "TLB synthesizer field overflow\n");
+
+ return arg & IMM_MASK;
+}
+
+static __init u32 build_bimm(s32 arg)
+{
+ if (arg > 0x1ffff || arg < -0x20000)
+ printk(KERN_WARNING "TLB synthesizer field overflow\n");
+
+ if (arg & 0x3)
+ printk(KERN_WARNING "Invalid TLB synthesizer branch target\n");
+
+ return ((arg < 0) ? (1 << 15) : 0) | ((arg >> 2) & 0x7fff);
+}
+
+static __init u32 build_jimm(u32 arg)
+{
+ if (arg & ~((JIMM_MASK) << 2))
+ printk(KERN_WARNING "TLB synthesizer field overflow\n");
+
+ return (arg >> 2) & JIMM_MASK;
+}
+
+static __init u32 build_func(u32 arg)
+{
+ if (arg & ~FUNC_MASK)
+ printk(KERN_WARNING "TLB synthesizer field overflow\n");
+
+ return arg & FUNC_MASK;
+}
+
+/*
+ * The order of opcode arguments is implicitly left to right,
+ * starting with RS and ending with FUNC or IMM.
+ */
+static void __init build_insn(u32 **buf, enum opcode opc, ...)
+{
+ struct insn *ip = NULL;
+ unsigned int i;
+ va_list ap;
+ u32 op;
+
+ for (i = 0; insn_table[i].opcode != insn_invalid; i++)
+ if (insn_table[i].opcode == opc) {
+ ip = &insn_table[i];
+ break;
+ }
+
+ if (!ip)
+ panic("Unsupported TLB synthesizer instruction %d", opc);
+
+ op = ip->match;
+ va_start(ap, opc);
+ if (ip->fields & RS) op |= build_rs(va_arg(ap, u32));
+ if (ip->fields & RT) op |= build_rt(va_arg(ap, u32));
+ if (ip->fields & RD) op |= build_rd(va_arg(ap, u32));
+ if (ip->fields & RE) op |= build_re(va_arg(ap, u32));
+ if (ip->fields & SIMM) op |= build_simm(va_arg(ap, s32));
+ if (ip->fields & UIMM) op |= build_uimm(va_arg(ap, u32));
+ if (ip->fields & BIMM) op |= build_bimm(va_arg(ap, s32));
+ if (ip->fields & JIMM) op |= build_jimm(va_arg(ap, u32));
+ if (ip->fields & FUNC) op |= build_func(va_arg(ap, u32));
+ va_end(ap);
+
+ **buf = op;
+ (*buf)++;
+}
+
+#define I_u1u2u3(op) \
+ static inline void i##op(u32 **buf, unsigned int a, \
+ unsigned int b, unsigned int c) \
+ { \
+ build_insn(buf, insn##op, a, b, c); \
+ }
+
+#define I_u2u1u3(op) \
+ static inline void i##op(u32 **buf, unsigned int a, \
+ unsigned int b, unsigned int c) \
+ { \
+ build_insn(buf, insn##op, b, a, c); \
+ }
+
+#define I_u3u1u2(op) \
+ static inline void i##op(u32 **buf, unsigned int a, \
+ unsigned int b, unsigned int c) \
+ { \
+ build_insn(buf, insn##op, b, c, a); \
+ }
+
+#define I_u1u2s3(op) \
+ static inline void i##op(u32 **buf, unsigned int a, \
+ unsigned int b, signed int c) \
+ { \
+ build_insn(buf, insn##op, a, b, c); \
+ }
+
+#define I_u2s3u1(op) \
+ static inline void i##op(u32 **buf, unsigned int a, \
+ signed int b, unsigned int c) \
+ { \
+ build_insn(buf, insn##op, c, a, b); \
+ }
+
+#define I_u2u1s3(op) \
+ static inline void i##op(u32 **buf, unsigned int a, \
+ unsigned int b, signed int c) \
+ { \
+ build_insn(buf, insn##op, b, a, c); \
+ }
+
+#define I_u1u2(op) \
+ static inline void i##op(u32 **buf, unsigned int a, \
+ unsigned int b) \
+ { \
+ build_insn(buf, insn##op, a, b); \
+ }
+
+#define I_u1s2(op) \
+ static inline void i##op(u32 **buf, unsigned int a, \
+ signed int b) \
+ { \
+ build_insn(buf, insn##op, a, b); \
+ }
+
+#define I_u1(op) \
+ static inline void i##op(u32 **buf, unsigned int a) \
+ { \
+ build_insn(buf, insn##op, a); \
+ }
+
+#define I_0(op) \
+ static inline void i##op(u32 **buf) \
+ { \
+ build_insn(buf, insn##op); \
+ }
+
+I_u2u1s3(_addiu);
+I_u3u1u2(_addu);
+I_u2u1u3(_andi);
+I_u3u1u2(_and);
+I_u1u2s3(_beq);
+I_u1u2s3(_beql);
+I_u1s2(_bgez);
+I_u1s2(_bgezl);
+I_u1s2(_bltz);
+I_u1s2(_bltzl);
+I_u1u2s3(_bne);
+I_u1u2(_dmfc0);
+I_u1u2(_dmtc0);
+I_u2u1s3(_daddiu);
+I_u3u1u2(_daddu);
+I_u2u1u3(_dsll);
+I_u2u1u3(_dsll32);
+I_u2u1u3(_dsra);
+I_u2u1u3(_dsrl);
+I_u2u1u3(_dsrl32);
+I_u3u1u2(_dsubu);
+I_0(_eret);
+I_u1(_j);
+I_u1(_jal);
+I_u1(_jr);
+I_u2s3u1(_ld);
+I_u2s3u1(_ll);
+I_u2s3u1(_lld);
+I_u1s2(_lui);
+I_u2s3u1(_lw);
+I_u1u2(_mfc0);
+I_u1u2(_mtc0);
+I_u2u1u3(_ori);
+I_0(_rfe);
+I_u2s3u1(_sc);
+I_u2s3u1(_scd);
+I_u2s3u1(_sd);
+I_u2u1u3(_sll);
+I_u2u1u3(_sra);
+I_u2u1u3(_srl);
+I_u3u1u2(_subu);
+I_u2s3u1(_sw);
+I_0(_tlbp);
+I_0(_tlbwi);
+I_0(_tlbwr);
+I_u3u1u2(_xor)
+I_u2u1u3(_xori);
+
+/*
+ * handling labels
+ */
+
+enum label_id {
+ label_invalid,
+ label_second_part,
+ label_leave,
+ label_vmalloc,
+ label_vmalloc_done,
+ label_tlbw_hazard,
+ label_split,
+ label_nopage_tlbl,
+ label_nopage_tlbs,
+ label_nopage_tlbm,
+ label_smp_pgtable_change,
+ label_r3000_write_probe_fail,
+ label_r3000_write_probe_ok
+};
+
+struct label {
+ u32 *addr;
+ enum label_id lab;
+};
+
+static __init void build_label(struct label **lab, u32 *addr,
+ enum label_id l)
+{
+ (*lab)->addr = addr;
+ (*lab)->lab = l;
+ (*lab)++;
+}
+
+#define L_LA(lb) \
+ static inline void l##lb(struct label **lab, u32 *addr) \
+ { \
+ build_label(lab, addr, label##lb); \
+ }
+
+L_LA(_second_part)
+L_LA(_leave)
+L_LA(_vmalloc)
+L_LA(_vmalloc_done)
+L_LA(_tlbw_hazard)
+L_LA(_split)
+L_LA(_nopage_tlbl)
+L_LA(_nopage_tlbs)
+L_LA(_nopage_tlbm)
+L_LA(_smp_pgtable_change)
+L_LA(_r3000_write_probe_fail)
+L_LA(_r3000_write_probe_ok)
+
+/* convenience macros for instructions */
+#ifdef CONFIG_MIPS64
+# define i_LW(buf, rs, rt, off) i_ld(buf, rs, rt, off)
+# define i_SW(buf, rs, rt, off) i_sd(buf, rs, rt, off)
+# define i_SLL(buf, rs, rt, sh) i_dsll(buf, rs, rt, sh)
+# define i_SRA(buf, rs, rt, sh) i_dsra(buf, rs, rt, sh)
+# define i_SRL(buf, rs, rt, sh) i_dsrl(buf, rs, rt, sh)
+# define i_MFC0(buf, rt, rd) i_dmfc0(buf, rt, rd)
+# define i_MTC0(buf, rt, rd) i_dmtc0(buf, rt, rd)
+# define i_ADDIU(buf, rs, rt, val) i_daddiu(buf, rs, rt, val)
+# define i_ADDU(buf, rs, rt, rd) i_daddu(buf, rs, rt, rd)
+# define i_SUBU(buf, rs, rt, rd) i_dsubu(buf, rs, rt, rd)
+# define i_LL(buf, rs, rt, off) i_lld(buf, rs, rt, off)
+# define i_SC(buf, rs, rt, off) i_scd(buf, rs, rt, off)
+#else
+# define i_LW(buf, rs, rt, off) i_lw(buf, rs, rt, off)
+# define i_SW(buf, rs, rt, off) i_sw(buf, rs, rt, off)
+# define i_SLL(buf, rs, rt, sh) i_sll(buf, rs, rt, sh)
+# define i_SRA(buf, rs, rt, sh) i_sra(buf, rs, rt, sh)
+# define i_SRL(buf, rs, rt, sh) i_srl(buf, rs, rt, sh)
+# define i_MFC0(buf, rt, rd) i_mfc0(buf, rt, rd)
+# define i_MTC0(buf, rt, rd) i_mtc0(buf, rt, rd)
+# define i_ADDIU(buf, rs, rt, val) i_addiu(buf, rs, rt, val)
+# define i_ADDU(buf, rs, rt, rd) i_addu(buf, rs, rt, rd)
+# define i_SUBU(buf, rs, rt, rd) i_subu(buf, rs, rt, rd)
+# define i_LL(buf, rs, rt, off) i_ll(buf, rs, rt, off)
+# define i_SC(buf, rs, rt, off) i_sc(buf, rs, rt, off)
+#endif
+
+#define i_b(buf, off) i_beq(buf, 0, 0, off)
+#define i_beqz(buf, rs, off) i_beq(buf, rs, 0, off)
+#define i_beqzl(buf, rs, off) i_beql(buf, rs, 0, off)
+#define i_bnez(buf, rs, off) i_bne(buf, rs, 0, off)
+#define i_bnezl(buf, rs, off) i_bnel(buf, rs, 0, off)
+#define i_move(buf, a, b) i_ADDU(buf, a, 0, b)
+#define i_nop(buf) i_sll(buf, 0, 0, 0)
+#define i_ssnop(buf) i_sll(buf, 0, 0, 1)
+#define i_ehb(buf) i_sll(buf, 0, 0, 3)
+
+#ifdef CONFIG_MIPS64
+static __init int __attribute__((unused)) in_compat_space_p(long addr)
+{
+ /* Is this address in 32bit compat space? */
+ return (((addr) & 0xffffffff00000000) == 0xffffffff00000000);
+}
+
+static __init int __attribute__((unused)) rel_highest(long val)
+{
+ return ((((val + 0x800080008000L) >> 48) & 0xffff) ^ 0x8000) - 0x8000;
+}
+
+static __init int __attribute__((unused)) rel_higher(long val)
+{
+ return ((((val + 0x80008000L) >> 32) & 0xffff) ^ 0x8000) - 0x8000;
+}
+#endif
+
+static __init int rel_hi(long val)
+{
+ return ((((val + 0x8000L) >> 16) & 0xffff) ^ 0x8000) - 0x8000;
+}
+
+static __init int rel_lo(long val)
+{
+ return ((val & 0xffff) ^ 0x8000) - 0x8000;
+}
+
+static __init void i_LA_mostly(u32 **buf, unsigned int rs, long addr)
+{
+#if CONFIG_MIPS64
+ if (!in_compat_space_p(addr)) {
+ i_lui(buf, rs, rel_highest(addr));
+ if (rel_higher(addr))
+ i_daddiu(buf, rs, rs, rel_higher(addr));
+ if (rel_hi(addr)) {
+ i_dsll(buf, rs, rs, 16);
+ i_daddiu(buf, rs, rs, rel_hi(addr));
+ i_dsll(buf, rs, rs, 16);
+ } else
+ i_dsll32(buf, rs, rs, 0);
+ } else
+#endif
+ i_lui(buf, rs, rel_hi(addr));
+}
+
+static __init void __attribute__((unused)) i_LA(u32 **buf, unsigned int rs,
+ long addr)
+{
+ i_LA_mostly(buf, rs, addr);
+ if (rel_lo(addr))
+ i_ADDIU(buf, rs, rs, rel_lo(addr));
+}
+
+/*
+ * handle relocations
+ */
+
+struct reloc {
+ u32 *addr;
+ unsigned int type;
+ enum label_id lab;
+};
+
+static __init void r_mips_pc16(struct reloc **rel, u32 *addr,
+ enum label_id l)
+{
+ (*rel)->addr = addr;
+ (*rel)->type = R_MIPS_PC16;
+ (*rel)->lab = l;
+ (*rel)++;
+}
+
+static inline void __resolve_relocs(struct reloc *rel, struct label *lab)
+{
+ long laddr = (long)lab->addr;
+ long raddr = (long)rel->addr;
+
+ switch (rel->type) {
+ case R_MIPS_PC16:
+ *rel->addr |= build_bimm(laddr - (raddr + 4));
+ break;
+
+ default:
+ panic("Unsupported TLB synthesizer relocation %d",
+ rel->type);
+ }
+}
+
+static __init void resolve_relocs(struct reloc *rel, struct label *lab)
+{
+ struct label *l;
+
+ for (; rel->lab != label_invalid; rel++)
+ for (l = lab; l->lab != label_invalid; l++)
+ if (rel->lab == l->lab)
+ __resolve_relocs(rel, l);
+}
+
+static __init void move_relocs(struct reloc *rel, u32 *first, u32 *end,
+ long off)
+{
+ for (; rel->lab != label_invalid; rel++)
+ if (rel->addr >= first && rel->addr < end)
+ rel->addr += off;
+}
+
+static __init void move_labels(struct label *lab, u32 *first, u32 *end,
+ long off)
+{
+ for (; lab->lab != label_invalid; lab++)
+ if (lab->addr >= first && lab->addr < end)
+ lab->addr += off;
+}
+
+static __init void copy_handler(struct reloc *rel, struct label *lab,
+ u32 *first, u32 *end, u32 *target)
+{
+ long off = (long)(target - first);
+
+ memcpy(target, first, (end - first) * sizeof(u32));
+
+ move_relocs(rel, first, end, off);
+ move_labels(lab, first, end, off);
+}
+
+static __init int __attribute__((unused)) insn_has_bdelay(struct reloc *rel,
+ u32 *addr)
+{
+ for (; rel->lab != label_invalid; rel++) {
+ if (rel->addr == addr
+ && (rel->type == R_MIPS_PC16
+ || rel->type == R_MIPS_26))
+ return 1;
+ }
+
+ return 0;
+}
+
+/* convenience functions for labeled branches */
+static void __attribute__((unused)) il_bltz(u32 **p, struct reloc **r,
+ unsigned int reg, enum label_id l)
+{
+ r_mips_pc16(r, *p, l);
+ i_bltz(p, reg, 0);
+}
+
+static void __attribute__((unused)) il_b(u32 **p, struct reloc **r,
+ enum label_id l)
+{
+ r_mips_pc16(r, *p, l);
+ i_b(p, 0);
+}
+
+static void il_beqz(u32 **p, struct reloc **r, unsigned int reg,
+ enum label_id l)
+{
+ r_mips_pc16(r, *p, l);
+ i_beqz(p, reg, 0);
+}
+
+static void __attribute__((unused))
+il_beqzl(u32 **p, struct reloc **r, unsigned int reg, enum label_id l)
+{
+ r_mips_pc16(r, *p, l);
+ i_beqzl(p, reg, 0);
+}
+
+static void il_bnez(u32 **p, struct reloc **r, unsigned int reg,
+ enum label_id l)
+{
+ r_mips_pc16(r, *p, l);
+ i_bnez(p, reg, 0);
+}
+
+static void il_bgezl(u32 **p, struct reloc **r, unsigned int reg,
+ enum label_id l)
+{
+ r_mips_pc16(r, *p, l);
+ i_bgezl(p, reg, 0);
+}
+
+/* The only general purpose registers allowed in TLB handlers. */
+#define K0 26
+#define K1 27
+
+/* Some CP0 registers */
+#define C0_INDEX 0
+#define C0_ENTRYLO0 2
+#define C0_ENTRYLO1 3
+#define C0_CONTEXT 4
+#define C0_BADVADDR 8
+#define C0_ENTRYHI 10
+#define C0_EPC 14
+#define C0_XCONTEXT 20
+
+#ifdef CONFIG_MIPS64
+# define GET_CONTEXT(buf, reg) i_MFC0(buf, reg, C0_XCONTEXT)
+#else
+# define GET_CONTEXT(buf, reg) i_MFC0(buf, reg, C0_CONTEXT)
+#endif
+
+/* The worst case length of the handler is around 18 instructions for
+ * R3000-style TLBs and up to 63 instructions for R4000-style TLBs.
+ * Maximum space available is 32 instructions for R3000 and 64
+ * instructions for R4000.
+ *
+ * We deliberately chose a buffer size of 128, so we won't scribble
+ * over anything important on overflow before we panic.
+ */
+static __initdata u32 tlb_handler[128];
+
+/* simply assume worst case size for labels and relocs */
+static __initdata struct label labels[128];
+static __initdata struct reloc relocs[128];
+
+/*
+ * The R3000 TLB handler is simple.
+ */
+static void __init build_r3000_tlb_refill_handler(void)
+{
+ long pgdc = (long)pgd_current;
+ u32 *p;
+
+ memset(tlb_handler, 0, sizeof(tlb_handler));
+ p = tlb_handler;
+
+ i_mfc0(&p, K0, C0_BADVADDR);
+ i_lui(&p, K1, rel_hi(pgdc)); /* cp0 delay */
+ i_lw(&p, K1, rel_lo(pgdc), K1);
+ i_srl(&p, K0, K0, 22); /* load delay */
+ i_sll(&p, K0, K0, 2);
+ i_addu(&p, K1, K1, K0);
+ i_mfc0(&p, K0, C0_CONTEXT);
+ i_lw(&p, K1, 0, K1); /* cp0 delay */
+ i_andi(&p, K0, K0, 0xffc); /* load delay */
+ i_addu(&p, K1, K1, K0);
+ i_lw(&p, K0, 0, K1);
+ i_nop(&p); /* load delay */
+ i_mtc0(&p, K0, C0_ENTRYLO0);
+ i_mfc0(&p, K1, C0_EPC); /* cp0 delay */
+ i_tlbwr(&p); /* cp0 delay */
+ i_jr(&p, K1);
+ i_rfe(&p); /* branch delay */
+
+ if (p > tlb_handler + 32)
+ panic("TLB refill handler space exceeded");
+
+ printk("Synthesized TLB handler (%u instructions).\n",
+ (unsigned int)(p - tlb_handler));
+#ifdef DEBUG_TLB
+ {
+ int i;
+
+ for (i = 0; i < (p - tlb_handler); i++)
+ printk("%08x\n", tlb_handler[i]);
+ }
+#endif
+
+ memcpy((void *)CAC_BASE, tlb_handler, 0x80);
+ flush_icache_range(CAC_BASE, CAC_BASE + 0x80);
+}
+
+/*
+ * The R4000 TLB handler is much more complicated. We have two
+ * consecutive handler areas with 32 instructions space each.
+ * Since they aren't used at the same time, we can overflow in the
+ * other one.To keep things simple, we first assume linear space,
+ * then we relocate it to the final handler layout as needed.
+ */
+static __initdata u32 final_handler[64];
+
+/*
+ * Hazards
+ *
+ * From the IDT errata for the QED RM5230 (Nevada), processor revision 1.0:
+ * 2. A timing hazard exists for the TLBP instruction.
+ *
+ * stalling_instruction
+ * TLBP
+ *
+ * The JTLB is being read for the TLBP throughout the stall generated by the
+ * previous instruction. This is not really correct as the stalling instruction
+ * can modify the address used to access the JTLB. The failure symptom is that
+ * the TLBP instruction will use an address created for the stalling instruction
+ * and not the address held in C0_ENHI and thus report the wrong results.
+ *
+ * The software work-around is to not allow the instruction preceding the TLBP
+ * to stall - make it an NOP or some other instruction guaranteed not to stall.
+ *
+ * Errata 2 will not be fixed. This errata is also on the R5000.
+ *
+ * As if we MIPS hackers wouldn't know how to nop pipelines happy ...
+ */
+static __init void __attribute__((unused)) build_tlb_probe_entry(u32 **p)
+{
+ switch (current_cpu_data.cputype) {
+ case CPU_R5000:
+ case CPU_R5000A:
+ case CPU_NEVADA:
+ i_nop(p);
+ i_tlbp(p);
+ break;
+
+ default:
+ i_tlbp(p);
+ break;
+ }
+}
+
+/*
+ * Write random or indexed TLB entry, and care about the hazards from
+ * the preceeding mtc0 and for the following eret.
+ */
+enum tlb_write_entry { tlb_random, tlb_indexed };
+
+static __init void build_tlb_write_entry(u32 **p, struct label **l,
+ struct reloc **r,
+ enum tlb_write_entry wmode)
+{
+ void(*tlbw)(u32 **) = NULL;
+
+ switch (wmode) {
+ case tlb_random: tlbw = i_tlbwr; break;
+ case tlb_indexed: tlbw = i_tlbwi; break;
+ }
+
+ switch (current_cpu_data.cputype) {
+ case CPU_R4000PC:
+ case CPU_R4000SC:
+ case CPU_R4000MC:
+ case CPU_R4400PC:
+ case CPU_R4400SC:
+ case CPU_R4400MC:
+ /*
+ * This branch uses up a mtc0 hazard nop slot and saves
+ * two nops after the tlbw instruction.
+ */
+ il_bgezl(p, r, 0, label_tlbw_hazard);
+ tlbw(p);
+ l_tlbw_hazard(l, *p);
+ i_nop(p);
+ break;
+
+ case CPU_R4600:
+ case CPU_R4700:
+ case CPU_R5000:
+ case CPU_R5000A:
+ case CPU_5KC:
+ case CPU_TX49XX:
+ case CPU_AU1000:
+ case CPU_AU1100:
+ case CPU_AU1500:
+ case CPU_AU1550:
+ i_nop(p);
+ tlbw(p);
+ break;
+
+ case CPU_R10000:
+ case CPU_R12000:
+ case CPU_4KC:
+ case CPU_SB1:
+ case CPU_4KSC:
+ case CPU_20KC:
+ case CPU_25KF:
+ tlbw(p);
+ break;
+
+ case CPU_NEVADA:
+ i_nop(p); /* QED specifies 2 nops hazard */
+ /*
+ * This branch uses up a mtc0 hazard nop slot and saves
+ * a nop after the tlbw instruction.
+ */
+ il_bgezl(p, r, 0, label_tlbw_hazard);
+ tlbw(p);
+ l_tlbw_hazard(l, *p);
+ break;
+
+ case CPU_RM7000:
+ i_nop(p);
+ i_nop(p);
+ i_nop(p);
+ i_nop(p);
+ tlbw(p);
+ break;
+
+ case CPU_4KEC:
+ case CPU_24K:
+ i_ehb(p);
+ tlbw(p);
+ break;
+
+ case CPU_RM9000:
+ /*
+ * When the JTLB is updated by tlbwi or tlbwr, a subsequent
+ * use of the JTLB for instructions should not occur for 4
+ * cpu cycles and use for data translations should not occur
+ * for 3 cpu cycles.
+ */
+ i_ssnop(p);
+ i_ssnop(p);
+ i_ssnop(p);
+ i_ssnop(p);
+ tlbw(p);
+ i_ssnop(p);
+ i_ssnop(p);
+ i_ssnop(p);
+ i_ssnop(p);
+ break;
+
+ case CPU_VR4111:
+ case CPU_VR4121:
+ case CPU_VR4122:
+ case CPU_VR4181:
+ case CPU_VR4181A:
+ i_nop(p);
+ i_nop(p);
+ tlbw(p);
+ i_nop(p);
+ i_nop(p);
+ break;
+
+ case CPU_VR4131:
+ case CPU_VR4133:
+ i_nop(p);
+ i_nop(p);
+ tlbw(p);
+ break;
+
+ default:
+ panic("No TLB refill handler yet (CPU type: %d)",
+ current_cpu_data.cputype);
+ break;
+ }
+}
+
+#ifdef CONFIG_MIPS64
+/*
+ * TMP and PTR are scratch.
+ * TMP will be clobbered, PTR will hold the pmd entry.
+ */
+static __init void
+build_get_pmde64(u32 **p, struct label **l, struct reloc **r,
+ unsigned int tmp, unsigned int ptr)
+{
+ long pgdc = (long)pgd_current;
+
+ /*
+ * The vmalloc handling is not in the hotpath.
+ */
+ i_dmfc0(p, tmp, C0_BADVADDR);
+ il_bltz(p, r, tmp, label_vmalloc);
+ /* No i_nop needed here, since the next insn doesn't touch TMP. */
+
+#ifdef CONFIG_SMP
+ /*
+ * 64 bit SMP has the lower part of &pgd_current[smp_processor_id()]
+ * stored in CONTEXT.
+ */
+ if (in_compat_space_p(pgdc)) {
+ i_dmfc0(p, ptr, C0_CONTEXT);
+ i_dsra(p, ptr, ptr, 23);
+ i_ld(p, ptr, 0, ptr);
+ } else {
+#ifdef CONFIG_BUILD_ELF64
+ i_dmfc0(p, ptr, C0_CONTEXT);
+ i_dsrl(p, ptr, ptr, 23);
+ i_dsll(p, ptr, ptr, 3);
+ i_LA_mostly(p, tmp, pgdc);
+ i_daddu(p, ptr, ptr, tmp);
+ i_dmfc0(p, tmp, C0_BADVADDR);
+ i_ld(p, ptr, rel_lo(pgdc), ptr);
+#else
+ i_dmfc0(p, ptr, C0_CONTEXT);
+ i_lui(p, tmp, rel_highest(pgdc));
+ i_dsll(p, ptr, ptr, 9);
+ i_daddiu(p, tmp, tmp, rel_higher(pgdc));
+ i_dsrl32(p, ptr, ptr, 0);
+ i_and(p, ptr, ptr, tmp);
+ i_dmfc0(p, tmp, C0_BADVADDR);
+ i_ld(p, ptr, 0, ptr);
+#endif
+ }
+#else
+ i_LA_mostly(p, ptr, pgdc);
+ i_ld(p, ptr, rel_lo(pgdc), ptr);
+#endif
+
+ l_vmalloc_done(l, *p);
+ i_dsrl(p, tmp, tmp, PGDIR_SHIFT-3); /* get pgd offset in bytes */
+ i_andi(p, tmp, tmp, (PTRS_PER_PGD - 1)<<3);
+ i_daddu(p, ptr, ptr, tmp); /* add in pgd offset */
+ i_dmfc0(p, tmp, C0_BADVADDR); /* get faulting address */
+ i_ld(p, ptr, 0, ptr); /* get pmd pointer */
+ i_dsrl(p, tmp, tmp, PMD_SHIFT-3); /* get pmd offset in bytes */
+ i_andi(p, tmp, tmp, (PTRS_PER_PMD - 1)<<3);
+ i_daddu(p, ptr, ptr, tmp); /* add in pmd offset */
+}
+
+/*
+ * BVADDR is the faulting address, PTR is scratch.
+ * PTR will hold the pgd for vmalloc.
+ */
+static __init void
+build_get_pgd_vmalloc64(u32 **p, struct label **l, struct reloc **r,
+ unsigned int bvaddr, unsigned int ptr)
+{
+ long swpd = (long)swapper_pg_dir;
+
+ l_vmalloc(l, *p);
+ i_LA(p, ptr, VMALLOC_START);
+ i_dsubu(p, bvaddr, bvaddr, ptr);
+
+ if (in_compat_space_p(swpd) && !rel_lo(swpd)) {
+ il_b(p, r, label_vmalloc_done);
+ i_lui(p, ptr, rel_hi(swpd));
+ } else {
+ i_LA_mostly(p, ptr, swpd);
+ il_b(p, r, label_vmalloc_done);
+ i_daddiu(p, ptr, ptr, rel_lo(swpd));
+ }
+}
+
+#else /* !CONFIG_MIPS64 */
+
+/*
+ * TMP and PTR are scratch.
+ * TMP will be clobbered, PTR will hold the pgd entry.
+ */
+static __init void __attribute__((unused))
+build_get_pgde32(u32 **p, unsigned int tmp, unsigned int ptr)
+{
+ long pgdc = (long)pgd_current;
+
+ /* 32 bit SMP has smp_processor_id() stored in CONTEXT. */
+#ifdef CONFIG_SMP
+ i_mfc0(p, ptr, C0_CONTEXT);
+ i_LA_mostly(p, tmp, pgdc);
+ i_srl(p, ptr, ptr, 23);
+ i_sll(p, ptr, ptr, 2);
+ i_addu(p, ptr, tmp, ptr);
+#else
+ i_LA_mostly(p, ptr, pgdc);
+#endif
+ i_mfc0(p, tmp, C0_BADVADDR); /* get faulting address */
+ i_lw(p, ptr, rel_lo(pgdc), ptr);
+ i_srl(p, tmp, tmp, PGDIR_SHIFT); /* get pgd only bits */
+ i_sll(p, tmp, tmp, PGD_T_LOG2);
+ i_addu(p, ptr, ptr, tmp); /* add in pgd offset */
+}
+
+#endif /* !CONFIG_MIPS64 */
+
+static __init void build_adjust_context(u32 **p, unsigned int ctx)
+{
+ unsigned int shift = 4 - (PTE_T_LOG2 + 1);
+ unsigned int mask = (PTRS_PER_PTE / 2 - 1) << (PTE_T_LOG2 + 1);
+
+ switch (current_cpu_data.cputype) {
+ case CPU_VR41XX:
+ case CPU_VR4111:
+ case CPU_VR4121:
+ case CPU_VR4122:
+ case CPU_VR4131:
+ case CPU_VR4181:
+ case CPU_VR4181A:
+ case CPU_VR4133:
+ shift += 2;
+ break;
+
+ default:
+ break;
+ }
+
+ if (shift)
+ i_SRL(p, ctx, ctx, shift);
+ i_andi(p, ctx, ctx, mask);
+}
+
+static __init void build_get_ptep(u32 **p, unsigned int tmp, unsigned int ptr)
+{
+ /*
+ * Bug workaround for the Nevada. It seems as if under certain
+ * circumstances the move from cp0_context might produce a
+ * bogus result when the mfc0 instruction and its consumer are
+ * in a different cacheline or a load instruction, probably any
+ * memory reference, is between them.
+ */
+ switch (current_cpu_data.cputype) {
+ case CPU_NEVADA:
+ i_LW(p, ptr, 0, ptr);
+ GET_CONTEXT(p, tmp); /* get context reg */
+ break;
+
+ default:
+ GET_CONTEXT(p, tmp); /* get context reg */
+ i_LW(p, ptr, 0, ptr);
+ break;
+ }
+
+ build_adjust_context(p, tmp);
+ i_ADDU(p, ptr, ptr, tmp); /* add in offset */
+}
+
+static __init void build_update_entries(u32 **p, unsigned int tmp,
+ unsigned int ptep)
+{
+ /*
+ * 64bit address support (36bit on a 32bit CPU) in a 32bit
+ * Kernel is a special case. Only a few CPUs use it.
+ */
+#ifdef CONFIG_64BIT_PHYS_ADDR
+ if (cpu_has_64bits) {
+ i_ld(p, tmp, 0, ptep); /* get even pte */
+ i_ld(p, ptep, sizeof(pte_t), ptep); /* get odd pte */
+ i_dsrl(p, tmp, tmp, 6); /* convert to entrylo0 */
+ i_mtc0(p, tmp, C0_ENTRYLO0); /* load it */
+ i_dsrl(p, ptep, ptep, 6); /* convert to entrylo1 */
+ i_mtc0(p, ptep, C0_ENTRYLO1); /* load it */
+ } else {
+ int pte_off_even = sizeof(pte_t) / 2;
+ int pte_off_odd = pte_off_even + sizeof(pte_t);
+
+ /* The pte entries are pre-shifted */
+ i_lw(p, tmp, pte_off_even, ptep); /* get even pte */
+ i_mtc0(p, tmp, C0_ENTRYLO0); /* load it */
+ i_lw(p, ptep, pte_off_odd, ptep); /* get odd pte */
+ i_mtc0(p, ptep, C0_ENTRYLO1); /* load it */
+ }
+#else
+ i_LW(p, tmp, 0, ptep); /* get even pte */
+ i_LW(p, ptep, sizeof(pte_t), ptep); /* get odd pte */
+ if (r45k_bvahwbug())
+ build_tlb_probe_entry(p);
+ i_SRL(p, tmp, tmp, 6); /* convert to entrylo0 */
+ if (r4k_250MHZhwbug())
+ i_mtc0(p, 0, C0_ENTRYLO0);
+ i_mtc0(p, tmp, C0_ENTRYLO0); /* load it */
+ i_SRL(p, ptep, ptep, 6); /* convert to entrylo1 */
+ if (r45k_bvahwbug())
+ i_mfc0(p, tmp, C0_INDEX);
+ if (r4k_250MHZhwbug())
+ i_mtc0(p, 0, C0_ENTRYLO1);
+ i_mtc0(p, ptep, C0_ENTRYLO1); /* load it */
+#endif
+}
+
+static void __init build_r4000_tlb_refill_handler(void)
+{
+ u32 *p = tlb_handler;
+ struct label *l = labels;
+ struct reloc *r = relocs;
+ u32 *f;
+ unsigned int final_len;
+
+ memset(tlb_handler, 0, sizeof(tlb_handler));
+ memset(labels, 0, sizeof(labels));
+ memset(relocs, 0, sizeof(relocs));
+ memset(final_handler, 0, sizeof(final_handler));
+
+ /*
+ * create the plain linear handler
+ */
+ if (bcm1250_m3_war()) {
+ i_MFC0(&p, K0, C0_BADVADDR);
+ i_MFC0(&p, K1, C0_ENTRYHI);
+ i_xor(&p, K0, K0, K1);
+ i_SRL(&p, K0, K0, PAGE_SHIFT + 1);
+ il_bnez(&p, &r, K0, label_leave);
+ /* No need for i_nop */
+ }
+
+#ifdef CONFIG_MIPS64
+ build_get_pmde64(&p, &l, &r, K0, K1); /* get pmd in K1 */
+#else
+ build_get_pgde32(&p, K0, K1); /* get pgd in K1 */
+#endif
+
+ build_get_ptep(&p, K0, K1);
+ build_update_entries(&p, K0, K1);
+ build_tlb_write_entry(&p, &l, &r, tlb_random);
+ l_leave(&l, p);
+ i_eret(&p); /* return from trap */
+
+#ifdef CONFIG_MIPS64
+ build_get_pgd_vmalloc64(&p, &l, &r, K0, K1);
+#endif
+
+ /*
+ * Overflow check: For the 64bit handler, we need at least one
+ * free instruction slot for the wrap-around branch. In worst
+ * case, if the intended insertion point is a delay slot, we
+ * need three, with the the second nop'ed and the third being
+ * unused.
+ */
+#ifdef CONFIG_MIPS32
+ if ((p - tlb_handler) > 64)
+ panic("TLB refill handler space exceeded");
+#else
+ if (((p - tlb_handler) > 63)
+ || (((p - tlb_handler) > 61)
+ && insn_has_bdelay(relocs, tlb_handler + 29)))
+ panic("TLB refill handler space exceeded");
+#endif
+
+ /*
+ * Now fold the handler in the TLB refill handler space.
+ */
+#ifdef CONFIG_MIPS32
+ f = final_handler;
+ /* Simplest case, just copy the handler. */
+ copy_handler(relocs, labels, tlb_handler, p, f);
+ final_len = p - tlb_handler;
+#else /* CONFIG_MIPS64 */
+ f = final_handler + 32;
+ if ((p - tlb_handler) <= 32) {
+ /* Just copy the handler. */
+ copy_handler(relocs, labels, tlb_handler, p, f);
+ final_len = p - tlb_handler;
+ } else {
+ u32 *split = tlb_handler + 30;
+
+ /*
+ * Find the split point.
+ */
+ if (insn_has_bdelay(relocs, split - 1))
+ split--;
+
+ /* Copy first part of the handler. */
+ copy_handler(relocs, labels, tlb_handler, split, f);
+ f += split - tlb_handler;
+
+ /* Insert branch. */
+ l_split(&l, final_handler);
+ il_b(&f, &r, label_split);
+ if (insn_has_bdelay(relocs, split))
+ i_nop(&f);
+ else {
+ copy_handler(relocs, labels, split, split + 1, f);
+ move_labels(labels, f, f + 1, -1);
+ f++;
+ split++;
+ }
+
+ /* Copy the rest of the handler. */
+ copy_handler(relocs, labels, split, p, final_handler);
+ final_len = (f - (final_handler + 32)) + (p - split);
+ }
+#endif /* CONFIG_MIPS64 */
+
+ resolve_relocs(relocs, labels);
+ printk("Synthesized TLB refill handler (%u instructions).\n",
+ final_len);
+
+#ifdef DEBUG_TLB
+ {
+ int i;
+
+ for (i = 0; i < 64; i++)
+ printk("%08x\n", final_handler[i]);
+ }
+#endif
+
+ memcpy((void *)CAC_BASE, final_handler, 0x100);
+ flush_icache_range(CAC_BASE, CAC_BASE + 0x100);
+}
+
+/*
+ * TLB load/store/modify handlers.
+ *
+ * Only the fastpath gets synthesized at runtime, the slowpath for
+ * do_page_fault remains normal asm.
+ */
+extern void tlb_do_page_fault_0(void);
+extern void tlb_do_page_fault_1(void);
+
+#define __tlb_handler_align \
+ __attribute__((__aligned__(1 << CONFIG_MIPS_L1_CACHE_SHIFT)))
+
+/*
+ * 128 instructions for the fastpath handler is generous and should
+ * never be exceeded.
+ */
+#define FASTPATH_SIZE 128
+
+u32 __tlb_handler_align handle_tlbl[FASTPATH_SIZE];
+u32 __tlb_handler_align handle_tlbs[FASTPATH_SIZE];
+u32 __tlb_handler_align handle_tlbm[FASTPATH_SIZE];
+
+static void __init
+iPTE_LW(u32 **p, struct label **l, unsigned int pte, int offset,
+ unsigned int ptr)
+{
+#ifdef CONFIG_SMP
+# ifdef CONFIG_64BIT_PHYS_ADDR
+ if (cpu_has_64bits)
+ i_lld(p, pte, offset, ptr);
+ else
+# endif
+ i_LL(p, pte, offset, ptr);
+#else
+# ifdef CONFIG_64BIT_PHYS_ADDR
+ if (cpu_has_64bits)
+ i_ld(p, pte, offset, ptr);
+ else
+# endif
+ i_LW(p, pte, offset, ptr);
+#endif
+}
+
+static void __init
+iPTE_SW(u32 **p, struct reloc **r, unsigned int pte, int offset,
+ unsigned int ptr)
+{
+#ifdef CONFIG_SMP
+# ifdef CONFIG_64BIT_PHYS_ADDR
+ if (cpu_has_64bits)
+ i_scd(p, pte, offset, ptr);
+ else
+# endif
+ i_SC(p, pte, offset, ptr);
+
+ if (r10000_llsc_war())
+ il_beqzl(p, r, pte, label_smp_pgtable_change);
+ else
+ il_beqz(p, r, pte, label_smp_pgtable_change);
+
+# ifdef CONFIG_64BIT_PHYS_ADDR
+ if (!cpu_has_64bits) {
+ /* no i_nop needed */
+ i_ll(p, pte, sizeof(pte_t) / 2, ptr);
+ i_ori(p, pte, pte, _PAGE_VALID);
+ i_sc(p, pte, sizeof(pte_t) / 2, ptr);
+ il_beqz(p, r, pte, label_smp_pgtable_change);
+ /* no i_nop needed */
+ i_lw(p, pte, 0, ptr);
+ } else
+ i_nop(p);
+# else
+ i_nop(p);
+# endif
+#else
+# ifdef CONFIG_64BIT_PHYS_ADDR
+ if (cpu_has_64bits)
+ i_sd(p, pte, offset, ptr);
+ else
+# endif
+ i_SW(p, pte, offset, ptr);
+
+# ifdef CONFIG_64BIT_PHYS_ADDR
+ if (!cpu_has_64bits) {
+ i_lw(p, pte, sizeof(pte_t) / 2, ptr);
+ i_ori(p, pte, pte, _PAGE_VALID);
+ i_sw(p, pte, sizeof(pte_t) / 2, ptr);
+ i_lw(p, pte, 0, ptr);
+ }
+# endif
+#endif
+}
+
+/*
+ * Check if PTE is present, if not then jump to LABEL. PTR points to
+ * the page table where this PTE is located, PTE will be re-loaded
+ * with it's original value.
+ */
+static void __init
+build_pte_present(u32 **p, struct label **l, struct reloc **r,
+ unsigned int pte, unsigned int ptr, enum label_id lid)
+{
+ i_andi(p, pte, pte, _PAGE_PRESENT | _PAGE_READ);
+ i_xori(p, pte, pte, _PAGE_PRESENT | _PAGE_READ);
+ il_bnez(p, r, pte, lid);
+ iPTE_LW(p, l, pte, 0, ptr);
+}
+
+/* Make PTE valid, store result in PTR. */
+static void __init
+build_make_valid(u32 **p, struct reloc **r, unsigned int pte,
+ unsigned int ptr)
+{
+ i_ori(p, pte, pte, _PAGE_VALID | _PAGE_ACCESSED);
+ iPTE_SW(p, r, pte, 0, ptr);
+}
+
+/*
+ * Check if PTE can be written to, if not branch to LABEL. Regardless
+ * restore PTE with value from PTR when done.
+ */
+static void __init
+build_pte_writable(u32 **p, struct label **l, struct reloc **r,
+ unsigned int pte, unsigned int ptr, enum label_id lid)
+{
+ i_andi(p, pte, pte, _PAGE_PRESENT | _PAGE_WRITE);
+ i_xori(p, pte, pte, _PAGE_PRESENT | _PAGE_WRITE);
+ il_bnez(p, r, pte, lid);
+ iPTE_LW(p, l, pte, 0, ptr);
+}
+
+/* Make PTE writable, update software status bits as well, then store
+ * at PTR.
+ */
+static void __init
+build_make_write(u32 **p, struct reloc **r, unsigned int pte,
+ unsigned int ptr)
+{
+ i_ori(p, pte, pte,
+ _PAGE_ACCESSED | _PAGE_MODIFIED | _PAGE_VALID | _PAGE_DIRTY);
+ iPTE_SW(p, r, pte, 0, ptr);
+}
+
+/*
+ * Check if PTE can be modified, if not branch to LABEL. Regardless
+ * restore PTE with value from PTR when done.
+ */
+static void __init
+build_pte_modifiable(u32 **p, struct label **l, struct reloc **r,
+ unsigned int pte, unsigned int ptr, enum label_id lid)
+{
+ i_andi(p, pte, pte, _PAGE_WRITE);
+ il_beqz(p, r, pte, lid);
+ iPTE_LW(p, l, pte, 0, ptr);
+}
+
+/*
+ * R3000 style TLB load/store/modify handlers.
+ */
+
+/* This places the pte in the page table at PTR into ENTRYLO0. */
+static void __init
+build_r3000_pte_reload(u32 **p, unsigned int ptr)
+{
+ i_lw(p, ptr, 0, ptr);
+ i_nop(p); /* load delay */
+ i_mtc0(p, ptr, C0_ENTRYLO0);
+ i_nop(p); /* cp0 delay */
+}
+
+/*
+ * The index register may have the probe fail bit set,
+ * because we would trap on access kseg2, i.e. without refill.
+ */
+static void __init
+build_r3000_tlb_write(u32 **p, struct label **l, struct reloc **r,
+ unsigned int tmp)
+{
+ i_mfc0(p, tmp, C0_INDEX);
+ i_nop(p); /* cp0 delay */
+ il_bltz(p, r, tmp, label_r3000_write_probe_fail);
+ i_nop(p); /* branch delay */
+ i_tlbwi(p);
+ il_b(p, r, label_r3000_write_probe_ok);
+ i_nop(p); /* branch delay */
+ l_r3000_write_probe_fail(l, *p);
+ i_tlbwr(p);
+ l_r3000_write_probe_ok(l, *p);
+}
+
+static void __init
+build_r3000_tlbchange_handler_head(u32 **p, unsigned int pte,
+ unsigned int ptr)
+{
+ long pgdc = (long)pgd_current;
+
+ i_mfc0(p, pte, C0_BADVADDR);
+ i_lui(p, ptr, rel_hi(pgdc)); /* cp0 delay */
+ i_lw(p, ptr, rel_lo(pgdc), ptr);
+ i_srl(p, pte, pte, 22); /* load delay */
+ i_sll(p, pte, pte, 2);
+ i_addu(p, ptr, ptr, pte);
+ i_mfc0(p, pte, C0_CONTEXT);
+ i_lw(p, ptr, 0, ptr); /* cp0 delay */
+ i_andi(p, pte, pte, 0xffc); /* load delay */
+ i_addu(p, ptr, ptr, pte);
+ i_lw(p, pte, 0, ptr);
+ i_nop(p); /* load delay */
+ i_tlbp(p);
+}
+
+static void __init
+build_r3000_tlbchange_handler_tail(u32 **p, unsigned int tmp)
+{
+ i_mfc0(p, tmp, C0_EPC);
+ i_nop(p); /* cp0 delay */
+ i_jr(p, tmp);
+ i_rfe(p); /* branch delay */
+}
+
+static void __init build_r3000_tlb_load_handler(void)
+{
+ u32 *p = handle_tlbl;
+ struct label *l = labels;
+ struct reloc *r = relocs;
+
+ memset(handle_tlbl, 0, sizeof(handle_tlbl));
+ memset(labels, 0, sizeof(labels));
+ memset(relocs, 0, sizeof(relocs));
+
+ build_r3000_tlbchange_handler_head(&p, K0, K1);
+ build_pte_present(&p, &l, &r, K0, K1, label_nopage_tlbl);
+ build_make_valid(&p, &r, K0, K1);
+ build_r3000_pte_reload(&p, K1);
+ build_r3000_tlb_write(&p, &l, &r, K0);
+ build_r3000_tlbchange_handler_tail(&p, K0);
+
+ l_nopage_tlbl(&l, p);
+ i_j(&p, (unsigned long)tlb_do_page_fault_0 & 0x0fffffff);
+ i_nop(&p);
+
+ if ((p - handle_tlbl) > FASTPATH_SIZE)
+ panic("TLB load handler fastpath space exceeded");
+
+ resolve_relocs(relocs, labels);
+ printk("Synthesized TLB load handler fastpath (%u instructions).\n",
+ (unsigned int)(p - handle_tlbl));
+
+#ifdef DEBUG_TLB
+ {
+ int i;
+
+ for (i = 0; i < FASTPATH_SIZE; i++)
+ printk("%08x\n", handle_tlbl[i]);
+ }
+#endif
+
+ flush_icache_range((unsigned long)handle_tlbl,
+ (unsigned long)handle_tlbl + FASTPATH_SIZE * sizeof(u32));
+}
+
+static void __init build_r3000_tlb_store_handler(void)
+{
+ u32 *p = handle_tlbs;
+ struct label *l = labels;
+ struct reloc *r = relocs;
+
+ memset(handle_tlbs, 0, sizeof(handle_tlbs));
+ memset(labels, 0, sizeof(labels));
+ memset(relocs, 0, sizeof(relocs));
+
+ build_r3000_tlbchange_handler_head(&p, K0, K1);
+ build_pte_writable(&p, &l, &r, K0, K1, label_nopage_tlbs);
+ build_make_write(&p, &r, K0, K1);
+ build_r3000_pte_reload(&p, K1);
+ build_r3000_tlb_write(&p, &l, &r, K0);
+ build_r3000_tlbchange_handler_tail(&p, K0);
+
+ l_nopage_tlbs(&l, p);
+ i_j(&p, (unsigned long)tlb_do_page_fault_1 & 0x0fffffff);
+ i_nop(&p);
+
+ if ((p - handle_tlbs) > FASTPATH_SIZE)
+ panic("TLB store handler fastpath space exceeded");
+
+ resolve_relocs(relocs, labels);
+ printk("Synthesized TLB store handler fastpath (%u instructions).\n",
+ (unsigned int)(p - handle_tlbs));
+
+#ifdef DEBUG_TLB
+ {
+ int i;
+
+ for (i = 0; i < FASTPATH_SIZE; i++)
+ printk("%08x\n", handle_tlbs[i]);
+ }
+#endif
+
+ flush_icache_range((unsigned long)handle_tlbs,
+ (unsigned long)handle_tlbs + FASTPATH_SIZE * sizeof(u32));
+}
+
+static void __init build_r3000_tlb_modify_handler(void)
+{
+ u32 *p = handle_tlbm;
+ struct label *l = labels;
+ struct reloc *r = relocs;
+
+ memset(handle_tlbm, 0, sizeof(handle_tlbm));
+ memset(labels, 0, sizeof(labels));
+ memset(relocs, 0, sizeof(relocs));
+
+ build_r3000_tlbchange_handler_head(&p, K0, K1);
+ build_pte_modifiable(&p, &l, &r, K0, K1, label_nopage_tlbm);
+ build_make_write(&p, &r, K0, K1);
+ build_r3000_pte_reload(&p, K1);
+ i_tlbwi(&p);
+ build_r3000_tlbchange_handler_tail(&p, K0);
+
+ l_nopage_tlbm(&l, p);
+ i_j(&p, (unsigned long)tlb_do_page_fault_1 & 0x0fffffff);
+ i_nop(&p);
+
+ if ((p - handle_tlbm) > FASTPATH_SIZE)
+ panic("TLB modify handler fastpath space exceeded");
+
+ resolve_relocs(relocs, labels);
+ printk("Synthesized TLB modify handler fastpath (%u instructions).\n",
+ (unsigned int)(p - handle_tlbm));
+
+#ifdef DEBUG_TLB
+ {
+ int i;
+
+ for (i = 0; i < FASTPATH_SIZE; i++)
+ printk("%08x\n", handle_tlbm[i]);
+ }
+#endif
+
+ flush_icache_range((unsigned long)handle_tlbm,
+ (unsigned long)handle_tlbm + FASTPATH_SIZE * sizeof(u32));
+}
+
+/*
+ * R4000 style TLB load/store/modify handlers.
+ */
+static void __init
+build_r4000_tlbchange_handler_head(u32 **p, struct label **l,
+ struct reloc **r, unsigned int pte,
+ unsigned int ptr)
+{
+#ifdef CONFIG_MIPS64
+ build_get_pmde64(p, l, r, pte, ptr); /* get pmd in ptr */
+#else
+ build_get_pgde32(p, pte, ptr); /* get pgd in ptr */
+#endif
+
+ i_MFC0(p, pte, C0_BADVADDR);
+ i_LW(p, ptr, 0, ptr);
+ i_SRL(p, pte, pte, PAGE_SHIFT + PTE_ORDER - PTE_T_LOG2);
+ i_andi(p, pte, pte, (PTRS_PER_PTE - 1) << PTE_T_LOG2);
+ i_ADDU(p, ptr, ptr, pte);
+
+#ifdef CONFIG_SMP
+ l_smp_pgtable_change(l, *p);
+# endif
+ iPTE_LW(p, l, pte, 0, ptr); /* get even pte */
+ build_tlb_probe_entry(p);
+}
+
+static void __init
+build_r4000_tlbchange_handler_tail(u32 **p, struct label **l,
+ struct reloc **r, unsigned int tmp,
+ unsigned int ptr)
+{
+ i_ori(p, ptr, ptr, sizeof(pte_t));
+ i_xori(p, ptr, ptr, sizeof(pte_t));
+ build_update_entries(p, tmp, ptr);
+ build_tlb_write_entry(p, l, r, tlb_indexed);
+ l_leave(l, *p);
+ i_eret(p); /* return from trap */
+
+#ifdef CONFIG_MIPS64
+ build_get_pgd_vmalloc64(p, l, r, tmp, ptr);
+#endif
+}
+
+static void __init build_r4000_tlb_load_handler(void)
+{
+ u32 *p = handle_tlbl;
+ struct label *l = labels;
+ struct reloc *r = relocs;
+
+ memset(handle_tlbl, 0, sizeof(handle_tlbl));
+ memset(labels, 0, sizeof(labels));
+ memset(relocs, 0, sizeof(relocs));
+
+ if (bcm1250_m3_war()) {
+ i_MFC0(&p, K0, C0_BADVADDR);
+ i_MFC0(&p, K1, C0_ENTRYHI);
+ i_xor(&p, K0, K0, K1);
+ i_SRL(&p, K0, K0, PAGE_SHIFT + 1);
+ il_bnez(&p, &r, K0, label_leave);
+ /* No need for i_nop */
+ }
+
+ build_r4000_tlbchange_handler_head(&p, &l, &r, K0, K1);
+ build_pte_present(&p, &l, &r, K0, K1, label_nopage_tlbl);
+ build_make_valid(&p, &r, K0, K1);
+ build_r4000_tlbchange_handler_tail(&p, &l, &r, K0, K1);
+
+ l_nopage_tlbl(&l, p);
+ i_j(&p, (unsigned long)tlb_do_page_fault_0 & 0x0fffffff);
+ i_nop(&p);
+
+ if ((p - handle_tlbl) > FASTPATH_SIZE)
+ panic("TLB load handler fastpath space exceeded");
+
+ resolve_relocs(relocs, labels);
+ printk("Synthesized TLB load handler fastpath (%u instructions).\n",
+ (unsigned int)(p - handle_tlbl));
+
+#ifdef DEBUG_TLB
+ {
+ int i;
+
+ for (i = 0; i < FASTPATH_SIZE; i++)
+ printk("%08x\n", handle_tlbl[i]);
+ }
+#endif
+
+ flush_icache_range((unsigned long)handle_tlbl,
+ (unsigned long)handle_tlbl + FASTPATH_SIZE * sizeof(u32));
+}
+
+static void __init build_r4000_tlb_store_handler(void)
+{
+ u32 *p = handle_tlbs;
+ struct label *l = labels;
+ struct reloc *r = relocs;
+
+ memset(handle_tlbs, 0, sizeof(handle_tlbs));
+ memset(labels, 0, sizeof(labels));
+ memset(relocs, 0, sizeof(relocs));
+
+ build_r4000_tlbchange_handler_head(&p, &l, &r, K0, K1);
+ build_pte_writable(&p, &l, &r, K0, K1, label_nopage_tlbs);
+ build_make_write(&p, &r, K0, K1);
+ build_r4000_tlbchange_handler_tail(&p, &l, &r, K0, K1);
+
+ l_nopage_tlbs(&l, p);
+ i_j(&p, (unsigned long)tlb_do_page_fault_1 & 0x0fffffff);
+ i_nop(&p);
+
+ if ((p - handle_tlbs) > FASTPATH_SIZE)
+ panic("TLB store handler fastpath space exceeded");
+
+ resolve_relocs(relocs, labels);
+ printk("Synthesized TLB store handler fastpath (%u instructions).\n",
+ (unsigned int)(p - handle_tlbs));
+
+#ifdef DEBUG_TLB
+ {
+ int i;
+
+ for (i = 0; i < FASTPATH_SIZE; i++)
+ printk("%08x\n", handle_tlbs[i]);
+ }
+#endif
+
+ flush_icache_range((unsigned long)handle_tlbs,
+ (unsigned long)handle_tlbs + FASTPATH_SIZE * sizeof(u32));
+}
+
+static void __init build_r4000_tlb_modify_handler(void)
+{
+ u32 *p = handle_tlbm;
+ struct label *l = labels;
+ struct reloc *r = relocs;
+
+ memset(handle_tlbm, 0, sizeof(handle_tlbm));
+ memset(labels, 0, sizeof(labels));
+ memset(relocs, 0, sizeof(relocs));
+
+ build_r4000_tlbchange_handler_head(&p, &l, &r, K0, K1);
+ build_pte_modifiable(&p, &l, &r, K0, K1, label_nopage_tlbm);
+ /* Present and writable bits set, set accessed and dirty bits. */
+ build_make_write(&p, &r, K0, K1);
+ build_r4000_tlbchange_handler_tail(&p, &l, &r, K0, K1);
+
+ l_nopage_tlbm(&l, p);
+ i_j(&p, (unsigned long)tlb_do_page_fault_1 & 0x0fffffff);
+ i_nop(&p);
+
+ if ((p - handle_tlbm) > FASTPATH_SIZE)
+ panic("TLB modify handler fastpath space exceeded");
+
+ resolve_relocs(relocs, labels);
+ printk("Synthesized TLB modify handler fastpath (%u instructions).\n",
+ (unsigned int)(p - handle_tlbm));
+
+#ifdef DEBUG_TLB
+ {
+ int i;
+
+ for (i = 0; i < FASTPATH_SIZE; i++)
+ printk("%08x\n", handle_tlbm[i]);
+ }
+#endif
+
+ flush_icache_range((unsigned long)handle_tlbm,
+ (unsigned long)handle_tlbm + FASTPATH_SIZE * sizeof(u32));
+}
+
+void __init build_tlb_refill_handler(void)
+{
+ /*
+ * The refill handler is generated per-CPU, multi-node systems
+ * may have local storage for it. The other handlers are only
+ * needed once.
+ */
+ static int run_once = 0;
+
+ switch (current_cpu_data.cputype) {
+ case CPU_R2000:
+ case CPU_R3000:
+ case CPU_R3000A:
+ case CPU_R3081E:
+ case CPU_TX3912:
+ case CPU_TX3922:
+ case CPU_TX3927:
+ build_r3000_tlb_refill_handler();
+ if (!run_once) {
+ build_r3000_tlb_load_handler();
+ build_r3000_tlb_store_handler();
+ build_r3000_tlb_modify_handler();
+ run_once++;
+ }
+ break;
+
+ case CPU_R6000:
+ case CPU_R6000A:
+ panic("No R6000 TLB refill handler yet");
+ break;
+
+ case CPU_R8000:
+ panic("No R8000 TLB refill handler yet");
+ break;
+
+ default:
+ build_r4000_tlb_refill_handler();
+ if (!run_once) {
+ build_r4000_tlb_load_handler();
+ build_r4000_tlb_store_handler();
+ build_r4000_tlb_modify_handler();
+ run_once++;
+ }
+ }
+}
diff --git a/arch/mips/momentum/jaguar_atx/Makefile b/arch/mips/momentum/jaguar_atx/Makefile
new file mode 100644
index 0000000..20bbd3e
--- /dev/null
+++ b/arch/mips/momentum/jaguar_atx/Makefile
@@ -0,0 +1,12 @@
+#
+# Makefile for Momentum Computer's Jaguar-ATX board.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+
+obj-y += int-handler.o irq.o prom.o reset.o setup.o
+
+obj-$(CONFIG_SERIAL_8250_CONSOLE) += ja-console.o
+obj-$(CONFIG_REMOTE_DEBUG) += dbg_io.o
diff --git a/arch/mips/momentum/jaguar_atx/dbg_io.c b/arch/mips/momentum/jaguar_atx/dbg_io.c
new file mode 100644
index 0000000..542eac8
--- /dev/null
+++ b/arch/mips/momentum/jaguar_atx/dbg_io.c
@@ -0,0 +1,126 @@
+#include <linux/config.h>
+
+#if defined(CONFIG_REMOTE_DEBUG)
+
+#include <asm/serial.h> /* For the serial port location and base baud */
+
+/* --- CONFIG --- */
+
+typedef unsigned char uint8;
+typedef unsigned int uint32;
+
+/* --- END OF CONFIG --- */
+
+#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
+
+/* ----------------------------------------------------- */
+
+/* === CONFIG === */
+
+/* [jsun] we use the second serial port for kdb */
+#define BASE OCELOT_SERIAL1_BASE
+#define MAX_BAUD OCELOT_BASE_BAUD
+
+/* === END OF CONFIG === */
+
+#define REG_OFFSET 4
+
+/* register offset */
+#define OFS_RCV_BUFFER 0
+#define OFS_TRANS_HOLD 0
+#define OFS_SEND_BUFFER 0
+#define OFS_INTR_ENABLE (1*REG_OFFSET)
+#define OFS_INTR_ID (2*REG_OFFSET)
+#define OFS_DATA_FORMAT (3*REG_OFFSET)
+#define OFS_LINE_CONTROL (3*REG_OFFSET)
+#define OFS_MODEM_CONTROL (4*REG_OFFSET)
+#define OFS_RS232_OUTPUT (4*REG_OFFSET)
+#define OFS_LINE_STATUS (5*REG_OFFSET)
+#define OFS_MODEM_STATUS (6*REG_OFFSET)
+#define OFS_RS232_INPUT (6*REG_OFFSET)
+#define OFS_SCRATCH_PAD (7*REG_OFFSET)
+
+#define OFS_DIVISOR_LSB (0*REG_OFFSET)
+#define OFS_DIVISOR_MSB (1*REG_OFFSET)
+
+
+/* memory-mapped read/write of the port */
+#define UART16550_READ(y) (*((volatile uint8*)(BASE + y)))
+#define UART16550_WRITE(y, z) ((*((volatile uint8*)(BASE + y))) = z)
+
+void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop)
+{
+ /* disable interrupts */
+ UART16550_WRITE(OFS_INTR_ENABLE, 0);
+
+ /* set up buad rate */
+ {
+ uint32 divisor;
+
+ /* set DIAB bit */
+ UART16550_WRITE(OFS_LINE_CONTROL, 0x80);
+
+ /* set divisor */
+ divisor = MAX_BAUD / baud;
+ UART16550_WRITE(OFS_DIVISOR_LSB, divisor & 0xff);
+ UART16550_WRITE(OFS_DIVISOR_MSB, (divisor & 0xff00) >> 8);
+
+ /* clear DIAB bit */
+ UART16550_WRITE(OFS_LINE_CONTROL, 0x0);
+ }
+
+ /* set data format */
+ UART16550_WRITE(OFS_DATA_FORMAT, data | parity | stop);
+}
+
+static int remoteDebugInitialized = 0;
+
+uint8 getDebugChar(void)
+{
+ if (!remoteDebugInitialized) {
+ remoteDebugInitialized = 1;
+ debugInit(UART16550_BAUD_38400,
+ UART16550_DATA_8BIT,
+ UART16550_PARITY_NONE, UART16550_STOP_1BIT);
+ }
+
+ while ((UART16550_READ(OFS_LINE_STATUS) & 0x1) == 0);
+ return UART16550_READ(OFS_RCV_BUFFER);
+}
+
+
+int putDebugChar(uint8 byte)
+{
+ if (!remoteDebugInitialized) {
+ remoteDebugInitialized = 1;
+ debugInit(UART16550_BAUD_38400,
+ UART16550_DATA_8BIT,
+ UART16550_PARITY_NONE, UART16550_STOP_1BIT);
+ }
+
+ while ((UART16550_READ(OFS_LINE_STATUS) & 0x20) == 0);
+ UART16550_WRITE(OFS_SEND_BUFFER, byte);
+ return 1;
+}
+
+#endif
diff --git a/arch/mips/momentum/jaguar_atx/int-handler.S b/arch/mips/momentum/jaguar_atx/int-handler.S
new file mode 100644
index 0000000..43fd5a5
--- /dev/null
+++ b/arch/mips/momentum/jaguar_atx/int-handler.S
@@ -0,0 +1,128 @@
+/*
+ * Copyright 2002 Momentum Computer Inc.
+ * Author: Matthew Dharm <mdharm@momenco.com>
+ *
+ * Based on work:
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: jsun@mvista.com or jsun@junsun.net
+ *
+ * First-level interrupt dispatcher for Jaguar-ATX board.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+#include <asm/asm.h>
+#include <asm/mipsregs.h>
+#include <asm/addrspace.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+
+/*
+ * First level interrupt dispatcher for Ocelot-CS board
+ */
+ .align 5
+ NESTED(jaguar_handle_int, PT_SIZE, sp)
+ SAVE_ALL
+ CLI
+ .set at
+ mfc0 t0, CP0_CAUSE
+ mfc0 t2, CP0_STATUS
+
+ and t0, t2
+
+ andi t1, t0, STATUSF_IP0 /* sw0 software interrupt */
+ bnez t1, ll_sw0_irq
+ andi t1, t0, STATUSF_IP1 /* sw1 software interrupt */
+ bnez t1, ll_sw1_irq
+ andi t1, t0, STATUSF_IP2 /* int0 hardware line */
+ bnez t1, ll_pcixa_irq
+ andi t1, t0, STATUSF_IP3 /* int1 hardware line */
+ bnez t1, ll_pcixb_irq
+ andi t1, t0, STATUSF_IP4 /* int2 hardware line */
+ bnez t1, ll_pcia_irq
+ andi t1, t0, STATUSF_IP5 /* int3 hardware line */
+ bnez t1, ll_pcib_irq
+ andi t1, t0, STATUSF_IP6 /* int4 hardware line */
+ bnez t1, ll_uart_irq
+ andi t1, t0, STATUSF_IP7 /* cpu timer */
+ bnez t1, ll_cputimer_irq
+
+ nop
+ nop
+
+ /* now look at extended interrupts */
+ mfc0 t0, CP0_CAUSE
+ cfc0 t1, CP0_S1_INTCONTROL
+
+ /* shift the mask 8 bits left to line up the bits */
+ sll t2, t1, 8
+
+ and t0, t2
+ srl t0, t0, 16
+
+ andi t1, t0, STATUSF_IP8 /* int6 hardware line */
+ bnez t1, ll_mv64340_decode_irq
+
+ nop
+ nop
+
+ .set reorder
+
+ /* wrong alarm or masked ... */
+ j spurious_interrupt
+ nop
+ END(jaguar_handle_int)
+
+ .align 5
+ll_sw0_irq:
+ li a0, 0
+ move a1, sp
+ jal do_IRQ
+ j ret_from_irq
+ll_sw1_irq:
+ li a0, 1
+ move a1, sp
+ jal do_IRQ
+ j ret_from_irq
+ll_pcixa_irq:
+ li a0, 2
+ move a1, sp
+ jal do_IRQ
+ j ret_from_irq
+
+ll_pcixb_irq:
+ li a0, 3
+ move a1, sp
+ jal do_IRQ
+ j ret_from_irq
+
+ll_pcia_irq:
+ li a0, 4
+ move a1, sp
+ jal do_IRQ
+ j ret_from_irq
+
+ll_pcib_irq:
+ li a0, 5
+ move a1, sp
+ jal do_IRQ
+ j ret_from_irq
+
+ll_uart_irq:
+ li a0, 6
+ move a1, sp
+ jal do_IRQ
+ j ret_from_irq
+
+ll_cputimer_irq:
+ li a0, 7
+ move a1, sp
+ jal ll_timer_interrupt
+ j ret_from_irq
+
+ll_mv64340_decode_irq:
+ move a0, sp
+ jal ll_mv64340_irq
+ j ret_from_irq
diff --git a/arch/mips/momentum/jaguar_atx/irq.c b/arch/mips/momentum/jaguar_atx/irq.c
new file mode 100644
index 0000000..15588f9
--- /dev/null
+++ b/arch/mips/momentum/jaguar_atx/irq.c
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2002 Momentum Computer, Inc.
+ * Author: Matthew Dharm, mdharm@momenco.com
+ *
+ * Based on work by:
+ * Copyright (C) 2000 RidgeRun, Inc.
+ * Author: RidgeRun, Inc.
+ * glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
+ *
+ * Copyright (C) 2000, 2001 Ralf Baechle (ralf@gnu.org)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/signal.h>
+#include <linux/types.h>
+#include <asm/irq_cpu.h>
+#include <asm/mipsregs.h>
+
+extern asmlinkage void jaguar_handle_int(void);
+
+static struct irqaction cascade_mv64340 = {
+ no_action, SA_INTERRUPT, CPU_MASK_NONE, "MV64340-Cascade", NULL, NULL
+};
+
+void __init arch_init_irq(void)
+{
+ /*
+ * Clear all of the interrupts while we change the able around a bit.
+ * int-handler is not on bootstrap
+ */
+ clear_c0_status(ST0_IM);
+
+ /* Sets the first-level interrupt dispatcher. */
+ set_except_vector(0, jaguar_handle_int);
+ mips_cpu_irq_init(0);
+ rm7k_cpu_irq_init(8);
+
+ /* set up the cascading interrupts */
+ setup_irq(8, &cascade_mv64340);
+
+ mv64340_irq_init(16);
+
+ set_c0_status(ST0_IM);
+}
diff --git a/arch/mips/momentum/jaguar_atx/ja-console.c b/arch/mips/momentum/jaguar_atx/ja-console.c
new file mode 100644
index 0000000..da6e1ed
--- /dev/null
+++ b/arch/mips/momentum/jaguar_atx/ja-console.c
@@ -0,0 +1,106 @@
+/*
+ * 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) 2001, 2002, 2004 Ralf Baechle
+ */
+#include <linux/init.h>
+#include <linux/console.h>
+#include <linux/kdev_t.h>
+#include <linux/major.h>
+#include <linux/termios.h>
+#include <linux/sched.h>
+#include <linux/tty.h>
+
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+#include <asm/serial.h>
+
+/* SUPERIO uart register map */
+struct ja_uartregs {
+ union {
+ volatile u8 pad0[3];
+ volatile u8 rbr; /* read only, DLAB == 0 */
+ volatile u8 pad1[3];
+ volatile u8 thr; /* write only, DLAB == 0 */
+ volatile u8 pad2[3];
+ volatile u8 dll; /* DLAB == 1 */
+ } u1;
+ union {
+ volatile u8 pad0[3];
+ volatile u8 ier; /* DLAB == 0 */
+ volatile u8 pad1[3];
+ volatile u8 dlm; /* DLAB == 1 */
+ } u2;
+ union {
+ volatile u8 pad0[3];
+ volatile u8 iir; /* read only */
+ volatile u8 pad1[3];
+ volatile u8 fcr; /* write only */
+ } u3;
+ volatile u8 pad0[3];
+ volatile u8 iu_lcr;
+ volatile u8 pad1[3];
+ volatile u8 iu_mcr;
+ volatile u8 pad2[3];
+ volatile u8 iu_lsr;
+ volatile u8 pad3[3];
+ volatile u8 iu_msr;
+ volatile u8 pad4[3];
+ volatile u8 iu_scr;
+} ja_uregs_t;
+
+#define iu_rbr u1.rbr
+#define iu_thr u1.thr
+#define iu_dll u1.dll
+#define iu_ier u2.ier
+#define iu_dlm u2.dlm
+#define iu_iir u3.iir
+#define iu_fcr u3.fcr
+
+extern unsigned long uart_base;
+
+static inline struct ja_uartregs *console_uart(void)
+{
+ return (struct ja_uartregs *) (uart_base + 0x23UL);
+}
+
+void prom_putchar(char c)
+{
+ struct ja_uartregs *uart = console_uart();
+
+ while ((uart->iu_lsr & 0x20) == 0);
+ uart->iu_thr = c;
+}
+
+char __init prom_getchar(void)
+{
+ return 0;
+}
+
+static void inline ja_console_probe(void)
+{
+ struct uart_port up;
+
+ /*
+ * Register to interrupt zero because we share the interrupt with
+ * the serial driver which we don't properly support yet.
+ */
+ memset(&up, 0, sizeof(up));
+ up.membase = (unsigned char *) uart_base + 0x23UL;
+ up.irq = JAGUAR_ATX_SERIAL1_IRQ;
+ up.uartclk = JAGUAR_ATX_UART_CLK;
+ up.regshift = 2;
+ up.iotype = UPIO_MEM;
+ up.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST;
+ up.line = 0;
+
+ if (early_serial_setup(&up))
+ printk(KERN_ERR "Early serial init of port 0 failed\n");
+}
+
+__init void ja_setup_console(void)
+{
+ ja_console_probe();
+}
diff --git a/arch/mips/momentum/jaguar_atx/jaguar_atx_fpga.h b/arch/mips/momentum/jaguar_atx/jaguar_atx_fpga.h
new file mode 100644
index 0000000..6978654
--- /dev/null
+++ b/arch/mips/momentum/jaguar_atx/jaguar_atx_fpga.h
@@ -0,0 +1,52 @@
+/*
+ * Jaguar-ATX Board Register Definitions
+ *
+ * (C) 2002 Momentum Computer Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __JAGUAR_ATX_FPGA_H__
+#define __JAGUAR_ATX_FPGA_H__
+
+#define JAGUAR_ATX_REG_BOARDREV 0x0
+#define JAGUAR_ATX_REG_FPGA_REV 0x1
+#define JAGUAR_ATX_REG_FPGA_TYPE 0x2
+#define JAGUAR_ATX_REG_RESET_STATUS 0x3
+#define JAGUAR_ATX_REG_BOARD_STATUS 0x4
+#define JAGUAR_ATX_REG_RESERVED1 0x5
+#define JAGUAR_ATX_REG_SET 0x6
+#define JAGUAR_ATX_REG_CLR 0x7
+#define JAGUAR_ATX_REG_EEPROM_MODE 0x9
+#define JAGUAR_ATX_REG_RESERVED2 0xa
+#define JAGUAR_ATX_REG_RESERVED3 0xb
+#define JAGUAR_ATX_REG_RESERVED4 0xc
+#define JAGUAR_ATX_REG_PHY_INTSTAT 0xd
+#define JAGUAR_ATX_REG_RESERVED5 0xe
+#define JAGUAR_ATX_REG_RESERVED6 0xf
+
+#define JAGUAR_ATX_CS0_ADDR 0xfc000000L
+
+extern unsigned long ja_fpga_base;
+
+#define JAGUAR_FPGA_WRITE(x,y) writeb(x, ja_fpga_base + JAGUAR_ATX_REG_##y)
+#define JAGUAR_FPGA_READ(x) readb(ja_fpga_base + JAGUAR_ATX_REG_##x)
+
+#endif
diff --git a/arch/mips/momentum/jaguar_atx/prom.c b/arch/mips/momentum/jaguar_atx/prom.c
new file mode 100644
index 0000000..fa5982a
--- /dev/null
+++ b/arch/mips/momentum/jaguar_atx/prom.c
@@ -0,0 +1,266 @@
+/*
+ * Copyright 2002 Momentum Computer Inc.
+ * Author: Matthew Dharm <mdharm@momenco.com>
+ *
+ * Louis Hamilton, Red Hat, Inc.
+ * hamilton@redhat.com [MIPS64 modifications]
+ *
+ * Based on Ocelot Linux port, which is
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: jsun@mvista.com or jsun@junsun.net
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * Added changes for SMP - Manish Lachwani (lachwani@pmc-sierra.com)
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/bootmem.h>
+
+#include <asm/addrspace.h>
+#include <asm/bootinfo.h>
+#include <asm/mv64340.h>
+#include <asm/pmon.h>
+
+#include "jaguar_atx_fpga.h"
+
+extern void ja_setup_console(void);
+
+struct callvectors *debug_vectors;
+
+extern unsigned long cpu_clock;
+
+const char *get_system_type(void)
+{
+ return "Momentum Jaguar-ATX";
+}
+
+#ifdef CONFIG_MV643XX_ETH
+extern unsigned char prom_mac_addr_base[6];
+
+static void burn_clocks(void)
+{
+ int i;
+
+ /* this loop should burn at least 1us -- this should be plenty */
+ for (i = 0; i < 0x10000; i++)
+ ;
+}
+
+static u8 exchange_bit(u8 val, u8 cs)
+{
+ /* place the data */
+ JAGUAR_FPGA_WRITE((val << 2) | cs, EEPROM_MODE);
+ burn_clocks();
+
+ /* turn the clock on */
+ JAGUAR_FPGA_WRITE((val << 2) | cs | 0x2, EEPROM_MODE);
+ burn_clocks();
+
+ /* turn the clock off and read-strobe */
+ JAGUAR_FPGA_WRITE((val << 2) | cs | 0x10, EEPROM_MODE);
+
+ /* return the data */
+ return ((JAGUAR_FPGA_READ(EEPROM_MODE) >> 3) & 0x1);
+}
+
+void get_mac(char dest[6])
+{
+ u8 read_opcode[12] = {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+ int i,j;
+
+ for (i = 0; i < 12; i++)
+ exchange_bit(read_opcode[i], 1);
+
+ for (j = 0; j < 6; j++) {
+ dest[j] = 0;
+ for (i = 0; i < 8; i++) {
+ dest[j] <<= 1;
+ dest[j] |= exchange_bit(0, 1);
+ }
+ }
+
+ /* turn off CS */
+ exchange_bit(0,0);
+}
+#endif
+
+#ifdef CONFIG_MIPS64
+
+unsigned long signext(unsigned long addr)
+{
+ addr &= 0xffffffff;
+ return (unsigned long)((int)addr);
+}
+
+void *get_arg(unsigned long args, int arc)
+{
+ unsigned long ul;
+ unsigned char *puc, uc;
+
+ args += (arc * 4);
+ ul = (unsigned long)signext(args);
+ puc = (unsigned char *)ul;
+ if (puc == 0)
+ return (void *)0;
+
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+ uc = *puc++;
+ l = (unsigned long)uc;
+ uc = *puc++;
+ ul |= (((unsigned long)uc) << 8);
+ uc = *puc++;
+ ul |= (((unsigned long)uc) << 16);
+ uc = *puc++;
+ ul |= (((unsigned long)uc) << 24);
+#else
+ uc = *puc++;
+ ul = ((unsigned long)uc) << 24;
+ uc = *puc++;
+ ul |= (((unsigned long)uc) << 16);
+ uc = *puc++;
+ ul |= (((unsigned long)uc) << 8);
+ uc = *puc++;
+ ul |= ((unsigned long)uc);
+#endif
+ ul = signext(ul);
+
+ return (void *)ul;
+}
+
+char *arg64(unsigned long addrin, int arg_index)
+{
+ unsigned long args;
+ char *p;
+
+ args = signext(addrin);
+ p = (char *)get_arg(args, arg_index);
+
+ return p;
+}
+#endif /* CONFIG_MIPS64 */
+
+/* PMON passes arguments in C main() style */
+void __init prom_init(void)
+{
+ int argc = fw_arg0;
+ char **arg = (char **) fw_arg1;
+ char **env = (char **) fw_arg2;
+ struct callvectors *cv = (struct callvectors *) fw_arg3;
+ int i;
+
+#ifdef CONFIG_SERIAL_8250_CONSOLE
+// ja_setup_console(); /* The very first thing. */
+#endif
+
+#ifdef CONFIG_MIPS64
+ char *ptr;
+
+ printk("Mips64 Jaguar-ATX\n");
+ /* save the PROM vectors for debugging use */
+ debug_vectors = (struct callvectors *)signext((unsigned long)cv);
+
+ /* arg[0] is "g", the rest is boot parameters */
+ arcs_cmdline[0] = '\0';
+
+ for (i = 1; i < argc; i++) {
+ ptr = (char *)arg64((unsigned long)arg, i);
+ if ((strlen(arcs_cmdline) + strlen(ptr) + 1) >=
+ sizeof(arcs_cmdline))
+ break;
+ strcat(arcs_cmdline, ptr);
+ strcat(arcs_cmdline, " ");
+ }
+
+ i = 0;
+ while (1) {
+ ptr = (char *)arg64((unsigned long)env, i);
+ if (! ptr)
+ break;
+
+ if (strncmp("gtbase", ptr, strlen("gtbase")) == 0) {
+ marvell_base = simple_strtol(ptr + strlen("gtbase="),
+ NULL, 16);
+
+ if ((marvell_base & 0xffffffff00000000) == 0)
+ marvell_base |= 0xffffffff00000000;
+
+ printk("marvell_base set to 0x%016lx\n", marvell_base);
+ }
+ if (strncmp("cpuclock", ptr, strlen("cpuclock")) == 0) {
+ cpu_clock = simple_strtol(ptr + strlen("cpuclock="),
+ NULL, 10);
+ printk("cpu_clock set to %d\n", cpu_clock);
+ }
+ i++;
+ }
+ printk("arcs_cmdline: %s\n", arcs_cmdline);
+
+#else /* CONFIG_MIPS64 */
+ /* save the PROM vectors for debugging use */
+ debug_vectors = cv;
+
+ /* arg[0] is "g", the rest is boot parameters */
+ arcs_cmdline[0] = '\0';
+ for (i = 1; i < argc; i++) {
+ if (strlen(arcs_cmdline) + strlen(arg[i] + 1)
+ >= sizeof(arcs_cmdline))
+ break;
+ strcat(arcs_cmdline, arg[i]);
+ strcat(arcs_cmdline, " ");
+ }
+
+ while (*env) {
+ if (strncmp("gtbase", *env, strlen("gtbase")) == 0) {
+ marvell_base = simple_strtol(*env + strlen("gtbase="),
+ NULL, 16);
+ }
+ if (strncmp("cpuclock", *env, strlen("cpuclock")) == 0) {
+ cpu_clock = simple_strtol(*env + strlen("cpuclock="),
+ NULL, 10);
+ }
+ env++;
+ }
+#endif /* CONFIG_MIPS64 */
+ mips_machgroup = MACH_GROUP_MOMENCO;
+ mips_machtype = MACH_MOMENCO_JAGUAR_ATX;
+
+#ifdef CONFIG_MV643XX_ETH
+ /* get the base MAC address for on-board ethernet ports */
+ get_mac(prom_mac_addr_base);
+#endif
+}
+
+void __init prom_free_prom_memory(void)
+{
+}
+
+void __init prom_fixup_mem_map(unsigned long start, unsigned long end)
+{
+}
+
+int prom_boot_secondary(int cpu, unsigned long sp, unsigned long gp)
+{
+ /* Clear the semaphore */
+ *(volatile uint32_t *)(0xbb000a68) = 0x80000000;
+
+ return 1;
+}
+
+void prom_init_secondary(void)
+{
+ clear_c0_config(CONF_CM_CMASK);
+ set_c0_config(0x2);
+
+ clear_c0_status(ST0_IM);
+ set_c0_status(0x1ffff);
+}
+
+void prom_smp_finish(void)
+{
+}
diff --git a/arch/mips/momentum/jaguar_atx/reset.c b/arch/mips/momentum/jaguar_atx/reset.c
new file mode 100644
index 0000000..4803948
--- /dev/null
+++ b/arch/mips/momentum/jaguar_atx/reset.c
@@ -0,0 +1,57 @@
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * Copyright (C) 1997, 2001 Ralf Baechle
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: jsun@mvista.com or jsun@junsun.net
+ *
+ * Copyright (C) 2002 Momentum Computer Inc.
+ * Author: Matthew Dharm <mdharm@momenco.com>
+ *
+ * Louis Hamilton, Red Hat, Inc.
+ * hamilton@redhat.com [MIPS64 modifications]
+ */
+#include <linux/config.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/reboot.h>
+#include <asm/system.h>
+#include <linux/delay.h>
+
+void momenco_jaguar_restart(char *command)
+{
+ /* base address of timekeeper portion of part */
+#ifdef CONFIG_MIPS64
+ void *nvram = (void*) 0xfffffffffc807000;
+#else
+ void *nvram = (void*) 0xfc807000;
+#endif
+ /* Ask the NVRAM/RTC/watchdog chip to assert reset in 1/16 second */
+ writeb(0x84, nvram + 0xff7);
+
+ /* wait for the watchdog to go off */
+ mdelay(100+(1000/16));
+
+ /* if the watchdog fails for some reason, let people know */
+ printk(KERN_NOTICE "Watchdog reset failed\n");
+}
+
+void momenco_jaguar_halt(void)
+{
+ printk(KERN_NOTICE "\n** You can safely turn off the power\n");
+ while (1)
+ __asm__(".set\tmips3\n\t"
+ "wait\n\t"
+ ".set\tmips0");
+}
+
+void momenco_jaguar_power_off(void)
+{
+ momenco_jaguar_halt();
+}
diff --git a/arch/mips/momentum/jaguar_atx/setup.c b/arch/mips/momentum/jaguar_atx/setup.c
new file mode 100644
index 0000000..30462e7
--- /dev/null
+++ b/arch/mips/momentum/jaguar_atx/setup.c
@@ -0,0 +1,474 @@
+/*
+ * BRIEF MODULE DESCRIPTION
+ * Momentum Computer Jaguar-ATX board dependent boot routines
+ *
+ * Copyright (C) 1996, 1997, 2001, 2004 Ralf Baechle (ralf@linux-mips.org)
+ * Copyright (C) 2000 RidgeRun, Inc.
+ * Copyright (C) 2001 Red Hat, Inc.
+ * Copyright (C) 2002 Momentum Computer
+ *
+ * Author: Matthew Dharm, Momentum Computer
+ * mdharm@momenco.com
+ *
+ * Louis Hamilton, Red Hat, Inc.
+ * hamilton@redhat.com [MIPS64 modifications]
+ *
+ * Author: RidgeRun, Inc.
+ * glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: jsun@mvista.com or jsun@junsun.net
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/config.h>
+#include <linux/bcd.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/bootmem.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/swap.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/timex.h>
+#include <linux/vmalloc.h>
+#include <asm/time.h>
+#include <asm/bootinfo.h>
+#include <asm/page.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/processor.h>
+#include <asm/ptrace.h>
+#include <asm/reboot.h>
+#include <asm/tlbflush.h>
+#include <asm/mv64340.h>
+
+#include "jaguar_atx_fpga.h"
+
+extern unsigned long mv64340_sram_base;
+unsigned long cpu_clock;
+
+/* These functions are used for rebooting or halting the machine*/
+extern void momenco_jaguar_restart(char *command);
+extern void momenco_jaguar_halt(void);
+extern void momenco_jaguar_power_off(void);
+
+void momenco_time_init(void);
+
+static char reset_reason;
+
+static inline unsigned long ENTRYLO(unsigned long paddr)
+{
+ return ((paddr & PAGE_MASK) |
+ (_PAGE_PRESENT | __READABLE | __WRITEABLE | _PAGE_GLOBAL |
+ _CACHE_UNCACHED)) >> 6;
+}
+
+void __init bus_error_init(void) { /* nothing */ }
+
+/*
+ * Load a few TLB entries for the MV64340 and perhiperals. The MV64340 is going
+ * to be hit on every IRQ anyway - there's absolutely no point in letting it be
+ * a random TLB entry, as it'll just cause needless churning of the TLB. And we
+ * use the other half for the serial port, which is just a PITA otherwise :)
+ *
+ * Device Physical Virtual
+ * MV64340 Internal Regs 0xf4000000 0xf4000000
+ * Ocelot-C[S] PLD (CS0) 0xfc000000 0xfc000000
+ * NVRAM (CS1) 0xfc800000 0xfc800000
+ * UARTs (CS2) 0xfd000000 0xfd000000
+ * Internal SRAM 0xfe000000 0xfe000000
+ * M-Systems DOC (CS3) 0xff000000 0xff000000
+ */
+
+static __init void wire_stupidity_into_tlb(void)
+{
+#ifdef CONFIG_MIPS32
+ write_c0_wired(0);
+ local_flush_tlb_all();
+
+ /* marvell and extra space */
+ add_wired_entry(ENTRYLO(0xf4000000), ENTRYLO(0xf4010000),
+ 0xf4000000UL, PM_64K);
+ /* fpga, rtc, and uart */
+ add_wired_entry(ENTRYLO(0xfc000000), ENTRYLO(0xfd000000),
+ 0xfc000000UL, PM_16M);
+// /* m-sys and internal SRAM */
+// add_wired_entry(ENTRYLO(0xfe000000), ENTRYLO(0xff000000),
+// 0xfe000000UL, PM_16M);
+
+ marvell_base = 0xf4000000;
+ //mv64340_sram_base = 0xfe000000; /* Currently unused */
+#endif
+}
+
+unsigned long marvell_base = 0xf4000000L;
+unsigned long ja_fpga_base = JAGUAR_ATX_CS0_ADDR;
+unsigned long uart_base = 0xfd000000L;
+static unsigned char *rtc_base = (unsigned char*) 0xfc800000L;
+
+EXPORT_SYMBOL(marvell_base);
+
+static __init int per_cpu_mappings(void)
+{
+ marvell_base = (unsigned long) ioremap(0xf4000000, 0x10000);
+ ja_fpga_base = (unsigned long) ioremap(JAGUAR_ATX_CS0_ADDR, 0x1000);
+ uart_base = (unsigned long) ioremap(0xfd000000UL, 0x1000);
+ rtc_base = ioremap(0xfc000000UL, 0x8000);
+ // ioremap(0xfe000000, 32 << 20);
+ write_c0_wired(0);
+ local_flush_tlb_all();
+ ja_setup_console();
+
+ return 0;
+}
+arch_initcall(per_cpu_mappings);
+
+unsigned long m48t37y_get_time(void)
+{
+ unsigned int year, month, day, hour, min, sec;
+
+ /* stop the update */
+ rtc_base[0x7ff8] = 0x40;
+
+ year = BCD2BIN(rtc_base[0x7fff]);
+ year += BCD2BIN(rtc_base[0x7ff1]) * 100;
+
+ month = BCD2BIN(rtc_base[0x7ffe]);
+
+ day = BCD2BIN(rtc_base[0x7ffd]);
+
+ hour = BCD2BIN(rtc_base[0x7ffb]);
+ min = BCD2BIN(rtc_base[0x7ffa]);
+ sec = BCD2BIN(rtc_base[0x7ff9]);
+
+ /* start the update */
+ rtc_base[0x7ff8] = 0x00;
+
+ return mktime(year, month, day, hour, min, sec);
+}
+
+int m48t37y_set_time(unsigned long sec)
+{
+ struct rtc_time tm;
+
+ /* convert to a more useful format -- note months count from 0 */
+ to_tm(sec, &tm);
+ tm.tm_mon += 1;
+
+ /* enable writing */
+ rtc_base[0x7ff8] = 0x80;
+
+ /* year */
+ rtc_base[0x7fff] = BIN2BCD(tm.tm_year % 100);
+ rtc_base[0x7ff1] = BIN2BCD(tm.tm_year / 100);
+
+ /* month */
+ rtc_base[0x7ffe] = BIN2BCD(tm.tm_mon);
+
+ /* day */
+ rtc_base[0x7ffd] = BIN2BCD(tm.tm_mday);
+
+ /* hour/min/sec */
+ rtc_base[0x7ffb] = BIN2BCD(tm.tm_hour);
+ rtc_base[0x7ffa] = BIN2BCD(tm.tm_min);
+ rtc_base[0x7ff9] = BIN2BCD(tm.tm_sec);
+
+ /* day of week -- not really used, but let's keep it up-to-date */
+ rtc_base[0x7ffc] = BIN2BCD(tm.tm_wday + 1);
+
+ /* disable writing */
+ rtc_base[0x7ff8] = 0x00;
+
+ return 0;
+}
+
+void momenco_timer_setup(struct irqaction *irq)
+{
+ setup_irq(8, irq);
+}
+
+/*
+ * Ugly but the least of all evils. TLB initialization did flush the TLB so
+ * We need to setup mappings again before we can touch the RTC.
+ */
+void momenco_time_init(void)
+{
+ wire_stupidity_into_tlb();
+
+ mips_hpt_frequency = cpu_clock / 2;
+ board_timer_setup = momenco_timer_setup;
+
+ rtc_get_time = m48t37y_get_time;
+ rtc_set_time = m48t37y_set_time;
+}
+
+static struct resource mv_pci_io_mem0_resource = {
+ .name = "MV64340 PCI0 IO MEM",
+ .flags = IORESOURCE_IO
+};
+
+static struct resource mv_pci_mem0_resource = {
+ .name = "MV64340 PCI0 MEM",
+ .flags = IORESOURCE_MEM
+};
+
+static struct mv_pci_controller mv_bus0_controller = {
+ .pcic = {
+ .pci_ops = &mv_pci_ops,
+ .mem_resource = &mv_pci_mem0_resource,
+ .io_resource = &mv_pci_io_mem0_resource,
+ },
+ .config_addr = MV64340_PCI_0_CONFIG_ADDR,
+ .config_vreg = MV64340_PCI_0_CONFIG_DATA_VIRTUAL_REG,
+};
+
+static uint32_t mv_io_base, mv_io_size;
+
+static void ja_pci0_init(void)
+{
+ uint32_t mem0_base, mem0_size;
+ uint32_t io_base, io_size;
+
+ io_base = MV_READ(MV64340_PCI_0_IO_BASE_ADDR) << 16;
+ io_size = (MV_READ(MV64340_PCI_0_IO_SIZE) + 1) << 16;
+ mem0_base = MV_READ(MV64340_PCI_0_MEMORY0_BASE_ADDR) << 16;
+ mem0_size = (MV_READ(MV64340_PCI_0_MEMORY0_SIZE) + 1) << 16;
+
+ mv_pci_io_mem0_resource.start = 0;
+ mv_pci_io_mem0_resource.end = io_size - 1;
+ mv_pci_mem0_resource.start = mem0_base;
+ mv_pci_mem0_resource.end = mem0_base + mem0_size - 1;
+ mv_bus0_controller.pcic.mem_offset = mem0_base;
+ mv_bus0_controller.pcic.io_offset = 0;
+
+ ioport_resource.end = io_size - 1;
+
+ register_pci_controller(&mv_bus0_controller.pcic);
+
+ mv_io_base = io_base;
+ mv_io_size = io_size;
+}
+
+static struct resource mv_pci_io_mem1_resource = {
+ .name = "MV64340 PCI1 IO MEM",
+ .flags = IORESOURCE_IO
+};
+
+static struct resource mv_pci_mem1_resource = {
+ .name = "MV64340 PCI1 MEM",
+ .flags = IORESOURCE_MEM
+};
+
+static struct mv_pci_controller mv_bus1_controller = {
+ .pcic = {
+ .pci_ops = &mv_pci_ops,
+ .mem_resource = &mv_pci_mem1_resource,
+ .io_resource = &mv_pci_io_mem1_resource,
+ },
+ .config_addr = MV64340_PCI_1_CONFIG_ADDR,
+ .config_vreg = MV64340_PCI_1_CONFIG_DATA_VIRTUAL_REG,
+};
+
+static __init void ja_pci1_init(void)
+{
+ uint32_t mem0_base, mem0_size;
+ uint32_t io_base, io_size;
+
+ io_base = MV_READ(MV64340_PCI_1_IO_BASE_ADDR) << 16;
+ io_size = (MV_READ(MV64340_PCI_1_IO_SIZE) + 1) << 16;
+ mem0_base = MV_READ(MV64340_PCI_1_MEMORY0_BASE_ADDR) << 16;
+ mem0_size = (MV_READ(MV64340_PCI_1_MEMORY0_SIZE) + 1) << 16;
+
+ /*
+ * Here we assume the I/O window of second bus to be contiguous with
+ * the first. A gap is no problem but would waste address space for
+ * remapping the port space.
+ */
+ mv_pci_io_mem1_resource.start = mv_io_size;
+ mv_pci_io_mem1_resource.end = mv_io_size + io_size - 1;
+ mv_pci_mem1_resource.start = mem0_base;
+ mv_pci_mem1_resource.end = mem0_base + mem0_size - 1;
+ mv_bus1_controller.pcic.mem_offset = mem0_base;
+ mv_bus1_controller.pcic.io_offset = 0;
+
+ ioport_resource.end = io_base + io_size -mv_io_base - 1;
+
+ register_pci_controller(&mv_bus1_controller.pcic);
+
+ mv_io_size = io_base + io_size - mv_io_base;
+}
+
+static __init int __init ja_pci_init(void)
+{
+ unsigned long io_v_base;
+ uint32_t enable;
+
+ enable = ~MV_READ(MV64340_BASE_ADDR_ENABLE);
+
+ /*
+ * We require at least one enabled I/O or PCI memory window or we
+ * will ignore this PCI bus. We ignore PCI windows 1, 2 and 3.
+ */
+ if (enable & (0x01 << 9) || enable & (0x01 << 10))
+ ja_pci0_init();
+
+ if (enable & (0x01 << 14) || enable & (0x01 << 15))
+ ja_pci1_init();
+
+ if (mv_io_size) {
+ io_v_base = (unsigned long) ioremap(mv_io_base, mv_io_size);
+ if (!io_v_base)
+ panic("Could not ioremap I/O port range");
+
+ set_io_port_base(io_v_base);
+ }
+
+ return 0;
+}
+
+arch_initcall(ja_pci_init);
+
+static int __init momenco_jaguar_atx_setup(void)
+{
+ unsigned int tmpword;
+
+ board_time_init = momenco_time_init;
+
+ _machine_restart = momenco_jaguar_restart;
+ _machine_halt = momenco_jaguar_halt;
+ _machine_power_off = momenco_jaguar_power_off;
+
+ /*
+ * initrd_start = (ulong)jaguar_initrd_start;
+ * initrd_end = (ulong)jaguar_initrd_start + (ulong)jaguar_initrd_size;
+ * initrd_below_start_ok = 1;
+ */
+
+ wire_stupidity_into_tlb();
+
+ /*
+ * shut down ethernet ports, just to be sure our memory doesn't get
+ * corrupted by random ethernet traffic.
+ */
+ MV_WRITE(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(0), 0xff << 8);
+ MV_WRITE(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(1), 0xff << 8);
+ MV_WRITE(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(2), 0xff << 8);
+ MV_WRITE(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(0), 0xff << 8);
+ MV_WRITE(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(1), 0xff << 8);
+ MV_WRITE(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(2), 0xff << 8);
+ while (MV_READ(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(0)) & 0xff);
+ while (MV_READ(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(1)) & 0xff);
+ while (MV_READ(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(2)) & 0xff);
+ while (MV_READ(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(0)) & 0xff);
+ while (MV_READ(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(1)) & 0xff);
+ while (MV_READ(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(2)) & 0xff);
+ MV_WRITE(MV64340_ETH_PORT_SERIAL_CONTROL_REG(0),
+ MV_READ(MV64340_ETH_PORT_SERIAL_CONTROL_REG(0)) & ~1);
+ MV_WRITE(MV64340_ETH_PORT_SERIAL_CONTROL_REG(1),
+ MV_READ(MV64340_ETH_PORT_SERIAL_CONTROL_REG(1)) & ~1);
+ MV_WRITE(MV64340_ETH_PORT_SERIAL_CONTROL_REG(2),
+ MV_READ(MV64340_ETH_PORT_SERIAL_CONTROL_REG(2)) & ~1);
+
+ /* Turn off the Bit-Error LED */
+ JAGUAR_FPGA_WRITE(0x80, CLR);
+
+ tmpword = JAGUAR_FPGA_READ(BOARDREV);
+ if (tmpword < 26)
+ printk("Momentum Jaguar-ATX: Board Assembly Rev. %c\n",
+ 'A'+tmpword);
+ else
+ printk("Momentum Jaguar-ATX: Board Assembly Revision #0x%x\n",
+ tmpword);
+
+ tmpword = JAGUAR_FPGA_READ(FPGA_REV);
+ printk("FPGA Rev: %d.%d\n", tmpword>>4, tmpword&15);
+ tmpword = JAGUAR_FPGA_READ(RESET_STATUS);
+ printk("Reset reason: 0x%x\n", tmpword);
+ switch (tmpword) {
+ case 0x1:
+ printk(" - Power-up reset\n");
+ break;
+ case 0x2:
+ printk(" - Push-button reset\n");
+ break;
+ case 0x8:
+ printk(" - Watchdog reset\n");
+ break;
+ case 0x10:
+ printk(" - JTAG reset\n");
+ break;
+ default:
+ printk(" - Unknown reset cause\n");
+ }
+ reset_reason = tmpword;
+ JAGUAR_FPGA_WRITE(0xff, RESET_STATUS);
+
+ tmpword = JAGUAR_FPGA_READ(BOARD_STATUS);
+ printk("Board Status register: 0x%02x\n", tmpword);
+ printk(" - User jumper: %s\n", (tmpword & 0x80)?"installed":"absent");
+ printk(" - Boot flash write jumper: %s\n", (tmpword&0x40)?"installed":"absent");
+
+ /* 256MiB of RM9000x2 DDR */
+// add_memory_region(0x0, 0x100<<20, BOOT_MEM_RAM);
+
+ /* 128MiB of MV-64340 DDR */
+// add_memory_region(0x100<<20, 0x80<<20, BOOT_MEM_RAM);
+
+ /* XXX Memory configuration should be picked up from PMON2k */
+#ifdef CONFIG_JAGUAR_DMALOW
+ printk("Jaguar ATX DMA-low mode set\n");
+ add_memory_region(0x00000000, 0x08000000, BOOT_MEM_RAM);
+ add_memory_region(0x08000000, 0x10000000, BOOT_MEM_RAM);
+#else
+ /* 128MiB of MV-64340 DDR RAM */
+ printk("Jaguar ATX DMA-low mode is not set\n");
+ add_memory_region(0x100<<20, 0x80<<20, BOOT_MEM_RAM);
+#endif
+
+#ifdef GEMDEBUG_TRACEBUFFER
+ {
+ unsigned int tbControl;
+ tbControl =
+ 0 << 26 | /* post trigger delay 0 */
+ 0x2 << 16 | /* sequential trace mode */
+ // 0x0 << 16 | /* non-sequential trace mode */
+ // 0xf << 4 | /* watchpoints disabled */
+ 2 << 2 | /* armed */
+ 2 ; /* interrupt disabled */
+ printk ("setting tbControl = %08lx\n", tbControl);
+ write_32bit_cp0_set1_register($22, tbControl);
+ __asm__ __volatile__(".set noreorder\n\t" \
+ "nop; nop; nop; nop; nop; nop;\n\t" \
+ "nop; nop; nop; nop; nop; nop;\n\t" \
+ ".set reorder\n\t");
+
+ }
+#endif
+
+ return 0;
+}
+
+early_initcall(momenco_jaguar_atx_setup);
diff --git a/arch/mips/momentum/ocelot_3/Makefile b/arch/mips/momentum/ocelot_3/Makefile
new file mode 100644
index 0000000..aab8fd8
--- /dev/null
+++ b/arch/mips/momentum/ocelot_3/Makefile
@@ -0,0 +1,8 @@
+#
+# Makefile for Momentum Computer's Ocelot-3 board.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+obj-y += int-handler.o irq.o prom.o reset.o setup.o
diff --git a/arch/mips/momentum/ocelot_3/int-handler.S b/arch/mips/momentum/ocelot_3/int-handler.S
new file mode 100644
index 0000000..4522f09
--- /dev/null
+++ b/arch/mips/momentum/ocelot_3/int-handler.S
@@ -0,0 +1,137 @@
+/*
+ * Copyright 2002 Momentum Computer Inc.
+ * Author: Matthew Dharm <mdharm@momenco.com>
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: jsun@mvista.com or jsun@junsun.net
+ *
+ * Copyright 2004 PMC-Sierra
+ * Author: Manish Lachwani (lachwani@pmc-sierra.com)
+ *
+ * Copyright (C) 2004 MontaVista Software Inc.
+ * Author: Manish Lachwani, mlachwani@mvista.com
+ *
+ * First-level interrupt dispatcher for Ocelot-3 board.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+#include <asm/asm.h>
+#include <asm/mipsregs.h>
+#include <asm/addrspace.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+
+/*
+ * First level interrupt dispatcher for Ocelot-3 board
+ */
+ .align 5
+ NESTED(ocelot3_handle_int, PT_SIZE, sp)
+ SAVE_ALL
+ CLI
+ .set at
+
+ mfc0 t0, CP0_CAUSE
+ mfc0 t2, CP0_STATUS
+
+ and t0, t2
+
+ andi t1, t0, STATUSF_IP0 /* sw0 software interrupt (IRQ0) */
+ bnez t1, ll_sw0_irq
+
+ andi t1, t0, STATUSF_IP1 /* sw1 software interrupt (IRQ1) */
+ bnez t1, ll_sw1_irq
+
+ andi t1, t0, STATUSF_IP2 /* int0 hardware line (IRQ2) */
+ bnez t1, ll_pci0slot1_irq
+
+ andi t1, t0, STATUSF_IP3 /* int1 hardware line (IRQ3) */
+ bnez t1, ll_pci0slot2_irq
+
+ andi t1, t0, STATUSF_IP4 /* int2 hardware line (IRQ4) */
+ bnez t1, ll_pci1slot1_irq
+
+ andi t1, t0, STATUSF_IP5 /* int3 hardware line (IRQ5) */
+ bnez t1, ll_pci1slot2_irq
+
+ andi t1, t0, STATUSF_IP6 /* int4 hardware line (IRQ6) */
+ bnez t1, ll_uart_irq
+
+ andi t1, t0, STATUSF_IP7 /* cpu timer (IRQ7) */
+ bnez t1, ll_cputimer_irq
+
+ /* now look at extended interrupts */
+ mfc0 t0, CP0_CAUSE
+ cfc0 t1, CP0_S1_INTCONTROL
+
+ /* shift the mask 8 bits left to line up the bits */
+ sll t2, t1, 8
+
+ and t0, t2
+ srl t0, t0, 16
+
+ andi t1, t0, STATUSF_IP8 /* int6 hardware line (IRQ9) */
+ bnez t1, ll_mv64340_decode_irq
+
+ .set reorder
+
+ /* wrong alarm or masked ... */
+ j spurious_interrupt
+ nop
+ END(ocelot3_handle_int)
+
+ .align 5
+ll_sw0_irq:
+ li a0, 0 /* IRQ 1 */
+ move a1, sp
+ jal do_IRQ
+ j ret_from_irq
+ll_sw1_irq:
+ li a0, 1 /* IRQ 2 */
+ move a1, sp
+ jal do_IRQ
+ j ret_from_irq
+
+ll_pci0slot1_irq:
+ li a0, 2 /* IRQ 3 */
+ move a1, sp
+ jal do_IRQ
+ j ret_from_irq
+
+ll_pci0slot2_irq:
+ li a0, 3 /* IRQ 4 */
+ move a1, sp
+ jal do_IRQ
+ j ret_from_irq
+
+ll_pci1slot1_irq:
+ li a0, 4 /* IRQ 5 */
+ move a1, sp
+ jal do_IRQ
+ j ret_from_irq
+
+ll_pci1slot2_irq:
+ li a0, 5 /* IRQ 6 */
+ move a1, sp
+ jal do_IRQ
+ j ret_from_irq
+
+ll_uart_irq:
+ li a0, 6 /* IRQ 7 */
+ move a1, sp
+ jal do_IRQ
+ j ret_from_irq
+
+ll_cputimer_irq:
+ li a0, 7 /* IRQ 8 */
+ move a1, sp
+ jal do_IRQ
+ j ret_from_irq
+
+ll_mv64340_decode_irq:
+ move a0, sp
+ jal ll_mv64340_irq
+ j ret_from_irq
+
diff --git a/arch/mips/momentum/ocelot_3/irq.c b/arch/mips/momentum/ocelot_3/irq.c
new file mode 100644
index 0000000..42464db
--- /dev/null
+++ b/arch/mips/momentum/ocelot_3/irq.c
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2000 RidgeRun, Inc.
+ * Author: RidgeRun, Inc.
+ * glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
+ * Copyright (C) 2000, 2001 Ralf Baechle (ralf@gnu.org)
+ *
+ * Copyright 2004 PMC-Sierra
+ * Author: Manish Lachwani (lachwani@pmc-sierra.com)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Copyright (C) 2004 MontaVista Software Inc.
+ * Author: Manish Lachwani, mlachwani@mvista.com
+ *
+ */
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel_stat.h>
+#include <linux/module.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/timex.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+#include <asm/bitops.h>
+#include <asm/bootinfo.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mipsregs.h>
+#include <asm/system.h>
+
+extern asmlinkage void ocelot3_handle_int(void);
+
+static struct irqaction cascade_mv64340 = {
+ no_action, SA_INTERRUPT, CPU_MASK_NONE, "MV64340-Cascade", NULL, NULL
+};
+
+void __init arch_init_irq(void)
+{
+ /*
+ * Clear all of the interrupts while we change the able around a bit.
+ * int-handler is not on bootstrap
+ */
+ clear_c0_status(ST0_IM | ST0_BEV);
+
+ /* Sets the first-level interrupt dispatcher. */
+ set_except_vector(0, ocelot3_handle_int);
+ mips_cpu_irq_init(0);
+ rm7k_cpu_irq_init(8);
+
+ /* set up the cascading interrupts */
+ setup_irq(8, &cascade_mv64340); /* unmask intControl IM8, IRQ 9 */
+ mv64340_irq_init(16);
+
+ set_c0_status(ST0_IM); /* IE in the status register */
+
+}
diff --git a/arch/mips/momentum/ocelot_3/ocelot_3_fpga.h b/arch/mips/momentum/ocelot_3/ocelot_3_fpga.h
new file mode 100644
index 0000000..227e429
--- /dev/null
+++ b/arch/mips/momentum/ocelot_3/ocelot_3_fpga.h
@@ -0,0 +1,57 @@
+/*
+ * Ocelot-3 Board Register Definitions
+ *
+ * (C) 2002 Momentum Computer Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Louis Hamilton, Red Hat, Inc.
+ * hamilton@redhat.com [MIPS64 modifications]
+ *
+ * Copyright (C) 2004 MontaVista Software Inc.
+ * Author: Manish Lachwani, mlachwani@mvista.com
+ */
+
+#ifndef __OCELOT_3_FPGA_H__
+#define __OCELOT_3_FPGA_H__
+
+#define OCELOT_3_REG_BOARDREV 0x0
+#define OCELOT_3_REG_FPGA_REV 0x1
+#define OCELOT_3_REG_FPGA_TYPE 0x2
+#define OCELOT_3_REG_RESET_STATUS 0x3
+#define OCELOT_3_REG_BOARD_STATUS 0x4
+#define OCELOT_3_REG_CPCI_ID 0x5
+#define OCELOT_3_REG_SET 0x6
+#define OCELOT_3_REG_CLR 0x7
+#define OCELOT_3_REG_EEPROM_MODE 0x9
+#define OCELOT_3_REG_INTMASK 0xa
+#define OCELOT_3_REG_INTSTAT 0xb
+#define OCELOT_3_REG_UART_INTMASK 0xc
+#define OCELOT_3_REG_UART_INTSTAT 0xd
+#define OCELOT_3_REG_INTSET 0xe
+#define OCELOT_3_REG_INTCLR 0xf
+
+extern unsigned long ocelot_fpga_base;
+
+#define OCELOT_FPGA_WRITE(x, y) writeb(x, ocelot_fpga_base + OCELOT_3_REG_##y)
+#define OCELOT_FPGA_READ(x) readb(ocelot_fpga_base + OCELOT_3_REG_##x)
+
+#endif
diff --git a/arch/mips/momentum/ocelot_3/prom.c b/arch/mips/momentum/ocelot_3/prom.c
new file mode 100644
index 0000000..89c17a0
--- /dev/null
+++ b/arch/mips/momentum/ocelot_3/prom.c
@@ -0,0 +1,248 @@
+/*
+ * Copyright 2002 Momentum Computer Inc.
+ * Author: Matthew Dharm <mdharm@momenco.com>
+ *
+ * Louis Hamilton, Red Hat, Inc.
+ * hamilton@redhat.com [MIPS64 modifications]
+ *
+ * Copyright 2004 PMC-Sierra
+ * Author: Manish Lachwani (lachwani@pmc-sierra.com)
+ *
+ * Based on Ocelot Linux port, which is
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: jsun@mvista.com or jsun@junsun.net
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * Copyright (C) 2004 MontaVista Software Inc.
+ * Author: Manish Lachwani, mlachwani@mvista.com
+ *
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/bootmem.h>
+#include <linux/mv643xx.h>
+
+#include <asm/addrspace.h>
+#include <asm/bootinfo.h>
+#include <asm/pmon.h>
+#include "ocelot_3_fpga.h"
+
+struct callvectors* debug_vectors;
+extern unsigned long marvell_base;
+extern unsigned long cpu_clock;
+
+#ifdef CONFIG_MV643XX_ETH
+extern unsigned char prom_mac_addr_base[6];
+#endif
+
+const char *get_system_type(void)
+{
+ return "Momentum Ocelot-3";
+}
+
+#ifdef CONFIG_MV643XX_ETH
+void burn_clocks(void)
+{
+ int i;
+
+ /* this loop should burn at least 1us -- this should be plenty */
+ for (i = 0; i < 0x10000; i++)
+ ;
+}
+
+u8 exchange_bit(u8 val, u8 cs)
+{
+ /* place the data */
+ OCELOT_FPGA_WRITE((val << 2) | cs, EEPROM_MODE);
+ burn_clocks();
+
+ /* turn the clock on */
+ OCELOT_FPGA_WRITE((val << 2) | cs | 0x2, EEPROM_MODE);
+ burn_clocks();
+
+ /* turn the clock off and read-strobe */
+ OCELOT_FPGA_WRITE((val << 2) | cs | 0x10, EEPROM_MODE);
+
+ /* return the data */
+ return ((OCELOT_FPGA_READ(EEPROM_MODE) >> 3) & 0x1);
+}
+
+void get_mac(char dest[6])
+{
+ u8 read_opcode[12] = {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+ int i,j;
+
+ for (i = 0; i < 12; i++)
+ exchange_bit(read_opcode[i], 1);
+
+ for (j = 0; j < 6; j++) {
+ dest[j] = 0;
+ for (i = 0; i < 8; i++) {
+ dest[j] <<= 1;
+ dest[j] |= exchange_bit(0, 1);
+ }
+ }
+
+ /* turn off CS */
+ exchange_bit(0,0);
+}
+#endif
+
+
+#ifdef CONFIG_MIPS64
+
+unsigned long signext(unsigned long addr)
+{
+ addr &= 0xffffffff;
+ return (unsigned long)((int)addr);
+}
+
+void *get_arg(unsigned long args, int arc)
+{
+ unsigned long ul;
+ unsigned char *puc, uc;
+
+ args += (arc * 4);
+ ul = (unsigned long)signext(args);
+ puc = (unsigned char *)ul;
+ if (puc == 0)
+ return (void *)0;
+
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+ uc = *puc++;
+ ul = (unsigned long)uc;
+ uc = *puc++;
+ ul |= (((unsigned long)uc) << 8);
+ uc = *puc++;
+ ul |= (((unsigned long)uc) << 16);
+ uc = *puc++;
+ ul |= (((unsigned long)uc) << 24);
+#else /* CONFIG_CPU_LITTLE_ENDIAN */
+ uc = *puc++;
+ ul = ((unsigned long)uc) << 24;
+ uc = *puc++;
+ ul |= (((unsigned long)uc) << 16);
+ uc = *puc++;
+ ul |= (((unsigned long)uc) << 8);
+ uc = *puc++;
+ ul |= ((unsigned long)uc);
+#endif /* CONFIG_CPU_LITTLE_ENDIAN */
+ ul = signext(ul);
+ return (void *)ul;
+}
+
+char *arg64(unsigned long addrin, int arg_index)
+{
+ unsigned long args;
+ char *p;
+
+ args = signext(addrin);
+ p = (char *)get_arg(args, arg_index);
+
+ return p;
+}
+#endif /* CONFIG_MIPS64 */
+
+void __init prom_init(void)
+{
+ int argc = fw_arg0;
+ char **arg = (char **) fw_arg1;
+ char **env = (char **) fw_arg2;
+ struct callvectors *cv = (struct callvectors *) fw_arg3;
+ int i;
+
+#ifdef CONFIG_MIPS64
+ char *ptr;
+ printk("prom_init - MIPS64\n");
+
+ /* save the PROM vectors for debugging use */
+ debug_vectors = (struct callvectors *)signext((unsigned long)cv);
+
+ /* arg[0] is "g", the rest is boot parameters */
+ arcs_cmdline[0] = '\0';
+
+ for (i = 1; i < argc; i++) {
+ ptr = (char *)arg64((unsigned long)arg, i);
+ if ((strlen(arcs_cmdline) + strlen(ptr) + 1) >=
+ sizeof(arcs_cmdline))
+ break;
+ strcat(arcs_cmdline, ptr);
+ strcat(arcs_cmdline, " ");
+ }
+ i = 0;
+
+ while (1) {
+ ptr = (char *)arg64((unsigned long)env, i);
+ if (! ptr)
+ break;
+
+ if (strncmp("gtbase", ptr, strlen("gtbase")) == 0) {
+ marvell_base = simple_strtol(ptr + strlen("gtbase="),
+ NULL, 16);
+
+ if ((marvell_base & 0xffffffff00000000) == 0)
+ marvell_base |= 0xffffffff00000000;
+
+ printk("marvell_base set to 0x%016lx\n", marvell_base);
+ }
+ if (strncmp("cpuclock", ptr, strlen("cpuclock")) == 0) {
+ cpu_clock = simple_strtol(ptr + strlen("cpuclock="),
+ NULL, 10);
+ printk("cpu_clock set to %d\n", cpu_clock);
+ }
+ i++;
+ }
+ printk("arcs_cmdline: %s\n", arcs_cmdline);
+
+#else /* CONFIG_MIPS64 */
+
+ /* save the PROM vectors for debugging use */
+ debug_vectors = cv;
+
+ /* arg[0] is "g", the rest is boot parameters */
+ arcs_cmdline[0] = '\0';
+ for (i = 1; i < argc; i++) {
+ if (strlen(arcs_cmdline) + strlen(arg[i] + 1)
+ >= sizeof(arcs_cmdline))
+ break;
+ strcat(arcs_cmdline, arg[i]);
+ strcat(arcs_cmdline, " ");
+ }
+
+ while (*env) {
+ if (strncmp("gtbase", *env, strlen("gtbase")) == 0) {
+ marvell_base = simple_strtol(*env + strlen("gtbase="),
+ NULL, 16);
+ }
+ if (strncmp("cpuclock", *env, strlen("cpuclock")) == 0) {
+ cpu_clock = simple_strtol(*env + strlen("cpuclock="),
+ NULL, 10);
+ }
+ env++;
+ }
+#endif /* CONFIG_MIPS64 */
+
+ mips_machgroup = MACH_GROUP_MOMENCO;
+ mips_machtype = MACH_MOMENCO_OCELOT_3;
+
+#ifdef CONFIG_MV643XX_ETH
+ /* get the base MAC address for on-board ethernet ports */
+ get_mac(prom_mac_addr_base);
+#endif
+
+#ifndef CONFIG_MIPS64
+ debug_vectors->printf("Booting Linux kernel...\n");
+#endif
+}
+
+void __init prom_free_prom_memory(void)
+{
+}
+
+void __init prom_fixup_mem_map(unsigned long start, unsigned long end)
+{
+}
diff --git a/arch/mips/momentum/ocelot_3/reset.c b/arch/mips/momentum/ocelot_3/reset.c
new file mode 100644
index 0000000..72b4423
--- /dev/null
+++ b/arch/mips/momentum/ocelot_3/reset.c
@@ -0,0 +1,59 @@
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * Copyright (C) 1997, 01, 05 Ralf Baechle
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: jsun@mvista.com or jsun@junsun.net
+ *
+ * Copyright (C) 2002 Momentum Computer Inc.
+ * Author: Matthew Dharm <mdharm@momenco.com>
+ *
+ * Louis Hamilton, Red Hat, Inc.
+ * hamilton@redhat.com [MIPS64 modifications]
+ *
+ * Copyright 2004 PMC-Sierra
+ * Author: Manish Lachwani (lachwani@pmc-sierra.com)
+ *
+ * Copyright (C) 2004 MontaVista Software Inc.
+ * Author: Manish Lachwani, mlachwani@mvista.com
+ */
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/delay.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/reboot.h>
+#include <asm/system.h>
+
+void momenco_ocelot_restart(char *command)
+{
+ /* base address of timekeeper portion of part */
+ void *nvram = (void *) 0xfc807000L;
+
+ /* Ask the NVRAM/RTC/watchdog chip to assert reset in 1/16 second */
+ writeb(0x84, nvram + 0xff7);
+
+ /* wait for the watchdog to go off */
+ mdelay(100+(1000/16));
+
+ /* if the watchdog fails for some reason, let people know */
+ printk(KERN_NOTICE "Watchdog reset failed\n");
+}
+
+void momenco_ocelot_halt(void)
+{
+ printk(KERN_NOTICE "\n** You can safely turn off the power\n");
+ while (1)
+ __asm__(".set\tmips3\n\t"
+ "wait\n\t"
+ ".set\tmips0");
+}
+
+void momenco_ocelot_power_off(void)
+{
+ momenco_ocelot_halt();
+}
diff --git a/arch/mips/momentum/ocelot_3/setup.c b/arch/mips/momentum/ocelot_3/setup.c
new file mode 100644
index 0000000..ce2efcb
--- /dev/null
+++ b/arch/mips/momentum/ocelot_3/setup.c
@@ -0,0 +1,398 @@
+/*
+ * setup.c
+ *
+ * BRIEF MODULE DESCRIPTION
+ * Momentum Computer Ocelot-3 board dependent boot routines
+ *
+ * Copyright (C) 1996, 1997, 01, 05 Ralf Baechle
+ * Copyright (C) 2000 RidgeRun, Inc.
+ * Copyright (C) 2001 Red Hat, Inc.
+ * Copyright (C) 2002 Momentum Computer
+ *
+ * Author: Matthew Dharm, Momentum Computer
+ * mdharm@momenco.com
+ *
+ * Louis Hamilton, Red Hat, Inc.
+ * hamilton@redhat.com [MIPS64 modifications]
+ *
+ * Author: RidgeRun, Inc.
+ * glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: jsun@mvista.com or jsun@junsun.net
+ *
+ * Copyright 2004 PMC-Sierra
+ * Author: Manish Lachwani (lachwani@pmc-sierra.com)
+ *
+ * Copyright (C) 2004 MontaVista Software Inc.
+ * Author: Manish Lachwani, mlachwani@mvista.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/mc146818rtc.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/timex.h>
+#include <linux/bootmem.h>
+#include <linux/mv643xx.h>
+#include <asm/time.h>
+#include <asm/page.h>
+#include <asm/bootinfo.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/pci.h>
+#include <asm/processor.h>
+#include <asm/ptrace.h>
+#include <asm/reboot.h>
+#include <asm/mc146818rtc.h>
+#include <asm/tlbflush.h>
+#include "ocelot_3_fpga.h"
+
+/* Marvell Discovery Register Base */
+unsigned long marvell_base = (signed)0xf4000000;
+
+/* CPU clock */
+unsigned long cpu_clock;
+
+/* RTC/NVRAM */
+unsigned char* rtc_base = (unsigned char*)(signed)0xfc800000;
+
+/* FPGA Base */
+unsigned long ocelot_fpga_base = (signed)0xfc000000;
+
+/* Serial base */
+unsigned long uart_base = (signed)0xfd000000;
+
+/*
+ * Marvell Discovery SRAM. This is one place where Ethernet
+ * Tx and Rx descriptors can be placed to improve performance
+ */
+extern unsigned long mv64340_sram_base;
+
+/* These functions are used for rebooting or halting the machine*/
+extern void momenco_ocelot_restart(char *command);
+extern void momenco_ocelot_halt(void);
+extern void momenco_ocelot_power_off(void);
+
+void momenco_time_init(void);
+static char reset_reason;
+
+void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1,
+ unsigned long entryhi, unsigned long pagemask);
+
+static inline unsigned long ENTRYLO(unsigned long paddr)
+{
+ return ((paddr & PAGE_MASK) |
+ (_PAGE_PRESENT | __READABLE | __WRITEABLE | _PAGE_GLOBAL |
+ _CACHE_UNCACHED)) >> 6;
+}
+
+void __init bus_error_init(void)
+{
+ /* nothing */
+}
+
+/*
+ * setup code for a handoff from a version 2 PMON 2000 PROM
+ */
+void setup_wired_tlb_entries(void)
+{
+ write_c0_wired(0);
+ local_flush_tlb_all();
+
+ /* marvell and extra space */
+ add_wired_entry(ENTRYLO(0xf4000000), ENTRYLO(0xf4010000), (signed)0xf4000000, PM_64K);
+
+ /* fpga, rtc, and uart */
+ add_wired_entry(ENTRYLO(0xfc000000), ENTRYLO(0xfd000000), (signed)0xfc000000, PM_16M);
+}
+
+#define CONV_BCD_TO_BIN(val) (((val) & 0xf) + (((val) >> 4) * 10))
+#define CONV_BIN_TO_BCD(val) (((val) % 10) + (((val) / 10) << 4))
+
+unsigned long m48t37y_get_time(void)
+{
+ unsigned int year, month, day, hour, min, sec;
+
+ /* stop the update */
+ rtc_base[0x7ff8] = 0x40;
+
+ year = CONV_BCD_TO_BIN(rtc_base[0x7fff]);
+ year += CONV_BCD_TO_BIN(rtc_base[0x7ff1]) * 100;
+
+ month = CONV_BCD_TO_BIN(rtc_base[0x7ffe]);
+
+ day = CONV_BCD_TO_BIN(rtc_base[0x7ffd]);
+
+ hour = CONV_BCD_TO_BIN(rtc_base[0x7ffb]);
+ min = CONV_BCD_TO_BIN(rtc_base[0x7ffa]);
+ sec = CONV_BCD_TO_BIN(rtc_base[0x7ff9]);
+
+ /* start the update */
+ rtc_base[0x7ff8] = 0x00;
+
+ return mktime(year, month, day, hour, min, sec);
+}
+
+int m48t37y_set_time(unsigned long sec)
+{
+ struct rtc_time tm;
+
+ /* convert to a more useful format -- note months count from 0 */
+ to_tm(sec, &tm);
+ tm.tm_mon += 1;
+
+ /* enable writing */
+ rtc_base[0x7ff8] = 0x80;
+
+ /* year */
+ rtc_base[0x7fff] = CONV_BIN_TO_BCD(tm.tm_year % 100);
+ rtc_base[0x7ff1] = CONV_BIN_TO_BCD(tm.tm_year / 100);
+
+ /* month */
+ rtc_base[0x7ffe] = CONV_BIN_TO_BCD(tm.tm_mon);
+
+ /* day */
+ rtc_base[0x7ffd] = CONV_BIN_TO_BCD(tm.tm_mday);
+
+ /* hour/min/sec */
+ rtc_base[0x7ffb] = CONV_BIN_TO_BCD(tm.tm_hour);
+ rtc_base[0x7ffa] = CONV_BIN_TO_BCD(tm.tm_min);
+ rtc_base[0x7ff9] = CONV_BIN_TO_BCD(tm.tm_sec);
+
+ /* day of week -- not really used, but let's keep it up-to-date */
+ rtc_base[0x7ffc] = CONV_BIN_TO_BCD(tm.tm_wday + 1);
+
+ /* disable writing */
+ rtc_base[0x7ff8] = 0x00;
+
+ return 0;
+}
+
+void momenco_timer_setup(struct irqaction *irq)
+{
+ setup_irq(7, irq); /* Timer interrupt, unmask status IM7 */
+}
+
+void momenco_time_init(void)
+{
+ setup_wired_tlb_entries();
+
+ /*
+ * Ocelot-3 board has been built with both
+ * the Rm7900 and the Rm7065C
+ */
+ mips_hpt_frequency = cpu_clock / 2;
+ board_timer_setup = momenco_timer_setup;
+
+ rtc_get_time = m48t37y_get_time;
+ rtc_set_time = m48t37y_set_time;
+}
+
+/*
+ * PCI Support for Ocelot-3
+ */
+
+/* Bus #0 IO and MEM space */
+#define OCELOT_3_PCI_IO_0_START 0xe0000000
+#define OCELOT_3_PCI_IO_0_SIZE 0x08000000
+#define OCELOT_3_PCI_MEM_0_START 0xc0000000
+#define OCELOT_3_PCI_MEM_0_SIZE 0x10000000
+
+/* Bus #1 IO and MEM space */
+#define OCELOT_3_PCI_IO_1_START 0xe8000000
+#define OCELOT_3_PCI_IO_1_SIZE 0x08000000
+#define OCELOT_3_PCI_MEM_1_START 0xd0000000
+#define OCELOT_3_PCI_MEM_1_SIZE 0x10000000
+
+static struct resource mv_pci_io_mem0_resource = {
+ .name = "MV64340 PCI0 IO MEM",
+ .start = OCELOT_3_PCI_IO_0_START,
+ .end = OCELOT_3_PCI_IO_0_START + OCELOT_3_PCI_IO_0_SIZE - 1,
+ .flags = IORESOURCE_IO,
+};
+
+static struct resource mv_pci_io_mem1_resource = {
+ .name = "MV64340 PCI1 IO MEM",
+ .start = OCELOT_3_PCI_IO_1_START,
+ .end = OCELOT_3_PCI_IO_1_START + OCELOT_3_PCI_IO_1_SIZE - 1,
+ .flags = IORESOURCE_IO,
+};
+
+static struct resource mv_pci_mem0_resource = {
+ .name = "MV64340 PCI0 MEM",
+ .start = OCELOT_3_PCI_MEM_0_START,
+ .end = OCELOT_3_PCI_MEM_0_START + OCELOT_3_PCI_MEM_0_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+};
+
+static struct resource mv_pci_mem1_resource = {
+ .name = "MV64340 PCI1 MEM",
+ .start = OCELOT_3_PCI_MEM_1_START,
+ .end = OCELOT_3_PCI_MEM_1_START + OCELOT_3_PCI_MEM_1_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+};
+
+static struct mv_pci_controller mv_bus0_controller = {
+ .pcic = {
+ .pci_ops = &mv_pci_ops,
+ .mem_resource = &mv_pci_mem0_resource,
+ .io_resource = &mv_pci_io_mem0_resource,
+ },
+ .config_addr = MV64340_PCI_0_CONFIG_ADDR,
+ .config_vreg = MV64340_PCI_0_CONFIG_DATA_VIRTUAL_REG,
+};
+
+static struct mv_pci_controller mv_bus1_controller = {
+ .pcic = {
+ .pci_ops = &mv_pci_ops,
+ .mem_resource = &mv_pci_mem1_resource,
+ .io_resource = &mv_pci_io_mem1_resource,
+ },
+ .config_addr = MV64340_PCI_1_CONFIG_ADDR,
+ .config_vreg = MV64340_PCI_1_CONFIG_DATA_VIRTUAL_REG,
+};
+
+static __init int __init ja_pci_init(void)
+{
+ uint32_t enable;
+ extern int pci_probe_only;
+
+ /* PMON will assign PCI resources */
+ pci_probe_only = 1;
+
+ enable = ~MV_READ(MV64340_BASE_ADDR_ENABLE);
+ /*
+ * We require at least one enabled I/O or PCI memory window or we
+ * will ignore this PCI bus. We ignore PCI windows 1, 2 and 3.
+ */
+ if (enable & (0x01 << 9) || enable & (0x01 << 10))
+ register_pci_controller(&mv_bus0_controller.pcic);
+
+ if (enable & (0x01 << 14) || enable & (0x01 << 15))
+ register_pci_controller(&mv_bus1_controller.pcic);
+
+ ioport_resource.end = OCELOT_3_PCI_IO_0_START + OCELOT_3_PCI_IO_0_SIZE +
+ OCELOT_3_PCI_IO_1_SIZE - 1;
+
+ iomem_resource.end = OCELOT_3_PCI_MEM_0_START + OCELOT_3_PCI_MEM_0_SIZE +
+ OCELOT_3_PCI_MEM_1_SIZE - 1;
+
+ set_io_port_base(OCELOT_3_PCI_IO_0_START); /* mips_io_port_base */
+
+ return 0;
+}
+
+arch_initcall(ja_pci_init);
+
+static int __init momenco_ocelot_3_setup(void)
+{
+ unsigned int tmpword;
+
+ board_time_init = momenco_time_init;
+
+ _machine_restart = momenco_ocelot_restart;
+ _machine_halt = momenco_ocelot_halt;
+ _machine_power_off = momenco_ocelot_power_off;
+
+ /* Wired TLB entries */
+ setup_wired_tlb_entries();
+
+ /* shut down ethernet ports, just to be sure our memory doesn't get
+ * corrupted by random ethernet traffic.
+ */
+ MV_WRITE(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(0), 0xff << 8);
+ MV_WRITE(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(1), 0xff << 8);
+ MV_WRITE(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(0), 0xff << 8);
+ MV_WRITE(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(1), 0xff << 8);
+ do {}
+ while (MV_READ(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(0)) & 0xff);
+ do {}
+ while (MV_READ(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(1)) & 0xff);
+ do {}
+ while (MV_READ(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(0)) & 0xff);
+ do {}
+ while (MV_READ(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(1)) & 0xff);
+ MV_WRITE(MV64340_ETH_PORT_SERIAL_CONTROL_REG(0),
+ MV_READ(MV64340_ETH_PORT_SERIAL_CONTROL_REG(0)) & ~1);
+ MV_WRITE(MV64340_ETH_PORT_SERIAL_CONTROL_REG(1),
+ MV_READ(MV64340_ETH_PORT_SERIAL_CONTROL_REG(1)) & ~1);
+
+ /* Turn off the Bit-Error LED */
+ OCELOT_FPGA_WRITE(0x80, CLR);
+
+ tmpword = OCELOT_FPGA_READ(BOARDREV);
+ if (tmpword < 26)
+ printk("Momenco Ocelot-3: Board Assembly Rev. %c\n",
+ 'A'+tmpword);
+ else
+ printk("Momenco Ocelot-3: Board Assembly Revision #0x%x\n",
+ tmpword);
+
+ tmpword = OCELOT_FPGA_READ(FPGA_REV);
+ printk("FPGA Rev: %d.%d\n", tmpword>>4, tmpword&15);
+ tmpword = OCELOT_FPGA_READ(RESET_STATUS);
+ printk("Reset reason: 0x%x\n", tmpword);
+ switch (tmpword) {
+ case 0x1:
+ printk(" - Power-up reset\n");
+ break;
+ case 0x2:
+ printk(" - Push-button reset\n");
+ break;
+ case 0x4:
+ printk(" - cPCI bus reset\n");
+ break;
+ case 0x8:
+ printk(" - Watchdog reset\n");
+ break;
+ case 0x10:
+ printk(" - Software reset\n");
+ break;
+ default:
+ printk(" - Unknown reset cause\n");
+ }
+ reset_reason = tmpword;
+ OCELOT_FPGA_WRITE(0xff, RESET_STATUS);
+
+ tmpword = OCELOT_FPGA_READ(CPCI_ID);
+ printk("cPCI ID register: 0x%02x\n", tmpword);
+ printk(" - Slot number: %d\n", tmpword & 0x1f);
+ printk(" - PCI bus present: %s\n", tmpword & 0x40 ? "yes" : "no");
+ printk(" - System Slot: %s\n", tmpword & 0x20 ? "yes" : "no");
+
+ tmpword = OCELOT_FPGA_READ(BOARD_STATUS);
+ printk("Board Status register: 0x%02x\n", tmpword);
+ printk(" - User jumper: %s\n", (tmpword & 0x80)?"installed":"absent");
+ printk(" - Boot flash write jumper: %s\n", (tmpword&0x40)?"installed":"absent");
+ printk(" - L3 cache size: %d MB\n", (1<<((tmpword&12) >> 2))&~1);
+
+ /* Support for 128 MB memory */
+ add_memory_region(0x0, 0x08000000, BOOT_MEM_RAM);
+
+ return 0;
+}
+
+early_initcall(momenco_ocelot_3_setup);
diff --git a/arch/mips/momentum/ocelot_c/Makefile b/arch/mips/momentum/ocelot_c/Makefile
new file mode 100644
index 0000000..9124077
--- /dev/null
+++ b/arch/mips/momentum/ocelot_c/Makefile
@@ -0,0 +1,8 @@
+#
+# Makefile for Momentum Computer's Ocelot-C and -CS boards.
+#
+
+obj-y += cpci-irq.o int-handler.o irq.o prom.o reset.o \
+ setup.o uart-irq.o
+
+obj-$(CONFIG_KGDB) += dbg_io.o
diff --git a/arch/mips/momentum/ocelot_c/cpci-irq.c b/arch/mips/momentum/ocelot_c/cpci-irq.c
new file mode 100644
index 0000000..dea48b3
--- /dev/null
+++ b/arch/mips/momentum/ocelot_c/cpci-irq.c
@@ -0,0 +1,153 @@
+/*
+ * Copyright 2002 Momentum Computer
+ * Author: mdharm@momenco.com
+ *
+ * arch/mips/momentum/ocelot_c/cpci-irq.c
+ * Interrupt routines for cpci. Interrupt numbers are assigned from
+ * CPCI_IRQ_BASE to CPCI_IRQ_BASE+8 (8 interrupt sources).
+ *
+ * Note that the high-level software will need to be careful about using
+ * these interrupts. If this board is asserting a cPCI interrupt, it will
+ * also see the asserted interrupt. Care must be taken to avoid an
+ * interrupt flood.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <asm/ptrace.h>
+#include <linux/sched.h>
+#include <linux/kernel_stat.h>
+#include <asm/io.h>
+#include "ocelot_c_fpga.h"
+
+#define CPCI_IRQ_BASE 8
+
+static inline int ls1bit8(unsigned int x)
+{
+ int b = 7, s;
+
+ s = 4; if (((unsigned char)(x << 4)) == 0) s = 0; b -= s; x <<= s;
+ s = 2; if (((unsigned char)(x << 2)) == 0) s = 0; b -= s; x <<= s;
+ s = 1; if (((unsigned char)(x << 1)) == 0) s = 0; b -= s;
+
+ return b;
+}
+
+/* mask off an interrupt -- 0 is enable, 1 is disable */
+static inline void mask_cpci_irq(unsigned int irq)
+{
+ uint32_t value;
+
+ value = OCELOT_FPGA_READ(INTMASK);
+ value |= 1 << (irq - CPCI_IRQ_BASE);
+ OCELOT_FPGA_WRITE(value, INTMASK);
+
+ /* read the value back to assure that it's really been written */
+ value = OCELOT_FPGA_READ(INTMASK);
+}
+
+/* unmask an interrupt -- 0 is enable, 1 is disable */
+static inline void unmask_cpci_irq(unsigned int irq)
+{
+ uint32_t value;
+
+ value = OCELOT_FPGA_READ(INTMASK);
+ value &= ~(1 << (irq - CPCI_IRQ_BASE));
+ OCELOT_FPGA_WRITE(value, INTMASK);
+
+ /* read the value back to assure that it's really been written */
+ value = OCELOT_FPGA_READ(INTMASK);
+}
+
+/*
+ * Enables the IRQ in the FPGA
+ */
+static void enable_cpci_irq(unsigned int irq)
+{
+ unmask_cpci_irq(irq);
+}
+
+/*
+ * Initialize the IRQ in the FPGA
+ */
+static unsigned int startup_cpci_irq(unsigned int irq)
+{
+ unmask_cpci_irq(irq);
+ return 0;
+}
+
+/*
+ * Disables the IRQ in the FPGA
+ */
+static void disable_cpci_irq(unsigned int irq)
+{
+ mask_cpci_irq(irq);
+}
+
+/*
+ * Masks and ACKs an IRQ
+ */
+static void mask_and_ack_cpci_irq(unsigned int irq)
+{
+ mask_cpci_irq(irq);
+}
+
+/*
+ * End IRQ processing
+ */
+static void end_cpci_irq(unsigned int irq)
+{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+ unmask_cpci_irq(irq);
+}
+
+/*
+ * Interrupt handler for interrupts coming from the FPGA chip.
+ * It could be built in ethernet ports etc...
+ */
+void ll_cpci_irq(struct pt_regs *regs)
+{
+ unsigned int irq_src, irq_mask;
+
+ /* read the interrupt status registers */
+ irq_src = OCELOT_FPGA_READ(INTSTAT);
+ irq_mask = OCELOT_FPGA_READ(INTMASK);
+
+ /* mask for just the interrupts we want */
+ irq_src &= ~irq_mask;
+
+ do_IRQ(ls1bit8(irq_src) + CPCI_IRQ_BASE, regs);
+}
+
+#define shutdown_cpci_irq disable_cpci_irq
+
+struct hw_interrupt_type cpci_irq_type = {
+ "CPCI/FPGA",
+ startup_cpci_irq,
+ shutdown_cpci_irq,
+ enable_cpci_irq,
+ disable_cpci_irq,
+ mask_and_ack_cpci_irq,
+ end_cpci_irq,
+ NULL
+};
+
+void cpci_irq_init(void)
+{
+ int i;
+
+ /* Reset irq handlers pointers to NULL */
+ for (i = CPCI_IRQ_BASE; i < (CPCI_IRQ_BASE + 8); i++) {
+ irq_desc[i].status = IRQ_DISABLED;
+ irq_desc[i].action = 0;
+ irq_desc[i].depth = 2;
+ irq_desc[i].handler = &cpci_irq_type;
+ }
+}
diff --git a/arch/mips/momentum/ocelot_c/dbg_io.c b/arch/mips/momentum/ocelot_c/dbg_io.c
new file mode 100644
index 0000000..8720bcc
--- /dev/null
+++ b/arch/mips/momentum/ocelot_c/dbg_io.c
@@ -0,0 +1,126 @@
+#include <linux/config.h>
+
+#ifdef CONFIG_KGDB
+
+#include <asm/serial.h> /* For the serial port location and base baud */
+
+/* --- CONFIG --- */
+
+typedef unsigned char uint8;
+typedef unsigned int uint32;
+
+/* --- END OF CONFIG --- */
+
+#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
+
+/* ----------------------------------------------------- */
+
+/* === CONFIG === */
+
+/* [jsun] we use the second serial port for kdb */
+#define BASE OCELOT_SERIAL1_BASE
+#define MAX_BAUD OCELOT_BASE_BAUD
+
+/* === END OF CONFIG === */
+
+#define REG_OFFSET 4
+
+/* register offset */
+#define OFS_RCV_BUFFER 0
+#define OFS_TRANS_HOLD 0
+#define OFS_SEND_BUFFER 0
+#define OFS_INTR_ENABLE (1*REG_OFFSET)
+#define OFS_INTR_ID (2*REG_OFFSET)
+#define OFS_DATA_FORMAT (3*REG_OFFSET)
+#define OFS_LINE_CONTROL (3*REG_OFFSET)
+#define OFS_MODEM_CONTROL (4*REG_OFFSET)
+#define OFS_RS232_OUTPUT (4*REG_OFFSET)
+#define OFS_LINE_STATUS (5*REG_OFFSET)
+#define OFS_MODEM_STATUS (6*REG_OFFSET)
+#define OFS_RS232_INPUT (6*REG_OFFSET)
+#define OFS_SCRATCH_PAD (7*REG_OFFSET)
+
+#define OFS_DIVISOR_LSB (0*REG_OFFSET)
+#define OFS_DIVISOR_MSB (1*REG_OFFSET)
+
+
+/* memory-mapped read/write of the port */
+#define UART16550_READ(y) (*((volatile uint8*)(BASE + y)))
+#define UART16550_WRITE(y, z) ((*((volatile uint8*)(BASE + y))) = z)
+
+void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop)
+{
+ /* disable interrupts */
+ UART16550_WRITE(OFS_INTR_ENABLE, 0);
+
+ /* set up buad rate */
+ {
+ uint32 divisor;
+
+ /* set DIAB bit */
+ UART16550_WRITE(OFS_LINE_CONTROL, 0x80);
+
+ /* set divisor */
+ divisor = MAX_BAUD / baud;
+ UART16550_WRITE(OFS_DIVISOR_LSB, divisor & 0xff);
+ UART16550_WRITE(OFS_DIVISOR_MSB, (divisor & 0xff00) >> 8);
+
+ /* clear DIAB bit */
+ UART16550_WRITE(OFS_LINE_CONTROL, 0x0);
+ }
+
+ /* set data format */
+ UART16550_WRITE(OFS_DATA_FORMAT, data | parity | stop);
+}
+
+static int remoteDebugInitialized = 0;
+
+uint8 getDebugChar(void)
+{
+ if (!remoteDebugInitialized) {
+ remoteDebugInitialized = 1;
+ debugInit(UART16550_BAUD_38400,
+ UART16550_DATA_8BIT,
+ UART16550_PARITY_NONE, UART16550_STOP_1BIT);
+ }
+
+ while ((UART16550_READ(OFS_LINE_STATUS) & 0x1) == 0);
+ return UART16550_READ(OFS_RCV_BUFFER);
+}
+
+
+int putDebugChar(uint8 byte)
+{
+ if (!remoteDebugInitialized) {
+ remoteDebugInitialized = 1;
+ debugInit(UART16550_BAUD_38400,
+ UART16550_DATA_8BIT,
+ UART16550_PARITY_NONE, UART16550_STOP_1BIT);
+ }
+
+ while ((UART16550_READ(OFS_LINE_STATUS) & 0x20) == 0);
+ UART16550_WRITE(OFS_SEND_BUFFER, byte);
+ return 1;
+}
+
+#endif
diff --git a/arch/mips/momentum/ocelot_c/int-handler.S b/arch/mips/momentum/ocelot_c/int-handler.S
new file mode 100644
index 0000000..2f24306
--- /dev/null
+++ b/arch/mips/momentum/ocelot_c/int-handler.S
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2002 Momentum Computer Inc.
+ * Author: Matthew Dharm <mdharm@momenco.com>
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: jsun@mvista.com or jsun@junsun.net
+ *
+ * First-level interrupt dispatcher for Ocelot-CS board.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+#include <asm/asm.h>
+#include <asm/mipsregs.h>
+#include <asm/addrspace.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+#include "ocelot_c_fpga.h"
+
+/*
+ * First level interrupt dispatcher for Ocelot-CS board
+ */
+ .align 5
+ NESTED(ocelot_handle_int, PT_SIZE, sp)
+ SAVE_ALL
+ CLI
+ .set at
+ mfc0 t0, CP0_CAUSE
+ mfc0 t2, CP0_STATUS
+
+ and t0, t2
+
+ andi t1, t0, STATUSF_IP0 /* sw0 software interrupt */
+ bnez t1, ll_sw0_irq
+ andi t1, t0, STATUSF_IP1 /* sw1 software interrupt */
+ bnez t1, ll_sw1_irq
+ andi t1, t0, STATUSF_IP2 /* int0 hardware line */
+ bnez t1, ll_scsi_irq
+ andi t1, t0, STATUSF_IP3 /* int1 hardware line */
+ bnez t1, ll_uart_decode_irq
+ andi t1, t0, STATUSF_IP4 /* int2 hardware line */
+ bnez t1, ll_pmc_irq
+ andi t1, t0, STATUSF_IP5 /* int3 hardware line */
+ bnez t1, ll_cpci_decode_irq
+ andi t1, t0, STATUSF_IP6 /* int4 hardware line */
+ bnez t1, ll_mv64340_decode_irq
+ andi t1, t0, STATUSF_IP7 /* cpu timer */
+ bnez t1, ll_cputimer_irq
+
+ .set reorder
+
+ /* wrong alarm or masked ... */
+ j spurious_interrupt
+ nop
+ END(ocelot_handle_int)
+
+ .align 5
+ll_sw0_irq:
+ li a0, 0
+ move a1, sp
+ jal do_IRQ
+ j ret_from_irq
+ll_sw1_irq:
+ li a0, 1
+ move a1, sp
+ jal do_IRQ
+ j ret_from_irq
+ll_scsi_irq:
+ li a0, 2
+ move a1, sp
+ jal do_IRQ
+ j ret_from_irq
+
+ll_uart_decode_irq:
+ move a0, sp
+ jal ll_uart_irq
+ j ret_from_irq
+
+ll_pmc_irq:
+ li a0, 4
+ move a1, sp
+ jal do_IRQ
+ j ret_from_irq
+
+ll_cpci_decode_irq:
+ move a0, sp
+ jal ll_cpci_irq
+ j ret_from_irq
+
+ll_mv64340_decode_irq:
+ move a0, sp
+ jal ll_mv64340_irq
+ j ret_from_irq
+
+ll_cputimer_irq:
+ li a0, 7
+ move a1, sp
+ jal do_IRQ
+ j ret_from_irq
+
diff --git a/arch/mips/momentum/ocelot_c/irq.c b/arch/mips/momentum/ocelot_c/irq.c
new file mode 100644
index 0000000..300fe8e
--- /dev/null
+++ b/arch/mips/momentum/ocelot_c/irq.c
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2000 RidgeRun, Inc.
+ * Author: RidgeRun, Inc.
+ * glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
+ * Copyright (C) 2000, 01, 05 Ralf Baechle (ralf@linux-mips.org)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel_stat.h>
+#include <linux/module.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/timex.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+#include <linux/bitops.h>
+#include <asm/bootinfo.h>
+#include <asm/io.h>
+#include <asm/irq_cpu.h>
+#include <asm/mipsregs.h>
+#include <asm/mv64340.h>
+#include <asm/system.h>
+
+extern asmlinkage void ocelot_handle_int(void);
+extern void uart_irq_init(void);
+extern void cpci_irq_init(void);
+
+static struct irqaction cascade_fpga = {
+ no_action, SA_INTERRUPT, CPU_MASK_NONE, "cascade via FPGA", NULL, NULL
+};
+
+static struct irqaction cascade_mv64340 = {
+ no_action, SA_INTERRUPT, CPU_MASK_NONE, "cascade via MV64340", NULL, NULL
+};
+
+void __init arch_init_irq(void)
+{
+ /*
+ * Clear all of the interrupts while we change the able around a bit.
+ * int-handler is not on bootstrap
+ */
+ clear_c0_status(ST0_IM);
+
+ /* Sets the first-level interrupt dispatcher. */
+ set_except_vector(0, ocelot_handle_int);
+ mips_cpu_irq_init(0);
+
+ /* set up the cascading interrupts */
+ setup_irq(3, &cascade_fpga);
+ setup_irq(5, &cascade_fpga);
+ setup_irq(6, &cascade_mv64340);
+
+ mv64340_irq_init(16);
+ uart_irq_init();
+ cpci_irq_init();
+}
diff --git a/arch/mips/momentum/ocelot_c/ocelot_c_fpga.h b/arch/mips/momentum/ocelot_c/ocelot_c_fpga.h
new file mode 100644
index 0000000..a6cf7a7
--- /dev/null
+++ b/arch/mips/momentum/ocelot_c/ocelot_c_fpga.h
@@ -0,0 +1,60 @@
+/*
+ * Ocelot-C Board Register Definitions
+ *
+ * (C) 2002 Momentum Computer Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Louis Hamilton, Red Hat, Inc.
+ * hamilton@redhat.com [MIPS64 modifications]
+ */
+
+#ifndef __OCELOT_C_FPGA_H__
+#define __OCELOT_C_FPGA_H__
+
+#include <linux/config.h>
+
+#ifdef CONFIG_MIPS64
+#define OCELOT_C_CS0_ADDR (0xfffffffffc000000)
+#else
+#define OCELOT_C_CS0_ADDR (0xfc000000)
+#endif
+
+#define OCELOT_C_REG_BOARDREV 0x0
+#define OCELOT_C_REG_FPGA_REV 0x1
+#define OCELOT_C_REG_FPGA_TYPE 0x2
+#define OCELOT_C_REG_RESET_STATUS 0x3
+#define OCELOT_C_REG_BOARD_STATUS 0x4
+#define OCELOT_C_REG_CPCI_ID 0x5
+#define OCELOT_C_REG_SET 0x6
+#define OCELOT_C_REG_CLR 0x7
+#define OCELOT_C_REG_EEPROM_MODE 0x9
+#define OCELOT_C_REG_INTMASK 0xa
+#define OCELOT_C_REG_INTSTAT 0xb
+#define OCELOT_C_REG_UART_INTMASK 0xc
+#define OCELOT_C_REG_UART_INTSTAT 0xd
+#define OCELOT_C_REG_INTSET 0xe
+#define OCELOT_C_REG_INTCLR 0xf
+
+#define OCELOT_FPGA_WRITE(x, y) writeb(x, OCELOT_C_CS0_ADDR + OCELOT_C_REG_##y)
+#define OCELOT_FPGA_READ(x) readb(OCELOT_C_CS0_ADDR + OCELOT_C_REG_##x)
+
+#endif
diff --git a/arch/mips/momentum/ocelot_c/prom.c b/arch/mips/momentum/ocelot_c/prom.c
new file mode 100644
index 0000000..49ac302
--- /dev/null
+++ b/arch/mips/momentum/ocelot_c/prom.c
@@ -0,0 +1,243 @@
+/*
+ * Copyright 2002 Momentum Computer Inc.
+ * Author: Matthew Dharm <mdharm@momenco.com>
+ *
+ * Louis Hamilton, Red Hat, Inc.
+ * hamilton@redhat.com [MIPS64 modifications]
+ *
+ * Based on Ocelot Linux port, which is
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: jsun@mvista.com or jsun@junsun.net
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/bootmem.h>
+
+#include <asm/addrspace.h>
+#include <asm/bootinfo.h>
+#include <asm/mv64340.h>
+#include <asm/pmon.h>
+
+#include "ocelot_c_fpga.h"
+
+struct callvectors* debug_vectors;
+
+extern unsigned long marvell_base;
+extern unsigned long cpu_clock;
+
+#ifdef CONFIG_MV643XX_ETH
+extern unsigned char prom_mac_addr_base[6];
+#endif
+
+const char *get_system_type(void)
+{
+#ifdef CONFIG_CPU_SR71000
+ return "Momentum Ocelot-CS";
+#else
+ return "Momentum Ocelot-C";
+#endif
+}
+
+#ifdef CONFIG_MV643XX_ETH
+static void burn_clocks(void)
+{
+ int i;
+
+ /* this loop should burn at least 1us -- this should be plenty */
+ for (i = 0; i < 0x10000; i++)
+ ;
+}
+
+static u8 exchange_bit(u8 val, u8 cs)
+{
+ /* place the data */
+ OCELOT_FPGA_WRITE((val << 2) | cs, EEPROM_MODE);
+ burn_clocks();
+
+ /* turn the clock on */
+ OCELOT_FPGA_WRITE((val << 2) | cs | 0x2, EEPROM_MODE);
+ burn_clocks();
+
+ /* turn the clock off and read-strobe */
+ OCELOT_FPGA_WRITE((val << 2) | cs | 0x10, EEPROM_MODE);
+
+ /* return the data */
+ return ((OCELOT_FPGA_READ(EEPROM_MODE) >> 3) & 0x1);
+}
+
+void get_mac(char dest[6])
+{
+ u8 read_opcode[12] = {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+ int i,j;
+
+ for (i = 0; i < 12; i++)
+ exchange_bit(read_opcode[i], 1);
+
+ for (j = 0; j < 6; j++) {
+ dest[j] = 0;
+ for (i = 0; i < 8; i++) {
+ dest[j] <<= 1;
+ dest[j] |= exchange_bit(0, 1);
+ }
+ }
+
+ /* turn off CS */
+ exchange_bit(0,0);
+}
+#endif
+
+
+#ifdef CONFIG_MIPS64
+
+unsigned long signext(unsigned long addr)
+{
+ addr &= 0xffffffff;
+ return (unsigned long)((int)addr);
+}
+
+void *get_arg(unsigned long args, int arc)
+{
+ unsigned long ul;
+ unsigned char *puc, uc;
+
+ args += (arc * 4);
+ ul = (unsigned long)signext(args);
+ puc = (unsigned char *)ul;
+ if (puc == 0)
+ return (void *)0;
+
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+ uc = *puc++;
+ ul = (unsigned long)uc;
+ uc = *puc++;
+ ul |= (((unsigned long)uc) << 8);
+ uc = *puc++;
+ ul |= (((unsigned long)uc) << 16);
+ uc = *puc++;
+ ul |= (((unsigned long)uc) << 24);
+#else /* CONFIG_CPU_LITTLE_ENDIAN */
+ uc = *puc++;
+ ul = ((unsigned long)uc) << 24;
+ uc = *puc++;
+ ul |= (((unsigned long)uc) << 16);
+ uc = *puc++;
+ ul |= (((unsigned long)uc) << 8);
+ uc = *puc++;
+ ul |= ((unsigned long)uc);
+#endif /* CONFIG_CPU_LITTLE_ENDIAN */
+ ul = signext(ul);
+ return (void *)ul;
+}
+
+char *arg64(unsigned long addrin, int arg_index)
+{
+ unsigned long args;
+ char *p;
+ args = signext(addrin);
+ p = (char *)get_arg(args, arg_index);
+ return p;
+}
+#endif /* CONFIG_MIPS64 */
+
+
+void __init prom_init(void)
+{
+ int argc = fw_arg0;
+ char **arg = (char **) fw_arg1;
+ char **env = (char **) fw_arg2;
+ struct callvectors *cv = (struct callvectors *) fw_arg3;
+ int i;
+
+#ifdef CONFIG_MIPS64
+ char *ptr;
+
+ printk("prom_init - MIPS64\n");
+ /* save the PROM vectors for debugging use */
+ debug_vectors = (struct callvectors *)signext((unsigned long)cv);
+
+ /* arg[0] is "g", the rest is boot parameters */
+ arcs_cmdline[0] = '\0';
+
+ for (i = 1; i < argc; i++) {
+ ptr = (char *)arg64((unsigned long)arg, i);
+ if ((strlen(arcs_cmdline) + strlen(ptr) + 1) >=
+ sizeof(arcs_cmdline))
+ break;
+ strcat(arcs_cmdline, ptr);
+ strcat(arcs_cmdline, " ");
+ }
+ i = 0;
+ while (1) {
+ ptr = (char *)arg64((unsigned long)env, i);
+ if (! ptr)
+ break;
+
+ if (strncmp("gtbase", ptr, strlen("gtbase")) == 0) {
+ marvell_base = simple_strtol(ptr + strlen("gtbase="),
+ NULL, 16);
+
+ if ((marvell_base & 0xffffffff00000000) == 0)
+ marvell_base |= 0xffffffff00000000;
+
+ printk("marvell_base set to 0x%016lx\n", marvell_base);
+ }
+ if (strncmp("cpuclock", ptr, strlen("cpuclock")) == 0) {
+ cpu_clock = simple_strtol(ptr + strlen("cpuclock="),
+ NULL, 10);
+ printk("cpu_clock set to %d\n", cpu_clock);
+ }
+ i++;
+ }
+ printk("arcs_cmdline: %s\n", arcs_cmdline);
+
+#else /* CONFIG_MIPS64 */
+ /* save the PROM vectors for debugging use */
+ debug_vectors = cv;
+
+ /* arg[0] is "g", the rest is boot parameters */
+ arcs_cmdline[0] = '\0';
+ for (i = 1; i < argc; i++) {
+ if (strlen(arcs_cmdline) + strlen(arg[i] + 1)
+ >= sizeof(arcs_cmdline))
+ break;
+ strcat(arcs_cmdline, arg[i]);
+ strcat(arcs_cmdline, " ");
+ }
+
+ while (*env) {
+ if (strncmp("gtbase", *env, strlen("gtbase")) == 0) {
+ marvell_base = simple_strtol(*env + strlen("gtbase="),
+ NULL, 16);
+ }
+ if (strncmp("cpuclock", *env, strlen("cpuclock")) == 0) {
+ cpu_clock = simple_strtol(*env + strlen("cpuclock="),
+ NULL, 10);
+ }
+ env++;
+ }
+#endif /* CONFIG_MIPS64 */
+
+ mips_machgroup = MACH_GROUP_MOMENCO;
+ mips_machtype = MACH_MOMENCO_OCELOT_C;
+
+#ifdef CONFIG_MV643XX_ETH
+ /* get the base MAC address for on-board ethernet ports */
+ get_mac(prom_mac_addr_base);
+#endif
+
+#ifndef CONFIG_MIPS64
+ debug_vectors->printf("Booting Linux kernel...\n");
+#endif
+}
+
+unsigned long __init prom_free_prom_memory(void)
+{
+ return 0;
+}
diff --git a/arch/mips/momentum/ocelot_c/reset.c b/arch/mips/momentum/ocelot_c/reset.c
new file mode 100644
index 0000000..1f2b426
--- /dev/null
+++ b/arch/mips/momentum/ocelot_c/reset.c
@@ -0,0 +1,59 @@
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * Copyright (C) 1997, 2001 Ralf Baechle
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: jsun@mvista.com or jsun@junsun.net
+ *
+ * Copyright (C) 2002 Momentum Computer Inc.
+ * Author: Matthew Dharm <mdharm@momenco.com>
+ *
+ * Louis Hamilton, Red Hat, Inc.
+ * hamilton@redhat.com [MIPS64 modifications]
+ */
+#include <linux/config.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/reboot.h>
+#include <asm/system.h>
+#include <linux/delay.h>
+
+void momenco_ocelot_restart(char *command)
+{
+ /* base address of timekeeper portion of part */
+ void *nvram = (void *)
+#ifdef CONFIG_MIPS64
+ 0xfffffffffc807000;
+#else
+ 0xfc807000;
+#endif
+
+ /* Ask the NVRAM/RTC/watchdog chip to assert reset in 1/16 second */
+ writeb(0x84, nvram + 0xff7);
+
+ /* wait for the watchdog to go off */
+ mdelay(100+(1000/16));
+
+ /* if the watchdog fails for some reason, let people know */
+ printk(KERN_NOTICE "Watchdog reset failed\n");
+}
+
+void momenco_ocelot_halt(void)
+{
+ printk(KERN_NOTICE "\n** You can safely turn off the power\n");
+ while (1)
+ __asm__(".set\tmips3\n\t"
+ "wait\n\t"
+ ".set\tmips0");
+}
+
+void momenco_ocelot_power_off(void)
+{
+ momenco_ocelot_halt();
+}
diff --git a/arch/mips/momentum/ocelot_c/setup.c b/arch/mips/momentum/ocelot_c/setup.c
new file mode 100644
index 0000000..021c00e
--- /dev/null
+++ b/arch/mips/momentum/ocelot_c/setup.c
@@ -0,0 +1,363 @@
+/*
+ * BRIEF MODULE DESCRIPTION
+ * Momentum Computer Ocelot-C and -CS board dependent boot routines
+ *
+ * Copyright (C) 1996, 1997, 2001 Ralf Baechle
+ * Copyright (C) 2000 RidgeRun, Inc.
+ * Copyright (C) 2001 Red Hat, Inc.
+ * Copyright (C) 2002 Momentum Computer
+ *
+ * Author: Matthew Dharm, Momentum Computer
+ * mdharm@momenco.com
+ *
+ * Louis Hamilton, Red Hat, Inc.
+ * hamilton@redhat.com [MIPS64 modifications]
+ *
+ * Author: RidgeRun, Inc.
+ * glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: jsun@mvista.com or jsun@junsun.net
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+#include <linux/config.h>
+#include <linux/bcd.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/swap.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/timex.h>
+#include <linux/vmalloc.h>
+#include <asm/time.h>
+#include <asm/bootinfo.h>
+#include <asm/page.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/pci.h>
+#include <asm/processor.h>
+#include <asm/ptrace.h>
+#include <asm/reboot.h>
+#include <linux/bootmem.h>
+#include <linux/blkdev.h>
+#include <asm/mv64340.h>
+#include "ocelot_c_fpga.h"
+
+unsigned long marvell_base;
+extern unsigned long mv64340_sram_base;
+unsigned long cpu_clock;
+
+/* These functions are used for rebooting or halting the machine*/
+extern void momenco_ocelot_restart(char *command);
+extern void momenco_ocelot_halt(void);
+extern void momenco_ocelot_power_off(void);
+
+void momenco_time_init(void);
+
+static char reset_reason;
+
+void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1, unsigned long entryhi, unsigned long pagemask);
+
+static unsigned long ENTRYLO(unsigned long paddr)
+{
+ return ((paddr & PAGE_MASK) |
+ (_PAGE_PRESENT | __READABLE | __WRITEABLE | _PAGE_GLOBAL |
+ _CACHE_UNCACHED)) >> 6;
+}
+
+/* setup code for a handoff from a version 2 PMON 2000 PROM */
+void PMON_v2_setup(void)
+{
+ /* Some wired TLB entries for the MV64340 and perhiperals. The
+ MV64340 is going to be hit on every IRQ anyway - there's
+ absolutely no point in letting it be a random TLB entry, as
+ it'll just cause needless churning of the TLB. And we use
+ the other half for the serial port, which is just a PITA
+ otherwise :)
+
+ Device Physical Virtual
+ MV64340 Internal Regs 0xf4000000 0xf4000000
+ Ocelot-C[S] PLD (CS0) 0xfc000000 0xfc000000
+ NVRAM (CS1) 0xfc800000 0xfc800000
+ UARTs (CS2) 0xfd000000 0xfd000000
+ Internal SRAM 0xfe000000 0xfe000000
+ M-Systems DOC (CS3) 0xff000000 0xff000000
+ */
+ printk("PMON_v2_setup\n");
+
+#ifdef CONFIG_MIPS64
+ /* marvell and extra space */
+ add_wired_entry(ENTRYLO(0xf4000000), ENTRYLO(0xf4010000), 0xfffffffff4000000, PM_64K);
+ /* fpga, rtc, and uart */
+ add_wired_entry(ENTRYLO(0xfc000000), ENTRYLO(0xfd000000), 0xfffffffffc000000, PM_16M);
+ /* m-sys and internal SRAM */
+ add_wired_entry(ENTRYLO(0xfe000000), ENTRYLO(0xff000000), 0xfffffffffe000000, PM_16M);
+
+ marvell_base = 0xfffffffff4000000;
+ mv64340_sram_base = 0xfffffffffe000000;
+#else
+ /* marvell and extra space */
+ add_wired_entry(ENTRYLO(0xf4000000), ENTRYLO(0xf4010000), 0xf4000000, PM_64K);
+ /* fpga, rtc, and uart */
+ add_wired_entry(ENTRYLO(0xfc000000), ENTRYLO(0xfd000000), 0xfc000000, PM_16M);
+ /* m-sys and internal SRAM */
+ add_wired_entry(ENTRYLO(0xfe000000), ENTRYLO(0xff000000), 0xfe000000, PM_16M);
+
+ marvell_base = 0xf4000000;
+ mv64340_sram_base = 0xfe000000;
+#endif
+}
+
+unsigned long m48t37y_get_time(void)
+{
+#ifdef CONFIG_MIPS64
+ unsigned char *rtc_base = (unsigned char*)0xfffffffffc800000;
+#else
+ unsigned char* rtc_base = (unsigned char*)0xfc800000;
+#endif
+ unsigned int year, month, day, hour, min, sec;
+
+ /* stop the update */
+ rtc_base[0x7ff8] = 0x40;
+
+ year = BCD2BIN(rtc_base[0x7fff]);
+ year += BCD2BIN(rtc_base[0x7ff1]) * 100;
+
+ month = BCD2BIN(rtc_base[0x7ffe]);
+
+ day = BCD2BIN(rtc_base[0x7ffd]);
+
+ hour = BCD2BIN(rtc_base[0x7ffb]);
+ min = BCD2BIN(rtc_base[0x7ffa]);
+ sec = BCD2BIN(rtc_base[0x7ff9]);
+
+ /* start the update */
+ rtc_base[0x7ff8] = 0x00;
+
+ return mktime(year, month, day, hour, min, sec);
+}
+
+int m48t37y_set_time(unsigned long sec)
+{
+#ifdef CONFIG_MIPS64
+ unsigned char* rtc_base = (unsigned char*)0xfffffffffc800000;
+#else
+ unsigned char* rtc_base = (unsigned char*)0xfc800000;
+#endif
+ struct rtc_time tm;
+
+ /* convert to a more useful format -- note months count from 0 */
+ to_tm(sec, &tm);
+ tm.tm_mon += 1;
+
+ /* enable writing */
+ rtc_base[0x7ff8] = 0x80;
+
+ /* year */
+ rtc_base[0x7fff] = BIN2BCD(tm.tm_year % 100);
+ rtc_base[0x7ff1] = BIN2BCD(tm.tm_year / 100);
+
+ /* month */
+ rtc_base[0x7ffe] = BIN2BCD(tm.tm_mon);
+
+ /* day */
+ rtc_base[0x7ffd] = BIN2BCD(tm.tm_mday);
+
+ /* hour/min/sec */
+ rtc_base[0x7ffb] = BIN2BCD(tm.tm_hour);
+ rtc_base[0x7ffa] = BIN2BCD(tm.tm_min);
+ rtc_base[0x7ff9] = BIN2BCD(tm.tm_sec);
+
+ /* day of week -- not really used, but let's keep it up-to-date */
+ rtc_base[0x7ffc] = BIN2BCD(tm.tm_wday + 1);
+
+ /* disable writing */
+ rtc_base[0x7ff8] = 0x00;
+
+ return 0;
+}
+
+void momenco_timer_setup(struct irqaction *irq)
+{
+ setup_irq(7, irq);
+}
+
+void momenco_time_init(void)
+{
+#ifdef CONFIG_CPU_SR71000
+ mips_hpt_frequency = cpu_clock;
+#elif defined(CONFIG_CPU_RM7000)
+ mips_hpt_frequency = cpu_clock / 2;
+#else
+#error Unknown CPU for this board
+#endif
+ printk("momenco_time_init cpu_clock=%d\n", cpu_clock);
+ board_timer_setup = momenco_timer_setup;
+
+ rtc_get_time = m48t37y_get_time;
+ rtc_set_time = m48t37y_set_time;
+}
+
+static void __init momenco_ocelot_c_setup(void)
+{
+ unsigned int tmpword;
+
+ board_time_init = momenco_time_init;
+
+ _machine_restart = momenco_ocelot_restart;
+ _machine_halt = momenco_ocelot_halt;
+ _machine_power_off = momenco_ocelot_power_off;
+
+ /*
+ * initrd_start = (ulong)ocelot_initrd_start;
+ * initrd_end = (ulong)ocelot_initrd_start + (ulong)ocelot_initrd_size;
+ * initrd_below_start_ok = 1;
+ */
+
+ /* do handoff reconfiguration */
+ PMON_v2_setup();
+
+ /* shut down ethernet ports, just to be sure our memory doesn't get
+ * corrupted by random ethernet traffic.
+ */
+ MV_WRITE(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(0), 0xff << 8);
+ MV_WRITE(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(1), 0xff << 8);
+ MV_WRITE(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(0), 0xff << 8);
+ MV_WRITE(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(1), 0xff << 8);
+ do {}
+ while (MV_READ(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(0)) & 0xff);
+ do {}
+ while (MV_READ(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(1)) & 0xff);
+ do {}
+ while (MV_READ(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(0)) & 0xff);
+ do {}
+ while (MV_READ(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(1)) & 0xff);
+ MV_WRITE(MV64340_ETH_PORT_SERIAL_CONTROL_REG(0),
+ MV_READ(MV64340_ETH_PORT_SERIAL_CONTROL_REG(0)) & ~1);
+ MV_WRITE(MV64340_ETH_PORT_SERIAL_CONTROL_REG(1),
+ MV_READ(MV64340_ETH_PORT_SERIAL_CONTROL_REG(1)) & ~1);
+
+ /* Turn off the Bit-Error LED */
+ OCELOT_FPGA_WRITE(0x80, CLR);
+
+ tmpword = OCELOT_FPGA_READ(BOARDREV);
+#ifdef CONFIG_CPU_SR71000
+ if (tmpword < 26)
+ printk("Momenco Ocelot-CS: Board Assembly Rev. %c\n",
+ 'A'+tmpword);
+ else
+ printk("Momenco Ocelot-CS: Board Assembly Revision #0x%x\n",
+ tmpword);
+#else
+ if (tmpword < 26)
+ printk("Momenco Ocelot-C: Board Assembly Rev. %c\n",
+ 'A'+tmpword);
+ else
+ printk("Momenco Ocelot-C: Board Assembly Revision #0x%x\n",
+ tmpword);
+#endif
+
+ tmpword = OCELOT_FPGA_READ(FPGA_REV);
+ printk("FPGA Rev: %d.%d\n", tmpword>>4, tmpword&15);
+ tmpword = OCELOT_FPGA_READ(RESET_STATUS);
+ printk("Reset reason: 0x%x\n", tmpword);
+ switch (tmpword) {
+ case 0x1:
+ printk(" - Power-up reset\n");
+ break;
+ case 0x2:
+ printk(" - Push-button reset\n");
+ break;
+ case 0x4:
+ printk(" - cPCI bus reset\n");
+ break;
+ case 0x8:
+ printk(" - Watchdog reset\n");
+ break;
+ case 0x10:
+ printk(" - Software reset\n");
+ break;
+ default:
+ printk(" - Unknown reset cause\n");
+ }
+ reset_reason = tmpword;
+ OCELOT_FPGA_WRITE(0xff, RESET_STATUS);
+
+ tmpword = OCELOT_FPGA_READ(CPCI_ID);
+ printk("cPCI ID register: 0x%02x\n", tmpword);
+ printk(" - Slot number: %d\n", tmpword & 0x1f);
+ printk(" - PCI bus present: %s\n", tmpword & 0x40 ? "yes" : "no");
+ printk(" - System Slot: %s\n", tmpword & 0x20 ? "yes" : "no");
+
+ tmpword = OCELOT_FPGA_READ(BOARD_STATUS);
+ printk("Board Status register: 0x%02x\n", tmpword);
+ printk(" - User jumper: %s\n", (tmpword & 0x80)?"installed":"absent");
+ printk(" - Boot flash write jumper: %s\n", (tmpword&0x40)?"installed":"absent");
+ printk(" - L3 Cache size: %d MiB\n", (1<<((tmpword&12) >> 2))&~1);
+ printk(" - SDRAM size: %d MiB\n", 1<<(6+(tmpword&3)));
+
+ switch(tmpword &3) {
+ case 3:
+ /* 512MiB */
+ add_memory_region(0x0, 0x200<<20, BOOT_MEM_RAM);
+ break;
+ case 2:
+ /* 256MiB */
+ add_memory_region(0x0, 0x100<<20, BOOT_MEM_RAM);
+ break;
+ case 1:
+ /* 128MiB */
+ add_memory_region(0x0, 0x80<<20, BOOT_MEM_RAM);
+ break;
+ case 0:
+ /* 1GiB -- needs CONFIG_HIGHMEM */
+ add_memory_region(0x0, 0x400<<20, BOOT_MEM_RAM);
+ break;
+ }
+}
+
+early_initcall(momenco_ocelot_c_setup);
+
+#ifndef CONFIG_MIPS64
+/* This needs to be one of the first initcalls, because no I/O port access
+ can work before this */
+static int io_base_ioremap(void)
+{
+ /* we're mapping PCI accesses from 0xc0000000 to 0xf0000000 */
+ void *io_remap_range = ioremap(0xc0000000, 0x30000000);
+
+ if (!io_remap_range) {
+ panic("Could not ioremap I/O port range");
+ }
+ printk("io_remap_range set at 0x%08x\n", (uint32_t)io_remap_range);
+ set_io_port_base(io_remap_range - 0xc0000000);
+
+ return 0;
+}
+
+module_init(io_base_ioremap);
+#endif
diff --git a/arch/mips/momentum/ocelot_c/uart-irq.c b/arch/mips/momentum/ocelot_c/uart-irq.c
new file mode 100644
index 0000000..ebe1507
--- /dev/null
+++ b/arch/mips/momentum/ocelot_c/uart-irq.c
@@ -0,0 +1,147 @@
+/*
+ * Copyright 2002 Momentum Computer
+ * Author: mdharm@momenco.com
+ *
+ * arch/mips/momentum/ocelot_c/uart-irq.c
+ * Interrupt routines for UARTs. Interrupt numbers are assigned from
+ * 80 to 81 (2 interrupt sources).
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <asm/ptrace.h>
+#include <linux/sched.h>
+#include <linux/kernel_stat.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include "ocelot_c_fpga.h"
+
+static inline int ls1bit8(unsigned int x)
+{
+ int b = 7, s;
+
+ s = 4; if (((unsigned char)(x << 4)) == 0) s = 0; b -= s; x <<= s;
+ s = 2; if (((unsigned char)(x << 2)) == 0) s = 0; b -= s; x <<= s;
+ s = 1; if (((unsigned char)(x << 1)) == 0) s = 0; b -= s;
+
+ return b;
+}
+
+/* mask off an interrupt -- 0 is enable, 1 is disable */
+static inline void mask_uart_irq(unsigned int irq)
+{
+ uint8_t value;
+
+ value = OCELOT_FPGA_READ(UART_INTMASK);
+ value |= 1 << (irq - 74);
+ OCELOT_FPGA_WRITE(value, UART_INTMASK);
+
+ /* read the value back to assure that it's really been written */
+ value = OCELOT_FPGA_READ(UART_INTMASK);
+}
+
+/* unmask an interrupt -- 0 is enable, 1 is disable */
+static inline void unmask_uart_irq(unsigned int irq)
+{
+ uint8_t value;
+
+ value = OCELOT_FPGA_READ(UART_INTMASK);
+ value &= ~(1 << (irq - 74));
+ OCELOT_FPGA_WRITE(value, UART_INTMASK);
+
+ /* read the value back to assure that it's really been written */
+ value = OCELOT_FPGA_READ(UART_INTMASK);
+}
+
+/*
+ * Enables the IRQ in the FPGA
+ */
+static void enable_uart_irq(unsigned int irq)
+{
+ unmask_uart_irq(irq);
+}
+
+/*
+ * Initialize the IRQ in the FPGA
+ */
+static unsigned int startup_uart_irq(unsigned int irq)
+{
+ unmask_uart_irq(irq);
+ return 0;
+}
+
+/*
+ * Disables the IRQ in the FPGA
+ */
+static void disable_uart_irq(unsigned int irq)
+{
+ mask_uart_irq(irq);
+}
+
+/*
+ * Masks and ACKs an IRQ
+ */
+static void mask_and_ack_uart_irq(unsigned int irq)
+{
+ mask_uart_irq(irq);
+}
+
+/*
+ * End IRQ processing
+ */
+static void end_uart_irq(unsigned int irq)
+{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+ unmask_uart_irq(irq);
+}
+
+/*
+ * Interrupt handler for interrupts coming from the FPGA chip.
+ */
+void ll_uart_irq(struct pt_regs *regs)
+{
+ unsigned int irq_src, irq_mask;
+
+ /* read the interrupt status registers */
+ irq_src = OCELOT_FPGA_READ(UART_INTSTAT);
+ irq_mask = OCELOT_FPGA_READ(UART_INTMASK);
+
+ /* mask for just the interrupts we want */
+ irq_src &= ~irq_mask;
+
+ do_IRQ(ls1bit8(irq_src) + 74, regs);
+}
+
+#define shutdown_uart_irq disable_uart_irq
+
+struct hw_interrupt_type uart_irq_type = {
+ "UART/FPGA",
+ startup_uart_irq,
+ shutdown_uart_irq,
+ enable_uart_irq,
+ disable_uart_irq,
+ mask_and_ack_uart_irq,
+ end_uart_irq,
+ NULL
+};
+
+void uart_irq_init(void)
+{
+ /* Reset irq handlers pointers to NULL */
+ irq_desc[80].status = IRQ_DISABLED;
+ irq_desc[80].action = 0;
+ irq_desc[80].depth = 2;
+ irq_desc[80].handler = &uart_irq_type;
+
+ irq_desc[81].status = IRQ_DISABLED;
+ irq_desc[81].action = 0;
+ irq_desc[81].depth = 2;
+ irq_desc[81].handler = &uart_irq_type;
+}
diff --git a/arch/mips/momentum/ocelot_g/Makefile b/arch/mips/momentum/ocelot_g/Makefile
new file mode 100644
index 0000000..e5f1cb0
--- /dev/null
+++ b/arch/mips/momentum/ocelot_g/Makefile
@@ -0,0 +1,8 @@
+#
+# Makefile for Momentum Computer's Ocelot-G board.
+#
+
+obj-y += int-handler.o irq.o gt-irq.o prom.o reset.o setup.o
+obj-$(CONFIG_KGDB) += dbg_io.o
+
+EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/momentum/ocelot_g/dbg_io.c b/arch/mips/momentum/ocelot_g/dbg_io.c
new file mode 100644
index 0000000..8720bcc
--- /dev/null
+++ b/arch/mips/momentum/ocelot_g/dbg_io.c
@@ -0,0 +1,126 @@
+#include <linux/config.h>
+
+#ifdef CONFIG_KGDB
+
+#include <asm/serial.h> /* For the serial port location and base baud */
+
+/* --- CONFIG --- */
+
+typedef unsigned char uint8;
+typedef unsigned int uint32;
+
+/* --- END OF CONFIG --- */
+
+#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
+
+/* ----------------------------------------------------- */
+
+/* === CONFIG === */
+
+/* [jsun] we use the second serial port for kdb */
+#define BASE OCELOT_SERIAL1_BASE
+#define MAX_BAUD OCELOT_BASE_BAUD
+
+/* === END OF CONFIG === */
+
+#define REG_OFFSET 4
+
+/* register offset */
+#define OFS_RCV_BUFFER 0
+#define OFS_TRANS_HOLD 0
+#define OFS_SEND_BUFFER 0
+#define OFS_INTR_ENABLE (1*REG_OFFSET)
+#define OFS_INTR_ID (2*REG_OFFSET)
+#define OFS_DATA_FORMAT (3*REG_OFFSET)
+#define OFS_LINE_CONTROL (3*REG_OFFSET)
+#define OFS_MODEM_CONTROL (4*REG_OFFSET)
+#define OFS_RS232_OUTPUT (4*REG_OFFSET)
+#define OFS_LINE_STATUS (5*REG_OFFSET)
+#define OFS_MODEM_STATUS (6*REG_OFFSET)
+#define OFS_RS232_INPUT (6*REG_OFFSET)
+#define OFS_SCRATCH_PAD (7*REG_OFFSET)
+
+#define OFS_DIVISOR_LSB (0*REG_OFFSET)
+#define OFS_DIVISOR_MSB (1*REG_OFFSET)
+
+
+/* memory-mapped read/write of the port */
+#define UART16550_READ(y) (*((volatile uint8*)(BASE + y)))
+#define UART16550_WRITE(y, z) ((*((volatile uint8*)(BASE + y))) = z)
+
+void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop)
+{
+ /* disable interrupts */
+ UART16550_WRITE(OFS_INTR_ENABLE, 0);
+
+ /* set up buad rate */
+ {
+ uint32 divisor;
+
+ /* set DIAB bit */
+ UART16550_WRITE(OFS_LINE_CONTROL, 0x80);
+
+ /* set divisor */
+ divisor = MAX_BAUD / baud;
+ UART16550_WRITE(OFS_DIVISOR_LSB, divisor & 0xff);
+ UART16550_WRITE(OFS_DIVISOR_MSB, (divisor & 0xff00) >> 8);
+
+ /* clear DIAB bit */
+ UART16550_WRITE(OFS_LINE_CONTROL, 0x0);
+ }
+
+ /* set data format */
+ UART16550_WRITE(OFS_DATA_FORMAT, data | parity | stop);
+}
+
+static int remoteDebugInitialized = 0;
+
+uint8 getDebugChar(void)
+{
+ if (!remoteDebugInitialized) {
+ remoteDebugInitialized = 1;
+ debugInit(UART16550_BAUD_38400,
+ UART16550_DATA_8BIT,
+ UART16550_PARITY_NONE, UART16550_STOP_1BIT);
+ }
+
+ while ((UART16550_READ(OFS_LINE_STATUS) & 0x1) == 0);
+ return UART16550_READ(OFS_RCV_BUFFER);
+}
+
+
+int putDebugChar(uint8 byte)
+{
+ if (!remoteDebugInitialized) {
+ remoteDebugInitialized = 1;
+ debugInit(UART16550_BAUD_38400,
+ UART16550_DATA_8BIT,
+ UART16550_PARITY_NONE, UART16550_STOP_1BIT);
+ }
+
+ while ((UART16550_READ(OFS_LINE_STATUS) & 0x20) == 0);
+ UART16550_WRITE(OFS_SEND_BUFFER, byte);
+ return 1;
+}
+
+#endif
diff --git a/arch/mips/momentum/ocelot_g/gt-irq.c b/arch/mips/momentum/ocelot_g/gt-irq.c
new file mode 100644
index 0000000..d0b5c9d
--- /dev/null
+++ b/arch/mips/momentum/ocelot_g/gt-irq.c
@@ -0,0 +1,214 @@
+/*
+ *
+ * Copyright 2002 Momentum Computer
+ * Author: mdharm@momenco.com
+ *
+ * arch/mips/momentum/ocelot_g/gt_irq.c
+ * Interrupt routines for gt64240. Currently it only handles timer irq.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <asm/ptrace.h>
+#include <linux/sched.h>
+#include <linux/kernel_stat.h>
+#include <asm/gt64240.h>
+#include <asm/io.h>
+
+unsigned long bus_clock;
+
+/*
+ * These are interrupt handlers for the GT on-chip interrupts. They
+ * all come in to the MIPS on a single interrupt line, and have to
+ * be handled and ack'ed differently than other MIPS interrupts.
+ */
+
+#if CURRENTLY_UNUSED
+
+struct tq_struct irq_handlers[MAX_CAUSE_REGS][MAX_CAUSE_REG_WIDTH];
+void hook_irq_handler(int int_cause, int bit_num, void *isr_ptr);
+
+/*
+ * Hooks IRQ handler to the system. When the system is interrupted
+ * the interrupt service routine is called.
+ *
+ * Inputs :
+ * int_cause - The interrupt cause number. In EVB64120 two parameters
+ * are declared, INT_CAUSE_MAIN and INT_CAUSE_HIGH.
+ * bit_num - Indicates which bit number in the cause register
+ * isr_ptr - Pointer to the interrupt service routine
+ */
+void hook_irq_handler(int int_cause, int bit_num, void *isr_ptr)
+{
+ irq_handlers[int_cause][bit_num].routine = isr_ptr;
+}
+
+
+/*
+ * Enables the IRQ on Galileo Chip
+ *
+ * Inputs :
+ * int_cause - The interrupt cause number. In EVB64120 two parameters
+ * are declared, INT_CAUSE_MAIN and INT_CAUSE_HIGH.
+ * bit_num - Indicates which bit number in the cause register
+ *
+ * Outputs :
+ * 1 if succesful, 0 if failure
+ */
+int enable_galileo_irq(int int_cause, int bit_num)
+{
+ if (int_cause == INT_CAUSE_MAIN)
+ SET_REG_BITS(CPU_INTERRUPT_MASK_REGISTER, (1 << bit_num));
+ else if (int_cause == INT_CAUSE_HIGH)
+ SET_REG_BITS(CPU_HIGH_INTERRUPT_MASK_REGISTER,
+ (1 << bit_num));
+ else
+ return 0;
+
+ return 1;
+}
+
+/*
+ * Disables the IRQ on Galileo Chip
+ *
+ * Inputs :
+ * int_cause - The interrupt cause number. In EVB64120 two parameters
+ * are declared, INT_CAUSE_MAIN and INT_CAUSE_HIGH.
+ * bit_num - Indicates which bit number in the cause register
+ *
+ * Outputs :
+ * 1 if succesful, 0 if failure
+ */
+int disable_galileo_irq(int int_cause, int bit_num)
+{
+ if (int_cause == INT_CAUSE_MAIN)
+ RESET_REG_BITS(CPU_INTERRUPT_MASK_REGISTER,
+ (1 << bit_num));
+ else if (int_cause == INT_CAUSE_HIGH)
+ RESET_REG_BITS(CPU_HIGH_INTERRUPT_MASK_REGISTER,
+ (1 << bit_num));
+ else
+ return 0;
+ return 1;
+}
+#endif /* UNUSED */
+
+/*
+ * Interrupt handler for interrupts coming from the Galileo chip via P0_INT#.
+ *
+ * We route the timer interrupt to P0_INT# (IRQ 6), and that's all this
+ * routine can handle, for now.
+ *
+ * In the future, we'll route more interrupts to this pin, and that's why
+ * we keep this particular structure in the function.
+ */
+
+static irqreturn_t gt64240_p0int_irq(int irq, void *dev, struct pt_regs *regs)
+{
+ uint32_t irq_src, irq_src_mask;
+ int handled;
+
+ /* get the low interrupt cause register */
+ irq_src = MV_READ(LOW_INTERRUPT_CAUSE_REGISTER);
+
+ /* get the mask register for this pin */
+ irq_src_mask = MV_READ(PCI_0INTERRUPT_CAUSE_MASK_REGISTER_LOW);
+
+ /* mask off only the interrupts we're interested in */
+ irq_src = irq_src & irq_src_mask;
+
+ handled = IRQ_NONE;
+
+ /* Check for timer interrupt */
+ if (irq_src & 0x00000100) {
+ handled = IRQ_HANDLED;
+ irq_src &= ~0x00000100;
+
+ /* Clear any pending cause bits */
+ MV_WRITE(TIMER_COUNTER_0_3_INTERRUPT_CAUSE, 0x0);
+
+ /* handle the timer call */
+ do_timer(regs);
+#ifndef CONFIG_SMP
+ update_process_times(user_mode(regs));
+#endif
+ }
+
+ if (irq_src) {
+ printk(KERN_INFO
+ "UNKNOWN P0_INT# interrupt received, irq_src=0x%x\n",
+ irq_src);
+ }
+
+ return handled;
+}
+
+/*
+ * Initializes timer using galileo's built in timer.
+ */
+
+/*
+ * This will ignore the standard MIPS timer interrupt handler
+ * that is passed in as *irq (=irq0 in ../kernel/time.c).
+ * We will do our own timer interrupt handling.
+ */
+void gt64240_time_init(void)
+{
+ static struct irqaction timer;
+
+ /* Stop the timer -- we'll use timer #0 */
+ MV_WRITE(TIMER_COUNTER_0_3_CONTROL, 0x0);
+
+ /* Load timer value for 100 Hz */
+ MV_WRITE(TIMER_COUNTER0, bus_clock / 100);
+
+ /*
+ * Create the IRQ structure entry for the timer. Since we're too early
+ * in the boot process to use the "request_irq()" call, we'll hard-code
+ * the values to the correct interrupt line.
+ */
+ timer.handler = >64240_p0int_irq;
+ timer.flags = SA_SHIRQ | SA_INTERRUPT;
+ timer.name = "timer";
+ timer.dev_id = NULL;
+ timer.next = NULL;
+ timer.mask = 0;
+ irq_desc[6].action = &timer;
+
+ enable_irq(6);
+
+ /* Clear any pending cause bits */
+ MV_WRITE(TIMER_COUNTER_0_3_INTERRUPT_CAUSE, 0x0);
+
+ /* Enable the interrupt for timer 0 */
+ MV_WRITE(TIMER_COUNTER_0_3_INTERRUPT_MASK, 0x1);
+
+ /* Enable the timer interrupt for GT-64240 pin P0_INT# */
+ MV_WRITE (PCI_0INTERRUPT_CAUSE_MASK_REGISTER_LOW, 0x100);
+
+ /* Configure and start the timer */
+ MV_WRITE(TIMER_COUNTER_0_3_CONTROL, 0x3);
+}
+
+void gt64240_irq_init(void)
+{
+#if CURRENTLY_UNUSED
+ int i, j;
+
+ /* Reset irq handlers pointers to NULL */
+ for (i = 0; i < MAX_CAUSE_REGS; i++) {
+ for (j = 0; j < MAX_CAUSE_REG_WIDTH; j++) {
+ irq_handlers[i][j].next = NULL;
+ irq_handlers[i][j].sync = 0;
+ irq_handlers[i][j].routine = NULL;
+ irq_handlers[i][j].data = NULL;
+ }
+ }
+#endif
+}
diff --git a/arch/mips/momentum/ocelot_g/int-handler.S b/arch/mips/momentum/ocelot_g/int-handler.S
new file mode 100644
index 0000000..772e8f7
--- /dev/null
+++ b/arch/mips/momentum/ocelot_g/int-handler.S
@@ -0,0 +1,131 @@
+/*
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: jsun@mvista.com or jsun@junsun.net
+ *
+ * First-level interrupt dispatcher for ocelot board.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+#include <asm/asm.h>
+#include <asm/mipsregs.h>
+#include <asm/addrspace.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+
+/*
+ * first level interrupt dispatcher for ocelot board -
+ * We check for the timer first, then check PCI ints A and D.
+ * Then check for serial IRQ and fall through.
+ */
+ .align 5
+ NESTED(ocelot_handle_int, PT_SIZE, sp)
+ SAVE_ALL
+ CLI
+ .set at
+ mfc0 t0, CP0_CAUSE
+ mfc0 t2, CP0_STATUS
+
+ and t0, t2
+
+ andi t1, t0, STATUSF_IP2 /* int0 hardware line */
+ bnez t1, ll_pri_enet_irq
+ andi t1, t0, STATUSF_IP3 /* int1 hardware line */
+ bnez t1, ll_sec_enet_irq
+ andi t1, t0, STATUSF_IP4 /* int2 hardware line */
+ bnez t1, ll_uart_irq
+ andi t1, t0, STATUSF_IP5 /* int3 hardware line */
+ bnez t1, ll_cpci_irq
+ andi t1, t0, STATUSF_IP6 /* int4 hardware line */
+ bnez t1, ll_galileo_p0_irq
+ andi t1, t0, STATUSF_IP7 /* cpu timer */
+ bnez t1, ll_cputimer_irq
+
+ /* now look at the extended interrupts */
+ mfc0 t0, CP0_CAUSE
+ cfc0 t1, CP0_S1_INTCONTROL
+
+ /* shift the mask 8 bits left to line up the bits */
+ sll t2, t1, 8
+
+ and t0, t2
+ srl t0, t0, 16
+
+ andi t1, t0, STATUSF_IP8 /* int6 hardware line */
+ bnez t1, ll_galileo_p1_irq
+ andi t1, t0, STATUSF_IP9 /* int7 hardware line */
+ bnez t1, ll_pmc_irq
+ andi t1, t0, STATUSF_IP10 /* int8 hardware line */
+ bnez t1, ll_cpci_abcd_irq
+ andi t1, t0, STATUSF_IP11 /* int9 hardware line */
+ bnez t1, ll_testpoint_irq
+
+ .set reorder
+
+ /* wrong alarm or masked ... */
+ j spurious_interrupt
+ nop
+ END(ocelot_handle_int)
+
+ .align 5
+ll_pri_enet_irq:
+ li a0, 2
+ move a1, sp
+ jal do_IRQ
+ j ret_from_irq
+
+ll_sec_enet_irq:
+ li a0, 3
+ move a1, sp
+ jal do_IRQ
+ j ret_from_irq
+
+ll_uart_irq:
+ li a0, 4
+ move a1, sp
+ jal do_IRQ
+ j ret_from_irq
+
+ll_cpci_irq:
+ li a0, 5
+ move a1, sp
+ jal do_IRQ
+ j ret_from_irq
+
+ll_galileo_p0_irq:
+ li a0, 6
+ move a1, sp
+ jal do_IRQ
+ j ret_from_irq
+
+ll_cputimer_irq:
+ li a0, 7
+ move a1, sp
+ jal do_IRQ
+ j ret_from_irq
+
+ll_galileo_p1_irq:
+ li a0, 8
+ move a1, sp
+ jal do_IRQ
+ j ret_from_irq
+
+ll_pmc_irq:
+ li a0, 9
+ move a1, sp
+ jal do_IRQ
+ j ret_from_irq
+
+ll_cpci_abcd_irq:
+ li a0, 10
+ move a1, sp
+ jal do_IRQ
+ j ret_from_irq
+
+ll_testpoint_irq:
+ li a0, 11
+ move a1, sp
+ jal do_IRQ
+ j ret_from_irq
diff --git a/arch/mips/momentum/ocelot_g/irq.c b/arch/mips/momentum/ocelot_g/irq.c
new file mode 100644
index 0000000..5eb85b1
--- /dev/null
+++ b/arch/mips/momentum/ocelot_g/irq.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2000 RidgeRun, Inc.
+ * Author: RidgeRun, Inc.
+ * glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
+ * Copyright (C) 2000, 01, 05 Ralf Baechle (ralf@linux-mips.org)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel_stat.h>
+#include <linux/module.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/timex.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+#include <linux/bitops.h>
+#include <asm/bootinfo.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/irq_cpu.h>
+#include <asm/mipsregs.h>
+#include <asm/system.h>
+
+extern asmlinkage void ocelot_handle_int(void);
+extern void gt64240_irq_init(void);
+
+void __init arch_init_irq(void)
+{
+ /*
+ * Clear all of the interrupts while we change the able around a bit.
+ * int-handler is not on bootstrap
+ */
+ clear_c0_status(ST0_IM);
+ local_irq_disable();
+
+ /* Sets the first-level interrupt dispatcher. */
+ set_except_vector(0, ocelot_handle_int);
+ mips_cpu_irq_init(0);
+ rm7k_cpu_irq_init(8);
+
+ gt64240_irq_init();
+}
diff --git a/arch/mips/momentum/ocelot_g/ocelot_pld.h b/arch/mips/momentum/ocelot_g/ocelot_pld.h
new file mode 100644
index 0000000..fcb8275
--- /dev/null
+++ b/arch/mips/momentum/ocelot_g/ocelot_pld.h
@@ -0,0 +1,30 @@
+/*
+ * Ocelot Board Register Definitions
+ *
+ * (C) 2001 Red Hat, Inc.
+ *
+ * GPL'd
+ */
+#ifndef __MOMENCO_OCELOT_PLD_H__
+#define __MOMENCO_OCELOT_PLD_H__
+
+#define OCELOT_CS0_ADDR (0xfc000000)
+
+#define OCELOT_REG_BOARDREV (0)
+#define OCELOT_REG_PLD1_ID (1)
+#define OCELOT_REG_PLD2_ID (2)
+#define OCELOT_REG_RESET_STATUS (3)
+#define OCELOT_REG_BOARD_STATUS (4)
+#define OCELOT_REG_CPCI_ID (5)
+#define OCELOT_REG_I2C_CTRL (8)
+#define OCELOT_REG_EEPROM_MODE (9)
+#define OCELOT_REG_INTMASK (10)
+#define OCELOT_REG_INTSTATUS (11)
+#define OCELOT_REG_INTSET (12)
+#define OCELOT_REG_INTCLR (13)
+
+#define OCELOT_PLD_WRITE(x, y) writeb(x, OCELOT_CS0_ADDR + OCELOT_REG_##y)
+#define OCELOT_PLD_READ(x) readb(OCELOT_CS0_ADDR + OCELOT_REG_##x)
+
+
+#endif /* __MOMENCO_OCELOT_PLD_H__ */
diff --git a/arch/mips/momentum/ocelot_g/prom.c b/arch/mips/momentum/ocelot_g/prom.c
new file mode 100644
index 0000000..6b4f577
--- /dev/null
+++ b/arch/mips/momentum/ocelot_g/prom.c
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2002 Momentum Computer Inc.
+ * Author: Matthew Dharm <mdharm@momenco.com>
+ *
+ * Based on Ocelot Linux port, which is
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: jsun@mvista.com or jsun@junsun.net
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/bootmem.h>
+
+#include <asm/addrspace.h>
+#include <asm/bootinfo.h>
+#include <asm/pmon.h>
+#include <asm/gt64240.h>
+
+#include "ocelot_pld.h"
+
+struct callvectors* debug_vectors;
+
+extern unsigned long marvell_base;
+extern unsigned long bus_clock;
+
+#ifdef CONFIG_GALILLEO_GT64240_ETH
+extern unsigned char prom_mac_addr_base[6];
+#endif
+
+const char *get_system_type(void)
+{
+ return "Momentum Ocelot";
+}
+
+void __init prom_init(void)
+{
+ int argc = fw_arg0;
+ char **arg = (char **) fw_arg1;
+ char **env = (char **) fw_arg2;
+ struct callvectors *cv = (struct callvectors *) fw_arg3;
+ int i;
+
+ /* save the PROM vectors for debugging use */
+ debug_vectors = cv;
+
+ /* arg[0] is "g", the rest is boot parameters */
+ arcs_cmdline[0] = '\0';
+ for (i = 1; i < argc; i++) {
+ if (strlen(arcs_cmdline) + strlen(arg[i] + 1)
+ >= sizeof(arcs_cmdline))
+ break;
+ strcat(arcs_cmdline, arg[i]);
+ strcat(arcs_cmdline, " ");
+ }
+
+ mips_machgroup = MACH_GROUP_MOMENCO;
+ mips_machtype = MACH_MOMENCO_OCELOT_G;
+
+#ifdef CONFIG_GALILLEO_GT64240_ETH
+ /* get the base MAC address for on-board ethernet ports */
+ memcpy(prom_mac_addr_base, (void*)0xfc807cf2, 6);
+#endif
+
+ while (*env) {
+ if (strncmp("gtbase", *env, strlen("gtbase")) == 0) {
+ marvell_base = simple_strtol(*env + strlen("gtbase="),
+ NULL, 16);
+ }
+ if (strncmp("busclock", *env, strlen("busclock")) == 0) {
+ bus_clock = simple_strtol(*env + strlen("busclock="),
+ NULL, 10);
+ }
+ env++;
+ }
+}
+
+unsigned long __init prom_free_prom_memory(void)
+{
+ return 0;
+}
diff --git a/arch/mips/momentum/ocelot_g/reset.c b/arch/mips/momentum/ocelot_g/reset.c
new file mode 100644
index 0000000..3fd499a
--- /dev/null
+++ b/arch/mips/momentum/ocelot_g/reset.c
@@ -0,0 +1,47 @@
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * Copyright (C) 1997, 2001 Ralf Baechle
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: jsun@mvista.com or jsun@junsun.net
+ */
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/reboot.h>
+#include <asm/system.h>
+#include <linux/delay.h>
+
+void momenco_ocelot_restart(char *command)
+{
+ void *nvram = ioremap_nocache(0x2c807000, 0x1000);
+
+ if (!nvram) {
+ printk(KERN_NOTICE "ioremap of reset register failed\n");
+ return;
+ }
+ writeb(0x84, nvram + 0xff7); /* Ask the NVRAM/RTC/watchdog chip to
+ assert reset in 1/16 second */
+ mdelay(10+(1000/16));
+ iounmap(nvram);
+ printk(KERN_NOTICE "Watchdog reset failed\n");
+}
+
+void momenco_ocelot_halt(void)
+{
+ printk(KERN_NOTICE "\n** You can safely turn off the power\n");
+ while (1)
+ __asm__(".set\tmips3\n\t"
+ "wait\n\t"
+ ".set\tmips0");
+}
+
+void momenco_ocelot_power_off(void)
+{
+ momenco_ocelot_halt();
+}
diff --git a/arch/mips/momentum/ocelot_g/setup.c b/arch/mips/momentum/ocelot_g/setup.c
new file mode 100644
index 0000000..38a78ab
--- /dev/null
+++ b/arch/mips/momentum/ocelot_g/setup.c
@@ -0,0 +1,266 @@
+/*
+ * BRIEF MODULE DESCRIPTION
+ * Momentum Computer Ocelot-G (CP7000G) - board dependent boot routines
+ *
+ * Copyright (C) 1996, 1997, 2001 Ralf Baechle
+ * Copyright (C) 2000 RidgeRun, Inc.
+ * Copyright (C) 2001 Red Hat, Inc.
+ * Copyright (C) 2002 Momentum Computer
+ *
+ * Author: Matthew Dharm, Momentum Computer
+ * mdharm@momenco.com
+ *
+ * Author: RidgeRun, Inc.
+ * glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: jsun@mvista.com or jsun@junsun.net
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/swap.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/timex.h>
+#include <linux/vmalloc.h>
+#include <asm/time.h>
+#include <asm/bootinfo.h>
+#include <asm/page.h>
+#include <asm/io.h>
+#include <asm/gt64240.h>
+#include <asm/irq.h>
+#include <asm/pci.h>
+#include <asm/processor.h>
+#include <asm/ptrace.h>
+#include <asm/reboot.h>
+#include <linux/bootmem.h>
+
+#include "ocelot_pld.h"
+
+#ifdef CONFIG_GALILLEO_GT64240_ETH
+extern unsigned char prom_mac_addr_base[6];
+#endif
+
+unsigned long marvell_base;
+
+/* These functions are used for rebooting or halting the machine*/
+extern void momenco_ocelot_restart(char *command);
+extern void momenco_ocelot_halt(void);
+extern void momenco_ocelot_power_off(void);
+
+extern void gt64240_time_init(void);
+extern void momenco_ocelot_irq_setup(void);
+
+static char reset_reason;
+
+static unsigned long ENTRYLO(unsigned long paddr)
+{
+ return ((paddr & PAGE_MASK) |
+ (_PAGE_PRESENT | __READABLE | __WRITEABLE | _PAGE_GLOBAL |
+ _CACHE_UNCACHED)) >> 6;
+}
+
+/* setup code for a handoff from a version 2 PMON 2000 PROM */
+void PMON_v2_setup(void)
+{
+ /* A wired TLB entry for the GT64240 and the serial port. The
+ GT64240 is going to be hit on every IRQ anyway - there's
+ absolutely no point in letting it be a random TLB entry, as
+ it'll just cause needless churning of the TLB. And we use
+ the other half for the serial port, which is just a PITA
+ otherwise :)
+
+ Device Physical Virtual
+ GT64240 Internal Regs 0xf4000000 0xe0000000
+ UARTs (CS2) 0xfd000000 0xe0001000
+ */
+ add_wired_entry(ENTRYLO(0xf4000000), ENTRYLO(0xf4010000),
+ 0xf4000000, PM_64K);
+ add_wired_entry(ENTRYLO(0xfd000000), ENTRYLO(0xfd001000),
+ 0xfd000000, PM_4K);
+
+ /* Also a temporary entry to let us talk to the Ocelot PLD and NVRAM
+ in the CS[012] region. We can't use ioremap() yet. The NVRAM
+ is a ST M48T37Y, which includes NVRAM, RTC, and Watchdog functions.
+
+ Ocelot PLD (CS0) 0xfc000000 0xe0020000
+ NVRAM (CS1) 0xfc800000 0xe0030000
+ */
+ add_temporary_entry(ENTRYLO(0xfc000000), ENTRYLO(0xfc010000),
+ 0xfc000000, PM_64K);
+ add_temporary_entry(ENTRYLO(0xfc800000), ENTRYLO(0xfc810000),
+ 0xfc800000, PM_64K);
+
+ marvell_base = 0xf4000000;
+}
+
+extern int rm7k_tcache_enabled;
+
+/*
+ * This runs in KSEG1. See the verbiage in rm7k.c::probe_scache()
+ */
+#define Page_Invalidate_T 0x16
+static void __init setup_l3cache(unsigned long size)
+{
+ int register i;
+
+ printk("Enabling L3 cache...");
+
+ /* Enable the L3 cache in the GT64120A's CPU Configuration register */
+ MV_WRITE(0, MV_READ(0) | (1<<14));
+
+ /* Enable the L3 cache in the CPU */
+ set_c0_config(1<<12 /* CONF_TE */);
+
+ /* Clear the cache */
+ write_c0_taglo(0);
+ write_c0_taghi(0);
+
+ for (i=0; i < size; i+= 4096) {
+ __asm__ __volatile__ (
+ ".set noreorder\n\t"
+ ".set mips3\n\t"
+ "cache %1, (%0)\n\t"
+ ".set mips0\n\t"
+ ".set reorder"
+ :
+ : "r" (KSEG0ADDR(i)),
+ "i" (Page_Invalidate_T));
+ }
+
+ /* Let the RM7000 MM code know that the tertiary cache is enabled */
+ rm7k_tcache_enabled = 1;
+
+ printk("Done\n");
+}
+
+static int __init momenco_ocelot_g_setup(void)
+{
+ void (*l3func)(unsigned long) = (void *) KSEG1ADDR(setup_l3cache);
+ unsigned int tmpword;
+
+ board_time_init = gt64240_time_init;
+
+ _machine_restart = momenco_ocelot_restart;
+ _machine_halt = momenco_ocelot_halt;
+ _machine_power_off = momenco_ocelot_power_off;
+
+ /*
+ * initrd_start = (ulong)ocelot_initrd_start;
+ * initrd_end = (ulong)ocelot_initrd_start + (ulong)ocelot_initrd_size;
+ * initrd_below_start_ok = 1;
+ */
+
+ /* do handoff reconfiguration */
+ PMON_v2_setup();
+
+#ifdef CONFIG_GALILLEO_GT64240_ETH
+ /* get the mac addr */
+ memcpy(prom_mac_addr_base, (void*)0xfc807cf2, 6);
+#endif
+
+ /* Turn off the Bit-Error LED */
+ OCELOT_PLD_WRITE(0x80, INTCLR);
+
+ tmpword = OCELOT_PLD_READ(BOARDREV);
+ if (tmpword < 26)
+ printk("Momenco Ocelot-G: Board Assembly Rev. %c\n", 'A'+tmpword);
+ else
+ printk("Momenco Ocelot-G: Board Assembly Revision #0x%x\n", tmpword);
+
+ tmpword = OCELOT_PLD_READ(PLD1_ID);
+ printk("PLD 1 ID: %d.%d\n", tmpword>>4, tmpword&15);
+ tmpword = OCELOT_PLD_READ(PLD2_ID);
+ printk("PLD 2 ID: %d.%d\n", tmpword>>4, tmpword&15);
+ tmpword = OCELOT_PLD_READ(RESET_STATUS);
+ printk("Reset reason: 0x%x\n", tmpword);
+ reset_reason = tmpword;
+ OCELOT_PLD_WRITE(0xff, RESET_STATUS);
+
+ tmpword = OCELOT_PLD_READ(BOARD_STATUS);
+ printk("Board Status register: 0x%02x\n", tmpword);
+ printk(" - User jumper: %s\n", (tmpword & 0x80)?"installed":"absent");
+ printk(" - Boot flash write jumper: %s\n", (tmpword&0x40)?"installed":"absent");
+ printk(" - Tulip PHY %s connected\n", (tmpword&0x10)?"is":"not");
+ printk(" - L3 Cache size: %d MiB\n", (1<<((tmpword&12) >> 2))&~1);
+ printk(" - SDRAM size: %d MiB\n", 1<<(6+(tmpword&3)));
+
+ if (tmpword&12)
+ l3func((1<<(((tmpword&12) >> 2)+20)));
+
+ switch(tmpword &3) {
+ case 3:
+ /* 512MiB -- two banks of 256MiB */
+ add_memory_region( 0x0<<20, 0x100<<20, BOOT_MEM_RAM);
+/*
+ add_memory_region(0x100<<20, 0x100<<20, BOOT_MEM_RAM);
+*/
+ break;
+ case 2:
+ /* 256MiB -- two banks of 128MiB */
+ add_memory_region( 0x0<<20, 0x80<<20, BOOT_MEM_RAM);
+ add_memory_region(0x80<<20, 0x80<<20, BOOT_MEM_RAM);
+ break;
+ case 1:
+ /* 128MiB -- 64MiB per bank */
+ add_memory_region( 0x0<<20, 0x40<<20, BOOT_MEM_RAM);
+ add_memory_region(0x40<<20, 0x40<<20, BOOT_MEM_RAM);
+ break;
+ case 0:
+ /* 64MiB */
+ add_memory_region( 0x0<<20, 0x40<<20, BOOT_MEM_RAM);
+ break;
+ }
+
+ /* FIXME: Fix up the DiskOnChip mapping */
+ MV_WRITE(0x468, 0xfef73);
+
+ return 0;
+}
+
+early_initcall(momenco_ocelot_g_setup);
+
+/* This needs to be one of the first initcalls, because no I/O port access
+ can work before this */
+
+static int io_base_ioremap(void)
+{
+ /* we're mapping PCI accesses from 0xc0000000 to 0xf0000000 */
+ unsigned long io_remap_range;
+
+ io_remap_range = (unsigned long) ioremap(0xc0000000, 0x30000000);
+ if (!io_remap_range)
+ panic("Could not ioremap I/O port range");
+
+ set_io_port_base(io_remap_range - 0xc0000000);
+
+ return 0;
+}
+
+module_init(io_base_ioremap);
diff --git a/arch/mips/oprofile/Kconfig b/arch/mips/oprofile/Kconfig
new file mode 100644
index 0000000..19d3773
--- /dev/null
+++ b/arch/mips/oprofile/Kconfig
@@ -0,0 +1,23 @@
+
+menu "Profiling support"
+ depends on EXPERIMENTAL
+
+config PROFILING
+ bool "Profiling support (EXPERIMENTAL)"
+ help
+ Say Y here to enable the extended profiling support mechanisms used
+ by profilers such as OProfile.
+
+
+config OPROFILE
+ tristate "OProfile system profiling (EXPERIMENTAL)"
+ depends on PROFILING
+ help
+ OProfile is a profiling system capable of profiling the
+ whole system, include the kernel, kernel modules, libraries,
+ and applications.
+
+ If unsure, say N.
+
+endmenu
+
diff --git a/arch/mips/oprofile/Makefile b/arch/mips/oprofile/Makefile
new file mode 100644
index 0000000..354261d
--- /dev/null
+++ b/arch/mips/oprofile/Makefile
@@ -0,0 +1,15 @@
+EXTRA_CFLAGS := -Werror
+
+obj-$(CONFIG_OPROFILE) += oprofile.o
+
+DRIVER_OBJS = $(addprefix ../../../drivers/oprofile/, \
+ oprof.o cpu_buffer.o buffer_sync.o \
+ event_buffer.o oprofile_files.o \
+ oprofilefs.o oprofile_stats.o \
+ timer_int.o )
+
+oprofile-y := $(DRIVER_OBJS) common.o
+
+oprofile-$(CONFIG_CPU_MIPS32) += op_model_mipsxx.o
+oprofile-$(CONFIG_CPU_MIPS64) += op_model_mipsxx.o
+oprofile-$(CONFIG_CPU_RM9000) += op_model_rm9000.o
diff --git a/arch/mips/oprofile/common.c b/arch/mips/oprofile/common.c
new file mode 100644
index 0000000..ab65ce3
--- /dev/null
+++ b/arch/mips/oprofile/common.c
@@ -0,0 +1,106 @@
+/*
+ * 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) 2004 by Ralf Baechle
+ */
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/oprofile.h>
+#include <linux/smp.h>
+#include <asm/cpu-info.h>
+
+#include "op_impl.h"
+
+extern struct op_mips_model op_model_mipsxx __attribute__((weak));
+extern struct op_mips_model op_model_rm9000 __attribute__((weak));
+
+static struct op_mips_model *model;
+
+static struct op_counter_config ctr[20];
+
+static int op_mips_setup(void)
+{
+ /* Pre-compute the values to stuff in the hardware registers. */
+ model->reg_setup(ctr);
+
+ /* Configure the registers on all cpus. */
+ on_each_cpu(model->cpu_setup, 0, 0, 1);
+
+ return 0;
+}
+
+static int op_mips_create_files(struct super_block * sb, struct dentry * root)
+{
+ int i;
+
+ for (i = 0; i < model->num_counters; ++i) {
+ struct dentry *dir;
+ char buf[3];
+
+ snprintf(buf, sizeof buf, "%d", i);
+ dir = oprofilefs_mkdir(sb, root, buf);
+
+ oprofilefs_create_ulong(sb, dir, "enabled", &ctr[i].enabled);
+ oprofilefs_create_ulong(sb, dir, "event", &ctr[i].event);
+ oprofilefs_create_ulong(sb, dir, "count", &ctr[i].count);
+ /* Dummies. */
+ oprofilefs_create_ulong(sb, dir, "kernel", &ctr[i].kernel);
+ oprofilefs_create_ulong(sb, dir, "user", &ctr[i].user);
+ oprofilefs_create_ulong(sb, dir, "exl", &ctr[i].exl);
+ oprofilefs_create_ulong(sb, dir, "unit_mask", &ctr[i].unit_mask);
+ }
+
+ return 0;
+}
+
+static int op_mips_start(void)
+{
+ on_each_cpu(model->cpu_start, NULL, 0, 1);
+
+ return 0;
+}
+
+static void op_mips_stop(void)
+{
+ /* Disable performance monitoring for all counters. */
+ on_each_cpu(model->cpu_stop, NULL, 0, 1);
+}
+
+void __init oprofile_arch_init(struct oprofile_operations *ops)
+{
+ struct op_mips_model *lmodel = NULL;
+
+ switch (current_cpu_data.cputype) {
+ case CPU_24K:
+ lmodel = &op_model_mipsxx;
+ break;
+
+ case CPU_RM9000:
+ lmodel = &op_model_rm9000;
+ break;
+ };
+
+ if (!lmodel)
+ return;
+
+ if (lmodel->init())
+ return;
+
+ model = lmodel;
+
+ ops->create_files = op_mips_create_files;
+ ops->setup = op_mips_setup;
+ ops->start = op_mips_start;
+ ops->stop = op_mips_stop;
+ ops->cpu_type = lmodel->cpu_type;
+
+ printk(KERN_INFO "oprofile: using %s performance monitoring.\n",
+ lmodel->cpu_type);
+}
+
+void oprofile_arch_exit(void)
+{
+ model->exit();
+}
diff --git a/arch/mips/oprofile/op_impl.h b/arch/mips/oprofile/op_impl.h
new file mode 100644
index 0000000..9f5cdff
--- /dev/null
+++ b/arch/mips/oprofile/op_impl.h
@@ -0,0 +1,37 @@
+/**
+ * @file arch/alpha/oprofile/op_impl.h
+ *
+ * @remark Copyright 2002 OProfile authors
+ * @remark Read the file COPYING
+ *
+ * @author Richard Henderson <rth@twiddle.net>
+ */
+
+#ifndef OP_IMPL_H
+#define OP_IMPL_H 1
+
+/* Per-counter configuration as set via oprofilefs. */
+struct op_counter_config {
+ unsigned long enabled;
+ unsigned long event;
+ unsigned long count;
+ /* Dummies because I am too lazy to hack the userspace tools. */
+ unsigned long kernel;
+ unsigned long user;
+ unsigned long exl;
+ unsigned long unit_mask;
+};
+
+/* Per-architecture configury and hooks. */
+struct op_mips_model {
+ void (*reg_setup) (struct op_counter_config *);
+ void (*cpu_setup) (void * dummy);
+ int (*init)(void);
+ void (*exit)(void);
+ void (*cpu_start)(void *args);
+ void (*cpu_stop)(void *args);
+ char *cpu_type;
+ unsigned char num_counters;
+};
+
+#endif
diff --git a/arch/mips/oprofile/op_model_rm9000.c b/arch/mips/oprofile/op_model_rm9000.c
new file mode 100644
index 0000000..bee4779
--- /dev/null
+++ b/arch/mips/oprofile/op_model_rm9000.c
@@ -0,0 +1,137 @@
+/*
+ * 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) 2004 by Ralf Baechle
+ */
+#include <linux/oprofile.h>
+#include <linux/interrupt.h>
+#include <linux/smp.h>
+
+#include "op_impl.h"
+
+#define RM9K_COUNTER1_EVENT(event) ((event) << 0)
+#define RM9K_COUNTER1_SUPERVISOR (1ULL << 7)
+#define RM9K_COUNTER1_KERNEL (1ULL << 8)
+#define RM9K_COUNTER1_USER (1ULL << 9)
+#define RM9K_COUNTER1_ENABLE (1ULL << 10)
+#define RM9K_COUNTER1_OVERFLOW (1ULL << 15)
+
+#define RM9K_COUNTER2_EVENT(event) ((event) << 16)
+#define RM9K_COUNTER2_SUPERVISOR (1ULL << 23)
+#define RM9K_COUNTER2_KERNEL (1ULL << 24)
+#define RM9K_COUNTER2_USER (1ULL << 25)
+#define RM9K_COUNTER2_ENABLE (1ULL << 26)
+#define RM9K_COUNTER2_OVERFLOW (1ULL << 31)
+
+extern unsigned int rm9000_perfcount_irq;
+
+static struct rm9k_register_config {
+ unsigned int control;
+ unsigned int reset_counter1;
+ unsigned int reset_counter2;
+} reg;
+
+/* Compute all of the registers in preparation for enabling profiling. */
+
+static void rm9000_reg_setup(struct op_counter_config *ctr)
+{
+ unsigned int control = 0;
+
+ /* Compute the performance counter control word. */
+ /* For now count kernel and user mode */
+ if (ctr[0].enabled)
+ control |= RM9K_COUNTER1_EVENT(ctr[0].event) |
+ RM9K_COUNTER1_KERNEL |
+ RM9K_COUNTER1_USER |
+ RM9K_COUNTER1_ENABLE;
+ if (ctr[1].enabled)
+ control |= RM9K_COUNTER2_EVENT(ctr[1].event) |
+ RM9K_COUNTER2_KERNEL |
+ RM9K_COUNTER2_USER |
+ RM9K_COUNTER2_ENABLE;
+ reg.control = control;
+
+ reg.reset_counter1 = 0x80000000 - ctr[0].count;
+ reg.reset_counter2 = 0x80000000 - ctr[1].count;
+}
+
+/* Program all of the registers in preparation for enabling profiling. */
+
+static void rm9000_cpu_setup (void *args)
+{
+ uint64_t perfcount;
+
+ perfcount = ((uint64_t) reg.reset_counter2 << 32) | reg.reset_counter1;
+ write_c0_perfcount(perfcount);
+}
+
+static void rm9000_cpu_start(void *args)
+{
+ /* Start all counters on current CPU */
+ write_c0_perfcontrol(reg.control);
+}
+
+static void rm9000_cpu_stop(void *args)
+{
+ /* Stop all counters on current CPU */
+ write_c0_perfcontrol(0);
+}
+
+static irqreturn_t rm9000_perfcount_handler(int irq, void * dev_id,
+ struct pt_regs *regs)
+{
+ unsigned int control = read_c0_perfcontrol();
+ uint32_t counter1, counter2;
+ uint64_t counters;
+
+ /*
+ * RM9000 combines two 32-bit performance counters into a single
+ * 64-bit coprocessor zero register. To avoid a race updating the
+ * registers we need to stop the counters while we're messing with
+ * them ...
+ */
+ write_c0_perfcontrol(0);
+
+ counters = read_c0_perfcount();
+ counter1 = counters;
+ counter2 = counters >> 32;
+
+ if (control & RM9K_COUNTER1_OVERFLOW) {
+ oprofile_add_sample(regs, 0);
+ counter1 = reg.reset_counter1;
+ }
+ if (control & RM9K_COUNTER2_OVERFLOW) {
+ oprofile_add_sample(regs, 1);
+ counter2 = reg.reset_counter2;
+ }
+
+ counters = ((uint64_t)counter2 << 32) | counter1;
+ write_c0_perfcount(counters);
+ write_c0_perfcontrol(reg.control);
+
+ return IRQ_HANDLED;
+}
+
+static int rm9000_init(void)
+{
+ return request_irq(rm9000_perfcount_irq, rm9000_perfcount_handler,
+ 0, "Perfcounter", NULL);
+}
+
+static void rm9000_exit(void)
+{
+ free_irq(rm9000_perfcount_irq, NULL);
+}
+
+struct op_mips_model op_model_rm9000 = {
+ .reg_setup = rm9000_reg_setup,
+ .cpu_setup = rm9000_cpu_setup,
+ .init = rm9000_init,
+ .exit = rm9000_exit,
+ .cpu_start = rm9000_cpu_start,
+ .cpu_stop = rm9000_cpu_stop,
+ .cpu_type = "mips/rm9000",
+ .num_counters = 2
+};
diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile
new file mode 100644
index 0000000..c53e4cb
--- /dev/null
+++ b/arch/mips/pci/Makefile
@@ -0,0 +1,54 @@
+#
+# Makefile for the PCI specific kernel interface routines under Linux.
+#
+
+obj-y += pci.o
+
+#
+# PCI bus host bridge specific code
+#
+obj-$(CONFIG_ITE_BOARD_GEN) += ops-it8172.o
+obj-$(CONFIG_MIPS_BONITO64) += ops-bonito64.o
+obj-$(CONFIG_MIPS_GT64111) += ops-gt64111.o
+obj-$(CONFIG_MIPS_GT64120) += ops-gt64120.o
+obj-$(CONFIG_MIPS_GT96100) += ops-gt96100.o
+obj-$(CONFIG_PCI_MARVELL) += ops-marvell.o
+obj-$(CONFIG_MIPS_MSC) += ops-msc.o
+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_NEC_CMBVR4133) += fixup-vr4133.o
+
+#
+# These are still pretty much in the old state, watch, go blind.
+#
+obj-$(CONFIG_DDB5074) += fixup-ddb5074.o pci-ddb5074.o ops-ddb5074.o
+obj-$(CONFIG_DDB5476) += ops-ddb5476.o pci-ddb5476.o
+obj-$(CONFIG_DDB5477) += fixup-ddb5477.o pci-ddb5477.o ops-ddb5477.o
+obj-$(CONFIG_LASAT) += pci-lasat.o
+obj-$(CONFIG_MIPS_ATLAS) += fixup-atlas.o
+obj-$(CONFIG_MIPS_COBALT) += fixup-cobalt.o
+obj-$(CONFIG_MIPS_EV96100) += fixup-ev64120.o
+obj-$(CONFIG_MIPS_EV96100) += fixup-ev96100.o pci-ev96100.o
+obj-$(CONFIG_MIPS_ITE8172) += fixup-ite8172g.o
+obj-$(CONFIG_MIPS_IVR) += fixup-ivr.o
+obj-$(CONFIG_SOC_AU1500) += fixup-au1000.o ops-au1000.o
+obj-$(CONFIG_SOC_AU1550) += fixup-au1000.o ops-au1000.o
+obj-$(CONFIG_MIPS_MALTA) += fixup-malta.o
+obj-$(CONFIG_MOMENCO_JAGUAR_ATX)+= fixup-jaguar.o
+obj-$(CONFIG_MOMENCO_OCELOT) += fixup-ocelot.o pci-ocelot.o
+obj-$(CONFIG_MOMENCO_OCELOT_3) += fixup-ocelot3.o
+obj-$(CONFIG_MOMENCO_OCELOT_C) += fixup-ocelot-c.o pci-ocelot-c.o
+obj-$(CONFIG_MOMENCO_OCELOT_G) += fixup-ocelot-g.o pci-ocelot-g.o
+obj-$(CONFIG_PMC_YOSEMITE) += fixup-yosemite.o ops-titan.o ops-titan-ht.o \
+ pci-yosemite.o
+obj-$(CONFIG_SGI_IP27) += pci-ip27.o
+obj-$(CONFIG_SGI_IP32) += fixup-ip32.o ops-mace.o pci-ip32.o
+obj-$(CONFIG_SIBYTE_SB1250) += fixup-sb1250.o pci-sb1250.o
+obj-$(CONFIG_SNI_RM200_PCI) += fixup-sni.o ops-sni.o
+obj-$(CONFIG_TANBAC_TB0219) += fixup-tb0219.o
+obj-$(CONFIG_TANBAC_TB0226) += fixup-tb0226.o
+obj-$(CONFIG_TOSHIBA_JMR3927) += fixup-jmr3927.o pci-jmr3927.o
+obj-$(CONFIG_TOSHIBA_RBTX4927) += fixup-rbtx4927.o ops-tx4927.o
+obj-$(CONFIG_VICTOR_MPC30X) += fixup-mpc30x.o
+obj-$(CONFIG_ZAO_CAPCELLA) += fixup-capcella.o
diff --git a/arch/mips/pci/fixup-atlas.c b/arch/mips/pci/fixup-atlas.c
new file mode 100644
index 0000000..2406835
--- /dev/null
+++ b/arch/mips/pci/fixup-atlas.c
@@ -0,0 +1,69 @@
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <asm/mips-boards/atlasint.h>
+
+#define INTD ATLASINT_INTD
+#define INTC ATLASINT_INTC
+#define INTB ATLASINT_INTB
+#define INTA ATLASINT_INTA
+#define SCSI ATLASINT_SCSI
+#define ETH ATLASINT_ETH
+
+static char irq_tab[][5] __initdata = {
+ /* INTA INTB INTC INTD */
+ {0, 0, 0, 0, 0 }, /* 0: Unused */
+ {0, 0, 0, 0, 0 }, /* 1: Unused */
+ {0, 0, 0, 0, 0 }, /* 2: Unused */
+ {0, 0, 0, 0, 0 }, /* 3: Unused */
+ {0, 0, 0, 0, 0 }, /* 4: Unused */
+ {0, 0, 0, 0, 0 }, /* 5: Unused */
+ {0, 0, 0, 0, 0 }, /* 6: Unused */
+ {0, 0, 0, 0, 0 }, /* 7: Unused */
+ {0, 0, 0, 0, 0 }, /* 8: Unused */
+ {0, 0, 0, 0, 0 }, /* 9: Unused */
+ {0, 0, 0, 0, 0 }, /* 10: Unused */
+ {0, 0, 0, 0, 0 }, /* 11: Unused */
+ {0, 0, 0, 0, 0 }, /* 12: Unused */
+ {0, 0, 0, 0, 0 }, /* 13: Unused */
+ {0, 0, 0, 0, 0 }, /* 14: Unused */
+ {0, 0, 0, 0, 0 }, /* 15: Unused */
+ {0, SCSI, 0, 0, 0 }, /* 16: SYM53C810A SCSI */
+ {0, 0, 0, 0, 0 }, /* 17: Core */
+ {0, INTA, INTB, INTC, INTD }, /* 18: PCI Slot 1 */
+ {0, ETH, 0, 0, 0 }, /* 19: SAA9730 Ethernet */
+ {0, 0, 0, 0, 0 }, /* 20: PCI Slot 3 */
+ {0, 0, 0, 0, 0 } /* 21: PCI Slot 4 */
+};
+
+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+ return irq_tab[slot][pin];
+}
+
+/* Do platform specific device initialization at pci_enable_device() time */
+int pcibios_plat_dev_init(struct pci_dev *dev)
+{
+ return 0;
+}
+
+#ifdef CONFIG_KGDB
+/*
+ * The PCI scan may have moved the saa9730 I/O address, so reread
+ * the address here.
+ * This does mean that it's not possible to debug the PCI bus configuration
+ * code, but it is better than nothing...
+ */
+
+static void atlas_saa9730_base_fixup (struct pci_dev *pdev)
+{
+ extern void *saa9730_base;
+ if (pdev->bus == 0 && PCI_SLOT(pdev->devfn) == 19)
+ (void) pci_read_config_dword (pdev, 0x14, (u32 *)&saa9730_base);
+ printk ("saa9730_base = %x\n", saa9730_base);
+}
+
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA9730,
+ atlas_saa9730_base_fixup);
+
+#endif
diff --git a/arch/mips/pci/fixup-au1000.c b/arch/mips/pci/fixup-au1000.c
new file mode 100644
index 0000000..39fe2b1
--- /dev/null
+++ b/arch/mips/pci/fixup-au1000.c
@@ -0,0 +1,123 @@
+/*
+ * BRIEF MODULE DESCRIPTION
+ * Board specific pci fixups.
+ *
+ * Copyright 2001-2003 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ * ppopov@mvista.com or source@mvista.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/mach-au1x00/au1000.h>
+
+/*
+ * Shortcut
+ */
+#ifdef CONFIG_SOC_AU1500
+#define INTA AU1000_PCI_INTA
+#define INTB AU1000_PCI_INTB
+#define INTC AU1000_PCI_INTC
+#define INTD AU1000_PCI_INTD
+#endif
+
+#ifdef CONFIG_SOC_AU1550
+#define INTA AU1550_PCI_INTA
+#define INTB AU1550_PCI_INTB
+#define INTC AU1550_PCI_INTC
+#define INTD AU1550_PCI_INTD
+#endif
+
+#define INTX 0xFF /* not valid */
+
+#ifdef CONFIG_MIPS_DB1500
+static char irq_tab_alchemy[][5] __initdata = {
+ [12] = { -1, INTA, INTX, INTX, INTX}, /* IDSEL 12 - HPT371 */
+ [13] = { -1, INTA, INTB, INTC, INTD}, /* IDSEL 13 - PCI slot */
+};
+#endif
+
+#ifdef CONFIG_MIPS_BOSPORUS
+static char irq_tab_alchemy[][5] __initdata = {
+ [11] = { -1, INTA, INTB, INTX, INTX}, /* IDSEL 11 - miniPCI */
+ [12] = { -1, INTA, INTX, INTX, INTX}, /* IDSEL 12 - SN1741 */
+ [13] = { -1, INTA, INTB, INTC, INTD}, /* IDSEL 13 - PCI slot */
+};
+#endif
+
+#ifdef CONFIG_MIPS_MIRAGE
+static char irq_tab_alchemy[][5] __initdata = {
+ [11] = { -1, INTD, INTX, INTX, INTX}, /* IDSEL 11 - SMI VGX */
+ [12] = { -1, INTX, INTX, INTC, INTX}, /* IDSEL 12 - PNX1300 */
+ [13] = { -1, INTA, INTB, INTX, INTX}, /* IDSEL 13 - miniPCI */
+};
+#endif
+
+#ifdef CONFIG_MIPS_DB1550
+static char irq_tab_alchemy[][5] __initdata = {
+ [11] = { -1, INTC, INTX, INTX, INTX}, /* IDSEL 11 - on-board HPT371 */
+ [12] = { -1, INTB, INTC, INTD, INTA}, /* IDSEL 12 - PCI slot 2 (left) */
+ [13] = { -1, INTA, INTB, INTC, INTD}, /* IDSEL 13 - PCI slot 1 (right) */
+};
+#endif
+
+#ifdef CONFIG_MIPS_PB1500
+static char irq_tab_alchemy[][5] __initdata = {
+ [12] = { -1, INTA, INTX, INTX, INTX}, /* IDSEL 12 - HPT370 */
+ [13] = { -1, INTA, INTB, INTC, INTD}, /* IDSEL 13 - PCI slot */
+};
+#endif
+
+#ifdef CONFIG_MIPS_PB1550
+static char irq_tab_alchemy[][5] __initdata = {
+ [12] = { -1, INTB, INTC, INTD, INTA}, /* IDSEL 12 - PCI slot 2 (left) */
+ [13] = { -1, INTA, INTB, INTC, INTD}, /* IDSEL 13 - PCI slot 1 (right) */
+};
+#endif
+
+#ifdef CONFIG_MIPS_MTX1
+static char irq_tab_alchemy[][5] __initdata = {
+ [0] = { -1, INTA, INTB, INTX, INTX}, /* IDSEL 00 - AdapterA-Slot0 (top) */
+ [1] = { -1, INTB, INTA, INTX, INTX}, /* IDSEL 01 - AdapterA-Slot1 (bottom) */
+ [2] = { -1, INTC, INTD, INTX, INTX}, /* IDSEL 02 - AdapterB-Slot0 (top) */
+ [3] = { -1, INTD, INTC, INTX, INTX}, /* IDSEL 03 - AdapterB-Slot1 (bottom) */
+ [4] = { -1, INTA, INTB, INTX, INTX}, /* IDSEL 04 - AdapterC-Slot0 (top) */
+ [5] = { -1, INTB, INTA, INTX, INTX}, /* IDSEL 05 - AdapterC-Slot1 (bottom) */
+ [6] = { -1, INTC, INTD, INTX, INTX}, /* IDSEL 06 - AdapterD-Slot0 (top) */
+ [7] = { -1, INTD, INTC, INTX, INTX}, /* IDSEL 07 - AdapterD-Slot1 (bottom) */
+};
+#endif
+
+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+ return irq_tab_alchemy[slot][pin];
+}
+
+/* Do platform specific device initialization at pci_enable_device() time */
+int pcibios_plat_dev_init(struct pci_dev *dev)
+{
+ return 0;
+}
diff --git a/arch/mips/pci/fixup-capcella.c b/arch/mips/pci/fixup-capcella.c
new file mode 100644
index 0000000..f2fc82c
--- /dev/null
+++ b/arch/mips/pci/fixup-capcella.c
@@ -0,0 +1,50 @@
+/*
+ * fixup-cappcela.c, The ZAO Networks Capcella specific PCI fixups.
+ *
+ * Copyright (C) 2002,2004 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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 <linux/init.h>
+#include <linux/pci.h>
+
+#include <asm/vr41xx/capcella.h>
+
+/*
+ * Shortcuts
+ */
+#define INT1 RTL8139_1_IRQ
+#define INT2 RTL8139_2_IRQ
+#define INTA PC104PLUS_INTA_IRQ
+#define INTB PC104PLUS_INTB_IRQ
+#define INTC PC104PLUS_INTC_IRQ
+#define INTD PC104PLUS_INTD_IRQ
+
+static char irq_tab_capcella[][5] __initdata = {
+ [11] = { -1, INT1, INT1, INT1, INT1 },
+ [12] = { -1, INT2, INT2, INT2, INT2 },
+ [14] = { -1, INTA, INTB, INTC, INTD }
+};
+
+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+ return irq_tab_capcella[slot][pin];
+}
+
+/* Do platform specific device initialization at pci_enable_device() time */
+int pcibios_plat_dev_init(struct pci_dev *dev)
+{
+ return 0;
+}
diff --git a/arch/mips/pci/fixup-cobalt.c b/arch/mips/pci/fixup-cobalt.c
new file mode 100644
index 0000000..57e1ca2
--- /dev/null
+++ b/arch/mips/pci/fixup-cobalt.c
@@ -0,0 +1,112 @@
+/*
+ * Cobalt Qube/Raq PCI support
+ *
+ * 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, 1996, 1997, 2002, 2003 by Ralf Baechle
+ * Copyright (C) 2001, 2002, 2003 by Liam Davies (ldavies@agile.tv)
+ */
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/pci.h>
+#include <asm/io.h>
+#include <asm/gt64120.h>
+
+#include <asm/cobalt/cobalt.h>
+
+extern int cobalt_board_id;
+
+static void qube_raq_via_bmIDE_fixup(struct pci_dev *dev)
+{
+ unsigned short cfgword;
+ unsigned char lt;
+
+ /* Enable Bus Mastering and fast back to back. */
+ pci_read_config_word(dev, PCI_COMMAND, &cfgword);
+ cfgword |= (PCI_COMMAND_FAST_BACK | PCI_COMMAND_MASTER);
+ pci_write_config_word(dev, PCI_COMMAND, cfgword);
+
+ /* Enable both ide interfaces. ROM only enables primary one. */
+ pci_write_config_byte(dev, 0x40, 0xb);
+
+ /* Set latency timer to reasonable value. */
+ pci_read_config_byte(dev, PCI_LATENCY_TIMER, <);
+ if (lt < 64)
+ pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64);
+ pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 7);
+}
+
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1,
+ qube_raq_via_bmIDE_fixup);
+
+static void qube_raq_galileo_fixup(struct pci_dev *dev)
+{
+ unsigned short galileo_id;
+
+ /* Fix PCI latency-timer and cache-line-size values in Galileo
+ * host bridge.
+ */
+ pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64);
+ pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 7);
+
+ /*
+ * On all machines prior to Q2, we had the STOP line disconnected
+ * from Galileo to VIA on PCI. The new Galileo does not function
+ * correctly unless we have it connected.
+ *
+ * Therefore we must set the disconnect/retry cycle values to
+ * something sensible when using the new Galileo.
+ */
+ pci_read_config_word(dev, PCI_REVISION_ID, &galileo_id);
+ galileo_id &= 0xff; /* mask off class info */
+ if (galileo_id >= 0x10) {
+ /* New Galileo, assumes PCI stop line to VIA is connected. */
+ GALILEO_OUTL(0x4020, GT_PCI0_TOR_OFS);
+ } else if (galileo_id == 0x1 || galileo_id == 0x2) {
+ signed int timeo;
+ /* XXX WE MUST DO THIS ELSE GALILEO LOCKS UP! -DaveM */
+ timeo = GALILEO_INL(GT_PCI0_TOR_OFS);
+ /* Old Galileo, assumes PCI STOP line to VIA is disconnected. */
+ GALILEO_OUTL(0xffff, GT_PCI0_TOR_OFS);
+ }
+}
+
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_GALILEO, PCI_ANY_ID,
+ qube_raq_galileo_fixup);
+
+static char irq_tab_cobalt[] __initdata = {
+ [COBALT_PCICONF_CPU] = 0,
+ [COBALT_PCICONF_ETH0] = COBALT_ETH0_IRQ,
+ [COBALT_PCICONF_RAQSCSI] = COBALT_SCSI_IRQ,
+ [COBALT_PCICONF_VIA] = 0,
+ [COBALT_PCICONF_PCISLOT] = COBALT_QUBE_SLOT_IRQ,
+ [COBALT_PCICONF_ETH1] = COBALT_ETH1_IRQ
+};
+
+static char irq_tab_raq2[] __initdata = {
+ [COBALT_PCICONF_CPU] = 0,
+ [COBALT_PCICONF_ETH0] = COBALT_ETH0_IRQ,
+ [COBALT_PCICONF_RAQSCSI] = COBALT_RAQ_SCSI_IRQ,
+ [COBALT_PCICONF_VIA] = 0,
+ [COBALT_PCICONF_PCISLOT] = COBALT_QUBE_SLOT_IRQ,
+ [COBALT_PCICONF_ETH1] = COBALT_ETH1_IRQ
+};
+
+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+ if (cobalt_board_id == COBALT_BRD_ID_RAQ2)
+ return irq_tab_raq2[slot];
+
+ return irq_tab_cobalt[slot];
+}
+
+/* Do platform specific device initialization at pci_enable_device() time */
+int pcibios_plat_dev_init(struct pci_dev *dev)
+{
+ return 0;
+}
diff --git a/arch/mips/pci/fixup-ddb5074.c b/arch/mips/pci/fixup-ddb5074.c
new file mode 100644
index 0000000..b345e52
--- /dev/null
+++ b/arch/mips/pci/fixup-ddb5074.c
@@ -0,0 +1,21 @@
+/*
+ * It's nice to have the LEDs on the GPIO pins available for debugging
+ */
+static void ddb5074_fixup(struct pci_dev *dev)
+{
+ extern struct pci_dev *pci_pmu;
+ u8 t8;
+
+ pci_pmu = dev; /* for LEDs D2 and D3 */
+ /* Program the lines for LEDs D2 and D3 to output */
+ pci_read_config_byte(dev, 0x7d, &t8);
+ t8 |= 0xc0;
+ pci_write_config_byte(dev, 0x7d, t8);
+ /* Turn LEDs D2 and D3 off */
+ pci_read_config_byte(dev, 0x7e, &t8);
+ t8 |= 0xc0;
+ pci_write_config_byte(dev, 0x7e, t8);
+}
+
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101,
+ ddb5074_fixup);
diff --git a/arch/mips/pci/fixup-ddb5477.c b/arch/mips/pci/fixup-ddb5477.c
new file mode 100644
index 0000000..6abdc88
--- /dev/null
+++ b/arch/mips/pci/fixup-ddb5477.c
@@ -0,0 +1,78 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ * Board specific pci fixups.
+ *
+ * Copyright 2001, 2002, 2003 MontaVista Software Inc.
+ * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+static void ddb5477_fixup(struct pci_dev *dev)
+{
+ u8 old;
+
+ printk(KERN_NOTICE "Enabling ALI M1533/35 PS2 keyboard/mouse.\n");
+ pci_read_config_byte(dev, 0x41, &old);
+ pci_write_config_byte(dev, 0x41, old | 0xd0);
+}
+
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533,
+ ddb5477_fixup);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1535,
+ ddb5477_fixup);
+
+/*
+ * Fixup baseboard AMD chip so that tx does not underflow.
+ * bcr_18 |= 0x0800
+ * This sets NOUFLO bit which makes tx not start until whole pkt
+ * is fetched to the chip.
+ */
+#define PCNET32_WIO_RDP 0x10
+#define PCNET32_WIO_RAP 0x12
+#define PCNET32_WIO_RESET 0x14
+#define PCNET32_WIO_BDP 0x16
+
+static void ddb5477_amd_lance_fixup(struct pci_dev *dev)
+{
+ unsigned long ioaddr;
+ u16 temp;
+
+ ioaddr = pci_resource_start(dev, 0);
+
+ inw(ioaddr + PCNET32_WIO_RESET); /* reset chip */
+
+ /* bcr_18 |= 0x0800 */
+ outw(18, ioaddr + PCNET32_WIO_RAP);
+ temp = inw(ioaddr + PCNET32_WIO_BDP);
+ temp |= 0x0800;
+ outw(18, ioaddr + PCNET32_WIO_RAP);
+ outw(temp, ioaddr + PCNET32_WIO_BDP);
+}
+
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE,
+ ddb5477_amd_lance_fixup);
diff --git a/arch/mips/pci/fixup-ev64120.c b/arch/mips/pci/fixup-ev64120.c
new file mode 100644
index 0000000..8dbb90d
--- /dev/null
+++ b/arch/mips/pci/fixup-ev64120.c
@@ -0,0 +1,34 @@
+#include <linux/pci.h>
+#include <linux/init.h>
+
+int pci_range_ck(unsigned char bus, unsigned char dev)
+{
+ if (((bus == 0) || (bus == 1)) && (dev >= 6) && (dev <= 8))
+ return 0;
+
+ return -1;
+}
+
+/*
+ * After detecting all agents over the PCI , this function is called
+ * in order to give an interrupt number for each PCI device starting
+ * from IRQ 20. It does also enables master for each device.
+ */
+void __devinit pcibios_fixup_bus(struct pci_bus *bus)
+{
+ unsigned int irq = 20;
+ struct pci_bus *current_bus = bus;
+ struct pci_dev *dev;
+ struct list_head *devices_link;
+
+ list_for_each(devices_link, &(current_bus->devices)) {
+ dev = pci_dev_b(devices_link);
+ if (dev != NULL) {
+ dev->irq = irq++;
+
+ /* Assign an interrupt number for the device */
+ pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
+ pcibios_set_master(dev);
+ }
+ }
+}
diff --git a/arch/mips/pci/fixup-ev96100.c b/arch/mips/pci/fixup-ev96100.c
new file mode 100644
index 0000000..e2bc977
--- /dev/null
+++ b/arch/mips/pci/fixup-ev96100.c
@@ -0,0 +1,48 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ * EV96100 Board specific pci fixups.
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ * ppopov@mvista.com or source@mvista.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+
+static char irq_tab_ev96100[][5] __initdata = {
+ [8] = { 0, 5, 5, 5, 5 },
+ [9] = { 0, 2, 2, 2, 2 }
+};
+
+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+ return irq_tab_ev96100[slot][pin];
+}
+
+/* Do platform specific device initialization at pci_enable_device() time */
+int pcibios_plat_dev_init(struct pci_dev *dev)
+{
+ return 0;
+}
diff --git a/arch/mips/pci/fixup-ip32.c b/arch/mips/pci/fixup-ip32.c
new file mode 100644
index 0000000..3e66b0a
--- /dev/null
+++ b/arch/mips/pci/fixup-ip32.c
@@ -0,0 +1,51 @@
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <asm/ip32/ip32_ints.h>
+/*
+ * O2 has up to 5 PCI devices connected into the MACE bridge. The device
+ * map looks like this:
+ *
+ * 0 aic7xxx 0
+ * 1 aic7xxx 1
+ * 2 expansion slot
+ * 3 N/C
+ * 4 N/C
+ */
+
+#define SCSI0 MACEPCI_SCSI0_IRQ
+#define SCSI1 MACEPCI_SCSI1_IRQ
+#define INTA0 MACEPCI_SLOT0_IRQ
+#define INTA1 MACEPCI_SLOT1_IRQ
+#define INTA2 MACEPCI_SLOT2_IRQ
+#define INTB MACEPCI_SHARED0_IRQ
+#define INTC MACEPCI_SHARED1_IRQ
+#define INTD MACEPCI_SHARED2_IRQ
+static char irq_tab_mace[][5] __initdata = {
+ /* Dummy INT#A INT#B INT#C INT#D */
+ {0, 0, 0, 0, 0}, /* This is placeholder row - never used */
+ {0, SCSI0, SCSI0, SCSI0, SCSI0},
+ {0, SCSI1, SCSI1, SCSI1, SCSI1},
+ {0, INTA0, INTB, INTC, INTD},
+ {0, INTA1, INTC, INTD, INTB},
+ {0, INTA2, INTD, INTB, INTC},
+};
+
+
+/*
+ * Given a PCI slot number (a la PCI_SLOT(...)) and the interrupt pin of
+ * the device (1-4 => A-D), tell what irq to use. Note that we don't
+ * in theory have slots 4 and 5, and we never normally use the shared
+ * irqs. I suppose a device without a pin A will thank us for doing it
+ * right if there exists such a broken piece of crap.
+ */
+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+ return irq_tab_mace[slot][pin];
+}
+
+/* Do platform specific device initialization at pci_enable_device() time */
+int pcibios_plat_dev_init(struct pci_dev *dev)
+{
+ return 0;
+}
diff --git a/arch/mips/pci/fixup-ite8172g.c b/arch/mips/pci/fixup-ite8172g.c
new file mode 100644
index 0000000..2290ea4
--- /dev/null
+++ b/arch/mips/pci/fixup-ite8172g.c
@@ -0,0 +1,80 @@
+/*
+ * BRIEF MODULE DESCRIPTION
+ * Board specific pci fixups.
+ *
+ * Copyright 2000 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ * ppopov@mvista.com or source@mvista.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/it8172/it8172.h>
+#include <asm/it8172/it8172_pci.h>
+#include <asm/it8172/it8172_int.h>
+
+/*
+ * Shortcuts
+ */
+#define INTA IT8172_PCI_INTA_IRQ
+#define INTB IT8172_PCI_INTB_IRQ
+#define INTC IT8172_PCI_INTC_IRQ
+#define INTD IT8172_PCI_INTD_IRQ
+
+static const int internal_func_irqs[7] __initdata = {
+ IT8172_AC97_IRQ,
+ IT8172_DMA_IRQ,
+ IT8172_CDMA_IRQ,
+ IT8172_USB_IRQ,
+ IT8172_BRIDGE_MASTER_IRQ,
+ IT8172_IDE_IRQ,
+ IT8172_MC68K_IRQ
+};
+
+static char irq_tab_ite8172g[][5] __initdata = {
+ [0x10] = { 0, INTA, INTB, INTC, INTD },
+ [0x11] = { 0, INTA, INTB, INTC, INTD },
+ [0x12] = { 0, INTB, INTC, INTD, INTA },
+ [0x13] = { 0, INTC, INTD, INTA, INTB },
+ [0x14] = { 0, INTD, INTA, INTB, INTC },
+};
+
+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+ /*
+ * Internal device 1 is actually 7 different internal devices on the
+ * IT8172G (a multifunction device).
+ */
+ if (slot == 1)
+ return internal_func_irqs[PCI_FUNC(dev->devfn)];
+
+ return irq_tab_ite8172g[slot][pin];
+}
+
+/* Do platform specific device initialization at pci_enable_device() time */
+int pcibios_plat_dev_init(struct pci_dev *dev)
+{
+ return 0;
+}
diff --git a/arch/mips/pci/fixup-ivr.c b/arch/mips/pci/fixup-ivr.c
new file mode 100644
index 0000000..0c7c164
--- /dev/null
+++ b/arch/mips/pci/fixup-ivr.c
@@ -0,0 +1,75 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ * Globespan IVR board-specific pci fixups.
+ *
+ * Copyright 2000 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ * ppopov@mvista.com or source@mvista.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/it8172/it8172.h>
+#include <asm/it8172/it8172_pci.h>
+#include <asm/it8172/it8172_int.h>
+
+/*
+ * Shortcuts
+ */
+#define INTA IT8172_PCI_INTA_IRQ
+#define INTB IT8172_PCI_INTB_IRQ
+#define INTC IT8172_PCI_INTC_IRQ
+#define INTD IT8172_PCI_INTD_IRQ
+
+static const int internal_func_irqs[7] __initdata = {
+ IT8172_AC97_IRQ,
+ IT8172_DMA_IRQ,
+ IT8172_CDMA_IRQ,
+ IT8172_USB_IRQ,
+ IT8172_BRIDGE_MASTER_IRQ,
+ IT8172_IDE_IRQ,
+ IT8172_MC68K_IRQ
+};
+
+static char irq_tab_ivr[][5] __initdata = {
+ [0x11] = { INTC, INTC, INTD, INTA, INTB }, /* Realtek RTL-8139 */
+ [0x12] = { INTB, INTB, INTB, INTC, INTC }, /* IVR slot */
+ [0x13] = { INTA, INTA, INTB, INTC, INTD } /* Expansion slot */
+};
+
+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+ if (slot == 1)
+ return internal_func_irqs[PCI_FUNC(dev->devfn)];
+
+ return irq_tab_ivr[slot][pin];
+}
+
+/* Do platform specific device initialization at pci_enable_device() time */
+int pcibios_plat_dev_init(struct pci_dev *dev)
+{
+ return 0;
+}
diff --git a/arch/mips/pci/fixup-jaguar.c b/arch/mips/pci/fixup-jaguar.c
new file mode 100644
index 0000000..6c5e1d4
--- /dev/null
+++ b/arch/mips/pci/fixup-jaguar.c
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ *
+ * Marvell MV64340 interrupt fixup code.
+ *
+ * Marvell wants an NDA for their docs so this was written without
+ * documentation. You've been warned.
+ *
+ * Copyright (C) 2004 Ralf Baechle (ralf@linux-mips.org)
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+
+#include <asm/mipsregs.h>
+
+/*
+ * WARNING: Example of how _NOT_ to do it.
+ */
+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+ int bus = dev->bus->number;
+
+ if (bus == 0 && slot == 1)
+ return 3; /* PCI-X A */
+ if (bus == 0 && slot == 2)
+ return 4; /* PCI-X B */
+ if (bus == 1 && slot == 1)
+ return 5; /* PCI A */
+ if (bus == 1 && slot == 2)
+ return 6; /* PCI B */
+
+return 0;
+ panic("Whooops in pcibios_map_irq");
+}
+
+/* Do platform specific device initialization at pci_enable_device() time */
+int pcibios_plat_dev_init(struct pci_dev *dev)
+{
+ return 0;
+}
diff --git a/arch/mips/pci/fixup-jmr3927.c b/arch/mips/pci/fixup-jmr3927.c
new file mode 100644
index 0000000..f869608
--- /dev/null
+++ b/arch/mips/pci/fixup-jmr3927.c
@@ -0,0 +1,105 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ * Board specific pci fixups.
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ * ppopov@mvista.com or source@mvista.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/jmr3927/jmr3927.h>
+
+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+ unsigned char irq = pin;
+
+ /* IRQ rotation (PICMG) */
+ irq--; /* 0-3 */
+ if (dev->bus->parent == NULL &&
+ slot == TX3927_PCIC_IDSEL_AD_TO_SLOT(23)) {
+ /* PCI CardSlot (IDSEL=A23, DevNu=12) */
+ /* PCIA => PCIC (IDSEL=A23) */
+ /* NOTE: JMR3927 JP1 must be set to OPEN */
+ irq = (irq + 2) % 4;
+ } else if (dev->bus->parent == NULL &&
+ slot == TX3927_PCIC_IDSEL_AD_TO_SLOT(22)) {
+ /* PCI CardSlot (IDSEL=A22, DevNu=11) */
+ /* PCIA => PCIA (IDSEL=A22) */
+ /* NOTE: JMR3927 JP1 must be set to OPEN */
+ irq = (irq + 0) % 4;
+ } else {
+ /* PCI Backplane */
+ irq = (irq + 3 + slot) % 4;
+ }
+ irq++; /* 1-4 */
+
+ switch (irq) {
+ case 1:
+ irq = JMR3927_IRQ_IOC_PCIA;
+ break;
+ case 2:
+ // wrong for backplane irq = JMR3927_IRQ_IOC_PCIB;
+ irq = JMR3927_IRQ_IOC_PCID;
+ break;
+ case 3:
+ irq = JMR3927_IRQ_IOC_PCIC;
+ break;
+ case 4:
+ // wrong for backplane irq = JMR3927_IRQ_IOC_PCID;
+ irq = JMR3927_IRQ_IOC_PCIB;
+ break;
+ }
+
+ /* Check OnBoard Ethernet (IDSEL=A24, DevNu=13) */
+ if (dev->bus->parent == NULL &&
+ slot == TX3927_PCIC_IDSEL_AD_TO_SLOT(24)) {
+ extern int jmr3927_ether1_irq;
+ /* check this irq line was reserved for ether1 */
+ if (jmr3927_ether1_irq != JMR3927_IRQ_ETHER0)
+ irq = JMR3927_IRQ_ETHER0;
+ else
+ irq = 0; /* disable */
+ }
+ return irq;
+}
+
+/* Do platform specific device initialization at pci_enable_device() time */
+int pcibios_plat_dev_init(struct pci_dev *dev)
+{
+ return 0;
+}
+
+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+ /* SMSC SLC90E66 IDE uses irq 14, 15 (default) */
+ if (!(dev->vendor == PCI_VENDOR_ID_EFAR &&
+ dev->device == PCI_DEVICE_ID_EFAR_SLC90E66_1))
+ return pci_get_irq(dev, pin);
+
+ dev->irq = irq;
+}
diff --git a/arch/mips/pci/fixup-malta.c b/arch/mips/pci/fixup-malta.c
new file mode 100644
index 0000000..b9296d9
--- /dev/null
+++ b/arch/mips/pci/fixup-malta.c
@@ -0,0 +1,103 @@
+#include <linux/init.h>
+#include <linux/pci.h>
+
+/* PCI interrupt pins */
+#define PCIA 1
+#define PCIB 2
+#define PCIC 3
+#define PCID 4
+
+/* This table is filled in by interrogating the PIIX4 chip */
+static char pci_irq[5] __initdata;
+
+static char irq_tab[][5] __initdata = {
+ /* INTA INTB INTC INTD */
+ {0, 0, 0, 0, 0 }, /* 0: GT64120 PCI bridge */
+ {0, 0, 0, 0, 0 }, /* 1: Unused */
+ {0, 0, 0, 0, 0 }, /* 2: Unused */
+ {0, 0, 0, 0, 0 }, /* 3: Unused */
+ {0, 0, 0, 0, 0 }, /* 4: Unused */
+ {0, 0, 0, 0, 0 }, /* 5: Unused */
+ {0, 0, 0, 0, 0 }, /* 6: Unused */
+ {0, 0, 0, 0, 0 }, /* 7: Unused */
+ {0, 0, 0, 0, 0 }, /* 8: Unused */
+ {0, 0, 0, 0, 0 }, /* 9: Unused */
+ {0, 0, 0, 0, PCID }, /* 10: PIIX4 USB */
+ {0, PCIB, 0, 0, 0 }, /* 11: AMD 79C973 Ethernet */
+ {0, PCIC, 0, 0, 0 }, /* 12: Crystal 4281 Sound */
+ {0, 0, 0, 0, 0 }, /* 13: Unused */
+ {0, 0, 0, 0, 0 }, /* 14: Unused */
+ {0, 0, 0, 0, 0 }, /* 15: Unused */
+ {0, 0, 0, 0, 0 }, /* 16: Unused */
+ {0, 0, 0, 0, 0 }, /* 17: Bonito/SOC-it PCI Bridge*/
+ {0, PCIA, PCIB, PCIC, PCID }, /* 18: PCI Slot 1 */
+ {0, PCIB, PCIC, PCID, PCIA }, /* 19: PCI Slot 2 */
+ {0, PCIC, PCID, PCIA, PCIB }, /* 20: PCI Slot 3 */
+ {0, PCID, PCIA, PCIB, PCIC } /* 21: PCI Slot 4 */
+};
+
+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+ int virq;
+ virq = irq_tab[slot][pin];
+ return pci_irq[virq];
+}
+
+/* Do platform specific device initialization at pci_enable_device() time */
+int pcibios_plat_dev_init(struct pci_dev *dev)
+{
+ return 0;
+}
+
+static void __init malta_piix_func0_fixup(struct pci_dev *pdev)
+{
+ unsigned char reg_val;
+ static int piixirqmap[16] __initdata = { /* PIIX PIRQC[A:D] irq mappings */
+ 0, 0, 0, 3,
+ 4, 5, 6, 7,
+ 0, 9, 10, 11,
+ 12, 0, 14, 15
+ };
+ int i;
+
+ /* Interrogate PIIX4 to get PCI IRQ mapping */
+ for (i = 0; i <= 3; i++) {
+ pci_read_config_byte(pdev, 0x60+i, ®_val);
+ if (reg_val & 0x80)
+ pci_irq[PCIA+i] = 0; /* Disabled */
+ else
+ pci_irq[PCIA+i] = piixirqmap[reg_val & 15];
+ }
+
+ /* Done by YAMON 2.00 onwards */
+ if (PCI_SLOT(pdev->devfn) == 10) {
+ /*
+ * Set top of main memory accessible by ISA or DMA
+ * devices to 16 Mb.
+ */
+ pci_read_config_byte(pdev, 0x69, ®_val);
+ pci_write_config_byte(pdev, 0x69, reg_val | 0xf0);
+ }
+}
+
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_0,
+ malta_piix_func0_fixup);
+
+static void __init malta_piix_func1_fixup(struct pci_dev *pdev)
+{
+ unsigned char reg_val;
+
+ /* Done by YAMON 2.02 onwards */
+ if (PCI_SLOT(pdev->devfn) == 10) {
+ /*
+ * IDE Decode enable.
+ */
+ pci_read_config_byte(pdev, 0x41, ®_val);
+ pci_write_config_byte(pdev, 0x41, reg_val|0x80);
+ pci_read_config_byte(pdev, 0x43, ®_val);
+ pci_write_config_byte(pdev, 0x43, reg_val|0x80);
+ }
+}
+
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB,
+ malta_piix_func1_fixup);
diff --git a/arch/mips/pci/fixup-mpc30x.c b/arch/mips/pci/fixup-mpc30x.c
new file mode 100644
index 0000000..4975846
--- /dev/null
+++ b/arch/mips/pci/fixup-mpc30x.c
@@ -0,0 +1,50 @@
+/*
+ * fixup-mpc30x.c, The Victor MP-C303/304 specific PCI fixups.
+ *
+ * Copyright (C) 2002,2004 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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 <linux/init.h>
+#include <linux/pci.h>
+
+#include <asm/vr41xx/mpc30x.h>
+#include <asm/vr41xx/vrc4173.h>
+
+static const int internal_func_irqs[] __initdata = {
+ VRC4173_CASCADE_IRQ,
+ VRC4173_AC97_IRQ,
+ VRC4173_USB_IRQ,
+};
+
+static const int irq_tab_mpc30x[] __initdata = {
+ [12] = VRC4173_PCMCIA1_IRQ,
+ [13] = VRC4173_PCMCIA2_IRQ,
+ [29] = MQ200_IRQ,
+};
+
+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+ if (slot == 30)
+ return internal_func_irqs[PCI_FUNC(dev->devfn)];
+
+ return irq_tab_mpc30x[slot];
+}
+
+/* Do platform specific device initialization at pci_enable_device() time */
+int pcibios_plat_dev_init(struct pci_dev *dev)
+{
+ return 0;
+}
diff --git a/arch/mips/pci/fixup-ocelot-c.c b/arch/mips/pci/fixup-ocelot-c.c
new file mode 100644
index 0000000..d454948
--- /dev/null
+++ b/arch/mips/pci/fixup-ocelot-c.c
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2002 Momentum Computer Inc.
+ * Author: Matthew Dharm <mdharm@momenco.com>
+ *
+ * Based on work for the Linux port to the Ocelot board, which is
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
+ *
+ * arch/mips/momentum/ocelot_g/pci.c
+ * Board-specific PCI routines for mv64340 controller.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+ int bus = dev->bus->number;
+
+ if (bus == 0 && slot == 1)
+ return 2; /* PCI-X A */
+ if (bus == 1 && slot == 1)
+ return 12; /* PCI-X B */
+ if (bus == 1 && slot == 2)
+ return 4; /* PCI B */
+
+return 0;
+ panic("Whooops in pcibios_map_irq");
+}
+
+/* Do platform specific device initialization at pci_enable_device() time */
+int pcibios_plat_dev_init(struct pci_dev *dev)
+{
+ return 0;
+}
diff --git a/arch/mips/pci/fixup-ocelot-g.c b/arch/mips/pci/fixup-ocelot-g.c
new file mode 100644
index 0000000..d7a652e
--- /dev/null
+++ b/arch/mips/pci/fixup-ocelot-g.c
@@ -0,0 +1,37 @@
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * Copyright (C) 2004 Ralf Baechle (ralf@linux-mips.org)
+ */
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+ int bus = dev->bus->number;
+
+ if (bus == 0 && slot == 1) /* Intel 82543 Gigabit MAC */
+ return 2; /* irq_nr is 2 for INT0 */
+
+ if (bus == 0 && slot == 2) /* Intel 82543 Gigabit MAC */
+ return 3; /* irq_nr is 3 for INT1 */
+
+ if (bus == 1 && slot == 3) /* Intel 21555 bridge */
+ return 5; /* irq_nr is 8 for INT6 */
+
+ if (bus == 1 && slot == 4) /* PMC Slot */
+ return 9; /* irq_nr is 9 for INT7 */
+
+ return -1;
+}
+
+/* Do platform specific device initialization at pci_enable_device() time */
+int pcibios_plat_dev_init(struct pci_dev *dev)
+{
+ return 0;
+}
diff --git a/arch/mips/pci/fixup-ocelot.c b/arch/mips/pci/fixup-ocelot.c
new file mode 100644
index 0000000..99629bd
--- /dev/null
+++ b/arch/mips/pci/fixup-ocelot.c
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
+ *
+ * arch/mips/gt64120/momenco_ocelot/pci.c
+ * Board-specific PCI routines for gt64120 controller.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <asm/pci.h>
+
+
+void __devinit pcibios_fixup_bus(struct pci_bus *bus)
+{
+ struct pci_bus *current_bus = bus;
+ struct pci_dev *devices;
+ struct list_head *devices_link;
+ u16 cmd;
+
+ list_for_each(devices_link, &(current_bus->devices)) {
+
+ devices = pci_dev_b(devices_link);
+ if (devices == NULL)
+ continue;
+
+ if (PCI_SLOT(devices->devfn) == 1) {
+ /*
+ * Slot 1 is primary ether port, i82559
+ * we double-check against that assumption
+ */
+ if ((devices->vendor != 0x8086) ||
+ (devices->device != 0x1209)) {
+ panic("pcibios_fixup_bus: found "
+ "unexpected PCI device in slot 1.");
+ }
+ devices->irq = 2; /* irq_nr is 2 for INT0 */
+ } else if (PCI_SLOT(devices->devfn) == 2) {
+ /*
+ * Slot 2 is secondary ether port, i21143
+ * we double-check against that assumption
+ */
+ if ((devices->vendor != 0x1011) ||
+ (devices->device != 0x19)) {
+ panic("galileo_pcibios_fixup_bus: "
+ "found unexpected PCI device in slot 2.");
+ }
+ devices->irq = 3; /* irq_nr is 3 for INT1 */
+ } else if (PCI_SLOT(devices->devfn) == 4) {
+ /* PMC Slot 1 */
+ devices->irq = 8; /* irq_nr is 8 for INT6 */
+ } else if (PCI_SLOT(devices->devfn) == 5) {
+ /* PMC Slot 1 */
+ devices->irq = 9; /* irq_nr is 9 for INT7 */
+ } else {
+ /* We don't have assign interrupts for other devices. */
+ devices->irq = 0xff;
+ }
+
+ /* Assign an interrupt number for the device */
+ bus->ops->write_byte(devices, PCI_INTERRUPT_LINE,
+ devices->irq);
+
+ /* enable master */
+ bus->ops->read_word(devices, PCI_COMMAND, &cmd);
+ cmd |= PCI_COMMAND_MASTER;
+ bus->ops->write_word(devices, PCI_COMMAND, cmd);
+ }
+}
diff --git a/arch/mips/pci/fixup-ocelot3.c b/arch/mips/pci/fixup-ocelot3.c
new file mode 100644
index 0000000..ececc03
--- /dev/null
+++ b/arch/mips/pci/fixup-ocelot3.c
@@ -0,0 +1,41 @@
+/*
+ * 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) 2004 Montavista Software Inc.
+ * Author: Manish Lachwani (mlachwani@mvista.com)
+ *
+ * Looking at the schematics for the Ocelot-3 board, there are
+ * two PCI busses and each bus has two PCI slots.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <asm/mipsregs.h>
+
+/*
+ * Do platform specific device initialization at
+ * pci_enable_device() time
+ */
+int pcibios_plat_dev_init(struct pci_dev *dev)
+{
+ return 0;
+}
+
+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+ int bus = dev->bus->number;
+
+ if (bus == 0 && slot == 1)
+ return 2; /* PCI-X A */
+ if (bus == 0 && slot == 2)
+ return 3; /* PCI-X B */
+ if (bus == 1 && slot == 1)
+ return 4; /* PCI A */
+ if (bus == 1 && slot == 2)
+ return 5; /* PCI B */
+
+return 0;
+ panic("Whooops in pcibios_map_irq");
+}
diff --git a/arch/mips/pci/fixup-rbtx4927.c b/arch/mips/pci/fixup-rbtx4927.c
new file mode 100644
index 0000000..de4e443
--- /dev/null
+++ b/arch/mips/pci/fixup-rbtx4927.c
@@ -0,0 +1,140 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ * Board specific pci fixups for the Toshiba rbtx4927
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ * ppopov@mvista.com or source@mvista.com
+ *
+ * Copyright (C) 2000-2001 Toshiba Corporation
+ *
+ * Copyright (C) 2004 MontaVista Software Inc.
+ * Author: Manish Lachwani (mlachwani@mvista.com)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/tx4927/tx4927.h>
+#include <asm/tx4927/tx4927_pci.h>
+
+#undef DEBUG
+#ifdef DEBUG
+#define DBG(x...) printk(x)
+#else
+#define DBG(x...)
+#endif
+
+/* look up table for backplane pci irq for slots 17-20 by pin # */
+static unsigned char backplane_pci_irq[4][4] = {
+ /* PJ6 SLOT: 17, PIN: 1 */ {TX4927_IRQ_IOC_PCIA,
+ /* PJ6 SLOT: 17, PIN: 2 */
+ TX4927_IRQ_IOC_PCIB,
+ /* PJ6 SLOT: 17, PIN: 3 */
+ TX4927_IRQ_IOC_PCIC,
+ /* PJ6 SLOT: 17, PIN: 4 */
+ TX4927_IRQ_IOC_PCID},
+ /* SB SLOT: 18, PIN: 1 */ {TX4927_IRQ_IOC_PCIB,
+ /* SB SLOT: 18, PIN: 2 */
+ TX4927_IRQ_IOC_PCIC,
+ /* SB SLOT: 18, PIN: 3 */
+ TX4927_IRQ_IOC_PCID,
+ /* SB SLOT: 18, PIN: 4 */
+ TX4927_IRQ_IOC_PCIA},
+ /* PJ5 SLOT: 19, PIN: 1 */ {TX4927_IRQ_IOC_PCIC,
+ /* PJ5 SLOT: 19, PIN: 2 */
+ TX4927_IRQ_IOC_PCID,
+ /* PJ5 SLOT: 19, PIN: 3 */
+ TX4927_IRQ_IOC_PCIA,
+ /* PJ5 SLOT: 19, PIN: 4 */
+ TX4927_IRQ_IOC_PCIB},
+ /* PJ4 SLOT: 20, PIN: 1 */ {TX4927_IRQ_IOC_PCID,
+ /* PJ4 SLOT: 20, PIN: 2 */
+ TX4927_IRQ_IOC_PCIA,
+ /* PJ4 SLOT: 20, PIN: 3 */
+ TX4927_IRQ_IOC_PCIB,
+ /* PJ4 SLOT: 20, PIN: 4 */
+ TX4927_IRQ_IOC_PCIC}
+};
+
+int pci_get_irq(struct pci_dev *dev, int pin)
+{
+ unsigned char irq = pin;
+
+ DBG("pci_get_irq: pin is %d\n", pin);
+ /* IRQ rotation */
+ irq--; /* 0-3 */
+ if (dev->bus->parent == NULL &&
+ PCI_SLOT(dev->devfn) == TX4927_PCIC_IDSEL_AD_TO_SLOT(23)) {
+ printk("Onboard PCI_SLOT(dev->devfn) is %d\n",
+ PCI_SLOT(dev->devfn));
+ /* IDSEL=A23 is tx4927 onboard pci slot */
+ irq = (irq + PCI_SLOT(dev->devfn)) % 4;
+ irq++; /* 1-4 */
+ DBG("irq is now %d\n", irq);
+
+ switch (irq) {
+ case 1:
+ irq = TX4927_IRQ_IOC_PCIA;
+ break;
+ case 2:
+ irq = TX4927_IRQ_IOC_PCIB;
+ break;
+ case 3:
+ irq = TX4927_IRQ_IOC_PCIC;
+ break;
+ case 4:
+ irq = TX4927_IRQ_IOC_PCID;
+ break;
+ }
+ } else {
+ /* PCI Backplane */
+ DBG("PCI Backplane PCI_SLOT(dev->devfn) is %d\n",
+ PCI_SLOT(dev->devfn));
+ irq = backplane_pci_irq[PCI_SLOT(dev->devfn) - 17][irq];
+ }
+ DBG("assigned irq %d\n", irq);
+ return irq;
+}
+
+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+ unsigned char irq;
+
+ printk("PCI Setup for pin %d \n", pin);
+
+ if (dev->device == 0x9130) /* IDE */
+ irq = 14;
+ else
+ irq = pci_get_irq(dev, pin);
+
+ return irq;
+}
+
+/* Do platform specific device initialization at pci_enable_device() time */
+int pcibios_plat_dev_init(struct pci_dev *dev)
+{
+ return 0;
+}
diff --git a/arch/mips/pci/fixup-sb1250.c b/arch/mips/pci/fixup-sb1250.c
new file mode 100644
index 0000000..13791b7
--- /dev/null
+++ b/arch/mips/pci/fixup-sb1250.c
@@ -0,0 +1,24 @@
+/*
+ * arch/mips/pci/fixup-sb1250.c
+ *
+ * Copyright (C) 2004 MIPS Technologies, Inc. All rights reserved.
+ * Author: Maciej W. Rozycki <macro@mips.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/init.h>
+#include <linux/pci.h>
+
+/*
+ * The BCM1250, etc. PCI/HT bridge reports as a host bridge.
+ */
+static void __init quirk_sb1250_ht(struct pci_dev *dev)
+{
+ dev->class = PCI_CLASS_BRIDGE_PCI << 8;
+}
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SIBYTE, PCI_DEVICE_ID_BCM1250_HT,
+ quirk_sb1250_ht);
diff --git a/arch/mips/pci/fixup-sni.c b/arch/mips/pci/fixup-sni.c
new file mode 100644
index 0000000..c8ef01a
--- /dev/null
+++ b/arch/mips/pci/fixup-sni.c
@@ -0,0 +1,89 @@
+/*
+ * 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.
+ *
+ * SNI specific PCI support for RM200/RM300.
+ *
+ * Copyright (C) 1997 - 2000, 2003, 04 Ralf Baechle (ralf@linux-mips.org)
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+
+#include <asm/mipsregs.h>
+#include <asm/sni.h>
+
+/*
+ * Shortcuts ...
+ */
+#define SCSI PCIMT_IRQ_SCSI
+#define ETH PCIMT_IRQ_ETHERNET
+#define INTA PCIMT_IRQ_INTA
+#define INTB PCIMT_IRQ_INTB
+#define INTC PCIMT_IRQ_INTC
+#define INTD PCIMT_IRQ_INTD
+
+/*
+ * Device 0: PCI EISA Bridge (directly routed)
+ * Device 1: NCR53c810 SCSI (directly routed)
+ * Device 2: PCnet32 Ethernet (directly routed)
+ * Device 3: VGA (routed to INTB)
+ * Device 4: Unused
+ * Device 5: Slot 2
+ * Device 6: Slot 3
+ * Device 7: Slot 4
+ *
+ * Documentation says the VGA is device 5 and device 3 is unused but that
+ * seem to be a documentation error. At least on my RM200C the Cirrus
+ * Logic CL-GD5434 VGA is device 3.
+ */
+static char irq_tab_rm200[8][5] __initdata = {
+ /* INTA INTB INTC INTD */
+ { 0, 0, 0, 0, 0 }, /* EISA bridge */
+ { SCSI, SCSI, SCSI, SCSI, SCSI }, /* SCSI */
+ { ETH, ETH, ETH, ETH, ETH }, /* Ethernet */
+ { INTB, INTB, INTB, INTB, INTB }, /* VGA */
+ { 0, 0, 0, 0, 0 }, /* Unused */
+ { 0, INTB, INTC, INTD, INTA }, /* Slot 2 */
+ { 0, INTC, INTD, INTA, INTB }, /* Slot 3 */
+ { 0, INTD, INTA, INTB, INTC }, /* Slot 4 */
+};
+
+/*
+ * In Revision D of the RM300 Device 2 has become a normal purpose Slot 1
+ *
+ * The VGA card is optional for RM300 systems.
+ */
+static char irq_tab_rm300d[8][5] __initdata = {
+ /* INTA INTB INTC INTD */
+ { 0, 0, 0, 0, 0 }, /* EISA bridge */
+ { SCSI, SCSI, SCSI, SCSI, SCSI }, /* SCSI */
+ { 0, INTC, INTD, INTA, INTB }, /* Slot 1 */
+ { INTB, INTB, INTB, INTB, INTB }, /* VGA */
+ { 0, 0, 0, 0, 0 }, /* Unused */
+ { 0, INTB, INTC, INTD, INTA }, /* Slot 2 */
+ { 0, INTC, INTD, INTA, INTB }, /* Slot 3 */
+ { 0, INTD, INTA, INTB, INTC }, /* Slot 4 */
+};
+
+static inline int is_rm300_revd(void)
+{
+ unsigned char csmsr = *(volatile unsigned char *)PCIMT_CSMSR;
+
+ return (csmsr & 0xa0) == 0x20;
+}
+
+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+ if (is_rm300_revd())
+ return irq_tab_rm300d[slot][pin];
+
+ return irq_tab_rm200[slot][pin];
+}
+
+/* Do platform specific device initialization at pci_enable_device() time */
+int pcibios_plat_dev_init(struct pci_dev *dev)
+{
+ return 0;
+}
diff --git a/arch/mips/pci/fixup-tb0219.c b/arch/mips/pci/fixup-tb0219.c
new file mode 100644
index 0000000..850a900
--- /dev/null
+++ b/arch/mips/pci/fixup-tb0219.c
@@ -0,0 +1,66 @@
+/*
+ * fixup-tb0219.c, The TANBAC TB0219 specific PCI fixups.
+ *
+ * Copyright (C) 2003 Megasolution Inc. <matsu@megasolution.jp>
+ * Copyright (C) 2004 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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 <linux/init.h>
+#include <linux/pci.h>
+
+#include <asm/vr41xx/tb0219.h>
+
+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+ int irq = -1;
+
+ switch (slot) {
+ case 12:
+ vr41xx_set_irq_trigger(TB0219_PCI_SLOT1_PIN,
+ TRIGGER_LEVEL,
+ SIGNAL_THROUGH);
+ vr41xx_set_irq_level(TB0219_PCI_SLOT1_PIN,
+ LEVEL_LOW);
+ irq = TB0219_PCI_SLOT1_IRQ;
+ break;
+ case 13:
+ vr41xx_set_irq_trigger(TB0219_PCI_SLOT2_PIN,
+ TRIGGER_LEVEL,
+ SIGNAL_THROUGH);
+ vr41xx_set_irq_level(TB0219_PCI_SLOT2_PIN,
+ LEVEL_LOW);
+ irq = TB0219_PCI_SLOT2_IRQ;
+ break;
+ case 14:
+ vr41xx_set_irq_trigger(TB0219_PCI_SLOT3_PIN,
+ TRIGGER_LEVEL,
+ SIGNAL_THROUGH);
+ vr41xx_set_irq_level(TB0219_PCI_SLOT3_PIN,
+ LEVEL_LOW);
+ irq = TB0219_PCI_SLOT3_IRQ;
+ break;
+ default:
+ break;
+ }
+
+ return irq;
+}
+
+/* Do platform specific device initialization at pci_enable_device() time */
+int pcibios_plat_dev_init(struct pci_dev *dev)
+{
+ return 0;
+}
diff --git a/arch/mips/pci/fixup-tb0226.c b/arch/mips/pci/fixup-tb0226.c
new file mode 100644
index 0000000..61513d5
--- /dev/null
+++ b/arch/mips/pci/fixup-tb0226.c
@@ -0,0 +1,85 @@
+/*
+ * fixup-tb0226.c, The TANBAC TB0226 specific PCI fixups.
+ *
+ * Copyright (C) 2002-2004 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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 <linux/init.h>
+#include <linux/pci.h>
+
+#include <asm/vr41xx/tb0226.h>
+
+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+ int irq = -1;
+
+ switch (slot) {
+ case 12:
+ vr41xx_set_irq_trigger(GD82559_1_PIN,
+ TRIGGER_LEVEL,
+ SIGNAL_THROUGH);
+ vr41xx_set_irq_level(GD82559_1_PIN, LEVEL_LOW);
+ irq = GD82559_1_IRQ;
+ break;
+ case 13:
+ vr41xx_set_irq_trigger(GD82559_2_PIN,
+ TRIGGER_LEVEL,
+ SIGNAL_THROUGH);
+ vr41xx_set_irq_level(GD82559_2_PIN, LEVEL_LOW);
+ irq = GD82559_2_IRQ;
+ break;
+ case 14:
+ switch (pin) {
+ case 1:
+ vr41xx_set_irq_trigger(UPD720100_INTA_PIN,
+ TRIGGER_LEVEL,
+ SIGNAL_THROUGH);
+ vr41xx_set_irq_level(UPD720100_INTA_PIN,
+ LEVEL_LOW);
+ irq = UPD720100_INTA_IRQ;
+ break;
+ case 2:
+ vr41xx_set_irq_trigger(UPD720100_INTB_PIN,
+ TRIGGER_LEVEL,
+ SIGNAL_THROUGH);
+ vr41xx_set_irq_level(UPD720100_INTB_PIN,
+ LEVEL_LOW);
+ irq = UPD720100_INTB_IRQ;
+ break;
+ case 3:
+ vr41xx_set_irq_trigger(UPD720100_INTC_PIN,
+ TRIGGER_LEVEL,
+ SIGNAL_THROUGH);
+ vr41xx_set_irq_level(UPD720100_INTC_PIN,
+ LEVEL_LOW);
+ irq = UPD720100_INTC_IRQ;
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return irq;
+}
+
+/* Do platform specific device initialization at pci_enable_device() time */
+int pcibios_plat_dev_init(struct pci_dev *dev)
+{
+ return 0;
+}
diff --git a/arch/mips/pci/fixup-vr4133.c b/arch/mips/pci/fixup-vr4133.c
new file mode 100644
index 0000000..03a0ff2
--- /dev/null
+++ b/arch/mips/pci/fixup-vr4133.c
@@ -0,0 +1,204 @@
+/*
+ * arch/mips/vr41xx/nec-cmbvr4133/pci_fixup.c
+ *
+ * The NEC CMB-VR4133 Board specific PCI fixups.
+ *
+ * Author: Yoichi Yuasa <yyuasa@mvista.com, or source@mvista.com> and
+ * Alex Sapkov <asapkov@ru.mvista.com>
+ *
+ * 2003-2004 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ *
+ * Modified for support in 2.6
+ * Author: Manish Lachwani (mlachwani@mvista.com)
+ *
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+
+#include <asm/io.h>
+#include <asm/vr41xx/cmbvr4133.h>
+
+extern int vr4133_rockhopper;
+extern void ali_m1535plus_init(struct pci_dev *dev);
+extern void ali_m5229_init(struct pci_dev *dev);
+
+/* Do platform specific device initialization at pci_enable_device() time */
+int pcibios_plat_dev_init(struct pci_dev *dev)
+{
+ /*
+ * We have to reset AMD PCnet adapter on Rockhopper since
+ * PMON leaves it enabled and generating interrupts. This leads
+ * to a lock if some PCI device driver later enables the IRQ line
+ * shared with PCnet and there is no AMD PCnet driver to catch its
+ * interrupts.
+ */
+#ifdef CONFIG_ROCKHOPPER
+ if (dev->vendor == PCI_VENDOR_ID_AMD &&
+ dev->device == PCI_DEVICE_ID_AMD_LANCE) {
+ inl(pci_resource_start(dev, 0) + 0x18);
+ }
+#endif
+
+ /*
+ * we have to open the bridges' windows down to 0 because otherwise
+ * we cannot access ISA south bridge I/O registers that get mapped from
+ * 0. for example, 8259 PIC would be unaccessible without that
+ */
+ if(dev->vendor == PCI_VENDOR_ID_INTEL && dev->device == PCI_DEVICE_ID_INTEL_S21152BB) {
+ pci_write_config_byte(dev, PCI_IO_BASE, 0);
+ if(dev->bus->number == 0) {
+ pci_write_config_word(dev, PCI_IO_BASE_UPPER16, 0);
+ } else {
+ pci_write_config_word(dev, PCI_IO_BASE_UPPER16, 1);
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * M1535 IRQ mapping
+ * Feel free to change this, although it shouldn't be needed
+ */
+#define M1535_IRQ_INTA 7
+#define M1535_IRQ_INTB 9
+#define M1535_IRQ_INTC 10
+#define M1535_IRQ_INTD 11
+
+#define M1535_IRQ_USB 9
+#define M1535_IRQ_IDE 14
+#define M1535_IRQ_IDE2 15
+#define M1535_IRQ_PS2 12
+#define M1535_IRQ_RTC 8
+#define M1535_IRQ_FDC 6
+#define M1535_IRQ_AUDIO 5
+#define M1535_IRQ_COM1 4
+#define M1535_IRQ_COM2 4
+#define M1535_IRQ_IRDA 3
+#define M1535_IRQ_KBD 1
+#define M1535_IRQ_TMR 0
+
+/* Rockhopper "slots" assignment; this is hard-coded ... */
+#define ROCKHOPPER_M5451_SLOT 1
+#define ROCKHOPPER_M1535_SLOT 2
+#define ROCKHOPPER_M5229_SLOT 11
+#define ROCKHOPPER_M5237_SLOT 15
+#define ROCKHOPPER_PMU_SLOT 12
+/* ... and hard-wired. */
+#define ROCKHOPPER_PCI1_SLOT 3
+#define ROCKHOPPER_PCI2_SLOT 4
+#define ROCKHOPPER_PCI3_SLOT 5
+#define ROCKHOPPER_PCI4_SLOT 6
+#define ROCKHOPPER_PCNET_SLOT 1
+
+#define M1535_IRQ_MASK(n) (1 << (n))
+
+#define M1535_IRQ_EDGE (M1535_IRQ_MASK(M1535_IRQ_TMR) | \
+ M1535_IRQ_MASK(M1535_IRQ_KBD) | \
+ M1535_IRQ_MASK(M1535_IRQ_COM1) | \
+ M1535_IRQ_MASK(M1535_IRQ_COM2) | \
+ M1535_IRQ_MASK(M1535_IRQ_IRDA) | \
+ M1535_IRQ_MASK(M1535_IRQ_RTC) | \
+ M1535_IRQ_MASK(M1535_IRQ_FDC) | \
+ M1535_IRQ_MASK(M1535_IRQ_PS2))
+
+#define M1535_IRQ_LEVEL (M1535_IRQ_MASK(M1535_IRQ_IDE) | \
+ M1535_IRQ_MASK(M1535_IRQ_USB) | \
+ M1535_IRQ_MASK(M1535_IRQ_INTA) | \
+ M1535_IRQ_MASK(M1535_IRQ_INTB) | \
+ M1535_IRQ_MASK(M1535_IRQ_INTC) | \
+ M1535_IRQ_MASK(M1535_IRQ_INTD))
+
+struct irq_map_entry {
+ u16 bus;
+ u8 slot;
+ u8 irq;
+};
+static struct irq_map_entry int_map[] = {
+ {1, ROCKHOPPER_M5451_SLOT, M1535_IRQ_AUDIO}, /* Audio controller */
+ {1, ROCKHOPPER_PCI1_SLOT, M1535_IRQ_INTD}, /* PCI slot #1 */
+ {1, ROCKHOPPER_PCI2_SLOT, M1535_IRQ_INTC}, /* PCI slot #2 */
+ {1, ROCKHOPPER_M5237_SLOT, M1535_IRQ_USB}, /* USB host controller */
+ {1, ROCKHOPPER_M5229_SLOT, IDE_PRIMARY_IRQ}, /* IDE controller */
+ {2, ROCKHOPPER_PCNET_SLOT, M1535_IRQ_INTD}, /* AMD Am79c973 on-board
+ ethernet */
+ {2, ROCKHOPPER_PCI3_SLOT, M1535_IRQ_INTB}, /* PCI slot #3 */
+ {2, ROCKHOPPER_PCI4_SLOT, M1535_IRQ_INTC} /* PCI slot #4 */
+};
+
+static int pci_intlines[] =
+ { M1535_IRQ_INTA, M1535_IRQ_INTB, M1535_IRQ_INTC, M1535_IRQ_INTD };
+
+/* Determine the Rockhopper IRQ line number for the PCI device */
+int rockhopper_get_irq(struct pci_dev *dev, u8 pin, u8 slot)
+{
+ struct pci_bus *bus;
+ int i;
+
+ bus = dev->bus;
+ if (bus == NULL)
+ return -1;
+
+ for (i = 0; i < sizeof (int_map) / sizeof (int_map[0]); i++) {
+ if (int_map[i].bus == bus->number && int_map[i].slot == slot) {
+ int line;
+ for (line = 0; line < 4; line++)
+ if (pci_intlines[line] == int_map[i].irq)
+ break;
+ if (line < 4)
+ return pci_intlines[(line + (pin - 1)) % 4];
+ else
+ return int_map[i].irq;
+ }
+ }
+ return -1;
+}
+
+#ifdef CONFIG_ROCKHOPPER
+void i8259_init(void)
+{
+ outb(0x11, 0x20); /* Master ICW1 */
+ outb(I8259_IRQ_BASE, 0x21); /* Master ICW2 */
+ outb(0x04, 0x21); /* Master ICW3 */
+ outb(0x01, 0x21); /* Master ICW4 */
+ outb(0xff, 0x21); /* Master IMW */
+
+ outb(0x11, 0xa0); /* Slave ICW1 */
+ outb(I8259_IRQ_BASE + 8, 0xa1); /* Slave ICW2 */
+ outb(0x02, 0xa1); /* Slave ICW3 */
+ outb(0x01, 0xa1); /* Slave ICW4 */
+ outb(0xff, 0xa1); /* Slave IMW */
+
+ outb(0x00, 0x4d0);
+ outb(0x02, 0x4d1); /* USB IRQ9 is level */
+}
+#endif
+
+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+ extern int pci_probe_only;
+ pci_probe_only = 1;
+
+#ifdef CONFIG_ROCKHOPPER
+ if( dev->bus->number == 1 && vr4133_rockhopper ) {
+ if(slot == ROCKHOPPER_PCI1_SLOT || slot == ROCKHOPPER_PCI2_SLOT)
+ dev->irq = CMBVR41XX_INTA_IRQ;
+ else
+ dev->irq = rockhopper_get_irq(dev, pin, slot);
+ } else
+ dev->irq = CMBVR41XX_INTA_IRQ;
+#else
+ dev->irq = CMBVR41XX_INTA_IRQ;
+#endif
+
+ return dev->irq;
+}
+
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, ali_m1535plus_init);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M5229, ali_m5229_init);
+
+
diff --git a/arch/mips/pci/fixup-yosemite.c b/arch/mips/pci/fixup-yosemite.c
new file mode 100644
index 0000000..81d77a5
--- /dev/null
+++ b/arch/mips/pci/fixup-yosemite.c
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2003 PMC-Sierra
+ * Author: Manish Lachwani (lachwani@pmc-sierra.com)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+
+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+ if (pin == 0)
+ return -1;
+
+ return 3; /* Everything goes to one irq bit */
+}
+
+/* Do platform specific device initialization at pci_enable_device() time */
+int pcibios_plat_dev_init(struct pci_dev *dev)
+{
+ return 0;
+}
diff --git a/arch/mips/pci/ops-au1000.c b/arch/mips/pci/ops-au1000.c
new file mode 100644
index 0000000..c1c91ca
--- /dev/null
+++ b/arch/mips/pci/ops-au1000.c
@@ -0,0 +1,325 @@
+/*
+ * BRIEF MODULE DESCRIPTION
+ * Alchemy/AMD Au1x00 pci support.
+ *
+ * Copyright 2001,2002,2003 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ * ppopov@mvista.com or source@mvista.com
+ *
+ * Support for all devices (greater than 16) added by David Gathright.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/vmalloc.h>
+
+#include <asm/mach-au1x00/au1000.h>
+
+#undef DEBUG
+#ifdef DEBUG
+#define DBG(x...) printk(x)
+#else
+#define DBG(x...)
+#endif
+
+#define PCI_ACCESS_READ 0
+#define PCI_ACCESS_WRITE 1
+
+
+int (*board_pci_idsel)(unsigned int devsel, int assert);
+
+/* CP0 hazard avoidance. */
+#define BARRIER __asm__ __volatile__(".set noreorder\n\t" \
+ "nop; nop; nop; nop;\t" \
+ ".set reorder\n\t")
+
+void mod_wired_entry(int entry, unsigned long entrylo0,
+ unsigned long entrylo1, unsigned long entryhi,
+ unsigned long pagemask)
+{
+ unsigned long old_pagemask;
+ unsigned long old_ctx;
+
+ /* Save old context and create impossible VPN2 value */
+ old_ctx = read_c0_entryhi() & 0xff;
+ old_pagemask = read_c0_pagemask();
+ write_c0_index(entry);
+ BARRIER;
+ write_c0_pagemask(pagemask);
+ write_c0_entryhi(entryhi);
+ write_c0_entrylo0(entrylo0);
+ write_c0_entrylo1(entrylo1);
+ BARRIER;
+ tlb_write_indexed();
+ BARRIER;
+ write_c0_entryhi(old_ctx);
+ BARRIER;
+ write_c0_pagemask(old_pagemask);
+}
+
+struct vm_struct *pci_cfg_vm;
+static int pci_cfg_wired_entry;
+static int first_cfg = 1;
+unsigned long last_entryLo0, last_entryLo1;
+
+static int config_access(unsigned char access_type, struct pci_bus *bus,
+ unsigned int dev_fn, unsigned char where,
+ u32 * data)
+{
+#if defined( CONFIG_SOC_AU1500 ) || defined( CONFIG_SOC_AU1550 )
+ unsigned int device = PCI_SLOT(dev_fn);
+ unsigned int function = PCI_FUNC(dev_fn);
+ unsigned long offset, status;
+ unsigned long cfg_base;
+ unsigned long flags;
+ int error = PCIBIOS_SUCCESSFUL;
+ unsigned long entryLo0, entryLo1;
+
+ if (device > 19) {
+ *data = 0xffffffff;
+ return -1;
+ }
+
+ local_irq_save(flags);
+ au_writel(((0x2000 << 16) | (au_readl(Au1500_PCI_STATCMD) & 0xffff)),
+ Au1500_PCI_STATCMD);
+ au_sync_udelay(1);
+
+ /*
+ * We can't ioremap the entire pci config space because it's
+ * too large. Nor can we call ioremap dynamically because some
+ * device drivers use the pci config routines from within
+ * interrupt handlers and that becomes a problem in get_vm_area().
+ * We use one wired tlb to handle all config accesses for all
+ * busses. To improve performance, if the current device
+ * is the same as the last device accessed, we don't touch the
+ * tlb.
+ */
+ if (first_cfg) {
+ /* reserve a wired entry for pci config accesses */
+ first_cfg = 0;
+ pci_cfg_vm = get_vm_area(0x2000, 0);
+ if (!pci_cfg_vm)
+ panic (KERN_ERR "PCI unable to get vm area\n");
+ pci_cfg_wired_entry = read_c0_wired();
+ add_wired_entry(0, 0, (unsigned long)pci_cfg_vm->addr, PM_4K);
+ last_entryLo0 = last_entryLo1 = 0xffffffff;
+ }
+
+ /* Since the Au1xxx doesn't do the idsel timing exactly to spec,
+ * many board vendors implement their own off-chip idsel, so call
+ * it now. If it doesn't succeed, may as well bail out at this point.
+ */
+ if (board_pci_idsel) {
+ if (board_pci_idsel(device, 1) == 0) {
+ *data = 0xffffffff;
+ local_irq_restore(flags);
+ return -1;
+ }
+ }
+
+ /* setup the config window */
+ if (bus->number == 0) {
+ cfg_base = ((1<<device)<<11);
+ } else {
+ cfg_base = 0x80000000 | (bus->number<<16) | (device<<11);
+ }
+
+ /* setup the lower bits of the 36 bit address */
+ offset = (function << 8) | (where & ~0x3);
+ /* pick up any address that falls below the page mask */
+ offset |= cfg_base & ~PAGE_MASK;
+
+ /* page boundary */
+ cfg_base = cfg_base & PAGE_MASK;
+
+ entryLo0 = (6 << 26) | (cfg_base >> 6) | (2 << 3) | 7;
+ entryLo1 = (6 << 26) | (cfg_base >> 6) | (0x1000 >> 6) | (2 << 3) | 7;
+
+ if ((entryLo0 != last_entryLo0) || (entryLo1 != last_entryLo1)) {
+ mod_wired_entry(pci_cfg_wired_entry, entryLo0, entryLo1,
+ (unsigned long)pci_cfg_vm->addr, PM_4K);
+ last_entryLo0 = entryLo0;
+ last_entryLo1 = entryLo1;
+ }
+
+ if (access_type == PCI_ACCESS_WRITE) {
+ au_writel(*data, (int)(pci_cfg_vm->addr + offset));
+ } else {
+ *data = au_readl((int)(pci_cfg_vm->addr + offset));
+ }
+ au_sync_udelay(2);
+
+ DBG("cfg_access %d bus->number %d dev %d at %x *data %x conf %x\n",
+ access_type, bus->number, device, where, *data, offset);
+
+ /* check master abort */
+ status = au_readl(Au1500_PCI_STATCMD);
+
+ if (status & (1<<29)) {
+ *data = 0xffffffff;
+ error = -1;
+ DBG("Au1x Master Abort\n");
+ } else if ((status >> 28) & 0xf) {
+ DBG("PCI ERR detected: status %x\n", status);
+ *data = 0xffffffff;
+ error = -1;
+ }
+
+ /* Take away the idsel.
+ */
+ if (board_pci_idsel) {
+ (void)board_pci_idsel(device, 0);
+ }
+
+ local_irq_restore(flags);
+ return error;
+#endif
+}
+
+static int read_config_byte(struct pci_bus *bus, unsigned int devfn,
+ int where, u8 * val)
+{
+ u32 data;
+ int ret;
+
+ ret = config_access(PCI_ACCESS_READ, bus, devfn, where, &data);
+ if (where & 1)
+ data >>= 8;
+ if (where & 2)
+ data >>= 16;
+ *val = data & 0xff;
+ return ret;
+}
+
+
+static int read_config_word(struct pci_bus *bus, unsigned int devfn,
+ int where, u16 * val)
+{
+ u32 data;
+ int ret;
+
+ ret = config_access(PCI_ACCESS_READ, bus, devfn, where, &data);
+ if (where & 2)
+ data >>= 16;
+ *val = data & 0xffff;
+ return ret;
+}
+
+static int read_config_dword(struct pci_bus *bus, unsigned int devfn,
+ int where, u32 * val)
+{
+ int ret;
+
+ ret = config_access(PCI_ACCESS_READ, bus, devfn, where, val);
+ return ret;
+}
+
+static int
+write_config_byte(struct pci_bus *bus, unsigned int devfn, int where,
+ u8 val)
+{
+ u32 data = 0;
+
+ if (config_access(PCI_ACCESS_READ, bus, devfn, where, &data))
+ return -1;
+
+ data = (data & ~(0xff << ((where & 3) << 3))) |
+ (val << ((where & 3) << 3));
+
+ if (config_access(PCI_ACCESS_WRITE, bus, devfn, where, &data))
+ return -1;
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int
+write_config_word(struct pci_bus *bus, unsigned int devfn, int where,
+ u16 val)
+{
+ u32 data = 0;
+
+ if (config_access(PCI_ACCESS_READ, bus, devfn, where, &data))
+ return -1;
+
+ data = (data & ~(0xffff << ((where & 3) << 3))) |
+ (val << ((where & 3) << 3));
+
+ if (config_access(PCI_ACCESS_WRITE, bus, devfn, where, &data))
+ return -1;
+
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int
+write_config_dword(struct pci_bus *bus, unsigned int devfn, int where,
+ u32 val)
+{
+ if (config_access(PCI_ACCESS_WRITE, bus, devfn, where, &val))
+ return -1;
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int config_read(struct pci_bus *bus, unsigned int devfn,
+ int where, int size, u32 * val)
+{
+ switch (size) {
+ case 1: {
+ u8 _val;
+ int rc = read_config_byte(bus, devfn, where, &_val);
+ *val = _val;
+ return rc;
+ }
+ case 2: {
+ u16 _val;
+ int rc = read_config_word(bus, devfn, where, &_val);
+ *val = _val;
+ return rc;
+ }
+ default:
+ return read_config_dword(bus, devfn, where, val);
+ }
+}
+
+static int config_write(struct pci_bus *bus, unsigned int devfn,
+ int where, int size, u32 val)
+{
+ switch (size) {
+ case 1:
+ return write_config_byte(bus, devfn, where, (u8) val);
+ case 2:
+ return write_config_word(bus, devfn, where, (u16) val);
+ default:
+ return write_config_dword(bus, devfn, where, val);
+ }
+}
+
+
+struct pci_ops au1x_pci_ops = {
+ config_read,
+ config_write
+};
diff --git a/arch/mips/pci/ops-bonito64.c b/arch/mips/pci/ops-bonito64.c
new file mode 100644
index 0000000..4b4e086
--- /dev/null
+++ b/arch/mips/pci/ops-bonito64.c
@@ -0,0 +1,196 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999, 2000 MIPS Technologies, Inc. All rights reserved.
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * MIPS boards specific PCI support.
+ */
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/mips-boards/bonito64.h>
+
+#define PCI_ACCESS_READ 0
+#define PCI_ACCESS_WRITE 1
+
+/*
+ * PCI configuration cycle AD bus definition
+ */
+/* Type 0 */
+#define PCI_CFG_TYPE0_REG_SHF 0
+#define PCI_CFG_TYPE0_FUNC_SHF 8
+
+/* Type 1 */
+#define PCI_CFG_TYPE1_REG_SHF 0
+#define PCI_CFG_TYPE1_FUNC_SHF 8
+#define PCI_CFG_TYPE1_DEV_SHF 11
+#define PCI_CFG_TYPE1_BUS_SHF 16
+
+static int bonito64_pcibios_config_access(unsigned char access_type,
+ struct pci_bus *bus,
+ unsigned int devfn, int where,
+ u32 * data)
+{
+ unsigned char busnum = bus->number;
+ u32 dummy;
+ u64 pci_addr;
+
+ /* Algorithmics Bonito64 system controller. */
+
+ if ((busnum == 0) && (PCI_SLOT(devfn) > 21)) {
+ /* We number bus 0 devices from 0..21 */
+ return -1;
+ }
+
+#ifdef CONFIG_MIPS_BOARDS_GEN
+ if ((busnum == 0) && (PCI_SLOT(devfn) == 17)) {
+ /* MIPS Core boards have Bonito connected as device 17 */
+ return -1;
+ }
+#endif
+
+ /* Clear cause register bits */
+ BONITO_PCICMD |= (BONITO_PCICMD_MABORT_CLR |
+ BONITO_PCICMD_MTABORT_CLR);
+
+ /*
+ * Setup pattern to be used as PCI "address" for
+ * Type 0 cycle
+ */
+ if (busnum == 0) {
+ /* IDSEL */
+ pci_addr = (u64) 1 << (PCI_SLOT(devfn) + 10);
+ } else {
+ /* Bus number */
+ pci_addr = busnum << PCI_CFG_TYPE1_BUS_SHF;
+
+ /* Device number */
+ pci_addr |=
+ PCI_SLOT(devfn) << PCI_CFG_TYPE1_DEV_SHF;
+ }
+
+ /* Function (same for Type 0/1) */
+ pci_addr |= PCI_FUNC(devfn) << PCI_CFG_TYPE0_FUNC_SHF;
+
+ /* Register number (same for Type 0/1) */
+ pci_addr |= (where & ~0x3) << PCI_CFG_TYPE0_REG_SHF;
+
+ if (busnum == 0) {
+ /* Type 0 */
+ BONITO_PCIMAP_CFG = pci_addr >> 16;
+ } else {
+ /* Type 1 */
+ BONITO_PCIMAP_CFG = (pci_addr >> 16) | 0x10000;
+ }
+
+ pci_addr &= 0xffff;
+
+ /* Flush Bonito register block */
+ dummy = BONITO_PCIMAP_CFG;
+ iob(); /* sync */
+
+ /* Perform access */
+ if (access_type == PCI_ACCESS_WRITE) {
+ *(volatile u32 *) (_pcictrl_bonito_pcicfg + (u32)pci_addr) = *(u32 *) data;
+
+ /* Wait till done */
+ while (BONITO_PCIMSTAT & 0xF);
+ } else {
+ *(u32 *) data = *(volatile u32 *) (_pcictrl_bonito_pcicfg + (u32)pci_addr);
+ }
+
+ /* Detect Master/Target abort */
+ if (BONITO_PCICMD & (BONITO_PCICMD_MABORT_CLR |
+ BONITO_PCICMD_MTABORT_CLR)) {
+ /* Error occurred */
+
+ /* Clear bits */
+ BONITO_PCICMD |= (BONITO_PCICMD_MABORT_CLR |
+ BONITO_PCICMD_MTABORT_CLR);
+
+ return -1;
+ }
+
+ return 0;
+}
+
+
+/*
+ * We can't address 8 and 16 bit words directly. Instead we have to
+ * read/write a 32bit word and mask/modify the data we actually want.
+ */
+static int bonito64_pcibios_read(struct pci_bus *bus, unsigned int devfn,
+ int where, int size, u32 * val)
+{
+ u32 data = 0;
+
+ if ((size == 2) && (where & 1))
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+ else if ((size == 4) && (where & 3))
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+
+ if (bonito64_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, where,
+ &data))
+ return -1;
+
+ if (size == 1)
+ *val = (data >> ((where & 3) << 3)) & 0xff;
+ else if (size == 2)
+ *val = (data >> ((where & 3) << 3)) & 0xffff;
+ else
+ *val = data;
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int bonito64_pcibios_write(struct pci_bus *bus, unsigned int devfn,
+ int where, int size, u32 val)
+{
+ u32 data = 0;
+
+ if ((size == 2) && (where & 1))
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+ else if ((size == 4) && (where & 3))
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+
+ if (size == 4)
+ data = val;
+ else {
+ if (bonito64_pcibios_config_access(PCI_ACCESS_READ, bus, devfn,
+ where, &data))
+ return -1;
+
+ if (size == 1)
+ data = (data & ~(0xff << ((where & 3) << 3))) |
+ (val << ((where & 3) << 3));
+ else if (size == 2)
+ data = (data & ~(0xffff << ((where & 3) << 3))) |
+ (val << ((where & 3) << 3));
+ }
+
+ if (bonito64_pcibios_config_access(PCI_ACCESS_WRITE, bus, devfn, where,
+ &data))
+ return -1;
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+struct pci_ops bonito64_pci_ops = {
+ .read = bonito64_pcibios_read,
+ .write = bonito64_pcibios_write
+};
diff --git a/arch/mips/pci/ops-ddb5074.c b/arch/mips/pci/ops-ddb5074.c
new file mode 100644
index 0000000..89f97bef4
--- /dev/null
+++ b/arch/mips/pci/ops-ddb5074.c
@@ -0,0 +1,271 @@
+/*
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
+ *
+ * arch/mips/ddb5xxx/ddb5476/pci_ops.c
+ * Define the pci_ops for DB5477.
+ *
+ * Much of the code is derived from the original DDB5074 port by
+ * Geert Uytterhoeven <geert@sonycom.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+
+#include <asm/addrspace.h>
+#include <asm/debug.h>
+
+#include <asm/ddb5xxx/ddb5xxx.h>
+
+/*
+ * config_swap structure records what set of pdar/pmr are used
+ * to access pci config space. It also provides a place hold the
+ * original values for future restoring.
+ */
+struct pci_config_swap {
+ u32 pdar;
+ u32 pmr;
+ u32 config_base;
+ u32 config_size;
+ u32 pdar_backup;
+ u32 pmr_backup;
+};
+
+/*
+ * On DDB5476, we have one set of swap registers
+ */
+struct pci_config_swap ext_pci_swap = {
+ DDB_PCIW0,
+ DDB_PCIINIT0,
+ DDB_PCI_CONFIG_BASE,
+ DDB_PCI_CONFIG_SIZE
+};
+
+static int pci_config_workaround = 1;
+
+/*
+ * access config space
+ */
+static inline u32 ddb_access_config_base(struct pci_config_swap *swap, u32 bus, /* 0 means top level bus */
+ u32 slot_num)
+{
+ u32 pci_addr = 0;
+ u32 pciinit_offset = 0;
+ u32 virt_addr = swap->config_base;
+ u32 option;
+
+ if (pci_config_workaround) {
+ if (slot_num == 5)
+ slot_num = 14;
+ } else {
+ if (slot_num == 5)
+ return DDB_BASE + DDB_PCI_BASE;
+ }
+
+ /* minimum pdar (window) size is 2MB */
+ db_assert(swap->config_size >= (2 << 20));
+
+ db_assert(slot_num < (1 << 5));
+ db_assert(bus < (1 << 8));
+
+ /* backup registers */
+ swap->pdar_backup = ddb_in32(swap->pdar);
+ swap->pmr_backup = ddb_in32(swap->pmr);
+
+ /* set the pdar (pci window) register */
+ ddb_set_pdar(swap->pdar, swap->config_base, swap->config_size, 32, /* 32 bit wide */
+ 0, /* not on local memory bus */
+ 0); /* not visible from PCI bus (N/A) */
+
+ /*
+ * calcuate the absolute pci config addr;
+ * according to the spec, we start scanning from adr:11 (0x800)
+ */
+ if (bus == 0) {
+ /* type 0 config */
+ pci_addr = 0x00040000 << slot_num;
+ } else {
+ /* type 1 config */
+ pci_addr = 0x00040000 << slot_num;
+ panic
+ ("ddb_access_config_base: we don't support type 1 config Yet");
+ }
+
+ /*
+ * if pci_addr is less than pci config window size, we set
+ * pciinit_offset to 0 and adjust the virt_address.
+ * Otherwise we will try to adjust pciinit_offset.
+ */
+ if (pci_addr < swap->config_size) {
+ virt_addr = KSEG1ADDR(swap->config_base + pci_addr);
+ pciinit_offset = 0;
+ } else {
+ db_assert((pci_addr & (swap->config_size - 1)) == 0);
+ virt_addr = KSEG1ADDR(swap->config_base);
+ pciinit_offset = pci_addr;
+ }
+
+ /* set the pmr register */
+ option = DDB_PCI_ACCESS_32;
+ if (bus != 0)
+ option |= DDB_PCI_CFGTYPE1;
+ ddb_set_pmr(swap->pmr, DDB_PCICMD_CFG, pciinit_offset, option);
+
+ return virt_addr;
+}
+
+static inline void ddb_close_config_base(struct pci_config_swap *swap)
+{
+ ddb_out32(swap->pdar, swap->pdar_backup);
+ ddb_out32(swap->pmr, swap->pmr_backup);
+}
+
+static int read_config_dword(struct pci_config_swap *swap,
+ struct pci_dev *dev, u32 where, u32 * val)
+{
+ u32 bus, slot_num, func_num;
+ u32 base;
+
+ db_assert((where & 3) == 0);
+ db_assert(where < (1 << 8));
+
+ /* check if the bus is top-level */
+ if (dev->bus->parent != NULL) {
+ bus = dev->bus->number;
+ db_assert(bus != 0);
+ } else {
+ bus = 0;
+ }
+
+ slot_num = PCI_SLOT(dev->devfn);
+ func_num = PCI_FUNC(dev->devfn);
+ base = ddb_access_config_base(swap, bus, slot_num);
+ *val = *(volatile u32 *) (base + (func_num << 8) + where);
+ ddb_close_config_base(swap);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int read_config_word(struct pci_config_swap *swap,
+ struct pci_dev *dev, u32 where, u16 * val)
+{
+ int status;
+ u32 result;
+
+ db_assert((where & 1) == 0);
+
+ status = read_config_dword(swap, dev, where & ~3, &result);
+ if (where & 2)
+ result >>= 16;
+ *val = result & 0xffff;
+ return status;
+}
+
+static int read_config_byte(struct pci_config_swap *swap,
+ struct pci_dev *dev, u32 where, u8 * val)
+{
+ int status;
+ u32 result;
+
+ status = read_config_dword(swap, dev, where & ~3, &result);
+ if (where & 1)
+ result >>= 8;
+ if (where & 2)
+ result >>= 16;
+ *val = result & 0xff;
+ return status;
+}
+
+static int write_config_dword(struct pci_config_swap *swap,
+ struct pci_dev *dev, u32 where, u32 val)
+{
+ u32 bus, slot_num, func_num;
+ u32 base;
+
+ db_assert((where & 3) == 0);
+ db_assert(where < (1 << 8));
+
+ /* check if the bus is top-level */
+ if (dev->bus->parent != NULL) {
+ bus = dev->bus->number;
+ db_assert(bus != 0);
+ } else {
+ bus = 0;
+ }
+
+ slot_num = PCI_SLOT(dev->devfn);
+ func_num = PCI_FUNC(dev->devfn);
+ base = ddb_access_config_base(swap, bus, slot_num);
+ *(volatile u32 *) (base + (func_num << 8) + where) = val;
+ ddb_close_config_base(swap);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int write_config_word(struct pci_config_swap *swap,
+ struct pci_dev *dev, u32 where, u16 val)
+{
+ int status, shift = 0;
+ u32 result;
+
+ db_assert((where & 1) == 0);
+
+ status = read_config_dword(swap, dev, where & ~3, &result);
+ if (status != PCIBIOS_SUCCESSFUL)
+ return status;
+
+ if (where & 2)
+ shift += 16;
+ result &= ~(0xffff << shift);
+ result |= val << shift;
+ return write_config_dword(swap, dev, where & ~3, result);
+}
+
+static int write_config_byte(struct pci_config_swap *swap,
+ struct pci_dev *dev, u32 where, u8 val)
+{
+ int status, shift = 0;
+ u32 result;
+
+ status = read_config_dword(swap, dev, where & ~3, &result);
+ if (status != PCIBIOS_SUCCESSFUL)
+ return status;
+
+ if (where & 2)
+ shift += 16;
+ if (where & 1)
+ shift += 8;
+ result &= ~(0xff << shift);
+ result |= val << shift;
+ return write_config_dword(swap, dev, where & ~3, result);
+}
+
+#define MAKE_PCI_OPS(prefix, rw, unitname, unittype, pciswap) \
+static int prefix##_##rw##_config_##unitname(struct pci_dev *dev, int where, unittype val) \
+{ \
+ return rw##_config_##unitname(pciswap, \
+ dev, \
+ where, \
+ val); \
+}
+
+MAKE_PCI_OPS(extpci, read, byte, u8 *, &ext_pci_swap)
+ MAKE_PCI_OPS(extpci, read, word, u16 *, &ext_pci_swap)
+ MAKE_PCI_OPS(extpci, read, dword, u32 *, &ext_pci_swap)
+
+ MAKE_PCI_OPS(extpci, write, byte, u8, &ext_pci_swap)
+ MAKE_PCI_OPS(extpci, write, word, u16, &ext_pci_swap)
+ MAKE_PCI_OPS(extpci, write, dword, u32, &ext_pci_swap)
+
+struct pci_ops ddb5476_ext_pci_ops = {
+ extpci_read_config_byte,
+ extpci_read_config_word,
+ extpci_read_config_dword,
+ extpci_write_config_byte,
+ extpci_write_config_word,
+ extpci_write_config_dword
+};
diff --git a/arch/mips/pci/ops-ddb5476.c b/arch/mips/pci/ops-ddb5476.c
new file mode 100644
index 0000000..12da58e
--- /dev/null
+++ b/arch/mips/pci/ops-ddb5476.c
@@ -0,0 +1,286 @@
+/*
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
+ *
+ * arch/mips/ddb5xxx/ddb5476/pci_ops.c
+ * Define the pci_ops for DB5477.
+ *
+ * Much of the code is derived from the original DDB5074 port by
+ * Geert Uytterhoeven <geert@sonycom.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+
+#include <asm/addrspace.h>
+#include <asm/debug.h>
+
+#include <asm/ddb5xxx/ddb5xxx.h>
+
+/*
+ * config_swap structure records what set of pdar/pmr are used
+ * to access pci config space. It also provides a place hold the
+ * original values for future restoring.
+ */
+struct pci_config_swap {
+ u32 pdar;
+ u32 pmr;
+ u32 config_base;
+ u32 config_size;
+ u32 pdar_backup;
+ u32 pmr_backup;
+};
+
+/*
+ * On DDB5476, we have one set of swap registers
+ */
+struct pci_config_swap ext_pci_swap = {
+ DDB_PCIW0,
+ DDB_PCIINIT0,
+ DDB_PCI_CONFIG_BASE,
+ DDB_PCI_CONFIG_SIZE
+};
+
+static int pci_config_workaround = 1;
+
+/*
+ * access config space
+ */
+static inline u32 ddb_access_config_base(struct pci_config_swap *swap, u32 bus, /* 0 means top level bus */
+ u32 slot_num)
+{
+ u32 pci_addr = 0;
+ u32 pciinit_offset = 0;
+ u32 virt_addr = swap->config_base;
+ u32 option;
+
+ if (pci_config_workaround) {
+ /* [jsun] work around Vrc5476 controller itself, returnning
+ * slot 0 essentially makes vrc5476 invisible
+ */
+ if (slot_num == 12)
+ slot_num = 0;
+
+#if 0
+ /* BUG : skip P2P bridge for now */
+ if (slot_num == 5)
+ slot_num = 0;
+#endif
+
+ } else {
+ /* now we have to be hornest, returning the true
+ * PCI config headers for vrc5476
+ */
+ if (slot_num == 12) {
+ swap->pdar_backup = ddb_in32(swap->pdar);
+ swap->pmr_backup = ddb_in32(swap->pmr);
+ return DDB_BASE + DDB_PCI_BASE;
+ }
+ }
+
+ /* minimum pdar (window) size is 2MB */
+ db_assert(swap->config_size >= (2 << 20));
+
+ db_assert(slot_num < (1 << 5));
+ db_assert(bus < (1 << 8));
+
+ /* backup registers */
+ swap->pdar_backup = ddb_in32(swap->pdar);
+ swap->pmr_backup = ddb_in32(swap->pmr);
+
+ /* set the pdar (pci window) register */
+ ddb_set_pdar(swap->pdar, swap->config_base, swap->config_size, 32, /* 32 bit wide */
+ 0, /* not on local memory bus */
+ 0); /* not visible from PCI bus (N/A) */
+
+ /*
+ * calcuate the absolute pci config addr;
+ * according to the spec, we start scanning from adr:11 (0x800)
+ */
+ if (bus == 0) {
+ /* type 0 config */
+ pci_addr = 0x800 << slot_num;
+ } else {
+ /* type 1 config */
+ pci_addr = (bus << 16) | (slot_num << 11);
+ /* panic("ddb_access_config_base: we don't support type 1 config Yet"); */
+ }
+
+ /*
+ * if pci_addr is less than pci config window size, we set
+ * pciinit_offset to 0 and adjust the virt_address.
+ * Otherwise we will try to adjust pciinit_offset.
+ */
+ if (pci_addr < swap->config_size) {
+ virt_addr = KSEG1ADDR(swap->config_base + pci_addr);
+ pciinit_offset = 0;
+ } else {
+ db_assert((pci_addr & (swap->config_size - 1)) == 0);
+ virt_addr = KSEG1ADDR(swap->config_base);
+ pciinit_offset = pci_addr;
+ }
+
+ /* set the pmr register */
+ option = DDB_PCI_ACCESS_32;
+ if (bus != 0)
+ option |= DDB_PCI_CFGTYPE1;
+ ddb_set_pmr(swap->pmr, DDB_PCICMD_CFG, pciinit_offset, option);
+
+ return virt_addr;
+}
+
+static inline void ddb_close_config_base(struct pci_config_swap *swap)
+{
+ ddb_out32(swap->pdar, swap->pdar_backup);
+ ddb_out32(swap->pmr, swap->pmr_backup);
+}
+
+static int read_config_dword(struct pci_config_swap *swap,
+ struct pci_dev *dev, u32 where, u32 * val)
+{
+ u32 bus, slot_num, func_num;
+ u32 base;
+
+ db_assert((where & 3) == 0);
+ db_assert(where < (1 << 8));
+
+ /* check if the bus is top-level */
+ if (dev->bus->parent != NULL) {
+ bus = dev->bus->number;
+ db_assert(bus != 0);
+ } else {
+ bus = 0;
+ }
+
+ slot_num = PCI_SLOT(dev->devfn);
+ func_num = PCI_FUNC(dev->devfn);
+ base = ddb_access_config_base(swap, bus, slot_num);
+ *val = *(volatile u32 *) (base + (func_num << 8) + where);
+ ddb_close_config_base(swap);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int read_config_word(struct pci_config_swap *swap,
+ struct pci_dev *dev, u32 where, u16 * val)
+{
+ int status;
+ u32 result;
+
+ db_assert((where & 1) == 0);
+
+ status = read_config_dword(swap, dev, where & ~3, &result);
+ if (where & 2)
+ result >>= 16;
+ *val = result & 0xffff;
+ return status;
+}
+
+static int read_config_byte(struct pci_config_swap *swap,
+ struct pci_dev *dev, u32 where, u8 * val)
+{
+ int status;
+ u32 result;
+
+ status = read_config_dword(swap, dev, where & ~3, &result);
+ if (where & 1)
+ result >>= 8;
+ if (where & 2)
+ result >>= 16;
+ *val = result & 0xff;
+ return status;
+}
+
+static int write_config_dword(struct pci_config_swap *swap,
+ struct pci_dev *dev, u32 where, u32 val)
+{
+ u32 bus, slot_num, func_num;
+ u32 base;
+
+ db_assert((where & 3) == 0);
+ db_assert(where < (1 << 8));
+
+ /* check if the bus is top-level */
+ if (dev->bus->parent != NULL) {
+ bus = dev->bus->number;
+ db_assert(bus != 0);
+ } else {
+ bus = 0;
+ }
+
+ slot_num = PCI_SLOT(dev->devfn);
+ func_num = PCI_FUNC(dev->devfn);
+ base = ddb_access_config_base(swap, bus, slot_num);
+ *(volatile u32 *) (base + (func_num << 8) + where) = val;
+ ddb_close_config_base(swap);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int write_config_word(struct pci_config_swap *swap,
+ struct pci_dev *dev, u32 where, u16 val)
+{
+ int status, shift = 0;
+ u32 result;
+
+ db_assert((where & 1) == 0);
+
+ status = read_config_dword(swap, dev, where & ~3, &result);
+ if (status != PCIBIOS_SUCCESSFUL)
+ return status;
+
+ if (where & 2)
+ shift += 16;
+ result &= ~(0xffff << shift);
+ result |= val << shift;
+ return write_config_dword(swap, dev, where & ~3, result);
+}
+
+static int write_config_byte(struct pci_config_swap *swap,
+ struct pci_dev *dev, u32 where, u8 val)
+{
+ int status, shift = 0;
+ u32 result;
+
+ status = read_config_dword(swap, dev, where & ~3, &result);
+ if (status != PCIBIOS_SUCCESSFUL)
+ return status;
+
+ if (where & 2)
+ shift += 16;
+ if (where & 1)
+ shift += 8;
+ result &= ~(0xff << shift);
+ result |= val << shift;
+ return write_config_dword(swap, dev, where & ~3, result);
+}
+
+#define MAKE_PCI_OPS(prefix, rw, unitname, unittype, pciswap) \
+static int prefix##_##rw##_config_##unitname(struct pci_dev *dev, int where, unittype val) \
+{ \
+ return rw##_config_##unitname(pciswap, \
+ dev, \
+ where, \
+ val); \
+}
+
+MAKE_PCI_OPS(extpci, read, byte, u8 *, &ext_pci_swap)
+ MAKE_PCI_OPS(extpci, read, word, u16 *, &ext_pci_swap)
+ MAKE_PCI_OPS(extpci, read, dword, u32 *, &ext_pci_swap)
+
+ MAKE_PCI_OPS(extpci, write, byte, u8, &ext_pci_swap)
+ MAKE_PCI_OPS(extpci, write, word, u16, &ext_pci_swap)
+ MAKE_PCI_OPS(extpci, write, dword, u32, &ext_pci_swap)
+
+struct pci_ops ddb5476_ext_pci_ops = {
+ extpci_read_config_byte,
+ extpci_read_config_word,
+ extpci_read_config_dword,
+ extpci_write_config_byte,
+ extpci_write_config_word,
+ extpci_write_config_dword
+};
diff --git a/arch/mips/pci/ops-ddb5477.c b/arch/mips/pci/ops-ddb5477.c
new file mode 100644
index 0000000..e955443
--- /dev/null
+++ b/arch/mips/pci/ops-ddb5477.c
@@ -0,0 +1,278 @@
+/***********************************************************************
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
+ *
+ * arch/mips/ddb5xxx/ddb5477/pci_ops.c
+ * Define the pci_ops for DB5477.
+ *
+ * Much of the code is derived from the original DDB5074 port by
+ * Geert Uytterhoeven <geert@sonycom.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ ***********************************************************************
+ */
+
+/*
+ * DDB5477 has two PCI channels, external PCI and IOPIC (internal)
+ * Therefore we provide two sets of pci_ops.
+ */
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+
+#include <asm/addrspace.h>
+#include <asm/debug.h>
+
+#include <asm/ddb5xxx/ddb5xxx.h>
+
+/*
+ * config_swap structure records what set of pdar/pmr are used
+ * to access pci config space. It also provides a place hold the
+ * original values for future restoring.
+ */
+struct pci_config_swap {
+ u32 pdar;
+ u32 pmr;
+ u32 config_base;
+ u32 config_size;
+ u32 pdar_backup;
+ u32 pmr_backup;
+};
+
+/*
+ * On DDB5477, we have two sets of swap registers, for ext PCI and IOPCI.
+ */
+struct pci_config_swap ext_pci_swap = {
+ DDB_PCIW0,
+ DDB_PCIINIT00,
+ DDB_PCI0_CONFIG_BASE,
+ DDB_PCI0_CONFIG_SIZE
+};
+struct pci_config_swap io_pci_swap = {
+ DDB_IOPCIW0,
+ DDB_PCIINIT01,
+ DDB_PCI1_CONFIG_BASE,
+ DDB_PCI1_CONFIG_SIZE
+};
+
+
+/*
+ * access config space
+ */
+static inline u32 ddb_access_config_base(struct pci_config_swap *swap, u32 bus, /* 0 means top level bus */
+ u32 slot_num)
+{
+ u32 pci_addr = 0;
+ u32 pciinit_offset = 0;
+ u32 virt_addr;
+ u32 option;
+
+ /* minimum pdar (window) size is 2MB */
+ db_assert(swap->config_size >= (2 << 20));
+
+ db_assert(slot_num < (1 << 5));
+ db_assert(bus < (1 << 8));
+
+ /* backup registers */
+ swap->pdar_backup = ddb_in32(swap->pdar);
+ swap->pmr_backup = ddb_in32(swap->pmr);
+
+ /* set the pdar (pci window) register */
+ ddb_set_pdar(swap->pdar, swap->config_base, swap->config_size, 32, /* 32 bit wide */
+ 0, /* not on local memory bus */
+ 0); /* not visible from PCI bus (N/A) */
+
+ /*
+ * calcuate the absolute pci config addr;
+ * according to the spec, we start scanning from adr:11 (0x800)
+ */
+ if (bus == 0) {
+ /* type 0 config */
+ pci_addr = 0x800 << slot_num;
+ } else {
+ /* type 1 config */
+ pci_addr = (bus << 16) | (slot_num << 11);
+ }
+
+ /*
+ * if pci_addr is less than pci config window size, we set
+ * pciinit_offset to 0 and adjust the virt_address.
+ * Otherwise we will try to adjust pciinit_offset.
+ */
+ if (pci_addr < swap->config_size) {
+ virt_addr = KSEG1ADDR(swap->config_base + pci_addr);
+ pciinit_offset = 0;
+ } else {
+ db_assert((pci_addr & (swap->config_size - 1)) == 0);
+ virt_addr = KSEG1ADDR(swap->config_base);
+ pciinit_offset = pci_addr;
+ }
+
+ /* set the pmr register */
+ option = DDB_PCI_ACCESS_32;
+ if (bus != 0)
+ option |= DDB_PCI_CFGTYPE1;
+ ddb_set_pmr(swap->pmr, DDB_PCICMD_CFG, pciinit_offset, option);
+
+ return virt_addr;
+}
+
+static inline void ddb_close_config_base(struct pci_config_swap *swap)
+{
+ ddb_out32(swap->pdar, swap->pdar_backup);
+ ddb_out32(swap->pmr, swap->pmr_backup);
+}
+
+static int read_config_dword(struct pci_config_swap *swap,
+ struct pci_bus *bus, u32 devfn, u32 where,
+ u32 * val)
+{
+ u32 bus_num, slot_num, func_num;
+ u32 base;
+
+ db_assert((where & 3) == 0);
+ db_assert(where < (1 << 8));
+
+ /* check if the bus is top-level */
+ if (bus->parent != NULL) {
+ bus_num = bus->number;
+ db_assert(bus_num != 0);
+ } else {
+ bus_num = 0;
+ }
+
+ slot_num = PCI_SLOT(devfn);
+ func_num = PCI_FUNC(devfn);
+ base = ddb_access_config_base(swap, bus_num, slot_num);
+ *val = *(volatile u32 *) (base + (func_num << 8) + where);
+ ddb_close_config_base(swap);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int read_config_word(struct pci_config_swap *swap,
+ struct pci_bus *bus, u32 devfn, u32 where,
+ u16 * val)
+{
+ int status;
+ u32 result;
+
+ db_assert((where & 1) == 0);
+
+ status = read_config_dword(swap, bus, devfn, where & ~3, &result);
+ if (where & 2)
+ result >>= 16;
+ *val = result & 0xffff;
+ return status;
+}
+
+static int read_config_byte(struct pci_config_swap *swap,
+ struct pci_bus *bus, u32 devfn, u32 where,
+ u8 * val)
+{
+ int status;
+ u32 result;
+
+ status = read_config_dword(swap, bus, devfn, where & ~3, &result);
+ if (where & 1)
+ result >>= 8;
+ if (where & 2)
+ result >>= 16;
+ *val = result & 0xff;
+
+ return status;
+}
+
+static int write_config_dword(struct pci_config_swap *swap,
+ struct pci_bus *bus, u32 devfn, u32 where,
+ u32 val)
+{
+ u32 bus_num, slot_num, func_num;
+ u32 base;
+
+ db_assert((where & 3) == 0);
+ db_assert(where < (1 << 8));
+
+ /* check if the bus is top-level */
+ if (bus->parent != NULL) {
+ bus_num = bus->number;
+ db_assert(bus_num != 0);
+ } else {
+ bus_num = 0;
+ }
+
+ slot_num = PCI_SLOT(devfn);
+ func_num = PCI_FUNC(devfn);
+ base = ddb_access_config_base(swap, bus_num, slot_num);
+ *(volatile u32 *) (base + (func_num << 8) + where) = val;
+ ddb_close_config_base(swap);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int write_config_word(struct pci_config_swap *swap,
+ struct pci_bus *bus, u32 devfn, u32 where, u16 val)
+{
+ int status, shift = 0;
+ u32 result;
+
+ db_assert((where & 1) == 0);
+
+ status = read_config_dword(swap, bus, devfn, where & ~3, &result);
+ if (status != PCIBIOS_SUCCESSFUL)
+ return status;
+
+ if (where & 2)
+ shift += 16;
+ result &= ~(0xffff << shift);
+ result |= val << shift;
+ return write_config_dword(swap, bus, devfn, where & ~3, result);
+}
+
+static int write_config_byte(struct pci_config_swap *swap,
+ struct pci_bus *bus, u32 devfn, u32 where, u8 val)
+{
+ int status, shift = 0;
+ u32 result;
+
+ status = read_config_dword(swap, bus, devfn, where & ~3, &result);
+ if (status != PCIBIOS_SUCCESSFUL)
+ return status;
+
+ if (where & 2)
+ shift += 16;
+ if (where & 1)
+ shift += 8;
+ result &= ~(0xff << shift);
+ result |= val << shift;
+ return write_config_dword(swap, bus, devfn, where & ~3, result);
+}
+
+#define MAKE_PCI_OPS(prefix, rw, pciswap, star) \
+static int prefix##_##rw##_config(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 star val) \
+{ \
+ if (size == 1) \
+ return rw##_config_byte(pciswap, bus, devfn, where, (u8 star)val); \
+ else if (size == 2) \
+ return rw##_config_word(pciswap, bus, devfn, where, (u16 star)val); \
+ /* Size must be 4 */ \
+ return rw##_config_dword(pciswap, bus, devfn, where, val); \
+}
+
+MAKE_PCI_OPS(extpci, read, &ext_pci_swap, *)
+MAKE_PCI_OPS(extpci, write, &ext_pci_swap,)
+
+MAKE_PCI_OPS(iopci, read, &io_pci_swap, *)
+MAKE_PCI_OPS(iopci, write, &io_pci_swap,)
+
+struct pci_ops ddb5477_ext_pci_ops = {
+ .read = extpci_read_config,
+ .write = extpci_write_config
+};
+
+
+struct pci_ops ddb5477_io_pci_ops = {
+ .read = iopci_read_config,
+ .write = iopci_write_config
+};
diff --git a/arch/mips/pci/ops-gt64111.c b/arch/mips/pci/ops-gt64111.c
new file mode 100644
index 0000000..c5b0fc1
--- /dev/null
+++ b/arch/mips/pci/ops-gt64111.c
@@ -0,0 +1,100 @@
+/*
+ * 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, 1996, 1997, 2002 by Ralf Baechle
+ * Copyright (C) 2001, 2002, 2003 by Liam Davies (ldavies@agile.tv)
+ */
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/pci.h>
+#include <asm/io.h>
+#include <asm/gt64120.h>
+
+#include <asm/cobalt/cobalt.h>
+
+/*
+ * Accessing device 31 hangs the GT64120. Not sure if this will also hang
+ * the GT64111, let's be paranoid for now.
+ */
+static inline int pci_range_ck(struct pci_bus *bus, unsigned int devfn)
+{
+ if (bus->number == 0 && devfn == PCI_DEVFN(31, 0))
+ return -1;
+
+ return 0;
+}
+
+static int gt64111_pci_read_config(struct pci_bus *bus, unsigned int devfn,
+ int where, int size, u32 * val)
+{
+ if (pci_range_ck(bus, devfn))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ switch (size) {
+ case 4:
+ PCI_CFG_SET(devfn, where);
+ *val = GALILEO_INL(GT_PCI0_CFGDATA_OFS);
+ return PCIBIOS_SUCCESSFUL;
+
+ case 2:
+ PCI_CFG_SET(devfn, (where & ~0x3));
+ *val = GALILEO_INL(GT_PCI0_CFGDATA_OFS)
+ >> ((where & 3) * 8);
+ return PCIBIOS_SUCCESSFUL;
+
+ case 1:
+ PCI_CFG_SET(devfn, (where & ~0x3));
+ *val = GALILEO_INL(GT_PCI0_CFGDATA_OFS)
+ >> ((where & 3) * 8);
+ return PCIBIOS_SUCCESSFUL;
+ }
+
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+}
+
+static int gt64111_pci_write_config(struct pci_bus *bus, unsigned int devfn,
+ int where, int size, u32 val)
+{
+ u32 tmp;
+
+ if (pci_range_ck(bus, devfn))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ switch (size) {
+ case 4:
+ PCI_CFG_SET(devfn, where);
+ GALILEO_OUTL(val, GT_PCI0_CFGDATA_OFS);
+
+ return PCIBIOS_SUCCESSFUL;
+
+ case 2:
+ PCI_CFG_SET(devfn, (where & ~0x3));
+ tmp = GALILEO_INL(GT_PCI0_CFGDATA_OFS);
+ tmp &= ~(0xffff << ((where & 0x3) * 8));
+ tmp |= (val << ((where & 0x3) * 8));
+ GALILEO_OUTL(tmp, GT_PCI0_CFGDATA_OFS);
+
+ return PCIBIOS_SUCCESSFUL;
+
+ case 1:
+ PCI_CFG_SET(devfn, (where & ~0x3));
+ tmp = GALILEO_INL(GT_PCI0_CFGDATA_OFS);
+ tmp &= ~(0xff << ((where & 0x3) * 8));
+ tmp |= (val << ((where & 0x3) * 8));
+ GALILEO_OUTL(tmp, GT_PCI0_CFGDATA_OFS);
+
+ return PCIBIOS_SUCCESSFUL;
+ }
+
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+}
+
+struct pci_ops gt64111_pci_ops = {
+ .read = gt64111_pci_read_config,
+ .write = gt64111_pci_write_config,
+};
diff --git a/arch/mips/pci/ops-gt64120.c b/arch/mips/pci/ops-gt64120.c
new file mode 100644
index 0000000..7b99dfa
--- /dev/null
+++ b/arch/mips/pci/ops-gt64120.c
@@ -0,0 +1,154 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999, 2000 MIPS Technologies, Inc. All rights reserved.
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ */
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+
+#include <asm/gt64120.h>
+
+#define PCI_ACCESS_READ 0
+#define PCI_ACCESS_WRITE 1
+
+/*
+ * PCI configuration cycle AD bus definition
+ */
+/* Type 0 */
+#define PCI_CFG_TYPE0_REG_SHF 0
+#define PCI_CFG_TYPE0_FUNC_SHF 8
+
+/* Type 1 */
+#define PCI_CFG_TYPE1_REG_SHF 0
+#define PCI_CFG_TYPE1_FUNC_SHF 8
+#define PCI_CFG_TYPE1_DEV_SHF 11
+#define PCI_CFG_TYPE1_BUS_SHF 16
+
+static int gt64120_pcibios_config_access(unsigned char access_type,
+ struct pci_bus *bus, unsigned int devfn, int where, u32 * data)
+{
+ unsigned char busnum = bus->number;
+ u32 intr;
+
+ if ((busnum == 0) && (PCI_SLOT(devfn) == 0))
+ /* Galileo itself is devfn 0, don't move it around */
+ return -1;
+
+ if ((busnum == 0) && (devfn >= PCI_DEVFN(31, 0)))
+ return -1; /* Because of a bug in the galileo (for slot 31). */
+
+ /* Clear cause register bits */
+ GT_WRITE(GT_INTRCAUSE_OFS, ~(GT_INTRCAUSE_MASABORT0_BIT |
+ GT_INTRCAUSE_TARABORT0_BIT));
+
+ /* Setup address */
+ GT_WRITE(GT_PCI0_CFGADDR_OFS,
+ (busnum << GT_PCI0_CFGADDR_BUSNUM_SHF) |
+ (devfn << GT_PCI0_CFGADDR_FUNCTNUM_SHF) |
+ ((where / 4) << GT_PCI0_CFGADDR_REGNUM_SHF) |
+ GT_PCI0_CFGADDR_CONFIGEN_BIT);
+
+ if (access_type == PCI_ACCESS_WRITE) {
+ if (busnum == 0 && PCI_SLOT(devfn) == 0) {
+ /*
+ * The Galileo system controller is acting
+ * differently than other devices.
+ */
+ GT_WRITE(GT_PCI0_CFGDATA_OFS, *data);
+ } else
+ __GT_WRITE(GT_PCI0_CFGDATA_OFS, *data);
+ } else {
+ if (busnum == 0 && PCI_SLOT(devfn) == 0) {
+ /*
+ * The Galileo system controller is acting
+ * differently than other devices.
+ */
+ *data = GT_READ(GT_PCI0_CFGDATA_OFS);
+ } else
+ *data = __GT_READ(GT_PCI0_CFGDATA_OFS);
+ }
+
+ /* Check for master or target abort */
+ intr = GT_READ(GT_INTRCAUSE_OFS);
+
+ if (intr & (GT_INTRCAUSE_MASABORT0_BIT | GT_INTRCAUSE_TARABORT0_BIT)) {
+ /* Error occurred */
+
+ /* Clear bits */
+ GT_WRITE(GT_INTRCAUSE_OFS, ~(GT_INTRCAUSE_MASABORT0_BIT |
+ GT_INTRCAUSE_TARABORT0_BIT));
+
+ return -1;
+ }
+
+ return 0;
+}
+
+
+/*
+ * We can't address 8 and 16 bit words directly. Instead we have to
+ * read/write a 32bit word and mask/modify the data we actually want.
+ */
+static int gt64120_pcibios_read(struct pci_bus *bus, unsigned int devfn,
+ int where, int size, u32 * val)
+{
+ u32 data = 0;
+
+ if (gt64120_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, where,
+ &data))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ if (size == 1)
+ *val = (data >> ((where & 3) << 3)) & 0xff;
+ else if (size == 2)
+ *val = (data >> ((where & 3) << 3)) & 0xffff;
+ else
+ *val = data;
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int gt64120_pcibios_write(struct pci_bus *bus, unsigned int devfn,
+ int where, int size, u32 val)
+{
+ u32 data = 0;
+
+ if (size == 4)
+ data = val;
+ else {
+ if (gt64120_pcibios_config_access(PCI_ACCESS_READ, bus, devfn,
+ where, &data))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ if (size == 1)
+ data = (data & ~(0xff << ((where & 3) << 3))) |
+ (val << ((where & 3) << 3));
+ else if (size == 2)
+ data = (data & ~(0xffff << ((where & 3) << 3))) |
+ (val << ((where & 3) << 3));
+ }
+
+ if (gt64120_pcibios_config_access(PCI_ACCESS_WRITE, bus, devfn, where,
+ &data))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+struct pci_ops gt64120_pci_ops = {
+ .read = gt64120_pcibios_read,
+ .write = gt64120_pcibios_write
+};
diff --git a/arch/mips/pci/ops-gt96100.c b/arch/mips/pci/ops-gt96100.c
new file mode 100644
index 0000000..9e4ea66
--- /dev/null
+++ b/arch/mips/pci/ops-gt96100.c
@@ -0,0 +1,169 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ * Galileo EV96100 board specific pci support.
+ *
+ * Copyright 2000 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ * ppopov@mvista.com or source@mvista.com
+ *
+ * This file was derived from Carsten Langgaard's
+ * arch/mips/mips-boards/generic/pci.c
+ *
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/delay.h>
+#include <asm/gt64120.h>
+#include <asm/galileo-boards/ev96100.h>
+
+#define PCI_ACCESS_READ 0
+#define PCI_ACCESS_WRITE 1
+
+static int static gt96100_config_access(unsigned char access_type,
+ struct pci_bus *bus, unsigned int devfn, int where, u32 * data)
+{
+ unsigned char bus = bus->number;
+ u32 intr;
+
+ /*
+ * Because of a bug in the galileo (for slot 31).
+ */
+ if (bus == 0 && devfn >= PCI_DEVFN(31, 0))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ /* Clear cause register bits */
+ GT_WRITE(GT_INTRCAUSE_OFS, ~(GT_INTRCAUSE_MASABORT0_BIT |
+ GT_INTRCAUSE_TARABORT0_BIT));
+
+ /* Setup address */
+ GT_WRITE(GT_PCI0_CFGADDR_OFS,
+ (bus << GT_PCI0_CFGADDR_BUSNUM_SHF) |
+ (devfn << GT_PCI0_CFGADDR_FUNCTNUM_SHF) |
+ ((where / 4) << GT_PCI0_CFGADDR_REGNUM_SHF) |
+ GT_PCI0_CFGADDR_CONFIGEN_BIT);
+ udelay(2);
+
+
+ if (access_type == PCI_ACCESS_WRITE) {
+ if (devfn != 0)
+ *data = le32_to_cpu(*data);
+ GT_WRITE(GT_PCI0_CFGDATA_OFS, *data);
+ } else {
+ *data = GT_READ(GT_PCI0_CFGDATA_OFS);
+ if (devfn != 0)
+ *data = le32_to_cpu(*data);
+ }
+
+ udelay(2);
+
+ /* Check for master or target abort */
+ intr = GT_READ(GT_INTRCAUSE_OFS);
+
+ if (intr & (GT_INTRCAUSE_MASABORT0_BIT | GT_INTRCAUSE_TARABORT0_BIT)) {
+ /* Error occured */
+
+ /* Clear bits */
+ GT_WRITE(GT_INTRCAUSE_OFS, ~(GT_INTRCAUSE_MASABORT0_BIT |
+ GT_INTRCAUSE_TARABORT0_BIT));
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ * We can't address 8 and 16 bit words directly. Instead we have to
+ * read/write a 32bit word and mask/modify the data we actually want.
+ */
+static int gt96100_pcibios_read(struct pci_bus *bus, unsigned int devfn,
+ int where, int size, u32 * val)
+{
+ u32 data = 0;
+
+ if (gt96100_config_access(PCI_ACCESS_READ, bus, devfn, where, &data))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ switch (size) {
+ case 1:
+ *val = (data >> ((where & 3) << 3)) & 0xff;
+ break;
+
+ case 2:
+ *val = (data >> ((where & 3) << 3)) & 0xffff;
+ break;
+
+ case 4:
+ *val = data;
+ break;
+ }
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int gt96100_pcibios_write(struct pci_bus *bus, unsigned int devfn,
+ int where, int size, u32 val)
+{
+ u32 data = 0;
+
+ switch (size) {
+ case 1:
+ if (gt96100_config_access(PCI_ACCESS_READ, bus, devfn, where, &data))
+ return -1;
+
+ data = (data & ~(0xff << ((where & 3) << 3))) |
+ (val << ((where & 3) << 3));
+
+ if (gt96100_config_access(PCI_ACCESS_WRITE, bus, devfn, where, &data))
+ return -1;
+
+ return PCIBIOS_SUCCESSFUL;
+
+ case 2:
+ if (gt96100_config_access(PCI_ACCESS_READ, bus, devfn, where, &data))
+ return -1;
+
+ data = (data & ~(0xffff << ((where & 3) << 3))) |
+ (val << ((where & 3) << 3));
+
+ if (gt96100_config_access(PCI_ACCESS_WRITE, dev, where, &data))
+ return -1;
+
+
+ return PCIBIOS_SUCCESSFUL;
+
+ case 4:
+ if (gt96100_config_access(PCI_ACCESS_WRITE, dev, where, &val))
+ return -1;
+
+ return PCIBIOS_SUCCESSFUL;
+ }
+}
+
+struct pci_ops gt96100_pci_ops = {
+ .read = gt96100_pcibios_read,
+ .write = gt96100_pcibios_write
+};
diff --git a/arch/mips/pci/ops-it8172.c b/arch/mips/pci/ops-it8172.c
new file mode 100644
index 0000000..b7a8b9a
--- /dev/null
+++ b/arch/mips/pci/ops-it8172.c
@@ -0,0 +1,215 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ * IT8172 system controller specific pci support.
+ *
+ * Copyright 2000 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ * ppopov@mvista.com or source@mvista.com
+ *
+ * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/it8172/it8172.h>
+#include <asm/it8172/it8172_pci.h>
+
+#define PCI_ACCESS_READ 0
+#define PCI_ACCESS_WRITE 1
+
+#undef DEBUG
+#ifdef DEBUG
+#define DBG(x...) printk(x)
+#else
+#define DBG(x...)
+#endif
+
+static struct resource pci_mem_resource_1;
+
+static struct resource pci_io_resource = {
+ "io pci IO space",
+ 0x14018000,
+ 0x17FFFFFF,
+ IORESOURCE_IO
+};
+
+static struct resource pci_mem_resource_0 = {
+ "ext pci memory space 0/1",
+ 0x10101000,
+ 0x13FFFFFF,
+ IORESOURCE_MEM,
+ &pci_mem_resource_0,
+ NULL,
+ &pci_mem_resource_1
+};
+
+static struct resource pci_mem_resource_1 = {
+ "ext pci memory space 2/3",
+ 0x1A000000,
+ 0x1FBFFFFF,
+ IORESOURCE_MEM,
+ &pci_mem_resource_0,
+ NULL,
+ NULL
+};
+
+extern struct pci_ops it8172_pci_ops;
+
+struct pci_controller it8172_controller = {
+ .pci_ops = &it8172_pci_ops,
+ .io_resource = &pci_io_resource,
+ .mem_resource = &pci_mem_resource_0,
+};
+
+static int it8172_pcibios_config_access(unsigned char access_type,
+ struct pci_bus *bus,
+ unsigned int devfn, int where,
+ u32 * data)
+{
+ /*
+ * config cycles are on 4 byte boundary only
+ */
+
+ /* Setup address */
+ IT_WRITE(IT_CONFADDR, (bus->number << IT_BUSNUM_SHF) |
+ (devfn << IT_FUNCNUM_SHF) | (where & ~0x3));
+
+ if (access_type == PCI_ACCESS_WRITE) {
+ IT_WRITE(IT_CONFDATA, *data);
+ } else {
+ IT_READ(IT_CONFDATA, *data);
+ }
+
+ /*
+ * Revisit: check for master or target abort.
+ */
+ return 0;
+}
+
+
+/*
+ * We can't address 8 and 16 bit words directly. Instead we have to
+ * read/write a 32bit word and mask/modify the data we actually want.
+ */
+static write_config(struct pci_bus *bus, unsigned int devfn, int where,
+ int size, u32 val)
+{
+ u32 data = 0;
+
+ switch (size) {
+ case 1:
+ if (it8172_pcibios_config_access
+ (PCI_ACCESS_READ, dev, where, &data))
+ return -1;
+
+ *val = (data >> ((where & 3) << 3)) & 0xff;
+
+ return PCIBIOS_SUCCESSFUL;
+
+ case 2:
+
+ if (where & 1)
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+
+ if (it8172_pcibios_config_access
+ (PCI_ACCESS_READ, dev, where, &data))
+ return -1;
+
+ *val = (data >> ((where & 3) << 3)) & 0xffff;
+ DBG("cfg read word: bus %d dev_fn %x where %x: val %x\n",
+ dev->bus->number, dev->devfn, where, *val);
+
+ return PCIBIOS_SUCCESSFUL;
+
+ case 4:
+
+ if (where & 3)
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+
+ if (it8172_pcibios_config_access
+ (PCI_ACCESS_READ, dev, where, &data))
+ return -1;
+
+ *val = data;
+
+ return PCIBIOS_SUCCESSFUL;
+ }
+}
+
+
+static write_config(struct pci_bus *bus, unsigned int devfn, int where,
+ int size, u32 val)
+{
+ u32 data = 0;
+
+ switch (size) {
+ case 1:
+ if (it8172_pcibios_config_access
+ (PCI_ACCESS_READ, dev, where, &data))
+ return -1;
+
+ data = (data & ~(0xff << ((where & 3) << 3))) |
+ (val << ((where & 3) << 3));
+
+ if (it8172_pcibios_config_access
+ (PCI_ACCESS_WRITE, dev, where, &data))
+ return -1;
+
+ return PCIBIOS_SUCCESSFUL;
+
+ case 2:
+ if (where & 1)
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+
+ if (it8172_pcibios_config_access
+ (PCI_ACCESS_READ, dev, where, &data))
+ eturn - 1;
+
+ data = (data & ~(0xffff << ((where & 3) << 3))) |
+ (val << ((where & 3) << 3));
+
+ if (it8172_pcibios_config_access
+ (PCI_ACCESS_WRITE, dev, where, &data))
+ return -1;
+
+ return PCIBIOS_SUCCESSFUL;
+
+ case 4:
+ if (where & 3)
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+
+ if (it8172_pcibios_config_access
+ (PCI_ACCESS_WRITE, dev, where, &val))
+ return -1;
+
+ return PCIBIOS_SUCCESSFUL;
+ }
+}
+
+struct pci_ops it8172_pci_ops = {
+ .read = read_config,
+ .write = write_config,
+};
diff --git a/arch/mips/pci/ops-mace.c b/arch/mips/pci/ops-mace.c
new file mode 100644
index 0000000..8008e31
--- /dev/null
+++ b/arch/mips/pci/ops-mace.c
@@ -0,0 +1,91 @@
+/*
+ * 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) 2000, 2001 Keith M Wesolowski
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/types.h>
+#include <asm/pci.h>
+#include <asm/ip32/mace.h>
+
+#if 0
+# define DPRINTK(args...) printk(args);
+#else
+# define DPRINTK(args...)
+#endif
+
+/*
+ * O2 has up to 5 PCI devices connected into the MACE bridge. The device
+ * map looks like this:
+ *
+ * 0 aic7xxx 0
+ * 1 aic7xxx 1
+ * 2 expansion slot
+ * 3 N/C
+ * 4 N/C
+ */
+
+#define chkslot(_bus,_devfn) \
+do { \
+ if ((_bus)->number > 0 || PCI_SLOT (_devfn) < 1 \
+ || PCI_SLOT (_devfn) > 3) \
+ return PCIBIOS_DEVICE_NOT_FOUND; \
+} while (0)
+
+#define mkaddr(_devfn, _reg) \
+((((_devfn) & 0xffUL) << 8) | ((_reg) & 0xfcUL))
+
+static int
+mace_pci_read_config(struct pci_bus *bus, unsigned int devfn,
+ int reg, int size, u32 *val)
+{
+ chkslot(bus, devfn);
+ mace->pci.config_addr = mkaddr(devfn, reg);
+ switch (size) {
+ case 1:
+ *val = mace->pci.config_data.b[(reg & 3) ^ 3];
+ break;
+ case 2:
+ *val = mace->pci.config_data.w[((reg >> 1) & 1) ^ 1];
+ break;
+ case 4:
+ *val = mace->pci.config_data.l;
+ break;
+ }
+
+ DPRINTK("read%d: reg=%08x,val=%02x\n", size * 8, reg, *val);
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int
+mace_pci_write_config(struct pci_bus *bus, unsigned int devfn,
+ int reg, int size, u32 val)
+{
+ chkslot(bus, devfn);
+ mace->pci.config_addr = mkaddr(devfn, reg);
+ switch (size) {
+ case 1:
+ mace->pci.config_data.b[(reg & 3) ^ 3] = val;
+ break;
+ case 2:
+ mace->pci.config_data.w[((reg >> 1) & 1) ^ 1] = val;
+ break;
+ case 4:
+ mace->pci.config_data.l = val;
+ break;
+ }
+
+ DPRINTK("write%d: reg=%08x,val=%02x\n", size * 8, reg, val);
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+struct pci_ops mace_pci_ops = {
+ .read = mace_pci_read_config,
+ .write = mace_pci_write_config,
+};
diff --git a/arch/mips/pci/ops-marvell.c b/arch/mips/pci/ops-marvell.c
new file mode 100644
index 0000000..1ac5c59
--- /dev/null
+++ b/arch/mips/pci/ops-marvell.c
@@ -0,0 +1,93 @@
+/*
+ * 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) 2003, 2004 Ralf Baechle (ralf@linux-mips.org)
+ */
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+
+#include <asm/marvell.h>
+
+static int mv_read_config(struct pci_bus *bus, unsigned int devfn,
+ int where, int size, u32 * val)
+{
+ struct mv_pci_controller *mvbc = bus->sysdata;
+ unsigned long address_reg, data_reg;
+ u32 address;
+
+ address_reg = mvbc->config_addr;
+ data_reg = mvbc->config_vreg;
+
+ /* Accessing device 31 crashes those Marvells. Since years.
+ Will they ever make sane controllers ... */
+ if (PCI_SLOT(devfn) == 31)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ address = (bus->number << 16) | (devfn << 8) |
+ (where & 0xfc) | 0x80000000;
+
+ /* start the configuration cycle */
+ MV_WRITE(address_reg, address);
+
+ switch (size) {
+ case 1:
+ *val = MV_READ_8(data_reg + (where & 0x3));
+ break;
+
+ case 2:
+ *val = MV_READ_16(data_reg + (where & 0x3));
+ break;
+
+ case 4:
+ *val = MV_READ(data_reg);
+ break;
+ }
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int mv_write_config(struct pci_bus *bus, unsigned int devfn,
+ int where, int size, u32 val)
+{
+ struct mv_pci_controller *mvbc = bus->sysdata;
+ unsigned long address_reg, data_reg;
+ u32 address;
+
+ address_reg = mvbc->config_addr;
+ data_reg = mvbc->config_vreg;
+
+ /* Accessing device 31 crashes those Marvells. Since years.
+ Will they ever make sane controllers ... */
+ if (PCI_SLOT(devfn) == 31)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ address = (bus->number << 16) | (devfn << 8) |
+ (where & 0xfc) | 0x80000000;
+
+ /* start the configuration cycle */
+ MV_WRITE(address_reg, address);
+
+ switch (size) {
+ case 1:
+ MV_WRITE_8(data_reg + (where & 0x3), val);
+ break;
+
+ case 2:
+ MV_WRITE_16(data_reg + (where & 0x3), val);
+ break;
+
+ case 4:
+ MV_WRITE(data_reg, val);
+ break;
+ }
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+struct pci_ops mv_pci_ops = {
+ .read = mv_read_config,
+ .write = mv_write_config
+};
diff --git a/arch/mips/pci/ops-msc.c b/arch/mips/pci/ops-msc.c
new file mode 100644
index 0000000..7bc0996
--- /dev/null
+++ b/arch/mips/pci/ops-msc.c
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 1999, 2000, 2004, 2005 MIPS Technologies, Inc.
+ * All rights reserved.
+ * Authors: Carsten Langgaard <carstenl@mips.com>
+ * Maciej W. Rozycki <macro@mips.com>
+ * Copyright (C) 2005 Ralf Baechle (ralf@linux-mips.org)
+ *
+ * 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.
+ *
+ * MIPS boards specific PCI support.
+ *
+ */
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/mips-boards/msc01_pci.h>
+
+#define PCI_ACCESS_READ 0
+#define PCI_ACCESS_WRITE 1
+
+/*
+ * PCI configuration cycle AD bus definition
+ */
+/* Type 0 */
+#define PCI_CFG_TYPE0_REG_SHF 0
+#define PCI_CFG_TYPE0_FUNC_SHF 8
+
+/* Type 1 */
+#define PCI_CFG_TYPE1_REG_SHF 0
+#define PCI_CFG_TYPE1_FUNC_SHF 8
+#define PCI_CFG_TYPE1_DEV_SHF 11
+#define PCI_CFG_TYPE1_BUS_SHF 16
+
+static int msc_pcibios_config_access(unsigned char access_type,
+ struct pci_bus *bus, unsigned int devfn, int where, u32 * data)
+{
+ unsigned char busnum = bus->number;
+ unsigned char type;
+ u32 intr;
+
+#ifdef CONFIG_MIPS_BOARDS_GEN
+ if ((busnum == 0) && (PCI_SLOT(devfn) == 17)) {
+ /* MIPS Core boards have SOCit connected as device 17 */
+ return -1;
+ }
+#endif
+
+ /* Clear status register bits. */
+ MSC_WRITE(MSC01_PCI_INTSTAT,
+ (MSC01_PCI_INTCFG_MA_BIT | MSC01_PCI_INTCFG_TA_BIT));
+
+ /* Setup address */
+ if (busnum == 0)
+ type = 0; /* Type 0 */
+ else
+ type = 1; /* Type 1 */
+
+ MSC_WRITE(MSC01_PCI_CFGADDR,
+ ((busnum << MSC01_PCI_CFGADDR_BNUM_SHF) |
+ (PCI_SLOT(devfn) << MSC01_PCI_CFGADDR_DNUM_SHF)
+ | (PCI_FUNC(devfn) <<
+ MSC01_PCI_CFGADDR_FNUM_SHF) | ((where /
+ 4) <<
+ MSC01_PCI_CFGADDR_RNUM_SHF)
+ | (type)));
+
+ /* Perform access */
+ if (access_type == PCI_ACCESS_WRITE)
+ MSC_WRITE(MSC01_PCI_CFGDATA, *data);
+ else
+ MSC_READ(MSC01_PCI_CFGDATA, *data);
+
+ /* Detect Master/Target abort */
+ MSC_READ(MSC01_PCI_INTSTAT, intr);
+ if (intr & (MSC01_PCI_INTCFG_MA_BIT |
+ MSC01_PCI_INTCFG_TA_BIT)) {
+ /* Error occurred */
+
+ /* Clear bits */
+ MSC_READ(MSC01_PCI_INTSTAT, intr);
+ MSC_WRITE(MSC01_PCI_INTSTAT,
+ (MSC01_PCI_INTCFG_MA_BIT |
+ MSC01_PCI_INTCFG_TA_BIT));
+
+ return -1;
+ }
+
+ return 0;
+}
+
+
+/*
+ * We can't address 8 and 16 bit words directly. Instead we have to
+ * read/write a 32bit word and mask/modify the data we actually want.
+ */
+static int msc_pcibios_read(struct pci_bus *bus, unsigned int devfn,
+ int where, int size, u32 * val)
+{
+ u32 data = 0;
+
+ if ((size == 2) && (where & 1))
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+ else if ((size == 4) && (where & 3))
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+
+ if (msc_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, where,
+ &data))
+ return -1;
+
+ if (size == 1)
+ *val = (data >> ((where & 3) << 3)) & 0xff;
+ else if (size == 2)
+ *val = (data >> ((where & 3) << 3)) & 0xffff;
+ else
+ *val = data;
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int msc_pcibios_write(struct pci_bus *bus, unsigned int devfn,
+ int where, int size, u32 val)
+{
+ u32 data = 0;
+
+ if ((size == 2) && (where & 1))
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+ else if ((size == 4) && (where & 3))
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+
+ if (size == 4)
+ data = val;
+ else {
+ if (msc_pcibios_config_access(PCI_ACCESS_READ, bus, devfn,
+ where, &data))
+ return -1;
+
+ if (size == 1)
+ data = (data & ~(0xff << ((where & 3) << 3))) |
+ (val << ((where & 3) << 3));
+ else if (size == 2)
+ data = (data & ~(0xffff << ((where & 3) << 3))) |
+ (val << ((where & 3) << 3));
+ }
+
+ if (msc_pcibios_config_access(PCI_ACCESS_WRITE, bus, devfn, where,
+ &data))
+ return -1;
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+struct pci_ops msc_pci_ops = {
+ .read = msc_pcibios_read,
+ .write = msc_pcibios_write
+};
diff --git a/arch/mips/pci/ops-nile4.c b/arch/mips/pci/ops-nile4.c
new file mode 100644
index 0000000..a716992
--- /dev/null
+++ b/arch/mips/pci/ops-nile4.c
@@ -0,0 +1,147 @@
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <asm/bootinfo.h>
+
+#include <asm/lasat/lasat.h>
+#include <asm/gt64120.h>
+#include <asm/nile4.h>
+
+#define PCI_ACCESS_READ 0
+#define PCI_ACCESS_WRITE 1
+
+#define LO(reg) (reg / 4)
+#define HI(reg) (reg / 4 + 1)
+
+volatile unsigned long *const vrc_pciregs = (void *) Vrc5074_BASE;
+
+static spinlock_t nile4_pci_lock;
+
+static int nile4_pcibios_config_access(unsigned char access_type,
+ struct pci_bus *bus, unsigned int devfn, int where, u32 * val)
+{
+ unsigned char busnum = bus->number;
+ u32 adr, mask, err;
+
+ if ((busnum == 0) && (PCI_SLOT(devfn) > 8))
+ /* The addressing scheme chosen leaves room for just
+ * 8 devices on the first busnum (besides the PCI
+ * controller itself) */
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ if ((busnum == 0) && (devfn == PCI_DEVFN(0, 0))) {
+ /* Access controller registers directly */
+ if (access_type == PCI_ACCESS_WRITE) {
+ vrc_pciregs[(0x200 + where) >> 2] = *val;
+ } else {
+ *val = vrc_pciregs[(0x200 + where) >> 2];
+ }
+ return PCIBIOS_SUCCESSFUL;
+ }
+
+ /* Temporarily map PCI Window 1 to config space */
+ mask = vrc_pciregs[LO(NILE4_PCIINIT1)];
+ vrc_pciregs[LO(NILE4_PCIINIT1)] = 0x0000001a | (busnum ? 0x200 : 0);
+
+ /* Clear PCI Error register. This also clears the Error Type
+ * bits in the Control register */
+ vrc_pciregs[LO(NILE4_PCIERR)] = 0;
+ vrc_pciregs[HI(NILE4_PCIERR)] = 0;
+
+ /* Setup address */
+ if (busnum == 0)
+ adr =
+ KSEG1ADDR(PCI_WINDOW1) +
+ ((1 << (PCI_SLOT(devfn) + 15)) | (PCI_FUNC(devfn) << 8)
+ | (where & ~3));
+ else
+ adr = KSEG1ADDR(PCI_WINDOW1) | (busnum << 16) | (devfn << 8) |
+ (where & ~3);
+
+ if (access_type == PCI_ACCESS_WRITE)
+ *(u32 *) adr = *val;
+ else
+ *val = *(u32 *) adr;
+
+ /* Check for master or target abort */
+ err = (vrc_pciregs[HI(NILE4_PCICTRL)] >> 5) & 0x7;
+
+ /* Restore PCI Window 1 */
+ vrc_pciregs[LO(NILE4_PCIINIT1)] = mask;
+
+ if (err)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int nile4_pcibios_read(struct pci_bus *bus, unsigned int devfn,
+ int where, int size, u32 * val)
+{
+ unsigned long flags;
+ u32 data = 0;
+ int err;
+
+ if ((size == 2) && (where & 1))
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+ else if ((size == 4) && (where & 3))
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+
+ spin_lock_irqsave(&nile4_pci_lock, flags);
+ err = nile4_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, where,
+ &data);
+ spin_unlock_irqrestore(&nile4_pci_lock, flags);
+
+ if (err)
+ return err;
+
+ if (size == 1)
+ *val = (data >> ((where & 3) << 3)) & 0xff;
+ else if (size == 2)
+ *val = (data >> ((where & 3) << 3)) & 0xffff;
+ else
+ *val = data;
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int nile4_pcibios_write(struct pci_bus *bus, unsigned int devfn,
+ int where, int size, u32 val)
+{
+ unsigned long flags;
+ u32 data = 0;
+ int err;
+
+ if ((size == 2) && (where & 1))
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+ else if ((size == 4) && (where & 3))
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+
+ spin_lock_irqsave(&nile4_pci_lock, flags);
+ err = nile4_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, where,
+ &data);
+ spin_unlock_irqrestore(&nile4_pci_lock, flags);
+
+ if (err)
+ return err;
+
+ if (size == 1)
+ data = (data & ~(0xff << ((where & 3) << 3))) |
+ (val << ((where & 3) << 3));
+ else if (size == 2)
+ data = (data & ~(0xffff << ((where & 3) << 3))) |
+ (val << ((where & 3) << 3));
+ else
+ data = val;
+
+ if (nile4_pcibios_config_access
+ (PCI_ACCESS_WRITE, bus, devfn, where, &data))
+ return -1;
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+struct pci_ops nile4_pci_ops = {
+ .read = nile4_pcibios_read,
+ .write = nile4_pcibios_write,
+};
diff --git a/arch/mips/pci/ops-sni.c b/arch/mips/pci/ops-sni.c
new file mode 100644
index 0000000..62bdd19
--- /dev/null
+++ b/arch/mips/pci/ops-sni.c
@@ -0,0 +1,89 @@
+/*
+ * 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.
+ *
+ * SNI specific PCI support for RM200/RM300.
+ *
+ * Copyright (C) 1997 - 2000, 2003 Ralf Baechle <ralf@linux-mips.org>
+ */
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/types.h>
+#include <asm/sni.h>
+
+/*
+ * It seems that on the RM200 only lower 3 bits of the 5 bit PCI device
+ * address are decoded. We therefore manually have to reject attempts at
+ * reading outside this range. Being on the paranoid side we only do this
+ * test for bus 0 and hope forwarding and decoding work properly for any
+ * subordinated busses.
+ *
+ * ASIC PCI only supports type 1 config cycles.
+ */
+static int set_config_address(unsigned int busno, unsigned int devfn, int reg)
+{
+ if ((devfn > 255) || (reg > 255))
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+
+ if (busno == 0 && devfn >= PCI_DEVFN(8, 0))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ *(volatile u32 *)PCIMT_CONFIG_ADDRESS =
+ ((busno & 0xff) << 16) |
+ ((devfn & 0xff) << 8) |
+ (reg & 0xfc);
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int pcimt_read(struct pci_bus *bus, unsigned int devfn, int reg,
+ int size, u32 * val)
+{
+ int res;
+
+ if ((res = set_config_address(bus->number, devfn, reg)))
+ return res;
+
+ switch (size) {
+ case 1:
+ *val = *(volatile u8 *) (PCIMT_CONFIG_DATA + (reg & 3));
+ break;
+ case 2:
+ *val = *(volatile u16 *) (PCIMT_CONFIG_DATA + (reg & 2));
+ break;
+ case 4:
+ *val = *(volatile u32 *) PCIMT_CONFIG_DATA;
+ break;
+ }
+
+ return 0;
+}
+
+static int pcimt_write(struct pci_bus *bus, unsigned int devfn, int reg,
+ int size, u32 val)
+{
+ int res;
+
+ if ((res = set_config_address(bus->number, devfn, reg)))
+ return res;
+
+ switch (size) {
+ case 1:
+ *(volatile u8 *) (PCIMT_CONFIG_DATA + (reg & 3)) = val;
+ break;
+ case 2:
+ *(volatile u16 *) (PCIMT_CONFIG_DATA + (reg & 2)) = val;
+ break;
+ case 4:
+ *(volatile u32 *) PCIMT_CONFIG_DATA = val;
+ break;
+ }
+
+ return 0;
+}
+
+struct pci_ops sni_pci_ops = {
+ .read = pcimt_read,
+ .write = pcimt_write,
+};
diff --git a/arch/mips/pci/ops-titan-ht.c b/arch/mips/pci/ops-titan-ht.c
new file mode 100644
index 0000000..46c636c
--- /dev/null
+++ b/arch/mips/pci/ops-titan-ht.c
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2003 PMC-Sierra
+ * Author: Manish Lachwani (lachwani@pmc-sierra.com)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <asm/io.h>
+
+#include <asm/titan_dep.h>
+
+static int titan_ht_config_read_dword(struct pci_bus *bus, unsigned int devfn,
+ int offset, u32 * val)
+{
+ volatile uint32_t address;
+ int busno;
+
+ busno = bus->number;
+
+ address = (busno << 16) | (devfn << 8) | (offset & 0xfc) | 0x80000000;
+ if (busno != 0)
+ address |= 1;
+
+ /*
+ * RM9000 HT Errata: Issue back to back HT config
+ * transcations. Issue a BIU sync before and
+ * after the HT cycle
+ */
+
+ *(volatile int32_t *) 0xfb0000f0 |= 0x2;
+
+ udelay(30);
+
+ *(volatile int32_t *) 0xfb0006f8 = address;
+ *(val) = *(volatile int32_t *) 0xfb0006fc;
+
+ udelay(30);
+
+ * (volatile int32_t *) 0xfb0000f0 |= 0x2;
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int titan_ht_config_read(struct pci_bus *bus, unsigned int devfn,
+ int offset, int size, u32 * val)
+{
+ uint32_t dword;
+
+ titan_ht_config_read_dword(bus, devfn, offset, &dword);
+
+ dword >>= ((offset & 3) << 3);
+ dword &= (0xffffffffU >> ((4 - size) << 8));
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static inline int titan_ht_config_write_dword(struct pci_bus *bus,
+ unsigned int devfn, int offset, u32 val)
+{
+ volatile uint32_t address;
+ int busno;
+
+ busno = bus->number;
+
+ address = (busno << 16) | (devfn << 8) | (offset & 0xfc) | 0x80000000;
+ if (busno != 0)
+ address |= 1;
+
+ *(volatile int32_t *) 0xfb0000f0 |= 0x2;
+
+ udelay(30);
+
+ *(volatile int32_t *) 0xfb0006f8 = address;
+ *(volatile int32_t *) 0xfb0006fc = val;
+
+ udelay(30);
+
+ *(volatile int32_t *) 0xfb0000f0 |= 0x2;
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int titan_ht_config_write(struct pci_bus *bus, unsigned int devfn,
+ int offset, int size, u32 val)
+{
+ uint32_t val1, val2, mask;
+
+ titan_ht_config_read_dword(bus, devfn, offset, &val2);
+
+ val1 = val << ((offset & 3) << 3);
+ mask = ~(0xffffffffU >> ((4 - size) << 8));
+ val2 &= ~(mask << ((offset & 3) << 8));
+
+ titan_ht_config_write_dword(bus, devfn, offset, val1 | val2);
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+struct pci_ops titan_ht_pci_ops = {
+ .read = titan_ht_config_read,
+ .write = titan_ht_config_write,
+};
diff --git a/arch/mips/pci/ops-titan.c b/arch/mips/pci/ops-titan.c
new file mode 100644
index 0000000..233ec6f
--- /dev/null
+++ b/arch/mips/pci/ops-titan.c
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2003 PMC-Sierra
+ * Author: Manish Lachwani (lachwani@pmc-sierra.com)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+
+#include <asm/titan_dep.h>
+
+static int titan_read_config(struct pci_bus *bus, unsigned int devfn, int reg,
+ int size, u32 * val)
+{
+ uint32_t address, tmp;
+ int dev, busno, func;
+
+ busno = bus->number;
+ dev = PCI_SLOT(devfn);
+ func = PCI_FUNC(devfn);
+
+ address = (busno << 16) | (dev << 11) | (func << 8) |
+ (reg & 0xfc) | 0x80000000;
+
+
+ /* start the configuration cycle */
+ TITAN_WRITE(TITAN_PCI_0_CONFIG_ADDRESS, address);
+ tmp = TITAN_READ(TITAN_PCI_0_CONFIG_DATA) >> ((reg & 3) << 3);
+
+ switch (size) {
+ case 1:
+ tmp &= 0xff;
+ case 2:
+ tmp &= 0xffff;
+ }
+ *val = tmp;
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int titan_write_config(struct pci_bus *bus, unsigned int devfn, int reg,
+ int size, u32 val)
+{
+ uint32_t address;
+ int dev, busno, func;
+
+ busno = bus->number;
+ dev = PCI_SLOT(devfn);
+ func = PCI_FUNC(devfn);
+
+ address = (busno << 16) | (dev << 11) | (func << 8) |
+ (reg & 0xfc) | 0x80000000;
+
+ /* start the configuration cycle */
+ TITAN_WRITE(TITAN_PCI_0_CONFIG_ADDRESS, address);
+
+ /* write the data */
+ switch (size) {
+ case 1:
+ TITAN_WRITE_8(TITAN_PCI_0_CONFIG_DATA + (~reg & 0x3), val);
+ break;
+
+ case 2:
+ TITAN_WRITE_16(TITAN_PCI_0_CONFIG_DATA + (~reg & 0x2), val);
+ break;
+
+ case 4:
+ TITAN_WRITE(TITAN_PCI_0_CONFIG_DATA, val);
+ break;
+ }
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+/*
+ * Titan PCI structure
+ */
+struct pci_ops titan_pci_ops = {
+ titan_read_config,
+ titan_write_config,
+};
diff --git a/arch/mips/pci/ops-tx3927.c b/arch/mips/pci/ops-tx3927.c
new file mode 100644
index 0000000..0e0daad
--- /dev/null
+++ b/arch/mips/pci/ops-tx3927.c
@@ -0,0 +1,391 @@
+/*
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ * ahennessy@mvista.com
+ *
+ * Copyright (C) 2000-2001 Toshiba Corporation
+ * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org)
+ *
+ * Based on arch/mips/ddb5xxx/ddb5477/pci_ops.c
+ *
+ * Define the pci_ops for JMR3927.
+ *
+ * Much of the code is derived from the original DDB5074 port by
+ * Geert Uytterhoeven <geert@sonycom.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/addrspace.h>
+#include <asm/jmr3927/jmr3927.h>
+#include <asm/debug.h>
+
+static inline int mkaddr(unsigned char bus, unsigned char dev_fn,
+ unsigned char where)
+{
+ if (bus == 0 && dev_fn >= PCI_DEVFN(TX3927_PCIC_MAX_DEVNU, 0))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ tx3927_pcicptr->ica = ((bus & 0xff) << 0x10) |
+ ((dev_fn & 0xff) << 0x08) |
+ (where & 0xfc);
+
+ /* clear M_ABORT and Disable M_ABORT Int. */
+ tx3927_pcicptr->pcistat |= PCI_STATUS_REC_MASTER_ABORT;
+ tx3927_pcicptr->pcistatim &= ~PCI_STATUS_REC_MASTER_ABORT;
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static inline int check_abort(void)
+{
+ if (tx3927_pcicptr->pcistat & PCI_STATUS_REC_MASTER_ABORT)
+ tx3927_pcicptr->pcistat |= PCI_STATUS_REC_MASTER_ABORT;
+ tx3927_pcicptr->pcistatim |= PCI_STATUS_REC_MASTER_ABORT;
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int jmr3927_pci_read_config(struct pci_bus *bus, unsigned int devfn,
+ int where, int size, u32 * val)
+{
+ int ret, busno;
+
+ /* check if the bus is top-level */
+ if (bus->parent != NULL)
+ busno = bus->number;
+
+ ret = mkaddr(busno, devfn, where);
+ if (ret)
+ return ret;
+
+ switch (size) {
+ case 1:
+ *val = *(volatile u8 *) ((unsigned long) & tx3927_pcicptr->icd | (where & 3));
+ break;
+
+ case 2:
+ *val = le16_to_cpu(*(volatile u16 *) ((unsigned long) & tx3927_pcicptr->icd | (where & 3)));
+ break;
+
+ case 4:
+ *val = le32_to_cpu(tx3927_pcicptr->icd);
+ break;
+ }
+
+ return check_abort();
+}
+
+static int jmr3927_pci_write_config(struct pci_bus *bus, unsigned int devfn,
+ int where, int size, u32 val)
+{
+ int ret, busno;
+
+ /* check if the bus is top-level */
+ if (bus->parent != NULL)
+ bus = bus->number;
+ else
+ bus = 0;
+
+ ret = mkaddr(busno, devfn, where);
+ if (ret)
+ return ret;
+
+ switch (size) {
+ case 1:
+ *(volatile u8 *) ((unsigned long) & tx3927_pcicptr->icd | (where & 3)) = val;
+ break;
+
+ case 2:
+ *(volatile u16 *) (unsigned longulong) & tx3927_pcicptr->icd | (where & 2)) =
+ cpu_to_le16(val);
+ break;
+
+ case 4:
+ tx3927_pcicptr->icd = cpu_to_le32(val);
+ }
+
+ if (tx3927_pcicptr->pcistat & PCI_STATUS_REC_MASTER_ABORT)
+ tx3927_pcicptr->pcistat |= PCI_STATUS_REC_MASTER_ABORT;
+ tx3927_pcicptr->pcistatim |= PCI_STATUS_REC_MASTER_ABORT;
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ return check_abort();
+}
+
+struct pci_ops jmr3927_pci_ops = {
+ jmr3927_pcibios_read_config,
+ jmr3927_pcibios_write_config,
+};
+
+
+#ifndef JMR3927_INIT_INDIRECT_PCI
+
+inline unsigned long tc_readl(volatile __u32 * addr)
+{
+ return readl(addr);
+}
+
+inline void tc_writel(unsigned long data, volatile __u32 * addr)
+{
+ writel(data, addr);
+}
+#else
+
+unsigned long tc_readl(volatile __u32 * addr)
+{
+ unsigned long val;
+
+ addr = PHYSADDR(addr);
+ *(volatile u32 *) (ulong) & tx3927_pcicptr->ipciaddr =
+ (unsigned long) addr;
+ *(volatile u32 *) (ulong) & tx3927_pcicptr->ipcibe =
+ (PCI_IPCIBE_ICMD_MEMREAD << PCI_IPCIBE_ICMD_SHIFT) |
+ PCI_IPCIBE_IBE_LONG;
+ while (!(tx3927_pcicptr->istat & PCI_ISTAT_IDICC));
+ val =
+ le32_to_cpu(*(volatile u32 *) (ulong) & tx3927_pcicptr->
+ ipcidata);
+ /* clear by setting */
+ tx3927_pcicptr->istat |= PCI_ISTAT_IDICC;
+ return val;
+}
+
+void tc_writel(unsigned long data, volatile __u32 * addr)
+{
+ addr = PHYSADDR(addr);
+ *(volatile u32 *) (ulong) & tx3927_pcicptr->ipcidata =
+ cpu_to_le32(data);
+ *(volatile u32 *) (ulong) & tx3927_pcicptr->ipciaddr =
+ (unsigned long) addr;
+ *(volatile u32 *) (ulong) & tx3927_pcicptr->ipcibe =
+ (PCI_IPCIBE_ICMD_MEMWRITE << PCI_IPCIBE_ICMD_SHIFT) |
+ PCI_IPCIBE_IBE_LONG;
+ while (!(tx3927_pcicptr->istat & PCI_ISTAT_IDICC));
+ /* clear by setting */
+ tx3927_pcicptr->istat |= PCI_ISTAT_IDICC;
+}
+
+unsigned char tx_ioinb(unsigned char *addr)
+{
+ unsigned long val;
+ __u32 ioaddr;
+ int offset;
+ int byte;
+
+ ioaddr = (unsigned long) addr;
+ offset = ioaddr & 0x3;
+ if (offset == 0)
+ byte = 0x7;
+ else if (offset == 1)
+ byte = 0xb;
+ else if (offset == 2)
+ byte = 0xd;
+ else if (offset == 3)
+ byte = 0xe;
+ *(volatile u32 *) (ulong) & tx3927_pcicptr->ipciaddr =
+ (unsigned long) ioaddr;
+ *(volatile u32 *) (ulong) & tx3927_pcicptr->ipcibe =
+ (PCI_IPCIBE_ICMD_IOREAD << PCI_IPCIBE_ICMD_SHIFT) | byte;
+ while (!(tx3927_pcicptr->istat & PCI_ISTAT_IDICC));
+ val =
+ le32_to_cpu(*(volatile u32 *) (ulong) & tx3927_pcicptr->
+ ipcidata);
+ val = val & 0xff;
+ /* clear by setting */
+ tx3927_pcicptr->istat |= PCI_ISTAT_IDICC;
+ return val;
+}
+
+void tx_iooutb(unsigned long data, unsigned char *addr)
+{
+ __u32 ioaddr;
+ int offset;
+ int byte;
+
+ data = data | (data << 8) | (data << 16) | (data << 24);
+ ioaddr = (unsigned long) addr;
+ offset = ioaddr & 0x3;
+ if (offset == 0)
+ byte = 0x7;
+ else if (offset == 1)
+ byte = 0xb;
+ else if (offset == 2)
+ byte = 0xd;
+ else if (offset == 3)
+ byte = 0xe;
+ *(volatile u32 *) (ulong) & tx3927_pcicptr->ipcidata = data;
+ *(volatile u32 *) (ulong) & tx3927_pcicptr->ipciaddr =
+ (unsigned long) ioaddr;
+ *(volatile u32 *) (ulong) & tx3927_pcicptr->ipcibe =
+ (PCI_IPCIBE_ICMD_IOWRITE << PCI_IPCIBE_ICMD_SHIFT) | byte;
+ while (!(tx3927_pcicptr->istat & PCI_ISTAT_IDICC));
+ /* clear by setting */
+ tx3927_pcicptr->istat |= PCI_ISTAT_IDICC;
+}
+
+unsigned short tx_ioinw(unsigned short *addr)
+{
+ unsigned long val;
+ __u32 ioaddr;
+ int offset;
+ int byte;
+
+ ioaddr = (unsigned long) addr;
+ offset = ioaddr & 0x3;
+ if (offset == 0)
+ byte = 0x3;
+ else if (offset == 2)
+ byte = 0xc;
+ *(volatile u32 *) (ulong) & tx3927_pcicptr->ipciaddr =
+ (unsigned long) ioaddr;
+ *(volatile u32 *) (ulong) & tx3927_pcicptr->ipcibe =
+ (PCI_IPCIBE_ICMD_IOREAD << PCI_IPCIBE_ICMD_SHIFT) | byte;
+ while (!(tx3927_pcicptr->istat & PCI_ISTAT_IDICC));
+ val =
+ le32_to_cpu(*(volatile u32 *) (ulong) & tx3927_pcicptr->
+ ipcidata);
+ val = val & 0xffff;
+ /* clear by setting */
+ tx3927_pcicptr->istat |= PCI_ISTAT_IDICC;
+ return val;
+
+}
+
+void tx_iooutw(unsigned long data, unsigned short *addr)
+{
+ __u32 ioaddr;
+ int offset;
+ int byte;
+
+ data = data | (data << 16);
+ ioaddr = (unsigned long) addr;
+ offset = ioaddr & 0x3;
+ if (offset == 0)
+ byte = 0x3;
+ else if (offset == 2)
+ byte = 0xc;
+ *(volatile u32 *) (ulong) & tx3927_pcicptr->ipcidata = data;
+ *(volatile u32 *) (ulong) & tx3927_pcicptr->ipciaddr =
+ (unsigned long) ioaddr;
+ *(volatile u32 *) (ulong) & tx3927_pcicptr->ipcibe =
+ (PCI_IPCIBE_ICMD_IOWRITE << PCI_IPCIBE_ICMD_SHIFT) | byte;
+ while (!(tx3927_pcicptr->istat & PCI_ISTAT_IDICC));
+ /* clear by setting */
+ tx3927_pcicptr->istat |= PCI_ISTAT_IDICC;
+}
+
+unsigned long tx_ioinl(unsigned int *addr)
+{
+ unsigned long val;
+ __u32 ioaddr;
+
+ ioaddr = (unsigned long) addr;
+ *(volatile u32 *) (ulong) & tx3927_pcicptr->ipciaddr =
+ (unsigned long) ioaddr;
+ *(volatile u32 *) (ulong) & tx3927_pcicptr->ipcibe =
+ (PCI_IPCIBE_ICMD_IOREAD << PCI_IPCIBE_ICMD_SHIFT) |
+ PCI_IPCIBE_IBE_LONG;
+ while (!(tx3927_pcicptr->istat & PCI_ISTAT_IDICC));
+ val =
+ le32_to_cpu(*(volatile u32 *) (ulong) & tx3927_pcicptr->
+ ipcidata);
+ /* clear by setting */
+ tx3927_pcicptr->istat |= PCI_ISTAT_IDICC;
+ return val;
+}
+
+void tx_iooutl(unsigned long data, unsigned int *addr)
+{
+ __u32 ioaddr;
+
+ ioaddr = (unsigned long) addr;
+ *(volatile u32 *) (ulong) & tx3927_pcicptr->ipcidata =
+ cpu_to_le32(data);
+ *(volatile u32 *) (ulong) & tx3927_pcicptr->ipciaddr =
+ (unsigned long) ioaddr;
+ *(volatile u32 *) (ulong) & tx3927_pcicptr->ipcibe =
+ (PCI_IPCIBE_ICMD_IOWRITE << PCI_IPCIBE_ICMD_SHIFT) |
+ PCI_IPCIBE_IBE_LONG;
+ while (!(tx3927_pcicptr->istat & PCI_ISTAT_IDICC));
+ /* clear by setting */
+ tx3927_pcicptr->istat |= PCI_ISTAT_IDICC;
+}
+
+void tx_insbyte(unsigned char *addr, void *buffer, unsigned int count)
+{
+ unsigned char *ptr = (unsigned char *) buffer;
+
+ while (count--) {
+ *ptr++ = tx_ioinb(addr);
+ }
+}
+
+void tx_insword(unsigned short *addr, void *buffer, unsigned int count)
+{
+ unsigned short *ptr = (unsigned short *) buffer;
+
+ while (count--) {
+ *ptr++ = tx_ioinw(addr);
+ }
+}
+
+void tx_inslong(unsigned int *addr, void *buffer, unsigned int count)
+{
+ unsigned long *ptr = (unsigned long *) buffer;
+
+ while (count--) {
+ *ptr++ = tx_ioinl(addr);
+ }
+}
+
+void tx_outsbyte(unsigned char *addr, void *buffer, unsigned int count)
+{
+ unsigned char *ptr = (unsigned char *) buffer;
+
+ while (count--) {
+ tx_iooutb(*ptr++, addr);
+ }
+}
+
+void tx_outsword(unsigned short *addr, void *buffer, unsigned int count)
+{
+ unsigned short *ptr = (unsigned short *) buffer;
+
+ while (count--) {
+ tx_iooutw(*ptr++, addr);
+ }
+}
+
+void tx_outslong(unsigned int *addr, void *buffer, unsigned int count)
+{
+ unsigned long *ptr = (unsigned long *) buffer;
+
+ while (count--) {
+ tx_iooutl(*ptr++, addr);
+ }
+}
+#endif
diff --git a/arch/mips/pci/ops-tx4927.c b/arch/mips/pci/ops-tx4927.c
new file mode 100644
index 0000000..2a9d722
--- /dev/null
+++ b/arch/mips/pci/ops-tx4927.c
@@ -0,0 +1,209 @@
+/*
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ * ahennessy@mvista.com
+ *
+ * Copyright (C) 2000-2001 Toshiba Corporation
+ * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org)
+ *
+ * Based on arch/mips/ddb5xxx/ddb5477/pci_ops.c
+ *
+ * Define the pci_ops for the Toshiba rbtx4927
+ *
+ * Much of the code is derived from the original DDB5074 port by
+ * Geert Uytterhoeven <geert@sonycom.com>
+ *
+ * Copyright 2004 MontaVista Software Inc.
+ * Author: Manish Lachwani (mlachwani@mvista.com)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/addrspace.h>
+#include <asm/byteorder.h>
+#include <asm/tx4927/tx4927_pci.h>
+
+/* initialize in setup */
+struct resource pci_io_resource = {
+ .name = "TX4927 PCI IO SPACE",
+ .start = 0x1000,
+ .end = (0x1000 + (TX4927_PCIIO_SIZE)) - 1,
+ .flags = IORESOURCE_IO
+};
+
+/* initialize in setup */
+struct resource pci_mem_resource = {
+ .name = "TX4927 PCI MEM SPACE",
+ .start = TX4927_PCIMEM,
+ .end = TX4927_PCIMEM + TX4927_PCIMEM_SIZE - 1,
+ .flags = IORESOURCE_MEM
+};
+
+static int mkaddr(int bus, int dev_fn, int where, int *flagsp)
+{
+ if (bus > 0) {
+ /* Type 1 configuration */
+ tx4927_pcicptr->g2pcfgadrs = ((bus & 0xff) << 0x10) |
+ ((dev_fn & 0xff) << 0x08) | (where & 0xfc) | 1;
+ } else {
+ if (dev_fn >= PCI_DEVFN(TX4927_PCIC_MAX_DEVNU, 0))
+ return -1;
+
+ /* Type 0 configuration */
+ tx4927_pcicptr->g2pcfgadrs = ((bus & 0xff) << 0x10) |
+ ((dev_fn & 0xff) << 0x08) | (where & 0xfc);
+ }
+ /* clear M_ABORT and Disable M_ABORT Int. */
+ tx4927_pcicptr->pcistatus =
+ (tx4927_pcicptr->pcistatus & 0x0000ffff) |
+ (PCI_STATUS_REC_MASTER_ABORT << 16);
+ tx4927_pcicptr->pcimask &= ~PCI_STATUS_REC_MASTER_ABORT;
+ return 0;
+}
+
+static int check_abort(int flags)
+{
+ int code = PCIBIOS_SUCCESSFUL;
+ if (tx4927_pcicptr->
+ pcistatus & (PCI_STATUS_REC_MASTER_ABORT << 16)) {
+ tx4927_pcicptr->pcistatus =
+ (tx4927_pcicptr->
+ pcistatus & 0x0000ffff) | (PCI_STATUS_REC_MASTER_ABORT
+ << 16);
+ tx4927_pcicptr->pcimask |= PCI_STATUS_REC_MASTER_ABORT;
+ code = PCIBIOS_DEVICE_NOT_FOUND;
+ }
+ return code;
+}
+
+static int tx4927_pcibios_read_config(struct pci_bus *bus, unsigned int devfn, int where,
+ int size, u32 * val)
+{
+ int flags, retval, dev, busno, func;
+
+ busno = bus->number;
+ dev = PCI_SLOT(devfn);
+ func = PCI_FUNC(devfn);
+
+ /* check if the bus is top-level */
+ if (bus->parent != NULL) {
+ busno = bus->number;
+ } else {
+ busno = 0;
+ }
+
+ if (mkaddr(busno, devfn, where, &flags))
+ return -1;
+
+ switch (size) {
+ case 1:
+ *val = *(volatile u8 *) ((ulong) & tx4927_pcicptr->
+ g2pcfgdata |
+#ifdef __LITTLE_ENDIAN
+ (where & 3));
+#else
+ ((where & 0x3) ^ 0x3));
+#endif
+ break;
+ case 2:
+ *val = *(volatile u16 *) ((ulong) & tx4927_pcicptr->
+ g2pcfgdata |
+#ifdef __LITTLE_ENDIAN
+ (where & 3));
+#else
+ ((where & 0x3) ^ 0x2));
+#endif
+ break;
+ case 4:
+ *val = tx4927_pcicptr->g2pcfgdata;
+ break;
+ }
+
+ retval = check_abort(flags);
+ if (retval == PCIBIOS_DEVICE_NOT_FOUND)
+ *val = 0xffffffff;
+
+ return retval;
+}
+
+static int tx4927_pcibios_write_config(struct pci_bus *bus, unsigned int devfn, int where,
+ int size, u32 val)
+{
+ int flags, dev, busno, func;
+ busno = bus->number;
+ dev = PCI_SLOT(devfn);
+ func = PCI_FUNC(devfn);
+
+ /* check if the bus is top-level */
+ if (bus->parent != NULL) {
+ busno = bus->number;
+ } else {
+ busno = 0;
+ }
+
+ if (mkaddr(busno, devfn, where, &flags))
+ return -1;
+
+ switch (size) {
+ case 1:
+ *(volatile u8 *) ((ulong) & tx4927_pcicptr->
+ g2pcfgdata |
+#ifdef __LITTLE_ENDIAN
+ (where & 3)) = val;
+#else
+ ((where & 0x3) ^ 0x3)) = val;
+#endif
+ break;
+
+ case 2:
+ *(volatile u16 *) ((ulong) & tx4927_pcicptr->
+ g2pcfgdata |
+#ifdef __LITTLE_ENDIAN
+ (where & 3)) = val;
+#else
+ ((where & 0x3) ^ 0x2)) = val;
+#endif
+ break;
+ case 4:
+ tx4927_pcicptr->g2pcfgdata = val;
+ break;
+ }
+
+ return check_abort(flags);
+}
+
+struct pci_ops tx4927_pci_ops = {
+ tx4927_pcibios_read_config,
+ tx4927_pcibios_write_config
+};
+
+/*
+ * h/w only supports devices 0x00 to 0x14
+ */
+struct pci_controller tx4927_controller = {
+ .pci_ops = &tx4927_pci_ops,
+ .io_resource = &pci_io_resource,
+ .mem_resource = &pci_mem_resource,
+};
diff --git a/arch/mips/pci/ops-vr41xx.c b/arch/mips/pci/ops-vr41xx.c
new file mode 100644
index 0000000..4465460
--- /dev/null
+++ b/arch/mips/pci/ops-vr41xx.c
@@ -0,0 +1,126 @@
+/*
+ * ops-vr41xx.c, PCI configuration routines for the PCIU of NEC VR4100 series.
+ *
+ * Copyright (C) 2001-2003 MontaVista Software Inc.
+ * Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com>
+ * Copyright (C) 2004 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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
+ */
+/*
+ * Changes:
+ * MontaVista Software Inc. <yyuasa@mvista.com> or <source@mvista.com>
+ * - New creation, NEC VR4122 and VR4131 are supported.
+ */
+#include <linux/pci.h>
+#include <linux/types.h>
+
+#include <asm/io.h>
+
+#define PCICONFDREG KSEG1ADDR(0x0f000c14)
+#define PCICONFAREG KSEG1ADDR(0x0f000c18)
+
+static inline int set_pci_configuration_address(unsigned char number,
+ unsigned int devfn, int where)
+{
+ if (number == 0) {
+ /*
+ * Type 0 configuration
+ */
+ if (PCI_SLOT(devfn) < 11 || where > 0xff)
+ return -EINVAL;
+
+ writel((1U << PCI_SLOT(devfn)) | (PCI_FUNC(devfn) << 8) |
+ (where & 0xfc), PCICONFAREG);
+ } else {
+ /*
+ * Type 1 configuration
+ */
+ if (where > 0xff)
+ return -EINVAL;
+
+ writel(((uint32_t)number << 16) | ((devfn & 0xff) << 8) |
+ (where & 0xfc) | 1U, PCICONFAREG);
+ }
+
+ return 0;
+}
+
+static int pci_config_read(struct pci_bus *bus, unsigned int devfn, int where,
+ int size, uint32_t *val)
+{
+ uint32_t data;
+
+ *val = 0xffffffffU;
+ if (set_pci_configuration_address(bus->number, devfn, where) < 0)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ data = readl(PCICONFDREG);
+
+ switch (size) {
+ case 1:
+ *val = (data >> ((where & 3) << 3)) & 0xffU;
+ break;
+ case 2:
+ *val = (data >> ((where & 2) << 3)) & 0xffffU;
+ break;
+ case 4:
+ *val = data;
+ break;
+ default:
+ return PCIBIOS_FUNC_NOT_SUPPORTED;
+ }
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int pci_config_write(struct pci_bus *bus, unsigned int devfn, int where,
+ int size, uint32_t val)
+{
+ uint32_t data;
+ int shift;
+
+ if (set_pci_configuration_address(bus->number, devfn, where) < 0)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ data = readl(PCICONFDREG);
+
+ switch (size) {
+ case 1:
+ shift = (where & 3) << 3;
+ data &= ~(0xffU << shift);
+ data |= ((val & 0xffU) << shift);
+ break;
+ case 2:
+ shift = (where & 2) << 3;
+ data &= ~(0xffffU << shift);
+ data |= ((val & 0xffffU) << shift);
+ break;
+ case 4:
+ data = val;
+ break;
+ default:
+ return PCIBIOS_FUNC_NOT_SUPPORTED;
+ }
+
+ writel(data, PCICONFDREG);
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+struct pci_ops vr41xx_pci_ops = {
+ .read = pci_config_read,
+ .write = pci_config_write,
+};
diff --git a/arch/mips/pci/pci-ddb5074.c b/arch/mips/pci/pci-ddb5074.c
new file mode 100644
index 0000000..73f9cee
--- /dev/null
+++ b/arch/mips/pci/pci-ddb5074.c
@@ -0,0 +1,79 @@
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+
+#include <asm/debug.h>
+
+#include <asm/ddb5xxx/ddb5xxx.h>
+
+static struct resource extpci_io_resource = {
+ "pci IO space",
+ 0x1000, /* leave some room for ISA bus */
+ DDB_PCI_IO_SIZE - 1,
+ IORESOURCE_IO
+};
+
+static struct resource extpci_mem_resource = {
+ "pci memory space",
+ DDB_PCI_MEM_BASE + 0x00100000, /* leave 1 MB for RTC */
+ DDB_PCI_MEM_BASE + DDB_PCI_MEM_SIZE - 1,
+ IORESOURCE_MEM
+};
+
+extern struct pci_ops ddb5476_ext_pci_ops;
+
+struct pci_controller ddb5476_controller = {
+ .pci_ops = &ddb5476_ext_pci_ops,
+ .io_resource = &extpci_io_resource,
+ .mem_resource = &extpci_mem_resource,
+};
+
+#define PCI_EXT_INTA 8
+#define PCI_EXT_INTB 9
+#define PCI_EXT_INTC 10
+#define PCI_EXT_INTD 11
+#define PCI_EXT_INTE 12
+
+#define MAX_SLOT_NUM 14
+
+static unsigned char irq_map[MAX_SLOT_NUM] = {
+ [ 0] = nile4_to_irq(PCI_EXT_INTE),
+ [ 1] = nile4_to_irq(PCI_EXT_INTA),
+ [ 2] = nile4_to_irq(PCI_EXT_INTA),
+ [ 3] = nile4_to_irq(PCI_EXT_INTB),
+ [ 4] = nile4_to_irq(PCI_EXT_INTC),
+ [ 5] = nile4_to_irq(NILE4_INT_UART),
+ [10] = nile4_to_irq(PCI_EXT_INTE),
+ [13] = nile4_to_irq(PCI_EXT_INTE),
+};
+
+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+ return irq_map[slot];
+}
+
+/* Do platform specific device initialization at pci_enable_device() time */
+int pcibios_plat_dev_init(struct pci_dev *dev)
+{
+ return 0;
+}
+
+void __init ddb_pci_reset_bus(void)
+{
+ u32 temp;
+
+ /*
+ * I am not sure about the "official" procedure, the following
+ * steps work as far as I know:
+ * We first set PCI cold reset bit (bit 31) in PCICTRL-H.
+ * Then we clear the PCI warm reset bit (bit 30) to 0 in PCICTRL-H.
+ * The same is true for both PCI channels.
+ */
+ temp = ddb_in32(DDB_PCICTRL + 4);
+ temp |= 0x80000000;
+ ddb_out32(DDB_PCICTRL + 4, temp);
+ temp &= ~0xc0000000;
+ ddb_out32(DDB_PCICTRL + 4, temp);
+
+}
diff --git a/arch/mips/pci/pci-ddb5476.c b/arch/mips/pci/pci-ddb5476.c
new file mode 100644
index 0000000..90dd495
--- /dev/null
+++ b/arch/mips/pci/pci-ddb5476.c
@@ -0,0 +1,93 @@
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+
+#include <asm/debug.h>
+
+#include <asm/ddb5xxx/ddb5xxx.h>
+
+static struct resource extpci_io_resource = {
+ "pci IO space",
+ 0x1000, /* leave some room for ISA bus */
+ DDB_PCI_IO_SIZE - 1,
+ IORESOURCE_IO
+};
+
+static struct resource extpci_mem_resource = {
+ "pci memory space",
+ DDB_PCI_MEM_BASE + 0x00100000, /* leave 1 MB for RTC */
+ DDB_PCI_MEM_BASE + DDB_PCI_MEM_SIZE - 1,
+ IORESOURCE_MEM
+};
+
+extern struct pci_ops ddb5476_ext_pci_ops;
+
+struct pci_controller ddb5476_controller = {
+ .pci_ops = &ddb5476_ext_pci_ops,
+ .io_resource = &extpci_io_resource,
+ .mem_resource = &extpci_mem_resource
+};
+
+
+/*
+ * we fix up irqs based on the slot number.
+ * The first entry is at AD:11.
+ *
+ * This does not work for devices on sub-buses yet.
+ */
+
+/*
+ * temporary
+ */
+
+#define PCI_EXT_INTA 8
+#define PCI_EXT_INTB 9
+#define PCI_EXT_INTC 10
+#define PCI_EXT_INTD 11
+#define PCI_EXT_INTE 12
+
+/*
+ * based on ddb5477 manual page 11
+ */
+#define MAX_SLOT_NUM 21
+static unsigned char irq_map[MAX_SLOT_NUM] = {
+ [ 2] = 9, /* AD:13 USB */
+ [ 3] = 10, /* AD:14 PMU */
+ [ 5] = 0, /* AD:16 P2P bridge */
+ [ 6] = nile4_to_irq(PCI_EXT_INTB), /* AD:17 */
+ [ 7] = nile4_to_irq(PCI_EXT_INTC), /* AD:18 */
+ [ 8] = nile4_to_irq(PCI_EXT_INTD), /* AD:19 */
+ [ 9] = nile4_to_irq(PCI_EXT_INTA), /* AD:20 */
+ [13] = 14, /* AD:24 HD controller, M5229 */
+};
+
+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+ return irq_map[slot];
+}
+
+/* Do platform specific device initialization at pci_enable_device() time */
+int pcibios_plat_dev_init(struct pci_dev *dev)
+{
+ return 0;
+}
+
+void __init ddb_pci_reset_bus(void)
+{
+ u32 temp;
+
+ /*
+ * I am not sure about the "official" procedure, the following
+ * steps work as far as I know:
+ * We first set PCI cold reset bit (bit 31) in PCICTRL-H.
+ * Then we clear the PCI warm reset bit (bit 30) to 0 in PCICTRL-H.
+ * The same is true for both PCI channels.
+ */
+ temp = ddb_in32(DDB_PCICTRL + 4);
+ temp |= 0x80000000;
+ ddb_out32(DDB_PCICTRL + 4, temp);
+ temp &= ~0xc0000000;
+ ddb_out32(DDB_PCICTRL + 4, temp);
+
+}
diff --git a/arch/mips/pci/pci-ddb5477.c b/arch/mips/pci/pci-ddb5477.c
new file mode 100644
index 0000000..4ddd53e
--- /dev/null
+++ b/arch/mips/pci/pci-ddb5477.c
@@ -0,0 +1,207 @@
+/*
+ * PCI code for DDB5477.
+ *
+ * Copyright (C) 2001 MontaVista Software Inc.
+ * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
+ *
+ * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+
+#include <asm/bootinfo.h>
+#include <asm/debug.h>
+
+#include <asm/ddb5xxx/ddb5xxx.h>
+
+static struct resource extpci_io_resource = {
+ "ext pci IO space",
+ DDB_PCI0_IO_BASE - DDB_PCI_IO_BASE + 0x4000,
+ DDB_PCI0_IO_BASE - DDB_PCI_IO_BASE + DDB_PCI0_IO_SIZE - 1,
+ IORESOURCE_IO
+};
+
+static struct resource extpci_mem_resource = {
+ "ext pci memory space",
+ DDB_PCI0_MEM_BASE + 0x100000,
+ DDB_PCI0_MEM_BASE + DDB_PCI0_MEM_SIZE - 1,
+ IORESOURCE_MEM
+};
+
+static struct resource iopci_io_resource = {
+ "io pci IO space",
+ DDB_PCI1_IO_BASE - DDB_PCI_IO_BASE,
+ DDB_PCI1_IO_BASE - DDB_PCI_IO_BASE + DDB_PCI1_IO_SIZE - 1,
+ IORESOURCE_IO
+};
+
+static struct resource iopci_mem_resource = {
+ "ext pci memory space",
+ DDB_PCI1_MEM_BASE,
+ DDB_PCI1_MEM_BASE + DDB_PCI1_MEM_SIZE - 1,
+ IORESOURCE_MEM
+};
+
+extern struct pci_ops ddb5477_ext_pci_ops;
+extern struct pci_ops ddb5477_io_pci_ops;
+
+struct pci_controller ddb5477_ext_controller = {
+ .pci_ops = &ddb5477_ext_pci_ops,
+ .io_resource = &extpci_io_resource,
+ .mem_resource = &extpci_mem_resource
+};
+
+struct pci_controller ddb5477_io_controller = {
+ .pci_ops = &ddb5477_io_pci_ops,
+ .io_resource = &iopci_io_resource,
+ .mem_resource = &iopci_mem_resource
+};
+
+
+
+/*
+ * we fix up irqs based on the slot number.
+ * The first entry is at AD:11.
+ * Fortunately this works because, although we have two pci buses,
+ * they all have different slot numbers (except for rockhopper slot 20
+ * which is handled below).
+ *
+ */
+
+/*
+ * irq mapping : device -> pci int # -> vrc4377 irq# ,
+ * ddb5477 board manual page 4 and vrc5477 manual page 46
+ */
+
+/*
+ * based on ddb5477 manual page 11
+ */
+#define MAX_SLOT_NUM 21
+static unsigned char irq_map[MAX_SLOT_NUM] = {
+ /* SLOT: 0, AD:11 */ 0xff,
+ /* SLOT: 1, AD:12 */ 0xff,
+ /* SLOT: 2, AD:13 */ 0xff,
+ /* SLOT: 3, AD:14 */ 0xff,
+ /* SLOT: 4, AD:15 */ VRC5477_IRQ_INTA, /* onboard tulip */
+ /* SLOT: 5, AD:16 */ VRC5477_IRQ_INTB, /* slot 1 */
+ /* SLOT: 6, AD:17 */ VRC5477_IRQ_INTC, /* slot 2 */
+ /* SLOT: 7, AD:18 */ VRC5477_IRQ_INTD, /* slot 3 */
+ /* SLOT: 8, AD:19 */ VRC5477_IRQ_INTE, /* slot 4 */
+ /* SLOT: 9, AD:20 */ 0xff,
+ /* SLOT: 10, AD:21 */ 0xff,
+ /* SLOT: 11, AD:22 */ 0xff,
+ /* SLOT: 12, AD:23 */ 0xff,
+ /* SLOT: 13, AD:24 */ 0xff,
+ /* SLOT: 14, AD:25 */ 0xff,
+ /* SLOT: 15, AD:26 */ 0xff,
+ /* SLOT: 16, AD:27 */ 0xff,
+ /* SLOT: 17, AD:28 */ 0xff,
+ /* SLOT: 18, AD:29 */ VRC5477_IRQ_IOPCI_INTC, /* vrc5477 ac97 */
+ /* SLOT: 19, AD:30 */ VRC5477_IRQ_IOPCI_INTB, /* vrc5477 usb peri */
+ /* SLOT: 20, AD:31 */ VRC5477_IRQ_IOPCI_INTA, /* vrc5477 usb host */
+};
+static unsigned char rockhopperII_irq_map[MAX_SLOT_NUM] = {
+ /* SLOT: 0, AD:11 */ 0xff,
+ /* SLOT: 1, AD:12 */ VRC5477_IRQ_INTB, /* onboard AMD PCNET */
+ /* SLOT: 2, AD:13 */ 0xff,
+ /* SLOT: 3, AD:14 */ 0xff,
+ /* SLOT: 4, AD:15 */ 14, /* M5229 ide ISA irq */
+ /* SLOT: 5, AD:16 */ VRC5477_IRQ_INTD, /* slot 3 */
+ /* SLOT: 6, AD:17 */ VRC5477_IRQ_INTA, /* slot 4 */
+ /* SLOT: 7, AD:18 */ VRC5477_IRQ_INTD, /* slot 5 */
+ /* SLOT: 8, AD:19 */ 0, /* M5457 modem nop */
+ /* SLOT: 9, AD:20 */ VRC5477_IRQ_INTA, /* slot 2 */
+ /* SLOT: 10, AD:21 */ 0xff,
+ /* SLOT: 11, AD:22 */ 0xff,
+ /* SLOT: 12, AD:23 */ 0xff,
+ /* SLOT: 13, AD:24 */ 0xff,
+ /* SLOT: 14, AD:25 */ 0xff,
+ /* SLOT: 15, AD:26 */ 0xff,
+ /* SLOT: 16, AD:27 */ 0xff,
+ /* SLOT: 17, AD:28 */ 0, /* M7101 PMU nop */
+ /* SLOT: 18, AD:29 */ VRC5477_IRQ_IOPCI_INTC, /* vrc5477 ac97 */
+ /* SLOT: 19, AD:30 */ VRC5477_IRQ_IOPCI_INTB, /* vrc5477 usb peri */
+ /* SLOT: 20, AD:31 */ VRC5477_IRQ_IOPCI_INTA, /* vrc5477 usb host */
+};
+
+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+ int slot_num;
+ unsigned char *slot_irq_map;
+ unsigned char irq;
+
+ /*
+ * We ignore the swizzled slot and pin values. The original
+ * pci_fixup_irq() codes largely base irq number on the dev slot
+ * numbers because except for one case they are unique even
+ * though there are multiple pci buses.
+ */
+
+ if (mips_machtype == MACH_NEC_ROCKHOPPERII)
+ slot_irq_map = rockhopperII_irq_map;
+ else
+ slot_irq_map = irq_map;
+
+ slot_num = PCI_SLOT(dev->devfn);
+ irq = slot_irq_map[slot_num];
+
+ db_assert(slot_num < MAX_SLOT_NUM);
+
+ db_assert(irq != 0xff);
+
+ pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
+
+ if (mips_machtype == MACH_NEC_ROCKHOPPERII) {
+ /* hack to distinquish overlapping slot 20s, one
+ * on bus 0 (ALI USB on the M1535 on the backplane),
+ * and one on bus 2 (NEC USB controller on the CPU board)
+ * Make the M1535 USB - ISA IRQ number 9.
+ */
+ if (slot_num == 20 && dev->bus->number == 0) {
+ pci_write_config_byte(dev,
+ PCI_INTERRUPT_LINE,
+ 9);
+ irq = 9;
+ }
+
+ }
+
+ return irq;
+}
+
+/* Do platform specific device initialization at pci_enable_device() time */
+int pcibios_plat_dev_init(struct pci_dev *dev)
+{
+ return 0;
+}
+
+void ddb_pci_reset_bus(void)
+{
+ u32 temp;
+
+ /*
+ * I am not sure about the "official" procedure, the following
+ * steps work as far as I know:
+ * We first set PCI cold reset bit (bit 31) in PCICTRL-H.
+ * Then we clear the PCI warm reset bit (bit 30) to 0 in PCICTRL-H.
+ * The same is true for both PCI channels.
+ */
+ temp = ddb_in32(DDB_PCICTL0_H);
+ temp |= 0x80000000;
+ ddb_out32(DDB_PCICTL0_H, temp);
+ temp &= ~0xc0000000;
+ ddb_out32(DDB_PCICTL0_H, temp);
+
+ temp = ddb_in32(DDB_PCICTL1_H);
+ temp |= 0x80000000;
+ ddb_out32(DDB_PCICTL1_H, temp);
+ temp &= ~0xc0000000;
+ ddb_out32(DDB_PCICTL1_H, temp);
+}
diff --git a/arch/mips/pci/pci-ev96100.c b/arch/mips/pci/pci-ev96100.c
new file mode 100644
index 0000000..f9457ea
--- /dev/null
+++ b/arch/mips/pci/pci-ev96100.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2000 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ * ppopov@mvista.com or source@mvista.com
+ *
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
+ *
+ * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+static struct resource pci_io_resource = {
+ .name = "io pci IO space",
+ .start = 0x10000000,
+ .end = 0x11ffffff,
+ .flags = IORESOURCE_IO
+};
+
+static struct resource pci_mem_resource = {
+ .name = "ext pci memory space",
+ .start = 0x12000000,
+ .end = 0x13ffffff,
+ .flags = IORESOURCE_MEM
+};
+
+extern struct pci_ops gt96100_pci_ops;
+
+struct pci_controller ev96100_controller = {
+ .pci_ops = >96100_pci_ops,
+ .io_resource = &pci_io_resource,
+ .mem_resource = &pci_mem_resource,
+};
+
+static void ev96100_pci_init(void)
+{
+ register_pci_controller(&ev96100_controller);
+}
+
+arch_initcall(ev96100_pci_init);
diff --git a/arch/mips/pci/pci-ip27.c b/arch/mips/pci/pci-ip27.c
new file mode 100644
index 0000000..068e0e5
--- /dev/null
+++ b/arch/mips/pci/pci-ip27.c
@@ -0,0 +1,489 @@
+/*
+ * 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) 2003 Christoph Hellwig (hch@lst.de)
+ * Copyright (C) 1999, 2000, 04 Ralf Baechle (ralf@linux-mips.org)
+ * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <asm/sn/arch.h>
+#include <asm/pci/bridge.h>
+#include <asm/paccess.h>
+#include <asm/sn/intr.h>
+#include <asm/sn/sn0/hub.h>
+
+extern unsigned int allocate_irqno(void);
+
+/*
+ * Max #PCI busses we can handle; ie, max #PCI bridges.
+ */
+#define MAX_PCI_BUSSES 40
+
+/*
+ * Max #PCI devices (like scsi controllers) we handle on a bus.
+ */
+#define MAX_DEVICES_PER_PCIBUS 8
+
+/*
+ * XXX: No kmalloc available when we do our crosstalk scan,
+ * we should try to move it later in the boot process.
+ */
+static struct bridge_controller bridges[MAX_PCI_BUSSES];
+
+/*
+ * Translate from irq to software PCI bus number and PCI slot.
+ */
+struct bridge_controller *irq_to_bridge[MAX_PCI_BUSSES * MAX_DEVICES_PER_PCIBUS];
+int irq_to_slot[MAX_PCI_BUSSES * MAX_DEVICES_PER_PCIBUS];
+
+/*
+ * The Bridge ASIC supports both type 0 and type 1 access. Type 1 is
+ * not really documented, so right now I can't write code which uses it.
+ * Therefore we use type 0 accesses for now even though they won't work
+ * correcly for PCI-to-PCI bridges.
+ *
+ * The function is complicated by the ultimate brokeness of the IOC3 chip
+ * which is used in SGI systems. The IOC3 can only handle 32-bit PCI
+ * accesses and does only decode parts of it's address space.
+ */
+
+static int pci_conf0_read_config(struct pci_bus *bus, unsigned int devfn,
+ int where, int size, u32 * value)
+{
+ struct bridge_controller *bc = BRIDGE_CONTROLLER(bus);
+ bridge_t *bridge = bc->base;
+ int slot = PCI_SLOT(devfn);
+ int fn = PCI_FUNC(devfn);
+ volatile void *addr;
+ u32 cf, shift, mask;
+ int res;
+
+ addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[PCI_VENDOR_ID];
+ if (get_dbe(cf, (u32 *) addr))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ /*
+ * IOC3 is fucked fucked beyond believe ... Don't even give the
+ * generic PCI code a chance to look at it for real ...
+ */
+ if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16)))
+ goto oh_my_gawd;
+
+ addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[where ^ (4 - size)];
+
+ if (size == 1)
+ res = get_dbe(*value, (u8 *) addr);
+ else if (size == 2)
+ res = get_dbe(*value, (u16 *) addr);
+ else
+ res = get_dbe(*value, (u32 *) addr);
+
+ return res ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL;
+
+oh_my_gawd:
+
+ /*
+ * IOC3 is fucked fucked beyond believe ... Don't even give the
+ * generic PCI code a chance to look at the wrong register.
+ */
+ if ((where >= 0x14 && where < 0x40) || (where >= 0x48)) {
+ *value = 0;
+ return PCIBIOS_SUCCESSFUL;
+ }
+
+ /*
+ * IOC3 is fucked fucked beyond believe ... Don't try to access
+ * anything but 32-bit words ...
+ */
+ addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2];
+
+ if (get_dbe(cf, (u32 *) addr))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ shift = ((where & 3) << 3);
+ mask = (0xffffffffU >> ((4 - size) << 3));
+ *value = (cf >> shift) & mask;
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int pci_conf1_read_config(struct pci_bus *bus, unsigned int devfn,
+ int where, int size, u32 * value)
+{
+ struct bridge_controller *bc = BRIDGE_CONTROLLER(bus);
+ bridge_t *bridge = bc->base;
+ int busno = bus->number;
+ int slot = PCI_SLOT(devfn);
+ int fn = PCI_FUNC(devfn);
+ volatile void *addr;
+ u32 cf, shift, mask;
+ int res;
+
+ bridge->b_pci_cfg = (busno << 16) | (slot << 11);
+ addr = &bridge->b_type1_cfg.c[(fn << 8) | PCI_VENDOR_ID];
+ if (get_dbe(cf, (u32 *) addr))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ /*
+ * IOC3 is fucked fucked beyond believe ... Don't even give the
+ * generic PCI code a chance to look at it for real ...
+ */
+ if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16)))
+ goto oh_my_gawd;
+
+ bridge->b_pci_cfg = (busno << 16) | (slot << 11);
+ addr = &bridge->b_type1_cfg.c[(fn << 8) | (where ^ (4 - size))];
+
+ if (size == 1)
+ res = get_dbe(*value, (u8 *) addr);
+ else if (size == 2)
+ res = get_dbe(*value, (u16 *) addr);
+ else
+ res = get_dbe(*value, (u32 *) addr);
+
+ return res ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL;
+
+oh_my_gawd:
+
+ /*
+ * IOC3 is fucked fucked beyond believe ... Don't even give the
+ * generic PCI code a chance to look at the wrong register.
+ */
+ if ((where >= 0x14 && where < 0x40) || (where >= 0x48)) {
+ *value = 0;
+ return PCIBIOS_SUCCESSFUL;
+ }
+
+ /*
+ * IOC3 is fucked fucked beyond believe ... Don't try to access
+ * anything but 32-bit words ...
+ */
+ bridge->b_pci_cfg = (busno << 16) | (slot << 11);
+ addr = &bridge->b_type1_cfg.c[(fn << 8) | where];
+
+ if (get_dbe(cf, (u32 *) addr))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ shift = ((where & 3) << 3);
+ mask = (0xffffffffU >> ((4 - size) << 3));
+ *value = (cf >> shift) & mask;
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int pci_read_config(struct pci_bus *bus, unsigned int devfn,
+ int where, int size, u32 * value)
+{
+ if (bus->number > 0)
+ return pci_conf1_read_config(bus, devfn, where, size, value);
+
+ return pci_conf0_read_config(bus, devfn, where, size, value);
+}
+
+static int pci_conf0_write_config(struct pci_bus *bus, unsigned int devfn,
+ int where, int size, u32 value)
+{
+ struct bridge_controller *bc = BRIDGE_CONTROLLER(bus);
+ bridge_t *bridge = bc->base;
+ int slot = PCI_SLOT(devfn);
+ int fn = PCI_FUNC(devfn);
+ volatile void *addr;
+ u32 cf, shift, mask, smask;
+ int res;
+
+ addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[PCI_VENDOR_ID];
+ if (get_dbe(cf, (u32 *) addr))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ /*
+ * IOC3 is fucked fucked beyond believe ... Don't even give the
+ * generic PCI code a chance to look at it for real ...
+ */
+ if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16)))
+ goto oh_my_gawd;
+
+ addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[where ^ (4 - size)];
+
+ if (size == 1) {
+ res = put_dbe(value, (u8 *) addr);
+ } else if (size == 2) {
+ res = put_dbe(value, (u16 *) addr);
+ } else {
+ res = put_dbe(value, (u32 *) addr);
+ }
+
+ if (res)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ return PCIBIOS_SUCCESSFUL;
+
+oh_my_gawd:
+
+ /*
+ * IOC3 is fucked fucked beyond believe ... Don't even give the
+ * generic PCI code a chance to touch the wrong register.
+ */
+ if ((where >= 0x14 && where < 0x40) || (where >= 0x48))
+ return PCIBIOS_SUCCESSFUL;
+
+ /*
+ * IOC3 is fucked fucked beyond believe ... Don't try to access
+ * anything but 32-bit words ...
+ */
+ addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2];
+
+ if (get_dbe(cf, (u32 *) addr))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ shift = ((where & 3) << 3);
+ mask = (0xffffffffU >> ((4 - size) << 3));
+ smask = mask << shift;
+
+ cf = (cf & ~smask) | ((value & mask) << shift);
+ if (put_dbe(cf, (u32 *) addr))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int pci_conf1_write_config(struct pci_bus *bus, unsigned int devfn,
+ int where, int size, u32 value)
+{
+ struct bridge_controller *bc = BRIDGE_CONTROLLER(bus);
+ bridge_t *bridge = bc->base;
+ int slot = PCI_SLOT(devfn);
+ int fn = PCI_FUNC(devfn);
+ int busno = bus->number;
+ volatile void *addr;
+ u32 cf, shift, mask, smask;
+ int res;
+
+ bridge->b_pci_cfg = (busno << 16) | (slot << 11);
+ addr = &bridge->b_type1_cfg.c[(fn << 8) | PCI_VENDOR_ID];
+ if (get_dbe(cf, (u32 *) addr))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ /*
+ * IOC3 is fucked fucked beyond believe ... Don't even give the
+ * generic PCI code a chance to look at it for real ...
+ */
+ if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16)))
+ goto oh_my_gawd;
+
+ addr = &bridge->b_type1_cfg.c[(fn << 8) | (where ^ (4 - size))];
+
+ if (size == 1) {
+ res = put_dbe(value, (u8 *) addr);
+ } else if (size == 2) {
+ res = put_dbe(value, (u16 *) addr);
+ } else {
+ res = put_dbe(value, (u32 *) addr);
+ }
+
+ if (res)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ return PCIBIOS_SUCCESSFUL;
+
+oh_my_gawd:
+
+ /*
+ * IOC3 is fucked fucked beyond believe ... Don't even give the
+ * generic PCI code a chance to touch the wrong register.
+ */
+ if ((where >= 0x14 && where < 0x40) || (where >= 0x48))
+ return PCIBIOS_SUCCESSFUL;
+
+ /*
+ * IOC3 is fucked fucked beyond believe ... Don't try to access
+ * anything but 32-bit words ...
+ */
+ addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2];
+
+ if (get_dbe(cf, (u32 *) addr))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ shift = ((where & 3) << 3);
+ mask = (0xffffffffU >> ((4 - size) << 3));
+ smask = mask << shift;
+
+ cf = (cf & ~smask) | ((value & mask) << shift);
+ if (put_dbe(cf, (u32 *) addr))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int pci_write_config(struct pci_bus *bus, unsigned int devfn,
+ int where, int size, u32 value)
+{
+ if (bus->number > 0)
+ return pci_conf1_write_config(bus, devfn, where, size, value);
+
+ return pci_conf0_write_config(bus, devfn, where, size, value);
+}
+
+static struct pci_ops bridge_pci_ops = {
+ .read = pci_read_config,
+ .write = pci_write_config,
+};
+
+int __init bridge_probe(nasid_t nasid, int widget_id, int masterwid)
+{
+ unsigned long offset = NODE_OFFSET(nasid);
+ struct bridge_controller *bc;
+ static int num_bridges = 0;
+ bridge_t *bridge;
+ int slot;
+
+ printk("a bridge\n");
+
+ /* XXX: kludge alert.. */
+ if (!num_bridges)
+ ioport_resource.end = ~0UL;
+
+ bc = &bridges[num_bridges];
+
+ bc->pc.pci_ops = &bridge_pci_ops;
+ bc->pc.mem_resource = &bc->mem;
+ bc->pc.io_resource = &bc->io;
+
+ bc->pc.index = num_bridges;
+
+ bc->mem.name = "Bridge PCI MEM";
+ bc->pc.mem_offset = offset;
+ bc->mem.start = 0;
+ bc->mem.end = ~0UL;
+ bc->mem.flags = IORESOURCE_MEM;
+
+ bc->io.name = "Bridge IO MEM";
+ bc->pc.io_offset = offset;
+ bc->io.start = 0UL;
+ bc->io.end = ~0UL;
+ bc->io.flags = IORESOURCE_IO;
+
+ bc->irq_cpu = smp_processor_id();
+ bc->widget_id = widget_id;
+ bc->nasid = nasid;
+
+ bc->baddr = (u64)masterwid << 60;
+ bc->baddr |= (1UL << 56); /* Barrier set */
+
+ /*
+ * point to this bridge
+ */
+ bridge = (bridge_t *) RAW_NODE_SWIN_BASE(nasid, widget_id);
+
+ /*
+ * Clear all pending interrupts.
+ */
+ bridge->b_int_rst_stat = BRIDGE_IRR_ALL_CLR;
+
+ /*
+ * Until otherwise set up, assume all interrupts are from slot 0
+ */
+ bridge->b_int_device = 0x0;
+
+ /*
+ * swap pio's to pci mem and io space (big windows)
+ */
+ bridge->b_wid_control |= BRIDGE_CTRL_IO_SWAP |
+ BRIDGE_CTRL_MEM_SWAP;
+
+ /*
+ * Hmm... IRIX sets additional bits in the address which
+ * are documented as reserved in the bridge docs.
+ */
+ bridge->b_wid_int_upper = 0x8000 | (masterwid << 16);
+ bridge->b_wid_int_lower = 0x01800090; /* PI_INT_PEND_MOD off*/
+ bridge->b_dir_map = (masterwid << 20); /* DMA */
+ bridge->b_int_enable = 0;
+
+ for (slot = 0; slot < 8; slot ++) {
+ bridge->b_device[slot].reg |= BRIDGE_DEV_SWAP_DIR;
+ bc->pci_int[slot] = -1;
+ }
+ bridge->b_wid_tflush; /* wait until Bridge PIO complete */
+
+ bc->base = bridge;
+
+ register_pci_controller(&bc->pc);
+
+ num_bridges++;
+
+ return 0;
+}
+
+/*
+ * All observed requests have pin == 1. We could have a global here, that
+ * gets incremented and returned every time - unfortunately, pci_map_irq
+ * may be called on the same device over and over, and need to return the
+ * same value. On O2000, pin can be 0 or 1, and PCI slots can be [0..7].
+ *
+ * A given PCI device, in general, should be able to intr any of the cpus
+ * on any one of the hubs connected to its xbow.
+ */
+int __devinit pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+ struct bridge_controller *bc = BRIDGE_CONTROLLER(dev->bus);
+ int irq = bc->pci_int[slot];
+
+ if (irq == -1) {
+ irq = bc->pci_int[slot] = request_bridge_irq(bc);
+ if (irq < 0)
+ panic("Can't allocate interrupt for PCI device %s\n",
+ pci_name(dev));
+ }
+
+ irq_to_bridge[irq] = bc;
+ irq_to_slot[irq] = slot;
+
+ return irq;
+}
+
+/* Do platform specific device initialization at pci_enable_device() time */
+int pcibios_plat_dev_init(struct pci_dev *dev)
+{
+ return 0;
+}
+
+/*
+ * Device might live on a subordinate PCI bus. XXX Walk up the chain of buses
+ * to find the slot number in sense of the bridge device register.
+ * XXX This also means multiple devices might rely on conflicting bridge
+ * settings.
+ */
+
+static inline void pci_disable_swapping(struct pci_dev *dev)
+{
+ struct bridge_controller *bc = BRIDGE_CONTROLLER(dev->bus);
+ bridge_t *bridge = bc->base;
+ int slot = PCI_SLOT(dev->devfn);
+
+ /* Turn off byte swapping */
+ bridge->b_device[slot].reg &= ~BRIDGE_DEV_SWAP_DIR;
+ bridge->b_widget.w_tflush; /* Flush */
+}
+
+static inline void pci_enable_swapping(struct pci_dev *dev)
+{
+ struct bridge_controller *bc = BRIDGE_CONTROLLER(dev->bus);
+ bridge_t *bridge = bc->base;
+ int slot = PCI_SLOT(dev->devfn);
+
+ /* Turn on byte swapping */
+ bridge->b_device[slot].reg |= BRIDGE_DEV_SWAP_DIR;
+ bridge->b_widget.w_tflush; /* Flush */
+}
+
+static void __init pci_fixup_ioc3(struct pci_dev *d)
+{
+ pci_disable_swapping(d);
+}
+
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SGI, PCI_DEVICE_ID_SGI_IOC3,
+ pci_fixup_ioc3);
diff --git a/arch/mips/pci/pci-ip32.c b/arch/mips/pci/pci-ip32.c
new file mode 100644
index 0000000..1faeb03
--- /dev/null
+++ b/arch/mips/pci/pci-ip32.c
@@ -0,0 +1,145 @@
+/*
+ * 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) 2000, 2001 Keith M Wesolowski
+ * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org)
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/types.h>
+#include <asm/ip32/mace.h>
+#include <asm/ip32/ip32_ints.h>
+
+#undef DEBUG_MACE_PCI
+
+/*
+ * Handle errors from the bridge. This includes master and target aborts,
+ * various command and address errors, and the interrupt test. This gets
+ * registered on the bridge error irq. It's conceivable that some of these
+ * conditions warrant a panic. Anybody care to say which ones?
+ */
+static irqreturn_t macepci_error(int irq, void *dev, struct pt_regs *regs)
+{
+ char s;
+ unsigned int flags = mace->pci.error;
+ unsigned int addr = mace->pci.error_addr;
+
+ if (flags & MACEPCI_ERROR_MEMORY_ADDR)
+ s = 'M';
+ else if (flags & MACEPCI_ERROR_CONFIG_ADDR)
+ s = 'C';
+ else
+ s = 'X';
+
+ if (flags & MACEPCI_ERROR_MASTER_ABORT) {
+ printk("MACEPCI: Master abort at 0x%08x (%c)\n", addr, s);
+ flags &= ~MACEPCI_ERROR_MASTER_ABORT;
+ }
+ if (flags & MACEPCI_ERROR_TARGET_ABORT) {
+ printk("MACEPCI: Target abort at 0x%08x (%c)\n", addr, s);
+ flags &= ~MACEPCI_ERROR_TARGET_ABORT;
+ }
+ if (flags & MACEPCI_ERROR_DATA_PARITY_ERR) {
+ printk("MACEPCI: Data parity error at 0x%08x (%c)\n", addr, s);
+ flags &= ~MACEPCI_ERROR_DATA_PARITY_ERR;
+ }
+ if (flags & MACEPCI_ERROR_RETRY_ERR) {
+ printk("MACEPCI: Retry error at 0x%08x (%c)\n", addr, s);
+ flags &= ~MACEPCI_ERROR_RETRY_ERR;
+ }
+ if (flags & MACEPCI_ERROR_ILLEGAL_CMD) {
+ printk("MACEPCI: Illegal command at 0x%08x (%c)\n", addr, s);
+ flags &= ~MACEPCI_ERROR_ILLEGAL_CMD;
+ }
+ if (flags & MACEPCI_ERROR_SYSTEM_ERR) {
+ printk("MACEPCI: System error at 0x%08x (%c)\n", addr, s);
+ flags &= ~MACEPCI_ERROR_SYSTEM_ERR;
+ }
+ if (flags & MACEPCI_ERROR_PARITY_ERR) {
+ printk("MACEPCI: Parity error at 0x%08x (%c)\n", addr, s);
+ flags &= ~MACEPCI_ERROR_PARITY_ERR;
+ }
+ if (flags & MACEPCI_ERROR_OVERRUN) {
+ printk("MACEPCI: Overrun error at 0x%08x (%c)\n", addr, s);
+ flags &= ~MACEPCI_ERROR_OVERRUN;
+ }
+ if (flags & MACEPCI_ERROR_SIG_TABORT) {
+ printk("MACEPCI: Signaled target abort (clearing)\n");
+ flags &= ~MACEPCI_ERROR_SIG_TABORT;
+ }
+ if (flags & MACEPCI_ERROR_INTERRUPT_TEST) {
+ printk("MACEPCI: Interrupt test triggered (clearing)\n");
+ flags &= ~MACEPCI_ERROR_INTERRUPT_TEST;
+ }
+
+ mace->pci.error = flags;
+
+ return IRQ_HANDLED;
+}
+
+
+extern struct pci_ops mace_pci_ops;
+#ifdef CONFIG_MIPS64
+static struct resource mace_pci_mem_resource = {
+ .name = "SGI O2 PCI MEM",
+ .start = MACEPCI_HI_MEMORY,
+ .end = 0x2FFFFFFFFUL,
+ .flags = IORESOURCE_MEM,
+};
+static struct resource mace_pci_io_resource = {
+ .name = "SGI O2 PCI IO",
+ .start = 0x00000000UL,
+ .end = 0xffffffffUL,
+ .flags = IORESOURCE_IO,
+};
+#define MACE_PCI_MEM_OFFSET 0x200000000
+#else
+static struct resource mace_pci_mem_resource = {
+ .name = "SGI O2 PCI MEM",
+ .start = MACEPCI_LOW_MEMORY,
+ .end = MACEPCI_LOW_MEMORY + 0x2000000 - 1,
+ .flags = IORESOURCE_MEM,
+};
+static struct resource mace_pci_io_resource = {
+ .name = "SGI O2 PCI IO",
+ .start = 0x00000000,
+ .end = 0xFFFFFFFF,
+ .flags = IORESOURCE_IO,
+};
+#define MACE_PCI_MEM_OFFSET (MACEPCI_LOW_MEMORY - 0x80000000)
+#endif
+static struct pci_controller mace_pci_controller = {
+ .pci_ops = &mace_pci_ops,
+ .mem_resource = &mace_pci_mem_resource,
+ .io_resource = &mace_pci_io_resource,
+ .iommu = 0,
+ .mem_offset = MACE_PCI_MEM_OFFSET,
+ .io_offset = 0,
+};
+
+static int __init mace_init(void)
+{
+ PCIBIOS_MIN_IO = 0x1000;
+
+ /* Clear any outstanding errors and enable interrupts */
+ mace->pci.error_addr = 0;
+ mace->pci.error = 0;
+ mace->pci.control = 0xff008500;
+
+ printk("MACE PCI rev %d\n", mace->pci.rev);
+
+ BUG_ON(request_irq(MACE_PCI_BRIDGE_IRQ, macepci_error, 0,
+ "MACE PCI error", NULL));
+
+ ioport_resource.end = mace_pci_io_resource.end;
+ register_pci_controller(&mace_pci_controller);
+
+ return 0;
+}
+
+arch_initcall(mace_init);
diff --git a/arch/mips/pci/pci-jmr3927.c b/arch/mips/pci/pci-jmr3927.c
new file mode 100644
index 0000000..95a0287
--- /dev/null
+++ b/arch/mips/pci/pci-jmr3927.c
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ * ahennessy@mvista.com
+ *
+ * Copyright (C) 2000-2001 Toshiba Corporation
+ * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/jmr3927/jmr3927.h>
+#include <asm/debug.h>
+
+struct resource pci_io_resource = {
+ "IO MEM",
+ 0x1000, /* reserve regacy I/O space */
+ 0x1000 + JMR3927_PCIIO_SIZE - 1,
+ IORESOURCE_IO
+};
+
+struct resource pci_mem_resource = {
+ "PCI MEM",
+ JMR3927_PCIMEM,
+ JMR3927_PCIMEM + JMR3927_PCIMEM_SIZE - 1,
+ IORESOURCE_MEM
+};
+
+extern struct pci_ops jmr3927_pci_ops;
+
+struct pci_controller jmr3927_controller = {
+ .pci_ops = &jmr3927_pci_ops,
+ .io_resource = &pci_io_resource,
+ .mem_resource = &pci_mem_resource,
+ .mem_offset = JMR3927_PCIMEM;
+};
diff --git a/arch/mips/pci/pci-lasat.c b/arch/mips/pci/pci-lasat.c
new file mode 100644
index 0000000..ae3cc4b
--- /dev/null
+++ b/arch/mips/pci/pci-lasat.c
@@ -0,0 +1,95 @@
+/*
+ * 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) 2000, 2001, 04 Keith M Wesolowski
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <asm/bootinfo.h>
+
+extern struct pci_ops nile4_pci_ops;
+extern struct pci_ops gt64120_pci_ops;
+static struct resource lasat_pci_mem_resource = {
+ .name = "LASAT PCI MEM",
+ .start = 0x18000000,
+ .end = 0x19FFFFFF,
+ .flags = IORESOURCE_MEM,
+};
+
+static struct resource lasat_pci_io_resource = {
+ .name = "LASAT PCI IO",
+ .start = 0x1a000000,
+ .end = 0x1bFFFFFF,
+ .flags = IORESOURCE_IO,
+};
+
+static struct pci_controller lasat_pci_controller = {
+ .mem_resource = &lasat_pci_mem_resource,
+ .io_resource = &lasat_pci_io_resource,
+};
+
+static int __init lasat_pci_setup(void)
+{
+ printk("PCI: starting\n");
+
+ switch (mips_machtype) {
+ case MACH_LASAT_100:
+ lasat_pci_controller.pci_ops = >64120_pci_ops;
+ break;
+ case MACH_LASAT_200:
+ lasat_pci_controller.pci_ops = &nile4_pci_ops;
+ break;
+ default:
+ panic("pcibios_init: mips_machtype incorrect");
+ }
+
+ register_pci_controller(&lasat_pci_controller);
+ return 0;
+}
+early_initcall(lasat_pci_setup);
+
+#define LASATINT_ETH1 0
+#define LASATINT_ETH0 1
+#define LASATINT_HDC 2
+#define LASATINT_COMP 3
+#define LASATINT_HDLC 4
+#define LASATINT_PCIA 5
+#define LASATINT_PCIB 6
+#define LASATINT_PCIC 7
+#define LASATINT_PCID 8
+
+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+ switch (slot) {
+ case 1:
+ return LASATINT_PCIA; /* Expansion Module 0 */
+ case 2:
+ return LASATINT_PCIB; /* Expansion Module 1 */
+ case 3:
+ return LASATINT_PCIC; /* Expansion Module 2 */
+ case 4:
+ return LASATINT_ETH1; /* Ethernet 1 (LAN 2) */
+ case 5:
+ return LASATINT_ETH0; /* Ethernet 0 (LAN 1) */
+ case 6:
+ return LASATINT_HDC; /* IDE controller */
+ default:
+ return 0xff; /* Illegal */
+ }
+
+ return -1;
+}
+
+/* Do platform specific device initialization at pci_enable_device() time */
+int pcibios_plat_dev_init(struct pci_dev *dev)
+{
+ return 0;
+}
diff --git a/arch/mips/pci/pci-ocelot-c.c b/arch/mips/pci/pci-ocelot-c.c
new file mode 100644
index 0000000..1d84d36
--- /dev/null
+++ b/arch/mips/pci/pci-ocelot-c.c
@@ -0,0 +1,143 @@
+/*
+ * 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) 2004 by Ralf Baechle (ralf@linux-mips.org)
+ */
+
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <asm/mv64340.h>
+
+#include <linux/init.h>
+
+/*
+ * We assume the address ranges have already been setup appropriately by
+ * the firmware. PMON in case of the Ocelot C does that.
+ */
+static struct resource mv_pci_io_mem0_resource = {
+ .name = "MV64340 PCI0 IO MEM",
+ .flags = IORESOURCE_IO
+};
+
+static struct resource mv_pci_mem0_resource = {
+ .name = "MV64340 PCI0 MEM",
+ .flags = IORESOURCE_MEM
+};
+
+static struct mv_pci_controller mv_bus0_controller = {
+ .pcic = {
+ .pci_ops = &mv_pci_ops,
+ .mem_resource = &mv_pci_mem0_resource,
+ .io_resource = &mv_pci_io_mem0_resource,
+ },
+ .config_addr = MV64340_PCI_0_CONFIG_ADDR,
+ .config_vreg = MV64340_PCI_0_CONFIG_DATA_VIRTUAL_REG,
+};
+
+static uint32_t mv_io_base, mv_io_size;
+
+static void mv64340_pci0_init(void)
+{
+ uint32_t mem0_base, mem0_size;
+ uint32_t io_base, io_size;
+
+ io_base = MV_READ(MV64340_PCI_0_IO_BASE_ADDR) << 16;
+ io_size = (MV_READ(MV64340_PCI_0_IO_SIZE) + 1) << 16;
+ mem0_base = MV_READ(MV64340_PCI_0_MEMORY0_BASE_ADDR) << 16;
+ mem0_size = (MV_READ(MV64340_PCI_0_MEMORY0_SIZE) + 1) << 16;
+
+ mv_pci_io_mem0_resource.start = 0;
+ mv_pci_io_mem0_resource.end = io_size - 1;
+ mv_pci_mem0_resource.start = mem0_base;
+ mv_pci_mem0_resource.end = mem0_base + mem0_size - 1;
+ mv_bus0_controller.pcic.mem_offset = mem0_base;
+ mv_bus0_controller.pcic.io_offset = 0;
+
+ ioport_resource.end = io_size - 1;
+
+ register_pci_controller(&mv_bus0_controller.pcic);
+
+ mv_io_base = io_base;
+ mv_io_size = io_size;
+}
+
+static struct resource mv_pci_io_mem1_resource = {
+ .name = "MV64340 PCI1 IO MEM",
+ .flags = IORESOURCE_IO
+};
+
+static struct resource mv_pci_mem1_resource = {
+ .name = "MV64340 PCI1 MEM",
+ .flags = IORESOURCE_MEM
+};
+
+static struct mv_pci_controller mv_bus1_controller = {
+ .pcic = {
+ .pci_ops = &mv_pci_ops,
+ .mem_resource = &mv_pci_mem1_resource,
+ .io_resource = &mv_pci_io_mem1_resource,
+ },
+ .config_addr = MV64340_PCI_1_CONFIG_ADDR,
+ .config_vreg = MV64340_PCI_1_CONFIG_DATA_VIRTUAL_REG,
+};
+
+static __init void mv64340_pci1_init(void)
+{
+ uint32_t mem0_base, mem0_size;
+ uint32_t io_base, io_size;
+
+ io_base = MV_READ(MV64340_PCI_1_IO_BASE_ADDR) << 16;
+ io_size = (MV_READ(MV64340_PCI_1_IO_SIZE) + 1) << 16;
+ mem0_base = MV_READ(MV64340_PCI_1_MEMORY0_BASE_ADDR) << 16;
+ mem0_size = (MV_READ(MV64340_PCI_1_MEMORY0_SIZE) + 1) << 16;
+
+ /*
+ * Here we assume the I/O window of second bus to be contiguous with
+ * the first. A gap is no problem but would waste address space for
+ * remapping the port space.
+ */
+ mv_pci_io_mem1_resource.start = mv_io_size;
+ mv_pci_io_mem1_resource.end = mv_io_size + io_size - 1;
+ mv_pci_mem1_resource.start = mem0_base;
+ mv_pci_mem1_resource.end = mem0_base + mem0_size - 1;
+ mv_bus1_controller.pcic.mem_offset = mem0_base;
+ mv_bus1_controller.pcic.io_offset = 0;
+
+ ioport_resource.end = io_base + io_size -mv_io_base - 1;
+
+ register_pci_controller(&mv_bus1_controller.pcic);
+
+ mv_io_size = io_base + io_size - mv_io_base;
+}
+
+static __init int __init ocelot_c_pci_init(void)
+{
+ unsigned long io_v_base;
+ uint32_t enable;
+
+ enable = ~MV_READ(MV64340_BASE_ADDR_ENABLE);
+
+ /*
+ * We require at least one enabled I/O or PCI memory window or we
+ * will ignore this PCI bus. We ignore PCI windows 1, 2 and 3.
+ */
+ if (enable & (0x01 << 9) || enable & (0x01 << 10))
+ mv64340_pci0_init();
+
+ if (enable & (0x01 << 14) || enable & (0x01 << 15))
+ mv64340_pci1_init();
+
+ if (mv_io_size) {
+ io_v_base = (unsigned long) ioremap(mv_io_base, mv_io_size);
+ if (!io_v_base)
+ panic("Could not ioremap I/O port range");
+
+ set_io_port_base(io_v_base);
+ }
+
+ return 0;
+}
+
+arch_initcall(ocelot_c_pci_init);
diff --git a/arch/mips/pci/pci-ocelot-g.c b/arch/mips/pci/pci-ocelot-g.c
new file mode 100644
index 0000000..1e34301
--- /dev/null
+++ b/arch/mips/pci/pci-ocelot-g.c
@@ -0,0 +1,97 @@
+/*
+ * 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) 2004 by Ralf Baechle (ralf@linux-mips.org)
+ *
+ * This doesn't really fly - but I don't have a GT64240 system for testing.
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <asm/gt64240.h>
+
+/*
+ * We assume these address ranges have been programmed into the GT-64240 by
+ * the firmware. PMON in case of the Ocelot G does that. Note the size of
+ * the I/O range is completly stupid; I/O mappings are limited to at most
+ * 256 bytes by the PCI spec and deprecated; and just to make things worse
+ * apparently many devices don't decode more than 64k of I/O space.
+ */
+
+#define gt_io_size 0x20000000UL
+#define gt_io_base 0xe0000000UL
+
+static struct resource gt_pci_mem0_resource = {
+ .name = "MV64240 PCI0 MEM",
+ .start = 0xc0000000UL,
+ .end = 0xcfffffffUL,
+ .flags = IORESOURCE_MEM
+};
+
+static struct resource gt_pci_io_mem0_resource = {
+ .name = "MV64240 PCI0 IO MEM",
+ .start = 0xe0000000UL,
+ .end = 0xefffffffUL,
+ .flags = IORESOURCE_IO
+};
+
+static struct mv_pci_controller gt_bus0_controller = {
+ .pcic = {
+ .pci_ops = &mv_pci_ops,
+ .mem_resource = >_pci_mem0_resource,
+ .mem_offset = 0xc0000000UL,
+ .io_resource = >_pci_io_mem0_resource,
+ .io_offset = 0x00000000UL
+ },
+ .config_addr = PCI_0CONFIGURATION_ADDRESS,
+ .config_vreg = PCI_0CONFIGURATION_DATA_VIRTUAL_REGISTER,
+};
+
+static struct resource gt_pci_mem1_resource = {
+ .name = "MV64240 PCI1 MEM",
+ .start = 0xd0000000UL,
+ .end = 0xdfffffffUL,
+ .flags = IORESOURCE_MEM
+};
+
+static struct resource gt_pci_io_mem1_resource = {
+ .name = "MV64240 PCI1 IO MEM",
+ .start = 0xf0000000UL,
+ .end = 0xffffffffUL,
+ .flags = IORESOURCE_IO
+};
+
+static struct mv_pci_controller gt_bus1_controller = {
+ .pcic = {
+ .pci_ops = &mv_pci_ops,
+ .mem_resource = >_pci_mem1_resource,
+ .mem_offset = 0xd0000000UL,
+ .io_resource = >_pci_io_mem1_resource,
+ .io_offset = 0x10000000UL
+ },
+ .config_addr = PCI_1CONFIGURATION_ADDRESS,
+ .config_vreg = PCI_1CONFIGURATION_DATA_VIRTUAL_REGISTER,
+};
+
+static __init int __init ocelot_g_pci_init(void)
+{
+ unsigned long io_v_base;
+
+ if (gt_io_size) {
+ io_v_base = (unsigned long) ioremap(gt_io_base, gt_io_size);
+ if (!io_v_base)
+ panic("Could not ioremap I/O port range");
+
+ set_io_port_base(io_v_base);
+ }
+
+ register_pci_controller(>_bus0_controller.pcic);
+ register_pci_controller(>_bus1_controller.pcic);
+
+ return 0;
+}
+
+arch_initcall(ocelot_g_pci_init);
diff --git a/arch/mips/pci/pci-ocelot.c b/arch/mips/pci/pci-ocelot.c
new file mode 100644
index 0000000..3da8a4e
--- /dev/null
+++ b/arch/mips/pci/pci-ocelot.c
@@ -0,0 +1,107 @@
+/*
+ * BRIEF MODULE DESCRIPTION
+ * Galileo Evaluation Boards PCI support.
+ *
+ * The general-purpose functions to read/write and configure the GT64120A's
+ * PCI registers (function names start with pci0 or pci1) are either direct
+ * copies of functions written by Galileo Technology, or are modifications
+ * of their functions to work with Linux 2.4 vs Linux 2.2. These functions
+ * are Copyright - Galileo Technology.
+ *
+ * Other functions are derived from other MIPS PCI implementations, or were
+ * written by RidgeRun, Inc, Copyright (C) 2000 RidgeRun, Inc.
+ * glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/cache.h>
+#include <asm/pci.h>
+#include <asm/io.h>
+#include <asm/gt64120.h>
+
+static inline unsigned int pci0ReadConfigReg(unsigned int offset)
+{
+ unsigned int DataForRegCf8;
+ unsigned int data;
+
+ DataForRegCf8 = ((PCI_SLOT(device->devfn) << 11) |
+ (PCI_FUNC(device->devfn) << 8) |
+ (offset & ~0x3)) | 0x80000000;
+ GT_WRITE(GT_PCI0_CFGADDR_OFS, DataForRegCf8);
+ GT_READ(GT_PCI0_CFGDATA_OFS, &data);
+
+ return data;
+}
+
+static inline void pci0WriteConfigReg(unsigned int offset, unsigned int data)
+{
+ unsigned int DataForRegCf8;
+
+ DataForRegCf8 = ((PCI_SLOT(device->devfn) << 11) |
+ (PCI_FUNC(device->devfn) << 8) |
+ (offset & ~0x3)) | 0x80000000;
+ GT_WRITE(GT_PCI0_CFGADDR_OFS, DataForRegCf8);
+ GT_WRITE(GT_PCI0_CFGDATA_OFS, data);
+}
+
+static struct resource ocelot_mem_resource = {
+ iomem_resource.start = GT_PCI_MEM_BASE;
+ iomem_resource.end = GT_PCI_MEM_BASE + GT_PCI_MEM_BASE - 1;
+};
+
+static struct resource ocelot_io_resource = {
+ ioport_resource.start = GT_PCI_IO_BASE;
+ ioport_resource.end = GT_PCI_IO_BASE + GT_PCI_IO_SIZE - 1;
+};
+
+static struct pci_controller ocelot_pci_controller = {
+ .pci_ops = gt64120_pci_ops;
+ .mem_resource = &ocelot_mem_resource;
+ .io_resource = &ocelot_io_resource;
+};
+
+static int __init ocelot_pcibios_init(void)
+{
+ u32 tmp;
+
+ GT_READ(GT_PCI0_CMD_OFS, &tmp);
+ GT_READ(GT_PCI0_BARE_OFS, &tmp);
+
+ /*
+ * You have to enable bus mastering to configure any other
+ * card on the bus.
+ */
+ tmp = pci0ReadConfigReg(PCI_COMMAND);
+ tmp |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_SERR;
+ pci0WriteConfigReg(PCI_COMMAND, tmp);
+
+ register_pci_controller(&ocelot_pci_controller);
+}
+
+arch_initcall(ocelot_pcibios_init);
diff --git a/arch/mips/pci/pci-sb1250.c b/arch/mips/pci/pci-sb1250.c
new file mode 100644
index 0000000..7cca3bd
--- /dev/null
+++ b/arch/mips/pci/pci-sb1250.c
@@ -0,0 +1,292 @@
+/*
+ * Copyright (C) 2001,2002,2003 Broadcom Corporation
+ * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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.
+ */
+
+/*
+ * BCM1250-specific PCI support
+ *
+ * This module provides the glue between Linux's PCI subsystem
+ * and the hardware. We basically provide glue for accessing
+ * configuration space, and set up the translation for I/O
+ * space accesses.
+ *
+ * To access configuration space, we use ioremap. In the 32-bit
+ * kernel, this consumes either 4 or 8 page table pages, and 16MB of
+ * kernel mapped memory. Hopefully neither of these should be a huge
+ * problem.
+ */
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/console.h>
+#include <linux/tty.h>
+
+#include <asm/io.h>
+
+#include <asm/sibyte/sb1250_defs.h>
+#include <asm/sibyte/sb1250_regs.h>
+#include <asm/sibyte/sb1250_scd.h>
+#include <asm/sibyte/board.h>
+
+/*
+ * Macros for calculating offsets into config space given a device
+ * structure or dev/fun/reg
+ */
+#define CFGOFFSET(bus,devfn,where) (((bus)<<16) + ((devfn)<<8) + (where))
+#define CFGADDR(bus,devfn,where) CFGOFFSET((bus)->number,(devfn),where)
+
+static void *cfg_space;
+
+#define PCI_BUS_ENABLED 1
+#define LDT_BUS_ENABLED 2
+#define PCI_DEVICE_MODE 4
+
+static int sb1250_bus_status = 0;
+
+#define PCI_BRIDGE_DEVICE 0
+#define LDT_BRIDGE_DEVICE 1
+
+#ifdef CONFIG_SIBYTE_HAS_LDT
+/*
+ * HT's level-sensitive interrupts require EOI, which is generated
+ * through a 4MB memory-mapped region
+ */
+unsigned long ldt_eoi_space;
+#endif
+
+/*
+ * Read/write 32-bit values in config space.
+ */
+static inline u32 READCFG32(u32 addr)
+{
+ return *(u32 *) (cfg_space + (addr & ~3));
+}
+
+static inline void WRITECFG32(u32 addr, u32 data)
+{
+ *(u32 *) (cfg_space + (addr & ~3)) = data;
+}
+
+int pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+ return dev->irq;
+}
+
+/* Do platform specific device initialization at pci_enable_device() time */
+int pcibios_plat_dev_init(struct pci_dev *dev)
+{
+ return 0;
+}
+
+/*
+ * Some checks before doing config cycles:
+ * In PCI Device Mode, hide everything on bus 0 except the LDT host
+ * bridge. Otherwise, access is controlled by bridge MasterEn bits.
+ */
+static int sb1250_pci_can_access(struct pci_bus *bus, int devfn)
+{
+ u32 devno;
+
+ if (!(sb1250_bus_status & (PCI_BUS_ENABLED | PCI_DEVICE_MODE)))
+ return 0;
+
+ if (bus->number == 0) {
+ devno = PCI_SLOT(devfn);
+ if (devno == LDT_BRIDGE_DEVICE)
+ return (sb1250_bus_status & LDT_BUS_ENABLED) != 0;
+ else if (sb1250_bus_status & PCI_DEVICE_MODE)
+ return 0;
+ else
+ return 1;
+ } else
+ return 1;
+}
+
+/*
+ * Read/write access functions for various sizes of values
+ * in config space. Return all 1's for disallowed accesses
+ * for a kludgy but adequate simulation of master aborts.
+ */
+
+static int sb1250_pcibios_read(struct pci_bus *bus, unsigned int devfn,
+ int where, int size, u32 * val)
+{
+ u32 data = 0;
+
+ if ((size == 2) && (where & 1))
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+ else if ((size == 4) && (where & 3))
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+
+ if (sb1250_pci_can_access(bus, devfn))
+ data = READCFG32(CFGADDR(bus, devfn, where));
+ else
+ data = 0xFFFFFFFF;
+
+ if (size == 1)
+ *val = (data >> ((where & 3) << 3)) & 0xff;
+ else if (size == 2)
+ *val = (data >> ((where & 3) << 3)) & 0xffff;
+ else
+ *val = data;
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int sb1250_pcibios_write(struct pci_bus *bus, unsigned int devfn,
+ int where, int size, u32 val)
+{
+ u32 cfgaddr = CFGADDR(bus, devfn, where);
+ u32 data = 0;
+
+ if ((size == 2) && (where & 1))
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+ else if ((size == 4) && (where & 3))
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+
+ if (!sb1250_pci_can_access(bus, devfn))
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+
+ data = READCFG32(cfgaddr);
+
+ if (size == 1)
+ data = (data & ~(0xff << ((where & 3) << 3))) |
+ (val << ((where & 3) << 3));
+ else if (size == 2)
+ data = (data & ~(0xffff << ((where & 3) << 3))) |
+ (val << ((where & 3) << 3));
+ else
+ data = val;
+
+ WRITECFG32(cfgaddr, data);
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+struct pci_ops sb1250_pci_ops = {
+ .read = sb1250_pcibios_read,
+ .write = sb1250_pcibios_write,
+};
+
+static struct resource sb1250_mem_resource = {
+ .name = "SB1250 PCI MEM",
+ .start = 0x40000000UL,
+ .end = 0x5fffffffUL,
+ .flags = IORESOURCE_MEM,
+};
+
+static struct resource sb1250_io_resource = {
+ .name = "SB1250 PCI I/O",
+ .start = 0x00000000UL,
+ .end = 0x01ffffffUL,
+ .flags = IORESOURCE_IO,
+};
+
+struct pci_controller sb1250_controller = {
+ .pci_ops = &sb1250_pci_ops,
+ .mem_resource = &sb1250_mem_resource,
+ .io_resource = &sb1250_io_resource,
+};
+
+static int __init sb1250_pcibios_init(void)
+{
+ uint32_t cmdreg;
+ uint64_t reg;
+ extern int pci_probe_only;
+
+ /* CFE will assign PCI resources */
+ pci_probe_only = 1;
+
+ /* Avoid ISA compat ranges. */
+ PCIBIOS_MIN_IO = 0x00008000UL;
+ PCIBIOS_MIN_MEM = 0x01000000UL;
+
+ /* Set I/O resource limits. */
+ ioport_resource.end = 0x01ffffffUL; /* 32MB accessible by sb1250 */
+ iomem_resource.end = 0xffffffffUL; /* no HT support yet */
+
+ cfg_space =
+ ioremap(A_PHYS_LDTPCI_CFG_MATCH_BITS, 16 * 1024 * 1024);
+
+ /*
+ * See if the PCI bus has been configured by the firmware.
+ */
+ reg = *((volatile uint64_t *) IOADDR(A_SCD_SYSTEM_CFG));
+ if (!(reg & M_SYS_PCI_HOST)) {
+ sb1250_bus_status |= PCI_DEVICE_MODE;
+ } else {
+ cmdreg =
+ READCFG32(CFGOFFSET
+ (0, PCI_DEVFN(PCI_BRIDGE_DEVICE, 0),
+ PCI_COMMAND));
+ if (!(cmdreg & PCI_COMMAND_MASTER)) {
+ printk
+ ("PCI: Skipping PCI probe. Bus is not initialized.\n");
+ iounmap(cfg_space);
+ return 0;
+ }
+ sb1250_bus_status |= PCI_BUS_ENABLED;
+ }
+
+ /*
+ * Establish mappings in KSEG2 (kernel virtual) to PCI I/O
+ * space. Use "match bytes" policy to make everything look
+ * little-endian. So, you need to also set
+ * CONFIG_SWAP_IO_SPACE, but this is the combination that
+ * works correctly with most of Linux's drivers.
+ * XXX ehs: Should this happen in PCI Device mode?
+ */
+
+ set_io_port_base((unsigned long)
+ ioremap(A_PHYS_LDTPCI_IO_MATCH_BYTES, 65536));
+ isa_slot_offset = (unsigned long)
+ ioremap(A_PHYS_LDTPCI_IO_MATCH_BYTES_32, 1024 * 1024);
+
+#ifdef CONFIG_SIBYTE_HAS_LDT
+ /*
+ * Also check the LDT bridge's enable, just in case we didn't
+ * initialize that one.
+ */
+
+ cmdreg = READCFG32(CFGOFFSET(0, PCI_DEVFN(LDT_BRIDGE_DEVICE, 0),
+ PCI_COMMAND));
+ if (cmdreg & PCI_COMMAND_MASTER) {
+ sb1250_bus_status |= LDT_BUS_ENABLED;
+
+ /*
+ * Need bits 23:16 to convey vector number. Note that
+ * this consumes 4MB of kernel-mapped memory
+ * (Kseg2/Kseg3) for 32-bit kernel.
+ */
+ ldt_eoi_space = (unsigned long)
+ ioremap(A_PHYS_LDT_SPECIAL_MATCH_BYTES,
+ 4 * 1024 * 1024);
+ }
+#endif
+
+ register_pci_controller(&sb1250_controller);
+
+#ifdef CONFIG_VGA_CONSOLE
+ take_over_console(&vga_con, 0, MAX_NR_CONSOLES - 1, 1);
+#endif
+ return 0;
+}
+arch_initcall(sb1250_pcibios_init);
diff --git a/arch/mips/pci/pci-vr41xx.c b/arch/mips/pci/pci-vr41xx.c
new file mode 100644
index 0000000..f3ccbf7
--- /dev/null
+++ b/arch/mips/pci/pci-vr41xx.c
@@ -0,0 +1,291 @@
+/*
+ * pci-vr41xx.c, PCI Control Unit routines for the NEC VR4100 series.
+ *
+ * Copyright (C) 2001-2003 MontaVista Software Inc.
+ * Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com>
+ * Copyright (C) 2004 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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
+ */
+/*
+ * Changes:
+ * MontaVista Software Inc. <yyuasa@mvista.com> or <source@mvista.com>
+ * - New creation, NEC VR4122 and VR4131 are supported.
+ */
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/types.h>
+
+#include <asm/cpu.h>
+#include <asm/io.h>
+#include <asm/vr41xx/vr41xx.h>
+
+#include "pci-vr41xx.h"
+
+extern struct pci_ops vr41xx_pci_ops;
+
+static struct pci_master_address_conversion pci_master_memory1 = {
+ .bus_base_address = PCI_MASTER_MEM1_BUS_BASE_ADDRESS,
+ .address_mask = PCI_MASTER_MEM1_ADDRESS_MASK,
+ .pci_base_address = PCI_MASTER_MEM1_PCI_BASE_ADDRESS,
+};
+
+static struct pci_target_address_conversion pci_target_memory1 = {
+ .address_mask = PCI_TARGET_MEM1_ADDRESS_MASK,
+ .bus_base_address = PCI_TARGET_MEM1_BUS_BASE_ADDRESS,
+};
+
+static struct pci_master_address_conversion pci_master_io = {
+ .bus_base_address = PCI_MASTER_IO_BUS_BASE_ADDRESS,
+ .address_mask = PCI_MASTER_IO_ADDRESS_MASK,
+ .pci_base_address = PCI_MASTER_IO_PCI_BASE_ADDRESS,
+};
+
+static struct pci_mailbox_address pci_mailbox = {
+ .base_address = PCI_MAILBOX_BASE_ADDRESS,
+};
+
+static struct pci_target_address_window pci_target_window1 = {
+ .base_address = PCI_TARGET_WINDOW1_BASE_ADDRESS,
+};
+
+static struct resource pci_mem_resource = {
+ .name = "PCI Memory resources",
+ .start = PCI_MEM_RESOURCE_START,
+ .end = PCI_MEM_RESOURCE_END,
+ .flags = IORESOURCE_MEM,
+};
+
+static struct resource pci_io_resource = {
+ .name = "PCI I/O resources",
+ .start = PCI_IO_RESOURCE_START,
+ .end = PCI_IO_RESOURCE_END,
+ .flags = IORESOURCE_IO,
+};
+
+static struct pci_controller_unit_setup vr41xx_pci_controller_unit_setup = {
+ .master_memory1 = &pci_master_memory1,
+ .target_memory1 = &pci_target_memory1,
+ .master_io = &pci_master_io,
+ .exclusive_access = CANNOT_LOCK_FROM_DEVICE,
+ .wait_time_limit_from_irdy_to_trdy = 0,
+ .mailbox = &pci_mailbox,
+ .target_window1 = &pci_target_window1,
+ .master_latency_timer = 0x80,
+ .retry_limit = 0,
+ .arbiter_priority_control = PCI_ARBITRATION_MODE_FAIR,
+ .take_away_gnt_mode = PCI_TAKE_AWAY_GNT_DISABLE,
+};
+
+static struct pci_controller vr41xx_pci_controller = {
+ .pci_ops = &vr41xx_pci_ops,
+ .mem_resource = &pci_mem_resource,
+ .io_resource = &pci_io_resource,
+};
+
+void __init vr41xx_pciu_setup(struct pci_controller_unit_setup *setup)
+{
+ vr41xx_pci_controller_unit_setup = *setup;
+}
+
+static int __init vr41xx_pciu_init(void)
+{
+ struct pci_controller_unit_setup *setup;
+ struct pci_master_address_conversion *master;
+ struct pci_target_address_conversion *target;
+ struct pci_mailbox_address *mailbox;
+ struct pci_target_address_window *window;
+ unsigned long vtclock, pci_clock_max;
+ uint32_t val;
+
+ setup = &vr41xx_pci_controller_unit_setup;
+
+ /* Disable PCI interrupt */
+ vr41xx_disable_pciint();
+
+ /* Supply VTClock to PCIU */
+ vr41xx_supply_clock(PCIU_CLOCK);
+
+ /* Dummy write, waiting for supply of VTClock. */
+ vr41xx_disable_pciint();
+
+ /* Select PCI clock */
+ if (setup->pci_clock_max != 0)
+ pci_clock_max = setup->pci_clock_max;
+ else
+ pci_clock_max = PCI_CLOCK_MAX;
+ vtclock = vr41xx_get_vtclock_frequency();
+ if (vtclock < pci_clock_max)
+ writel(EQUAL_VTCLOCK, PCICLKSELREG);
+ else if ((vtclock / 2) < pci_clock_max)
+ writel(HALF_VTCLOCK, PCICLKSELREG);
+ else if (current_cpu_data.processor_id >= PRID_VR4131_REV2_1 &&
+ (vtclock / 3) < pci_clock_max)
+ writel(ONE_THIRD_VTCLOCK, PCICLKSELREG);
+ else if ((vtclock / 4) < pci_clock_max)
+ writel(QUARTER_VTCLOCK, PCICLKSELREG);
+ else {
+ printk(KERN_ERR "PCI Clock is over 33MHz.\n");
+ return -EINVAL;
+ }
+
+ /* Supply PCI clock by PCI bus */
+ vr41xx_supply_clock(PCI_CLOCK);
+
+ if (setup->master_memory1 != NULL) {
+ master = setup->master_memory1;
+ val = IBA(master->bus_base_address) |
+ MASTER_MSK(master->address_mask) |
+ WINEN |
+ PCIA(master->pci_base_address);
+ writel(val, PCIMMAW1REG);
+ } else {
+ val = readl(PCIMMAW1REG);
+ val &= ~WINEN;
+ writel(val, PCIMMAW1REG);
+ }
+
+ if (setup->master_memory2 != NULL) {
+ master = setup->master_memory2;
+ val = IBA(master->bus_base_address) |
+ MASTER_MSK(master->address_mask) |
+ WINEN |
+ PCIA(master->pci_base_address);
+ writel(val, PCIMMAW2REG);
+ } else {
+ val = readl(PCIMMAW2REG);
+ val &= ~WINEN;
+ writel(val, PCIMMAW2REG);
+ }
+
+ if (setup->target_memory1 != NULL) {
+ target = setup->target_memory1;
+ val = TARGET_MSK(target->address_mask) |
+ WINEN |
+ ITA(target->bus_base_address);
+ writel(val, PCITAW1REG);
+ } else {
+ val = readl(PCITAW1REG);
+ val &= ~WINEN;
+ writel(val, PCITAW1REG);
+ }
+
+ if (setup->target_memory2 != NULL) {
+ target = setup->target_memory2;
+ val = TARGET_MSK(target->address_mask) |
+ WINEN |
+ ITA(target->bus_base_address);
+ writel(val, PCITAW2REG);
+ } else {
+ val = readl(PCITAW2REG);
+ val &= ~WINEN;
+ writel(val, PCITAW2REG);
+ }
+
+ if (setup->master_io != NULL) {
+ master = setup->master_io;
+ val = IBA(master->bus_base_address) |
+ MASTER_MSK(master->address_mask) |
+ WINEN |
+ PCIIA(master->pci_base_address);
+ writel(val, PCIMIOAWREG);
+ } else {
+ val = readl(PCIMIOAWREG);
+ val &= ~WINEN;
+ writel(val, PCIMIOAWREG);
+ }
+
+ if (setup->exclusive_access == CANNOT_LOCK_FROM_DEVICE)
+ writel(UNLOCK, PCIEXACCREG);
+ else
+ writel(0, PCIEXACCREG);
+
+ if (current_cpu_data.cputype == CPU_VR4122)
+ writel(TRDYV(setup->wait_time_limit_from_irdy_to_trdy), PCITRDYVREG);
+
+ writel(MLTIM(setup->master_latency_timer), LATTIMEREG);
+
+ if (setup->mailbox != NULL) {
+ mailbox = setup->mailbox;
+ val = MBADD(mailbox->base_address) | TYPE_32BITSPACE |
+ MSI_MEMORY | PREF_APPROVAL;
+ writel(val, MAILBAREG);
+ }
+
+ if (setup->target_window1) {
+ window = setup->target_window1;
+ val = PMBA(window->base_address) | TYPE_32BITSPACE |
+ MSI_MEMORY | PREF_APPROVAL;
+ writel(val, PCIMBA1REG);
+ }
+
+ if (setup->target_window2) {
+ window = setup->target_window2;
+ val = PMBA(window->base_address) | TYPE_32BITSPACE |
+ MSI_MEMORY | PREF_APPROVAL;
+ writel(val, PCIMBA2REG);
+ }
+
+ val = readl(RETVALREG);
+ val &= ~RTYVAL_MASK;
+ val |= RTYVAL(setup->retry_limit);
+ writel(val, RETVALREG);
+
+ val = readl(PCIAPCNTREG);
+ val &= ~(TKYGNT | PAPC);
+
+ switch (setup->arbiter_priority_control) {
+ case PCI_ARBITRATION_MODE_ALTERNATE_0:
+ val |= PAPC_ALTERNATE_0;
+ break;
+ case PCI_ARBITRATION_MODE_ALTERNATE_B:
+ val |= PAPC_ALTERNATE_B;
+ break;
+ default:
+ val |= PAPC_FAIR;
+ break;
+ }
+
+ if (setup->take_away_gnt_mode == PCI_TAKE_AWAY_GNT_ENABLE)
+ val |= TKYGNT_ENABLE;
+
+ writel(val, PCIAPCNTREG);
+
+ writel(PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER |
+ PCI_COMMAND_PARITY | PCI_COMMAND_SERR, COMMANDREG);
+
+ /* Clear bus error */
+ readl(BUSERRADREG);
+
+ writel(BLOODY_CONFIG_DONE, PCIENREG);
+
+ if (setup->mem_resource != NULL)
+ vr41xx_pci_controller.mem_resource = setup->mem_resource;
+
+ if (setup->io_resource != NULL) {
+ vr41xx_pci_controller.io_resource = setup->io_resource;
+ } else {
+ set_io_port_base(IO_PORT_BASE);
+ ioport_resource.start = IO_PORT_RESOURCE_START;
+ ioport_resource.end = IO_PORT_RESOURCE_END;
+ }
+
+ register_pci_controller(&vr41xx_pci_controller);
+
+ return 0;
+}
+
+arch_initcall(vr41xx_pciu_init);
diff --git a/arch/mips/pci/pci-vr41xx.h b/arch/mips/pci/pci-vr41xx.h
new file mode 100644
index 0000000..23815c8
--- /dev/null
+++ b/arch/mips/pci/pci-vr41xx.h
@@ -0,0 +1,151 @@
+/*
+ * pci-vr41xx.h, Include file for PCI Control Unit of the NEC VR4100 series.
+ *
+ * Copyright (C) 2002 MontaVista Software Inc.
+ * Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com>
+ * Copyright (C) 2004 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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
+ */
+#ifndef __PCI_VR41XX_H
+#define __PCI_VR41XX_H
+
+#define PCIMMAW1REG KSEG1ADDR(0x0f000c00)
+#define PCIMMAW2REG KSEG1ADDR(0x0f000c04)
+#define PCITAW1REG KSEG1ADDR(0x0f000c08)
+#define PCITAW2REG KSEG1ADDR(0x0f000c0c)
+#define PCIMIOAWREG KSEG1ADDR(0x0f000c10)
+ #define IBA(addr) ((addr) & 0xff000000U)
+ #define MASTER_MSK(mask) (((mask) >> 11) & 0x000fe000U)
+ #define PCIA(addr) (((addr) >> 24) & 0x000000ffU)
+ #define TARGET_MSK(mask) (((mask) >> 8) & 0x000fe000U)
+ #define ITA(addr) (((addr) >> 24) & 0x000000ffU)
+ #define PCIIA(addr) (((addr) >> 24) & 0x000000ffU)
+ #define WINEN 0x1000U
+#define PCICONFDREG KSEG1ADDR(0x0f000c14)
+#define PCICONFAREG KSEG1ADDR(0x0f000c18)
+#define PCIMAILREG KSEG1ADDR(0x0f000c1c)
+#define BUSERRADREG KSEG1ADDR(0x0f000c24)
+ #define EA(reg) ((reg) &0xfffffffc)
+
+#define INTCNTSTAREG KSEG1ADDR(0x0f000c28)
+ #define MABTCLR 0x80000000U
+ #define TRDYCLR 0x40000000U
+ #define PARCLR 0x20000000U
+ #define MBCLR 0x10000000U
+ #define SERRCLR 0x08000000U
+ #define RTYCLR 0x04000000U
+ #define MABCLR 0x02000000U
+ #define TABCLR 0x01000000U
+ /* RFU */
+ #define MABTMSK 0x00008000U
+ #define TRDYMSK 0x00004000U
+ #define PARMSK 0x00002000U
+ #define MBMSK 0x00001000U
+ #define SERRMSK 0x00000800U
+ #define RTYMSK 0x00000400U
+ #define MABMSK 0x00000200U
+ #define TABMSK 0x00000100U
+ #define IBAMABT 0x00000080U
+ #define TRDYRCH 0x00000040U
+ #define PAR 0x00000020U
+ #define MB 0x00000010U
+ #define PCISERR 0x00000008U
+ #define RTYRCH 0x00000004U
+ #define MABORT 0x00000002U
+ #define TABORT 0x00000001U
+
+#define PCIEXACCREG KSEG1ADDR(0x0f000c2c)
+ #define UNLOCK 0x2U
+ #define EAREQ 0x1U
+#define PCIRECONTREG KSEG1ADDR(0x0f000c30)
+ #define RTRYCNT(reg) ((reg) & 0x000000ffU)
+#define PCIENREG KSEG1ADDR(0x0f000c34)
+ #define BLOODY_CONFIG_DONE 0x4U
+#define PCICLKSELREG KSEG1ADDR(0x0f000c38)
+ #define EQUAL_VTCLOCK 0x2U
+ #define HALF_VTCLOCK 0x0U
+ #define ONE_THIRD_VTCLOCK 0x3U
+ #define QUARTER_VTCLOCK 0x1U
+#define PCITRDYVREG KSEG1ADDR(0x0f000c3c)
+ #define TRDYV(val) ((uint32_t)(val) & 0xffU)
+#define PCICLKRUNREG KSEG1ADDR(0x0f000c60)
+
+#define VENDORIDREG KSEG1ADDR(0x0f000d00)
+#define DEVICEIDREG KSEG1ADDR(0x0f000d00)
+#define COMMANDREG KSEG1ADDR(0x0f000d04)
+#define STATUSREG KSEG1ADDR(0x0f000d04)
+#define REVIDREG KSEG1ADDR(0x0f000d08)
+#define CLASSREG KSEG1ADDR(0x0f000d08)
+#define CACHELSREG KSEG1ADDR(0x0f000d0c)
+#define LATTIMEREG KSEG1ADDR(0x0f000d0c)
+ #define MLTIM(val) (((uint32_t)(val) << 7) & 0xff00U)
+#define MAILBAREG KSEG1ADDR(0x0f000d10)
+#define PCIMBA1REG KSEG1ADDR(0x0f000d14)
+#define PCIMBA2REG KSEG1ADDR(0x0f000d18)
+ #define MBADD(base) ((base) & 0xfffff800U)
+ #define PMBA(base) ((base) & 0xffe00000U)
+ #define PREF 0x8U
+ #define PREF_APPROVAL 0x8U
+ #define PREF_DISAPPROVAL 0x0U
+ #define TYPE 0x6U
+ #define TYPE_32BITSPACE 0x0U
+ #define MSI 0x1U
+ #define MSI_MEMORY 0x0U
+#define INTLINEREG KSEG1ADDR(0x0f000d3c)
+#define INTPINREG KSEG1ADDR(0x0f000d3c)
+#define RETVALREG KSEG1ADDR(0x0f000d40)
+#define PCIAPCNTREG KSEG1ADDR(0x0f000d40)
+ #define TKYGNT 0x04000000U
+ #define TKYGNT_ENABLE 0x04000000U
+ #define TKYGNT_DISABLE 0x00000000U
+ #define PAPC 0x03000000U
+ #define PAPC_ALTERNATE_B 0x02000000U
+ #define PAPC_ALTERNATE_0 0x01000000U
+ #define PAPC_FAIR 0x00000000U
+ #define RTYVAL(val) (((uint32_t)(val) << 7) & 0xff00U)
+ #define RTYVAL_MASK 0xff00U
+
+#define PCI_CLOCK_MAX 33333333U
+
+/*
+ * Default setup
+ */
+#define PCI_MASTER_MEM1_BUS_BASE_ADDRESS 0x10000000U
+#define PCI_MASTER_MEM1_ADDRESS_MASK 0x7c000000U
+#define PCI_MASTER_MEM1_PCI_BASE_ADDRESS 0x10000000U
+
+#define PCI_TARGET_MEM1_ADDRESS_MASK 0x08000000U
+#define PCI_TARGET_MEM1_BUS_BASE_ADDRESS 0x00000000U
+
+#define PCI_MASTER_IO_BUS_BASE_ADDRESS 0x16000000U
+#define PCI_MASTER_IO_ADDRESS_MASK 0x7e000000U
+#define PCI_MASTER_IO_PCI_BASE_ADDRESS 0x00000000U
+
+#define PCI_MAILBOX_BASE_ADDRESS 0x00000000U
+
+#define PCI_TARGET_WINDOW1_BASE_ADDRESS 0x00000000U
+
+#define IO_PORT_BASE KSEG1ADDR(PCI_MASTER_IO_BUS_BASE_ADDRESS)
+#define IO_PORT_RESOURCE_START PCI_MASTER_IO_PCI_BASE_ADDRESS
+#define IO_PORT_RESOURCE_END (~PCI_MASTER_IO_ADDRESS_MASK & PCI_MASTER_ADDRESS_MASK)
+
+#define PCI_IO_RESOURCE_START 0x01000000UL
+#define PCI_IO_RESOURCE_END 0x01ffffffUL
+
+#define PCI_MEM_RESOURCE_START 0x11000000UL
+#define PCI_MEM_RESOURCE_END 0x13ffffffUL
+
+#endif /* __PCI_VR41XX_H */
diff --git a/arch/mips/pci/pci-yosemite.c b/arch/mips/pci/pci-yosemite.c
new file mode 100644
index 0000000..dac9ed4
--- /dev/null
+++ b/arch/mips/pci/pci-yosemite.c
@@ -0,0 +1,60 @@
+/*
+ * 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) 2004 by Ralf Baechle (ralf@linux-mips.org)
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <asm/titan_dep.h>
+
+extern struct pci_ops titan_pci_ops;
+
+static struct resource py_mem_resource = {
+ "Titan PCI MEM", 0xe0000000UL, 0xe3ffffffUL, IORESOURCE_MEM
+};
+
+/*
+ * PMON really reserves 16MB of I/O port space but that's stupid, nothing
+ * needs that much since allocations are limited to 256 bytes per device
+ * anyway. So we just claim 64kB here.
+ */
+#define TITAN_IO_SIZE 0x0000ffffUL
+#define TITAN_IO_BASE 0xe8000000UL
+
+static struct resource py_io_resource = {
+ "Titan IO MEM", 0x00001000UL, TITAN_IO_SIZE - 1, IORESOURCE_IO,
+};
+
+static struct pci_controller py_controller = {
+ .pci_ops = &titan_pci_ops,
+ .mem_resource = &py_mem_resource,
+ .mem_offset = 0x00000000UL,
+ .io_resource = &py_io_resource,
+ .io_offset = 0x00000000UL
+};
+
+static char ioremap_failed[] __initdata = "Could not ioremap I/O port range";
+
+static int __init pmc_yosemite_setup(void)
+{
+ unsigned long io_v_base;
+
+ io_v_base = (unsigned long) ioremap(TITAN_IO_BASE, TITAN_IO_SIZE);
+ if (!io_v_base)
+ panic(ioremap_failed);
+
+ set_io_port_base(io_v_base);
+ TITAN_WRITE(RM9000x2_OCD_LKM7, TITAN_READ(RM9000x2_OCD_LKM7) | 1);
+
+ ioport_resource.end = TITAN_IO_SIZE - 1;
+
+ register_pci_controller(&py_controller);
+
+ return 0;
+}
+
+arch_initcall(pmc_yosemite_setup);
diff --git a/arch/mips/pci/pci.c b/arch/mips/pci/pci.c
new file mode 100644
index 0000000..8141dff
--- /dev/null
+++ b/arch/mips/pci/pci.c
@@ -0,0 +1,304 @@
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * Copyright (C) 2003, 04 Ralf Baechle (ralf@linux-mips.org)
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/bootmem.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+
+/*
+ * Indicate whether we respect the PCI setup left by the firmware.
+ *
+ * Make this long-lived so that we know when shutting down
+ * whether we probed only or not.
+ */
+int pci_probe_only;
+
+#define PCI_ASSIGN_ALL_BUSSES 1
+
+unsigned int pci_probe = PCI_ASSIGN_ALL_BUSSES;
+
+/*
+ * The PCI controller list.
+ */
+
+struct pci_controller *hose_head, **hose_tail = &hose_head;
+struct pci_controller *pci_isa_hose;
+
+unsigned long PCIBIOS_MIN_IO = 0x0000;
+unsigned long PCIBIOS_MIN_MEM = 0;
+
+/*
+ * We need to avoid collisions with `mirrored' VGA ports
+ * and other strange ISA hardware, so we always want the
+ * addresses to be allocated in the 0x000-0x0ff region
+ * modulo 0x400.
+ *
+ * Why? Because some silly external IO cards only decode
+ * the low 10 bits of the IO address. The 0x00-0xff region
+ * is reserved for motherboard devices that decode all 16
+ * bits, so it's ok to allocate at, say, 0x2800-0x28ff,
+ * but we want to try to avoid allocating at 0x2900-0x2bff
+ * which might have be mirrored at 0x0100-0x03ff..
+ */
+void
+pcibios_align_resource(void *data, struct resource *res,
+ unsigned long size, unsigned long align)
+{
+ struct pci_dev *dev = data;
+ struct pci_controller *hose = dev->sysdata;
+ unsigned long start = res->start;
+
+ if (res->flags & IORESOURCE_IO) {
+ /* Make sure we start at our min on all hoses */
+ if (start < PCIBIOS_MIN_IO + hose->io_resource->start)
+ start = PCIBIOS_MIN_IO + hose->io_resource->start;
+
+ /*
+ * Put everything into 0x00-0xff region modulo 0x400
+ */
+ if (start & 0x300)
+ start = (start + 0x3ff) & ~0x3ff;
+ } else if (res->flags & IORESOURCE_MEM) {
+ /* Make sure we start at our min on all hoses */
+ if (start < PCIBIOS_MIN_MEM + hose->mem_resource->start)
+ start = PCIBIOS_MIN_MEM + hose->mem_resource->start;
+ }
+
+ res->start = start;
+}
+
+struct pci_controller * __init alloc_pci_controller(void)
+{
+ return alloc_bootmem(sizeof(struct pci_controller));
+}
+
+void __init register_pci_controller(struct pci_controller *hose)
+{
+ *hose_tail = hose;
+ hose_tail = &hose->next;
+}
+
+/* Most MIPS systems have straight-forward swizzling needs. */
+
+static inline u8 bridge_swizzle(u8 pin, u8 slot)
+{
+ return (((pin - 1) + slot) % 4) + 1;
+}
+
+static u8 __init common_swizzle(struct pci_dev *dev, u8 *pinp)
+{
+ u8 pin = *pinp;
+
+ while (dev->bus->parent) {
+ pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn));
+ /* Move up the chain of bridges. */
+ dev = dev->bus->self;
+ }
+ *pinp = pin;
+
+ /* The slot is the slot of the last bridge. */
+ return PCI_SLOT(dev->devfn);
+}
+
+static int __init pcibios_init(void)
+{
+ struct pci_controller *hose;
+ struct pci_bus *bus;
+ int next_busno;
+ int need_domain_info = 0;
+
+ /* Scan all of the recorded PCI controllers. */
+ for (next_busno = 0, hose = hose_head; hose; hose = hose->next) {
+
+ if (request_resource(&iomem_resource, hose->mem_resource) < 0)
+ goto out;
+ if (request_resource(&ioport_resource, hose->io_resource) < 0)
+ goto out_free_mem_resource;
+
+ if (!hose->iommu)
+ PCI_DMA_BUS_IS_PHYS = 1;
+
+ bus = pci_scan_bus(next_busno, hose->pci_ops, hose);
+ hose->bus = bus;
+ hose->need_domain_info = need_domain_info;
+ next_busno = bus->subordinate + 1;
+ /* Don't allow 8-bit bus number overflow inside the hose -
+ reserve some space for bridges. */
+ if (next_busno > 224) {
+ next_busno = 0;
+ need_domain_info = 1;
+ }
+ continue;
+
+out_free_mem_resource:
+ release_resource(hose->mem_resource);
+
+out:
+ printk(KERN_WARNING
+ "Skipping PCI bus scan due to resource conflict\n");
+ }
+
+ if (!pci_probe_only)
+ pci_assign_unassigned_resources();
+ pci_fixup_irqs(common_swizzle, pcibios_map_irq);
+
+ return 0;
+}
+
+subsys_initcall(pcibios_init);
+
+static int pcibios_enable_resources(struct pci_dev *dev, int mask)
+{
+ u16 cmd, old_cmd;
+ int idx;
+ struct resource *r;
+
+ pci_read_config_word(dev, PCI_COMMAND, &cmd);
+ old_cmd = cmd;
+ for(idx=0; idx<6; idx++) {
+ /* Only set up the requested stuff */
+ if (!(mask & (1<<idx)))
+ continue;
+
+ r = &dev->resource[idx];
+ if (!r->start && r->end) {
+ printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", pci_name(dev));
+ return -EINVAL;
+ }
+ if (r->flags & IORESOURCE_IO)
+ cmd |= PCI_COMMAND_IO;
+ if (r->flags & IORESOURCE_MEM)
+ cmd |= PCI_COMMAND_MEMORY;
+ }
+ if (dev->resource[PCI_ROM_RESOURCE].start)
+ cmd |= PCI_COMMAND_MEMORY;
+ if (cmd != old_cmd) {
+ printk("PCI: Enabling device %s (%04x -> %04x)\n", pci_name(dev), old_cmd, cmd);
+ pci_write_config_word(dev, PCI_COMMAND, cmd);
+ }
+ return 0;
+}
+
+/*
+ * If we set up a device for bus mastering, we need to check the latency
+ * timer as certain crappy BIOSes forget to set it properly.
+ */
+unsigned int pcibios_max_latency = 255;
+
+void pcibios_set_master(struct pci_dev *dev)
+{
+ u8 lat;
+ pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
+ if (lat < 16)
+ lat = (64 <= pcibios_max_latency) ? 64 : pcibios_max_latency;
+ else if (lat > pcibios_max_latency)
+ lat = pcibios_max_latency;
+ else
+ return;
+ printk(KERN_DEBUG "PCI: Setting latency timer of device %s to %d\n",
+ pci_name(dev), lat);
+ pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat);
+}
+
+unsigned int pcibios_assign_all_busses(void)
+{
+ return (pci_probe & PCI_ASSIGN_ALL_BUSSES) ? 1 : 0;
+}
+
+int pcibios_enable_device(struct pci_dev *dev, int mask)
+{
+ int err;
+
+ if ((err = pcibios_enable_resources(dev, mask)) < 0)
+ return err;
+
+ return pcibios_plat_dev_init(dev);
+}
+
+static void __init pcibios_fixup_device_resources(struct pci_dev *dev,
+ struct pci_bus *bus)
+{
+ /* Update device resources. */
+ struct pci_controller *hose = (struct pci_controller *)bus->sysdata;
+ unsigned long offset = 0;
+ int i;
+
+ for (i = 0; i < PCI_NUM_RESOURCES; i++) {
+ if (!dev->resource[i].start)
+ continue;
+ if (dev->resource[i].flags & IORESOURCE_IO)
+ offset = hose->io_offset;
+ else if (dev->resource[i].flags & IORESOURCE_MEM)
+ offset = hose->mem_offset;
+
+ dev->resource[i].start += offset;
+ dev->resource[i].end += offset;
+ }
+}
+
+void __devinit pcibios_fixup_bus(struct pci_bus *bus)
+{
+ /* Propagate hose info into the subordinate devices. */
+
+ struct pci_controller *hose = bus->sysdata;
+ struct list_head *ln;
+ struct pci_dev *dev = bus->self;
+
+ if (!dev) {
+ bus->resource[0] = hose->io_resource;
+ bus->resource[1] = hose->mem_resource;
+ } else if (pci_probe_only &&
+ (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
+ pci_read_bridge_bases(bus);
+ pcibios_fixup_device_resources(dev, bus);
+ }
+
+ for (ln = bus->devices.next; ln != &bus->devices; ln = ln->next) {
+ struct pci_dev *dev = pci_dev_b(ln);
+
+ if ((dev->class >> 8) != PCI_CLASS_BRIDGE_PCI)
+ pcibios_fixup_device_resources(dev, bus);
+ }
+}
+
+void __init
+pcibios_update_irq(struct pci_dev *dev, int irq)
+{
+ pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
+}
+
+void __devinit
+pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
+ struct resource *res)
+{
+ struct pci_controller *hose = (struct pci_controller *)dev->sysdata;
+ unsigned long offset = 0;
+
+ if (res->flags & IORESOURCE_IO)
+ offset = hose->io_offset;
+ else if (res->flags & IORESOURCE_MEM)
+ offset = hose->mem_offset;
+
+ region->start = res->start - offset;
+ region->end = res->end - offset;
+}
+
+#ifdef CONFIG_HOTPLUG
+EXPORT_SYMBOL(pcibios_resource_to_bus);
+EXPORT_SYMBOL(PCIBIOS_MIN_IO);
+EXPORT_SYMBOL(PCIBIOS_MIN_MEM);
+#endif
+
+char *pcibios_setup(char *str)
+{
+ return str;
+}
diff --git a/arch/mips/pmc-sierra/yosemite/Makefile b/arch/mips/pmc-sierra/yosemite/Makefile
new file mode 100644
index 0000000..ae96a71
--- /dev/null
+++ b/arch/mips/pmc-sierra/yosemite/Makefile
@@ -0,0 +1,8 @@
+#
+# Makefile for the PMC-Sierra Titan
+#
+
+obj-y += irq-handler.o irq.o i2c-yosemite.o prom.o py-console.o setup.o
+
+obj-$(CONFIG_KGDB) += dbg_io.o
+obj-$(CONFIG_SMP) += smp.o
diff --git a/arch/mips/pmc-sierra/yosemite/atmel_read_eeprom.c b/arch/mips/pmc-sierra/yosemite/atmel_read_eeprom.c
new file mode 100644
index 0000000..b067988
--- /dev/null
+++ b/arch/mips/pmc-sierra/yosemite/atmel_read_eeprom.c
@@ -0,0 +1,171 @@
+/*
+ * arch/mips/pmc-sierra/yosemite/atmel_read_eeprom.c
+ *
+ * Copyright (C) 2003 PMC-Sierra Inc.
+ * Author: Manish Lachwani (lachwani@pmc-sierra.com)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * Description:
+ *
+ * This code reads the ATMEL 24CXX EEPROM. The PMC-Sierra Yosemite board uses the ATMEL
+ * 24C32/24C64 which uses two byte addressing as compared to 24C16. Note that this program
+ * uses the serial port like /dev/ttyS0, to communicate with the EEPROM. Hence, you are
+ * expected to have a connectivity from the EEPROM to the serial port. This program does
+ * __not__ communicate using the I2C protocol
+ */
+
+#include "atmel_read_eeprom.h"
+
+static void delay(int delay)
+{
+ while (delay--);
+}
+
+static void send_bit(unsigned char bit)
+{
+ scl_lo;
+ delay(TXX);
+ if (bit)
+ sda_hi;
+ else
+ sda_lo;
+
+ delay(TXX);
+ scl_hi;
+ delay(TXX);
+}
+
+static void send_ack(void)
+{
+ send_bit(0);
+}
+
+static void send_byte(unsigned char byte)
+{
+ int i = 0;
+
+ for (i = 7; i >= 0; i--)
+ send_bit((byte >> i) & 0x01);
+}
+
+static void send_start(void)
+{
+ sda_hi;
+ delay(TXX);
+ scl_hi;
+ delay(TXX);
+ sda_lo;
+ delay(TXX);
+}
+
+static void send_stop(void)
+{
+ sda_lo;
+ delay(TXX);
+ scl_hi;
+ delay(TXX);
+ sda_hi;
+ delay(TXX);
+}
+
+static void do_idle(void)
+{
+ sda_hi;
+ scl_hi;
+ vcc_off;
+}
+
+static int recv_bit(void)
+{
+ int status;
+
+ scl_lo;
+ delay(TXX);
+ sda_hi;
+ delay(TXX);
+ scl_hi;
+ delay(TXX);
+
+ return 1;
+}
+
+static unsigned char recv_byte(void) {
+ int i;
+ unsigned char byte=0;
+
+ for (i=7;i>=0;i--)
+ byte |= (recv_bit() << i);
+
+ return byte;
+}
+
+static int recv_ack(void)
+{
+ unsigned int ack;
+
+ ack = (unsigned int)recv_bit();
+ scl_lo;
+
+ if (ack) {
+ do_idle();
+ printk(KERN_ERR "Error reading the Atmel 24C32/24C64 EEPROM \n");
+ return -1;
+ }
+
+ return ack;
+}
+
+/*
+ * This function does the actual read of the EEPROM. It needs the buffer into which the
+ * read data is copied, the size of the EEPROM being read and the buffer size
+ */
+int read_eeprom(char *buffer, int eeprom_size, int size)
+{
+ int i = 0, err;
+
+ send_start();
+ send_byte(W_HEADER);
+ recv_ack();
+
+ /* EEPROM with size of more then 2K need two byte addressing */
+ if (eeprom_size > 2048) {
+ send_byte(0x00);
+ recv_ack();
+ }
+
+ send_start();
+ send_byte(R_HEADER);
+ err = recv_ack();
+ if (err == -1)
+ return err;
+
+ for (i = 0; i < size; i++) {
+ *buffer++ = recv_byte();
+ send_ack();
+ }
+
+ /* Note : We should do some check if the buffer contains correct information */
+
+ send_stop();
+}
diff --git a/arch/mips/pmc-sierra/yosemite/atmel_read_eeprom.h b/arch/mips/pmc-sierra/yosemite/atmel_read_eeprom.h
new file mode 100644
index 0000000..d27566d
--- /dev/null
+++ b/arch/mips/pmc-sierra/yosemite/atmel_read_eeprom.h
@@ -0,0 +1,69 @@
+/*
+ * arch/mips/pmc-sierra/yosemite/atmel_read_eeprom.c
+ *
+ * Copyright (C) 2003 PMC-Sierra Inc.
+ * Author: Manish Lachwani (lachwani@pmc-sierra.com)
+ * Copyright (C) 2005 Ralf Baechle (ralf@linux-mips.org)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * Header file for atmel_read_eeprom.c
+ */
+
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/version.h>
+#include <asm/pci.h>
+#include <asm/io.h>
+#include <linux/init.h>
+#include <asm/termios.h>
+#include <asm/ioctls.h>
+#include <linux/ioctl.h>
+#include <linux/fcntl.h>
+
+#define DEFAULT_PORT "/dev/ttyS0" /* Port to open */
+#define TXX 0 /* Dummy loop for spinning */
+
+#define BLOCK_SEL 0x00
+#define SLAVE_ADDR 0xa0
+#define READ_BIT 0x01
+#define WRITE_BIT 0x00
+#define R_HEADER SLAVE_ADDR + BLOCK_SEL + READ_BIT
+#define W_HEADER SLAVE_ADDR + BLOCK_SEL + WRITE_BIT
+
+/*
+ * Clock, Voltages and Data
+ */
+#define vcc_off (ioctl(fd, TIOCSBRK, 0))
+#define vcc_on (ioctl(fd, TIOCCBRK, 0))
+#define sda_hi (ioctl(fd, TIOCMBIS, &dtr))
+#define sda_lo (ioctl(fd, TIOCMBIC, &dtr))
+#define scl_lo (ioctl(fd, TIOCMBIC, &rts))
+#define scl_hi (ioctl(fd, TIOCMBIS, &rts))
+
+const char rts = TIOCM_RTS;
+const char dtr = TIOCM_DTR;
+int fd;
+
diff --git a/arch/mips/pmc-sierra/yosemite/dbg_io.c b/arch/mips/pmc-sierra/yosemite/dbg_io.c
new file mode 100644
index 0000000..0f659c9
--- /dev/null
+++ b/arch/mips/pmc-sierra/yosemite/dbg_io.c
@@ -0,0 +1,180 @@
+/*
+ * Copyright 2003 PMC-Sierra
+ * Author: Manish Lachwani (lachwani@pmc-sierra.com)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * Support for KGDB for the Yosemite board. We make use of single serial
+ * port to be used for KGDB as well as console. The second serial port
+ * seems to be having a problem. Single IRQ is allocated for both the
+ * ports. Hence, the interrupt routing code needs to figure out whether
+ * the interrupt came from channel A or B.
+ */
+
+#include <asm/serial.h>
+
+/*
+ * Baud rate, Parity, Data and Stop bit settings for the
+ * serial port on the Yosemite. Note that the Early printk
+ * patch has been added. So, we should be all set to go
+ */
+#define YOSEMITE_BAUD_2400 2400
+#define YOSEMITE_BAUD_4800 4800
+#define YOSEMITE_BAUD_9600 9600
+#define YOSEMITE_BAUD_19200 19200
+#define YOSEMITE_BAUD_38400 38400
+#define YOSEMITE_BAUD_57600 57600
+#define YOSEMITE_BAUD_115200 115200
+
+#define YOSEMITE_PARITY_NONE 0
+#define YOSEMITE_PARITY_ODD 0x08
+#define YOSEMITE_PARITY_EVEN 0x18
+#define YOSEMITE_PARITY_MARK 0x28
+#define YOSEMITE_PARITY_SPACE 0x38
+
+#define YOSEMITE_DATA_5BIT 0x0
+#define YOSEMITE_DATA_6BIT 0x1
+#define YOSEMITE_DATA_7BIT 0x2
+#define YOSEMITE_DATA_8BIT 0x3
+
+#define YOSEMITE_STOP_1BIT 0x0
+#define YOSEMITE_STOP_2BIT 0x4
+
+/* This is crucial */
+#define SERIAL_REG_OFS 0x1
+
+#define SERIAL_RCV_BUFFER 0x0
+#define SERIAL_TRANS_HOLD 0x0
+#define SERIAL_SEND_BUFFER 0x0
+#define SERIAL_INTR_ENABLE (1 * SERIAL_REG_OFS)
+#define SERIAL_INTR_ID (2 * SERIAL_REG_OFS)
+#define SERIAL_DATA_FORMAT (3 * SERIAL_REG_OFS)
+#define SERIAL_LINE_CONTROL (3 * SERIAL_REG_OFS)
+#define SERIAL_MODEM_CONTROL (4 * SERIAL_REG_OFS)
+#define SERIAL_RS232_OUTPUT (4 * SERIAL_REG_OFS)
+#define SERIAL_LINE_STATUS (5 * SERIAL_REG_OFS)
+#define SERIAL_MODEM_STATUS (6 * SERIAL_REG_OFS)
+#define SERIAL_RS232_INPUT (6 * SERIAL_REG_OFS)
+#define SERIAL_SCRATCH_PAD (7 * SERIAL_REG_OFS)
+
+#define SERIAL_DIVISOR_LSB (0 * SERIAL_REG_OFS)
+#define SERIAL_DIVISOR_MSB (1 * SERIAL_REG_OFS)
+
+/*
+ * Functions to READ and WRITE to serial port 0
+ */
+#define SERIAL_READ(ofs) (*((volatile unsigned char*) \
+ (TITAN_SERIAL_BASE + ofs)))
+
+#define SERIAL_WRITE(ofs, val) ((*((volatile unsigned char*) \
+ (TITAN_SERIAL_BASE + ofs))) = val)
+
+/*
+ * Functions to READ and WRITE to serial port 1
+ */
+#define SERIAL_READ_1(ofs) (*((volatile unsigned char*) \
+ (TITAN_SERIAL_BASE_1 + ofs)
+
+#define SERIAL_WRITE_1(ofs, val) ((*((volatile unsigned char*) \
+ (TITAN_SERIAL_BASE_1 + ofs))) = val)
+
+/*
+ * Second serial port initialization
+ */
+void init_second_port(void)
+{
+ /* Disable Interrupts */
+ SERIAL_WRITE_1(SERIAL_LINE_CONTROL, 0x0);
+ SERIAL_WRITE_1(SERIAL_INTR_ENABLE, 0x0);
+
+ {
+ unsigned int divisor;
+
+ SERIAL_WRITE_1(SERIAL_LINE_CONTROL, 0x80);
+ divisor = TITAN_SERIAL_BASE_BAUD / YOSEMITE_BAUD_115200;
+ SERIAL_WRITE_1(SERIAL_DIVISOR_LSB, divisor & 0xff);
+
+ SERIAL_WRITE_1(SERIAL_DIVISOR_MSB,
+ (divisor & 0xff00) >> 8);
+ SERIAL_WRITE_1(SERIAL_LINE_CONTROL, 0x0);
+ }
+
+ SERIAL_WRITE_1(SERIAL_DATA_FORMAT, YOSEMITE_DATA_8BIT |
+ YOSEMITE_PARITY_NONE | YOSEMITE_STOP_1BIT);
+
+ /* Enable Interrupts */
+ SERIAL_WRITE_1(SERIAL_INTR_ENABLE, 0xf);
+}
+
+/* Initialize the serial port for KGDB debugging */
+void debugInit(unsigned int baud, unsigned char data, unsigned char parity,
+ unsigned char stop)
+{
+ /* Disable Interrupts */
+ SERIAL_WRITE(SERIAL_LINE_CONTROL, 0x0);
+ SERIAL_WRITE(SERIAL_INTR_ENABLE, 0x0);
+
+ {
+ unsigned int divisor;
+
+ SERIAL_WRITE(SERIAL_LINE_CONTROL, 0x80);
+
+ divisor = TITAN_SERIAL_BASE_BAUD / baud;
+ SERIAL_WRITE(SERIAL_DIVISOR_LSB, divisor & 0xff);
+
+ SERIAL_WRITE(SERIAL_DIVISOR_MSB, (divisor & 0xff00) >> 8);
+ SERIAL_WRITE(SERIAL_LINE_CONTROL, 0x0);
+ }
+
+ SERIAL_WRITE(SERIAL_DATA_FORMAT, data | parity | stop);
+}
+
+static int remoteDebugInitialized = 0;
+
+unsigned char getDebugChar(void)
+{
+ if (!remoteDebugInitialized) {
+ remoteDebugInitialized = 1;
+ debugInit(YOSEMITE_BAUD_115200,
+ YOSEMITE_DATA_8BIT,
+ YOSEMITE_PARITY_NONE, YOSEMITE_STOP_1BIT);
+ }
+
+ while ((SERIAL_READ(SERIAL_LINE_STATUS) & 0x1) == 0);
+ return SERIAL_READ(SERIAL_RCV_BUFFER);
+}
+
+int putDebugChar(unsigned char byte)
+{
+ if (!remoteDebugInitialized) {
+ remoteDebugInitialized = 1;
+ debugInit(YOSEMITE_BAUD_115200,
+ YOSEMITE_DATA_8BIT,
+ YOSEMITE_PARITY_NONE, YOSEMITE_STOP_1BIT);
+ }
+
+ while ((SERIAL_READ(SERIAL_LINE_STATUS) & 0x20) == 0);
+ SERIAL_WRITE(SERIAL_SEND_BUFFER, byte);
+
+ return 1;
+}
diff --git a/arch/mips/pmc-sierra/yosemite/ht-irq.c b/arch/mips/pmc-sierra/yosemite/ht-irq.c
new file mode 100644
index 0000000..d22c9ff
--- /dev/null
+++ b/arch/mips/pmc-sierra/yosemite/ht-irq.c
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2003 PMC-Sierra
+ * Author: Manish Lachwani (lachwani@pmc-sierra.com)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/version.h>
+#include <linux/init.h>
+#include <asm/pci.h>
+
+/*
+ * HT Bus fixup for the Titan
+ * XXX IRQ values need to change based on the board layout
+ */
+void __init titan_ht_pcibios_fixup_bus(struct pci_bus *bus)
+{
+ struct pci_bus *current_bus = bus;
+ struct pci_dev *devices;
+ struct list_head *devices_link;
+
+ list_for_each(devices_link, &(current_bus->devices)) {
+ devices = pci_dev_b(devices_link);
+ if (devices == NULL)
+ continue;
+ }
+
+ /*
+ * PLX and SPKT related changes go here
+ */
+
+}
diff --git a/arch/mips/pmc-sierra/yosemite/ht.c b/arch/mips/pmc-sierra/yosemite/ht.c
new file mode 100644
index 0000000..dad228d
--- /dev/null
+++ b/arch/mips/pmc-sierra/yosemite/ht.c
@@ -0,0 +1,454 @@
+/*
+ * Copyright 2003 PMC-Sierra
+ * Author: Manish Lachwani (lachwani@pmc-sierra.com)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/version.h>
+#include <asm/pci.h>
+#include <asm/io.h>
+
+#include <linux/init.h>
+#include <asm/titan_dep.h>
+
+#ifdef CONFIG_HYPERTRANSPORT
+
+
+/*
+ * This function check if the Hypertransport Link Initialization completed. If
+ * it did, then proceed further with scanning bus #2
+ */
+static __inline__ int check_titan_htlink(void)
+{
+ u32 val;
+
+ val = *(volatile uint32_t *)(RM9000x2_HTLINK_REG);
+ if (val & 0x00000020)
+ /* HT Link Initialization completed */
+ return 1;
+ else
+ return 0;
+}
+
+static int titan_ht_config_read_dword(struct pci_dev *device,
+ int offset, u32* val)
+{
+ int dev, bus, func;
+ uint32_t address_reg, data_reg;
+ uint32_t address;
+
+ bus = device->bus->number;
+ dev = PCI_SLOT(device->devfn);
+ func = PCI_FUNC(device->devfn);
+
+ /* XXX Need to change the Bus # */
+ if (bus > 2)
+ address = (bus << 16) | (dev << 11) | (func << 8) | (offset & 0xfc) |
+ 0x80000000 | 0x1;
+ else
+ address = (dev << 11) | (func << 8) | (offset & 0xfc) | 0x80000000;
+
+ address_reg = RM9000x2_OCD_HTCFGA;
+ data_reg = RM9000x2_OCD_HTCFGD;
+
+ RM9K_WRITE(address_reg, address);
+ RM9K_READ(data_reg, val);
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+
+static int titan_ht_config_read_word(struct pci_dev *device,
+ int offset, u16* val)
+{
+ int dev, bus, func;
+ uint32_t address_reg, data_reg;
+ uint32_t address;
+
+ bus = device->bus->number;
+ dev = PCI_SLOT(device->devfn);
+ func = PCI_FUNC(device->devfn);
+
+ /* XXX Need to change the Bus # */
+ if (bus > 2)
+ address = (bus << 16) | (dev << 11) | (func << 8) | (offset & 0xfc) |
+ 0x80000000 | 0x1;
+ else
+ address = (dev << 11) | (func << 8) | (offset & 0xfc) | 0x80000000;
+
+ address_reg = RM9000x2_OCD_HTCFGA;
+ data_reg = RM9000x2_OCD_HTCFGD;
+
+ if ((offset & 0x3) == 0)
+ offset = 0x2;
+ else
+ offset = 0x0;
+
+ RM9K_WRITE(address_reg, address);
+ RM9K_READ_16(data_reg + offset, val);
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+
+u32 longswap(unsigned long l)
+{
+ unsigned char b1,b2,b3,b4;
+
+ b1 = l&255;
+ b2 = (l>>8)&255;
+ b3 = (l>>16)&255;
+ b4 = (l>>24)&255;
+
+ return ((b1<<24) + (b2<<16) + (b3<<8) + b4);
+}
+
+
+static int titan_ht_config_read_byte(struct pci_dev *device,
+ int offset, u8* val)
+{
+ int dev, bus, func;
+ uint32_t address_reg, data_reg;
+ uint32_t address;
+ int offset1;
+
+ bus = device->bus->number;
+ dev = PCI_SLOT(device->devfn);
+ func = PCI_FUNC(device->devfn);
+
+ /* XXX Need to change the Bus # */
+ if (bus > 2)
+ address = (bus << 16) | (dev << 11) | (func << 8) | (offset & 0xfc) |
+ 0x80000000 | 0x1;
+ else
+ address = (dev << 11) | (func << 8) | (offset & 0xfc) | 0x80000000;
+
+ address_reg = RM9000x2_OCD_HTCFGA;
+ data_reg = RM9000x2_OCD_HTCFGD;
+
+ RM9K_WRITE(address_reg, address);
+
+ if ((offset & 0x3) == 0) {
+ offset1 = 0x3;
+ }
+ if ((offset & 0x3) == 1) {
+ offset1 = 0x2;
+ }
+ if ((offset & 0x3) == 2) {
+ offset1 = 0x1;
+ }
+ if ((offset & 0x3) == 3) {
+ offset1 = 0x0;
+ }
+ RM9K_READ_8(data_reg + offset1, val);
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+
+static int titan_ht_config_write_dword(struct pci_dev *device,
+ int offset, u8 val)
+{
+ int dev, bus, func;
+ uint32_t address_reg, data_reg;
+ uint32_t address;
+
+ bus = device->bus->number;
+ dev = PCI_SLOT(device->devfn);
+ func = PCI_FUNC(device->devfn);
+
+ /* XXX Need to change the Bus # */
+ if (bus > 2)
+ address = (bus << 16) | (dev << 11) | (func << 8) | (offset & 0xfc) |
+ 0x80000000 | 0x1;
+ else
+ address = (dev << 11) | (func << 8) | (offset & 0xfc) | 0x80000000;
+
+ address_reg = RM9000x2_OCD_HTCFGA;
+ data_reg = RM9000x2_OCD_HTCFGD;
+
+ RM9K_WRITE(address_reg, address);
+ RM9K_WRITE(data_reg, val);
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int titan_ht_config_write_word(struct pci_dev *device,
+ int offset, u8 val)
+{
+ int dev, bus, func;
+ uint32_t address_reg, data_reg;
+ uint32_t address;
+
+ bus = device->bus->number;
+ dev = PCI_SLOT(device->devfn);
+ func = PCI_FUNC(device->devfn);
+
+ /* XXX Need to change the Bus # */
+ if (bus > 2)
+ address = (bus << 16) | (dev << 11) | (func << 8) | (offset & 0xfc) |
+ 0x80000000 | 0x1;
+ else
+ address = (dev << 11) | (func << 8) | (offset & 0xfc) | 0x80000000;
+
+ address_reg = RM9000x2_OCD_HTCFGA;
+ data_reg = RM9000x2_OCD_HTCFGD;
+
+ if ((offset & 0x3) == 0)
+ offset = 0x2;
+ else
+ offset = 0x0;
+
+ RM9K_WRITE(address_reg, address);
+ RM9K_WRITE_16(data_reg + offset, val);
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int titan_ht_config_write_byte(struct pci_dev *device,
+ int offset, u8 val)
+{
+ int dev, bus, func;
+ uint32_t address_reg, data_reg;
+ uint32_t address;
+ int offset1;
+
+ bus = device->bus->number;
+ dev = PCI_SLOT(device->devfn);
+ func = PCI_FUNC(device->devfn);
+
+ /* XXX Need to change the Bus # */
+ if (bus > 2)
+ address = (bus << 16) | (dev << 11) | (func << 8) | (offset & 0xfc) |
+ 0x80000000 | 0x1;
+ else
+ address = (dev << 11) | (func << 8) | (offset & 0xfc) | 0x80000000;
+
+ address_reg = RM9000x2_OCD_HTCFGA;
+ data_reg = RM9000x2_OCD_HTCFGD;
+
+ RM9K_WRITE(address_reg, address);
+
+ if ((offset & 0x3) == 0) {
+ offset1 = 0x3;
+ }
+ if ((offset & 0x3) == 1) {
+ offset1 = 0x2;
+ }
+ if ((offset & 0x3) == 2) {
+ offset1 = 0x1;
+ }
+ if ((offset & 0x3) == 3) {
+ offset1 = 0x0;
+ }
+
+ RM9K_WRITE_8(data_reg + offset1, val);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+
+static void titan_pcibios_set_master(struct pci_dev *dev)
+{
+ u16 cmd;
+ int bus = dev->bus->number;
+
+ if (check_titan_htlink())
+ titan_ht_config_read_word(dev, PCI_COMMAND, &cmd);
+
+ cmd |= PCI_COMMAND_MASTER;
+
+ if (check_titan_htlink())
+ titan_ht_config_write_word(dev, PCI_COMMAND, cmd);
+}
+
+
+int pcibios_enable_resources(struct pci_dev *dev)
+{
+ u16 cmd, old_cmd;
+ u8 tmp1;
+ int idx;
+ struct resource *r;
+ int bus = dev->bus->number;
+
+ if (check_titan_htlink())
+ titan_ht_config_read_word(dev, PCI_COMMAND, &cmd);
+
+ old_cmd = cmd;
+ for (idx = 0; idx < 6; idx++) {
+ r = &dev->resource[idx];
+ if (!r->start && r->end) {
+ printk(KERN_ERR
+ "PCI: Device %s not available because of "
+ "resource collisions\n", pci_name(dev));
+ return -EINVAL;
+ }
+ if (r->flags & IORESOURCE_IO)
+ cmd |= PCI_COMMAND_IO;
+ if (r->flags & IORESOURCE_MEM)
+ cmd |= PCI_COMMAND_MEMORY;
+ }
+ if (cmd != old_cmd) {
+ if (check_titan_htlink())
+ titan_ht_config_write_word(dev, PCI_COMMAND, cmd);
+ }
+
+ if (check_titan_htlink())
+ titan_ht_config_read_byte(dev, PCI_CACHE_LINE_SIZE, &tmp1);
+
+ if (tmp1 != 8) {
+ printk(KERN_WARNING "PCI setting cache line size to 8 from "
+ "%d\n", tmp1);
+ }
+
+ if (check_titan_htlink())
+ titan_ht_config_write_byte(dev, PCI_CACHE_LINE_SIZE, 8);
+
+ if (check_titan_htlink())
+ titan_ht_config_read_byte(dev, PCI_LATENCY_TIMER, &tmp1);
+
+ if (tmp1 < 32 || tmp1 == 0xff) {
+ printk(KERN_WARNING "PCI setting latency timer to 32 from %d\n",
+ tmp1);
+ }
+
+ if (check_titan_htlink())
+ titan_ht_config_write_byte(dev, PCI_LATENCY_TIMER, 32);
+
+ return 0;
+}
+
+
+int pcibios_enable_device(struct pci_dev *dev, int mask)
+{
+ return pcibios_enable_resources(dev);
+}
+
+
+
+void pcibios_update_resource(struct pci_dev *dev, struct resource *root,
+ struct resource *res, int resource)
+{
+ u32 new, check;
+ int reg;
+
+ return;
+
+ new = res->start | (res->flags & PCI_REGION_FLAG_MASK);
+ if (resource < 6) {
+ reg = PCI_BASE_ADDRESS_0 + 4 * resource;
+ } else if (resource == PCI_ROM_RESOURCE) {
+ res->flags |= IORESOURCE_ROM_ENABLE;
+ reg = dev->rom_base_reg;
+ } else {
+ /*
+ * Somebody might have asked allocation of a non-standard
+ * resource
+ */
+ return;
+ }
+
+ pci_write_config_dword(dev, reg, new);
+ pci_read_config_dword(dev, reg, &check);
+ if ((new ^ check) &
+ ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK :
+ PCI_BASE_ADDRESS_MEM_MASK)) {
+ printk(KERN_ERR "PCI: Error while updating region "
+ "%s/%d (%08x != %08x)\n", pci_name(dev), resource,
+ new, check);
+ }
+}
+
+
+void pcibios_align_resource(void *data, struct resource *res,
+ unsigned long size, unsigned long align)
+{
+ struct pci_dev *dev = data;
+
+ if (res->flags & IORESOURCE_IO) {
+ unsigned long start = res->start;
+
+ /* We need to avoid collisions with `mirrored' VGA ports
+ and other strange ISA hardware, so we always want the
+ addresses kilobyte aligned. */
+ if (size > 0x100) {
+ printk(KERN_ERR "PCI: I/O Region %s/%d too large"
+ " (%ld bytes)\n", pci_name(dev),
+ dev->resource - res, size);
+ }
+
+ start = (start + 1024 - 1) & ~(1024 - 1);
+ res->start = start;
+ }
+}
+
+struct pci_ops titan_pci_ops = {
+ titan_ht_config_read_byte,
+ titan_ht_config_read_word,
+ titan_ht_config_read_dword,
+ titan_ht_config_write_byte,
+ titan_ht_config_write_word,
+ titan_ht_config_write_dword
+};
+
+void __init pcibios_fixup_bus(struct pci_bus *c)
+{
+ titan_ht_pcibios_fixup_bus(c);
+}
+
+void __init pcibios_init(void)
+{
+
+ /* Reset PCI I/O and PCI MEM values */
+ /* XXX Need to add the proper values here */
+ ioport_resource.start = 0xe0000000;
+ ioport_resource.end = 0xe0000000 + 0x20000000 - 1;
+ iomem_resource.start = 0xc0000000;
+ iomem_resource.end = 0xc0000000 + 0x20000000 - 1;
+
+ /* XXX Need to add bus values */
+ pci_scan_bus(2, &titan_pci_ops, NULL);
+ pci_scan_bus(3, &titan_pci_ops, NULL);
+}
+
+/*
+ * for parsing "pci=" kernel boot arguments.
+ */
+char *pcibios_setup(char *str)
+{
+ printk(KERN_INFO "rr: pcibios_setup\n");
+ /* Nothing to do for now. */
+
+ return str;
+}
+
+unsigned __init int pcibios_assign_all_busses(void)
+{
+ /* We want to use the PCI bus detection done by PMON */
+ return 0;
+}
+
+#endif /* CONFIG_HYPERTRANSPORT */
diff --git a/arch/mips/pmc-sierra/yosemite/i2c-yosemite.c b/arch/mips/pmc-sierra/yosemite/i2c-yosemite.c
new file mode 100644
index 0000000..416da22
--- /dev/null
+++ b/arch/mips/pmc-sierra/yosemite/i2c-yosemite.c
@@ -0,0 +1,188 @@
+/*
+ * Copyright (C) 2003 PMC-Sierra Inc.
+ * Author: Manish Lachwani (lachwani@pmc-sierra.com)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * Detailed Description:
+ *
+ * This block implements the I2C interface to the slave devices like the
+ * Atmel 24C32 EEPROM and the MAX 1619 Sensors device. The I2C Master interface
+ * can be controlled by the SCMB block. And the SCMB block kicks in only when
+ * using the Ethernet Mode of operation and __not__ the SysAD mode
+ *
+ * The SCMB controls the two modes: MDIO and the I2C. The MDIO mode is used to
+ * communicate with the Quad-PHY from Marvel. The I2C is used to communicate
+ * with the I2C slave devices. It seems that the driver does not explicitly
+ * deal with the control of SDA and SCL serial lines. So, the driver will set
+ * the slave address, drive the command and then the data. The SCMB will then
+ * control the two serial lines as required.
+ *
+ * It seems the documents are very unclear abt this. Hence, I took some time
+ * out to write the desciption to have an idea of how the I2C can actually
+ * work. Currently, this Linux driver wont be integrated into the generic Linux
+ * I2C framework. And finally, the I2C interface is also known as the 2BI
+ * interface. 2BI means 2-bit interface referring to SDA and SCL serial lines
+ * respectively.
+ *
+ * - Manish Lachwani (12/09/2003)
+ */
+
+#include "i2c-yosemite.h"
+
+/*
+ * Poll the I2C interface for the BUSY bit.
+ */
+static int titan_i2c_poll(void)
+{
+ int i = 0;
+ unsigned long val = 0;
+
+ for (i = 0; i < TITAN_I2C_MAX_POLL; i++) {
+ val = TITAN_I2C_READ(TITAN_I2C_COMMAND);
+
+ if (!(val & 0x8000))
+ return 0;
+ }
+
+ return TITAN_I2C_ERR_TIMEOUT;
+}
+
+/*
+ * Execute the I2C command
+ */
+int titan_i2c_xfer(unsigned int slave_addr, titan_i2c_command * cmd,
+ int size, unsigned int *addr)
+{
+ int loop = 0, bytes, i;
+ unsigned int *write_data, data, *read_data;
+ unsigned long reg_val, val;
+
+ write_data = cmd->data;
+ read_data = addr;
+
+ TITAN_I2C_WRITE(TITAN_I2C_SLAVE_ADDRESS, slave_addr);
+
+ if (cmd->type == TITAN_I2C_CMD_WRITE)
+ loop = cmd->write_size;
+ else
+ loop = size;
+
+ while (loop > 0) {
+ if ((cmd->type == TITAN_I2C_CMD_WRITE) ||
+ (cmd->type == TITAN_I2C_CMD_READ_WRITE)) {
+
+ reg_val = TITAN_I2C_DATA;
+ for (i = 0; i < TITAN_I2C_MAX_WORDS_PER_RW;
+ ++i, write_data += 2, reg_val += 4) {
+ if (bytes < cmd->write_size) {
+ data = write_data[0];
+ ++data;
+ }
+
+ if (bytes < cmd->write_size) {
+ data = write_data[1];
+ ++data;
+ }
+
+ TITAN_I2C_WRITE(reg_val, data);
+ }
+ }
+
+ TITAN_I2C_WRITE(TITAN_I2C_COMMAND,
+ (unsigned int) (cmd->type << 13));
+ if (titan_i2c_poll() != TITAN_I2C_ERR_OK)
+ return TITAN_I2C_ERR_TIMEOUT;
+
+ if ((cmd->type == TITAN_I2C_CMD_READ) ||
+ (cmd->type == TITAN_I2C_CMD_READ_WRITE)) {
+
+ reg_val = TITAN_I2C_DATA;
+ for (i = 0; i < TITAN_I2C_MAX_WORDS_PER_RW;
+ ++i, read_data += 2, reg_val += 4) {
+ data = TITAN_I2C_READ(reg_val);
+
+ if (bytes < size) {
+ read_data[0] = data & 0xff;
+ ++bytes;
+ }
+
+ if (bytes < size) {
+ read_data[1] =
+ ((data >> 8) & 0xff);
+ ++bytes;
+ }
+ }
+ }
+
+ loop -= (TITAN_I2C_MAX_WORDS_PER_RW * 2);
+ }
+
+ /*
+ * Read the Interrupt status and then return the appropriate error code
+ */
+
+ val = TITAN_I2C_READ(TITAN_I2C_INTERRUPTS);
+ if (val & 0x0020)
+ return TITAN_I2C_ERR_ARB_LOST;
+
+ if (val & 0x0040)
+ return TITAN_I2C_ERR_NO_RESP;
+
+ if (val & 0x0080)
+ return TITAN_I2C_ERR_DATA_COLLISION;
+
+ return TITAN_I2C_ERR_OK;
+}
+
+/*
+ * Init the I2C subsystem of the PMC-Sierra Yosemite board
+ */
+int titan_i2c_init(titan_i2c_config * config)
+{
+ unsigned int val;
+
+ /*
+ * Reset the SCMB and program into the I2C mode
+ */
+ TITAN_I2C_WRITE(TITAN_I2C_SCMB_CONTROL, 0xA000);
+ TITAN_I2C_WRITE(TITAN_I2C_SCMB_CONTROL, 0x2000);
+
+ /*
+ * Configure the filtera and clka values
+ */
+ val = TITAN_I2C_READ(TITAN_I2C_SCMB_CLOCK_A);
+ val |= ((val & ~(0xF000)) | ((config->filtera << 12) & 0xF000));
+ val |= ((val & ~(0x03FF)) | (config->clka & 0x03FF));
+ TITAN_I2C_WRITE(TITAN_I2C_SCMB_CLOCK_A, val);
+
+ /*
+ * Configure the filterb and clkb values
+ */
+ val = TITAN_I2C_READ(TITAN_I2C_SCMB_CLOCK_B);
+ val |= ((val & ~(0xF000)) | ((config->filterb << 12) & 0xF000));
+ val |= ((val & ~(0x03FF)) | (config->clkb & 0x03FF));
+ TITAN_I2C_WRITE(TITAN_I2C_SCMB_CLOCK_B, val);
+
+ return TITAN_I2C_ERR_OK;
+}
diff --git a/arch/mips/pmc-sierra/yosemite/i2c-yosemite.h b/arch/mips/pmc-sierra/yosemite/i2c-yosemite.h
new file mode 100644
index 0000000..31c5523
--- /dev/null
+++ b/arch/mips/pmc-sierra/yosemite/i2c-yosemite.h
@@ -0,0 +1,96 @@
+/*
+ * arch/mips/pmc-sierra/yosemite/i2c-yosemite.h
+ *
+ * Copyright (C) 2003 PMC-Sierra Inc.
+ * Author: Manish Lachwani (lachwani@pmc-sierra.com)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __I2C_YOSEMITE_H
+#define __I2C_YOSEMITE_H
+
+/* Read and Write operations to the chip */
+
+#define TITAN_I2C_BASE 0xbb000000 /* XXX Needs to change */
+
+#define TITAN_I2C_WRITE(offset, data) \
+ *(volatile unsigned long *)(TITAN_I2C_BASE + offset) = data
+
+#define TITAN_I2C_READ(offset) *(volatile unsigned long *)(TITAN_I2C_BASE + offset)
+
+
+/* Local constansts*/
+#define TITAN_I2C_MAX_FILTER 15
+#define TITAN_I2C_MAX_CLK 1023
+#define TITAN_I2C_MAX_ARBF 15
+#define TITAN_I2C_MAX_NAK 15
+#define TITAN_I2C_MAX_MASTERCODE 7
+#define TITAN_I2C_MAX_WORDS_PER_RW 4
+#define TITAN_I2C_MAX_POLL 100
+
+/* Registers used for I2C work */
+#define TITAN_I2C_SCMB_CONTROL 0x0180 /* SCMB Control */
+#define TITAN_I2C_SCMB_CLOCK_A 0x0184 /* SCMB Clock A */
+#define TITAN_I2C_SCMB_CLOCK_B 0x0188 /* SCMB Clock B */
+#define TITAN_I2C_CONFIG 0x01A0 /* I2C Config */
+#define TITAN_I2C_COMMAND 0x01A4 /* I2C Command */
+#define TITAN_I2C_SLAVE_ADDRESS 0x01A8 /* I2C Slave Address */
+#define TITAN_I2C_DATA 0x01AC /* I2C Data [15:0] */
+#define TITAN_I2C_INTERRUPTS 0x01BC /* I2C Interrupts */
+
+/* Error */
+#define TITAN_I2C_ERR_ARB_LOST (-9220)
+#define TITAN_I2C_ERR_NO_RESP (-9221)
+#define TITAN_I2C_ERR_DATA_COLLISION (-9222)
+#define TITAN_I2C_ERR_TIMEOUT (-9223)
+#define TITAN_I2C_ERR_OK 0
+
+/* I2C Command Type */
+typedef enum {
+ TITAN_I2C_CMD_WRITE = 0,
+ TITAN_I2C_CMD_READ = 1,
+ TITAN_I2C_CMD_READ_WRITE = 2
+} titan_i2c_cmd_type;
+
+/* I2C structures */
+typedef struct {
+ int filtera; /* Register 0x0184, bits 15 - 12 */
+ int clka; /* Register 0x0184, bits 9 - 0 */
+ int filterb; /* Register 0x0188, bits 15 - 12 */
+ int clkb; /* Register 0x0188, bits 9 - 0 */
+} titan_i2c_config;
+
+/* I2C command type */
+typedef struct {
+ titan_i2c_cmd_type type; /* Type of command */
+ int num_arb; /* Register 0x01a0, bits 15 - 12 */
+ int num_nak; /* Register 0x01a0, bits 11 - 8 */
+ int addr_size; /* Register 0x01a0, bit 7 */
+ int mst_code; /* Register 0x01a0, bits 6 - 4 */
+ int arb_en; /* Register 0x01a0, bit 1 */
+ int speed; /* Register 0x01a0, bit 0 */
+ int slave_addr; /* Register 0x01a8 */
+ int write_size; /* Register 0x01a4, bits 10 - 8 */
+ unsigned int *data; /* Register 0x01ac */
+} titan_i2c_command;
+
+#endif /* __I2C_YOSEMITE_H */
diff --git a/arch/mips/pmc-sierra/yosemite/irq-handler.S b/arch/mips/pmc-sierra/yosemite/irq-handler.S
new file mode 100644
index 0000000..33b9c40
--- /dev/null
+++ b/arch/mips/pmc-sierra/yosemite/irq-handler.S
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2003, 04 PMC-Sierra Inc.
+ * Author: Manish Lachwani (lachwani@pmc-sierra.com
+ * Copyright 2004 Ralf Baechle (ralf@linux-mips.org)
+ *
+ * First-level interrupt router for the PMC-Sierra Titan board
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * Titan supports Hypertransport or PCI but not both. Hence, one interrupt
+ * line is shared between the PCI slot A and Hypertransport. This is the
+ * Processor INTB #0.
+ */
+
+#include <linux/config.h>
+#include <asm/asm.h>
+#include <asm/mipsregs.h>
+#include <asm/addrspace.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+
+ .align 5
+ NESTED(titan_handle_int, PT_SIZE, sp)
+ SAVE_ALL
+ CLI
+ .set at
+ .set noreorder
+ la ra, ret_from_irq
+ mfc0 t0, CP0_CAUSE
+ mfc0 t2, CP0_STATUS
+
+ and t0, t2
+
+ andi t2, t0, STATUSF_IP7 /* INTB5 hardware line */
+ bnez t2, ll_timer_irq /* Timer */
+ andi t1, t0, STATUSF_IP2 /* INTB0 hardware line */
+ bnez t1, ll_pcia_irq /* 64-bit PCI */
+ andi t2, t0, STATUSF_IP3 /* INTB1 hardware line */
+ bnez t2, ll_pcib_irq /* second 64-bit PCI slot */
+ andi t1, t0, STATUSF_IP4 /* INTB2 hardware line */
+ bnez t1, ll_duart_irq /* UART */
+ andi t2, t0, STATUSF_IP5 /* SMP inter-core interrupts */
+ bnez t2, ll_smp_irq
+ andi t1, t0, STATUSF_IP6
+ bnez t1, ll_ht_irq /* Hypertransport */
+
+ move a0, sp
+ j do_extended_irq
+ END(titan_handle_int)
+
+ .set reorder
+ .align 5
+
+ll_pcia_irq:
+ li a0, 2
+ move a1, sp
+#ifdef CONFIG_HYPERTRANSPORT
+ j ll_ht_smp_irq_handler
+#else
+ j do_IRQ
+#endif
+
+ll_pcib_irq:
+ li a0, 3
+ move a1, sp
+ j do_IRQ
+
+ll_duart_irq:
+ li a0, 4
+ move a1, sp
+ j do_IRQ
+
+ll_smp_irq:
+ li a0, 5
+ move a1, sp
+#ifdef CONFIG_SMP
+ j titan_mailbox_irq
+#else
+ j do_IRQ
+#endif
+
+ll_ht_irq:
+ li a0, 6
+ move a1, sp
+ j ll_ht_smp_irq_handler
+
+ll_timer_irq:
+ li a0, 7
+ move a1, sp
+ j do_IRQ
diff --git a/arch/mips/pmc-sierra/yosemite/irq.c b/arch/mips/pmc-sierra/yosemite/irq.c
new file mode 100644
index 0000000..f4e2897
--- /dev/null
+++ b/arch/mips/pmc-sierra/yosemite/irq.c
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2003 PMC-Sierra Inc.
+ * Author: Manish Lachwani (lachwani@pmc-sierra.com)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Second level Interrupt handlers for the PMC-Sierra Titan/Yosemite board
+ */
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel_stat.h>
+#include <linux/module.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/irq.h>
+#include <linux/timex.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+#include <linux/bitops.h>
+#include <asm/bootinfo.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/irq_cpu.h>
+#include <asm/mipsregs.h>
+#include <asm/system.h>
+#include <asm/titan_dep.h>
+
+/* Hypertransport specific */
+#define IRQ_ACK_BITS 0x00000000 /* Ack bits */
+
+#define HYPERTRANSPORT_INTA 0x78 /* INTA# */
+#define HYPERTRANSPORT_INTB 0x79 /* INTB# */
+#define HYPERTRANSPORT_INTC 0x7a /* INTC# */
+#define HYPERTRANSPORT_INTD 0x7b /* INTD# */
+
+extern asmlinkage void titan_handle_int(void);
+extern void jaguar_mailbox_irq(struct pt_regs *);
+
+/*
+ * Handle hypertransport & SMP interrupts. The interrupt lines are scarce.
+ * For interprocessor interrupts, the best thing to do is to use the INTMSG
+ * register. We use the same external interrupt line, i.e. INTB3 and monitor
+ * another status bit
+ */
+asmlinkage void ll_ht_smp_irq_handler(int irq, struct pt_regs *regs)
+{
+ u32 status = OCD_READ(RM9000x2_OCD_INTP0STATUS4);
+
+ /* Ack all the bits that correspond to the interrupt sources */
+ if (status != 0)
+ OCD_WRITE(RM9000x2_OCD_INTP0STATUS4, IRQ_ACK_BITS);
+
+ status = OCD_READ(RM9000x2_OCD_INTP1STATUS4);
+ if (status != 0)
+ OCD_WRITE(RM9000x2_OCD_INTP1STATUS4, IRQ_ACK_BITS);
+
+#ifdef CONFIG_HT_LEVEL_TRIGGER
+ /*
+ * Level Trigger Mode only. Send the HT EOI message back to the source.
+ */
+ switch (status) {
+ case 0x1000000:
+ OCD_WRITE(RM9000x2_OCD_HTEOI, HYPERTRANSPORT_INTA);
+ break;
+ case 0x2000000:
+ OCD_WRITE(RM9000x2_OCD_HTEOI, HYPERTRANSPORT_INTB);
+ break;
+ case 0x4000000:
+ OCD_WRITE(RM9000x2_OCD_HTEOI, HYPERTRANSPORT_INTC);
+ break;
+ case 0x8000000:
+ OCD_WRITE(RM9000x2_OCD_HTEOI, HYPERTRANSPORT_INTD);
+ break;
+ case 0x0000001:
+ /* PLX */
+ OCD_WRITE(RM9000x2_OCD_HTEOI, 0x20);
+ OCD_WRITE(IRQ_CLEAR_REG, IRQ_ACK_BITS);
+ break;
+ case 0xf000000:
+ OCD_WRITE(RM9000x2_OCD_HTEOI, HYPERTRANSPORT_INTA);
+ OCD_WRITE(RM9000x2_OCD_HTEOI, HYPERTRANSPORT_INTB);
+ OCD_WRITE(RM9000x2_OCD_HTEOI, HYPERTRANSPORT_INTC);
+ OCD_WRITE(RM9000x2_OCD_HTEOI, HYPERTRANSPORT_INTD);
+ break;
+ }
+#endif /* CONFIG_HT_LEVEL_TRIGGER */
+
+ do_IRQ(irq, regs);
+}
+
+asmlinkage void do_extended_irq(struct pt_regs *regs)
+{
+ unsigned int intcontrol = read_c0_intcontrol();
+ unsigned int cause = read_c0_cause();
+ unsigned int status = read_c0_status();
+ unsigned int pending_sr, pending_ic;
+
+ pending_sr = status & cause & 0xff00;
+ pending_ic = (cause >> 8) & intcontrol & 0xff00;
+
+ if (pending_ic & (1 << 13))
+ do_IRQ(13, regs);
+
+}
+
+#ifdef CONFIG_KGDB
+extern void init_second_port(void);
+#endif
+
+/*
+ * Initialize the next level interrupt handler
+ */
+void __init arch_init_irq(void)
+{
+ clear_c0_status(ST0_IM);
+
+ set_except_vector(0, titan_handle_int);
+ mips_cpu_irq_init(0);
+ rm7k_cpu_irq_init(8);
+ rm9k_cpu_irq_init(12);
+
+#ifdef CONFIG_KGDB
+ /* At this point, initialize the second serial port */
+ init_second_port();
+#endif
+
+#ifdef CONFIG_GDB_CONSOLE
+ register_gdb_console();
+#endif
+}
+
+#ifdef CONFIG_KGDB
+/*
+ * The 16550 DUART has two ports, but is allocated one IRQ
+ * for the serial console. Hence, a generic framework for
+ * serial IRQ routing in place. Currently, just calls the
+ * do_IRQ fuction. But, going in the future, need to check
+ * DUART registers for channel A and B, then decide the
+ * appropriate action
+ */
+asmlinkage void yosemite_kgdb_irq(int irq, struct pt_regs *regs)
+{
+ do_IRQ(irq, regs);
+}
+#endif
diff --git a/arch/mips/pmc-sierra/yosemite/prom.c b/arch/mips/pmc-sierra/yosemite/prom.c
new file mode 100644
index 0000000..1fb3e69
--- /dev/null
+++ b/arch/mips/pmc-sierra/yosemite/prom.c
@@ -0,0 +1,141 @@
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * Copyright (C) 2003, 2004 PMC-Sierra Inc.
+ * Author: Manish Lachwani (lachwani@pmc-sierra.com)
+ * Copyright (C) 2004 Ralf Baechle
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/delay.h>
+#include <linux/smp.h>
+
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/reboot.h>
+#include <asm/system.h>
+#include <asm/bootinfo.h>
+#include <asm/pmon.h>
+
+#ifdef CONFIG_SMP
+extern void prom_grab_secondary(void);
+#else
+#define prom_grab_secondary() do { } while (0)
+#endif
+
+#include "setup.h"
+
+struct callvectors *debug_vectors;
+
+extern unsigned long yosemite_base;
+extern unsigned long cpu_clock;
+
+const char *get_system_type(void)
+{
+ return "PMC-Sierra Yosemite";
+}
+
+static void prom_cpu0_exit(void *arg)
+{
+ void *nvram = (void *) YOSEMITE_RTC_BASE;
+
+ /* Ask the NVRAM/RTC/watchdog chip to assert reset in 1/16 second */
+ writeb(0x84, nvram + 0xff7);
+
+ /* wait for the watchdog to go off */
+ mdelay(100 + (1000 / 16));
+
+ /* if the watchdog fails for some reason, let people know */
+ printk(KERN_NOTICE "Watchdog reset failed\n");
+}
+
+/*
+ * Reset the NVRAM over the local bus
+ */
+static void prom_exit(void)
+{
+#ifdef CONFIG_SMP
+ if (smp_processor_id())
+ /* CPU 1 */
+ smp_call_function(prom_cpu0_exit, NULL, 1, 1);
+#endif
+ prom_cpu0_exit(NULL);
+}
+
+/*
+ * Halt the system
+ */
+static void prom_halt(void)
+{
+ printk(KERN_NOTICE "\n** You can safely turn off the power\n");
+ while (1)
+ __asm__(".set\tmips3\n\t" "wait\n\t" ".set\tmips0");
+}
+
+/*
+ * Init routine which accepts the variables from PMON
+ */
+void __init prom_init(void)
+{
+ int argc = fw_arg0;
+ char **arg = (char **) fw_arg1;
+ char **env = (char **) fw_arg2;
+ struct callvectors *cv = (struct callvectors *) fw_arg3;
+ int i = 0;
+
+ /* Callbacks for halt, restart */
+ _machine_restart = (void (*)(char *)) prom_exit;
+ _machine_halt = prom_halt;
+ _machine_power_off = prom_halt;
+
+ debug_vectors = cv;
+ arcs_cmdline[0] = '\0';
+
+ /* Get the boot parameters */
+ for (i = 1; i < argc; i++) {
+ if (strlen(arcs_cmdline) + strlen(arg[i] + 1) >=
+ sizeof(arcs_cmdline))
+ break;
+
+ strcat(arcs_cmdline, arg[i]);
+ strcat(arcs_cmdline, " ");
+ }
+
+#ifdef CONFIG_SERIAL_8250_CONSOLE
+ if ((strstr(arcs_cmdline, "console=ttyS")) == NULL)
+ strcat(arcs_cmdline, "console=ttyS0,115200");
+#endif
+
+ while (*env) {
+ if (strncmp("ocd_base", *env, strlen("ocd_base")) == 0)
+ yosemite_base =
+ simple_strtol(*env + strlen("ocd_base="), NULL,
+ 16);
+
+ if (strncmp("cpuclock", *env, strlen("cpuclock")) == 0)
+ cpu_clock =
+ simple_strtol(*env + strlen("cpuclock="), NULL,
+ 10);
+
+ env++;
+ }
+
+ mips_machgroup = MACH_GROUP_TITAN;
+ mips_machtype = MACH_TITAN_YOSEMITE;
+
+ prom_grab_secondary();
+}
+
+void __init prom_free_prom_memory(void)
+{
+}
+
+void __init prom_fixup_mem_map(unsigned long start, unsigned long end)
+{
+}
diff --git a/arch/mips/pmc-sierra/yosemite/py-console.c b/arch/mips/pmc-sierra/yosemite/py-console.c
new file mode 100644
index 0000000..757e605
--- /dev/null
+++ b/arch/mips/pmc-sierra/yosemite/py-console.c
@@ -0,0 +1,114 @@
+/*
+ * 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) 2001, 2002, 2004 Ralf Baechle
+ */
+#include <linux/init.h>
+#include <linux/console.h>
+#include <linux/kdev_t.h>
+#include <linux/major.h>
+#include <linux/termios.h>
+#include <linux/sched.h>
+#include <linux/tty.h>
+
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+#include <asm/serial.h>
+#include <asm/io.h>
+
+/* SUPERIO uart register map */
+struct yo_uartregs {
+ union {
+ volatile u8 rbr; /* read only, DLAB == 0 */
+ volatile u8 thr; /* write only, DLAB == 0 */
+ volatile u8 dll; /* DLAB == 1 */
+ } u1;
+ union {
+ volatile u8 ier; /* DLAB == 0 */
+ volatile u8 dlm; /* DLAB == 1 */
+ } u2;
+ union {
+ volatile u8 iir; /* read only */
+ volatile u8 fcr; /* write only */
+ } u3;
+ volatile u8 iu_lcr;
+ volatile u8 iu_mcr;
+ volatile u8 iu_lsr;
+ volatile u8 iu_msr;
+ volatile u8 iu_scr;
+} yo_uregs_t;
+
+#define iu_rbr u1.rbr
+#define iu_thr u1.thr
+#define iu_dll u1.dll
+#define iu_ier u2.ier
+#define iu_dlm u2.dlm
+#define iu_iir u3.iir
+#define iu_fcr u3.fcr
+
+#define ssnop() __asm__ __volatile__("sll $0, $0, 1\n");
+#define ssnop_4() do { ssnop(); ssnop(); ssnop(); ssnop(); } while (0)
+
+#define IO_BASE_64 0x9000000000000000ULL
+
+static unsigned char readb_outer_space(unsigned long long phys)
+{
+ unsigned long long vaddr = IO_BASE_64 | phys;
+ unsigned char res;
+ unsigned int sr;
+
+ sr = read_c0_status();
+ write_c0_status((sr | ST0_KX) & ~ ST0_IE);
+ ssnop_4();
+
+ __asm__ __volatile__ (
+ " .set mips3 \n"
+ " ld %0, %1 \n"
+ " lbu %0, (%0) \n"
+ " .set mips0 \n"
+ : "=r" (res)
+ : "m" (vaddr));
+
+ write_c0_status(sr);
+ ssnop_4();
+
+ return res;
+}
+
+static void writeb_outer_space(unsigned long long phys, unsigned char c)
+{
+ unsigned long long vaddr = IO_BASE_64 | phys;
+ unsigned long tmp;
+ unsigned int sr;
+
+ sr = read_c0_status();
+ write_c0_status((sr | ST0_KX) & ~ ST0_IE);
+ ssnop_4();
+
+ __asm__ __volatile__ (
+ " .set mips3 \n"
+ " ld %0, %1 \n"
+ " sb %2, (%0) \n"
+ " .set mips0 \n"
+ : "=&r" (tmp)
+ : "m" (vaddr), "r" (c));
+
+ write_c0_status(sr);
+ ssnop_4();
+}
+
+void prom_putchar(char c)
+{
+ unsigned long lsr = 0xfd000008ULL + offsetof(struct yo_uartregs, iu_lsr);
+ unsigned long thr = 0xfd000008ULL + offsetof(struct yo_uartregs, iu_thr);
+
+ while ((readb_outer_space(lsr) & 0x20) == 0);
+ writeb_outer_space(thr, c);
+}
+
+char __init prom_getchar(void)
+{
+ return 0;
+}
diff --git a/arch/mips/pmc-sierra/yosemite/setup.c b/arch/mips/pmc-sierra/yosemite/setup.c
new file mode 100644
index 0000000..7225bbf
--- /dev/null
+++ b/arch/mips/pmc-sierra/yosemite/setup.c
@@ -0,0 +1,235 @@
+/*
+ * Copyright (C) 2003 PMC-Sierra Inc.
+ * Author: Manish Lachwani (lachwani@pmc-sierra.com)
+ *
+ * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/bcd.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/bootmem.h>
+#include <linux/swap.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/timex.h>
+#include <linux/termios.h>
+#include <linux/tty.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+
+#include <asm/time.h>
+#include <asm/bootinfo.h>
+#include <asm/page.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/processor.h>
+#include <asm/ptrace.h>
+#include <asm/reboot.h>
+#include <asm/serial.h>
+#include <asm/titan_dep.h>
+#include <asm/m48t37.h>
+
+#include "setup.h"
+
+unsigned char titan_ge_mac_addr_base[6] = {
+ // 0x00, 0x03, 0xcc, 0x1d, 0x22, 0x00
+ 0x00, 0xe0, 0x04, 0x00, 0x00, 0x21
+};
+
+unsigned long cpu_clock;
+unsigned long yosemite_base;
+
+static struct m48t37_rtc *m48t37_base;
+
+void __init bus_error_init(void)
+{
+ /* Do nothing */
+}
+
+
+unsigned long m48t37y_get_time(void)
+{
+ unsigned int year, month, day, hour, min, sec;
+
+ /* Stop the update to the time */
+ m48t37_base->control = 0x40;
+
+ year = BCD2BIN(m48t37_base->year);
+ year += BCD2BIN(m48t37_base->century) * 100;
+
+ month = BCD2BIN(m48t37_base->month);
+ day = BCD2BIN(m48t37_base->date);
+ hour = BCD2BIN(m48t37_base->hour);
+ min = BCD2BIN(m48t37_base->min);
+ sec = BCD2BIN(m48t37_base->sec);
+
+ /* Start the update to the time again */
+ m48t37_base->control = 0x00;
+
+ return mktime(year, month, day, hour, min, sec);
+}
+
+int m48t37y_set_time(unsigned long sec)
+{
+ struct rtc_time tm;
+
+ /* convert to a more useful format -- note months count from 0 */
+ to_tm(sec, &tm);
+ tm.tm_mon += 1;
+
+ /* enable writing */
+ m48t37_base->control = 0x80;
+
+ /* year */
+ m48t37_base->year = BIN2BCD(tm.tm_year % 100);
+ m48t37_base->century = BIN2BCD(tm.tm_year / 100);
+
+ /* month */
+ m48t37_base->month = BIN2BCD(tm.tm_mon);
+
+ /* day */
+ m48t37_base->date = BIN2BCD(tm.tm_mday);
+
+ /* hour/min/sec */
+ m48t37_base->hour = BIN2BCD(tm.tm_hour);
+ m48t37_base->min = BIN2BCD(tm.tm_min);
+ m48t37_base->sec = BIN2BCD(tm.tm_sec);
+
+ /* day of week -- not really used, but let's keep it up-to-date */
+ m48t37_base->day = BIN2BCD(tm.tm_wday + 1);
+
+ /* disable writing */
+ m48t37_base->control = 0x00;
+
+ return 0;
+}
+
+void yosemite_timer_setup(struct irqaction *irq)
+{
+ setup_irq(7, irq);
+}
+
+void yosemite_time_init(void)
+{
+ board_timer_setup = yosemite_timer_setup;
+ mips_hpt_frequency = cpu_clock / 2;
+mips_hpt_frequency = 33000000 * 3 * 5;
+}
+
+/* No other usable initialization hook than this ... */
+extern void (*late_time_init)(void);
+
+unsigned long ocd_base;
+
+EXPORT_SYMBOL(ocd_base);
+
+/*
+ * Common setup before any secondaries are started
+ */
+
+#define TITAN_UART_CLK 3686400
+#define TITAN_SERIAL_BASE_BAUD (TITAN_UART_CLK / 16)
+#define TITAN_SERIAL_IRQ 4
+#define TITAN_SERIAL_BASE 0xfd000008UL
+
+static void __init py_map_ocd(void)
+{
+ ocd_base = (unsigned long) ioremap(OCD_BASE, OCD_SIZE);
+ if (!ocd_base)
+ panic("Mapping OCD failed - game over. Your score is 0.");
+
+ /* Kludge for PMON bug ... */
+ OCD_WRITE(0x0710, 0x0ffff029);
+}
+
+static void __init py_uart_setup(void)
+{
+ struct uart_port up;
+
+ /*
+ * Register to interrupt zero because we share the interrupt with
+ * the serial driver which we don't properly support yet.
+ */
+ memset(&up, 0, sizeof(up));
+ up.membase = (unsigned char *) ioremap(TITAN_SERIAL_BASE, 8);
+ up.irq = TITAN_SERIAL_IRQ;
+ up.uartclk = TITAN_UART_CLK;
+ up.regshift = 0;
+ up.iotype = UPIO_MEM;
+ up.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST;
+ up.line = 0;
+
+ if (early_serial_setup(&up))
+ printk(KERN_ERR "Early serial init of port 0 failed\n");
+}
+
+static void __init py_rtc_setup(void)
+{
+ m48t37_base = ioremap(YOSEMITE_RTC_BASE, YOSEMITE_RTC_SIZE);
+ if (!m48t37_base)
+ printk(KERN_ERR "Mapping the RTC failed\n");
+
+ rtc_get_time = m48t37y_get_time;
+ rtc_set_time = m48t37y_set_time;
+
+ write_seqlock(&xtime_lock);
+ xtime.tv_sec = m48t37y_get_time();
+ xtime.tv_nsec = 0;
+
+ set_normalized_timespec(&wall_to_monotonic,
+ -xtime.tv_sec, -xtime.tv_nsec);
+ write_sequnlock(&xtime_lock);
+}
+
+/* Not only time init but that's what the hook it's called through is named */
+static void __init py_late_time_init(void)
+{
+ py_map_ocd();
+ py_uart_setup();
+ py_rtc_setup();
+}
+
+static int __init pmc_yosemite_setup(void)
+{
+ board_time_init = yosemite_time_init;
+ late_time_init = py_late_time_init;
+
+ /* Add memory regions */
+ add_memory_region(0x00000000, 0x10000000, BOOT_MEM_RAM);
+
+#if 0 /* XXX Crash ... */
+ OCD_WRITE(RM9000x2_OCD_HTSC,
+ OCD_READ(RM9000x2_OCD_HTSC) | HYPERTRANSPORT_ENABLE);
+
+ /* Set the BAR. Shifted mode */
+ OCD_WRITE(RM9000x2_OCD_HTBAR0, HYPERTRANSPORT_BAR0_ADDR);
+ OCD_WRITE(RM9000x2_OCD_HTMASK0, HYPERTRANSPORT_SIZE0);
+#endif
+
+ return 0;
+}
+
+early_initcall(pmc_yosemite_setup);
diff --git a/arch/mips/pmc-sierra/yosemite/setup.h b/arch/mips/pmc-sierra/yosemite/setup.h
new file mode 100644
index 0000000..1a01abf
--- /dev/null
+++ b/arch/mips/pmc-sierra/yosemite/setup.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2003, 04 PMC-Sierra
+ * Author: Manish Lachwani (lachwani@pmc-sierra.com)
+ * Copyright 2004 Ralf Baechle <ralf@linux-mips.org>
+ *
+ * Board specific definititions for the PMC-Sierra Yosemite
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+#ifndef __SETUP_H__
+#define __SETUP_H__
+
+/* M48T37 RTC + NVRAM */
+#define YOSEMITE_RTC_BASE 0xfc800000
+#define YOSEMITE_RTC_SIZE 0x00800000
+
+#define HYPERTRANSPORT_BAR0_ADDR 0x00000006
+#define HYPERTRANSPORT_SIZE0 0x0fffffff
+#define HYPERTRANSPORT_BAR0_ATTR 0x00002000
+
+#define HYPERTRANSPORT_ENABLE 0x6
+
+/*
+ * EEPROM Size
+ */
+#define TITAN_ATMEL_24C32_SIZE 32768
+#define TITAN_ATMEL_24C64_SIZE 65536
+
+#endif /* __SETUP_H__ */
diff --git a/arch/mips/pmc-sierra/yosemite/smp.c b/arch/mips/pmc-sierra/yosemite/smp.c
new file mode 100644
index 0000000..1d3b073
--- /dev/null
+++ b/arch/mips/pmc-sierra/yosemite/smp.c
@@ -0,0 +1,172 @@
+#include <linux/linkage.h>
+#include <linux/sched.h>
+
+#include <asm/pmon.h>
+#include <asm/titan_dep.h>
+
+extern unsigned int (*mips_hpt_read)(void);
+extern void (*mips_hpt_init)(unsigned int);
+
+#define LAUNCHSTACK_SIZE 256
+
+static spinlock_t launch_lock __initdata;
+
+static unsigned long secondary_sp __initdata;
+static unsigned long secondary_gp __initdata;
+
+static unsigned char launchstack[LAUNCHSTACK_SIZE] __initdata
+ __attribute__((aligned(2 * sizeof(long))));
+
+static void __init prom_smp_bootstrap(void)
+{
+ local_irq_disable();
+
+ while (spin_is_locked(&launch_lock));
+
+ __asm__ __volatile__(
+ " move $sp, %0 \n"
+ " move $gp, %1 \n"
+ " j smp_bootstrap \n"
+ :
+ : "r" (secondary_sp), "r" (secondary_gp));
+}
+
+/*
+ * PMON is a fragile beast. It'll blow up once the mappings it's littering
+ * right into the middle of KSEG3 are blown away so we have to grab the slave
+ * core early and keep it in a waiting loop.
+ */
+void __init prom_grab_secondary(void)
+{
+ spin_lock(&launch_lock);
+
+ pmon_cpustart(1, &prom_smp_bootstrap,
+ launchstack + LAUNCHSTACK_SIZE, 0);
+}
+
+/*
+ * Detect available CPUs, populate phys_cpu_present_map before smp_init
+ *
+ * We don't want to start the secondary CPU yet nor do we have a nice probing
+ * feature in PMON so we just assume presence of the secondary core.
+ */
+static char maxcpus_string[] __initdata =
+ KERN_WARNING "max_cpus set to 0; using 1 instead\n";
+
+void __init prom_prepare_cpus(unsigned int max_cpus)
+{
+ int enabled = 0, i;
+
+ if (max_cpus == 0) {
+ printk(maxcpus_string);
+ max_cpus = 1;
+ }
+
+ cpus_clear(phys_cpu_present_map);
+
+ for (i = 0; i < 2; i++) {
+ if (i == max_cpus)
+ break;
+
+ /*
+ * The boot CPU
+ */
+ cpu_set(i, phys_cpu_present_map);
+ __cpu_number_map[i] = i;
+ __cpu_logical_map[i] = i;
+ enabled++;
+ }
+
+ /*
+ * Be paranoid. Enable the IPI only if we're really about to go SMP.
+ */
+ if (enabled > 1)
+ set_c0_status(STATUSF_IP5);
+}
+
+/*
+ * Firmware CPU startup hook
+ * Complicated by PMON's weird interface which tries to minimic the UNIX fork.
+ * It launches the next * available CPU and copies some information on the
+ * stack so the first thing we do is throw away that stuff and load useful
+ * values into the registers ...
+ */
+void prom_boot_secondary(int cpu, struct task_struct *idle)
+{
+ unsigned long gp = (unsigned long) idle->thread_info;
+ unsigned long sp = gp + THREAD_SIZE - 32;
+
+ secondary_sp = sp;
+ secondary_gp = gp;
+
+ spin_unlock(&launch_lock);
+}
+
+/* Hook for after all CPUs are online */
+void prom_cpus_done(void)
+{
+}
+
+/*
+ * After we've done initial boot, this function is called to allow the
+ * board code to clean up state, if needed
+ */
+void prom_init_secondary(void)
+{
+ mips_hpt_init(mips_hpt_read());
+
+ set_c0_status(ST0_CO | ST0_IE | ST0_IM);
+}
+
+void prom_smp_finish(void)
+{
+}
+
+asmlinkage void titan_mailbox_irq(struct pt_regs *regs)
+{
+ int cpu = smp_processor_id();
+ unsigned long status;
+
+ if (cpu == 0) {
+ status = OCD_READ(RM9000x2_OCD_INTP0STATUS3);
+ OCD_WRITE(RM9000x2_OCD_INTP0CLEAR3, status);
+ }
+
+ if (cpu == 1) {
+ status = OCD_READ(RM9000x2_OCD_INTP1STATUS3);
+ OCD_WRITE(RM9000x2_OCD_INTP1CLEAR3, status);
+ }
+
+ if (status & 0x2)
+ smp_call_function_interrupt();
+}
+
+/*
+ * Send inter-processor interrupt
+ */
+void core_send_ipi(int cpu, unsigned int action)
+{
+ /*
+ * Generate an INTMSG so that it can be sent over to the
+ * destination CPU. The INTMSG will put the STATUS bits
+ * based on the action desired. An alternative strategy
+ * is to write to the Interrupt Set register, read the
+ * Interrupt Status register and clear the Interrupt
+ * Clear register. The latter is preffered.
+ */
+ switch (action) {
+ case SMP_RESCHEDULE_YOURSELF:
+ if (cpu == 1)
+ OCD_WRITE(RM9000x2_OCD_INTP1SET3, 4);
+ else
+ OCD_WRITE(RM9000x2_OCD_INTP0SET3, 4);
+ break;
+
+ case SMP_CALL_FUNCTION:
+ if (cpu == 1)
+ OCD_WRITE(RM9000x2_OCD_INTP1SET3, 2);
+ else
+ OCD_WRITE(RM9000x2_OCD_INTP0SET3, 2);
+ break;
+ }
+}
diff --git a/arch/mips/sgi-ip22/Makefile b/arch/mips/sgi-ip22/Makefile
new file mode 100644
index 0000000..eb0820f
--- /dev/null
+++ b/arch/mips/sgi-ip22/Makefile
@@ -0,0 +1,11 @@
+#
+# Makefile for the SGI specific kernel interface routines
+# under Linux.
+#
+
+obj-y += ip22-mc.o ip22-hpc.o ip22-int.o ip22-irq.o ip22-berr.o \
+ ip22-time.o ip22-nvram.o ip22-reset.o ip22-setup.o
+
+obj-$(CONFIG_EISA) += ip22-eisa.o
+
+EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/sgi-ip22/ip22-berr.c b/arch/mips/sgi-ip22/ip22-berr.c
new file mode 100644
index 0000000..a28dc78
--- /dev/null
+++ b/arch/mips/sgi-ip22/ip22-berr.c
@@ -0,0 +1,114 @@
+/*
+ * ip22-berr.c: Bus error handling.
+ *
+ * Copyright (C) 2002, 2003 Ladislav Michl (ladis@linux-mips.org)
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+
+#include <asm/addrspace.h>
+#include <asm/system.h>
+#include <asm/traps.h>
+#include <asm/branch.h>
+#include <asm/sgi/mc.h>
+#include <asm/sgi/hpc3.h>
+#include <asm/sgi/ioc.h>
+#include <asm/sgi/ip22.h>
+
+
+static unsigned int cpu_err_stat; /* Status reg for CPU */
+static unsigned int gio_err_stat; /* Status reg for GIO */
+static unsigned int cpu_err_addr; /* Error address reg for CPU */
+static unsigned int gio_err_addr; /* Error address reg for GIO */
+static unsigned int extio_stat;
+static unsigned int hpc3_berr_stat; /* Bus error interrupt status */
+
+static void save_and_clear_buserr(void)
+{
+ /* save status registers */
+ cpu_err_addr = sgimc->cerr;
+ cpu_err_stat = sgimc->cstat;
+ gio_err_addr = sgimc->gerr;
+ gio_err_stat = sgimc->gstat;
+ extio_stat = ip22_is_fullhouse() ? sgioc->extio : (sgint->errstat << 4);
+ hpc3_berr_stat = hpc3c0->bestat;
+
+ sgimc->cstat = sgimc->gstat = 0;
+}
+
+#define GIO_ERRMASK 0xff00
+#define CPU_ERRMASK 0x3f00
+
+static void print_buserr(void)
+{
+ if (extio_stat & EXTIO_MC_BUSERR)
+ printk(KERN_ERR "MC Bus Error\n");
+ if (extio_stat & EXTIO_HPC3_BUSERR)
+ printk(KERN_ERR "HPC3 Bus Error 0x%x:<id=0x%x,%s,lane=0x%x>\n",
+ hpc3_berr_stat,
+ (hpc3_berr_stat & HPC3_BESTAT_PIDMASK) >>
+ HPC3_BESTAT_PIDSHIFT,
+ (hpc3_berr_stat & HPC3_BESTAT_CTYPE) ? "PIO" : "DMA",
+ hpc3_berr_stat & HPC3_BESTAT_BLMASK);
+ if (extio_stat & EXTIO_EISA_BUSERR)
+ printk(KERN_ERR "EISA Bus Error\n");
+ if (cpu_err_stat & CPU_ERRMASK)
+ printk(KERN_ERR "CPU error 0x%x<%s%s%s%s%s%s> @ 0x%08x\n",
+ cpu_err_stat,
+ cpu_err_stat & SGIMC_CSTAT_RD ? "RD " : "",
+ cpu_err_stat & SGIMC_CSTAT_PAR ? "PAR " : "",
+ cpu_err_stat & SGIMC_CSTAT_ADDR ? "ADDR " : "",
+ cpu_err_stat & SGIMC_CSTAT_SYSAD_PAR ? "SYSAD " : "",
+ cpu_err_stat & SGIMC_CSTAT_SYSCMD_PAR ? "SYSCMD " : "",
+ cpu_err_stat & SGIMC_CSTAT_BAD_DATA ? "BAD_DATA " : "",
+ cpu_err_addr);
+ if (gio_err_stat & GIO_ERRMASK)
+ printk(KERN_ERR "GIO error 0x%x:<%s%s%s%s%s%s%s%s> @ 0x%08x\n",
+ gio_err_stat,
+ gio_err_stat & SGIMC_GSTAT_RD ? "RD " : "",
+ gio_err_stat & SGIMC_GSTAT_WR ? "WR " : "",
+ gio_err_stat & SGIMC_GSTAT_TIME ? "TIME " : "",
+ gio_err_stat & SGIMC_GSTAT_PROM ? "PROM " : "",
+ gio_err_stat & SGIMC_GSTAT_ADDR ? "ADDR " : "",
+ gio_err_stat & SGIMC_GSTAT_BC ? "BC " : "",
+ gio_err_stat & SGIMC_GSTAT_PIO_RD ? "PIO_RD " : "",
+ gio_err_stat & SGIMC_GSTAT_PIO_WR ? "PIO_WR " : "",
+ gio_err_addr);
+}
+
+/*
+ * MC sends an interrupt whenever bus or parity errors occur. In addition,
+ * if the error happened during a CPU read, it also asserts the bus error
+ * pin on the R4K. Code in bus error handler save the MC bus error registers
+ * and then clear the interrupt when this happens.
+ */
+
+void ip22_be_interrupt(int irq, struct pt_regs *regs)
+{
+ const int field = 2 * sizeof(unsigned long);
+
+ save_and_clear_buserr();
+ print_buserr();
+ printk(KERN_ALERT "%s bus error, epc == %0*lx, ra == %0*lx\n",
+ (regs->cp0_cause & 4) ? "Data" : "Instruction",
+ field, regs->cp0_epc, field, regs->regs[31]);
+ /* Assume it would be too dangerous to continue ... */
+ die_if_kernel("Oops", regs);
+ force_sig(SIGBUS, current);
+}
+
+static int ip22_be_handler(struct pt_regs *regs, int is_fixup)
+{
+ save_and_clear_buserr();
+ if (is_fixup)
+ return MIPS_BE_FIXUP;
+ print_buserr();
+ return MIPS_BE_FATAL;
+}
+
+void __init ip22_be_init(void)
+{
+ board_be_handler = ip22_be_handler;
+}
diff --git a/arch/mips/sgi-ip22/ip22-eisa.c b/arch/mips/sgi-ip22/ip22-eisa.c
new file mode 100644
index 0000000..0ab4abf
--- /dev/null
+++ b/arch/mips/sgi-ip22/ip22-eisa.c
@@ -0,0 +1,308 @@
+/*
+ * Basic EISA bus support for the SGI Indigo-2.
+ *
+ * (C) 2002 Pascal Dameme <netinet@freesurf.fr>
+ * and Marc Zyngier <mzyngier@freesurf.fr>
+ *
+ * This code is released under both the GPL version 2 and BSD
+ * licenses. Either license may be used.
+ *
+ * This code offers a very basic support for this EISA bus present in
+ * the SGI Indigo-2. It currently only supports PIO (forget about DMA
+ * for the time being). This is enough for a low-end ethernet card,
+ * but forget about your favorite SCSI card...
+ *
+ * TODO :
+ * - Fix bugs...
+ * - Add ISA support
+ * - Add DMA (yeah, right...).
+ * - Fix more bugs.
+ */
+
+#include <linux/config.h>
+#include <linux/eisa.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/kernel_stat.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <asm/irq.h>
+#include <asm/mipsregs.h>
+#include <asm/addrspace.h>
+#include <asm/processor.h>
+#include <asm/sgi/ioc.h>
+#include <asm/sgi/mc.h>
+#include <asm/sgi/ip22.h>
+
+#define EISA_MAX_SLOTS 4
+#define EISA_MAX_IRQ 16
+
+#define EISA_TO_PHYS(x) (0x00080000 | (x))
+#define EISA_TO_KSEG1(x) ((void *) KSEG1ADDR(EISA_TO_PHYS((x))))
+
+#define EIU_MODE_REG 0x0009ffc0
+#define EIU_STAT_REG 0x0009ffc4
+#define EIU_PREMPT_REG 0x0009ffc8
+#define EIU_QUIET_REG 0x0009ffcc
+#define EIU_INTRPT_ACK 0x00090004
+
+#define EISA_DMA1_STATUS 8
+#define EISA_INT1_CTRL 0x20
+#define EISA_INT1_MASK 0x21
+#define EISA_INT2_CTRL 0xA0
+#define EISA_INT2_MASK 0xA1
+#define EISA_DMA2_STATUS 0xD0
+#define EISA_DMA2_WRITE_SINGLE 0xD4
+#define EISA_EXT_NMI_RESET_CTRL 0x461
+#define EISA_INT1_EDGE_LEVEL 0x4D0
+#define EISA_INT2_EDGE_LEVEL 0x4D1
+#define EISA_VENDOR_ID_OFFSET 0xC80
+
+#define EIU_WRITE_32(x,y) { *((u32 *) KSEG1ADDR(x)) = (u32) (y); mb(); }
+#define EIU_READ_8(x) *((u8 *) KSEG1ADDR(x))
+#define EISA_WRITE_8(x,y) { *((u8 *) EISA_TO_KSEG1(x)) = (u8) (y); mb(); }
+#define EISA_READ_8(x) *((u8 *) EISA_TO_KSEG1(x))
+
+static char *decode_eisa_sig(u8 * sig)
+{
+ static char sig_str[8];
+ u16 rev;
+
+ if (sig[0] & 0x80)
+ return NULL;
+
+ sig_str[0] = ((sig[0] >> 2) & 0x1f) + ('A' - 1);
+ sig_str[1] = (((sig[0] & 3) << 3) | (sig[1] >> 5)) + ('A' - 1);
+ sig_str[2] = (sig[1] & 0x1f) + ('A' - 1);
+ rev = (sig[2] << 8) | sig[3];
+ sprintf(sig_str + 3, "%04X", rev);
+
+ return sig_str;
+}
+
+static void ip22_eisa_intr(int irq, void *dev_id, struct pt_regs *regs)
+{
+ u8 eisa_irq;
+ u8 dma1, dma2;
+
+ eisa_irq = EIU_READ_8(EIU_INTRPT_ACK);
+ dma1 = EISA_READ_8(EISA_DMA1_STATUS);
+ dma2 = EISA_READ_8(EISA_DMA2_STATUS);
+
+ if (eisa_irq >= EISA_MAX_IRQ) {
+ /* Oops, Bad Stuff Happened... */
+ printk(KERN_ERR "eisa_irq %d out of bound\n", eisa_irq);
+
+ EISA_WRITE_8(EISA_INT2_CTRL, 0x20);
+ EISA_WRITE_8(EISA_INT1_CTRL, 0x20);
+ } else
+ do_IRQ(eisa_irq, regs);
+}
+
+static void enable_eisa1_irq(unsigned int irq)
+{
+ unsigned long flags;
+ u8 mask;
+
+ local_irq_save(flags);
+
+ mask = EISA_READ_8(EISA_INT1_MASK);
+ mask &= ~((u8) (1 << irq));
+ EISA_WRITE_8(EISA_INT1_MASK, mask);
+
+ local_irq_restore(flags);
+}
+
+static unsigned int startup_eisa1_irq(unsigned int irq)
+{
+ u8 edge;
+
+ /* Only use edge interrupts for EISA */
+
+ edge = EISA_READ_8(EISA_INT1_EDGE_LEVEL);
+ edge &= ~((u8) (1 << irq));
+ EISA_WRITE_8(EISA_INT1_EDGE_LEVEL, edge);
+
+ enable_eisa1_irq(irq);
+ return 0;
+}
+
+static void disable_eisa1_irq(unsigned int irq)
+{
+ u8 mask;
+
+ mask = EISA_READ_8(EISA_INT1_MASK);
+ mask |= ((u8) (1 << irq));
+ EISA_WRITE_8(EISA_INT1_MASK, mask);
+}
+
+#define shutdown_eisa1_irq disable_eisa1_irq
+
+static void mask_and_ack_eisa1_irq(unsigned int irq)
+{
+ disable_eisa1_irq(irq);
+
+ EISA_WRITE_8(EISA_INT1_CTRL, 0x20);
+}
+
+static void end_eisa1_irq(unsigned int irq)
+{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
+ enable_eisa1_irq(irq);
+}
+
+static struct hw_interrupt_type ip22_eisa1_irq_type = {
+ .typename = "IP22 EISA",
+ .startup = startup_eisa1_irq,
+ .shutdown = shutdown_eisa1_irq,
+ .enable = enable_eisa1_irq,
+ .disable = disable_eisa1_irq,
+ .ack = mask_and_ack_eisa1_irq,
+ .end = end_eisa1_irq,
+};
+
+static void enable_eisa2_irq(unsigned int irq)
+{
+ unsigned long flags;
+ u8 mask;
+
+ local_irq_save(flags);
+
+ mask = EISA_READ_8(EISA_INT2_MASK);
+ mask &= ~((u8) (1 << (irq - 8)));
+ EISA_WRITE_8(EISA_INT2_MASK, mask);
+
+ local_irq_restore(flags);
+}
+
+static unsigned int startup_eisa2_irq(unsigned int irq)
+{
+ u8 edge;
+
+ /* Only use edge interrupts for EISA */
+
+ edge = EISA_READ_8(EISA_INT2_EDGE_LEVEL);
+ edge &= ~((u8) (1 << (irq - 8)));
+ EISA_WRITE_8(EISA_INT2_EDGE_LEVEL, edge);
+
+ enable_eisa2_irq(irq);
+ return 0;
+}
+
+static void disable_eisa2_irq(unsigned int irq)
+{
+ u8 mask;
+
+ mask = EISA_READ_8(EISA_INT2_MASK);
+ mask |= ((u8) (1 << (irq - 8)));
+ EISA_WRITE_8(EISA_INT2_MASK, mask);
+}
+
+#define shutdown_eisa2_irq disable_eisa2_irq
+
+static void mask_and_ack_eisa2_irq(unsigned int irq)
+{
+ disable_eisa2_irq(irq);
+
+ EISA_WRITE_8(EISA_INT2_CTRL, 0x20);
+ EISA_WRITE_8(EISA_INT1_CTRL, 0x20);
+}
+
+static void end_eisa2_irq(unsigned int irq)
+{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
+ enable_eisa2_irq(irq);
+}
+
+static struct hw_interrupt_type ip22_eisa2_irq_type = {
+ .typename = "IP22 EISA",
+ .startup = startup_eisa2_irq,
+ .shutdown = shutdown_eisa2_irq,
+ .enable = enable_eisa2_irq,
+ .disable = disable_eisa2_irq,
+ .ack = mask_and_ack_eisa2_irq,
+ .end = end_eisa2_irq,
+};
+
+static struct irqaction eisa_action = {
+ .handler = ip22_eisa_intr,
+ .name = "EISA",
+};
+
+static struct irqaction cascade_action = {
+ .handler = no_action,
+ .name = "EISA cascade",
+};
+
+int __init ip22_eisa_init(void)
+{
+ int i, c;
+ char *str;
+ u8 *slot_addr;
+
+ if (!(sgimc->systemid & SGIMC_SYSID_EPRESENT)) {
+ printk(KERN_INFO "EISA: bus not present.\n");
+ return 1;
+ }
+
+ printk(KERN_INFO "EISA: Probing bus...\n");
+ for (c = 0, i = 1; i <= EISA_MAX_SLOTS; i++) {
+ slot_addr =
+ (u8 *) EISA_TO_KSEG1((0x1000 * i) +
+ EISA_VENDOR_ID_OFFSET);
+ if ((str = decode_eisa_sig(slot_addr))) {
+ printk(KERN_INFO "EISA: slot %d : %s detected.\n",
+ i, str);
+ c++;
+ }
+ }
+ printk(KERN_INFO "EISA: Detected %d card%s.\n", c, c < 2 ? "" : "s");
+#ifdef CONFIG_ISA
+ printk(KERN_INFO "ISA support compiled in.\n");
+#endif
+
+ /* Warning : BlackMagicAhead(tm).
+ Please wave your favorite dead chicken over the busses */
+
+ /* First say hello to the EIU */
+ EIU_WRITE_32(EIU_PREMPT_REG, 0x0000FFFF);
+ EIU_WRITE_32(EIU_QUIET_REG, 1);
+ EIU_WRITE_32(EIU_MODE_REG, 0x40f3c07F);
+
+ /* Now be nice to the EISA chipset */
+ EISA_WRITE_8(EISA_EXT_NMI_RESET_CTRL, 1);
+ for (i = 0; i < 10000; i++); /* Wait long enough for the dust to settle */
+ EISA_WRITE_8(EISA_EXT_NMI_RESET_CTRL, 0);
+ EISA_WRITE_8(EISA_INT1_CTRL, 0x11);
+ EISA_WRITE_8(EISA_INT2_CTRL, 0x11);
+ EISA_WRITE_8(EISA_INT1_MASK, 0);
+ EISA_WRITE_8(EISA_INT2_MASK, 8);
+ EISA_WRITE_8(EISA_INT1_MASK, 4);
+ EISA_WRITE_8(EISA_INT2_MASK, 2);
+ EISA_WRITE_8(EISA_INT1_MASK, 1);
+ EISA_WRITE_8(EISA_INT2_MASK, 1);
+ EISA_WRITE_8(EISA_INT1_MASK, 0xfb);
+ EISA_WRITE_8(EISA_INT2_MASK, 0xff);
+ EISA_WRITE_8(EISA_DMA2_WRITE_SINGLE, 0);
+
+ for (i = SGINT_EISA; i < (SGINT_EISA + EISA_MAX_IRQ); i++) {
+ irq_desc[i].status = IRQ_DISABLED;
+ irq_desc[i].action = 0;
+ irq_desc[i].depth = 1;
+ if (i < (SGINT_EISA + 8))
+ irq_desc[i].handler = &ip22_eisa1_irq_type;
+ else
+ irq_desc[i].handler = &ip22_eisa2_irq_type;
+ }
+
+ /* Cannot use request_irq because of kmalloc not being ready at such
+ * an early stage. Yes, I've been bitten... */
+ setup_irq(SGI_EISA_IRQ, &eisa_action);
+ setup_irq(SGINT_EISA + 2, &cascade_action);
+
+ EISA_bus = 1;
+ return 0;
+}
diff --git a/arch/mips/sgi-ip22/ip22-hpc.c b/arch/mips/sgi-ip22/ip22-hpc.c
new file mode 100644
index 0000000..c0afecc
--- /dev/null
+++ b/arch/mips/sgi-ip22/ip22-hpc.c
@@ -0,0 +1,63 @@
+/*
+ * ip22-hpc.c: Routines for generic manipulation of the HPC controllers.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ * Copyright (C) 1998 Ralf Baechle
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/types.h>
+
+#include <asm/io.h>
+#include <asm/sgi/hpc3.h>
+#include <asm/sgi/ioc.h>
+#include <asm/sgi/ip22.h>
+
+struct hpc3_regs *hpc3c0, *hpc3c1;
+
+EXPORT_SYMBOL(hpc3c0);
+EXPORT_SYMBOL(hpc3c1);
+
+struct sgioc_regs *sgioc;
+
+EXPORT_SYMBOL(sgioc);
+
+/* We need software copies of these because they are write only. */
+u8 sgi_ioc_reset, sgi_ioc_write;
+
+extern char *system_type;
+
+void __init sgihpc_init(void)
+{
+ /* ioremap can't fail */
+ hpc3c0 = (struct hpc3_regs *)
+ ioremap(HPC3_CHIP0_BASE, sizeof(struct hpc3_regs));
+ hpc3c1 = (struct hpc3_regs *)
+ ioremap(HPC3_CHIP1_BASE, sizeof(struct hpc3_regs));
+ /* IOC lives in PBUS PIO channel 6 */
+ sgioc = (struct sgioc_regs *)hpc3c0->pbus_extregs[6];
+
+ hpc3c0->pbus_piocfg[6][0] |= HPC3_PIOCFG_DS16;
+ if (ip22_is_fullhouse()) {
+ /* Full House comes with INT2 which lives in PBUS PIO
+ * channel 4 */
+ sgint = (struct sgint_regs *)hpc3c0->pbus_extregs[4];
+ system_type = "SGI Indigo2";
+ } else {
+ /* Guiness comes with INT3 which is part of IOC */
+ sgint = &sgioc->int3;
+ system_type = "SGI Indy";
+ }
+
+ sgi_ioc_reset = (SGIOC_RESET_PPORT | SGIOC_RESET_KBDMOUSE |
+ SGIOC_RESET_EISA | SGIOC_RESET_ISDN |
+ SGIOC_RESET_LC0OFF);
+
+ sgi_ioc_write = (SGIOC_WRITE_EASEL | SGIOC_WRITE_NTHRESH |
+ SGIOC_WRITE_TPSPEED | SGIOC_WRITE_EPSEL |
+ SGIOC_WRITE_U0AMODE | SGIOC_WRITE_U1AMODE);
+
+ sgioc->reset = sgi_ioc_reset;
+ sgioc->write = sgi_ioc_write;
+}
diff --git a/arch/mips/sgi-ip22/ip22-int.c b/arch/mips/sgi-ip22/ip22-int.c
new file mode 100644
index 0000000..ea2844d
--- /dev/null
+++ b/arch/mips/sgi-ip22/ip22-int.c
@@ -0,0 +1,410 @@
+/*
+ * ip22-int.c: Routines for generic manipulation of the INT[23] ASIC
+ * found on INDY and Indigo2 workstations.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ * Copyright (C) 1997, 1998 Ralf Baechle (ralf@gnu.org)
+ * Copyright (C) 1999 Andrew R. Baker (andrewb@uab.edu)
+ * - Indigo2 changes
+ * - Interrupt handling fixes
+ * Copyright (C) 2001, 2003 Ladislav Michl (ladis@linux-mips.org)
+ */
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/kernel_stat.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+
+#include <asm/mipsregs.h>
+#include <asm/addrspace.h>
+
+#include <asm/sgi/ioc.h>
+#include <asm/sgi/hpc3.h>
+#include <asm/sgi/ip22.h>
+
+/* #define DEBUG_SGINT */
+
+/* So far nothing hangs here */
+#undef USE_LIO3_IRQ
+
+struct sgint_regs *sgint;
+
+static char lc0msk_to_irqnr[256];
+static char lc1msk_to_irqnr[256];
+static char lc2msk_to_irqnr[256];
+static char lc3msk_to_irqnr[256];
+
+extern asmlinkage void indyIRQ(void);
+extern int ip22_eisa_init(void);
+
+static void enable_local0_irq(unsigned int irq)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+ /* don't allow mappable interrupt to be enabled from setup_irq,
+ * we have our own way to do so */
+ if (irq != SGI_MAP_0_IRQ)
+ sgint->imask0 |= (1 << (irq - SGINT_LOCAL0));
+ local_irq_restore(flags);
+}
+
+static unsigned int startup_local0_irq(unsigned int irq)
+{
+ enable_local0_irq(irq);
+ return 0; /* Never anything pending */
+}
+
+static void disable_local0_irq(unsigned int irq)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+ sgint->imask0 &= ~(1 << (irq - SGINT_LOCAL0));
+ local_irq_restore(flags);
+}
+
+#define shutdown_local0_irq disable_local0_irq
+#define mask_and_ack_local0_irq disable_local0_irq
+
+static void end_local0_irq (unsigned int irq)
+{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+ enable_local0_irq(irq);
+}
+
+static struct hw_interrupt_type ip22_local0_irq_type = {
+ .typename = "IP22 local 0",
+ .startup = startup_local0_irq,
+ .shutdown = shutdown_local0_irq,
+ .enable = enable_local0_irq,
+ .disable = disable_local0_irq,
+ .ack = mask_and_ack_local0_irq,
+ .end = end_local0_irq,
+};
+
+static void enable_local1_irq(unsigned int irq)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+ /* don't allow mappable interrupt to be enabled from setup_irq,
+ * we have our own way to do so */
+ if (irq != SGI_MAP_1_IRQ)
+ sgint->imask1 |= (1 << (irq - SGINT_LOCAL1));
+ local_irq_restore(flags);
+}
+
+static unsigned int startup_local1_irq(unsigned int irq)
+{
+ enable_local1_irq(irq);
+ return 0; /* Never anything pending */
+}
+
+void disable_local1_irq(unsigned int irq)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+ sgint->imask1 &= ~(1 << (irq - SGINT_LOCAL1));
+ local_irq_restore(flags);
+}
+
+#define shutdown_local1_irq disable_local1_irq
+#define mask_and_ack_local1_irq disable_local1_irq
+
+static void end_local1_irq (unsigned int irq)
+{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+ enable_local1_irq(irq);
+}
+
+static struct hw_interrupt_type ip22_local1_irq_type = {
+ .typename = "IP22 local 1",
+ .startup = startup_local1_irq,
+ .shutdown = shutdown_local1_irq,
+ .enable = enable_local1_irq,
+ .disable = disable_local1_irq,
+ .ack = mask_and_ack_local1_irq,
+ .end = end_local1_irq,
+};
+
+static void enable_local2_irq(unsigned int irq)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+ sgint->imask0 |= (1 << (SGI_MAP_0_IRQ - SGINT_LOCAL0));
+ sgint->cmeimask0 |= (1 << (irq - SGINT_LOCAL2));
+ local_irq_restore(flags);
+}
+
+static unsigned int startup_local2_irq(unsigned int irq)
+{
+ enable_local2_irq(irq);
+ return 0; /* Never anything pending */
+}
+
+void disable_local2_irq(unsigned int irq)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+ sgint->cmeimask0 &= ~(1 << (irq - SGINT_LOCAL2));
+ if (!sgint->cmeimask0)
+ sgint->imask0 &= ~(1 << (SGI_MAP_0_IRQ - SGINT_LOCAL0));
+ local_irq_restore(flags);
+}
+
+#define shutdown_local2_irq disable_local2_irq
+#define mask_and_ack_local2_irq disable_local2_irq
+
+static void end_local2_irq (unsigned int irq)
+{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+ enable_local2_irq(irq);
+}
+
+static struct hw_interrupt_type ip22_local2_irq_type = {
+ .typename = "IP22 local 2",
+ .startup = startup_local2_irq,
+ .shutdown = shutdown_local2_irq,
+ .enable = enable_local2_irq,
+ .disable = disable_local2_irq,
+ .ack = mask_and_ack_local2_irq,
+ .end = end_local2_irq,
+};
+
+static void enable_local3_irq(unsigned int irq)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+ sgint->imask1 |= (1 << (SGI_MAP_1_IRQ - SGINT_LOCAL1));
+ sgint->cmeimask1 |= (1 << (irq - SGINT_LOCAL3));
+ local_irq_restore(flags);
+}
+
+static unsigned int startup_local3_irq(unsigned int irq)
+{
+ enable_local3_irq(irq);
+ return 0; /* Never anything pending */
+}
+
+void disable_local3_irq(unsigned int irq)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+ sgint->cmeimask1 &= ~(1 << (irq - SGINT_LOCAL3));
+ if (!sgint->cmeimask1)
+ sgint->imask1 &= ~(1 << (SGI_MAP_1_IRQ - SGINT_LOCAL1));
+ local_irq_restore(flags);
+}
+
+#define shutdown_local3_irq disable_local3_irq
+#define mask_and_ack_local3_irq disable_local3_irq
+
+static void end_local3_irq (unsigned int irq)
+{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+ enable_local3_irq(irq);
+}
+
+static struct hw_interrupt_type ip22_local3_irq_type = {
+ .typename = "IP22 local 3",
+ .startup = startup_local3_irq,
+ .shutdown = shutdown_local3_irq,
+ .enable = enable_local3_irq,
+ .disable = disable_local3_irq,
+ .ack = mask_and_ack_local3_irq,
+ .end = end_local3_irq,
+};
+
+void indy_local0_irqdispatch(struct pt_regs *regs)
+{
+ u8 mask = sgint->istat0 & sgint->imask0;
+ u8 mask2;
+ int irq;
+
+ if (mask & SGINT_ISTAT0_LIO2) {
+ mask2 = sgint->vmeistat & sgint->cmeimask0;
+ irq = lc2msk_to_irqnr[mask2];
+ } else
+ irq = lc0msk_to_irqnr[mask];
+
+ /* if irq == 0, then the interrupt has already been cleared */
+ if (irq)
+ do_IRQ(irq, regs);
+ return;
+}
+
+void indy_local1_irqdispatch(struct pt_regs *regs)
+{
+ u8 mask = sgint->istat1 & sgint->imask1;
+ u8 mask2;
+ int irq;
+
+ if (mask & SGINT_ISTAT1_LIO3) {
+ mask2 = sgint->vmeistat & sgint->cmeimask1;
+ irq = lc3msk_to_irqnr[mask2];
+ } else
+ irq = lc1msk_to_irqnr[mask];
+
+ /* if irq == 0, then the interrupt has already been cleared */
+ if (irq)
+ do_IRQ(irq, regs);
+ return;
+}
+
+extern void ip22_be_interrupt(int irq, struct pt_regs *regs);
+
+void indy_buserror_irq(struct pt_regs *regs)
+{
+ int irq = SGI_BUSERR_IRQ;
+
+ irq_enter();
+ kstat_this_cpu.irqs[irq]++;
+ ip22_be_interrupt(irq, regs);
+ irq_exit();
+}
+
+static struct irqaction local0_cascade = {
+ .handler = no_action,
+ .flags = SA_INTERRUPT,
+ .name = "local0 cascade",
+};
+
+static struct irqaction local1_cascade = {
+ .handler = no_action,
+ .flags = SA_INTERRUPT,
+ .name = "local1 cascade",
+};
+
+static struct irqaction buserr = {
+ .handler = no_action,
+ .flags = SA_INTERRUPT,
+ .name = "Bus Error",
+};
+
+static struct irqaction map0_cascade = {
+ .handler = no_action,
+ .flags = SA_INTERRUPT,
+ .name = "mapable0 cascade",
+};
+
+#ifdef USE_LIO3_IRQ
+static struct irqaction map1_cascade = {
+ .handler = no_action,
+ .flags = SA_INTERRUPT,
+ .name = "mapable1 cascade",
+};
+#define SGI_INTERRUPTS SGINT_END
+#else
+#define SGI_INTERRUPTS SGINT_LOCAL3
+#endif
+
+extern void mips_cpu_irq_init(unsigned int irq_base);
+
+void __init arch_init_irq(void)
+{
+ int i;
+
+ /* Init local mask --> irq tables. */
+ for (i = 0; i < 256; i++) {
+ if (i & 0x80) {
+ lc0msk_to_irqnr[i] = SGINT_LOCAL0 + 7;
+ lc1msk_to_irqnr[i] = SGINT_LOCAL1 + 7;
+ lc2msk_to_irqnr[i] = SGINT_LOCAL2 + 7;
+ lc3msk_to_irqnr[i] = SGINT_LOCAL3 + 7;
+ } else if (i & 0x40) {
+ lc0msk_to_irqnr[i] = SGINT_LOCAL0 + 6;
+ lc1msk_to_irqnr[i] = SGINT_LOCAL1 + 6;
+ lc2msk_to_irqnr[i] = SGINT_LOCAL2 + 6;
+ lc3msk_to_irqnr[i] = SGINT_LOCAL3 + 6;
+ } else if (i & 0x20) {
+ lc0msk_to_irqnr[i] = SGINT_LOCAL0 + 5;
+ lc1msk_to_irqnr[i] = SGINT_LOCAL1 + 5;
+ lc2msk_to_irqnr[i] = SGINT_LOCAL2 + 5;
+ lc3msk_to_irqnr[i] = SGINT_LOCAL3 + 5;
+ } else if (i & 0x10) {
+ lc0msk_to_irqnr[i] = SGINT_LOCAL0 + 4;
+ lc1msk_to_irqnr[i] = SGINT_LOCAL1 + 4;
+ lc2msk_to_irqnr[i] = SGINT_LOCAL2 + 4;
+ lc3msk_to_irqnr[i] = SGINT_LOCAL3 + 4;
+ } else if (i & 0x08) {
+ lc0msk_to_irqnr[i] = SGINT_LOCAL0 + 3;
+ lc1msk_to_irqnr[i] = SGINT_LOCAL1 + 3;
+ lc2msk_to_irqnr[i] = SGINT_LOCAL2 + 3;
+ lc3msk_to_irqnr[i] = SGINT_LOCAL3 + 3;
+ } else if (i & 0x04) {
+ lc0msk_to_irqnr[i] = SGINT_LOCAL0 + 2;
+ lc1msk_to_irqnr[i] = SGINT_LOCAL1 + 2;
+ lc2msk_to_irqnr[i] = SGINT_LOCAL2 + 2;
+ lc3msk_to_irqnr[i] = SGINT_LOCAL3 + 2;
+ } else if (i & 0x02) {
+ lc0msk_to_irqnr[i] = SGINT_LOCAL0 + 1;
+ lc1msk_to_irqnr[i] = SGINT_LOCAL1 + 1;
+ lc2msk_to_irqnr[i] = SGINT_LOCAL2 + 1;
+ lc3msk_to_irqnr[i] = SGINT_LOCAL3 + 1;
+ } else if (i & 0x01) {
+ lc0msk_to_irqnr[i] = SGINT_LOCAL0 + 0;
+ lc1msk_to_irqnr[i] = SGINT_LOCAL1 + 0;
+ lc2msk_to_irqnr[i] = SGINT_LOCAL2 + 0;
+ lc3msk_to_irqnr[i] = SGINT_LOCAL3 + 0;
+ } else {
+ lc0msk_to_irqnr[i] = 0;
+ lc1msk_to_irqnr[i] = 0;
+ lc2msk_to_irqnr[i] = 0;
+ lc3msk_to_irqnr[i] = 0;
+ }
+ }
+
+ /* Mask out all interrupts. */
+ sgint->imask0 = 0;
+ sgint->imask1 = 0;
+ sgint->cmeimask0 = 0;
+ sgint->cmeimask1 = 0;
+
+ set_except_vector(0, indyIRQ);
+
+ /* init CPU irqs */
+ mips_cpu_irq_init(SGINT_CPU);
+
+ for (i = SGINT_LOCAL0; i < SGI_INTERRUPTS; i++) {
+ hw_irq_controller *handler;
+
+ if (i < SGINT_LOCAL1)
+ handler = &ip22_local0_irq_type;
+ else if (i < SGINT_LOCAL2)
+ handler = &ip22_local1_irq_type;
+ else if (i < SGINT_LOCAL3)
+ handler = &ip22_local2_irq_type;
+ else
+ handler = &ip22_local3_irq_type;
+
+ irq_desc[i].status = IRQ_DISABLED;
+ irq_desc[i].action = 0;
+ irq_desc[i].depth = 1;
+ irq_desc[i].handler = handler;
+ }
+
+ /* vector handler. this register the IRQ as non-sharable */
+ setup_irq(SGI_LOCAL_0_IRQ, &local0_cascade);
+ setup_irq(SGI_LOCAL_1_IRQ, &local1_cascade);
+ setup_irq(SGI_BUSERR_IRQ, &buserr);
+
+ /* cascade in cascade. i love Indy ;-) */
+ setup_irq(SGI_MAP_0_IRQ, &map0_cascade);
+#ifdef USE_LIO3_IRQ
+ setup_irq(SGI_MAP_1_IRQ, &map1_cascade);
+#endif
+
+#ifdef CONFIG_EISA
+ if (ip22_is_fullhouse()) /* Only Indigo-2 has EISA stuff */
+ ip22_eisa_init ();
+#endif
+}
diff --git a/arch/mips/sgi-ip22/ip22-irq.S b/arch/mips/sgi-ip22/ip22-irq.S
new file mode 100644
index 0000000..6ccbd9e
--- /dev/null
+++ b/arch/mips/sgi-ip22/ip22-irq.S
@@ -0,0 +1,118 @@
+/*
+ * ip22-irq.S: Interrupt exception dispatch code for FullHouse and
+ * Guiness.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+
+#include <asm/asm.h>
+#include <asm/mipsregs.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+
+/* A lot of complication here is taken away because:
+ *
+ * 1) We handle one interrupt and return, sitting in a loop and moving across
+ * all the pending IRQ bits in the cause register is _NOT_ the answer, the
+ * common case is one pending IRQ so optimize in that direction.
+ *
+ * 2) We need not check against bits in the status register IRQ mask, that
+ * would make this routine slow as hell.
+ *
+ * 3) Linux only thinks in terms of all IRQs on or all IRQs off, nothing in
+ * between like BSD spl() brain-damage.
+ *
+ * Furthermore, the IRQs on the INDY look basically (barring software IRQs
+ * which we don't use at all) like:
+ *
+ * MIPS IRQ Source
+ * -------- ------
+ * 0 Software (ignored)
+ * 1 Software (ignored)
+ * 2 Local IRQ level zero
+ * 3 Local IRQ level one
+ * 4 8254 Timer zero
+ * 5 8254 Timer one
+ * 6 Bus Error
+ * 7 R4k timer (what we use)
+ *
+ * We handle the IRQ according to _our_ priority which is:
+ *
+ * Highest ---- R4k Timer
+ * Local IRQ zero
+ * Local IRQ one
+ * Bus Error
+ * 8254 Timer zero
+ * Lowest ---- 8254 Timer one
+ *
+ * then we just return, if multiple IRQs are pending then we will just take
+ * another exception, big deal.
+ */
+
+ .text
+ .set noreorder
+ .set noat
+ .align 5
+ NESTED(indyIRQ, PT_SIZE, sp)
+ SAVE_ALL
+ CLI
+ .set at
+ mfc0 s0, CP0_CAUSE # get irq mask
+
+ /* First we check for r4k counter/timer IRQ. */
+ andi a0, s0, CAUSEF_IP7
+ beq a0, zero, 1f
+ andi a0, s0, CAUSEF_IP2 # delay slot, check local level zero
+
+ /* Wheee, a timer interrupt. */
+ jal indy_r4k_timer_interrupt
+ move a0, sp # delay slot
+ j ret_from_irq
+ nop # delay slot
+
+1:
+ beq a0, zero, 1f
+ andi a0, s0, CAUSEF_IP3 # delay slot, check local level one
+
+ /* Wheee, local level zero interrupt. */
+ jal indy_local0_irqdispatch
+ move a0, sp # delay slot
+
+ j ret_from_irq
+ nop # delay slot
+
+1:
+ beq a0, zero, 1f
+ andi a0, s0, CAUSEF_IP6 # delay slot, check bus error
+
+ /* Wheee, local level one interrupt. */
+ jal indy_local1_irqdispatch
+ move a0, sp # delay slot
+ j ret_from_irq
+ nop # delay slot
+
+1:
+ beq a0, zero, 1f
+ andi a0, s0, (CAUSEF_IP4 | CAUSEF_IP5) # delay slot
+
+ /* Wheee, an asynchronous bus error... */
+ jal indy_buserror_irq
+ move a0, sp # delay slot
+ j ret_from_irq
+ nop # delay slot
+
+1:
+ /* Here by mistake? It is possible, that by the time we take
+ * the exception the IRQ pin goes low, so just leave if this
+ * is the case.
+ */
+ beq a0, zero, 1f
+ nop # delay slot
+
+ /* Must be one of the 8254 timers... */
+ jal indy_8254timer_irq
+ move a0, sp # delay slot
+1:
+ j ret_from_irq
+ nop # delay slot
+ END(indyIRQ)
diff --git a/arch/mips/sgi-ip22/ip22-mc.c b/arch/mips/sgi-ip22/ip22-mc.c
new file mode 100644
index 0000000..b58bd52
--- /dev/null
+++ b/arch/mips/sgi-ip22/ip22-mc.c
@@ -0,0 +1,208 @@
+/*
+ * ip22-mc.c: Routines for manipulating SGI Memory Controller.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ * Copyright (C) 1999 Andrew R. Baker (andrewb@uab.edu) - Indigo2 changes
+ * Copyright (C) 2003 Ladislav Michl (ladis@linux-mips.org)
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+
+#include <asm/io.h>
+#include <asm/bootinfo.h>
+#include <asm/sgialib.h>
+#include <asm/sgi/mc.h>
+#include <asm/sgi/hpc3.h>
+#include <asm/sgi/ip22.h>
+
+struct sgimc_regs *sgimc;
+
+EXPORT_SYMBOL(sgimc);
+
+static inline unsigned long get_bank_addr(unsigned int memconfig)
+{
+ return ((memconfig & SGIMC_MCONFIG_BASEADDR) <<
+ ((sgimc->systemid & SGIMC_SYSID_MASKREV) >= 5 ? 24 : 22));
+}
+
+static inline unsigned long get_bank_size(unsigned int memconfig)
+{
+ return ((memconfig & SGIMC_MCONFIG_RMASK) + 0x0100) <<
+ ((sgimc->systemid & SGIMC_SYSID_MASKREV) >= 5 ? 16 : 14);
+}
+
+static inline unsigned int get_bank_config(int bank)
+{
+ unsigned int res = bank > 1 ? sgimc->mconfig1 : sgimc->mconfig0;
+ return bank % 2 ? res & 0xffff : res >> 16;
+}
+
+struct mem {
+ unsigned long addr;
+ unsigned long size;
+};
+
+/*
+ * Detect installed memory, do some sanity checks and notify kernel about it
+ */
+static void probe_memory(void)
+{
+ int i, j, found, cnt = 0;
+ struct mem bank[4];
+ struct mem space[2] = {{SGIMC_SEG0_BADDR, 0}, {SGIMC_SEG1_BADDR, 0}};
+
+ printk(KERN_INFO "MC: Probing memory configuration:\n");
+ for (i = 0; i < ARRAY_SIZE(bank); i++) {
+ unsigned int tmp = get_bank_config(i);
+ if (!(tmp & SGIMC_MCONFIG_BVALID))
+ continue;
+
+ bank[cnt].size = get_bank_size(tmp);
+ bank[cnt].addr = get_bank_addr(tmp);
+ printk(KERN_INFO " bank%d: %3ldM @ %08lx\n",
+ i, bank[cnt].size / 1024 / 1024, bank[cnt].addr);
+ cnt++;
+ }
+
+ /* And you thought bubble sort is dead algorithm... */
+ do {
+ unsigned long addr, size;
+
+ found = 0;
+ for (i = 1; i < cnt; i++)
+ if (bank[i-1].addr > bank[i].addr) {
+ addr = bank[i].addr;
+ size = bank[i].size;
+ bank[i].addr = bank[i-1].addr;
+ bank[i].size = bank[i-1].size;
+ bank[i-1].addr = addr;
+ bank[i-1].size = size;
+ found = 1;
+ }
+ } while (found);
+
+ /* Figure out how are memory banks mapped into spaces */
+ for (i = 0; i < cnt; i++) {
+ found = 0;
+ for (j = 0; j < ARRAY_SIZE(space) && !found; j++)
+ if (space[j].addr + space[j].size == bank[i].addr) {
+ space[j].size += bank[i].size;
+ found = 1;
+ }
+ /* There is either hole or overlapping memory */
+ if (!found)
+ printk(KERN_CRIT "MC: Memory configuration mismatch "
+ "(%08lx), expect Bus Error soon\n",
+ bank[i].addr);
+ }
+
+ for (i = 0; i < ARRAY_SIZE(space); i++)
+ if (space[i].size)
+ add_memory_region(space[i].addr, space[i].size,
+ BOOT_MEM_RAM);
+}
+
+void __init sgimc_init(void)
+{
+ u32 tmp;
+
+ /* ioremap can't fail */
+ sgimc = (struct sgimc_regs *)
+ ioremap(SGIMC_BASE, sizeof(struct sgimc_regs));
+
+ printk(KERN_INFO "MC: SGI memory controller Revision %d\n",
+ (int) sgimc->systemid & SGIMC_SYSID_MASKREV);
+
+ /* Place the MC into a known state. This must be done before
+ * interrupts are first enabled etc.
+ */
+
+ /* Step 0: Make sure we turn off the watchdog in case it's
+ * still running (which might be the case after a
+ * soft reboot).
+ */
+ tmp = sgimc->cpuctrl0;
+ tmp &= ~SGIMC_CCTRL0_WDOG;
+ sgimc->cpuctrl0 = tmp;
+
+ /* Step 1: The CPU/GIO error status registers will not latch
+ * up a new error status until the register has been
+ * cleared by the cpu. These status registers are
+ * cleared by writing any value to them.
+ */
+ sgimc->cstat = sgimc->gstat = 0;
+
+ /* Step 2: Enable all parity checking in cpu control register
+ * zero.
+ */
+ tmp = sgimc->cpuctrl0;
+ tmp |= (SGIMC_CCTRL0_EPERRGIO | SGIMC_CCTRL0_EPERRMEM |
+ SGIMC_CCTRL0_R4KNOCHKPARR);
+ sgimc->cpuctrl0 = tmp;
+
+ /* Step 3: Setup the MC write buffer depth, this is controlled
+ * in cpu control register 1 in the lower 4 bits.
+ */
+ tmp = sgimc->cpuctrl1;
+ tmp &= ~0xf;
+ tmp |= 0xd;
+ sgimc->cpuctrl1 = tmp;
+
+ /* Step 4: Initialize the RPSS divider register to run as fast
+ * as it can correctly operate. The register is laid
+ * out as follows:
+ *
+ * ----------------------------------------
+ * | RESERVED | INCREMENT | DIVIDER |
+ * ----------------------------------------
+ * 31 16 15 8 7 0
+ *
+ * DIVIDER determines how often a 'tick' happens,
+ * INCREMENT determines by how the RPSS increment
+ * registers value increases at each 'tick'. Thus,
+ * for IP22 we get INCREMENT=1, DIVIDER=1 == 0x101
+ */
+ sgimc->divider = 0x101;
+
+ /* Step 5: Initialize GIO64 arbitrator configuration register.
+ *
+ * NOTE: HPC init code in sgihpc_init() must run before us because
+ * we need to know Guiness vs. FullHouse and the board
+ * revision on this machine. You have been warned.
+ */
+
+ /* First the basic invariants across all GIO64 implementations. */
+ tmp = SGIMC_GIOPAR_HPC64; /* All 1st HPC's interface at 64bits */
+ tmp |= SGIMC_GIOPAR_ONEBUS; /* Only one physical GIO bus exists */
+
+ if (ip22_is_fullhouse()) {
+ /* Fullhouse specific settings. */
+ if (SGIOC_SYSID_BOARDREV(sgioc->sysid) < 2) {
+ tmp |= SGIMC_GIOPAR_HPC264; /* 2nd HPC at 64bits */
+ tmp |= SGIMC_GIOPAR_PLINEEXP0; /* exp0 pipelines */
+ tmp |= SGIMC_GIOPAR_MASTEREXP1; /* exp1 masters */
+ tmp |= SGIMC_GIOPAR_RTIMEEXP0; /* exp0 is realtime */
+ } else {
+ tmp |= SGIMC_GIOPAR_HPC264; /* 2nd HPC 64bits */
+ tmp |= SGIMC_GIOPAR_PLINEEXP0; /* exp[01] pipelined */
+ tmp |= SGIMC_GIOPAR_PLINEEXP1;
+ tmp |= SGIMC_GIOPAR_MASTEREISA; /* EISA masters */
+ tmp |= SGIMC_GIOPAR_GFX64; /* GFX at 64 bits */
+ }
+ } else {
+ /* Guiness specific settings. */
+ tmp |= SGIMC_GIOPAR_EISA64; /* MC talks to EISA at 64bits */
+ tmp |= SGIMC_GIOPAR_MASTEREISA; /* EISA bus can act as master */
+ }
+ sgimc->giopar = tmp; /* poof */
+
+ probe_memory();
+}
+
+void __init prom_meminit(void) {}
+unsigned long __init prom_free_prom_memory(void)
+{
+ return 0;
+}
diff --git a/arch/mips/sgi-ip22/ip22-nvram.c b/arch/mips/sgi-ip22/ip22-nvram.c
new file mode 100644
index 0000000..de43e86
--- /dev/null
+++ b/arch/mips/sgi-ip22/ip22-nvram.c
@@ -0,0 +1,119 @@
+/*
+ * ip22-nvram.c: NVRAM and serial EEPROM handling.
+ *
+ * Copyright (C) 2003 Ladislav Michl (ladis@linux-mips.org)
+ */
+#include <linux/module.h>
+
+#include <asm/sgi/hpc3.h>
+#include <asm/sgi/ip22.h>
+
+/* Control opcode for serial eeprom */
+#define EEPROM_READ 0xc000 /* serial memory read */
+#define EEPROM_WEN 0x9800 /* write enable before prog modes */
+#define EEPROM_WRITE 0xa000 /* serial memory write */
+#define EEPROM_WRALL 0x8800 /* write all registers */
+#define EEPROM_WDS 0x8000 /* disable all programming */
+#define EEPROM_PRREAD 0xc000 /* read protect register */
+#define EEPROM_PREN 0x9800 /* enable protect register mode */
+#define EEPROM_PRCLEAR 0xffff /* clear protect register */
+#define EEPROM_PRWRITE 0xa000 /* write protect register */
+#define EEPROM_PRDS 0x8000 /* disable protect register, forever */
+
+#define EEPROM_EPROT 0x01 /* Protect register enable */
+#define EEPROM_CSEL 0x02 /* Chip select */
+#define EEPROM_ECLK 0x04 /* EEPROM clock */
+#define EEPROM_DATO 0x08 /* Data out */
+#define EEPROM_DATI 0x10 /* Data in */
+
+/* We need to use these functions early... */
+#define delay() ({ \
+ int x; \
+ for (x=0; x<100000; x++) __asm__ __volatile__(""); })
+
+#define eeprom_cs_on(ptr) ({ \
+ *ptr &= ~EEPROM_DATO; \
+ *ptr &= ~EEPROM_ECLK; \
+ *ptr &= ~EEPROM_EPROT; \
+ delay(); \
+ *ptr |= EEPROM_CSEL; \
+ *ptr |= EEPROM_ECLK; })
+
+
+#define eeprom_cs_off(ptr) ({ \
+ *ptr &= ~EEPROM_ECLK; \
+ *ptr &= ~EEPROM_CSEL; \
+ *ptr |= EEPROM_EPROT; \
+ *ptr |= EEPROM_ECLK; })
+
+#define BITS_IN_COMMAND 11
+/*
+ * clock in the nvram command and the register number. For the
+ * national semiconductor nv ram chip the op code is 3 bits and
+ * the address is 6/8 bits.
+ */
+static inline void eeprom_cmd(volatile unsigned int *ctrl, unsigned cmd,
+ unsigned reg)
+{
+ unsigned short ser_cmd;
+ int i;
+
+ ser_cmd = cmd | (reg << (16 - BITS_IN_COMMAND));
+ for (i = 0; i < BITS_IN_COMMAND; i++) {
+ if (ser_cmd & (1<<15)) /* if high order bit set */
+ *ctrl |= EEPROM_DATO;
+ else
+ *ctrl &= ~EEPROM_DATO;
+ *ctrl &= ~EEPROM_ECLK;
+ *ctrl |= EEPROM_ECLK;
+ ser_cmd <<= 1;
+ }
+ *ctrl &= ~EEPROM_DATO; /* see data sheet timing diagram */
+}
+
+unsigned short ip22_eeprom_read(volatile unsigned int *ctrl, int reg)
+{
+ unsigned short res = 0;
+ int i;
+
+ *ctrl &= ~EEPROM_EPROT;
+ eeprom_cs_on(ctrl);
+ eeprom_cmd(ctrl, EEPROM_READ, reg);
+
+ /* clock the data ouf of serial mem */
+ for (i = 0; i < 16; i++) {
+ *ctrl &= ~EEPROM_ECLK;
+ delay();
+ *ctrl |= EEPROM_ECLK;
+ delay();
+ res <<= 1;
+ if (*ctrl & EEPROM_DATI)
+ res |= 1;
+ }
+
+ eeprom_cs_off(ctrl);
+
+ return res;
+}
+
+EXPORT_SYMBOL(ip22_eeprom_read);
+
+/*
+ * Read specified register from main NVRAM
+ */
+unsigned short ip22_nvram_read(int reg)
+{
+ if (ip22_is_fullhouse())
+ /* IP22 (Indigo2 aka FullHouse) stores env variables into
+ * 93CS56 Microwire Bus EEPROM 2048 Bit (128x16) */
+ return ip22_eeprom_read(&hpc3c0->eeprom, reg);
+ else {
+ unsigned short tmp;
+ /* IP24 (Indy aka Guiness) uses DS1386 8K version */
+ reg <<= 1;
+ tmp = hpc3c0->bbram[reg++] & 0xff;
+ return (tmp << 8) | (hpc3c0->bbram[reg] & 0xff);
+ }
+}
+
+EXPORT_SYMBOL(ip22_nvram_read);
diff --git a/arch/mips/sgi-ip22/ip22-reset.c b/arch/mips/sgi-ip22/ip22-reset.c
new file mode 100644
index 0000000..ed5c60a
--- /dev/null
+++ b/arch/mips/sgi-ip22/ip22-reset.c
@@ -0,0 +1,247 @@
+/*
+ * 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) 1997, 1998, 2001, 2003 by Ralf Baechle
+ */
+#include <linux/init.h>
+#include <linux/ds1286.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/notifier.h>
+#include <linux/timer.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+#include <asm/reboot.h>
+#include <asm/sgialib.h>
+#include <asm/sgi/ioc.h>
+#include <asm/sgi/hpc3.h>
+#include <asm/sgi/mc.h>
+#include <asm/sgi/ip22.h>
+
+/*
+ * Just powerdown if init hasn't done after POWERDOWN_TIMEOUT seconds.
+ * I'm not sure if this feature is a good idea, for now it's here just to
+ * make the power button make behave just like under IRIX.
+ */
+#define POWERDOWN_TIMEOUT 120
+
+/*
+ * Blink frequency during reboot grace period and when paniced.
+ */
+#define POWERDOWN_FREQ (HZ / 4)
+#define PANIC_FREQ (HZ / 8)
+
+static struct timer_list power_timer, blink_timer, debounce_timer, volume_timer;
+
+#define MACHINE_PANICED 1
+#define MACHINE_SHUTTING_DOWN 2
+static int machine_state = 0;
+
+static void sgi_machine_restart(char *command) __attribute__((noreturn));
+static void sgi_machine_halt(void) __attribute__((noreturn));
+static void sgi_machine_power_off(void) __attribute__((noreturn));
+
+static void sgi_machine_restart(char *command)
+{
+ if (machine_state & MACHINE_SHUTTING_DOWN)
+ sgi_machine_power_off();
+ sgimc->cpuctrl0 |= SGIMC_CCTRL0_SYSINIT;
+ while (1);
+}
+
+static void sgi_machine_halt(void)
+{
+ if (machine_state & MACHINE_SHUTTING_DOWN)
+ sgi_machine_power_off();
+ ArcEnterInteractiveMode();
+}
+
+static void sgi_machine_power_off(void)
+{
+ unsigned int tmp;
+
+ local_irq_disable();
+
+ /* Disable watchdog */
+ tmp = hpc3c0->rtcregs[RTC_CMD] & 0xff;
+ hpc3c0->rtcregs[RTC_CMD] = tmp | RTC_WAM;
+ hpc3c0->rtcregs[RTC_WSEC] = 0;
+ hpc3c0->rtcregs[RTC_WHSEC] = 0;
+
+ while (1) {
+ sgioc->panel = ~SGIOC_PANEL_POWERON;
+ /* Good bye cruel world ... */
+
+ /* If we're still running, we probably got sent an alarm
+ interrupt. Read the flag to clear it. */
+ tmp = hpc3c0->rtcregs[RTC_HOURS_ALARM];
+ }
+}
+
+static void power_timeout(unsigned long data)
+{
+ sgi_machine_power_off();
+}
+
+static void blink_timeout(unsigned long data)
+{
+ /* XXX fix this for fullhouse */
+ sgi_ioc_reset ^= (SGIOC_RESET_LC0OFF|SGIOC_RESET_LC1OFF);
+ sgioc->reset = sgi_ioc_reset;
+
+ mod_timer(&blink_timer, jiffies+data);
+}
+
+static void debounce(unsigned long data)
+{
+ del_timer(&debounce_timer);
+ if (sgint->istat1 & SGINT_ISTAT1_PWR) {
+ /* Interrupt still being sent. */
+ debounce_timer.expires = jiffies + 5; /* 0.05s */
+ add_timer(&debounce_timer);
+
+ sgioc->panel = SGIOC_PANEL_POWERON | SGIOC_PANEL_POWERINTR |
+ SGIOC_PANEL_VOLDNINTR | SGIOC_PANEL_VOLDNHOLD |
+ SGIOC_PANEL_VOLUPINTR | SGIOC_PANEL_VOLUPHOLD;
+
+ return;
+ }
+
+ if (machine_state & MACHINE_PANICED)
+ sgimc->cpuctrl0 |= SGIMC_CCTRL0_SYSINIT;
+
+ enable_irq(SGI_PANEL_IRQ);
+}
+
+static inline void power_button(void)
+{
+ if (machine_state & MACHINE_PANICED)
+ return;
+
+ if ((machine_state & MACHINE_SHUTTING_DOWN) || kill_proc(1,SIGINT,1)) {
+ /* No init process or button pressed twice. */
+ sgi_machine_power_off();
+ }
+
+ machine_state |= MACHINE_SHUTTING_DOWN;
+ blink_timer.data = POWERDOWN_FREQ;
+ blink_timeout(POWERDOWN_FREQ);
+
+ init_timer(&power_timer);
+ power_timer.function = power_timeout;
+ power_timer.expires = jiffies + POWERDOWN_TIMEOUT * HZ;
+ add_timer(&power_timer);
+}
+
+void (*indy_volume_button)(int) = NULL;
+
+EXPORT_SYMBOL(indy_volume_button);
+
+static inline void volume_up_button(unsigned long data)
+{
+ del_timer(&volume_timer);
+
+ if (indy_volume_button)
+ indy_volume_button(1);
+
+ if (sgint->istat1 & SGINT_ISTAT1_PWR) {
+ volume_timer.expires = jiffies + 1;
+ add_timer(&volume_timer);
+ }
+}
+
+static inline void volume_down_button(unsigned long data)
+{
+ del_timer(&volume_timer);
+
+ if (indy_volume_button)
+ indy_volume_button(-1);
+
+ if (sgint->istat1 & SGINT_ISTAT1_PWR) {
+ volume_timer.expires = jiffies + 1;
+ add_timer(&volume_timer);
+ }
+}
+
+static irqreturn_t panel_int(int irq, void *dev_id, struct pt_regs *regs)
+{
+ unsigned int buttons;
+
+ buttons = sgioc->panel;
+ sgioc->panel = SGIOC_PANEL_POWERON | SGIOC_PANEL_POWERINTR;
+
+ if (sgint->istat1 & SGINT_ISTAT1_PWR) {
+ /* Wait until interrupt goes away */
+ disable_irq(SGI_PANEL_IRQ);
+ init_timer(&debounce_timer);
+ debounce_timer.function = debounce;
+ debounce_timer.expires = jiffies + 5;
+ add_timer(&debounce_timer);
+ }
+
+ /* Power button was pressed
+ * ioc.ps page 22: "The Panel Register is called Power Control by Full
+ * House. Only lowest 2 bits are used. Guiness uses upper four bits
+ * for volume control". This is not true, all bits are pulled high
+ * on fullhouse */
+ if (ip22_is_fullhouse() || !(buttons & SGIOC_PANEL_POWERINTR)) {
+ power_button();
+ return IRQ_HANDLED;
+ }
+ /* TODO: mute/unmute */
+ /* Volume up button was pressed */
+ if (!(buttons & SGIOC_PANEL_VOLUPINTR)) {
+ init_timer(&volume_timer);
+ volume_timer.function = volume_up_button;
+ volume_timer.expires = jiffies + 1;
+ add_timer(&volume_timer);
+ }
+ /* Volume down button was pressed */
+ if (!(buttons & SGIOC_PANEL_VOLDNINTR)) {
+ init_timer(&volume_timer);
+ volume_timer.function = volume_down_button;
+ volume_timer.expires = jiffies + 1;
+ add_timer(&volume_timer);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static int panic_event(struct notifier_block *this, unsigned long event,
+ void *ptr)
+{
+ if (machine_state & MACHINE_PANICED)
+ return NOTIFY_DONE;
+ machine_state |= MACHINE_PANICED;
+
+ blink_timer.data = PANIC_FREQ;
+ blink_timeout(PANIC_FREQ);
+
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block panic_block = {
+ .notifier_call = panic_event,
+};
+
+static int __init reboot_setup(void)
+{
+ _machine_restart = sgi_machine_restart;
+ _machine_halt = sgi_machine_halt;
+ _machine_power_off = sgi_machine_power_off;
+
+ request_irq(SGI_PANEL_IRQ, panel_int, 0, "Front Panel", NULL);
+ init_timer(&blink_timer);
+ blink_timer.function = blink_timeout;
+ notifier_chain_register(&panic_notifier_list, &panic_block);
+
+ return 0;
+}
+
+subsys_initcall(reboot_setup);
diff --git a/arch/mips/sgi-ip22/ip22-setup.c b/arch/mips/sgi-ip22/ip22-setup.c
new file mode 100644
index 0000000..0e96a5d
--- /dev/null
+++ b/arch/mips/sgi-ip22/ip22-setup.c
@@ -0,0 +1,144 @@
+/*
+ * ip22-setup.c: SGI specific setup, including init of the feature struct.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ * Copyright (C) 1997, 1998 Ralf Baechle (ralf@gnu.org)
+ */
+#include <linux/config.h>
+#include <linux/ds1286.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/kdev_t.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/console.h>
+#include <linux/sched.h>
+#include <linux/tty.h>
+
+#include <asm/addrspace.h>
+#include <asm/bcache.h>
+#include <asm/bootinfo.h>
+#include <asm/irq.h>
+#include <asm/reboot.h>
+#include <asm/time.h>
+#include <asm/gdb-stub.h>
+#include <asm/io.h>
+#include <asm/traps.h>
+#include <asm/sgialib.h>
+#include <asm/sgi/mc.h>
+#include <asm/sgi/hpc3.h>
+#include <asm/sgi/ip22.h>
+
+unsigned long sgi_gfxaddr;
+
+/*
+ * Stop-A is originally a Sun thing that isn't standard on IP22 so to avoid
+ * accidents it's disabled by default on IP22.
+ *
+ * FIXME: provide a mechanism to change the value of stop_a_enabled.
+ */
+int stop_a_enabled;
+
+void ip22_do_break(void)
+{
+ if (!stop_a_enabled)
+ return;
+
+ printk("\n");
+ ArcEnterInteractiveMode();
+}
+
+EXPORT_SYMBOL(ip22_do_break);
+
+extern void ip22_be_init(void) __init;
+extern void ip22_time_init(void) __init;
+
+static int __init ip22_setup(void)
+{
+ char *ctype;
+
+ board_be_init = ip22_be_init;
+ ip22_time_init();
+
+ /* Init the INDY HPC I/O controller. Need to call this before
+ * fucking with the memory controller because it needs to know the
+ * boardID and whether this is a Guiness or a FullHouse machine.
+ */
+ sgihpc_init();
+
+ /* Init INDY memory controller. */
+ sgimc_init();
+
+#ifdef CONFIG_BOARD_SCACHE
+ /* Now enable boardcaches, if any. */
+ indy_sc_init();
+#endif
+
+ /* Set EISA IO port base for Indigo2
+ * ioremap cannot fail */
+ set_io_port_base((unsigned long)ioremap(0x00080000,
+ 0x1fffffff - 0x00080000));
+ /* ARCS console environment variable is set to "g?" for
+ * graphics console, it is set to "d" for the first serial
+ * line and "d2" for the second serial line.
+ */
+ ctype = ArcGetEnvironmentVariable("console");
+ if (ctype && *ctype == 'd') {
+ static char options[8];
+ char *baud = ArcGetEnvironmentVariable("dbaud");
+ if (baud)
+ strcpy(options, baud);
+ add_preferred_console("ttyS", *(ctype + 1) == '2' ? 1 : 0,
+ baud ? options : NULL);
+ } else if (!ctype || *ctype != 'g') {
+ /* Use ARC if we don't want serial ('d') or Newport ('g'). */
+ prom_flags |= PROM_FLAG_USE_AS_CONSOLE;
+ add_preferred_console("arc", 0, NULL);
+ }
+
+#ifdef CONFIG_KGDB
+ {
+ char *kgdb_ttyd = prom_getcmdline();
+
+ if ((kgdb_ttyd = strstr(kgdb_ttyd, "kgdb=ttyd")) != NULL) {
+ int line;
+ kgdb_ttyd += strlen("kgdb=ttyd");
+ if (*kgdb_ttyd != '1' && *kgdb_ttyd != '2')
+ printk(KERN_INFO "KGDB: Uknown serial line /dev/ttyd%c"
+ ", falling back to /dev/ttyd1\n", *kgdb_ttyd);
+ line = *kgdb_ttyd == '2' ? 0 : 1;
+ printk(KERN_INFO "KGDB: Using serial line /dev/ttyd%d for "
+ "session\n", line ? 1 : 2);
+ rs_kgdb_hook(line);
+
+ printk(KERN_INFO "KGDB: Using serial line /dev/ttyd%d for "
+ "session, please connect your debugger\n", line ? 1:2);
+
+ kgdb_enabled = 1;
+ /* Breakpoints and stuff are in sgi_irq_setup() */
+ }
+ }
+#endif
+
+#if defined(CONFIG_VT) && defined(CONFIG_SGI_NEWPORT_CONSOLE)
+ {
+ ULONG *gfxinfo;
+ ULONG * (*__vec)(void) = (void *) (long)
+ *((_PULONG *)(long)((PROMBLOCK)->pvector + 0x20));
+
+ gfxinfo = __vec();
+ sgi_gfxaddr = ((gfxinfo[1] >= 0xa0000000
+ && gfxinfo[1] <= 0xc0000000)
+ ? gfxinfo[1] - 0xa0000000 : 0);
+
+ /* newport addresses? */
+ if (sgi_gfxaddr == 0x1f0f0000 || sgi_gfxaddr == 0x1f4f0000) {
+ conswitchp = &newport_con;
+ }
+ }
+#endif
+
+ return 0;
+}
+
+early_initcall(ip22_setup);
diff --git a/arch/mips/sgi-ip22/ip22-time.c b/arch/mips/sgi-ip22/ip22-time.c
new file mode 100644
index 0000000..173f768
--- /dev/null
+++ b/arch/mips/sgi-ip22/ip22-time.c
@@ -0,0 +1,214 @@
+/*
+ * 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.
+ *
+ * Time operations for IP22 machines. Original code may come from
+ * Ralf Baechle or David S. Miller (sorry guys, i'm really not sure)
+ *
+ * Copyright (C) 2001 by Ladislav Michl
+ * Copyright (C) 2003 Ralf Baechle (ralf@linux-mips.org)
+ */
+#include <linux/bcd.h>
+#include <linux/ds1286.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/kernel_stat.h>
+#include <linux/time.h>
+
+#include <asm/cpu.h>
+#include <asm/mipsregs.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/time.h>
+#include <asm/sgialib.h>
+#include <asm/sgi/ioc.h>
+#include <asm/sgi/hpc3.h>
+#include <asm/sgi/ip22.h>
+
+/*
+ * note that mktime uses month from 1 to 12 while to_tm
+ * uses 0 to 11.
+ */
+static unsigned long indy_rtc_get_time(void)
+{
+ unsigned int yrs, mon, day, hrs, min, sec;
+ unsigned int save_control;
+
+ save_control = hpc3c0->rtcregs[RTC_CMD] & 0xff;
+ hpc3c0->rtcregs[RTC_CMD] = save_control | RTC_TE;
+
+ sec = BCD2BIN(hpc3c0->rtcregs[RTC_SECONDS] & 0xff);
+ min = BCD2BIN(hpc3c0->rtcregs[RTC_MINUTES] & 0xff);
+ hrs = BCD2BIN(hpc3c0->rtcregs[RTC_HOURS] & 0x3f);
+ day = BCD2BIN(hpc3c0->rtcregs[RTC_DATE] & 0xff);
+ mon = BCD2BIN(hpc3c0->rtcregs[RTC_MONTH] & 0x1f);
+ yrs = BCD2BIN(hpc3c0->rtcregs[RTC_YEAR] & 0xff);
+
+ hpc3c0->rtcregs[RTC_CMD] = save_control;
+
+ if (yrs < 45)
+ yrs += 30;
+ if ((yrs += 40) < 70)
+ yrs += 100;
+
+ return mktime(yrs + 1900, mon, day, hrs, min, sec);
+}
+
+static int indy_rtc_set_time(unsigned long tim)
+{
+ struct rtc_time tm;
+ unsigned int save_control;
+
+ to_tm(tim, &tm);
+
+ tm.tm_mon += 1; /* tm_mon starts at zero */
+ tm.tm_year -= 1940;
+ if (tm.tm_year >= 100)
+ tm.tm_year -= 100;
+
+ save_control = hpc3c0->rtcregs[RTC_CMD] & 0xff;
+ hpc3c0->rtcregs[RTC_CMD] = save_control | RTC_TE;
+
+ hpc3c0->rtcregs[RTC_YEAR] = BIN2BCD(tm.tm_sec);
+ hpc3c0->rtcregs[RTC_MONTH] = BIN2BCD(tm.tm_mon);
+ hpc3c0->rtcregs[RTC_DATE] = BIN2BCD(tm.tm_mday);
+ hpc3c0->rtcregs[RTC_HOURS] = BIN2BCD(tm.tm_hour);
+ hpc3c0->rtcregs[RTC_MINUTES] = BIN2BCD(tm.tm_min);
+ hpc3c0->rtcregs[RTC_SECONDS] = BIN2BCD(tm.tm_sec);
+ hpc3c0->rtcregs[RTC_HUNDREDTH_SECOND] = 0;
+
+ hpc3c0->rtcregs[RTC_CMD] = save_control;
+
+ return 0;
+}
+
+static unsigned long dosample(void)
+{
+ u32 ct0, ct1;
+ volatile u8 msb, lsb;
+
+ /* Start the counter. */
+ sgint->tcword = (SGINT_TCWORD_CNT2 | SGINT_TCWORD_CALL |
+ SGINT_TCWORD_MRGEN);
+ sgint->tcnt2 = SGINT_TCSAMP_COUNTER & 0xff;
+ sgint->tcnt2 = SGINT_TCSAMP_COUNTER >> 8;
+
+ /* Get initial counter invariant */
+ ct0 = read_c0_count();
+
+ /* Latch and spin until top byte of counter2 is zero */
+ do {
+ sgint->tcword = SGINT_TCWORD_CNT2 | SGINT_TCWORD_CLAT;
+ lsb = sgint->tcnt2;
+ msb = sgint->tcnt2;
+ ct1 = read_c0_count();
+ } while (msb);
+
+ /* Stop the counter. */
+ sgint->tcword = (SGINT_TCWORD_CNT2 | SGINT_TCWORD_CALL |
+ SGINT_TCWORD_MSWST);
+ /*
+ * Return the difference, this is how far the r4k counter increments
+ * for every 1/HZ seconds. We round off the nearest 1 MHz of master
+ * clock (= 1000000 / HZ / 2).
+ */
+ /*return (ct1 - ct0 + (500000/HZ/2)) / (500000/HZ) * (500000/HZ);*/
+ return (ct1 - ct0) / (500000/HZ) * (500000/HZ);
+}
+
+/*
+ * Here we need to calibrate the cycle counter to at least be close.
+ */
+static __init void indy_time_init(void)
+{
+ unsigned long r4k_ticks[3];
+ unsigned long r4k_tick;
+
+ /*
+ * Figure out the r4k offset, the algorithm is very simple and works in
+ * _all_ cases as long as the 8254 counter register itself works ok (as
+ * an interrupt driving timer it does not because of bug, this is why
+ * we are using the onchip r4k counter/compare register to serve this
+ * purpose, but for r4k_offset calculation it will work ok for us).
+ * There are other very complicated ways of performing this calculation
+ * but this one works just fine so I am not going to futz around. ;-)
+ */
+ printk(KERN_INFO "Calibrating system timer... ");
+ dosample(); /* Prime cache. */
+ dosample(); /* Prime cache. */
+ /* Zero is NOT an option. */
+ do {
+ r4k_ticks[0] = dosample();
+ } while (!r4k_ticks[0]);
+ do {
+ r4k_ticks[1] = dosample();
+ } while (!r4k_ticks[1]);
+
+ if (r4k_ticks[0] != r4k_ticks[1]) {
+ printk("warning: timer counts differ, retrying... ");
+ r4k_ticks[2] = dosample();
+ if (r4k_ticks[2] == r4k_ticks[0]
+ || r4k_ticks[2] == r4k_ticks[1])
+ r4k_tick = r4k_ticks[2];
+ else {
+ printk("disagreement, using average... ");
+ r4k_tick = (r4k_ticks[0] + r4k_ticks[1]
+ + r4k_ticks[2]) / 3;
+ }
+ } else
+ r4k_tick = r4k_ticks[0];
+
+ printk("%d [%d.%04d MHz CPU]\n", (int) r4k_tick,
+ (int) (r4k_tick / (500000 / HZ)),
+ (int) (r4k_tick % (500000 / HZ)));
+
+ mips_hpt_frequency = r4k_tick * HZ;
+}
+
+/* Generic SGI handler for (spurious) 8254 interrupts */
+void indy_8254timer_irq(struct pt_regs *regs)
+{
+ int irq = SGI_8254_0_IRQ;
+ ULONG cnt;
+ char c;
+
+ irq_enter();
+ kstat_this_cpu.irqs[irq]++;
+ printk(KERN_ALERT "Oops, got 8254 interrupt.\n");
+ ArcRead(0, &c, 1, &cnt);
+ ArcEnterInteractiveMode();
+ irq_exit();
+}
+
+void indy_r4k_timer_interrupt(struct pt_regs *regs)
+{
+ int irq = SGI_TIMER_IRQ;
+
+ irq_enter();
+ kstat_this_cpu.irqs[irq]++;
+ timer_interrupt(irq, NULL, regs);
+ irq_exit();
+}
+
+extern int setup_irq(unsigned int irq, struct irqaction *irqaction);
+
+static void indy_timer_setup(struct irqaction *irq)
+{
+ /* over-write the handler, we use our own way */
+ irq->handler = no_action;
+
+ /* setup irqaction */
+ setup_irq(SGI_TIMER_IRQ, irq);
+}
+
+void __init ip22_time_init(void)
+{
+ /* setup hookup functions */
+ rtc_get_time = indy_rtc_get_time;
+ rtc_set_time = indy_rtc_set_time;
+
+ board_time_init = indy_time_init;
+ board_timer_setup = indy_timer_setup;
+}
diff --git a/arch/mips/sgi-ip27/Makefile b/arch/mips/sgi-ip27/Makefile
new file mode 100644
index 0000000..4ba3407
--- /dev/null
+++ b/arch/mips/sgi-ip27/Makefile
@@ -0,0 +1,12 @@
+#
+# Makefile for the IP27 specific kernel interface routines under Linux.
+#
+
+obj-y := ip27-berr.o ip27-console.o ip27-irq.o ip27-init.o ip27-irq-glue.o \
+ ip27-klconfig.o ip27-klnuma.o ip27-memory.o ip27-nmi.o ip27-reset.o \
+ ip27-timer.o ip27-hubio.o ip27-xtalk.o
+
+obj-$(CONFIG_KGDB) += ip27-dbgio.o
+obj-$(CONFIG_SMP) += ip27-smp.o
+
+EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/sgi-ip27/TODO b/arch/mips/sgi-ip27/TODO
new file mode 100644
index 0000000..3210613
--- /dev/null
+++ b/arch/mips/sgi-ip27/TODO
@@ -0,0 +1,23 @@
+1. Need to figure out why PCI writes to the IOC3 hang, and if it is okay
+not to write to the IOC3 ever.
+2. Need to figure out RRB allocation in bridge_startup().
+3. Need to figure out why address swaizzling is needed in inw/outw for
+Qlogic scsi controllers.
+4. Need to integrate ip27-klconfig.c:find_lboard and
+ip27-init.c:find_lbaord_real. DONE
+5. Is it okay to set calias space on all nodes as 0, instead of 8k as
+in irix?
+6. Investigate why things do not work without the setup_test() call
+being invoked on all nodes in ip27-memory.c.
+7. Too many CLIs in the locore handlers :
+For the low level handlers set up by set_except_vector(),
+__tlb_refill_debug_tramp, __xtlb_refill_debug_tramp and cacheerror,
+investigate whether the code should do CLI, STI or KMODE.
+8. Too many do_page_faults invoked - investigate.
+9. start_thread must turn off UX64 ... and define tlb_refill_debug.
+10. Need a bad pmd table, bad pte table. __bad_pmd_table/__bad_pagetable
+does not agree with pgd_bad/pmd_bad.
+11. All intrs (ip27_do_irq handlers) are targetted at cpu A on the node.
+This might need to change later. Only the timer intr is set up to be
+received on both Cpu A and B. (ip27_do_irq()/bridge_startup())
+13. Cache flushing (specially the SMP version) has to be investigated.
diff --git a/arch/mips/sgi-ip27/ip27-berr.c b/arch/mips/sgi-ip27/ip27-berr.c
new file mode 100644
index 0000000..e1829a5
--- /dev/null
+++ b/arch/mips/sgi-ip27/ip27-berr.c
@@ -0,0 +1,94 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1994, 1995, 1996, 1999, 2000 by Ralf Baechle
+ * Copyright (C) 1999, 2000 by Silicon Graphics
+ * Copyright (C) 2002 Maciej W. Rozycki
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#include <asm/module.h>
+#include <asm/sn/addrs.h>
+#include <asm/sn/arch.h>
+#include <asm/sn/sn0/hub.h>
+#include <asm/tlbdebug.h>
+#include <asm/traps.h>
+#include <asm/uaccess.h>
+
+extern void dump_tlb_addr(unsigned long addr);
+extern void dump_tlb_all(void);
+
+static void dump_hub_information(unsigned long errst0, unsigned long errst1)
+{
+ static char *err_type[2][8] = {
+ { NULL, "Uncached Partial Read PRERR", "DERR", "Read Timeout",
+ NULL, NULL, NULL, NULL },
+ { "WERR", "Uncached Partial Write", "PWERR", "Write Timeout",
+ NULL, NULL, NULL, NULL }
+ };
+ int wrb = errst1 & PI_ERR_ST1_WRBRRB_MASK;
+
+ if (!(errst0 & PI_ERR_ST0_VALID_MASK)) {
+ printk("Hub does not contain valid error information\n");
+ return;
+ }
+
+
+ printk("Hub has valid error information:\n");
+ if (errst0 & PI_ERR_ST0_OVERRUN_MASK)
+ printk("Overrun is set. Error stack may contain additional "
+ "information.\n");
+ printk("Hub error address is %08lx\n",
+ (errst0 & PI_ERR_ST0_ADDR_MASK) >> (PI_ERR_ST0_ADDR_SHFT - 3));
+ printk("Incoming message command 0x%lx\n",
+ (errst0 & PI_ERR_ST0_CMD_MASK) >> PI_ERR_ST0_CMD_SHFT);
+ printk("Supplemental field of incoming message is 0x%lx\n",
+ (errst0 & PI_ERR_ST0_SUPPL_MASK) >> PI_ERR_ST0_SUPPL_SHFT);
+ printk("T5 Rn (for RRB only) is 0x%lx\n",
+ (errst0 & PI_ERR_ST0_REQNUM_MASK) >> PI_ERR_ST0_REQNUM_SHFT);
+ printk("Error type is %s\n", err_type[wrb]
+ [(errst0 & PI_ERR_ST0_TYPE_MASK) >> PI_ERR_ST0_TYPE_SHFT]
+ ? : "invalid");
+}
+
+int ip27_be_handler(struct pt_regs *regs, int is_fixup)
+{
+ unsigned long errst0, errst1;
+ int data = regs->cp0_cause & 4;
+ int cpu = LOCAL_HUB_L(PI_CPU_NUM);
+
+ if (is_fixup)
+ return MIPS_BE_FIXUP;
+
+ printk("Slice %c got %cbe at 0x%lx\n", 'A' + cpu, data ? 'd' : 'i',
+ regs->cp0_epc);
+ printk("Hub information:\n");
+ printk("ERR_INT_PEND = 0x%06lx\n", LOCAL_HUB_L(PI_ERR_INT_PEND));
+ errst0 = LOCAL_HUB_L(cpu ? PI_ERR_STATUS0_B : PI_ERR_STATUS0_A);
+ errst1 = LOCAL_HUB_L(cpu ? PI_ERR_STATUS1_B : PI_ERR_STATUS1_A);
+ dump_hub_information(errst0, errst1);
+ show_regs(regs);
+ dump_tlb_all();
+ while(1);
+ force_sig(SIGBUS, current);
+}
+
+void __init ip27_be_init(void)
+{
+ /* XXX Initialize all the Hub & Bridge error handling here. */
+ int cpu = LOCAL_HUB_L(PI_CPU_NUM);
+ int cpuoff = cpu << 8;
+
+ board_be_handler = ip27_be_handler;
+
+ LOCAL_HUB_S(PI_ERR_INT_PEND,
+ cpu ? PI_ERR_CLEAR_ALL_B : PI_ERR_CLEAR_ALL_A);
+ LOCAL_HUB_S(PI_ERR_INT_MASK_A + cpuoff, 0);
+ LOCAL_HUB_S(PI_ERR_STACK_ADDR_A + cpuoff, 0);
+ LOCAL_HUB_S(PI_ERR_STACK_SIZE, 0); /* Disable error stack */
+ LOCAL_HUB_S(PI_SYSAD_ERRCHK_EN, PI_SYSAD_CHECK_ALL);
+}
diff --git a/arch/mips/sgi-ip27/ip27-console.c b/arch/mips/sgi-ip27/ip27-console.c
new file mode 100644
index 0000000..d97f5b5
--- /dev/null
+++ b/arch/mips/sgi-ip27/ip27-console.c
@@ -0,0 +1,76 @@
+/*
+ * 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) 2001, 2002 Ralf Baechle
+ */
+#include <linux/init.h>
+#include <linux/console.h>
+#include <linux/kdev_t.h>
+#include <linux/major.h>
+#include <linux/termios.h>
+#include <linux/sched.h>
+#include <linux/tty.h>
+
+#include <asm/page.h>
+#include <asm/semaphore.h>
+#include <asm/sn/addrs.h>
+#include <asm/sn/sn0/hub.h>
+#include <asm/sn/klconfig.h>
+#include <asm/sn/ioc3.h>
+#include <asm/sn/sn_private.h>
+
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+
+#define IOC3_CLK (22000000 / 3)
+#define IOC3_FLAGS (0)
+
+static inline struct ioc3_uartregs *console_uart(void)
+{
+ struct ioc3 *ioc3;
+
+ ioc3 = (struct ioc3 *)KL_CONFIG_CH_CONS_INFO(get_nasid())->memory_base;
+
+ return &ioc3->sregs.uarta;
+}
+
+void prom_putchar(char c)
+{
+ struct ioc3_uartregs *uart = console_uart();
+
+ while ((uart->iu_lsr & 0x20) == 0);
+ uart->iu_thr = c;
+}
+
+char __init prom_getchar(void)
+{
+ return 0;
+}
+
+static void inline ioc3_console_probe(void)
+{
+ struct uart_port up;
+
+ /*
+ * Register to interrupt zero because we share the interrupt with
+ * the serial driver which we don't properly support yet.
+ */
+ memset(&up, 0, sizeof(up));
+ up.membase = (unsigned char *) console_uart();
+ up.irq = 0;
+ up.uartclk = IOC3_CLK;
+ up.regshift = 0;
+ up.iotype = UPIO_MEM;
+ up.flags = IOC3_FLAGS;
+ up.line = 0;
+
+ if (early_serial_setup(&up))
+ printk(KERN_ERR "Early serial init of port 0 failed\n");
+}
+
+__init void ip27_setup_console(void)
+{
+ ioc3_console_probe();
+}
diff --git a/arch/mips/sgi-ip27/ip27-dbgio.c b/arch/mips/sgi-ip27/ip27-dbgio.c
new file mode 100644
index 0000000..08fd88b
--- /dev/null
+++ b/arch/mips/sgi-ip27/ip27-dbgio.c
@@ -0,0 +1,60 @@
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Copyright 2004 Ralf Baechle <ralf@linux-mips.org>
+ */
+#include <asm/sn/addrs.h>
+#include <asm/sn/sn0/hub.h>
+#include <asm/sn/klconfig.h>
+#include <asm/sn/ioc3.h>
+#include <asm/sn/sn_private.h>
+
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+#include <linux/serial_reg.h>
+
+#define IOC3_CLK (22000000 / 3)
+#define IOC3_FLAGS (0)
+
+static inline struct ioc3_uartregs *console_uart(void)
+{
+ struct ioc3 *ioc3;
+
+ ioc3 = (struct ioc3 *)KL_CONFIG_CH_CONS_INFO(get_nasid())->memory_base;
+
+ return &ioc3->sregs.uarta;
+}
+
+unsigned char getDebugChar(void)
+{
+ struct ioc3_uartregs *uart = console_uart();
+
+ while ((uart->iu_lsr & UART_LSR_DR) == 0);
+ return uart->iu_rbr;
+}
+
+void putDebugChar(unsigned char c)
+{
+ struct ioc3_uartregs *uart = console_uart();
+
+ while ((uart->iu_lsr & UART_LSR_THRE) == 0);
+ uart->iu_thr = c;
+}
diff --git a/arch/mips/sgi-ip27/ip27-hubio.c b/arch/mips/sgi-ip27/ip27-hubio.c
new file mode 100644
index 0000000..524b371
--- /dev/null
+++ b/arch/mips/sgi-ip27/ip27-hubio.c
@@ -0,0 +1,186 @@
+/*
+ * Copyright (C) 1992-1997, 2000-2003 Silicon Graphics, Inc.
+ * Copyright (C) 2004 Christoph Hellwig.
+ * Released under GPL v2.
+ *
+ * Support functions for the HUB ASIC - mostly PIO mapping related.
+ */
+
+#include <linux/bitops.h>
+#include <linux/string.h>
+#include <linux/mmzone.h>
+#include <asm/sn/addrs.h>
+#include <asm/sn/arch.h>
+#include <asm/sn/hub.h>
+
+
+static int force_fire_and_forget = 1;
+
+/**
+ * hub_pio_map - establish a HUB PIO mapping
+ *
+ * @hub: hub to perform PIO mapping on
+ * @widget: widget ID to perform PIO mapping for
+ * @xtalk_addr: xtalk_address that needs to be mapped
+ * @size: size of the PIO mapping
+ *
+ **/
+unsigned long hub_pio_map(cnodeid_t cnode, xwidgetnum_t widget,
+ unsigned long xtalk_addr, size_t size)
+{
+ nasid_t nasid = COMPACT_TO_NASID_NODEID(cnode);
+ volatile hubreg_t junk;
+ unsigned i;
+
+ /* use small-window mapping if possible */
+ if ((xtalk_addr % SWIN_SIZE) + size <= SWIN_SIZE)
+ return NODE_SWIN_BASE(nasid, widget) + (xtalk_addr % SWIN_SIZE);
+
+ if ((xtalk_addr % BWIN_SIZE) + size > BWIN_SIZE) {
+ printk(KERN_WARNING "PIO mapping at hub %d widget %d addr 0x%lx"
+ " too big (%ld)\n",
+ nasid, widget, xtalk_addr, size);
+ return 0;
+ }
+
+ xtalk_addr &= ~(BWIN_SIZE-1);
+ for (i = 0; i < HUB_NUM_BIG_WINDOW; i++) {
+ if (test_and_set_bit(i, hub_data(cnode)->h_bigwin_used))
+ continue;
+
+ /*
+ * The code below does a PIO write to setup an ITTE entry.
+ *
+ * We need to prevent other CPUs from seeing our updated
+ * memory shadow of the ITTE (in the piomap) until the ITTE
+ * entry is actually set up; otherwise, another CPU might
+ * attempt a PIO prematurely.
+ *
+ * Also, the only way we can know that an entry has been
+ * received by the hub and can be used by future PIO reads/
+ * writes is by reading back the ITTE entry after writing it.
+ *
+ * For these two reasons, we PIO read back the ITTE entry
+ * after we write it.
+ */
+ IIO_ITTE_PUT(nasid, i, HUB_PIO_MAP_TO_MEM, widget, xtalk_addr);
+ junk = HUB_L(IIO_ITTE_GET(nasid, i));
+
+ return NODE_BWIN_BASE(nasid, widget) + (xtalk_addr % BWIN_SIZE);
+ }
+
+ printk(KERN_WARNING "unable to establish PIO mapping for at"
+ " hub %d widget %d addr 0x%lx\n",
+ nasid, widget, xtalk_addr);
+ return 0;
+}
+
+
+/*
+ * hub_setup_prb(nasid, prbnum, credits, conveyor)
+ *
+ * Put a PRB into fire-and-forget mode if conveyor isn't set. Otherwise,
+ * put it into conveyor belt mode with the specified number of credits.
+ */
+static void hub_setup_prb(nasid_t nasid, int prbnum, int credits)
+{
+ iprb_t prb;
+ int prb_offset;
+
+ /*
+ * Get the current register value.
+ */
+ prb_offset = IIO_IOPRB(prbnum);
+ prb.iprb_regval = REMOTE_HUB_L(nasid, prb_offset);
+
+ /*
+ * Clear out some fields.
+ */
+ prb.iprb_ovflow = 1;
+ prb.iprb_bnakctr = 0;
+ prb.iprb_anakctr = 0;
+
+ /*
+ * Enable or disable fire-and-forget mode.
+ */
+ prb.iprb_ff = force_fire_and_forget ? 1 : 0;
+
+ /*
+ * Set the appropriate number of PIO cresits for the widget.
+ */
+ prb.iprb_xtalkctr = credits;
+
+ /*
+ * Store the new value to the register.
+ */
+ REMOTE_HUB_S(nasid, prb_offset, prb.iprb_regval);
+}
+
+/**
+ * hub_set_piomode - set pio mode for a given hub
+ *
+ * @nasid: physical node ID for the hub in question
+ *
+ * Put the hub into either "PIO conveyor belt" mode or "fire-and-forget" mode.
+ * To do this, we have to make absolutely sure that no PIOs are in progress
+ * so we turn off access to all widgets for the duration of the function.
+ *
+ * XXX - This code should really check what kind of widget we're talking
+ * to. Bridges can only handle three requests, but XG will do more.
+ * How many can crossbow handle to widget 0? We're assuming 1.
+ *
+ * XXX - There is a bug in the crossbow that link reset PIOs do not
+ * return write responses. The easiest solution to this problem is to
+ * leave widget 0 (xbow) in fire-and-forget mode at all times. This
+ * only affects pio's to xbow registers, which should be rare.
+ **/
+static void hub_set_piomode(nasid_t nasid)
+{
+ hubreg_t ii_iowa;
+ hubii_wcr_t ii_wcr;
+ unsigned i;
+
+ ii_iowa = REMOTE_HUB_L(nasid, IIO_OUTWIDGET_ACCESS);
+ REMOTE_HUB_S(nasid, IIO_OUTWIDGET_ACCESS, 0);
+
+ ii_wcr.wcr_reg_value = REMOTE_HUB_L(nasid, IIO_WCR);
+
+ if (ii_wcr.iwcr_dir_con) {
+ /*
+ * Assume a bridge here.
+ */
+ hub_setup_prb(nasid, 0, 3);
+ } else {
+ /*
+ * Assume a crossbow here.
+ */
+ hub_setup_prb(nasid, 0, 1);
+ }
+
+ /*
+ * XXX - Here's where we should take the widget type into
+ * when account assigning credits.
+ */
+ for (i = HUB_WIDGET_ID_MIN; i <= HUB_WIDGET_ID_MAX; i++)
+ hub_setup_prb(nasid, i, 3);
+
+ REMOTE_HUB_S(nasid, IIO_OUTWIDGET_ACCESS, ii_iowa);
+}
+
+/*
+ * hub_pio_init - PIO-related hub initalization
+ *
+ * @hub: hubinfo structure for our hub
+ */
+void hub_pio_init(cnodeid_t cnode)
+{
+ nasid_t nasid = COMPACT_TO_NASID_NODEID(cnode);
+ unsigned i;
+
+ /* initialize big window piomaps for this hub */
+ bitmap_zero(hub_data(cnode)->h_bigwin_used, HUB_NUM_BIG_WINDOW);
+ for (i = 0; i < HUB_NUM_BIG_WINDOW; i++)
+ IIO_ITTE_DISABLE(nasid, i);
+
+ hub_set_piomode(nasid);
+}
diff --git a/arch/mips/sgi-ip27/ip27-init.c b/arch/mips/sgi-ip27/ip27-init.c
new file mode 100644
index 0000000..6dcee5c
--- /dev/null
+++ b/arch/mips/sgi-ip27/ip27-init.c
@@ -0,0 +1,252 @@
+/*
+ * 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) 2000 - 2001 by Kanoj Sarcar (kanoj@sgi.com)
+ * Copyright (C) 2000 - 2001 by Silicon Graphics, Inc.
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/cpumask.h>
+#include <asm/cpu.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/time.h>
+#include <asm/sn/types.h>
+#include <asm/sn/sn0/addrs.h>
+#include <asm/sn/sn0/hubni.h>
+#include <asm/sn/sn0/hubio.h>
+#include <asm/sn/klconfig.h>
+#include <asm/sn/ioc3.h>
+#include <asm/mipsregs.h>
+#include <asm/sn/gda.h>
+#include <asm/sn/hub.h>
+#include <asm/sn/intr.h>
+#include <asm/current.h>
+#include <asm/smp.h>
+#include <asm/processor.h>
+#include <asm/mmu_context.h>
+#include <asm/thread_info.h>
+#include <asm/sn/launch.h>
+#include <asm/sn/sn_private.h>
+#include <asm/sn/sn0/ip27.h>
+#include <asm/sn/mapped_kernel.h>
+
+#define CPU_NONE (cpuid_t)-1
+
+static DECLARE_BITMAP(hub_init_mask, MAX_COMPACT_NODES);
+nasid_t master_nasid = INVALID_NASID;
+
+cnodeid_t nasid_to_compact_node[MAX_NASIDS];
+nasid_t compact_to_nasid_node[MAX_COMPACT_NODES];
+cnodeid_t cpuid_to_compact_node[MAXCPUS];
+
+EXPORT_SYMBOL(nasid_to_compact_node);
+
+extern void pcibr_setup(cnodeid_t);
+
+extern void xtalk_probe_node(cnodeid_t nid);
+
+static void __init per_hub_init(cnodeid_t cnode)
+{
+ struct hub_data *hub = hub_data(cnode);
+ nasid_t nasid = COMPACT_TO_NASID_NODEID(cnode);
+
+ cpu_set(smp_processor_id(), hub->h_cpus);
+
+ if (test_and_set_bit(cnode, hub_init_mask))
+ return;
+
+ /*
+ * Set CRB timeout at 5ms, (< PI timeout of 10ms)
+ */
+ REMOTE_HUB_S(nasid, IIO_ICTP, 0x800);
+ REMOTE_HUB_S(nasid, IIO_ICTO, 0xff);
+
+ hub_rtc_init(cnode);
+ xtalk_probe_node(cnode);
+
+#ifdef CONFIG_REPLICATE_EXHANDLERS
+ /*
+ * If this is not a headless node initialization,
+ * copy over the caliased exception handlers.
+ */
+ if (get_compact_nodeid() == cnode) {
+ extern char except_vec2_generic, except_vec3_generic;
+ extern void build_tlb_refill_handler(void);
+
+ memcpy((void *)(CKSEG0 + 0x100), &except_vec2_generic, 0x80);
+ memcpy((void *)(CKSEG0 + 0x180), &except_vec3_generic, 0x80);
+ build_tlb_refill_handler();
+ memcpy((void *)(CKSEG0 + 0x100), (void *) CKSEG0, 0x80);
+ memcpy((void *)(CKSEG0 + 0x180), &except_vec3_generic, 0x100);
+ __flush_cache_all();
+ }
+#endif
+}
+
+void __init per_cpu_init(void)
+{
+ int cpu = smp_processor_id();
+ int slice = LOCAL_HUB_L(PI_CPU_NUM);
+ cnodeid_t cnode = get_compact_nodeid();
+ struct hub_data *hub = hub_data(cnode);
+ struct slice_data *si = hub->slice + slice;
+ int i;
+
+ if (test_and_set_bit(slice, &hub->slice_map))
+ return;
+
+ clear_c0_status(ST0_IM);
+
+ for (i = 0; i < LEVELS_PER_SLICE; i++)
+ si->level_to_irq[i] = -1;
+
+ /*
+ * Some interrupts are reserved by hardware or by software convention.
+ * Mark these as reserved right away so they won't be used accidently
+ * later.
+ */
+ for (i = 0; i <= BASE_PCI_IRQ; i++) {
+ __set_bit(i, si->irq_alloc_mask);
+ LOCAL_HUB_S(PI_INT_PEND_MOD, i);
+ }
+
+ __set_bit(IP_PEND0_6_63, si->irq_alloc_mask);
+ LOCAL_HUB_S(PI_INT_PEND_MOD, IP_PEND0_6_63);
+
+ for (i = NI_BRDCAST_ERR_A; i <= MSC_PANIC_INTR; i++) {
+ __set_bit(i, si->irq_alloc_mask + 1);
+ LOCAL_HUB_S(PI_INT_PEND_MOD, i);
+ }
+
+ LOCAL_HUB_L(PI_INT_PEND0);
+
+ /*
+ * We use this so we can find the local hub's data as fast as only
+ * possible.
+ */
+ cpu_data[cpu].data = si;
+
+ cpu_time_init();
+ install_ipi();
+
+ /* Install our NMI handler if symmon hasn't installed one. */
+ install_cpu_nmi_handler(cputoslice(cpu));
+
+ set_c0_status(SRB_DEV0 | SRB_DEV1);
+
+ per_hub_init(cnode);
+}
+
+/*
+ * get_nasid() returns the physical node id number of the caller.
+ */
+nasid_t
+get_nasid(void)
+{
+ return (nasid_t)((LOCAL_HUB_L(NI_STATUS_REV_ID) & NSRI_NODEID_MASK)
+ >> NSRI_NODEID_SHFT);
+}
+
+/*
+ * Map the physical node id to a virtual node id (virtual node ids are contiguous).
+ */
+cnodeid_t get_compact_nodeid(void)
+{
+ return NASID_TO_COMPACT_NODEID(get_nasid());
+}
+
+/* Extracted from the IOC3 meta driver. FIXME. */
+static inline void ioc3_sio_init(void)
+{
+ struct ioc3 *ioc3;
+ nasid_t nid;
+ long loops;
+
+ nid = get_nasid();
+ ioc3 = (struct ioc3 *) KL_CONFIG_CH_CONS_INFO(nid)->memory_base;
+
+ ioc3->sscr_a = 0; /* PIO mode for uarta. */
+ ioc3->sscr_b = 0; /* PIO mode for uartb. */
+ ioc3->sio_iec = ~0;
+ ioc3->sio_ies = (SIO_IR_SA_INT | SIO_IR_SB_INT);
+
+ loops=1000000; while(loops--);
+ ioc3->sregs.uarta.iu_fcr = 0;
+ ioc3->sregs.uartb.iu_fcr = 0;
+ loops=1000000; while(loops--);
+}
+
+static inline void ioc3_eth_init(void)
+{
+ struct ioc3 *ioc3;
+ nasid_t nid;
+
+ nid = get_nasid();
+ ioc3 = (struct ioc3 *) KL_CONFIG_CH_CONS_INFO(nid)->memory_base;
+
+ ioc3->eier = 0;
+}
+
+extern void ip27_setup_console(void);
+extern void ip27_time_init(void);
+extern void ip27_reboot_setup(void);
+
+static int __init ip27_setup(void)
+{
+ hubreg_t p, e, n_mode;
+ nasid_t nid;
+
+ ip27_setup_console();
+ ip27_reboot_setup();
+
+ /*
+ * hub_rtc init and cpu clock intr enabled for later calibrate_delay.
+ */
+ nid = get_nasid();
+ printk("IP27: Running on node %d.\n", nid);
+
+ p = LOCAL_HUB_L(PI_CPU_PRESENT_A) & 1;
+ e = LOCAL_HUB_L(PI_CPU_ENABLE_A) & 1;
+ printk("Node %d has %s primary CPU%s.\n", nid,
+ p ? "a" : "no",
+ e ? ", CPU is running" : "");
+
+ p = LOCAL_HUB_L(PI_CPU_PRESENT_B) & 1;
+ e = LOCAL_HUB_L(PI_CPU_ENABLE_B) & 1;
+ printk("Node %d has %s secondary CPU%s.\n", nid,
+ p ? "a" : "no",
+ e ? ", CPU is running" : "");
+
+ /*
+ * Try to catch kernel missconfigurations and give user an
+ * indication what option to select.
+ */
+ n_mode = LOCAL_HUB_L(NI_STATUS_REV_ID) & NSRI_MORENODES_MASK;
+ printk("Machine is in %c mode.\n", n_mode ? 'N' : 'M');
+#ifdef CONFIG_SGI_SN0_N_MODE
+ if (!n_mode)
+ panic("Kernel compiled for M mode.");
+#else
+ if (n_mode)
+ panic("Kernel compiled for N mode.");
+#endif
+
+ ioc3_sio_init();
+ ioc3_eth_init();
+ per_cpu_init();
+
+ set_io_port_base(IO_BASE);
+
+ board_time_init = ip27_time_init;
+
+ return 0;
+}
+
+early_initcall(ip27_setup);
diff --git a/arch/mips/sgi-ip27/ip27-irq-glue.S b/arch/mips/sgi-ip27/ip27-irq-glue.S
new file mode 100644
index 0000000..c304df7
--- /dev/null
+++ b/arch/mips/sgi-ip27/ip27-irq-glue.S
@@ -0,0 +1,45 @@
+/*
+ * 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) 1999 Ralf Baechle
+ * Copyright (C) 1999 Silicon Graphics, Inc.
+ */
+#include <asm/asm.h>
+#include <asm/mipsregs.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+
+ .text
+ .align 5
+NESTED(ip27_irq, PT_SIZE, sp)
+ SAVE_ALL
+ CLI
+
+ mfc0 s0, CP0_CAUSE
+ mfc0 t0, CP0_STATUS
+ and s0, t0
+ move a0, sp
+ PTR_LA ra, ret_from_irq
+
+ /* First check for RT interrupt. */
+ andi t0, s0, CAUSEF_IP4
+ bnez t0, ip4
+ andi t0, s0, CAUSEF_IP2
+ bnez t0, ip2
+ andi t0, s0, CAUSEF_IP3
+ bnez t0, ip3
+ andi t0, s0, CAUSEF_IP5
+ bnez t0, ip5
+ andi t0, s0, CAUSEF_IP6
+ bnez t0, ip6
+ j ra
+
+ip2: j ip27_do_irq_mask0 # PI_INT_PEND_0 or CC_PEND_{A|B}
+ip3: j ip27_do_irq_mask1 # PI_INT_PEND_1
+ip4: j ip27_rt_timer_interrupt
+ip5: j ip27_prof_timer
+ip6: j ip27_hub_error
+
+ END(ip27_irq)
diff --git a/arch/mips/sgi-ip27/ip27-irq.c b/arch/mips/sgi-ip27/ip27-irq.c
new file mode 100644
index 0000000..61817a1
--- /dev/null
+++ b/arch/mips/sgi-ip27/ip27-irq.c
@@ -0,0 +1,457 @@
+/*
+ * ip27-irq.c: Highlevel interrupt handling for IP27 architecture.
+ *
+ * Copyright (C) 1999, 2000 Ralf Baechle (ralf@gnu.org)
+ * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
+ * Copyright (C) 1999 - 2001 Kanoj Sarcar
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/errno.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/irq.h>
+#include <linux/timex.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+#include <linux/smp_lock.h>
+#include <linux/kernel_stat.h>
+#include <linux/delay.h>
+#include <linux/bitops.h>
+
+#include <asm/bootinfo.h>
+#include <asm/io.h>
+#include <asm/mipsregs.h>
+#include <asm/system.h>
+
+#include <asm/ptrace.h>
+#include <asm/processor.h>
+#include <asm/pci/bridge.h>
+#include <asm/sn/addrs.h>
+#include <asm/sn/agent.h>
+#include <asm/sn/arch.h>
+#include <asm/sn/hub.h>
+#include <asm/sn/intr.h>
+
+#undef DEBUG_IRQ
+#ifdef DEBUG_IRQ
+#define DBG(x...) printk(x)
+#else
+#define DBG(x...)
+#endif
+
+/*
+ * Linux has a controller-independent x86 interrupt architecture.
+ * every controller has a 'controller-template', that is used
+ * by the main code to do the right thing. Each driver-visible
+ * interrupt source is transparently wired to the apropriate
+ * controller. Thus drivers need not be aware of the
+ * interrupt-controller.
+ *
+ * Various interrupt controllers we handle: 8259 PIC, SMP IO-APIC,
+ * PIIX4's internal 8259 PIC and SGI's Visual Workstation Cobalt (IO-)APIC.
+ * (IO-APICs assumed to be messaging to Pentium local-APICs)
+ *
+ * the code is designed to be easily extended with new/different
+ * interrupt controllers, without having to do assembly magic.
+ */
+
+extern asmlinkage void ip27_irq(void);
+
+extern struct bridge_controller *irq_to_bridge[];
+extern int irq_to_slot[];
+
+/*
+ * use these macros to get the encoded nasid and widget id
+ * from the irq value
+ */
+#define IRQ_TO_BRIDGE(i) irq_to_bridge[(i)]
+#define SLOT_FROM_PCI_IRQ(i) irq_to_slot[i]
+
+static inline int alloc_level(int cpu, int irq)
+{
+ struct slice_data *si = cpu_data[cpu].data;
+ int level; /* pre-allocated entries */
+
+ level = find_first_zero_bit(si->irq_alloc_mask, LEVELS_PER_SLICE);
+ if (level >= LEVELS_PER_SLICE)
+ panic("Cpu %d flooded with devices\n", cpu);
+
+ __set_bit(level, si->irq_alloc_mask);
+ si->level_to_irq[level] = irq;
+
+ return level;
+}
+
+static inline int find_level(cpuid_t *cpunum, int irq)
+{
+ int cpu, i;
+
+ for (cpu = 0; cpu <= NR_CPUS; cpu++) {
+ struct slice_data *si = cpu_data[cpu].data;
+
+ if (!cpu_online(cpu))
+ continue;
+
+ for (i = BASE_PCI_IRQ; i < LEVELS_PER_SLICE; i++)
+ if (si->level_to_irq[i] == irq) {
+ *cpunum = cpu;
+
+ return i;
+ }
+ }
+
+ panic("Could not identify cpu/level for irq %d\n", irq);
+}
+
+/*
+ * Find first bit set
+ */
+static int ms1bit(unsigned long x)
+{
+ int b = 0, s;
+
+ s = 16; if (x >> 16 == 0) s = 0; b += s; x >>= s;
+ s = 8; if (x >> 8 == 0) s = 0; b += s; x >>= s;
+ s = 4; if (x >> 4 == 0) s = 0; b += s; x >>= s;
+ s = 2; if (x >> 2 == 0) s = 0; b += s; x >>= s;
+ s = 1; if (x >> 1 == 0) s = 0; b += s;
+
+ return b;
+}
+
+/*
+ * This code is unnecessarily complex, because we do SA_INTERRUPT
+ * intr enabling. Basically, once we grab the set of intrs we need
+ * to service, we must mask _all_ these interrupts; firstly, to make
+ * sure the same intr does not intr again, causing recursion that
+ * can lead to stack overflow. Secondly, we can not just mask the
+ * one intr we are do_IRQing, because the non-masked intrs in the
+ * first set might intr again, causing multiple servicings of the
+ * same intr. This effect is mostly seen for intercpu intrs.
+ * Kanoj 05.13.00
+ */
+
+void ip27_do_irq_mask0(struct pt_regs *regs)
+{
+ int irq, swlevel;
+ hubreg_t pend0, mask0;
+ cpuid_t cpu = smp_processor_id();
+ int pi_int_mask0 =
+ (cputoslice(cpu) == 0) ? PI_INT_MASK0_A : PI_INT_MASK0_B;
+
+ /* copied from Irix intpend0() */
+ pend0 = LOCAL_HUB_L(PI_INT_PEND0);
+ mask0 = LOCAL_HUB_L(pi_int_mask0);
+
+ pend0 &= mask0; /* Pick intrs we should look at */
+ if (!pend0)
+ return;
+
+ swlevel = ms1bit(pend0);
+#ifdef CONFIG_SMP
+ if (pend0 & (1UL << CPU_RESCHED_A_IRQ)) {
+ LOCAL_HUB_CLR_INTR(CPU_RESCHED_A_IRQ);
+ } else if (pend0 & (1UL << CPU_RESCHED_B_IRQ)) {
+ LOCAL_HUB_CLR_INTR(CPU_RESCHED_B_IRQ);
+ } else if (pend0 & (1UL << CPU_CALL_A_IRQ)) {
+ LOCAL_HUB_CLR_INTR(CPU_CALL_A_IRQ);
+ smp_call_function_interrupt();
+ } else if (pend0 & (1UL << CPU_CALL_B_IRQ)) {
+ LOCAL_HUB_CLR_INTR(CPU_CALL_B_IRQ);
+ smp_call_function_interrupt();
+ } else
+#endif
+ {
+ /* "map" swlevel to irq */
+ struct slice_data *si = cpu_data[cpu].data;
+
+ irq = si->level_to_irq[swlevel];
+ do_IRQ(irq, regs);
+ }
+
+ LOCAL_HUB_L(PI_INT_PEND0);
+}
+
+void ip27_do_irq_mask1(struct pt_regs *regs)
+{
+ int irq, swlevel;
+ hubreg_t pend1, mask1;
+ cpuid_t cpu = smp_processor_id();
+ int pi_int_mask1 = (cputoslice(cpu) == 0) ? PI_INT_MASK1_A : PI_INT_MASK1_B;
+ struct slice_data *si = cpu_data[cpu].data;
+
+ /* copied from Irix intpend0() */
+ pend1 = LOCAL_HUB_L(PI_INT_PEND1);
+ mask1 = LOCAL_HUB_L(pi_int_mask1);
+
+ pend1 &= mask1; /* Pick intrs we should look at */
+ if (!pend1)
+ return;
+
+ swlevel = ms1bit(pend1);
+ /* "map" swlevel to irq */
+ irq = si->level_to_irq[swlevel];
+ LOCAL_HUB_CLR_INTR(swlevel);
+ do_IRQ(irq, regs);
+
+ LOCAL_HUB_L(PI_INT_PEND1);
+}
+
+void ip27_prof_timer(struct pt_regs *regs)
+{
+ panic("CPU %d got a profiling interrupt", smp_processor_id());
+}
+
+void ip27_hub_error(struct pt_regs *regs)
+{
+ panic("CPU %d got a hub error interrupt", smp_processor_id());
+}
+
+static int intr_connect_level(int cpu, int bit)
+{
+ nasid_t nasid = COMPACT_TO_NASID_NODEID(cpu_to_node(cpu));
+ struct slice_data *si = cpu_data[cpu].data;
+
+ __set_bit(bit, si->irq_enable_mask);
+
+ if (!cputoslice(cpu)) {
+ REMOTE_HUB_S(nasid, PI_INT_MASK0_A, si->irq_enable_mask[0]);
+ REMOTE_HUB_S(nasid, PI_INT_MASK1_A, si->irq_enable_mask[1]);
+ } else {
+ REMOTE_HUB_S(nasid, PI_INT_MASK0_B, si->irq_enable_mask[0]);
+ REMOTE_HUB_S(nasid, PI_INT_MASK1_B, si->irq_enable_mask[1]);
+ }
+
+ return 0;
+}
+
+static int intr_disconnect_level(int cpu, int bit)
+{
+ nasid_t nasid = COMPACT_TO_NASID_NODEID(cpu_to_node(cpu));
+ struct slice_data *si = cpu_data[cpu].data;
+
+ __clear_bit(bit, si->irq_enable_mask);
+
+ if (!cputoslice(cpu)) {
+ REMOTE_HUB_S(nasid, PI_INT_MASK0_A, si->irq_enable_mask[0]);
+ REMOTE_HUB_S(nasid, PI_INT_MASK1_A, si->irq_enable_mask[1]);
+ } else {
+ REMOTE_HUB_S(nasid, PI_INT_MASK0_B, si->irq_enable_mask[0]);
+ REMOTE_HUB_S(nasid, PI_INT_MASK1_B, si->irq_enable_mask[1]);
+ }
+
+ return 0;
+}
+
+/* Startup one of the (PCI ...) IRQs routes over a bridge. */
+static unsigned int startup_bridge_irq(unsigned int irq)
+{
+ struct bridge_controller *bc;
+ bridgereg_t device;
+ bridge_t *bridge;
+ int pin, swlevel;
+ cpuid_t cpu;
+
+ pin = SLOT_FROM_PCI_IRQ(irq);
+ bc = IRQ_TO_BRIDGE(irq);
+ bridge = bc->base;
+
+ DBG("bridge_startup(): irq= 0x%x pin=%d\n", irq, pin);
+ /*
+ * "map" irq to a swlevel greater than 6 since the first 6 bits
+ * of INT_PEND0 are taken
+ */
+ swlevel = find_level(&cpu, irq);
+ bridge->b_int_addr[pin].addr = (0x20000 | swlevel | (bc->nasid << 8));
+ bridge->b_int_enable |= (1 << pin);
+ bridge->b_int_enable |= 0x7ffffe00; /* more stuff in int_enable */
+
+ /*
+ * Enable sending of an interrupt clear packt to the hub on a high to
+ * low transition of the interrupt pin.
+ *
+ * IRIX sets additional bits in the address which are documented as
+ * reserved in the bridge docs.
+ */
+ bridge->b_int_mode |= (1UL << pin);
+
+ /*
+ * We assume the bridge to have a 1:1 mapping between devices
+ * (slots) and intr pins.
+ */
+ device = bridge->b_int_device;
+ device &= ~(7 << (pin*3));
+ device |= (pin << (pin*3));
+ bridge->b_int_device = device;
+
+ bridge->b_wid_tflush;
+
+ return 0; /* Never anything pending. */
+}
+
+/* Shutdown one of the (PCI ...) IRQs routes over a bridge. */
+static void shutdown_bridge_irq(unsigned int irq)
+{
+ struct bridge_controller *bc = IRQ_TO_BRIDGE(irq);
+ bridge_t *bridge = bc->base;
+ struct slice_data *si = cpu_data[bc->irq_cpu].data;
+ int pin, swlevel;
+ cpuid_t cpu;
+
+ DBG("bridge_shutdown: irq 0x%x\n", irq);
+ pin = SLOT_FROM_PCI_IRQ(irq);
+
+ /*
+ * map irq to a swlevel greater than 6 since the first 6 bits
+ * of INT_PEND0 are taken
+ */
+ swlevel = find_level(&cpu, irq);
+ intr_disconnect_level(cpu, swlevel);
+
+ __clear_bit(swlevel, si->irq_alloc_mask);
+ si->level_to_irq[swlevel] = -1;
+
+ bridge->b_int_enable &= ~(1 << pin);
+ bridge->b_wid_tflush;
+}
+
+static inline void enable_bridge_irq(unsigned int irq)
+{
+ cpuid_t cpu;
+ int swlevel;
+
+ swlevel = find_level(&cpu, irq); /* Criminal offence */
+ intr_connect_level(cpu, swlevel);
+}
+
+static inline void disable_bridge_irq(unsigned int irq)
+{
+ cpuid_t cpu;
+ int swlevel;
+
+ swlevel = find_level(&cpu, irq); /* Criminal offence */
+ intr_disconnect_level(cpu, swlevel);
+}
+
+static void mask_and_ack_bridge_irq(unsigned int irq)
+{
+ disable_bridge_irq(irq);
+}
+
+static void end_bridge_irq(unsigned int irq)
+{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)) &&
+ irq_desc[irq].action)
+ enable_bridge_irq(irq);
+}
+
+static struct hw_interrupt_type bridge_irq_type = {
+ .typename = "bridge",
+ .startup = startup_bridge_irq,
+ .shutdown = shutdown_bridge_irq,
+ .enable = enable_bridge_irq,
+ .disable = disable_bridge_irq,
+ .ack = mask_and_ack_bridge_irq,
+ .end = end_bridge_irq,
+};
+
+static unsigned long irq_map[NR_IRQS / BITS_PER_LONG];
+
+static int allocate_irqno(void)
+{
+ int irq;
+
+again:
+ irq = find_first_zero_bit(irq_map, NR_IRQS);
+
+ if (irq >= NR_IRQS)
+ return -ENOSPC;
+
+ if (test_and_set_bit(irq, irq_map))
+ goto again;
+
+ return irq;
+}
+
+void free_irqno(unsigned int irq)
+{
+ clear_bit(irq, irq_map);
+}
+
+void __devinit register_bridge_irq(unsigned int irq)
+{
+ irq_desc[irq].status = IRQ_DISABLED;
+ irq_desc[irq].action = 0;
+ irq_desc[irq].depth = 1;
+ irq_desc[irq].handler = &bridge_irq_type;
+}
+
+int __devinit request_bridge_irq(struct bridge_controller *bc)
+{
+ int irq = allocate_irqno();
+ int swlevel, cpu;
+ nasid_t nasid;
+
+ if (irq < 0)
+ return irq;
+
+ /*
+ * "map" irq to a swlevel greater than 6 since the first 6 bits
+ * of INT_PEND0 are taken
+ */
+ cpu = bc->irq_cpu;
+ swlevel = alloc_level(cpu, irq);
+ if (unlikely(swlevel < 0)) {
+ free_irqno(irq);
+
+ return -EAGAIN;
+ }
+
+ /* Make sure it's not already pending when we connect it. */
+ nasid = COMPACT_TO_NASID_NODEID(cpu_to_node(cpu));
+ REMOTE_HUB_CLR_INTR(nasid, swlevel);
+
+ intr_connect_level(cpu, swlevel);
+
+ register_bridge_irq(irq);
+
+ return irq;
+}
+
+void __init arch_init_irq(void)
+{
+ set_except_vector(0, ip27_irq);
+}
+
+void install_ipi(void)
+{
+ int slice = LOCAL_HUB_L(PI_CPU_NUM);
+ int cpu = smp_processor_id();
+ struct slice_data *si = cpu_data[cpu].data;
+ hubreg_t mask, set;
+
+ if (slice == 0) {
+ LOCAL_HUB_CLR_INTR(CPU_RESCHED_A_IRQ);
+ LOCAL_HUB_CLR_INTR(CPU_CALL_A_IRQ);
+ mask = LOCAL_HUB_L(PI_INT_MASK0_A); /* Slice A */
+ set = (1UL << CPU_RESCHED_A_IRQ) | (1UL << CPU_CALL_A_IRQ);
+ mask |= set;
+ si->irq_enable_mask[0] |= set;
+ si->irq_alloc_mask[0] |= set;
+ LOCAL_HUB_S(PI_INT_MASK0_A, mask);
+ } else {
+ LOCAL_HUB_CLR_INTR(CPU_RESCHED_B_IRQ);
+ LOCAL_HUB_CLR_INTR(CPU_CALL_B_IRQ);
+ mask = LOCAL_HUB_L(PI_INT_MASK0_B); /* Slice B */
+ set = (1UL << CPU_RESCHED_B_IRQ) | (1UL << CPU_CALL_B_IRQ);
+ mask |= set;
+ si->irq_enable_mask[1] |= set;
+ si->irq_alloc_mask[1] |= set;
+ LOCAL_HUB_S(PI_INT_MASK0_B, mask);
+ }
+}
diff --git a/arch/mips/sgi-ip27/ip27-klconfig.c b/arch/mips/sgi-ip27/ip27-klconfig.c
new file mode 100644
index 0000000..dd830b3
--- /dev/null
+++ b/arch/mips/sgi-ip27/ip27-klconfig.c
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 1999, 2000 Ralf Baechle (ralf@gnu.org)
+ * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/kernel_stat.h>
+#include <linux/param.h>
+#include <linux/timex.h>
+#include <linux/mm.h>
+
+#include <asm/sn/klconfig.h>
+#include <asm/sn/arch.h>
+#include <asm/sn/gda.h>
+
+klinfo_t *find_component(lboard_t *brd, klinfo_t *kli, unsigned char struct_type)
+{
+ int index, j;
+
+ if (kli == (klinfo_t *)NULL) {
+ index = 0;
+ } else {
+ for (j = 0; j < KLCF_NUM_COMPS(brd); j++)
+ if (kli == KLCF_COMP(brd, j))
+ break;
+ index = j;
+ if (index == KLCF_NUM_COMPS(brd)) {
+ printk("find_component: Bad pointer: 0x%p\n", kli);
+ return (klinfo_t *)NULL;
+ }
+ index++; /* next component */
+ }
+
+ for (; index < KLCF_NUM_COMPS(brd); index++) {
+ kli = KLCF_COMP(brd, index);
+ if (KLCF_COMP_TYPE(kli) == struct_type)
+ return kli;
+ }
+
+ /* Didn't find it. */
+ return (klinfo_t *)NULL;
+}
+
+klinfo_t *find_first_component(lboard_t *brd, unsigned char struct_type)
+{
+ return find_component(brd, (klinfo_t *)NULL, struct_type);
+}
+
+lboard_t * find_lboard(lboard_t *start, unsigned char brd_type)
+{
+ /* Search all boards stored on this node. */
+ while (start) {
+ if (start->brd_type == brd_type)
+ return start;
+ start = KLCF_NEXT(start);
+ }
+ /* Didn't find it. */
+ return (lboard_t *)NULL;
+}
+
+lboard_t * find_lboard_class(lboard_t *start, unsigned char brd_type)
+{
+ /* Search all boards stored on this node. */
+ while (start) {
+ if (KLCLASS(start->brd_type) == KLCLASS(brd_type))
+ return start;
+ start = KLCF_NEXT(start);
+ }
+
+ /* Didn't find it. */
+ return (lboard_t *)NULL;
+}
+
+cnodeid_t get_cpu_cnode(cpuid_t cpu)
+{
+ return CPUID_TO_COMPACT_NODEID(cpu);
+}
+
+klcpu_t * nasid_slice_to_cpuinfo(nasid_t nasid, int slice)
+{
+ lboard_t *brd;
+ klcpu_t *acpu;
+
+ if (!(brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_IP27)))
+ return (klcpu_t *)NULL;
+
+ if (!(acpu = (klcpu_t *)find_first_component(brd, KLSTRUCT_CPU)))
+ return (klcpu_t *)NULL;
+
+ do {
+ if ((acpu->cpu_info.physid) == slice)
+ return acpu;
+ } while ((acpu = (klcpu_t *)find_component(brd, (klinfo_t *)acpu,
+ KLSTRUCT_CPU)));
+ return (klcpu_t *)NULL;
+}
+
+klcpu_t * sn_get_cpuinfo(cpuid_t cpu)
+{
+ nasid_t nasid;
+ int slice;
+ klcpu_t *acpu;
+ gda_t *gdap = GDA;
+ cnodeid_t cnode;
+
+ if (!(cpu < MAXCPUS)) {
+ printk("sn_get_cpuinfo: illegal cpuid 0x%lx\n", cpu);
+ return NULL;
+ }
+
+ cnode = get_cpu_cnode(cpu);
+ if (cnode == INVALID_CNODEID)
+ return NULL;
+
+ if ((nasid = gdap->g_nasidtable[cnode]) == INVALID_NASID)
+ return NULL;
+
+ for (slice = 0; slice < CPUS_PER_NODE; slice++) {
+ acpu = nasid_slice_to_cpuinfo(nasid, slice);
+ if (acpu && acpu->cpu_info.virtid == cpu)
+ return acpu;
+ }
+ return NULL;
+}
+
+int get_cpu_slice(cpuid_t cpu)
+{
+ klcpu_t *acpu;
+
+ if ((acpu = sn_get_cpuinfo(cpu)) == NULL)
+ return -1;
+ return acpu->cpu_info.physid;
+}
diff --git a/arch/mips/sgi-ip27/ip27-klnuma.c b/arch/mips/sgi-ip27/ip27-klnuma.c
new file mode 100644
index 0000000..41c3f40
--- /dev/null
+++ b/arch/mips/sgi-ip27/ip27-klnuma.c
@@ -0,0 +1,135 @@
+/*
+ * Ported from IRIX to Linux by Kanoj Sarcar, 06/08/00.
+ * Copyright 2000 - 2001 Silicon Graphics, Inc.
+ * Copyright 2000 - 2001 Kanoj Sarcar (kanoj@sgi.com)
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/mmzone.h>
+#include <linux/kernel.h>
+#include <linux/nodemask.h>
+#include <linux/string.h>
+
+#include <asm/page.h>
+#include <asm/sections.h>
+#include <asm/smp.h>
+#include <asm/sn/types.h>
+#include <asm/sn/arch.h>
+#include <asm/sn/gda.h>
+#include <asm/sn/hub.h>
+#include <asm/sn/mapped_kernel.h>
+#include <asm/sn/sn_private.h>
+
+static cpumask_t ktext_repmask;
+
+/*
+ * XXX - This needs to be much smarter about where it puts copies of the
+ * kernel. For example, we should never put a copy on a headless node,
+ * and we should respect the topology of the machine.
+ */
+void __init setup_replication_mask()
+{
+ cnodeid_t cnode;
+
+ /* Set only the master cnode's bit. The master cnode is always 0. */
+ cpus_clear(ktext_repmask);
+ cpu_set(0, ktext_repmask);
+
+#ifdef CONFIG_REPLICATE_KTEXT
+#ifndef CONFIG_MAPPED_KERNEL
+#error Kernel replication works with mapped kernel support. No calias support.
+#endif
+ for_each_online_node(cnode) {
+ if (cnode == 0)
+ continue;
+ /* Advertise that we have a copy of the kernel */
+ cpu_set(cnode, ktext_repmask);
+ }
+#endif
+ /* Set up a GDA pointer to the replication mask. */
+ GDA->g_ktext_repmask = &ktext_repmask;
+}
+
+
+static __init void set_ktext_source(nasid_t client_nasid, nasid_t server_nasid)
+{
+ cnodeid_t client_cnode;
+ kern_vars_t *kvp;
+
+ client_cnode = NASID_TO_COMPACT_NODEID(client_nasid);
+
+ kvp = &hub_data(client_nasid)->kern_vars;
+
+ KERN_VARS_ADDR(client_nasid) = (unsigned long)kvp;
+
+ kvp->kv_magic = KV_MAGIC;
+ kvp->kv_ro_nasid = server_nasid;
+ kvp->kv_rw_nasid = master_nasid;
+ kvp->kv_ro_baseaddr = NODE_CAC_BASE(server_nasid);
+ kvp->kv_rw_baseaddr = NODE_CAC_BASE(master_nasid);
+ printk("REPLICATION: ON nasid %d, ktext from nasid %d, kdata from nasid %d\n", client_nasid, server_nasid, master_nasid);
+}
+
+/* XXX - When the BTE works, we should use it instead of this. */
+static __init void copy_kernel(nasid_t dest_nasid)
+{
+ unsigned long dest_kern_start, source_start, source_end, kern_size;
+
+ source_start = (unsigned long) _stext;
+ source_end = (unsigned long) _etext;
+ kern_size = source_end - source_start;
+
+ dest_kern_start = CHANGE_ADDR_NASID(MAPPED_KERN_RO_TO_K0(source_start),
+ dest_nasid);
+ memcpy((void *)dest_kern_start, (void *)source_start, kern_size);
+}
+
+void __init replicate_kernel_text()
+{
+ cnodeid_t cnode;
+ nasid_t client_nasid;
+ nasid_t server_nasid;
+
+ server_nasid = master_nasid;
+
+ /* Record where the master node should get its kernel text */
+ set_ktext_source(master_nasid, master_nasid);
+
+ for_each_online_node(cnode) {
+ if (cnode == 0)
+ continue;
+ client_nasid = COMPACT_TO_NASID_NODEID(cnode);
+
+ /* Check if this node should get a copy of the kernel */
+ if (cpu_isset(cnode, ktext_repmask)) {
+ server_nasid = client_nasid;
+ copy_kernel(server_nasid);
+ }
+
+ /* Record where this node should get its kernel text */
+ set_ktext_source(client_nasid, server_nasid);
+ }
+}
+
+/*
+ * Return pfn of first free page of memory on a node. PROM may allocate
+ * data structures on the first couple of pages of the first slot of each
+ * node. If this is the case, getfirstfree(node) > getslotstart(node, 0).
+ */
+pfn_t node_getfirstfree(cnodeid_t cnode)
+{
+ unsigned long loadbase = REP_BASE;
+ nasid_t nasid = COMPACT_TO_NASID_NODEID(cnode);
+ unsigned long offset;
+
+#ifdef CONFIG_MAPPED_KERNEL
+ loadbase += 16777216;
+#endif
+ offset = PAGE_ALIGN((unsigned long)(&_end)) - loadbase;
+ if ((cnode == 0) || (cpu_isset(cnode, ktext_repmask)))
+ return (TO_NODE(nasid, offset) >> PAGE_SHIFT);
+ else
+ return (KDM_TO_PHYS(PAGE_ALIGN(SYMMON_STK_ADDR(nasid, 0))) >>
+ PAGE_SHIFT);
+}
+
diff --git a/arch/mips/sgi-ip27/ip27-memory.c b/arch/mips/sgi-ip27/ip27-memory.c
new file mode 100644
index 0000000..0a44a98
--- /dev/null
+++ b/arch/mips/sgi-ip27/ip27-memory.c
@@ -0,0 +1,586 @@
+/*
+ * 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) 2000, 05 by Ralf Baechle (ralf@linux-mips.org)
+ * Copyright (C) 2000 by Silicon Graphics, Inc.
+ * Copyright (C) 2004 by Christoph Hellwig
+ *
+ * On SGI IP27 the ARC memory configuration data is completly bogus but
+ * alternate easier to use mechanisms are available.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/mmzone.h>
+#include <linux/module.h>
+#include <linux/nodemask.h>
+#include <linux/swap.h>
+#include <linux/bootmem.h>
+#include <asm/page.h>
+#include <asm/sections.h>
+
+#include <asm/sn/arch.h>
+#include <asm/sn/hub.h>
+#include <asm/sn/klconfig.h>
+#include <asm/sn/sn_private.h>
+
+
+#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
+
+#define SLOT_PFNSHIFT (SLOT_SHIFT - PAGE_SHIFT)
+#define PFN_NASIDSHFT (NASID_SHFT - PAGE_SHIFT)
+
+#define SLOT_IGNORED 0xffff
+
+static short __initdata slot_lastfilled_cache[MAX_COMPACT_NODES];
+static unsigned short __initdata slot_psize_cache[MAX_COMPACT_NODES][MAX_MEM_SLOTS];
+static struct bootmem_data __initdata plat_node_bdata[MAX_COMPACT_NODES];
+
+struct node_data *__node_data[MAX_COMPACT_NODES];
+
+EXPORT_SYMBOL(__node_data);
+
+static int fine_mode;
+
+static int is_fine_dirmode(void)
+{
+ return (((LOCAL_HUB_L(NI_STATUS_REV_ID) & NSRI_REGIONSIZE_MASK)
+ >> NSRI_REGIONSIZE_SHFT) & REGIONSIZE_FINE);
+}
+
+static hubreg_t get_region(cnodeid_t cnode)
+{
+ if (fine_mode)
+ return COMPACT_TO_NASID_NODEID(cnode) >> NASID_TO_FINEREG_SHFT;
+ else
+ return COMPACT_TO_NASID_NODEID(cnode) >> NASID_TO_COARSEREG_SHFT;
+}
+
+static hubreg_t region_mask;
+
+static void gen_region_mask(hubreg_t *region_mask)
+{
+ cnodeid_t cnode;
+
+ (*region_mask) = 0;
+ for_each_online_node(cnode) {
+ (*region_mask) |= 1ULL << get_region(cnode);
+ }
+}
+
+#define rou_rflag rou_flags
+
+static int router_distance;
+
+static void router_recurse(klrou_t *router_a, klrou_t *router_b, int depth)
+{
+ klrou_t *router;
+ lboard_t *brd;
+ int port;
+
+ if (router_a->rou_rflag == 1)
+ return;
+
+ if (depth >= router_distance)
+ return;
+
+ router_a->rou_rflag = 1;
+
+ for (port = 1; port <= MAX_ROUTER_PORTS; port++) {
+ if (router_a->rou_port[port].port_nasid == INVALID_NASID)
+ continue;
+
+ brd = (lboard_t *)NODE_OFFSET_TO_K0(
+ router_a->rou_port[port].port_nasid,
+ router_a->rou_port[port].port_offset);
+
+ if (brd->brd_type == KLTYPE_ROUTER) {
+ router = (klrou_t *)NODE_OFFSET_TO_K0(NASID_GET(brd), brd->brd_compts[0]);
+ if (router == router_b) {
+ if (depth < router_distance)
+ router_distance = depth;
+ }
+ else
+ router_recurse(router, router_b, depth + 1);
+ }
+ }
+
+ router_a->rou_rflag = 0;
+}
+
+unsigned char __node_distances[MAX_COMPACT_NODES][MAX_COMPACT_NODES];
+
+static int __init compute_node_distance(nasid_t nasid_a, nasid_t nasid_b)
+{
+ klrou_t *router, *router_a = NULL, *router_b = NULL;
+ lboard_t *brd, *dest_brd;
+ cnodeid_t cnode;
+ nasid_t nasid;
+ int port;
+
+ /* Figure out which routers nodes in question are connected to */
+ for_each_online_node(cnode) {
+ nasid = COMPACT_TO_NASID_NODEID(cnode);
+
+ if (nasid == -1) continue;
+
+ brd = find_lboard_class((lboard_t *)KL_CONFIG_INFO(nasid),
+ KLTYPE_ROUTER);
+
+ if (!brd)
+ continue;
+
+ do {
+ if (brd->brd_flags & DUPLICATE_BOARD)
+ continue;
+
+ router = (klrou_t *)NODE_OFFSET_TO_K0(NASID_GET(brd), brd->brd_compts[0]);
+ router->rou_rflag = 0;
+
+ for (port = 1; port <= MAX_ROUTER_PORTS; port++) {
+ if (router->rou_port[port].port_nasid == INVALID_NASID)
+ continue;
+
+ dest_brd = (lboard_t *)NODE_OFFSET_TO_K0(
+ router->rou_port[port].port_nasid,
+ router->rou_port[port].port_offset);
+
+ if (dest_brd->brd_type == KLTYPE_IP27) {
+ if (dest_brd->brd_nasid == nasid_a)
+ router_a = router;
+ if (dest_brd->brd_nasid == nasid_b)
+ router_b = router;
+ }
+ }
+
+ } while ((brd = find_lboard_class(KLCF_NEXT(brd), KLTYPE_ROUTER)));
+ }
+
+ if (router_a == NULL) {
+ printk("node_distance: router_a NULL\n");
+ return -1;
+ }
+ if (router_b == NULL) {
+ printk("node_distance: router_b NULL\n");
+ return -1;
+ }
+
+ if (nasid_a == nasid_b)
+ return 0;
+
+ if (router_a == router_b)
+ return 1;
+
+ router_distance = 100;
+ router_recurse(router_a, router_b, 2);
+
+ return router_distance;
+}
+
+static void __init init_topology_matrix(void)
+{
+ nasid_t nasid, nasid2;
+ cnodeid_t row, col;
+
+ for (row = 0; row < MAX_COMPACT_NODES; row++)
+ for (col = 0; col < MAX_COMPACT_NODES; col++)
+ __node_distances[row][col] = -1;
+
+ for_each_online_node(row) {
+ nasid = COMPACT_TO_NASID_NODEID(row);
+ for_each_online_node(col) {
+ nasid2 = COMPACT_TO_NASID_NODEID(col);
+ __node_distances[row][col] =
+ compute_node_distance(nasid, nasid2);
+ }
+ }
+}
+
+static void __init dump_topology(void)
+{
+ nasid_t nasid;
+ cnodeid_t cnode;
+ lboard_t *brd, *dest_brd;
+ int port;
+ int router_num = 0;
+ klrou_t *router;
+ cnodeid_t row, col;
+
+ printk("************** Topology ********************\n");
+
+ printk(" ");
+ for_each_online_node(col)
+ printk("%02d ", col);
+ printk("\n");
+ for_each_online_node(row) {
+ printk("%02d ", row);
+ for_each_online_node(col)
+ printk("%2d ", node_distance(row, col));
+ printk("\n");
+ }
+
+ for_each_online_node(cnode) {
+ nasid = COMPACT_TO_NASID_NODEID(cnode);
+
+ if (nasid == -1) continue;
+
+ brd = find_lboard_class((lboard_t *)KL_CONFIG_INFO(nasid),
+ KLTYPE_ROUTER);
+
+ if (!brd)
+ continue;
+
+ do {
+ if (brd->brd_flags & DUPLICATE_BOARD)
+ continue;
+ printk("Router %d:", router_num);
+ router_num++;
+
+ router = (klrou_t *)NODE_OFFSET_TO_K0(NASID_GET(brd), brd->brd_compts[0]);
+
+ for (port = 1; port <= MAX_ROUTER_PORTS; port++) {
+ if (router->rou_port[port].port_nasid == INVALID_NASID)
+ continue;
+
+ dest_brd = (lboard_t *)NODE_OFFSET_TO_K0(
+ router->rou_port[port].port_nasid,
+ router->rou_port[port].port_offset);
+
+ if (dest_brd->brd_type == KLTYPE_IP27)
+ printk(" %d", dest_brd->brd_nasid);
+ if (dest_brd->brd_type == KLTYPE_ROUTER)
+ printk(" r");
+ }
+ printk("\n");
+
+ } while ( (brd = find_lboard_class(KLCF_NEXT(brd), KLTYPE_ROUTER)) );
+ }
+}
+
+static pfn_t __init slot_getbasepfn(cnodeid_t cnode, int slot)
+{
+ nasid_t nasid = COMPACT_TO_NASID_NODEID(cnode);
+
+ return ((pfn_t)nasid << PFN_NASIDSHFT) | (slot << SLOT_PFNSHIFT);
+}
+
+/*
+ * Return the number of pages of memory provided by the given slot
+ * on the specified node.
+ */
+static pfn_t __init slot_getsize(cnodeid_t node, int slot)
+{
+ return (pfn_t) slot_psize_cache[node][slot];
+}
+
+/*
+ * Return highest slot filled
+ */
+static int __init node_getlastslot(cnodeid_t node)
+{
+ return (int) slot_lastfilled_cache[node];
+}
+
+/*
+ * Return the pfn of the last free page of memory on a node.
+ */
+static pfn_t __init node_getmaxclick(cnodeid_t node)
+{
+ pfn_t slot_psize;
+ int slot;
+
+ /*
+ * Start at the top slot. When we find a slot with memory in it,
+ * that's the winner.
+ */
+ for (slot = (MAX_MEM_SLOTS - 1); slot >= 0; slot--) {
+ if ((slot_psize = slot_getsize(node, slot))) {
+ if (slot_psize == SLOT_IGNORED)
+ continue;
+ /* Return the basepfn + the slot size, minus 1. */
+ return slot_getbasepfn(node, slot) + slot_psize - 1;
+ }
+ }
+
+ /*
+ * If there's no memory on the node, return 0. This is likely
+ * to cause problems.
+ */
+ return 0;
+}
+
+static pfn_t __init slot_psize_compute(cnodeid_t node, int slot)
+{
+ nasid_t nasid;
+ lboard_t *brd;
+ klmembnk_t *banks;
+ unsigned long size;
+
+ nasid = COMPACT_TO_NASID_NODEID(node);
+ /* Find the node board */
+ brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_IP27);
+ if (!brd)
+ return 0;
+
+ /* Get the memory bank structure */
+ banks = (klmembnk_t *) find_first_component(brd, KLSTRUCT_MEMBNK);
+ if (!banks)
+ return 0;
+
+ /* Size in _Megabytes_ */
+ size = (unsigned long)banks->membnk_bnksz[slot/4];
+
+ /* hack for 128 dimm banks */
+ if (size <= 128) {
+ if (slot % 4 == 0) {
+ size <<= 20; /* size in bytes */
+ return(size >> PAGE_SHIFT);
+ } else
+ return 0;
+ } else {
+ size /= 4;
+ size <<= 20;
+ return size >> PAGE_SHIFT;
+ }
+}
+
+static void __init mlreset(void)
+{
+ int i;
+
+ master_nasid = get_nasid();
+ fine_mode = is_fine_dirmode();
+
+ /*
+ * Probe for all CPUs - this creates the cpumask and sets up the
+ * mapping tables. We need to do this as early as possible.
+ */
+#ifdef CONFIG_SMP
+ cpu_node_probe();
+#endif
+
+ init_topology_matrix();
+ dump_topology();
+
+ gen_region_mask(®ion_mask);
+
+ setup_replication_mask();
+
+ /*
+ * Set all nodes' calias sizes to 8k
+ */
+ for_each_online_node(i) {
+ nasid_t nasid;
+
+ nasid = COMPACT_TO_NASID_NODEID(i);
+
+ /*
+ * Always have node 0 in the region mask, otherwise
+ * CALIAS accesses get exceptions since the hub
+ * thinks it is a node 0 address.
+ */
+ REMOTE_HUB_S(nasid, PI_REGION_PRESENT, (region_mask | 1));
+#ifdef CONFIG_REPLICATE_EXHANDLERS
+ REMOTE_HUB_S(nasid, PI_CALIAS_SIZE, PI_CALIAS_SIZE_8K);
+#else
+ REMOTE_HUB_S(nasid, PI_CALIAS_SIZE, PI_CALIAS_SIZE_0);
+#endif
+
+#ifdef LATER
+ /*
+ * Set up all hubs to have a big window pointing at
+ * widget 0. Memory mode, widget 0, offset 0
+ */
+ REMOTE_HUB_S(nasid, IIO_ITTE(SWIN0_BIGWIN),
+ ((HUB_PIO_MAP_TO_MEM << IIO_ITTE_IOSP_SHIFT) |
+ (0 << IIO_ITTE_WIDGET_SHIFT)));
+#endif
+ }
+}
+
+static void __init szmem(void)
+{
+ pfn_t slot_psize, slot0sz = 0, nodebytes; /* Hack to detect problem configs */
+ int slot, ignore;
+ cnodeid_t node;
+
+ num_physpages = 0;
+
+ for_each_online_node(node) {
+ ignore = nodebytes = 0;
+ for (slot = 0; slot < MAX_MEM_SLOTS; slot++) {
+ slot_psize = slot_psize_compute(node, slot);
+ if (slot == 0)
+ slot0sz = slot_psize;
+ /*
+ * We need to refine the hack when we have replicated
+ * kernel text.
+ */
+ nodebytes += (1LL << SLOT_SHIFT);
+ if ((nodebytes >> PAGE_SHIFT) * (sizeof(struct page)) >
+ (slot0sz << PAGE_SHIFT))
+ ignore = 1;
+ if (ignore && slot_psize) {
+ printk("Ignoring slot %d onwards on node %d\n",
+ slot, node);
+ slot_psize_cache[node][slot] = SLOT_IGNORED;
+ slot = MAX_MEM_SLOTS;
+ continue;
+ }
+ num_physpages += slot_psize;
+ slot_psize_cache[node][slot] =
+ (unsigned short) slot_psize;
+ if (slot_psize)
+ slot_lastfilled_cache[node] = slot;
+ }
+ }
+}
+
+static void __init node_mem_init(cnodeid_t node)
+{
+ pfn_t slot_firstpfn = slot_getbasepfn(node, 0);
+ pfn_t slot_lastpfn = slot_firstpfn + slot_getsize(node, 0);
+ pfn_t slot_freepfn = node_getfirstfree(node);
+ struct pglist_data *pd;
+ unsigned long bootmap_size;
+
+ /*
+ * Allocate the node data structures on the node first.
+ */
+ __node_data[node] = __va(slot_freepfn << PAGE_SHIFT);
+
+ pd = NODE_DATA(node);
+ pd->bdata = &plat_node_bdata[node];
+
+ cpus_clear(hub_data(node)->h_cpus);
+
+ slot_freepfn += PFN_UP(sizeof(struct pglist_data) +
+ sizeof(struct hub_data));
+
+ bootmap_size = init_bootmem_node(NODE_DATA(node), slot_freepfn,
+ slot_firstpfn, slot_lastpfn);
+ free_bootmem_node(NODE_DATA(node), slot_firstpfn << PAGE_SHIFT,
+ (slot_lastpfn - slot_firstpfn) << PAGE_SHIFT);
+ reserve_bootmem_node(NODE_DATA(node), slot_firstpfn << PAGE_SHIFT,
+ ((slot_freepfn - slot_firstpfn) << PAGE_SHIFT) + bootmap_size);
+}
+
+/*
+ * A node with nothing. We use it to avoid any special casing in
+ * node_to_cpumask
+ */
+static struct node_data null_node = {
+ .hub = {
+ .h_cpus = CPU_MASK_NONE
+ }
+};
+
+/*
+ * Currently, the intranode memory hole support assumes that each slot
+ * contains at least 32 MBytes of memory. We assume all bootmem data
+ * fits on the first slot.
+ */
+void __init prom_meminit(void)
+{
+ cnodeid_t node;
+
+ mlreset();
+ szmem();
+
+ for (node = 0; node < MAX_COMPACT_NODES; node++) {
+ if (node_online(node)) {
+ node_mem_init(node);
+ continue;
+ }
+ __node_data[node] = &null_node;
+ }
+}
+
+unsigned long __init prom_free_prom_memory(void)
+{
+ /* We got nothing to free here ... */
+ return 0;
+}
+
+extern void pagetable_init(void);
+extern unsigned long setup_zero_pages(void);
+
+void __init paging_init(void)
+{
+ unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0};
+ unsigned node;
+
+ pagetable_init();
+
+ for_each_online_node(node) {
+ pfn_t start_pfn = slot_getbasepfn(node, 0);
+ pfn_t end_pfn = node_getmaxclick(node) + 1;
+
+ zones_size[ZONE_DMA] = end_pfn - start_pfn;
+ free_area_init_node(node, NODE_DATA(node),
+ zones_size, start_pfn, NULL);
+
+ if (end_pfn > max_low_pfn)
+ max_low_pfn = end_pfn;
+ }
+}
+
+void __init mem_init(void)
+{
+ unsigned long codesize, datasize, initsize, tmp;
+ unsigned node;
+
+ high_memory = (void *) __va(num_physpages << PAGE_SHIFT);
+
+ for_each_online_node(node) {
+ unsigned slot, numslots;
+ struct page *end, *p;
+
+ /*
+ * This will free up the bootmem, ie, slot 0 memory.
+ */
+ totalram_pages += free_all_bootmem_node(NODE_DATA(node));
+
+ /*
+ * We need to manually do the other slots.
+ */
+ numslots = node_getlastslot(node);
+ for (slot = 1; slot <= numslots; slot++) {
+ p = NODE_DATA(node)->node_mem_map +
+ (slot_getbasepfn(node, slot) -
+ slot_getbasepfn(node, 0));
+
+ /*
+ * Free valid memory in current slot.
+ */
+ for (end = p + slot_getsize(node, slot); p < end; p++) {
+ /* if (!page_is_ram(pgnr)) continue; */
+ /* commented out until page_is_ram works */
+ ClearPageReserved(p);
+ set_page_count(p, 1);
+ __free_page(p);
+ totalram_pages++;
+ }
+ }
+ }
+
+ totalram_pages -= setup_zero_pages(); /* This comes from node 0 */
+
+ codesize = (unsigned long) &_etext - (unsigned long) &_text;
+ datasize = (unsigned long) &_edata - (unsigned long) &_etext;
+ initsize = (unsigned long) &__init_end - (unsigned long) &__init_begin;
+
+ tmp = nr_free_pages();
+ printk(KERN_INFO "Memory: %luk/%luk available (%ldk kernel code, "
+ "%ldk reserved, %ldk data, %ldk init, %ldk highmem)\n",
+ tmp << (PAGE_SHIFT-10),
+ num_physpages << (PAGE_SHIFT-10),
+ codesize >> 10,
+ (num_physpages - tmp) << (PAGE_SHIFT-10),
+ datasize >> 10,
+ initsize >> 10,
+ (unsigned long) (totalhigh_pages << (PAGE_SHIFT-10)));
+}
diff --git a/arch/mips/sgi-ip27/ip27-nmi.c b/arch/mips/sgi-ip27/ip27-nmi.c
new file mode 100644
index 0000000..b0a25e1
--- /dev/null
+++ b/arch/mips/sgi-ip27/ip27-nmi.c
@@ -0,0 +1,249 @@
+#include <linux/kallsyms.h>
+#include <linux/kernel.h>
+#include <linux/mmzone.h>
+#include <linux/nodemask.h>
+#include <linux/spinlock.h>
+#include <linux/smp.h>
+#include <asm/atomic.h>
+#include <asm/sn/types.h>
+#include <asm/sn/addrs.h>
+#include <asm/sn/nmi.h>
+#include <asm/sn/arch.h>
+#include <asm/sn/sn0/hub.h>
+
+#if 0
+#define NODE_NUM_CPUS(n) CNODE_NUM_CPUS(n)
+#else
+#define NODE_NUM_CPUS(n) CPUS_PER_NODE
+#endif
+
+#define CNODEID_NONE (cnodeid_t)-1
+#define enter_panic_mode() spin_lock(&nmi_lock)
+
+typedef unsigned long machreg_t;
+
+DEFINE_SPINLOCK(nmi_lock);
+
+/*
+ * Lets see what else we need to do here. Set up sp, gp?
+ */
+void nmi_dump(void)
+{
+ void cont_nmi_dump(void);
+
+ cont_nmi_dump();
+}
+
+void install_cpu_nmi_handler(int slice)
+{
+ nmi_t *nmi_addr;
+
+ nmi_addr = (nmi_t *)NMI_ADDR(get_nasid(), slice);
+ if (nmi_addr->call_addr)
+ return;
+ nmi_addr->magic = NMI_MAGIC;
+ nmi_addr->call_addr = (void *)nmi_dump;
+ nmi_addr->call_addr_c =
+ (void *)(~((unsigned long)(nmi_addr->call_addr)));
+ nmi_addr->call_parm = 0;
+}
+
+/*
+ * Copy the cpu registers which have been saved in the IP27prom format
+ * into the eframe format for the node under consideration.
+ */
+
+void nmi_cpu_eframe_save(nasid_t nasid, int slice)
+{
+ struct reg_struct *nr;
+ int i;
+
+ /* Get the pointer to the current cpu's register set. */
+ nr = (struct reg_struct *)
+ (TO_UNCAC(TO_NODE(nasid, IP27_NMI_KREGS_OFFSET)) +
+ slice * IP27_NMI_KREGS_CPU_SIZE);
+
+ printk("NMI nasid %d: slice %d\n", nasid, slice);
+
+ /*
+ * Saved main processor registers
+ */
+ for (i = 0; i < 32; ) {
+ if ((i % 4) == 0)
+ printk("$%2d :", i);
+ printk(" %016lx", nr->gpr[i]);
+
+ i++;
+ if ((i % 4) == 0)
+ printk("\n");
+ }
+
+ printk("Hi : (value lost)\n");
+ printk("Lo : (value lost)\n");
+
+ /*
+ * Saved cp0 registers
+ */
+ printk("epc : %016lx ", nr->epc);
+ print_symbol("%s ", nr->epc);
+ printk("%s\n", print_tainted());
+ printk("ErrEPC: %016lx ", nr->error_epc);
+ print_symbol("%s\n", nr->error_epc);
+ printk("ra : %016lx ", nr->gpr[31]);
+ print_symbol("%s\n", nr->gpr[31]);
+ printk("Status: %08lx ", nr->sr);
+
+ if (nr->sr & ST0_KX)
+ printk("KX ");
+ if (nr->sr & ST0_SX)
+ printk("SX ");
+ if (nr->sr & ST0_UX)
+ printk("UX ");
+
+ switch (nr->sr & ST0_KSU) {
+ case KSU_USER:
+ printk("USER ");
+ break;
+ case KSU_SUPERVISOR:
+ printk("SUPERVISOR ");
+ break;
+ case KSU_KERNEL:
+ printk("KERNEL ");
+ break;
+ default:
+ printk("BAD_MODE ");
+ break;
+ }
+
+ if (nr->sr & ST0_ERL)
+ printk("ERL ");
+ if (nr->sr & ST0_EXL)
+ printk("EXL ");
+ if (nr->sr & ST0_IE)
+ printk("IE ");
+ printk("\n");
+
+ printk("Cause : %08lx\n", nr->cause);
+ printk("PrId : %08x\n", read_c0_prid());
+ printk("BadVA : %016lx\n", nr->badva);
+ printk("CErr : %016lx\n", nr->cache_err);
+ printk("NMI_SR: %016lx\n", nr->nmi_sr);
+
+ printk("\n");
+}
+
+void nmi_dump_hub_irq(nasid_t nasid, int slice)
+{
+ hubreg_t mask0, mask1, pend0, pend1;
+
+ if (slice == 0) { /* Slice A */
+ mask0 = REMOTE_HUB_L(nasid, PI_INT_MASK0_A);
+ mask1 = REMOTE_HUB_L(nasid, PI_INT_MASK1_A);
+ } else { /* Slice B */
+ mask0 = REMOTE_HUB_L(nasid, PI_INT_MASK0_B);
+ mask1 = REMOTE_HUB_L(nasid, PI_INT_MASK1_B);
+ }
+
+ pend0 = REMOTE_HUB_L(nasid, PI_INT_PEND0);
+ pend1 = REMOTE_HUB_L(nasid, PI_INT_PEND1);
+
+ printk("PI_INT_MASK0: %16lx PI_INT_MASK1: %16lx\n", mask0, mask1);
+ printk("PI_INT_PEND0: %16lx PI_INT_PEND1: %16lx\n", pend0, pend1);
+ printk("\n\n");
+}
+
+/*
+ * Copy the cpu registers which have been saved in the IP27prom format
+ * into the eframe format for the node under consideration.
+ */
+void nmi_node_eframe_save(cnodeid_t cnode)
+{
+ nasid_t nasid;
+ int slice;
+
+ /* Make sure that we have a valid node */
+ if (cnode == CNODEID_NONE)
+ return;
+
+ nasid = COMPACT_TO_NASID_NODEID(cnode);
+ if (nasid == INVALID_NASID)
+ return;
+
+ /* Save the registers into eframe for each cpu */
+ for (slice = 0; slice < NODE_NUM_CPUS(slice); slice++) {
+ nmi_cpu_eframe_save(nasid, slice);
+ nmi_dump_hub_irq(nasid, slice);
+ }
+}
+
+/*
+ * Save the nmi cpu registers for all cpus in the system.
+ */
+void
+nmi_eframes_save(void)
+{
+ cnodeid_t cnode;
+
+ for_each_online_node(cnode)
+ nmi_node_eframe_save(cnode);
+}
+
+void
+cont_nmi_dump(void)
+{
+#ifndef REAL_NMI_SIGNAL
+ static atomic_t nmied_cpus = ATOMIC_INIT(0);
+
+ atomic_inc(&nmied_cpus);
+#endif
+ /*
+ * Use enter_panic_mode to allow only 1 cpu to proceed
+ */
+ enter_panic_mode();
+
+#ifdef REAL_NMI_SIGNAL
+ /*
+ * Wait up to 15 seconds for the other cpus to respond to the NMI.
+ * If a cpu has not responded after 10 sec, send it 1 additional NMI.
+ * This is for 2 reasons:
+ * - sometimes a MMSC fail to NMI all cpus.
+ * - on 512p SN0 system, the MMSC will only send NMIs to
+ * half the cpus. Unfortunately, we don't know which cpus may be
+ * NMIed - it depends on how the site chooses to configure.
+ *
+ * Note: it has been measure that it takes the MMSC up to 2.3 secs to
+ * send NMIs to all cpus on a 256p system.
+ */
+ for (i=0; i < 1500; i++) {
+ for_each_online_node(node)
+ if (NODEPDA(node)->dump_count == 0)
+ break;
+ if (node == MAX_NUMNODES)
+ break;
+ if (i == 1000) {
+ for_each_online_node(node)
+ if (NODEPDA(node)->dump_count == 0) {
+ cpu = node_to_first_cpu(node);
+ for (n=0; n < CNODE_NUM_CPUS(node); cpu++, n++) {
+ CPUMASK_SETB(nmied_cpus, cpu);
+ /*
+ * cputonasid, cputoslice
+ * needs kernel cpuid
+ */
+ SEND_NMI((cputonasid(cpu)), (cputoslice(cpu)));
+ }
+ }
+
+ }
+ udelay(10000);
+ }
+#else
+ while (atomic_read(&nmied_cpus) != num_online_cpus());
+#endif
+
+ /*
+ * Save the nmi cpu registers for all cpu in the eframe format.
+ */
+ nmi_eframes_save();
+ LOCAL_HUB_S(NI_PORT_RESET, NPR_PORTRESET | NPR_LOCALRESET);
+}
diff --git a/arch/mips/sgi-ip27/ip27-reset.c b/arch/mips/sgi-ip27/ip27-reset.c
new file mode 100644
index 0000000..2e16be9
--- /dev/null
+++ b/arch/mips/sgi-ip27/ip27-reset.c
@@ -0,0 +1,81 @@
+/*
+ * 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.
+ *
+ * Reset an IP27.
+ *
+ * Copyright (C) 1997, 1998, 1999, 2000 by Ralf Baechle
+ * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/smp.h>
+#include <linux/mmzone.h>
+#include <linux/nodemask.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/reboot.h>
+#include <asm/system.h>
+#include <asm/sgialib.h>
+#include <asm/sn/addrs.h>
+#include <asm/sn/arch.h>
+#include <asm/sn/gda.h>
+#include <asm/sn/sn0/hub.h>
+
+void machine_restart(char *command) __attribute__((noreturn));
+void machine_halt(void) __attribute__((noreturn));
+void machine_power_off(void) __attribute__((noreturn));
+
+#define noreturn while(1); /* Silence gcc. */
+
+/* XXX How to pass the reboot command to the firmware??? */
+static void ip27_machine_restart(char *command)
+{
+#if 0
+ int i;
+#endif
+
+ printk("Reboot started from CPU %d\n", smp_processor_id());
+#ifdef CONFIG_SMP
+ smp_send_stop();
+#endif
+#if 0
+ for_each_online_node(i)
+ REMOTE_HUB_S(COMPACT_TO_NASID_NODEID(i), PROMOP_REG,
+ PROMOP_REBOOT);
+#else
+ LOCAL_HUB_S(NI_PORT_RESET, NPR_PORTRESET | NPR_LOCALRESET);
+#endif
+ noreturn;
+}
+
+static void ip27_machine_halt(void)
+{
+ int i;
+
+#ifdef CONFIG_SMP
+ smp_send_stop();
+#endif
+ for_each_online_node(i)
+ REMOTE_HUB_S(COMPACT_TO_NASID_NODEID(i), PROMOP_REG,
+ PROMOP_RESTART);
+ LOCAL_HUB_S(NI_PORT_RESET, NPR_PORTRESET | NPR_LOCALRESET);
+ noreturn;
+}
+
+static void ip27_machine_power_off(void)
+{
+ /* To do ... */
+ noreturn;
+}
+
+void ip27_reboot_setup(void)
+{
+ _machine_restart = ip27_machine_restart;
+ _machine_halt = ip27_machine_halt;
+ _machine_power_off = ip27_machine_power_off;
+}
diff --git a/arch/mips/sgi-ip27/ip27-smp.c b/arch/mips/sgi-ip27/ip27-smp.c
new file mode 100644
index 0000000..17f768c
--- /dev/null
+++ b/arch/mips/sgi-ip27/ip27-smp.c
@@ -0,0 +1,225 @@
+/*
+ * 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) 2000 - 2001 by Kanoj Sarcar (kanoj@sgi.com)
+ * Copyright (C) 2000 - 2001 by Silicon Graphics, Inc.
+ */
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/nodemask.h>
+#include <asm/page.h>
+#include <asm/processor.h>
+#include <asm/sn/arch.h>
+#include <asm/sn/gda.h>
+#include <asm/sn/intr.h>
+#include <asm/sn/klconfig.h>
+#include <asm/sn/launch.h>
+#include <asm/sn/mapped_kernel.h>
+#include <asm/sn/sn_private.h>
+#include <asm/sn/types.h>
+#include <asm/sn/sn0/hubpi.h>
+#include <asm/sn/sn0/hubio.h>
+#include <asm/sn/sn0/ip27.h>
+
+/*
+ * Takes as first input the PROM assigned cpu id, and the kernel
+ * assigned cpu id as the second.
+ */
+static void alloc_cpupda(cpuid_t cpu, int cpunum)
+{
+ cnodeid_t node = get_cpu_cnode(cpu);
+ nasid_t nasid = COMPACT_TO_NASID_NODEID(node);
+
+ cputonasid(cpunum) = nasid;
+ cpu_data[cpunum].p_nodeid = node;
+ cputoslice(cpunum) = get_cpu_slice(cpu);
+}
+
+static nasid_t get_actual_nasid(lboard_t *brd)
+{
+ klhub_t *hub;
+
+ if (!brd)
+ return INVALID_NASID;
+
+ /* find out if we are a completely disabled brd. */
+ hub = (klhub_t *)find_first_component(brd, KLSTRUCT_HUB);
+ if (!hub)
+ return INVALID_NASID;
+ if (!(hub->hub_info.flags & KLINFO_ENABLE)) /* disabled node brd */
+ return hub->hub_info.physid;
+ else
+ return brd->brd_nasid;
+}
+
+static int do_cpumask(cnodeid_t cnode, nasid_t nasid, int highest)
+{
+ static int tot_cpus_found = 0;
+ lboard_t *brd;
+ klcpu_t *acpu;
+ int cpus_found = 0;
+ cpuid_t cpuid;
+
+ brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_IP27);
+
+ do {
+ acpu = (klcpu_t *)find_first_component(brd, KLSTRUCT_CPU);
+ while (acpu) {
+ cpuid = acpu->cpu_info.virtid;
+ /* cnode is not valid for completely disabled brds */
+ if (get_actual_nasid(brd) == brd->brd_nasid)
+ cpuid_to_compact_node[cpuid] = cnode;
+ if (cpuid > highest)
+ highest = cpuid;
+ /* Only let it join in if it's marked enabled */
+ if ((acpu->cpu_info.flags & KLINFO_ENABLE) &&
+ (tot_cpus_found != NR_CPUS)) {
+ cpu_set(cpuid, phys_cpu_present_map);
+ alloc_cpupda(cpuid, tot_cpus_found);
+ cpus_found++;
+ tot_cpus_found++;
+ }
+ acpu = (klcpu_t *)find_component(brd, (klinfo_t *)acpu,
+ KLSTRUCT_CPU);
+ }
+ brd = KLCF_NEXT(brd);
+ if (!brd)
+ break;
+
+ brd = find_lboard(brd, KLTYPE_IP27);
+ } while (brd);
+
+ return highest;
+}
+
+void cpu_node_probe(void)
+{
+ int i, highest = 0;
+ gda_t *gdap = GDA;
+
+ /*
+ * Initialize the arrays to invalid nodeid (-1)
+ */
+ for (i = 0; i < MAX_COMPACT_NODES; i++)
+ compact_to_nasid_node[i] = INVALID_NASID;
+ for (i = 0; i < MAX_NASIDS; i++)
+ nasid_to_compact_node[i] = INVALID_CNODEID;
+ for (i = 0; i < MAXCPUS; i++)
+ cpuid_to_compact_node[i] = INVALID_CNODEID;
+
+ /*
+ * MCD - this whole "compact node" stuff can probably be dropped,
+ * as we can handle sparse numbering now
+ */
+ nodes_clear(node_online_map);
+ for (i = 0; i < MAX_COMPACT_NODES; i++) {
+ nasid_t nasid = gdap->g_nasidtable[i];
+ if (nasid == INVALID_NASID)
+ break;
+ compact_to_nasid_node[i] = nasid;
+ nasid_to_compact_node[nasid] = i;
+ node_set_online(num_online_nodes());
+ highest = do_cpumask(i, nasid, highest);
+ }
+
+ printk("Discovered %d cpus on %d nodes\n", highest + 1, num_online_nodes());
+}
+
+static void intr_clear_bits(nasid_t nasid, volatile hubreg_t *pend,
+ int base_level)
+{
+ volatile hubreg_t bits;
+ int i;
+
+ /* Check pending interrupts */
+ if ((bits = HUB_L(pend)) != 0)
+ for (i = 0; i < N_INTPEND_BITS; i++)
+ if (bits & (1 << i))
+ LOCAL_HUB_CLR_INTR(base_level + i);
+}
+
+static void intr_clear_all(nasid_t nasid)
+{
+ REMOTE_HUB_S(nasid, PI_INT_MASK0_A, 0);
+ REMOTE_HUB_S(nasid, PI_INT_MASK0_B, 0);
+ REMOTE_HUB_S(nasid, PI_INT_MASK1_A, 0);
+ REMOTE_HUB_S(nasid, PI_INT_MASK1_B, 0);
+ intr_clear_bits(nasid, REMOTE_HUB_ADDR(nasid, PI_INT_PEND0),
+ INT_PEND0_BASELVL);
+ intr_clear_bits(nasid, REMOTE_HUB_ADDR(nasid, PI_INT_PEND1),
+ INT_PEND1_BASELVL);
+}
+
+void __init prom_prepare_cpus(unsigned int max_cpus)
+{
+ cnodeid_t cnode;
+
+ for_each_online_node(cnode)
+ intr_clear_all(COMPACT_TO_NASID_NODEID(cnode));
+
+ replicate_kernel_text();
+
+ /*
+ * Assumption to be fixed: we're always booted on logical / physical
+ * processor 0. While we're always running on logical processor 0
+ * this still means this is physical processor zero; it might for
+ * example be disabled in the firwware.
+ */
+ alloc_cpupda(0, 0);
+}
+
+/*
+ * Launch a slave into smp_bootstrap(). It doesn't take an argument, and we
+ * set sp to the kernel stack of the newly created idle process, gp to the proc
+ * struct so that current_thread_info() will work.
+ */
+void __init prom_boot_secondary(int cpu, struct task_struct *idle)
+{
+ unsigned long gp = (unsigned long) idle->thread_info;
+ unsigned long sp = gp + THREAD_SIZE - 32;
+
+ LAUNCH_SLAVE(cputonasid(cpu),cputoslice(cpu),
+ (launch_proc_t)MAPPED_KERN_RW_TO_K0(smp_bootstrap),
+ 0, (void *) sp, (void *) gp);
+}
+
+void prom_init_secondary(void)
+{
+ per_cpu_init();
+ local_irq_enable();
+}
+
+void __init prom_cpus_done(void)
+{
+}
+
+void prom_smp_finish(void)
+{
+}
+
+void core_send_ipi(int destid, unsigned int action)
+{
+ int irq;
+
+ switch (action) {
+ case SMP_RESCHEDULE_YOURSELF:
+ irq = CPU_RESCHED_A_IRQ;
+ break;
+ case SMP_CALL_FUNCTION:
+ irq = CPU_CALL_A_IRQ;
+ break;
+ default:
+ panic("sendintr");
+ }
+
+ irq += cputoslice(destid);
+
+ /*
+ * Convert the compact hub number to the NASID to get the correct
+ * part of the address space. Then set the interrupt bit associated
+ * with the CPU we want to send the interrupt to.
+ */
+ REMOTE_HUB_SEND_INTR(COMPACT_TO_NASID_NODEID(cpu_to_node(destid)), irq);
+}
diff --git a/arch/mips/sgi-ip27/ip27-timer.c b/arch/mips/sgi-ip27/ip27-timer.c
new file mode 100644
index 0000000..8c1b96f
--- /dev/null
+++ b/arch/mips/sgi-ip27/ip27-timer.c
@@ -0,0 +1,243 @@
+/*
+ * Copytight (C) 1999, 2000, 05 Ralf Baechle (ralf@linux-mips.org)
+ * Copytight (C) 1999, 2000 Silicon Graphics, Inc.
+ */
+#include <linux/bcd.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/kernel_stat.h>
+#include <linux/param.h>
+#include <linux/time.h>
+#include <linux/timex.h>
+#include <linux/mm.h>
+
+#include <asm/time.h>
+#include <asm/pgtable.h>
+#include <asm/sgialib.h>
+#include <asm/sn/ioc3.h>
+#include <asm/m48t35.h>
+#include <asm/sn/klconfig.h>
+#include <asm/sn/arch.h>
+#include <asm/sn/addrs.h>
+#include <asm/sn/sn_private.h>
+#include <asm/sn/sn0/ip27.h>
+#include <asm/sn/sn0/hub.h>
+
+/*
+ * This is a hack; we really need to figure these values out dynamically
+ *
+ * Since 800 ns works very well with various HUB frequencies, such as
+ * 360, 380, 390 and 400 MHZ, we use 800 ns rtc cycle time.
+ *
+ * Ralf: which clock rate is used to feed the counter?
+ */
+#define NSEC_PER_CYCLE 800
+#define CYCLES_PER_SEC (NSEC_PER_SEC/NSEC_PER_CYCLE)
+#define CYCLES_PER_JIFFY (CYCLES_PER_SEC/HZ)
+
+#define TICK_SIZE (tick_nsec / 1000)
+
+static unsigned long ct_cur[NR_CPUS]; /* What counter should be at next timer irq */
+static long last_rtc_update; /* Last time the rtc clock got updated */
+
+extern volatile unsigned long wall_jiffies;
+
+#if 0
+static int set_rtc_mmss(unsigned long nowtime)
+{
+ int retval = 0;
+ int real_seconds, real_minutes, cmos_minutes;
+ struct m48t35_rtc *rtc;
+ nasid_t nid;
+
+ nid = get_nasid();
+ rtc = (struct m48t35_rtc *)(KL_CONFIG_CH_CONS_INFO(nid)->memory_base +
+ IOC3_BYTEBUS_DEV0);
+
+ rtc->control |= M48T35_RTC_READ;
+ cmos_minutes = BCD2BIN(rtc->min);
+ rtc->control &= ~M48T35_RTC_READ;
+
+ /*
+ * Since we're only adjusting minutes and seconds, don't interfere with
+ * hour overflow. This avoids messing with unknown time zones but
+ * requires your RTC not to be off by more than 15 minutes
+ */
+ real_seconds = nowtime % 60;
+ real_minutes = nowtime / 60;
+ if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1)
+ real_minutes += 30; /* correct for half hour time zone */
+ real_minutes %= 60;
+
+ if (abs(real_minutes - cmos_minutes) < 30) {
+ real_seconds = BIN2BCD(real_seconds);
+ real_minutes = BIN2BCD(real_minutes);
+ rtc->control |= M48T35_RTC_SET;
+ rtc->sec = real_seconds;
+ rtc->min = real_minutes;
+ rtc->control &= ~M48T35_RTC_SET;
+ } else {
+ printk(KERN_WARNING
+ "set_rtc_mmss: can't update from %d to %d\n",
+ cmos_minutes, real_minutes);
+ retval = -1;
+ }
+
+ return retval;
+}
+#endif
+
+void ip27_rt_timer_interrupt(struct pt_regs *regs)
+{
+ int cpu = smp_processor_id();
+ int cpuA = cputoslice(cpu) == 0;
+ int irq = 9; /* XXX Assign number */
+
+ irq_enter();
+ write_seqlock(&xtime_lock);
+
+again:
+ LOCAL_HUB_S(cpuA ? PI_RT_PEND_A : PI_RT_PEND_B, 0); /* Ack */
+ ct_cur[cpu] += CYCLES_PER_JIFFY;
+ LOCAL_HUB_S(cpuA ? PI_RT_COMPARE_A : PI_RT_COMPARE_B, ct_cur[cpu]);
+
+ if (LOCAL_HUB_L(PI_RT_COUNT) >= ct_cur[cpu])
+ goto again;
+
+ kstat_this_cpu.irqs[irq]++; /* kstat only for bootcpu? */
+
+ if (cpu == 0)
+ do_timer(regs);
+
+ update_process_times(user_mode(regs));
+
+ /*
+ * If we have an externally synchronized Linux clock, then update
+ * RTC clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
+ * called as close as possible to when a second starts.
+ */
+ if ((time_status & STA_UNSYNC) == 0 &&
+ xtime.tv_sec > last_rtc_update + 660 &&
+ (xtime.tv_nsec / 1000) >= 500000 - ((unsigned) TICK_SIZE) / 2 &&
+ (xtime.tv_nsec / 1000) <= 500000 + ((unsigned) TICK_SIZE) / 2) {
+ if (rtc_set_time(xtime.tv_sec) == 0) {
+ last_rtc_update = xtime.tv_sec;
+ } else {
+ last_rtc_update = xtime.tv_sec - 600;
+ /* do it again in 60 s */
+ }
+ }
+
+ write_sequnlock(&xtime_lock);
+ irq_exit();
+}
+
+unsigned long ip27_do_gettimeoffset(void)
+{
+ unsigned long ct_cur1;
+ ct_cur1 = REMOTE_HUB_L(cputonasid(0), PI_RT_COUNT) + CYCLES_PER_JIFFY;
+ return (ct_cur1 - ct_cur[0]) * NSEC_PER_CYCLE / 1000;
+}
+
+/* Includes for ioc3_init(). */
+#include <asm/sn/types.h>
+#include <asm/sn/sn0/addrs.h>
+#include <asm/sn/sn0/hubni.h>
+#include <asm/sn/sn0/hubio.h>
+#include <asm/pci/bridge.h>
+
+static __init unsigned long get_m48t35_time(void)
+{
+ unsigned int year, month, date, hour, min, sec;
+ struct m48t35_rtc *rtc;
+ nasid_t nid;
+
+ nid = get_nasid();
+ rtc = (struct m48t35_rtc *)(KL_CONFIG_CH_CONS_INFO(nid)->memory_base +
+ IOC3_BYTEBUS_DEV0);
+
+ rtc->control |= M48T35_RTC_READ;
+ sec = rtc->sec;
+ min = rtc->min;
+ hour = rtc->hour;
+ date = rtc->date;
+ month = rtc->month;
+ year = rtc->year;
+ rtc->control &= ~M48T35_RTC_READ;
+
+ sec = BCD2BIN(sec);
+ min = BCD2BIN(min);
+ hour = BCD2BIN(hour);
+ date = BCD2BIN(date);
+ month = BCD2BIN(month);
+ year = BCD2BIN(year);
+
+ year += 1970;
+
+ return mktime(year, month, date, hour, min, sec);
+}
+
+static void ip27_timer_setup(struct irqaction *irq)
+{
+ /* over-write the handler, we use our own way */
+ irq->handler = no_action;
+
+ /* setup irqaction */
+// setup_irq(IP27_TIMER_IRQ, irq); /* XXX Can't do this yet. */
+}
+
+void __init ip27_time_init(void)
+{
+ xtime.tv_sec = get_m48t35_time();
+ xtime.tv_nsec = 0;
+
+ do_gettimeoffset = ip27_do_gettimeoffset;
+
+ board_timer_setup = ip27_timer_setup;
+}
+
+void __init cpu_time_init(void)
+{
+ lboard_t *board;
+ klcpu_t *cpu;
+ int cpuid;
+
+ /* Don't use ARCS. ARCS is fragile. Klconfig is simple and sane. */
+ board = find_lboard(KL_CONFIG_INFO(get_nasid()), KLTYPE_IP27);
+ if (!board)
+ panic("Can't find board info for myself.");
+
+ cpuid = LOCAL_HUB_L(PI_CPU_NUM) ? IP27_CPU0_INDEX : IP27_CPU1_INDEX;
+ cpu = (klcpu_t *) KLCF_COMP(board, cpuid);
+ if (!cpu)
+ panic("No information about myself?");
+
+ printk("CPU %d clock is %dMHz.\n", smp_processor_id(), cpu->cpu_speed);
+
+ set_c0_status(SRB_TIMOCLK);
+}
+
+void __init hub_rtc_init(cnodeid_t cnode)
+{
+ /*
+ * We only need to initialize the current node.
+ * If this is not the current node then it is a cpuless
+ * node and timeouts will not happen there.
+ */
+ if (get_compact_nodeid() == cnode) {
+ int cpu = smp_processor_id();
+ LOCAL_HUB_S(PI_RT_EN_A, 1);
+ LOCAL_HUB_S(PI_RT_EN_B, 1);
+ LOCAL_HUB_S(PI_PROF_EN_A, 0);
+ LOCAL_HUB_S(PI_PROF_EN_B, 0);
+ ct_cur[cpu] = CYCLES_PER_JIFFY;
+ LOCAL_HUB_S(PI_RT_COMPARE_A, ct_cur[cpu]);
+ LOCAL_HUB_S(PI_RT_COUNT, 0);
+ LOCAL_HUB_S(PI_RT_PEND_A, 0);
+ LOCAL_HUB_S(PI_RT_COMPARE_B, ct_cur[cpu]);
+ LOCAL_HUB_S(PI_RT_COUNT, 0);
+ LOCAL_HUB_S(PI_RT_PEND_B, 0);
+ }
+}
diff --git a/arch/mips/sgi-ip27/ip27-xtalk.c b/arch/mips/sgi-ip27/ip27-xtalk.c
new file mode 100644
index 0000000..fc82f34
--- /dev/null
+++ b/arch/mips/sgi-ip27/ip27-xtalk.c
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 1999, 2000 Ralf Baechle (ralf@gnu.org)
+ * Copyright (C) 1999, 2000 Silcon Graphics, Inc.
+ * Copyright (C) 2004 Christoph Hellwig.
+ * Released under GPL v2.
+ *
+ * Generic XTALK initialization code
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <asm/sn/types.h>
+#include <asm/sn/klconfig.h>
+#include <asm/sn/hub.h>
+#include <asm/pci/bridge.h>
+#include <asm/xtalk/xtalk.h>
+
+
+#define XBOW_WIDGET_PART_NUM 0x0
+#define XXBOW_WIDGET_PART_NUM 0xd000 /* Xbow in Xbridge */
+#define BASE_XBOW_PORT 8 /* Lowest external port */
+
+extern int bridge_probe(nasid_t nasid, int widget, int masterwid);
+
+static int __init probe_one_port(nasid_t nasid, int widget, int masterwid)
+{
+ widgetreg_t widget_id;
+ xwidget_part_num_t partnum;
+
+ widget_id = *(volatile widgetreg_t *)
+ (RAW_NODE_SWIN_BASE(nasid, widget) + WIDGET_ID);
+ partnum = XWIDGET_PART_NUM(widget_id);
+
+ printk(KERN_INFO "Cpu %d, Nasid 0x%x, widget 0x%x (partnum 0x%x) is ",
+ smp_processor_id(), nasid, widget, partnum);
+
+ switch (partnum) {
+ case BRIDGE_WIDGET_PART_NUM:
+ case XBRIDGE_WIDGET_PART_NUM:
+ bridge_probe(nasid, widget, masterwid);
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int __init xbow_probe(nasid_t nasid)
+{
+ lboard_t *brd;
+ klxbow_t *xbow_p;
+ unsigned masterwid, i;
+
+ printk("is xbow\n");
+
+ /*
+ * found xbow, so may have multiple bridges
+ * need to probe xbow
+ */
+ brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_MIDPLANE8);
+ if (!brd)
+ return -ENODEV;
+
+ xbow_p = (klxbow_t *)find_component(brd, NULL, KLSTRUCT_XBOW);
+ if (!xbow_p)
+ return -ENODEV;
+
+ /*
+ * Okay, here's a xbow. Lets arbitrate and find
+ * out if we should initialize it. Set enabled
+ * hub connected at highest or lowest widget as
+ * master.
+ */
+#ifdef WIDGET_A
+ i = HUB_WIDGET_ID_MAX + 1;
+ do {
+ i--;
+ } while ((!XBOW_PORT_TYPE_HUB(xbow_p, i)) ||
+ (!XBOW_PORT_IS_ENABLED(xbow_p, i)));
+#else
+ i = HUB_WIDGET_ID_MIN - 1;
+ do {
+ i++;
+ } while ((!XBOW_PORT_TYPE_HUB(xbow_p, i)) ||
+ (!XBOW_PORT_IS_ENABLED(xbow_p, i)));
+#endif
+
+ masterwid = i;
+ if (nasid != XBOW_PORT_NASID(xbow_p, i))
+ return 1;
+
+ for (i = HUB_WIDGET_ID_MIN; i <= HUB_WIDGET_ID_MAX; i++) {
+ if (XBOW_PORT_IS_ENABLED(xbow_p, i) &&
+ XBOW_PORT_TYPE_IO(xbow_p, i))
+ probe_one_port(nasid, i, masterwid);
+ }
+
+ return 0;
+}
+
+void __init xtalk_probe_node(cnodeid_t nid)
+{
+ volatile u64 hubreg;
+ nasid_t nasid;
+ xwidget_part_num_t partnum;
+ widgetreg_t widget_id;
+
+ nasid = COMPACT_TO_NASID_NODEID(nid);
+ hubreg = REMOTE_HUB_L(nasid, IIO_LLP_CSR);
+
+ /* check whether the link is up */
+ if (!(hubreg & IIO_LLP_CSR_IS_UP))
+ return;
+
+ widget_id = *(volatile widgetreg_t *)
+ (RAW_NODE_SWIN_BASE(nasid, 0x0) + WIDGET_ID);
+ partnum = XWIDGET_PART_NUM(widget_id);
+
+ printk(KERN_INFO "Cpu %d, Nasid 0x%x: partnum 0x%x is ",
+ smp_processor_id(), nasid, partnum);
+
+ switch (partnum) {
+ case BRIDGE_WIDGET_PART_NUM:
+ bridge_probe(nasid, 0x8, 0xa);
+ break;
+ case XBOW_WIDGET_PART_NUM:
+ case XXBOW_WIDGET_PART_NUM:
+ xbow_probe(nasid);
+ break;
+ default:
+ printk(" unknown widget??\n");
+ break;
+ }
+}
diff --git a/arch/mips/sgi-ip32/Makefile b/arch/mips/sgi-ip32/Makefile
new file mode 100644
index 0000000..470898f
--- /dev/null
+++ b/arch/mips/sgi-ip32/Makefile
@@ -0,0 +1,9 @@
+#
+# Makefile for the SGI specific kernel interface routines
+# under Linux.
+#
+
+obj-y += ip32-berr.o ip32-irq.o ip32-irq-glue.o ip32-setup.o ip32-reset.o \
+ crime.o ip32-memory.o
+
+EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/sgi-ip32/crime.c b/arch/mips/sgi-ip32/crime.c
new file mode 100644
index 0000000..eb3a16a
--- /dev/null
+++ b/arch/mips/sgi-ip32/crime.c
@@ -0,0 +1,103 @@
+/*
+ * 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) 2001, 2003 Keith M Wesolowski
+ * Copyright (C) 2005 Ilya A. Volynets <ilya@total-knowledge.com>
+ */
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <asm/bootinfo.h>
+#include <asm/io.h>
+#include <asm/mipsregs.h>
+#include <asm/ptrace.h>
+#include <asm/page.h>
+#include <asm/ip32/crime.h>
+#include <asm/ip32/mace.h>
+
+struct sgi_crime *crime;
+struct sgi_mace *mace;
+
+void __init crime_init(void)
+{
+ unsigned int id, rev;
+ const int field = 2 * sizeof(unsigned long);
+
+ set_io_port_base((unsigned long) ioremap(MACEPCI_LOW_IO, 0x2000000));
+ crime = ioremap(CRIME_BASE, sizeof(struct sgi_crime));
+ mace = ioremap(MACE_BASE, sizeof(struct sgi_mace));
+
+ id = crime->id;
+ rev = id & CRIME_ID_REV;
+ id = (id & CRIME_ID_IDBITS) >> 4;
+ printk (KERN_INFO "CRIME id %1x rev %d at 0x%0*lx\n",
+ id, rev, field, (unsigned long) CRIME_BASE);
+}
+
+irqreturn_t
+crime_memerr_intr (unsigned int irq, void *dev_id, struct pt_regs *regs)
+{
+ unsigned long stat, addr;
+ int fatal = 0;
+
+ stat = crime->mem_error_stat & CRIME_MEM_ERROR_STAT_MASK;
+ addr = crime->mem_error_addr & CRIME_MEM_ERROR_ADDR_MASK;
+
+ printk("CRIME memory error at 0x%08lx ST 0x%08lx<", addr, stat);
+
+ if (stat & CRIME_MEM_ERROR_INV)
+ printk("INV,");
+ if (stat & CRIME_MEM_ERROR_ECC) {
+ unsigned long ecc_syn =
+ crime->mem_ecc_syn & CRIME_MEM_ERROR_ECC_SYN_MASK;
+ unsigned long ecc_gen =
+ crime->mem_ecc_chk & CRIME_MEM_ERROR_ECC_CHK_MASK;
+ printk("ECC,SYN=0x%08lx,GEN=0x%08lx,", ecc_syn, ecc_gen);
+ }
+ if (stat & CRIME_MEM_ERROR_MULTIPLE) {
+ fatal = 1;
+ printk("MULTIPLE,");
+ }
+ if (stat & CRIME_MEM_ERROR_HARD_ERR) {
+ fatal = 1;
+ printk("HARD,");
+ }
+ if (stat & CRIME_MEM_ERROR_SOFT_ERR)
+ printk("SOFT,");
+ if (stat & CRIME_MEM_ERROR_CPU_ACCESS)
+ printk("CPU,");
+ if (stat & CRIME_MEM_ERROR_VICE_ACCESS)
+ printk("VICE,");
+ if (stat & CRIME_MEM_ERROR_GBE_ACCESS)
+ printk("GBE,");
+ if (stat & CRIME_MEM_ERROR_RE_ACCESS)
+ printk("RE,REID=0x%02lx,", (stat & CRIME_MEM_ERROR_RE_ID)>>8);
+ if (stat & CRIME_MEM_ERROR_MACE_ACCESS)
+ printk("MACE,MACEID=0x%02lx,", stat & CRIME_MEM_ERROR_MACE_ID);
+
+ crime->mem_error_stat = 0;
+
+ if (fatal) {
+ printk("FATAL>\n");
+ panic("Fatal memory error.");
+ } else
+ printk("NONFATAL>\n");
+
+ return IRQ_HANDLED;
+}
+
+irqreturn_t
+crime_cpuerr_intr (unsigned int irq, void *dev_id, struct pt_regs *regs)
+{
+ unsigned long stat = crime->cpu_error_stat & CRIME_CPU_ERROR_MASK;
+ unsigned long addr = crime->cpu_error_addr & CRIME_CPU_ERROR_ADDR_MASK;
+
+ addr <<= 2;
+ printk ("CRIME CPU error at 0x%09lx status 0x%08lx\n", addr, stat);
+ crime->cpu_error_stat = 0;
+
+ return IRQ_HANDLED;
+}
diff --git a/arch/mips/sgi-ip32/ip32-berr.c b/arch/mips/sgi-ip32/ip32-berr.c
new file mode 100644
index 0000000..a278e91
--- /dev/null
+++ b/arch/mips/sgi-ip32/ip32-berr.c
@@ -0,0 +1,36 @@
+/*
+ * 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) 1994, 1995, 1996, 1999, 2000 by Ralf Baechle
+ * Copyright (C) 1999, 2000 by Silicon Graphics
+ * Copyright (C) 2002 Maciej W. Rozycki
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <asm/traps.h>
+#include <asm/uaccess.h>
+#include <asm/addrspace.h>
+#include <asm/ptrace.h>
+#include <asm/tlbdebug.h>
+
+int ip32_be_handler(struct pt_regs *regs, int is_fixup)
+{
+ int data = regs->cp0_cause & 4;
+
+ if (is_fixup)
+ return MIPS_BE_FIXUP;
+
+ printk("Got %cbe at 0x%lx\n", data ? 'd' : 'i', regs->cp0_epc);
+ show_regs(regs);
+ dump_tlb_all();
+ while(1);
+ force_sig(SIGBUS, current);
+}
+
+void __init ip32_be_init(void)
+{
+ board_be_handler = ip32_be_handler;
+}
diff --git a/arch/mips/sgi-ip32/ip32-irq-glue.S b/arch/mips/sgi-ip32/ip32-irq-glue.S
new file mode 100644
index 0000000..200924e
--- /dev/null
+++ b/arch/mips/sgi-ip32/ip32-irq-glue.S
@@ -0,0 +1,86 @@
+/*
+ * Low level interrupt handler for the SGI O2 aka IP32 aka Moosehead
+ *
+ * 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) 2000 Harald Koerfgen
+ * Copyright (C) 2001 Keith M Wesolowski
+ */
+#include <asm/asm.h>
+#include <asm/regdef.h>
+#include <asm/mipsregs.h>
+#include <asm/stackframe.h>
+#include <asm/addrspace.h>
+
+ .text
+ .set noreorder
+ .set noat
+ .align 5
+ NESTED(ip32_handle_int, PT_SIZE, ra)
+ .set noat
+ SAVE_ALL
+ CLI # TEST: interrupts should be off
+ .set at
+ .set noreorder
+
+ mfc0 s0,CP0_CAUSE
+
+ andi t1, s0, IE_IRQ0
+ bnez t1, handle_irq0
+ andi t1, s0, IE_IRQ1
+ bnez t1, handle_irq1
+ andi t1, s0, IE_IRQ2
+ bnez t1, handle_irq2
+ andi t1, s0, IE_IRQ3
+ bnez t1, handle_irq3
+ andi t1, s0, IE_IRQ4
+ bnez t1, handle_irq4
+ andi t1, s0, IE_IRQ5
+ bnez t1, handle_irq5
+ nop
+
+ /* Either someone has triggered the "software interrupts"
+ * or we lost an interrupt somehow. Ignore it.
+ */
+ j ret_from_irq
+ nop
+
+handle_irq0:
+ jal ip32_irq0
+ move a0, sp
+ j ret_from_irq
+ nop
+
+handle_irq1:
+ jal ip32_irq1
+ move a0, sp
+ j ret_from_irq
+ nop
+
+handle_irq2:
+ jal ip32_irq2
+ move a0, sp
+ j ret_from_irq
+ nop
+
+handle_irq3:
+ jal ip32_irq3
+ move a0, sp
+ j ret_from_irq
+ nop
+
+handle_irq4:
+ jal ip32_irq4
+ move a0, sp
+ j ret_from_irq
+ nop
+
+handle_irq5:
+ jal ip32_irq5
+ move a0, sp
+ j ret_from_irq
+ nop
+
+ END(ip32_handle_int)
diff --git a/arch/mips/sgi-ip32/ip32-irq.c b/arch/mips/sgi-ip32/ip32-irq.c
new file mode 100644
index 0000000..fc3a8e9
--- /dev/null
+++ b/arch/mips/sgi-ip32/ip32-irq.c
@@ -0,0 +1,590 @@
+/*
+ * Code to handle IP32 IRQs
+ *
+ * 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) 2000 Harald Koerfgen
+ * Copyright (C) 2001 Keith M Wesolowski
+ */
+#include <linux/init.h>
+#include <linux/kernel_stat.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/bitops.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/random.h>
+#include <linux/sched.h>
+
+#include <asm/mipsregs.h>
+#include <asm/signal.h>
+#include <asm/system.h>
+#include <asm/time.h>
+#include <asm/ip32/crime.h>
+#include <asm/ip32/mace.h>
+#include <asm/ip32/ip32_ints.h>
+
+/* issue a PIO read to make sure no PIO writes are pending */
+static void inline flush_crime_bus(void)
+{
+ volatile unsigned long junk = crime->control;
+}
+
+static void inline flush_mace_bus(void)
+{
+ volatile unsigned long junk = mace->perif.ctrl.misc;
+}
+
+#undef DEBUG_IRQ
+#ifdef DEBUG_IRQ
+#define DBG(x...) printk(x)
+#else
+#define DBG(x...)
+#endif
+
+/* O2 irq map
+ *
+ * IP0 -> software (ignored)
+ * IP1 -> software (ignored)
+ * IP2 -> (irq0) C crime 1.1 all interrupts; crime 1.5 ???
+ * IP3 -> (irq1) X unknown
+ * IP4 -> (irq2) X unknown
+ * IP5 -> (irq3) X unknown
+ * IP6 -> (irq4) X unknown
+ * IP7 -> (irq5) 0 CPU count/compare timer (system timer)
+ *
+ * crime: (C)
+ *
+ * CRIME_INT_STAT 31:0:
+ *
+ * 0 -> 1 Video in 1
+ * 1 -> 2 Video in 2
+ * 2 -> 3 Video out
+ * 3 -> 4 Mace ethernet
+ * 4 -> S SuperIO sub-interrupt
+ * 5 -> M Miscellaneous sub-interrupt
+ * 6 -> A Audio sub-interrupt
+ * 7 -> 8 PCI bridge errors
+ * 8 -> 9 PCI SCSI aic7xxx 0
+ * 9 -> 10 PCI SCSI aic7xxx 1
+ * 10 -> 11 PCI slot 0
+ * 11 -> 12 unused (PCI slot 1)
+ * 12 -> 13 unused (PCI slot 2)
+ * 13 -> 14 unused (PCI shared 0)
+ * 14 -> 15 unused (PCI shared 1)
+ * 15 -> 16 unused (PCI shared 2)
+ * 16 -> 17 GBE0 (E)
+ * 17 -> 18 GBE1 (E)
+ * 18 -> 19 GBE2 (E)
+ * 19 -> 20 GBE3 (E)
+ * 20 -> 21 CPU errors
+ * 21 -> 22 Memory errors
+ * 22 -> 23 RE empty edge (E)
+ * 23 -> 24 RE full edge (E)
+ * 24 -> 25 RE idle edge (E)
+ * 25 -> 26 RE empty level
+ * 26 -> 27 RE full level
+ * 27 -> 28 RE idle level
+ * 28 -> 29 unused (software 0) (E)
+ * 29 -> 30 unused (software 1) (E)
+ * 30 -> 31 unused (software 2) - crime 1.5 CPU SysCorError (E)
+ * 31 -> 32 VICE
+ *
+ * S, M, A: Use the MACE ISA interrupt register
+ * MACE_ISA_INT_STAT 31:0
+ *
+ * 0-7 -> 33-40 Audio
+ * 8 -> 41 RTC
+ * 9 -> 42 Keyboard
+ * 10 -> X Keyboard polled
+ * 11 -> 44 Mouse
+ * 12 -> X Mouse polled
+ * 13-15 -> 46-48 Count/compare timers
+ * 16-19 -> 49-52 Parallel (16 E)
+ * 20-25 -> 53-58 Serial 1 (22 E)
+ * 26-31 -> 59-64 Serial 2 (28 E)
+ *
+ * Note that this means IRQs 5-7, 43, and 45 do not exist. This is a
+ * different IRQ map than IRIX uses, but that's OK as Linux irq handling
+ * is quite different anyway.
+ */
+
+/*
+ * IRQ spinlock - Ralf says not to disable CPU interrupts,
+ * and I think he knows better.
+ */
+static DEFINE_SPINLOCK(ip32_irq_lock);
+
+/* Some initial interrupts to set up */
+extern irqreturn_t crime_memerr_intr (int irq, void *dev_id,
+ struct pt_regs *regs);
+extern irqreturn_t crime_cpuerr_intr (int irq, void *dev_id,
+ struct pt_regs *regs);
+
+struct irqaction memerr_irq = { crime_memerr_intr, SA_INTERRUPT,
+ CPU_MASK_NONE, "CRIME memory error", NULL, NULL };
+struct irqaction cpuerr_irq = { crime_cpuerr_intr, SA_INTERRUPT,
+ CPU_MASK_NONE, "CRIME CPU error", NULL, NULL };
+
+extern void ip32_handle_int(void);
+
+/*
+ * For interrupts wired from a single device to the CPU. Only the clock
+ * uses this it seems, which is IRQ 0 and IP7.
+ */
+
+static void enable_cpu_irq(unsigned int irq)
+{
+ set_c0_status(STATUSF_IP7);
+}
+
+static unsigned int startup_cpu_irq(unsigned int irq)
+{
+ enable_cpu_irq(irq);
+ return 0;
+}
+
+static void disable_cpu_irq(unsigned int irq)
+{
+ clear_c0_status(STATUSF_IP7);
+}
+
+static void end_cpu_irq(unsigned int irq)
+{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
+ enable_cpu_irq (irq);
+}
+
+#define shutdown_cpu_irq disable_cpu_irq
+#define mask_and_ack_cpu_irq disable_cpu_irq
+
+static struct hw_interrupt_type ip32_cpu_interrupt = {
+ "IP32 CPU",
+ startup_cpu_irq,
+ shutdown_cpu_irq,
+ enable_cpu_irq,
+ disable_cpu_irq,
+ mask_and_ack_cpu_irq,
+ end_cpu_irq,
+ NULL
+};
+
+/*
+ * This is for pure CRIME interrupts - ie not MACE. The advantage?
+ * We get to split the register in half and do faster lookups.
+ */
+
+static uint64_t crime_mask;
+
+static void enable_crime_irq(unsigned int irq)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&ip32_irq_lock, flags);
+ crime_mask |= 1 << (irq - 1);
+ crime->imask = crime_mask;
+ spin_unlock_irqrestore(&ip32_irq_lock, flags);
+}
+
+static unsigned int startup_crime_irq(unsigned int irq)
+{
+ enable_crime_irq(irq);
+ return 0; /* This is probably not right; we could have pending irqs */
+}
+
+static void disable_crime_irq(unsigned int irq)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&ip32_irq_lock, flags);
+ crime_mask &= ~(1 << (irq - 1));
+ crime->imask = crime_mask;
+ flush_crime_bus();
+ spin_unlock_irqrestore(&ip32_irq_lock, flags);
+}
+
+static void mask_and_ack_crime_irq(unsigned int irq)
+{
+ unsigned long flags;
+
+ /* Edge triggered interrupts must be cleared. */
+ if ((irq >= CRIME_GBE0_IRQ && irq <= CRIME_GBE3_IRQ)
+ || (irq >= CRIME_RE_EMPTY_E_IRQ && irq <= CRIME_RE_IDLE_E_IRQ)
+ || (irq >= CRIME_SOFT0_IRQ && irq <= CRIME_SOFT2_IRQ)) {
+ uint64_t crime_int;
+ spin_lock_irqsave(&ip32_irq_lock, flags);
+ crime_int = crime->hard_int;
+ crime_int &= ~(1 << (irq - 1));
+ crime->hard_int = crime_int;
+ spin_unlock_irqrestore(&ip32_irq_lock, flags);
+ }
+ disable_crime_irq(irq);
+}
+
+static void end_crime_irq(unsigned int irq)
+{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
+ enable_crime_irq(irq);
+}
+
+#define shutdown_crime_irq disable_crime_irq
+
+static struct hw_interrupt_type ip32_crime_interrupt = {
+ "IP32 CRIME",
+ startup_crime_irq,
+ shutdown_crime_irq,
+ enable_crime_irq,
+ disable_crime_irq,
+ mask_and_ack_crime_irq,
+ end_crime_irq,
+ NULL
+};
+
+/*
+ * This is for MACE PCI interrupts. We can decrease bus traffic by masking
+ * as close to the source as possible. This also means we can take the
+ * next chunk of the CRIME register in one piece.
+ */
+
+static unsigned long macepci_mask;
+
+static void enable_macepci_irq(unsigned int irq)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&ip32_irq_lock, flags);
+ macepci_mask |= MACEPCI_CONTROL_INT(irq - 9);
+ mace->pci.control = macepci_mask;
+ crime_mask |= 1 << (irq - 1);
+ crime->imask = crime_mask;
+ spin_unlock_irqrestore(&ip32_irq_lock, flags);
+}
+
+static unsigned int startup_macepci_irq(unsigned int irq)
+{
+ enable_macepci_irq (irq);
+ return 0;
+}
+
+static void disable_macepci_irq(unsigned int irq)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&ip32_irq_lock, flags);
+ crime_mask &= ~(1 << (irq - 1));
+ crime->imask = crime_mask;
+ flush_crime_bus();
+ macepci_mask &= ~MACEPCI_CONTROL_INT(irq - 9);
+ mace->pci.control = macepci_mask;
+ flush_mace_bus();
+ spin_unlock_irqrestore(&ip32_irq_lock, flags);
+}
+
+static void end_macepci_irq(unsigned int irq)
+{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+ enable_macepci_irq(irq);
+}
+
+#define shutdown_macepci_irq disable_macepci_irq
+#define mask_and_ack_macepci_irq disable_macepci_irq
+
+static struct hw_interrupt_type ip32_macepci_interrupt = {
+ "IP32 MACE PCI",
+ startup_macepci_irq,
+ shutdown_macepci_irq,
+ enable_macepci_irq,
+ disable_macepci_irq,
+ mask_and_ack_macepci_irq,
+ end_macepci_irq,
+ NULL
+};
+
+/* This is used for MACE ISA interrupts. That means bits 4-6 in the
+ * CRIME register.
+ */
+
+#define MACEISA_AUDIO_INT (MACEISA_AUDIO_SW_INT | \
+ MACEISA_AUDIO_SC_INT | \
+ MACEISA_AUDIO1_DMAT_INT | \
+ MACEISA_AUDIO1_OF_INT | \
+ MACEISA_AUDIO2_DMAT_INT | \
+ MACEISA_AUDIO2_MERR_INT | \
+ MACEISA_AUDIO3_DMAT_INT | \
+ MACEISA_AUDIO3_MERR_INT)
+#define MACEISA_MISC_INT (MACEISA_RTC_INT | \
+ MACEISA_KEYB_INT | \
+ MACEISA_KEYB_POLL_INT | \
+ MACEISA_MOUSE_INT | \
+ MACEISA_MOUSE_POLL_INT | \
+ MACEISA_TIMER0_INT | \
+ MACEISA_TIMER1_INT | \
+ MACEISA_TIMER2_INT)
+#define MACEISA_SUPERIO_INT (MACEISA_PARALLEL_INT | \
+ MACEISA_PAR_CTXA_INT | \
+ MACEISA_PAR_CTXB_INT | \
+ MACEISA_PAR_MERR_INT | \
+ MACEISA_SERIAL1_INT | \
+ MACEISA_SERIAL1_TDMAT_INT | \
+ MACEISA_SERIAL1_TDMAPR_INT | \
+ MACEISA_SERIAL1_TDMAME_INT | \
+ MACEISA_SERIAL1_RDMAT_INT | \
+ MACEISA_SERIAL1_RDMAOR_INT | \
+ MACEISA_SERIAL2_INT | \
+ MACEISA_SERIAL2_TDMAT_INT | \
+ MACEISA_SERIAL2_TDMAPR_INT | \
+ MACEISA_SERIAL2_TDMAME_INT | \
+ MACEISA_SERIAL2_RDMAT_INT | \
+ MACEISA_SERIAL2_RDMAOR_INT)
+
+static unsigned long maceisa_mask;
+
+static void enable_maceisa_irq (unsigned int irq)
+{
+ unsigned int crime_int = 0;
+ unsigned long flags;
+
+ DBG ("maceisa enable: %u\n", irq);
+
+ switch (irq) {
+ case MACEISA_AUDIO_SW_IRQ ... MACEISA_AUDIO3_MERR_IRQ:
+ crime_int = MACE_AUDIO_INT;
+ break;
+ case MACEISA_RTC_IRQ ... MACEISA_TIMER2_IRQ:
+ crime_int = MACE_MISC_INT;
+ break;
+ case MACEISA_PARALLEL_IRQ ... MACEISA_SERIAL2_RDMAOR_IRQ:
+ crime_int = MACE_SUPERIO_INT;
+ break;
+ }
+ DBG ("crime_int %08x enabled\n", crime_int);
+ spin_lock_irqsave(&ip32_irq_lock, flags);
+ crime_mask |= crime_int;
+ crime->imask = crime_mask;
+ maceisa_mask |= 1 << (irq - 33);
+ mace->perif.ctrl.imask = maceisa_mask;
+ spin_unlock_irqrestore(&ip32_irq_lock, flags);
+}
+
+static unsigned int startup_maceisa_irq(unsigned int irq)
+{
+ enable_maceisa_irq(irq);
+ return 0;
+}
+
+static void disable_maceisa_irq(unsigned int irq)
+{
+ unsigned int crime_int = 0;
+ unsigned long flags;
+
+ spin_lock_irqsave(&ip32_irq_lock, flags);
+ maceisa_mask &= ~(1 << (irq - 33));
+ if(!(maceisa_mask & MACEISA_AUDIO_INT))
+ crime_int |= MACE_AUDIO_INT;
+ if(!(maceisa_mask & MACEISA_MISC_INT))
+ crime_int |= MACE_MISC_INT;
+ if(!(maceisa_mask & MACEISA_SUPERIO_INT))
+ crime_int |= MACE_SUPERIO_INT;
+ crime_mask &= ~crime_int;
+ crime->imask = crime_mask;
+ flush_crime_bus();
+ mace->perif.ctrl.imask = maceisa_mask;
+ flush_mace_bus();
+ spin_unlock_irqrestore(&ip32_irq_lock, flags);
+}
+
+static void mask_and_ack_maceisa_irq(unsigned int irq)
+{
+ unsigned long mace_int, flags;
+
+ switch (irq) {
+ case MACEISA_PARALLEL_IRQ:
+ case MACEISA_SERIAL1_TDMAPR_IRQ:
+ case MACEISA_SERIAL2_TDMAPR_IRQ:
+ /* edge triggered */
+ spin_lock_irqsave(&ip32_irq_lock, flags);
+ mace_int = mace->perif.ctrl.istat;
+ mace_int &= ~(1 << (irq - 33));
+ mace->perif.ctrl.istat = mace_int;
+ spin_unlock_irqrestore(&ip32_irq_lock, flags);
+ break;
+ }
+ disable_maceisa_irq(irq);
+}
+
+static void end_maceisa_irq(unsigned irq)
+{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
+ enable_maceisa_irq(irq);
+}
+
+#define shutdown_maceisa_irq disable_maceisa_irq
+
+static struct hw_interrupt_type ip32_maceisa_interrupt = {
+ "IP32 MACE ISA",
+ startup_maceisa_irq,
+ shutdown_maceisa_irq,
+ enable_maceisa_irq,
+ disable_maceisa_irq,
+ mask_and_ack_maceisa_irq,
+ end_maceisa_irq,
+ NULL
+};
+
+/* This is used for regular non-ISA, non-PCI MACE interrupts. That means
+ * bits 0-3 and 7 in the CRIME register.
+ */
+
+static void enable_mace_irq(unsigned int irq)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&ip32_irq_lock, flags);
+ crime_mask |= 1 << (irq - 1);
+ crime->imask = crime_mask;
+ spin_unlock_irqrestore(&ip32_irq_lock, flags);
+}
+
+static unsigned int startup_mace_irq(unsigned int irq)
+{
+ enable_mace_irq(irq);
+ return 0;
+}
+
+static void disable_mace_irq(unsigned int irq)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&ip32_irq_lock, flags);
+ crime_mask &= ~(1 << (irq - 1));
+ crime->imask = crime_mask;
+ flush_crime_bus();
+ spin_unlock_irqrestore(&ip32_irq_lock, flags);
+}
+
+static void end_mace_irq(unsigned int irq)
+{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+ enable_mace_irq(irq);
+}
+
+#define shutdown_mace_irq disable_mace_irq
+#define mask_and_ack_mace_irq disable_mace_irq
+
+static struct hw_interrupt_type ip32_mace_interrupt = {
+ "IP32 MACE",
+ startup_mace_irq,
+ shutdown_mace_irq,
+ enable_mace_irq,
+ disable_mace_irq,
+ mask_and_ack_mace_irq,
+ end_mace_irq,
+ NULL
+};
+
+static void ip32_unknown_interrupt(struct pt_regs *regs)
+{
+ printk ("Unknown interrupt occurred!\n");
+ printk ("cp0_status: %08x\n", read_c0_status());
+ printk ("cp0_cause: %08x\n", read_c0_cause());
+ printk ("CRIME intr mask: %016lx\n", crime->imask);
+ printk ("CRIME intr status: %016lx\n", crime->istat);
+ printk ("CRIME hardware intr register: %016lx\n", crime->hard_int);
+ printk ("MACE ISA intr mask: %08lx\n", mace->perif.ctrl.imask);
+ printk ("MACE ISA intr status: %08lx\n", mace->perif.ctrl.istat);
+ printk ("MACE PCI control register: %08x\n", mace->pci.control);
+
+ printk("Register dump:\n");
+ show_regs(regs);
+
+ printk("Please mail this report to linux-mips@linux-mips.org\n");
+ printk("Spinning...");
+ while(1) ;
+}
+
+/* CRIME 1.1 appears to deliver all interrupts to this one pin. */
+/* change this to loop over all edge-triggered irqs, exception masked out ones */
+void ip32_irq0(struct pt_regs *regs)
+{
+ uint64_t crime_int;
+ int irq = 0;
+
+ crime_int = crime->istat & crime_mask;
+ irq = ffs(crime_int);
+ crime_int = 1 << (irq - 1);
+
+ if (crime_int & CRIME_MACEISA_INT_MASK) {
+ unsigned long mace_int = mace->perif.ctrl.istat;
+ irq = ffs(mace_int & maceisa_mask) + 32;
+ }
+ DBG("*irq %u*\n", irq);
+ do_IRQ(irq, regs);
+}
+
+void ip32_irq1(struct pt_regs *regs)
+{
+ ip32_unknown_interrupt(regs);
+}
+
+void ip32_irq2(struct pt_regs *regs)
+{
+ ip32_unknown_interrupt(regs);
+}
+
+void ip32_irq3(struct pt_regs *regs)
+{
+ ip32_unknown_interrupt(regs);
+}
+
+void ip32_irq4(struct pt_regs *regs)
+{
+ ip32_unknown_interrupt(regs);
+}
+
+void ip32_irq5(struct pt_regs *regs)
+{
+ ll_timer_interrupt(IP32_R4K_TIMER_IRQ, regs);
+}
+
+void __init arch_init_irq(void)
+{
+ unsigned int irq;
+
+ /* Install our interrupt handler, then clear and disable all
+ * CRIME and MACE interrupts. */
+ crime->imask = 0;
+ crime->hard_int = 0;
+ crime->soft_int = 0;
+ mace->perif.ctrl.istat = 0;
+ mace->perif.ctrl.imask = 0;
+ set_except_vector(0, ip32_handle_int);
+
+ for (irq = 0; irq <= IP32_IRQ_MAX; irq++) {
+ hw_irq_controller *controller;
+
+ if (irq == IP32_R4K_TIMER_IRQ)
+ controller = &ip32_cpu_interrupt;
+ else if (irq <= MACE_PCI_BRIDGE_IRQ && irq >= MACE_VID_IN1_IRQ)
+ controller = &ip32_mace_interrupt;
+ else if (irq <= MACEPCI_SHARED2_IRQ && irq >= MACEPCI_SCSI0_IRQ)
+ controller = &ip32_macepci_interrupt;
+ else if (irq <= CRIME_VICE_IRQ && irq >= CRIME_GBE0_IRQ)
+ controller = &ip32_crime_interrupt;
+ else
+ controller = &ip32_maceisa_interrupt;
+
+ irq_desc[irq].status = IRQ_DISABLED;
+ irq_desc[irq].action = 0;
+ irq_desc[irq].depth = 0;
+ irq_desc[irq].handler = controller;
+ }
+ setup_irq(CRIME_MEMERR_IRQ, &memerr_irq);
+ setup_irq(CRIME_CPUERR_IRQ, &cpuerr_irq);
+
+#define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5)
+ change_c0_status(ST0_IM, ALLINTS);
+}
diff --git a/arch/mips/sgi-ip32/ip32-memory.c b/arch/mips/sgi-ip32/ip32-memory.c
new file mode 100644
index 0000000..fc76ca9
--- /dev/null
+++ b/arch/mips/sgi-ip32/ip32-memory.c
@@ -0,0 +1,49 @@
+/*
+ * 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) 2003 Keith M Wesolowski
+ * Copyright (C) 2005 Ilya A. Volynets (Total Knowledge)
+ */
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+
+#include <asm/ip32/crime.h>
+#include <asm/bootinfo.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/pgalloc.h>
+
+extern void crime_init(void);
+
+void __init prom_meminit (void)
+{
+ u64 base, size;
+ int bank;
+
+ crime_init();
+
+ for (bank=0; bank < CRIME_MAXBANKS; bank++) {
+ u64 bankctl = crime->bank_ctrl[bank];
+ base = (bankctl & CRIME_MEM_BANK_CONTROL_ADDR) << 25;
+ if (bank != 0 && base == 0)
+ continue;
+ size = (bankctl & CRIME_MEM_BANK_CONTROL_SDRAM_SIZE) ? 128 : 32;
+ size <<= 20;
+ if (base + size > (256 << 20))
+ base += CRIME_HI_MEM_BASE;
+
+ printk("CRIME MC: bank %u base 0x%016lx size %luMB\n",
+ bank, base, size);
+ add_memory_region (base, size, BOOT_MEM_RAM);
+ }
+}
+
+
+unsigned long __init prom_free_prom_memory (void)
+{
+ return 0;
+}
diff --git a/arch/mips/sgi-ip32/ip32-reset.c b/arch/mips/sgi-ip32/ip32-reset.c
new file mode 100644
index 0000000..281f090
--- /dev/null
+++ b/arch/mips/sgi-ip32/ip32-reset.c
@@ -0,0 +1,202 @@
+/*
+ * 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) 2001 Keith M Wesolowski
+ * Copyright (C) 2001 Paul Mundt
+ * Copyright (C) 2003 Guido Guenther <agx@sigxcpu.org>
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/notifier.h>
+#include <linux/delay.h>
+#include <linux/ds17287rtc.h>
+#include <linux/interrupt.h>
+
+#include <asm/addrspace.h>
+#include <asm/irq.h>
+#include <asm/reboot.h>
+#include <asm/system.h>
+#include <asm/wbflush.h>
+#include <asm/ip32/mace.h>
+#include <asm/ip32/crime.h>
+#include <asm/ip32/ip32_ints.h>
+
+#define POWERDOWN_TIMEOUT 120
+/*
+ * Blink frequency during reboot grace period and when paniced.
+ */
+#define POWERDOWN_FREQ (HZ / 4)
+#define PANIC_FREQ (HZ / 8)
+
+static struct timer_list power_timer, blink_timer, debounce_timer;
+static int has_paniced, shuting_down;
+
+static void ip32_machine_restart(char *command) __attribute__((noreturn));
+static void ip32_machine_halt(void) __attribute__((noreturn));
+static void ip32_machine_power_off(void) __attribute__((noreturn));
+
+static void ip32_machine_restart(char *cmd)
+{
+ crime->control = CRIME_CONTROL_HARD_RESET;
+ while (1);
+}
+
+static inline void ip32_machine_halt(void)
+{
+ ip32_machine_power_off();
+}
+
+static void ip32_machine_power_off(void)
+{
+ volatile unsigned char reg_a, xctrl_a, xctrl_b;
+
+ disable_irq(MACEISA_RTC_IRQ);
+ reg_a = CMOS_READ(RTC_REG_A);
+
+ /* setup for kickstart & wake-up (DS12287 Ref. Man. p. 19) */
+ reg_a &= ~DS_REGA_DV2;
+ reg_a |= DS_REGA_DV1;
+
+ CMOS_WRITE(reg_a | DS_REGA_DV0, RTC_REG_A);
+ wbflush();
+ xctrl_b = CMOS_READ(DS_B1_XCTRL4B)
+ | DS_XCTRL4B_ABE | DS_XCTRL4B_KFE;
+ CMOS_WRITE(xctrl_b, DS_B1_XCTRL4B);
+ xctrl_a = CMOS_READ(DS_B1_XCTRL4A) & ~DS_XCTRL4A_IFS;
+ CMOS_WRITE(xctrl_a, DS_B1_XCTRL4A);
+ wbflush();
+ /* adios amigos... */
+ CMOS_WRITE(xctrl_a | DS_XCTRL4A_PAB, DS_B1_XCTRL4A);
+ CMOS_WRITE(reg_a, RTC_REG_A);
+ wbflush();
+ while (1);
+}
+
+static void power_timeout(unsigned long data)
+{
+ ip32_machine_power_off();
+}
+
+static void blink_timeout(unsigned long data)
+{
+ unsigned long led = mace->perif.ctrl.misc ^ MACEISA_LED_RED;
+ mace->perif.ctrl.misc = led;
+ mod_timer(&blink_timer, jiffies + data);
+}
+
+static void debounce(unsigned long data)
+{
+ volatile unsigned char reg_a, reg_c, xctrl_a;
+
+ reg_c = CMOS_READ(RTC_INTR_FLAGS);
+ CMOS_WRITE(reg_a | DS_REGA_DV0, RTC_REG_A);
+ wbflush();
+ xctrl_a = CMOS_READ(DS_B1_XCTRL4A);
+ if ((xctrl_a & DS_XCTRL4A_IFS) || (reg_c & RTC_IRQF )) {
+ /* Interrupt still being sent. */
+ debounce_timer.expires = jiffies + 50;
+ add_timer(&debounce_timer);
+
+ /* clear interrupt source */
+ CMOS_WRITE(xctrl_a & ~DS_XCTRL4A_IFS, DS_B1_XCTRL4A);
+ CMOS_WRITE(reg_a & ~DS_REGA_DV0, RTC_REG_A);
+ return;
+ }
+ CMOS_WRITE(reg_a & ~DS_REGA_DV0, RTC_REG_A);
+
+ if (has_paniced)
+ ip32_machine_restart(NULL);
+
+ enable_irq(MACEISA_RTC_IRQ);
+}
+
+static inline void ip32_power_button(void)
+{
+ if (has_paniced)
+ return;
+
+ if (shuting_down || kill_proc(1, SIGINT, 1)) {
+ /* No init process or button pressed twice. */
+ ip32_machine_power_off();
+ }
+
+ shuting_down = 1;
+ blink_timer.data = POWERDOWN_FREQ;
+ blink_timeout(POWERDOWN_FREQ);
+
+ init_timer(&power_timer);
+ power_timer.function = power_timeout;
+ power_timer.expires = jiffies + POWERDOWN_TIMEOUT * HZ;
+ add_timer(&power_timer);
+}
+
+static irqreturn_t ip32_rtc_int(int irq, void *dev_id, struct pt_regs *regs)
+{
+ volatile unsigned char reg_c;
+
+ reg_c = CMOS_READ(RTC_INTR_FLAGS);
+ if (!(reg_c & RTC_IRQF)) {
+ printk(KERN_WARNING
+ "%s: RTC IRQ without RTC_IRQF\n", __FUNCTION__);
+ }
+ /* Wait until interrupt goes away */
+ disable_irq(MACEISA_RTC_IRQ);
+ init_timer(&debounce_timer);
+ debounce_timer.function = debounce;
+ debounce_timer.expires = jiffies + 50;
+ add_timer(&debounce_timer);
+
+ printk(KERN_DEBUG "Power button pressed\n");
+ ip32_power_button();
+ return IRQ_HANDLED;
+}
+
+static int panic_event(struct notifier_block *this, unsigned long event,
+ void *ptr)
+{
+ unsigned long led;
+
+ if (has_paniced)
+ return NOTIFY_DONE;
+ has_paniced = 1;
+
+ /* turn off the green LED */
+ led = mace->perif.ctrl.misc | MACEISA_LED_GREEN;
+ mace->perif.ctrl.misc = led;
+
+ blink_timer.data = PANIC_FREQ;
+ blink_timeout(PANIC_FREQ);
+
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block panic_block = {
+ .notifier_call = panic_event,
+};
+
+static __init int ip32_reboot_setup(void)
+{
+ /* turn on the green led only */
+ unsigned long led = mace->perif.ctrl.misc;
+ led |= MACEISA_LED_RED;
+ led &= ~MACEISA_LED_GREEN;
+ mace->perif.ctrl.misc = led;
+
+ _machine_restart = ip32_machine_restart;
+ _machine_halt = ip32_machine_halt;
+ _machine_power_off = ip32_machine_power_off;
+
+ init_timer(&blink_timer);
+ blink_timer.function = blink_timeout;
+ notifier_chain_register(&panic_notifier_list, &panic_block);
+
+ request_irq(MACEISA_RTC_IRQ, ip32_rtc_int, 0, "rtc", NULL);
+
+ return 0;
+}
+
+subsys_initcall(ip32_reboot_setup);
diff --git a/arch/mips/sgi-ip32/ip32-setup.c b/arch/mips/sgi-ip32/ip32-setup.c
new file mode 100644
index 0000000..8d270be
--- /dev/null
+++ b/arch/mips/sgi-ip32/ip32-setup.c
@@ -0,0 +1,159 @@
+/*
+ * IP32 basic setup
+ *
+ * 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) 2000 Harald Koerfgen
+ * Copyright (C) 2002, 2003, 2005 Ilya A. Volynets
+ */
+#include <linux/config.h>
+#include <linux/console.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/mc146818rtc.h>
+#include <linux/param.h>
+#include <linux/sched.h>
+
+#include <asm/bootinfo.h>
+#include <asm/mc146818-time.h>
+#include <asm/mipsregs.h>
+#include <asm/mmu_context.h>
+#include <asm/sgialib.h>
+#include <asm/time.h>
+#include <asm/traps.h>
+#include <asm/io.h>
+#include <asm/ip32/crime.h>
+#include <asm/ip32/mace.h>
+#include <asm/ip32/ip32_ints.h>
+
+extern void ip32_be_init(void);
+extern void crime_init(void);
+
+#ifdef CONFIG_SGI_O2MACE_ETH
+/*
+ * This is taken care of in here 'cause they say using Arc later on is
+ * problematic
+ */
+extern char o2meth_eaddr[8];
+static inline unsigned char str2hexnum(unsigned char c)
+{
+ if (c >= '0' && c <= '9')
+ return c - '0';
+ if (c >= 'a' && c <= 'f')
+ return c - 'a' + 10;
+ return 0; /* foo */
+}
+
+static inline void str2eaddr(unsigned char *ea, unsigned char *str)
+{
+ int i;
+
+ for (i = 0; i < 6; i++) {
+ unsigned char num;
+
+ if(*str == ':')
+ str++;
+ num = str2hexnum(*str++) << 4;
+ num |= (str2hexnum(*str++));
+ ea[i] = num;
+ }
+}
+#endif
+
+#ifdef CONFIG_SERIAL_8250
+#include <linux/tty.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+extern int early_serial_setup(struct uart_port *port);
+
+#define STD_COM_FLAGS (ASYNC_SKIP_TEST)
+#define BASE_BAUD (1843200 / 16)
+
+#endif /* CONFIG_SERIAL_8250 */
+
+/* An arbitrary time; this can be decreased if reliability looks good */
+#define WAIT_MS 10
+
+void __init ip32_time_init(void)
+{
+ printk(KERN_INFO "Calibrating system timer... ");
+ write_c0_count(0);
+ crime->timer = 0;
+ while (crime->timer < CRIME_MASTER_FREQ * WAIT_MS / 1000) ;
+ mips_hpt_frequency = read_c0_count() * 1000 / WAIT_MS;
+ printk("%d MHz CPU detected\n", mips_hpt_frequency * 2 / 1000000);
+}
+
+void __init ip32_timer_setup(struct irqaction *irq)
+{
+ irq->handler = no_action;
+ setup_irq(IP32_R4K_TIMER_IRQ, irq);
+}
+
+static int __init ip32_setup(void)
+{
+ board_be_init = ip32_be_init;
+
+ rtc_get_time = mc146818_get_cmos_time;
+ rtc_set_mmss = mc146818_set_rtc_mmss;
+
+ board_time_init = ip32_time_init;
+ board_timer_setup = ip32_timer_setup;
+
+#ifdef CONFIG_SERIAL_8250
+ {
+ static struct uart_port o2_serial[2];
+
+ memset(o2_serial, 0, sizeof(o2_serial));
+ o2_serial[0].type = PORT_16550A;
+ o2_serial[0].line = 0;
+ o2_serial[0].irq = MACEISA_SERIAL1_IRQ;
+ o2_serial[0].flags = STD_COM_FLAGS;
+ o2_serial[0].uartclk = BASE_BAUD * 16;
+ o2_serial[0].iotype = UPIO_MEM;
+ o2_serial[0].membase = (char *)&mace->isa.serial1;
+ o2_serial[0].fifosize = 14;
+ /* How much to shift register offset by. Each UART register
+ * is replicated over 256 byte space */
+ o2_serial[0].regshift = 8;
+ o2_serial[1].type = PORT_16550A;
+ o2_serial[1].line = 1;
+ o2_serial[1].irq = MACEISA_SERIAL2_IRQ;
+ o2_serial[1].flags = STD_COM_FLAGS;
+ o2_serial[1].uartclk = BASE_BAUD * 16;
+ o2_serial[1].iotype = UPIO_MEM;
+ o2_serial[1].membase = (char *)&mace->isa.serial2;
+ o2_serial[1].fifosize = 14;
+ o2_serial[1].regshift = 8;
+
+ early_serial_setup(&o2_serial[0]);
+ early_serial_setup(&o2_serial[1]);
+ }
+#endif
+#ifdef CONFIG_SGI_O2MACE_ETH
+ {
+ char *mac = ArcGetEnvironmentVariable("eaddr");
+ str2eaddr(o2meth_eaddr, mac);
+ }
+#endif
+
+#if defined(CONFIG_SERIAL_CORE_CONSOLE)
+ {
+ char* con = ArcGetEnvironmentVariable("console");
+ if (con && *con == 'd') {
+ static char options[8];
+ char *baud = ArcGetEnvironmentVariable("dbaud");
+ if (baud)
+ strcpy(options, baud);
+ add_preferred_console("ttyS", *(con + 1) == '2' ? 1 : 0,
+ baud ? options : NULL);
+ }
+ }
+#endif
+
+ return 0;
+}
+
+early_initcall(ip32_setup);
diff --git a/arch/mips/sibyte/cfe/Makefile b/arch/mips/sibyte/cfe/Makefile
new file mode 100644
index 0000000..059d84a
--- /dev/null
+++ b/arch/mips/sibyte/cfe/Makefile
@@ -0,0 +1,3 @@
+lib-y = cfe_api.o setup.o
+lib-$(CONFIG_SMP) += smp.o
+lib-$(CONFIG_SIBYTE_CFE_CONSOLE) += console.o
diff --git a/arch/mips/sibyte/cfe/cfe_api.c b/arch/mips/sibyte/cfe/cfe_api.c
new file mode 100644
index 0000000..c021360
--- /dev/null
+++ b/arch/mips/sibyte/cfe/cfe_api.c
@@ -0,0 +1,502 @@
+/*
+ * Copyright (C) 2000, 2001, 2002 Broadcom Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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 Common Firmware Environment (CFE)
+ *
+ * Device Function stubs File: cfe_api.c
+ *
+ * This module contains device function stubs (small routines to
+ * call the standard "iocb" interface entry point to CFE).
+ * There should be one routine here per iocb function call.
+ *
+ * Authors: Mitch Lichtenberg, Chris Demetriou
+ *
+ ********************************************************************* */
+
+#include "cfe_api.h"
+#include "cfe_api_int.h"
+
+/* Cast from a native pointer to a cfe_xptr_t and back. */
+#define XPTR_FROM_NATIVE(n) ((cfe_xptr_t) (intptr_t) (n))
+#define NATIVE_FROM_XPTR(x) ((void *) (intptr_t) (x))
+
+#ifdef CFE_API_IMPL_NAMESPACE
+#define cfe_iocb_dispatch(a) __cfe_iocb_dispatch(a)
+#endif
+int cfe_iocb_dispatch(cfe_xiocb_t * xiocb);
+
+#if defined(CFE_API_common) || defined(CFE_API_ALL)
+/*
+ * Declare the dispatch function with args of "intptr_t".
+ * This makes sure whatever model we're compiling in
+ * puts the pointers in a single register. For example,
+ * combining -mlong64 and -mips1 or -mips2 would lead to
+ * trouble, since the handle and IOCB pointer will be
+ * passed in two registers each, and CFE expects one.
+ */
+
+static int (*cfe_dispfunc) (intptr_t handle, intptr_t xiocb) = 0;
+static cfe_xuint_t cfe_handle = 0;
+
+int cfe_init(cfe_xuint_t handle, cfe_xuint_t ept)
+{
+ cfe_dispfunc = NATIVE_FROM_XPTR(ept);
+ cfe_handle = handle;
+ return 0;
+}
+
+int cfe_iocb_dispatch(cfe_xiocb_t * xiocb)
+{
+ if (!cfe_dispfunc)
+ return -1;
+ return (*cfe_dispfunc) ((intptr_t) cfe_handle, (intptr_t) xiocb);
+}
+#endif /* CFE_API_common || CFE_API_ALL */
+
+#if defined(CFE_API_close) || defined(CFE_API_ALL)
+int cfe_close(int handle)
+{
+ cfe_xiocb_t xiocb;
+
+ xiocb.xiocb_fcode = CFE_CMD_DEV_CLOSE;
+ xiocb.xiocb_status = 0;
+ xiocb.xiocb_handle = handle;
+ xiocb.xiocb_flags = 0;
+ xiocb.xiocb_psize = 0;
+
+ cfe_iocb_dispatch(&xiocb);
+
+ return xiocb.xiocb_status;
+
+}
+#endif /* CFE_API_close || CFE_API_ALL */
+
+#if defined(CFE_API_cpu_start) || defined(CFE_API_ALL)
+int cfe_cpu_start(int cpu, void (*fn) (void), long sp, long gp, long a1)
+{
+ cfe_xiocb_t xiocb;
+
+ xiocb.xiocb_fcode = CFE_CMD_FW_CPUCTL;
+ xiocb.xiocb_status = 0;
+ xiocb.xiocb_handle = 0;
+ xiocb.xiocb_flags = 0;
+ xiocb.xiocb_psize = sizeof(xiocb_cpuctl_t);
+ xiocb.plist.xiocb_cpuctl.cpu_number = cpu;
+ xiocb.plist.xiocb_cpuctl.cpu_command = CFE_CPU_CMD_START;
+ xiocb.plist.xiocb_cpuctl.gp_val = gp;
+ xiocb.plist.xiocb_cpuctl.sp_val = sp;
+ xiocb.plist.xiocb_cpuctl.a1_val = a1;
+ xiocb.plist.xiocb_cpuctl.start_addr = (long) fn;
+
+ cfe_iocb_dispatch(&xiocb);
+
+ return xiocb.xiocb_status;
+}
+#endif /* CFE_API_cpu_start || CFE_API_ALL */
+
+#if defined(CFE_API_cpu_stop) || defined(CFE_API_ALL)
+int cfe_cpu_stop(int cpu)
+{
+ cfe_xiocb_t xiocb;
+
+ xiocb.xiocb_fcode = CFE_CMD_FW_CPUCTL;
+ xiocb.xiocb_status = 0;
+ xiocb.xiocb_handle = 0;
+ xiocb.xiocb_flags = 0;
+ xiocb.xiocb_psize = sizeof(xiocb_cpuctl_t);
+ xiocb.plist.xiocb_cpuctl.cpu_number = cpu;
+ xiocb.plist.xiocb_cpuctl.cpu_command = CFE_CPU_CMD_STOP;
+
+ cfe_iocb_dispatch(&xiocb);
+
+ return xiocb.xiocb_status;
+}
+#endif /* CFE_API_cpu_stop || CFE_API_ALL */
+
+#if defined(CFE_API_enumenv) || defined(CFE_API_ALL)
+int cfe_enumenv(int idx, char *name, int namelen, char *val, int vallen)
+{
+ cfe_xiocb_t xiocb;
+
+ xiocb.xiocb_fcode = CFE_CMD_ENV_SET;
+ xiocb.xiocb_status = 0;
+ xiocb.xiocb_handle = 0;
+ xiocb.xiocb_flags = 0;
+ xiocb.xiocb_psize = sizeof(xiocb_envbuf_t);
+ xiocb.plist.xiocb_envbuf.enum_idx = idx;
+ xiocb.plist.xiocb_envbuf.name_ptr = XPTR_FROM_NATIVE(name);
+ xiocb.plist.xiocb_envbuf.name_length = namelen;
+ xiocb.plist.xiocb_envbuf.val_ptr = XPTR_FROM_NATIVE(val);
+ xiocb.plist.xiocb_envbuf.val_length = vallen;
+
+ cfe_iocb_dispatch(&xiocb);
+
+ return xiocb.xiocb_status;
+}
+#endif /* CFE_API_enumenv || CFE_API_ALL */
+
+#if defined(CFE_API_enummem) || defined(CFE_API_ALL)
+int
+cfe_enummem(int idx, int flags, cfe_xuint_t * start, cfe_xuint_t * length,
+ cfe_xuint_t * type)
+{
+ cfe_xiocb_t xiocb;
+
+ xiocb.xiocb_fcode = CFE_CMD_FW_MEMENUM;
+ xiocb.xiocb_status = 0;
+ xiocb.xiocb_handle = 0;
+ xiocb.xiocb_flags = flags;
+ xiocb.xiocb_psize = sizeof(xiocb_meminfo_t);
+ xiocb.plist.xiocb_meminfo.mi_idx = idx;
+
+ cfe_iocb_dispatch(&xiocb);
+
+ if (xiocb.xiocb_status < 0)
+ return xiocb.xiocb_status;
+
+ *start = xiocb.plist.xiocb_meminfo.mi_addr;
+ *length = xiocb.plist.xiocb_meminfo.mi_size;
+ *type = xiocb.plist.xiocb_meminfo.mi_type;
+
+ return 0;
+}
+#endif /* CFE_API_enummem || CFE_API_ALL */
+
+#if defined(CFE_API_exit) || defined(CFE_API_ALL)
+int cfe_exit(int warm, int status)
+{
+ cfe_xiocb_t xiocb;
+
+ xiocb.xiocb_fcode = CFE_CMD_FW_RESTART;
+ xiocb.xiocb_status = 0;
+ xiocb.xiocb_handle = 0;
+ xiocb.xiocb_flags = warm ? CFE_FLG_WARMSTART : 0;
+ xiocb.xiocb_psize = sizeof(xiocb_exitstat_t);
+ xiocb.plist.xiocb_exitstat.status = status;
+
+ cfe_iocb_dispatch(&xiocb);
+
+ return xiocb.xiocb_status;
+}
+#endif /* CFE_API_exit || CFE_API_ALL */
+
+#if defined(CFE_API_flushcache) || defined(CFE_API_ALL)
+int cfe_flushcache(int flg)
+{
+ cfe_xiocb_t xiocb;
+
+ xiocb.xiocb_fcode = CFE_CMD_FW_FLUSHCACHE;
+ xiocb.xiocb_status = 0;
+ xiocb.xiocb_handle = 0;
+ xiocb.xiocb_flags = flg;
+ xiocb.xiocb_psize = 0;
+
+ cfe_iocb_dispatch(&xiocb);
+
+ return xiocb.xiocb_status;
+}
+#endif /* CFE_API_flushcache || CFE_API_ALL */
+
+#if defined(CFE_API_getdevinfo) || defined(CFE_API_ALL)
+int cfe_getdevinfo(char *name)
+{
+ cfe_xiocb_t xiocb;
+
+ xiocb.xiocb_fcode = CFE_CMD_DEV_GETINFO;
+ xiocb.xiocb_status = 0;
+ xiocb.xiocb_handle = 0;
+ xiocb.xiocb_flags = 0;
+ xiocb.xiocb_psize = sizeof(xiocb_buffer_t);
+ xiocb.plist.xiocb_buffer.buf_offset = 0;
+ xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(name);
+ xiocb.plist.xiocb_buffer.buf_length = cfe_strlen(name);
+
+ cfe_iocb_dispatch(&xiocb);
+
+ if (xiocb.xiocb_status < 0)
+ return xiocb.xiocb_status;
+ return xiocb.plist.xiocb_buffer.buf_devflags;
+}
+#endif /* CFE_API_getdevinfo || CFE_API_ALL */
+
+#if defined(CFE_API_getenv) || defined(CFE_API_ALL)
+int cfe_getenv(char *name, char *dest, int destlen)
+{
+ cfe_xiocb_t xiocb;
+
+ *dest = 0;
+
+ xiocb.xiocb_fcode = CFE_CMD_ENV_GET;
+ xiocb.xiocb_status = 0;
+ xiocb.xiocb_handle = 0;
+ xiocb.xiocb_flags = 0;
+ xiocb.xiocb_psize = sizeof(xiocb_envbuf_t);
+ xiocb.plist.xiocb_envbuf.enum_idx = 0;
+ xiocb.plist.xiocb_envbuf.name_ptr = XPTR_FROM_NATIVE(name);
+ xiocb.plist.xiocb_envbuf.name_length = cfe_strlen(name);
+ xiocb.plist.xiocb_envbuf.val_ptr = XPTR_FROM_NATIVE(dest);
+ xiocb.plist.xiocb_envbuf.val_length = destlen;
+
+ cfe_iocb_dispatch(&xiocb);
+
+ return xiocb.xiocb_status;
+}
+#endif /* CFE_API_getenv || CFE_API_ALL */
+
+#if defined(CFE_API_getfwinfo) || defined(CFE_API_ALL)
+int cfe_getfwinfo(cfe_fwinfo_t * info)
+{
+ cfe_xiocb_t xiocb;
+
+ xiocb.xiocb_fcode = CFE_CMD_FW_GETINFO;
+ xiocb.xiocb_status = 0;
+ xiocb.xiocb_handle = 0;
+ xiocb.xiocb_flags = 0;
+ xiocb.xiocb_psize = sizeof(xiocb_fwinfo_t);
+
+ cfe_iocb_dispatch(&xiocb);
+
+ if (xiocb.xiocb_status < 0)
+ return xiocb.xiocb_status;
+
+ info->fwi_version = xiocb.plist.xiocb_fwinfo.fwi_version;
+ info->fwi_totalmem = xiocb.plist.xiocb_fwinfo.fwi_totalmem;
+ info->fwi_flags = xiocb.plist.xiocb_fwinfo.fwi_flags;
+ info->fwi_boardid = xiocb.plist.xiocb_fwinfo.fwi_boardid;
+ info->fwi_bootarea_va = xiocb.plist.xiocb_fwinfo.fwi_bootarea_va;
+ info->fwi_bootarea_pa = xiocb.plist.xiocb_fwinfo.fwi_bootarea_pa;
+ info->fwi_bootarea_size =
+ xiocb.plist.xiocb_fwinfo.fwi_bootarea_size;
+#if 0
+ info->fwi_reserved1 = xiocb.plist.xiocb_fwinfo.fwi_reserved1;
+ info->fwi_reserved2 = xiocb.plist.xiocb_fwinfo.fwi_reserved2;
+ info->fwi_reserved3 = xiocb.plist.xiocb_fwinfo.fwi_reserved3;
+#endif
+
+ return 0;
+}
+#endif /* CFE_API_getfwinfo || CFE_API_ALL */
+
+#if defined(CFE_API_getstdhandle) || defined(CFE_API_ALL)
+int cfe_getstdhandle(int flg)
+{
+ cfe_xiocb_t xiocb;
+
+ xiocb.xiocb_fcode = CFE_CMD_DEV_GETHANDLE;
+ xiocb.xiocb_status = 0;
+ xiocb.xiocb_handle = 0;
+ xiocb.xiocb_flags = flg;
+ xiocb.xiocb_psize = 0;
+
+ cfe_iocb_dispatch(&xiocb);
+
+ if (xiocb.xiocb_status < 0)
+ return xiocb.xiocb_status;
+ return xiocb.xiocb_handle;
+}
+#endif /* CFE_API_getstdhandle || CFE_API_ALL */
+
+#if defined(CFE_API_getticks) || defined(CFE_API_ALL)
+int64_t
+#ifdef CFE_API_IMPL_NAMESPACE
+__cfe_getticks(void)
+#else
+cfe_getticks(void)
+#endif
+{
+ cfe_xiocb_t xiocb;
+
+ xiocb.xiocb_fcode = CFE_CMD_FW_GETTIME;
+ xiocb.xiocb_status = 0;
+ xiocb.xiocb_handle = 0;
+ xiocb.xiocb_flags = 0;
+ xiocb.xiocb_psize = sizeof(xiocb_time_t);
+ xiocb.plist.xiocb_time.ticks = 0;
+
+ cfe_iocb_dispatch(&xiocb);
+
+ return xiocb.plist.xiocb_time.ticks;
+
+}
+#endif /* CFE_API_getticks || CFE_API_ALL */
+
+#if defined(CFE_API_inpstat) || defined(CFE_API_ALL)
+int cfe_inpstat(int handle)
+{
+ cfe_xiocb_t xiocb;
+
+ xiocb.xiocb_fcode = CFE_CMD_DEV_INPSTAT;
+ xiocb.xiocb_status = 0;
+ xiocb.xiocb_handle = handle;
+ xiocb.xiocb_flags = 0;
+ xiocb.xiocb_psize = sizeof(xiocb_inpstat_t);
+ xiocb.plist.xiocb_inpstat.inp_status = 0;
+
+ cfe_iocb_dispatch(&xiocb);
+
+ if (xiocb.xiocb_status < 0)
+ return xiocb.xiocb_status;
+ return xiocb.plist.xiocb_inpstat.inp_status;
+}
+#endif /* CFE_API_inpstat || CFE_API_ALL */
+
+#if defined(CFE_API_ioctl) || defined(CFE_API_ALL)
+int
+cfe_ioctl(int handle, unsigned int ioctlnum, unsigned char *buffer,
+ int length, int *retlen, cfe_xuint_t offset)
+{
+ cfe_xiocb_t xiocb;
+
+ xiocb.xiocb_fcode = CFE_CMD_DEV_IOCTL;
+ xiocb.xiocb_status = 0;
+ xiocb.xiocb_handle = handle;
+ xiocb.xiocb_flags = 0;
+ xiocb.xiocb_psize = sizeof(xiocb_buffer_t);
+ xiocb.plist.xiocb_buffer.buf_offset = offset;
+ xiocb.plist.xiocb_buffer.buf_ioctlcmd = ioctlnum;
+ xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(buffer);
+ xiocb.plist.xiocb_buffer.buf_length = length;
+
+ cfe_iocb_dispatch(&xiocb);
+
+ if (retlen)
+ *retlen = xiocb.plist.xiocb_buffer.buf_retlen;
+ return xiocb.xiocb_status;
+}
+#endif /* CFE_API_ioctl || CFE_API_ALL */
+
+#if defined(CFE_API_open) || defined(CFE_API_ALL)
+int cfe_open(char *name)
+{
+ cfe_xiocb_t xiocb;
+
+ xiocb.xiocb_fcode = CFE_CMD_DEV_OPEN;
+ xiocb.xiocb_status = 0;
+ xiocb.xiocb_handle = 0;
+ xiocb.xiocb_flags = 0;
+ xiocb.xiocb_psize = sizeof(xiocb_buffer_t);
+ xiocb.plist.xiocb_buffer.buf_offset = 0;
+ xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(name);
+ xiocb.plist.xiocb_buffer.buf_length = cfe_strlen(name);
+
+ cfe_iocb_dispatch(&xiocb);
+
+ if (xiocb.xiocb_status < 0)
+ return xiocb.xiocb_status;
+ return xiocb.xiocb_handle;
+}
+#endif /* CFE_API_open || CFE_API_ALL */
+
+#if defined(CFE_API_read) || defined(CFE_API_ALL)
+int cfe_read(int handle, unsigned char *buffer, int length)
+{
+ return cfe_readblk(handle, 0, buffer, length);
+}
+#endif /* CFE_API_read || CFE_API_ALL */
+
+#if defined(CFE_API_readblk) || defined(CFE_API_ALL)
+int
+cfe_readblk(int handle, cfe_xint_t offset, unsigned char *buffer,
+ int length)
+{
+ cfe_xiocb_t xiocb;
+
+ xiocb.xiocb_fcode = CFE_CMD_DEV_READ;
+ xiocb.xiocb_status = 0;
+ xiocb.xiocb_handle = handle;
+ xiocb.xiocb_flags = 0;
+ xiocb.xiocb_psize = sizeof(xiocb_buffer_t);
+ xiocb.plist.xiocb_buffer.buf_offset = offset;
+ xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(buffer);
+ xiocb.plist.xiocb_buffer.buf_length = length;
+
+ cfe_iocb_dispatch(&xiocb);
+
+ if (xiocb.xiocb_status < 0)
+ return xiocb.xiocb_status;
+ return xiocb.plist.xiocb_buffer.buf_retlen;
+}
+#endif /* CFE_API_readblk || CFE_API_ALL */
+
+#if defined(CFE_API_setenv) || defined(CFE_API_ALL)
+int cfe_setenv(char *name, char *val)
+{
+ cfe_xiocb_t xiocb;
+
+ xiocb.xiocb_fcode = CFE_CMD_ENV_SET;
+ xiocb.xiocb_status = 0;
+ xiocb.xiocb_handle = 0;
+ xiocb.xiocb_flags = 0;
+ xiocb.xiocb_psize = sizeof(xiocb_envbuf_t);
+ xiocb.plist.xiocb_envbuf.enum_idx = 0;
+ xiocb.plist.xiocb_envbuf.name_ptr = XPTR_FROM_NATIVE(name);
+ xiocb.plist.xiocb_envbuf.name_length = cfe_strlen(name);
+ xiocb.plist.xiocb_envbuf.val_ptr = XPTR_FROM_NATIVE(val);
+ xiocb.plist.xiocb_envbuf.val_length = cfe_strlen(val);
+
+ cfe_iocb_dispatch(&xiocb);
+
+ return xiocb.xiocb_status;
+}
+#endif /* CFE_API_setenv || CFE_API_ALL */
+
+#if (defined(CFE_API_strlen) || defined(CFE_API_ALL)) \
+ && !defined(CFE_API_STRLEN_CUSTOM)
+int cfe_strlen(char *name)
+{
+ int count = 0;
+
+ while (*name++)
+ count++;
+
+ return count;
+}
+#endif /* CFE_API_strlen || CFE_API_ALL */
+
+#if defined(CFE_API_write) || defined(CFE_API_ALL)
+int cfe_write(int handle, unsigned char *buffer, int length)
+{
+ return cfe_writeblk(handle, 0, buffer, length);
+}
+#endif /* CFE_API_write || CFE_API_ALL */
+
+#if defined(CFE_API_writeblk) || defined(CFE_API_ALL)
+int
+cfe_writeblk(int handle, cfe_xint_t offset, unsigned char *buffer,
+ int length)
+{
+ cfe_xiocb_t xiocb;
+
+ xiocb.xiocb_fcode = CFE_CMD_DEV_WRITE;
+ xiocb.xiocb_status = 0;
+ xiocb.xiocb_handle = handle;
+ xiocb.xiocb_flags = 0;
+ xiocb.xiocb_psize = sizeof(xiocb_buffer_t);
+ xiocb.plist.xiocb_buffer.buf_offset = offset;
+ xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(buffer);
+ xiocb.plist.xiocb_buffer.buf_length = length;
+
+ cfe_iocb_dispatch(&xiocb);
+
+ if (xiocb.xiocb_status < 0)
+ return xiocb.xiocb_status;
+ return xiocb.plist.xiocb_buffer.buf_retlen;
+}
+#endif /* CFE_API_writeblk || CFE_API_ALL */
diff --git a/arch/mips/sibyte/cfe/cfe_api.h b/arch/mips/sibyte/cfe/cfe_api.h
new file mode 100644
index 0000000..d8230cc
--- /dev/null
+++ b/arch/mips/sibyte/cfe/cfe_api.h
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2000, 2001, 2002 Broadcom Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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 Common Firmware Environment (CFE)
+ *
+ * Device function prototypes File: cfe_api.h
+ *
+ * This file contains declarations for doing callbacks to
+ * cfe from an application. It should be the only header
+ * needed by the application to use this library
+ *
+ * Authors: Mitch Lichtenberg, Chris Demetriou
+ *
+ ********************************************************************* */
+
+#ifndef CFE_API_H
+#define CFE_API_H
+
+/*
+ * Apply customizations here for different OSes. These need to:
+ * * typedef uint64_t, int64_t, intptr_t, uintptr_t.
+ * * define cfe_strlen() if use of an existing function is desired.
+ * * define CFE_API_IMPL_NAMESPACE if API functions are to use
+ * names in the implementation namespace.
+ * Also, optionally, if the build environment does not do so automatically,
+ * CFE_API_* can be defined here as desired.
+ */
+/* Begin customization. */
+#include <linux/types.h>
+#include <linux/string.h>
+
+typedef long intptr_t;
+
+#define cfe_strlen strlen
+
+#define CFE_API_ALL
+#define CFE_API_STRLEN_CUSTOM
+/* End customization. */
+
+
+/* *********************************************************************
+ * Constants
+ ********************************************************************* */
+
+/* Seal indicating CFE's presence, passed to user program. */
+#define CFE_EPTSEAL 0x43464531
+
+#define CFE_MI_RESERVED 0 /* memory is reserved, do not use */
+#define CFE_MI_AVAILABLE 1 /* memory is available */
+
+#define CFE_FLG_WARMSTART 0x00000001
+#define CFE_FLG_FULL_ARENA 0x00000001
+#define CFE_FLG_ENV_PERMANENT 0x00000001
+
+#define CFE_CPU_CMD_START 1
+#define CFE_CPU_CMD_STOP 0
+
+#define CFE_STDHANDLE_CONSOLE 0
+
+#define CFE_DEV_NETWORK 1
+#define CFE_DEV_DISK 2
+#define CFE_DEV_FLASH 3
+#define CFE_DEV_SERIAL 4
+#define CFE_DEV_CPU 5
+#define CFE_DEV_NVRAM 6
+#define CFE_DEV_CLOCK 7
+#define CFE_DEV_OTHER 8
+#define CFE_DEV_MASK 0x0F
+
+#define CFE_CACHE_FLUSH_D 1
+#define CFE_CACHE_INVAL_I 2
+#define CFE_CACHE_INVAL_D 4
+#define CFE_CACHE_INVAL_L2 8
+
+#define CFE_FWI_64BIT 0x00000001
+#define CFE_FWI_32BIT 0x00000002
+#define CFE_FWI_RELOC 0x00000004
+#define CFE_FWI_UNCACHED 0x00000008
+#define CFE_FWI_MULTICPU 0x00000010
+#define CFE_FWI_FUNCSIM 0x00000020
+#define CFE_FWI_RTLSIM 0x00000040
+
+typedef struct {
+ int64_t fwi_version; /* major, minor, eco version */
+ int64_t fwi_totalmem; /* total installed mem */
+ int64_t fwi_flags; /* various flags */
+ int64_t fwi_boardid; /* board ID */
+ int64_t fwi_bootarea_va; /* VA of boot area */
+ int64_t fwi_bootarea_pa; /* PA of boot area */
+ int64_t fwi_bootarea_size; /* size of boot area */
+} cfe_fwinfo_t;
+
+
+/*
+ * cfe_strlen is handled specially: If already defined, it has been
+ * overridden in this environment with a standard strlen-like function.
+ */
+#ifdef cfe_strlen
+# define CFE_API_STRLEN_CUSTOM
+#else
+# ifdef CFE_API_IMPL_NAMESPACE
+# define cfe_strlen(a) __cfe_strlen(a)
+# endif
+int cfe_strlen(char *name);
+#endif
+
+/*
+ * Defines and prototypes for functions which take no arguments.
+ */
+#ifdef CFE_API_IMPL_NAMESPACE
+int64_t __cfe_getticks(void);
+#define cfe_getticks() __cfe_getticks()
+#else
+int64_t cfe_getticks(void);
+#endif
+
+/*
+ * Defines and prototypes for the rest of the functions.
+ */
+#ifdef CFE_API_IMPL_NAMESPACE
+#define cfe_close(a) __cfe_close(a)
+#define cfe_cpu_start(a,b,c,d,e) __cfe_cpu_start(a,b,c,d,e)
+#define cfe_cpu_stop(a) __cfe_cpu_stop(a)
+#define cfe_enumenv(a,b,d,e,f) __cfe_enumenv(a,b,d,e,f)
+#define cfe_enummem(a,b,c,d,e) __cfe_enummem(a,b,c,d,e)
+#define cfe_exit(a,b) __cfe_exit(a,b)
+#define cfe_flushcache(a) __cfe_cacheflush(a)
+#define cfe_getdevinfo(a) __cfe_getdevinfo(a)
+#define cfe_getenv(a,b,c) __cfe_getenv(a,b,c)
+#define cfe_getfwinfo(a) __cfe_getfwinfo(a)
+#define cfe_getstdhandle(a) __cfe_getstdhandle(a)
+#define cfe_init(a,b) __cfe_init(a,b)
+#define cfe_inpstat(a) __cfe_inpstat(a)
+#define cfe_ioctl(a,b,c,d,e,f) __cfe_ioctl(a,b,c,d,e,f)
+#define cfe_open(a) __cfe_open(a)
+#define cfe_read(a,b,c) __cfe_read(a,b,c)
+#define cfe_readblk(a,b,c,d) __cfe_readblk(a,b,c,d)
+#define cfe_setenv(a,b) __cfe_setenv(a,b)
+#define cfe_write(a,b,c) __cfe_write(a,b,c)
+#define cfe_writeblk(a,b,c,d) __cfe_writeblk(a,b,c,d)
+#endif /* CFE_API_IMPL_NAMESPACE */
+
+int cfe_close(int handle);
+int cfe_cpu_start(int cpu, void (*fn) (void), long sp, long gp, long a1);
+int cfe_cpu_stop(int cpu);
+int cfe_enumenv(int idx, char *name, int namelen, char *val, int vallen);
+int cfe_enummem(int idx, int flags, uint64_t * start, uint64_t * length,
+ uint64_t * type);
+int cfe_exit(int warm, int status);
+int cfe_flushcache(int flg);
+int cfe_getdevinfo(char *name);
+int cfe_getenv(char *name, char *dest, int destlen);
+int cfe_getfwinfo(cfe_fwinfo_t * info);
+int cfe_getstdhandle(int flg);
+int cfe_init(uint64_t handle, uint64_t ept);
+int cfe_inpstat(int handle);
+int cfe_ioctl(int handle, unsigned int ioctlnum, unsigned char *buffer,
+ int length, int *retlen, uint64_t offset);
+int cfe_open(char *name);
+int cfe_read(int handle, unsigned char *buffer, int length);
+int cfe_readblk(int handle, int64_t offset, unsigned char *buffer,
+ int length);
+int cfe_setenv(char *name, char *val);
+int cfe_write(int handle, unsigned char *buffer, int length);
+int cfe_writeblk(int handle, int64_t offset, unsigned char *buffer,
+ int length);
+
+#endif /* CFE_API_H */
diff --git a/arch/mips/sibyte/cfe/cfe_api_int.h b/arch/mips/sibyte/cfe/cfe_api_int.h
new file mode 100644
index 0000000..f7e5a64
--- /dev/null
+++ b/arch/mips/sibyte/cfe/cfe_api_int.h
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2000, 2001, 2002 Broadcom Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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 Common Firmware Environment (CFE)
+ *
+ * Device function prototypes File: cfe_api_int.h
+ *
+ * This header defines all internal types and macros for the
+ * library. This is stuff that's not exported to an app
+ * using the library.
+ *
+ * Authors: Mitch Lichtenberg, Chris Demetriou
+ *
+ ********************************************************************* */
+
+#ifndef CFE_API_INT_H
+#define CFE_API_INT_H
+
+/* *********************************************************************
+ * Constants
+ ********************************************************************* */
+
+#define CFE_CMD_FW_GETINFO 0
+#define CFE_CMD_FW_RESTART 1
+#define CFE_CMD_FW_BOOT 2
+#define CFE_CMD_FW_CPUCTL 3
+#define CFE_CMD_FW_GETTIME 4
+#define CFE_CMD_FW_MEMENUM 5
+#define CFE_CMD_FW_FLUSHCACHE 6
+
+#define CFE_CMD_DEV_GETHANDLE 9
+#define CFE_CMD_DEV_ENUM 10
+#define CFE_CMD_DEV_OPEN 11
+#define CFE_CMD_DEV_INPSTAT 12
+#define CFE_CMD_DEV_READ 13
+#define CFE_CMD_DEV_WRITE 14
+#define CFE_CMD_DEV_IOCTL 15
+#define CFE_CMD_DEV_CLOSE 16
+#define CFE_CMD_DEV_GETINFO 17
+
+#define CFE_CMD_ENV_ENUM 20
+#define CFE_CMD_ENV_GET 22
+#define CFE_CMD_ENV_SET 23
+#define CFE_CMD_ENV_DEL 24
+
+#define CFE_CMD_MAX 32
+
+#define CFE_CMD_VENDOR_USE 0x8000 /* codes above this are for customer use */
+
+/* *********************************************************************
+ * Structures
+ ********************************************************************* */
+
+typedef uint64_t cfe_xuint_t;
+typedef int64_t cfe_xint_t;
+typedef int64_t cfe_xptr_t;
+
+typedef struct xiocb_buffer_s {
+ cfe_xuint_t buf_offset; /* offset on device (bytes) */
+ cfe_xptr_t buf_ptr; /* pointer to a buffer */
+ cfe_xuint_t buf_length; /* length of this buffer */
+ cfe_xuint_t buf_retlen; /* returned length (for read ops) */
+ cfe_xuint_t buf_ioctlcmd; /* IOCTL command (used only for IOCTLs) */
+} xiocb_buffer_t;
+
+#define buf_devflags buf_ioctlcmd /* returned device info flags */
+
+typedef struct xiocb_inpstat_s {
+ cfe_xuint_t inp_status; /* 1 means input available */
+} xiocb_inpstat_t;
+
+typedef struct xiocb_envbuf_s {
+ cfe_xint_t enum_idx; /* 0-based enumeration index */
+ cfe_xptr_t name_ptr; /* name string buffer */
+ cfe_xint_t name_length; /* size of name buffer */
+ cfe_xptr_t val_ptr; /* value string buffer */
+ cfe_xint_t val_length; /* size of value string buffer */
+} xiocb_envbuf_t;
+
+typedef struct xiocb_cpuctl_s {
+ cfe_xuint_t cpu_number; /* cpu number to control */
+ cfe_xuint_t cpu_command; /* command to issue to CPU */
+ cfe_xuint_t start_addr; /* CPU start address */
+ cfe_xuint_t gp_val; /* starting GP value */
+ cfe_xuint_t sp_val; /* starting SP value */
+ cfe_xuint_t a1_val; /* starting A1 value */
+} xiocb_cpuctl_t;
+
+typedef struct xiocb_time_s {
+ cfe_xint_t ticks; /* current time in ticks */
+} xiocb_time_t;
+
+typedef struct xiocb_exitstat_s {
+ cfe_xint_t status;
+} xiocb_exitstat_t;
+
+typedef struct xiocb_meminfo_s {
+ cfe_xint_t mi_idx; /* 0-based enumeration index */
+ cfe_xint_t mi_type; /* type of memory block */
+ cfe_xuint_t mi_addr; /* physical start address */
+ cfe_xuint_t mi_size; /* block size */
+} xiocb_meminfo_t;
+
+typedef struct xiocb_fwinfo_s {
+ cfe_xint_t fwi_version; /* major, minor, eco version */
+ cfe_xint_t fwi_totalmem; /* total installed mem */
+ cfe_xint_t fwi_flags; /* various flags */
+ cfe_xint_t fwi_boardid; /* board ID */
+ cfe_xint_t fwi_bootarea_va; /* VA of boot area */
+ cfe_xint_t fwi_bootarea_pa; /* PA of boot area */
+ cfe_xint_t fwi_bootarea_size; /* size of boot area */
+ cfe_xint_t fwi_reserved1;
+ cfe_xint_t fwi_reserved2;
+ cfe_xint_t fwi_reserved3;
+} xiocb_fwinfo_t;
+
+typedef struct cfe_xiocb_s {
+ cfe_xuint_t xiocb_fcode; /* IOCB function code */
+ cfe_xint_t xiocb_status; /* return status */
+ cfe_xint_t xiocb_handle; /* file/device handle */
+ cfe_xuint_t xiocb_flags; /* flags for this IOCB */
+ cfe_xuint_t xiocb_psize; /* size of parameter list */
+ union {
+ xiocb_buffer_t xiocb_buffer; /* buffer parameters */
+ xiocb_inpstat_t xiocb_inpstat; /* input status parameters */
+ xiocb_envbuf_t xiocb_envbuf; /* environment function parameters */
+ xiocb_cpuctl_t xiocb_cpuctl; /* CPU control parameters */
+ xiocb_time_t xiocb_time; /* timer parameters */
+ xiocb_meminfo_t xiocb_meminfo; /* memory arena info parameters */
+ xiocb_fwinfo_t xiocb_fwinfo; /* firmware information */
+ xiocb_exitstat_t xiocb_exitstat; /* Exit Status */
+ } plist;
+} cfe_xiocb_t;
+
+#endif /* CFE_API_INT_H */
diff --git a/arch/mips/sibyte/cfe/cfe_error.h b/arch/mips/sibyte/cfe/cfe_error.h
new file mode 100644
index 0000000..77eb493
--- /dev/null
+++ b/arch/mips/sibyte/cfe/cfe_error.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2000, 2001, 2002 Broadcom Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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 Common Firmware Environment (CFE)
+ *
+ * Error codes File: cfe_error.h
+ *
+ * CFE's global error code list is here.
+ *
+ * Author: Mitch Lichtenberg
+ *
+ ********************************************************************* */
+
+
+#define CFE_OK 0
+#define CFE_ERR -1 /* generic error */
+#define CFE_ERR_INV_COMMAND -2
+#define CFE_ERR_EOF -3
+#define CFE_ERR_IOERR -4
+#define CFE_ERR_NOMEM -5
+#define CFE_ERR_DEVNOTFOUND -6
+#define CFE_ERR_DEVOPEN -7
+#define CFE_ERR_INV_PARAM -8
+#define CFE_ERR_ENVNOTFOUND -9
+#define CFE_ERR_ENVREADONLY -10
+
+#define CFE_ERR_NOTELF -11
+#define CFE_ERR_NOT32BIT -12
+#define CFE_ERR_WRONGENDIAN -13
+#define CFE_ERR_BADELFVERS -14
+#define CFE_ERR_NOTMIPS -15
+#define CFE_ERR_BADELFFMT -16
+#define CFE_ERR_BADADDR -17
+
+#define CFE_ERR_FILENOTFOUND -18
+#define CFE_ERR_UNSUPPORTED -19
+
+#define CFE_ERR_HOSTUNKNOWN -20
+
+#define CFE_ERR_TIMEOUT -21
+
+#define CFE_ERR_PROTOCOLERR -22
+
+#define CFE_ERR_NETDOWN -23
+#define CFE_ERR_NONAMESERVER -24
+
+#define CFE_ERR_NOHANDLES -25
+#define CFE_ERR_ALREADYBOUND -26
+
+#define CFE_ERR_CANNOTSET -27
+#define CFE_ERR_NOMORE -28
+#define CFE_ERR_BADFILESYS -29
+#define CFE_ERR_FSNOTAVAIL -30
+
+#define CFE_ERR_INVBOOTBLOCK -31
+#define CFE_ERR_WRONGDEVTYPE -32
+#define CFE_ERR_BBCHECKSUM -33
+#define CFE_ERR_BOOTPROGCHKSUM -34
+
+#define CFE_ERR_LDRNOTAVAIL -35
+
+#define CFE_ERR_NOTREADY -36
+
+#define CFE_ERR_GETMEM -37
+#define CFE_ERR_SETMEM -38
+
+#define CFE_ERR_NOTCONN -39
+#define CFE_ERR_ADDRINUSE -40
diff --git a/arch/mips/sibyte/cfe/console.c b/arch/mips/sibyte/cfe/console.c
new file mode 100644
index 0000000..53a5c1e
--- /dev/null
+++ b/arch/mips/sibyte/cfe/console.c
@@ -0,0 +1,80 @@
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/console.h>
+
+#include <asm/sibyte/board.h>
+
+#include "cfe_api.h"
+#include "cfe_error.h"
+
+extern int cfe_cons_handle;
+
+static void cfe_console_write(struct console *cons, const char *str,
+ unsigned int count)
+{
+ int i, last, written;
+
+ for (i=0,last=0; i<count; i++) {
+ if (!str[i])
+ /* XXXKW can/should this ever happen? */
+ return;
+ if (str[i] == '\n') {
+ do {
+ written = cfe_write(cfe_cons_handle, &str[last], i-last);
+ if (written < 0)
+ ;
+ last += written;
+ } while (last < i);
+ while (cfe_write(cfe_cons_handle, "\r", 1) <= 0)
+ ;
+ }
+ }
+ if (last != count) {
+ do {
+ written = cfe_write(cfe_cons_handle, &str[last], count-last);
+ if (written < 0)
+ ;
+ last += written;
+ } while (last < count);
+ }
+
+}
+
+static int cfe_console_setup(struct console *cons, char *str)
+{
+ char consdev[32];
+ /* XXXKW think about interaction with 'console=' cmdline arg */
+ /* If none of the console options are configured, the build will break. */
+ if (cfe_getenv("BOOT_CONSOLE", consdev, 32) >= 0) {
+#ifdef CONFIG_SIBYTE_SB1250_DUART
+ if (!strcmp(consdev, "uart0")) {
+ setleds("u0cn");
+ } else if (!strcmp(consdev, "uart1")) {
+ setleds("u1cn");
+#endif
+#ifdef CONFIG_VGA_CONSOLE
+ } else if (!strcmp(consdev, "pcconsole0")) {
+ setleds("pccn");
+#endif
+ } else
+ return -ENODEV;
+ }
+ return 0;
+}
+
+static struct console sb1250_cfe_cons = {
+ .name = "cfe",
+ .write = cfe_console_write,
+ .setup = cfe_console_setup,
+ .flags = CON_PRINTBUFFER,
+ .index = -1,
+};
+
+static int __init sb1250_cfe_console_init(void)
+{
+ register_console(&sb1250_cfe_cons);
+ return 0;
+}
+
+console_initcall(sb1250_cfe_console_init);
diff --git a/arch/mips/sibyte/cfe/setup.c b/arch/mips/sibyte/cfe/setup.c
new file mode 100644
index 0000000..d6d0364
--- /dev/null
+++ b/arch/mips/sibyte/cfe/setup.c
@@ -0,0 +1,358 @@
+/*
+ * Copyright (C) 2000, 2001, 2002, 2003 Broadcom Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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 <linux/config.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/linkage.h>
+#include <linux/mm.h>
+#include <linux/blkdev.h>
+#include <linux/bootmem.h>
+#include <linux/smp.h>
+
+#include <asm/bootinfo.h>
+#include <asm/reboot.h>
+#include <asm/sibyte/board.h>
+
+#include "cfe_api.h"
+#include "cfe_error.h"
+
+/* Max ram addressable in 32-bit segments */
+#ifdef CONFIG_MIPS64
+#define MAX_RAM_SIZE (~0ULL)
+#else
+#ifdef CONFIG_HIGHMEM
+#ifdef CONFIG_64BIT_PHYS_ADDR
+#define MAX_RAM_SIZE (~0ULL)
+#else
+#define MAX_RAM_SIZE (0xffffffffULL)
+#endif
+#else
+#define MAX_RAM_SIZE (0x1fffffffULL)
+#endif
+#endif
+
+#define SIBYTE_MAX_MEM_REGIONS 8
+phys_t board_mem_region_addrs[SIBYTE_MAX_MEM_REGIONS];
+phys_t board_mem_region_sizes[SIBYTE_MAX_MEM_REGIONS];
+unsigned int board_mem_region_count;
+
+int cfe_cons_handle;
+
+#ifdef CONFIG_BLK_DEV_INITRD
+extern unsigned long initrd_start, initrd_end;
+#endif
+
+#ifdef CONFIG_KGDB
+extern int kgdb_port;
+#endif
+
+static void ATTRIB_NORET cfe_linux_exit(void *arg)
+{
+ int warm = *(int *)arg;
+
+ if (smp_processor_id()) {
+ static int reboot_smp;
+
+ /* Don't repeat the process from another CPU */
+ if (!reboot_smp) {
+ /* Get CPU 0 to do the cfe_exit */
+ reboot_smp = 1;
+ smp_call_function(cfe_linux_exit, arg, 1, 0);
+ }
+ } else {
+ printk("Passing control back to CFE...\n");
+ cfe_exit(warm, 0);
+ printk("cfe_exit returned??\n");
+ }
+ while (1);
+}
+
+static void ATTRIB_NORET cfe_linux_restart(char *command)
+{
+ static const int zero;
+
+ cfe_linux_exit((void *)&zero);
+}
+
+static void ATTRIB_NORET cfe_linux_halt(void)
+{
+ static const int one = 1;
+
+ cfe_linux_exit((void *)&one);
+}
+
+static __init void prom_meminit(void)
+{
+ u64 addr, size, type; /* regardless of 64BIT_PHYS_ADDR */
+ int mem_flags = 0;
+ unsigned int idx;
+ int rd_flag;
+#ifdef CONFIG_BLK_DEV_INITRD
+ unsigned long initrd_pstart;
+ unsigned long initrd_pend;
+
+ initrd_pstart = CPHYSADDR(initrd_start);
+ initrd_pend = CPHYSADDR(initrd_end);
+ if (initrd_start &&
+ ((initrd_pstart > MAX_RAM_SIZE)
+ || (initrd_pend > MAX_RAM_SIZE))) {
+ panic("initrd out of addressable memory");
+ }
+
+#endif /* INITRD */
+
+ for (idx = 0; cfe_enummem(idx, mem_flags, &addr, &size, &type) != CFE_ERR_NOMORE;
+ idx++) {
+ rd_flag = 0;
+ if (type == CFE_MI_AVAILABLE) {
+ /*
+ * See if this block contains (any portion of) the
+ * ramdisk
+ */
+#ifdef CONFIG_BLK_DEV_INITRD
+ if (initrd_start) {
+ if ((initrd_pstart > addr) &&
+ (initrd_pstart < (addr + size))) {
+ add_memory_region(addr,
+ initrd_pstart - addr,
+ BOOT_MEM_RAM);
+ rd_flag = 1;
+ }
+ if ((initrd_pend > addr) &&
+ (initrd_pend < (addr + size))) {
+ add_memory_region(initrd_pend,
+ (addr + size) - initrd_pend,
+ BOOT_MEM_RAM);
+ rd_flag = 1;
+ }
+ }
+#endif
+ if (!rd_flag) {
+ if (addr > MAX_RAM_SIZE)
+ continue;
+ if (addr+size > MAX_RAM_SIZE)
+ size = MAX_RAM_SIZE - (addr+size) + 1;
+ /*
+ * memcpy/__copy_user prefetch, which
+ * will cause a bus error for
+ * KSEG/KUSEG addrs not backed by RAM.
+ * Hence, reserve some padding for the
+ * prefetch distance.
+ */
+ if (size > 512)
+ size -= 512;
+ add_memory_region(addr, size, BOOT_MEM_RAM);
+ }
+ board_mem_region_addrs[board_mem_region_count] = addr;
+ board_mem_region_sizes[board_mem_region_count] = size;
+ board_mem_region_count++;
+ if (board_mem_region_count ==
+ SIBYTE_MAX_MEM_REGIONS) {
+ /*
+ * Too many regions. Need to configure more
+ */
+ while(1);
+ }
+ }
+ }
+#ifdef CONFIG_BLK_DEV_INITRD
+ if (initrd_start) {
+ add_memory_region(initrd_pstart, initrd_pend - initrd_pstart,
+ BOOT_MEM_RESERVED);
+ }
+#endif
+}
+
+#ifdef CONFIG_BLK_DEV_INITRD
+static int __init initrd_setup(char *str)
+{
+ char rdarg[64];
+ int idx;
+ char *tmp, *endptr;
+ unsigned long initrd_size;
+
+ /* Make a copy of the initrd argument so we can smash it up here */
+ for (idx = 0; idx < sizeof(rdarg)-1; idx++) {
+ if (!str[idx] || (str[idx] == ' ')) break;
+ rdarg[idx] = str[idx];
+ }
+
+ rdarg[idx] = 0;
+ str = rdarg;
+
+ /*
+ *Initrd location comes in the form "<hex size of ramdisk in bytes>@<location in memory>"
+ * e.g. initrd=3abfd@80010000. This is set up by the loader.
+ */
+ for (tmp = str; *tmp != '@'; tmp++) {
+ if (!*tmp) {
+ goto fail;
+ }
+ }
+ *tmp = 0;
+ tmp++;
+ if (!*tmp) {
+ goto fail;
+ }
+ initrd_size = simple_strtoul(str, &endptr, 16);
+ if (*endptr) {
+ *(tmp-1) = '@';
+ goto fail;
+ }
+ *(tmp-1) = '@';
+ initrd_start = simple_strtoul(tmp, &endptr, 16);
+ if (*endptr) {
+ goto fail;
+ }
+ initrd_end = initrd_start + initrd_size;
+ prom_printf("Found initrd of %lx@%lx\n", initrd_size, initrd_start);
+ return 1;
+ fail:
+ prom_printf("Bad initrd argument. Disabling initrd\n");
+ initrd_start = 0;
+ initrd_end = 0;
+ return 1;
+}
+
+#endif
+
+/*
+ * prom_init is called just after the cpu type is determined, from setup_arch()
+ */
+void __init prom_init(void)
+{
+ uint64_t cfe_ept, cfe_handle;
+ unsigned int cfe_eptseal;
+ int argc = fw_arg0;
+ char **envp = (char **) fw_arg2;
+ int *prom_vec = (int *) fw_arg3;
+#ifdef CONFIG_KGDB
+ char *arg;
+#endif
+
+ _machine_restart = cfe_linux_restart;
+ _machine_halt = cfe_linux_halt;
+ _machine_power_off = cfe_linux_halt;
+
+ /*
+ * Check if a loader was used; if NOT, the 4 arguments are
+ * what CFE gives us (handle, 0, EPT and EPTSEAL)
+ */
+ if (argc < 0) {
+ cfe_handle = (uint64_t)(long)argc;
+ cfe_ept = (long)envp;
+ cfe_eptseal = (uint32_t)(unsigned long)prom_vec;
+ } else {
+ if ((int32_t)(long)prom_vec < 0) {
+ /*
+ * Old loader; all it gives us is the handle,
+ * so use the "known" entrypoint and assume
+ * the seal.
+ */
+ cfe_handle = (uint64_t)(long)prom_vec;
+ cfe_ept = (uint64_t)((int32_t)0x9fc00500);
+ cfe_eptseal = CFE_EPTSEAL;
+ } else {
+ /*
+ * Newer loaders bundle the handle/ept/eptseal
+ * Note: prom_vec is in the loader's useg
+ * which is still alive in the TLB.
+ */
+ cfe_handle = (uint64_t)((int32_t *)prom_vec)[0];
+ cfe_ept = (uint64_t)((int32_t *)prom_vec)[2];
+ cfe_eptseal = (unsigned int)((uint32_t *)prom_vec)[3];
+ }
+ }
+ if (cfe_eptseal != CFE_EPTSEAL) {
+ /* too early for panic to do any good */
+ prom_printf("CFE's entrypoint seal doesn't match. Spinning.");
+ while (1) ;
+ }
+ cfe_init(cfe_handle, cfe_ept);
+ /*
+ * Get the handle for (at least) prom_putchar, possibly for
+ * boot console
+ */
+ cfe_cons_handle = cfe_getstdhandle(CFE_STDHANDLE_CONSOLE);
+ if (cfe_getenv("LINUX_CMDLINE", arcs_cmdline, CL_SIZE) < 0) {
+ if (argc < 0) {
+ /*
+ * It's OK for direct boot to not provide a
+ * command line
+ */
+ strcpy(arcs_cmdline, "root=/dev/ram0 ");
+#ifdef CONFIG_SIBYTE_PTSWARM
+ strcat(arcs_cmdline, "console=ttyS0,115200 ");
+#endif
+ } else {
+ /* The loader should have set the command line */
+ /* too early for panic to do any good */
+ prom_printf("LINUX_CMDLINE not defined in cfe.");
+ while (1) ;
+ }
+ }
+
+#ifdef CONFIG_KGDB
+ if ((arg = strstr(arcs_cmdline,"kgdb=duart")) != NULL)
+ kgdb_port = (arg[10] == '0') ? 0 : 1;
+ else
+ kgdb_port = 1;
+#endif
+
+#ifdef CONFIG_BLK_DEV_INITRD
+ {
+ char *ptr;
+ /* Need to find out early whether we've got an initrd. So scan
+ the list looking now */
+ for (ptr = arcs_cmdline; *ptr; ptr++) {
+ while (*ptr == ' ') {
+ ptr++;
+ }
+ if (!strncmp(ptr, "initrd=", 7)) {
+ initrd_setup(ptr+7);
+ break;
+ } else {
+ while (*ptr && (*ptr != ' ')) {
+ ptr++;
+ }
+ }
+ }
+ }
+#endif /* CONFIG_BLK_DEV_INITRD */
+
+ /* Not sure this is needed, but it's the safe way. */
+ arcs_cmdline[CL_SIZE-1] = 0;
+
+ mips_machgroup = MACH_GROUP_SIBYTE;
+ prom_meminit();
+}
+
+unsigned long __init prom_free_prom_memory(void)
+{
+ /* Not sure what I'm supposed to do here. Nothing, I think */
+ return 0;
+}
+
+void prom_putchar(char c)
+{
+ int ret;
+
+ while ((ret = cfe_write(cfe_cons_handle, &c, 1)) == 0)
+ ;
+}
diff --git a/arch/mips/sibyte/cfe/smp.c b/arch/mips/sibyte/cfe/smp.c
new file mode 100644
index 0000000..7339219
--- /dev/null
+++ b/arch/mips/sibyte/cfe/smp.c
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2000, 2001, 2002, 2003 Broadcom Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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 <linux/init.h>
+#include <linux/sched.h>
+#include <linux/smp.h>
+#include <asm/processor.h>
+
+#include "cfe_api.h"
+#include "cfe_error.h"
+
+/*
+ * Use CFE to find out how many CPUs are available, setting up
+ * phys_cpu_present_map and the logical/physical mappings.
+ * XXXKW will the boot CPU ever not be physical 0?
+ *
+ * Common setup before any secondaries are started
+ */
+void __init prom_prepare_cpus(unsigned int max_cpus)
+{
+ int i, num;
+
+ cpus_clear(phys_cpu_present_map);
+ cpu_set(0, phys_cpu_present_map);
+ __cpu_number_map[0] = 0;
+ __cpu_logical_map[0] = 0;
+
+ for (i=1, num=0; i<NR_CPUS; i++) {
+ if (cfe_cpu_stop(i) == 0) {
+ cpu_set(i, phys_cpu_present_map);
+ __cpu_number_map[i] = ++num;
+ __cpu_logical_map[num] = i;
+ }
+ }
+ printk("Detected %i available secondary CPU(s)\n", num);
+}
+
+/*
+ * Setup the PC, SP, and GP of a secondary processor and start it
+ * running!
+ */
+void prom_boot_secondary(int cpu, struct task_struct *idle)
+{
+ int retval;
+
+ retval = cfe_cpu_start(cpu_logical_map(cpu), &smp_bootstrap,
+ __KSTK_TOS(idle),
+ (unsigned long)idle->thread_info, 0);
+ if (retval != 0)
+ printk("cfe_start_cpu(%i) returned %i\n" , cpu, retval);
+}
+
+/*
+ * Code to run on secondary just after probing the CPU
+ */
+void prom_init_secondary(void)
+{
+ extern void sb1250_smp_init(void);
+ sb1250_smp_init();
+}
+
+/*
+ * Do any tidying up before marking online and running the idle
+ * loop
+ */
+void prom_smp_finish(void)
+{
+ extern void sb1250_smp_finish(void);
+ sb1250_smp_finish();
+}
+
+/*
+ * Final cleanup after all secondaries booted
+ */
+void prom_cpus_done(void)
+{
+}
diff --git a/arch/mips/sibyte/sb1250/Makefile b/arch/mips/sibyte/sb1250/Makefile
new file mode 100644
index 0000000..a8af846
--- /dev/null
+++ b/arch/mips/sibyte/sb1250/Makefile
@@ -0,0 +1,8 @@
+obj-y := setup.o irq.o irq_handler.o time.o
+
+obj-$(CONFIG_SMP) += smp.o
+obj-$(CONFIG_SIBYTE_TBPROF) += bcm1250_tbprof.o
+obj-$(CONFIG_SIBYTE_STANDALONE) += prom.o
+obj-$(CONFIG_SIBYTE_BUS_WATCHER) += bus_watcher.o
+
+EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/sibyte/sb1250/bcm1250_tbprof.c b/arch/mips/sibyte/sb1250/bcm1250_tbprof.c
new file mode 100644
index 0000000..7f813ae
--- /dev/null
+++ b/arch/mips/sibyte/sb1250/bcm1250_tbprof.c
@@ -0,0 +1,390 @@
+/*
+ * Copyright (C) 2001, 2002, 2003 Broadcom Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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.
+ */
+
+#define SBPROF_TB_DEBUG 0
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/fs.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/sibyte/sb1250.h>
+#include <asm/sibyte/sb1250_regs.h>
+#include <asm/sibyte/sb1250_scd.h>
+#include <asm/sibyte/sb1250_int.h>
+#include <asm/sibyte/trace_prof.h>
+
+#define DEVNAME "bcm1250_tbprof"
+
+static struct sbprof_tb sbp;
+
+#define TB_FULL (sbp.next_tb_sample == MAX_TB_SAMPLES)
+
+/************************************************************************
+ * Support for ZBbus sampling using the trace buffer
+ *
+ * We use the SCD performance counter interrupt, caused by a Zclk counter
+ * overflow, to trigger the start of tracing.
+ *
+ * We set the trace buffer to sample everything and freeze on
+ * overflow.
+ *
+ * We map the interrupt for trace_buffer_freeze to handle it on CPU 0.
+ *
+ ************************************************************************/
+
+static u_int64_t tb_period;
+
+static void arm_tb(void)
+{
+ u_int64_t scdperfcnt;
+ u_int64_t next = (1ULL << 40) - tb_period;
+ u_int64_t tb_options = M_SCD_TRACE_CFG_FREEZE_FULL;
+ /* Generate an SCD_PERFCNT interrupt in TB_PERIOD Zclks to
+ trigger start of trace. XXX vary sampling period */
+ bus_writeq(0, IOADDR(A_SCD_PERF_CNT_1));
+ scdperfcnt = bus_readq(IOADDR(A_SCD_PERF_CNT_CFG));
+ /* Unfortunately, in Pass 2 we must clear all counters to knock down
+ a previous interrupt request. This means that bus profiling
+ requires ALL of the SCD perf counters. */
+ bus_writeq((scdperfcnt & ~M_SPC_CFG_SRC1) | // keep counters 0,2,3 as is
+ M_SPC_CFG_ENABLE | // enable counting
+ M_SPC_CFG_CLEAR | // clear all counters
+ V_SPC_CFG_SRC1(1), // counter 1 counts cycles
+ IOADDR(A_SCD_PERF_CNT_CFG));
+ bus_writeq(next, IOADDR(A_SCD_PERF_CNT_1));
+ /* Reset the trace buffer */
+ bus_writeq(M_SCD_TRACE_CFG_RESET, IOADDR(A_SCD_TRACE_CFG));
+#if 0 && defined(M_SCD_TRACE_CFG_FORCECNT)
+ /* XXXKW may want to expose control to the data-collector */
+ tb_options |= M_SCD_TRACE_CFG_FORCECNT;
+#endif
+ bus_writeq(tb_options, IOADDR(A_SCD_TRACE_CFG));
+ sbp.tb_armed = 1;
+}
+
+static irqreturn_t sbprof_tb_intr(int irq, void *dev_id, struct pt_regs *regs)
+{
+ int i;
+ DBG(printk(DEVNAME ": tb_intr\n"));
+ if (sbp.next_tb_sample < MAX_TB_SAMPLES) {
+ /* XXX should use XKPHYS to make writes bypass L2 */
+ u_int64_t *p = sbp.sbprof_tbbuf[sbp.next_tb_sample++];
+ /* Read out trace */
+ bus_writeq(M_SCD_TRACE_CFG_START_READ, IOADDR(A_SCD_TRACE_CFG));
+ __asm__ __volatile__ ("sync" : : : "memory");
+ /* Loop runs backwards because bundles are read out in reverse order */
+ for (i = 256 * 6; i > 0; i -= 6) {
+ // Subscripts decrease to put bundle in the order
+ // t0 lo, t0 hi, t1 lo, t1 hi, t2 lo, t2 hi
+ p[i-1] = bus_readq(IOADDR(A_SCD_TRACE_READ)); // read t2 hi
+ p[i-2] = bus_readq(IOADDR(A_SCD_TRACE_READ)); // read t2 lo
+ p[i-3] = bus_readq(IOADDR(A_SCD_TRACE_READ)); // read t1 hi
+ p[i-4] = bus_readq(IOADDR(A_SCD_TRACE_READ)); // read t1 lo
+ p[i-5] = bus_readq(IOADDR(A_SCD_TRACE_READ)); // read t0 hi
+ p[i-6] = bus_readq(IOADDR(A_SCD_TRACE_READ)); // read t0 lo
+ }
+ if (!sbp.tb_enable) {
+ DBG(printk(DEVNAME ": tb_intr shutdown\n"));
+ bus_writeq(M_SCD_TRACE_CFG_RESET,
+ IOADDR(A_SCD_TRACE_CFG));
+ sbp.tb_armed = 0;
+ wake_up(&sbp.tb_sync);
+ } else {
+ arm_tb(); // knock down current interrupt and get another one later
+ }
+ } else {
+ /* No more trace buffer samples */
+ DBG(printk(DEVNAME ": tb_intr full\n"));
+ bus_writeq(M_SCD_TRACE_CFG_RESET, IOADDR(A_SCD_TRACE_CFG));
+ sbp.tb_armed = 0;
+ if (!sbp.tb_enable) {
+ wake_up(&sbp.tb_sync);
+ }
+ wake_up(&sbp.tb_read);
+ }
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t sbprof_pc_intr(int irq, void *dev_id, struct pt_regs *regs)
+{
+ printk(DEVNAME ": unexpected pc_intr");
+ return IRQ_NONE;
+}
+
+int sbprof_zbprof_start(struct file *filp)
+{
+ u_int64_t scdperfcnt;
+
+ if (sbp.tb_enable)
+ return -EBUSY;
+
+ DBG(printk(DEVNAME ": starting\n"));
+
+ sbp.tb_enable = 1;
+ sbp.next_tb_sample = 0;
+ filp->f_pos = 0;
+
+ if (request_irq
+ (K_INT_TRACE_FREEZE, sbprof_tb_intr, 0, DEVNAME " trace freeze", &sbp)) {
+ return -EBUSY;
+ }
+ /* Make sure there isn't a perf-cnt interrupt waiting */
+ scdperfcnt = bus_readq(IOADDR(A_SCD_PERF_CNT_CFG));
+ /* Disable and clear counters, override SRC_1 */
+ bus_writeq((scdperfcnt & ~(M_SPC_CFG_SRC1 | M_SPC_CFG_ENABLE)) |
+ M_SPC_CFG_ENABLE |
+ M_SPC_CFG_CLEAR |
+ V_SPC_CFG_SRC1(1),
+ IOADDR(A_SCD_PERF_CNT_CFG));
+
+ /* We grab this interrupt to prevent others from trying to use
+ it, even though we don't want to service the interrupts
+ (they only feed into the trace-on-interrupt mechanism) */
+ if (request_irq
+ (K_INT_PERF_CNT, sbprof_pc_intr, 0, DEVNAME " scd perfcnt", &sbp)) {
+ free_irq(K_INT_TRACE_FREEZE, &sbp);
+ return -EBUSY;
+ }
+
+ /* I need the core to mask these, but the interrupt mapper to
+ pass them through. I am exploiting my knowledge that
+ cp0_status masks out IP[5]. krw */
+ bus_writeq(K_INT_MAP_I3,
+ IOADDR(A_IMR_REGISTER(0, R_IMR_INTERRUPT_MAP_BASE) +
+ (K_INT_PERF_CNT << 3)));
+
+ /* Initialize address traps */
+ bus_writeq(0, IOADDR(A_ADDR_TRAP_UP_0));
+ bus_writeq(0, IOADDR(A_ADDR_TRAP_UP_1));
+ bus_writeq(0, IOADDR(A_ADDR_TRAP_UP_2));
+ bus_writeq(0, IOADDR(A_ADDR_TRAP_UP_3));
+
+ bus_writeq(0, IOADDR(A_ADDR_TRAP_DOWN_0));
+ bus_writeq(0, IOADDR(A_ADDR_TRAP_DOWN_1));
+ bus_writeq(0, IOADDR(A_ADDR_TRAP_DOWN_2));
+ bus_writeq(0, IOADDR(A_ADDR_TRAP_DOWN_3));
+
+ bus_writeq(0, IOADDR(A_ADDR_TRAP_CFG_0));
+ bus_writeq(0, IOADDR(A_ADDR_TRAP_CFG_1));
+ bus_writeq(0, IOADDR(A_ADDR_TRAP_CFG_2));
+ bus_writeq(0, IOADDR(A_ADDR_TRAP_CFG_3));
+
+ /* Initialize Trace Event 0-7 */
+ // when interrupt
+ bus_writeq(M_SCD_TREVT_INTERRUPT, IOADDR(A_SCD_TRACE_EVENT_0));
+ bus_writeq(0, IOADDR(A_SCD_TRACE_EVENT_1));
+ bus_writeq(0, IOADDR(A_SCD_TRACE_EVENT_2));
+ bus_writeq(0, IOADDR(A_SCD_TRACE_EVENT_3));
+ bus_writeq(0, IOADDR(A_SCD_TRACE_EVENT_4));
+ bus_writeq(0, IOADDR(A_SCD_TRACE_EVENT_5));
+ bus_writeq(0, IOADDR(A_SCD_TRACE_EVENT_6));
+ bus_writeq(0, IOADDR(A_SCD_TRACE_EVENT_7));
+
+ /* Initialize Trace Sequence 0-7 */
+ // Start on event 0 (interrupt)
+ bus_writeq(V_SCD_TRSEQ_FUNC_START | 0x0fff,
+ IOADDR(A_SCD_TRACE_SEQUENCE_0));
+ // dsamp when d used | asamp when a used
+ bus_writeq(M_SCD_TRSEQ_ASAMPLE | M_SCD_TRSEQ_DSAMPLE |
+ K_SCD_TRSEQ_TRIGGER_ALL,
+ IOADDR(A_SCD_TRACE_SEQUENCE_1));
+ bus_writeq(0, IOADDR(A_SCD_TRACE_SEQUENCE_2));
+ bus_writeq(0, IOADDR(A_SCD_TRACE_SEQUENCE_3));
+ bus_writeq(0, IOADDR(A_SCD_TRACE_SEQUENCE_4));
+ bus_writeq(0, IOADDR(A_SCD_TRACE_SEQUENCE_5));
+ bus_writeq(0, IOADDR(A_SCD_TRACE_SEQUENCE_6));
+ bus_writeq(0, IOADDR(A_SCD_TRACE_SEQUENCE_7));
+
+ /* Now indicate the PERF_CNT interrupt as a trace-relevant interrupt */
+ bus_writeq((1ULL << K_INT_PERF_CNT),
+ IOADDR(A_IMR_REGISTER(0, R_IMR_INTERRUPT_TRACE)));
+
+ arm_tb();
+
+ DBG(printk(DEVNAME ": done starting\n"));
+
+ return 0;
+}
+
+int sbprof_zbprof_stop(void)
+{
+ DBG(printk(DEVNAME ": stopping\n"));
+
+ if (sbp.tb_enable) {
+ sbp.tb_enable = 0;
+ /* XXXKW there is a window here where the intr handler
+ may run, see the disable, and do the wake_up before
+ this sleep happens. */
+ if (sbp.tb_armed) {
+ DBG(printk(DEVNAME ": wait for disarm\n"));
+ interruptible_sleep_on(&sbp.tb_sync);
+ DBG(printk(DEVNAME ": disarm complete\n"));
+ }
+ free_irq(K_INT_TRACE_FREEZE, &sbp);
+ free_irq(K_INT_PERF_CNT, &sbp);
+ }
+
+ DBG(printk(DEVNAME ": done stopping\n"));
+
+ return 0;
+}
+
+static int sbprof_tb_open(struct inode *inode, struct file *filp)
+{
+ int minor;
+
+ minor = iminor(inode);
+ if (minor != 0) {
+ return -ENODEV;
+ }
+ if (sbp.open) {
+ return -EBUSY;
+ }
+
+ memset(&sbp, 0, sizeof(struct sbprof_tb));
+ sbp.sbprof_tbbuf = vmalloc(MAX_TBSAMPLE_BYTES);
+ if (!sbp.sbprof_tbbuf) {
+ return -ENOMEM;
+ }
+ memset(sbp.sbprof_tbbuf, 0, MAX_TBSAMPLE_BYTES);
+ init_waitqueue_head(&sbp.tb_sync);
+ init_waitqueue_head(&sbp.tb_read);
+ sbp.open = 1;
+
+ return 0;
+}
+
+static int sbprof_tb_release(struct inode *inode, struct file *filp)
+{
+ int minor;
+
+ minor = iminor(inode);
+ if (minor != 0 || !sbp.open) {
+ return -ENODEV;
+ }
+
+ if (sbp.tb_armed || sbp.tb_enable) {
+ sbprof_zbprof_stop();
+ }
+
+ vfree(sbp.sbprof_tbbuf);
+ sbp.open = 0;
+
+ return 0;
+}
+
+static ssize_t sbprof_tb_read(struct file *filp, char *buf,
+ size_t size, loff_t *offp)
+{
+ int cur_sample, sample_off, cur_count, sample_left;
+ char *src;
+ int count = 0;
+ char *dest = buf;
+ long cur_off = *offp;
+
+ count = 0;
+ cur_sample = cur_off / TB_SAMPLE_SIZE;
+ sample_off = cur_off % TB_SAMPLE_SIZE;
+ sample_left = TB_SAMPLE_SIZE - sample_off;
+ while (size && (cur_sample < sbp.next_tb_sample)) {
+ cur_count = size < sample_left ? size : sample_left;
+ src = (char *)(((long)sbp.sbprof_tbbuf[cur_sample])+sample_off);
+ copy_to_user(dest, src, cur_count);
+ DBG(printk(DEVNAME ": read from sample %d, %d bytes\n",
+ cur_sample, cur_count));
+ size -= cur_count;
+ sample_left -= cur_count;
+ if (!sample_left) {
+ cur_sample++;
+ sample_off = 0;
+ sample_left = TB_SAMPLE_SIZE;
+ } else {
+ sample_off += cur_count;
+ }
+ cur_off += cur_count;
+ dest += cur_count;
+ count += cur_count;
+ }
+ *offp = cur_off;
+
+ return count;
+}
+
+static int sbprof_tb_ioctl(struct inode *inode,
+ struct file *filp,
+ unsigned int command,
+ unsigned long arg)
+{
+ int error = 0;
+
+ switch (command) {
+ case SBPROF_ZBSTART:
+ error = sbprof_zbprof_start(filp);
+ break;
+ case SBPROF_ZBSTOP:
+ error = sbprof_zbprof_stop();
+ break;
+ case SBPROF_ZBWAITFULL:
+ interruptible_sleep_on(&sbp.tb_read);
+ /* XXXKW check if interrupted? */
+ return put_user(TB_FULL, (int *) arg);
+ default:
+ error = -EINVAL;
+ break;
+ }
+
+ return error;
+}
+
+static struct file_operations sbprof_tb_fops = {
+ .owner = THIS_MODULE,
+ .open = sbprof_tb_open,
+ .release = sbprof_tb_release,
+ .read = sbprof_tb_read,
+ .ioctl = sbprof_tb_ioctl,
+ .mmap = NULL,
+};
+
+static int __init sbprof_tb_init(void)
+{
+ if (register_chrdev(SBPROF_TB_MAJOR, DEVNAME, &sbprof_tb_fops)) {
+ printk(KERN_WARNING DEVNAME ": initialization failed (dev %d)\n",
+ SBPROF_TB_MAJOR);
+ return -EIO;
+ }
+ sbp.open = 0;
+ tb_period = zbbus_mhz * 10000LL;
+ printk(KERN_INFO DEVNAME ": initialized - tb_period = %lld\n", tb_period);
+ return 0;
+}
+
+static void __exit sbprof_tb_cleanup(void)
+{
+ unregister_chrdev(SBPROF_TB_MAJOR, DEVNAME);
+}
+
+module_init(sbprof_tb_init);
+module_exit(sbprof_tb_cleanup);
diff --git a/arch/mips/sibyte/sb1250/bus_watcher.c b/arch/mips/sibyte/sb1250/bus_watcher.c
new file mode 100644
index 0000000..182a16f
--- /dev/null
+++ b/arch/mips/sibyte/sb1250/bus_watcher.c
@@ -0,0 +1,259 @@
+/*
+ * Copyright (C) 2002,2003 Broadcom Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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.
+ */
+
+/*
+ * The Bus Watcher monitors internal bus transactions and maintains
+ * counts of transactions with error status, logging details and
+ * causing one of several interrupts. This driver provides a handler
+ * for those interrupts which aggregates the counts (to avoid
+ * saturating the 8-bit counters) and provides a presence in
+ * /proc/bus_watcher if PROC_FS is on.
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/proc_fs.h>
+#include <asm/system.h>
+#include <asm/io.h>
+
+#include <asm/sibyte/sb1250.h>
+#include <asm/sibyte/sb1250_regs.h>
+#include <asm/sibyte/sb1250_int.h>
+#include <asm/sibyte/sb1250_scd.h>
+
+
+struct bw_stats_struct {
+ uint64_t status;
+ uint32_t l2_err;
+ uint32_t memio_err;
+ int status_printed;
+ unsigned long l2_cor_d;
+ unsigned long l2_bad_d;
+ unsigned long l2_cor_t;
+ unsigned long l2_bad_t;
+ unsigned long mem_cor_d;
+ unsigned long mem_bad_d;
+ unsigned long bus_error;
+} bw_stats;
+
+
+static void print_summary(uint32_t status, uint32_t l2_err,
+ uint32_t memio_err)
+{
+ printk("Bus watcher error counters: %08x %08x\n", l2_err, memio_err);
+ printk("\nLast recorded signature:\n");
+ printk("Request %02x from %d, answered by %d with Dcode %d\n",
+ (unsigned int)(G_SCD_BERR_TID(status) & 0x3f),
+ (int)(G_SCD_BERR_TID(status) >> 6),
+ (int)G_SCD_BERR_RID(status),
+ (int)G_SCD_BERR_DCODE(status));
+}
+
+/*
+ * check_bus_watcher is exported for use in situations where we want
+ * to see the most recent status of the bus watcher, which might have
+ * already been destructively read out of the registers.
+ *
+ * notes: this is currently used by the cache error handler
+ * should provide locking against the interrupt handler
+ */
+void check_bus_watcher(void)
+{
+ u32 status, l2_err, memio_err;
+
+#ifdef CONFIG_SB1_PASS_1_WORKAROUNDS
+ /* Destructive read, clears register and interrupt */
+ status = csr_in32(IOADDR(A_SCD_BUS_ERR_STATUS));
+#else
+ /* Use non-destructive register */
+ status = csr_in32(IOADDR(A_SCD_BUS_ERR_STATUS_DEBUG));
+#endif
+ if (!(status & 0x7fffffff)) {
+ printk("Using last values reaped by bus watcher driver\n");
+ status = bw_stats.status;
+ l2_err = bw_stats.l2_err;
+ memio_err = bw_stats.memio_err;
+ } else {
+ l2_err = csr_in32(IOADDR(A_BUS_L2_ERRORS));
+ memio_err = csr_in32(IOADDR(A_BUS_MEM_IO_ERRORS));
+ }
+ if (status & ~(1UL << 31))
+ print_summary(status, l2_err, memio_err);
+ else
+ printk("Bus watcher indicates no error\n");
+}
+
+static int bw_print_buffer(char *page, struct bw_stats_struct *stats)
+{
+ int len;
+
+ len = sprintf(page, "SiByte Bus Watcher statistics\n");
+ len += sprintf(page+len, "-----------------------------\n");
+ len += sprintf(page+len, "L2-d-cor %8ld\nL2-d-bad %8ld\n",
+ stats->l2_cor_d, stats->l2_bad_d);
+ len += sprintf(page+len, "L2-t-cor %8ld\nL2-t-bad %8ld\n",
+ stats->l2_cor_t, stats->l2_bad_t);
+ len += sprintf(page+len, "MC-d-cor %8ld\nMC-d-bad %8ld\n",
+ stats->mem_cor_d, stats->mem_bad_d);
+ len += sprintf(page+len, "IO-err %8ld\n", stats->bus_error);
+ len += sprintf(page+len, "\nLast recorded signature:\n");
+ len += sprintf(page+len, "Request %02x from %d, answered by %d with Dcode %d\n",
+ (unsigned int)(G_SCD_BERR_TID(stats->status) & 0x3f),
+ (int)(G_SCD_BERR_TID(stats->status) >> 6),
+ (int)G_SCD_BERR_RID(stats->status),
+ (int)G_SCD_BERR_DCODE(stats->status));
+ /* XXXKW indicate multiple errors between printings, or stats
+ collection (or both)? */
+ if (stats->status & M_SCD_BERR_MULTERRS)
+ len += sprintf(page+len, "Multiple errors observed since last check.\n");
+ if (stats->status_printed) {
+ len += sprintf(page+len, "(no change since last printing)\n");
+ } else {
+ stats->status_printed = 1;
+ }
+
+ return len;
+}
+
+#ifdef CONFIG_PROC_FS
+
+/* For simplicity, I want to assume a single read is required each
+ time */
+static int bw_read_proc(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ int len;
+
+ if (off == 0) {
+ len = bw_print_buffer(page, data);
+ *start = page;
+ } else {
+ len = 0;
+ *eof = 1;
+ }
+ return len;
+}
+
+static void create_proc_decoder(struct bw_stats_struct *stats)
+{
+ struct proc_dir_entry *ent;
+
+ ent = create_proc_read_entry("bus_watcher", S_IWUSR | S_IRUGO, NULL,
+ bw_read_proc, stats);
+ if (!ent) {
+ printk(KERN_INFO "Unable to initialize bus_watcher /proc entry\n");
+ return;
+ }
+}
+
+#endif /* CONFIG_PROC_FS */
+
+/*
+ * sibyte_bw_int - handle bus watcher interrupts and accumulate counts
+ *
+ * notes: possible re-entry due to multiple sources
+ * should check/indicate saturation
+ */
+static irqreturn_t sibyte_bw_int(int irq, void *data, struct pt_regs *regs)
+{
+ struct bw_stats_struct *stats = data;
+ unsigned long cntr;
+#ifdef CONFIG_SIBYTE_BW_TRACE
+ int i;
+#endif
+#ifndef CONFIG_PROC_FS
+ char bw_buf[1024];
+#endif
+
+#ifdef CONFIG_SIBYTE_BW_TRACE
+ csr_out32(M_SCD_TRACE_CFG_FREEZE, IOADDR(A_SCD_TRACE_CFG));
+ csr_out32(M_SCD_TRACE_CFG_START_READ, IOADDR(A_SCD_TRACE_CFG));
+
+ for (i=0; i<256*6; i++)
+ printk("%016llx\n",
+ (unsigned long long)bus_readq(IOADDR(A_SCD_TRACE_READ)));
+
+ csr_out32(M_SCD_TRACE_CFG_RESET, IOADDR(A_SCD_TRACE_CFG));
+ csr_out32(M_SCD_TRACE_CFG_START, IOADDR(A_SCD_TRACE_CFG));
+#endif
+
+ /* Destructive read, clears register and interrupt */
+ stats->status = csr_in32(IOADDR(A_SCD_BUS_ERR_STATUS));
+ stats->status_printed = 0;
+
+ stats->l2_err = cntr = csr_in32(IOADDR(A_BUS_L2_ERRORS));
+ stats->l2_cor_d += G_SCD_L2ECC_CORR_D(cntr);
+ stats->l2_bad_d += G_SCD_L2ECC_BAD_D(cntr);
+ stats->l2_cor_t += G_SCD_L2ECC_CORR_T(cntr);
+ stats->l2_bad_t += G_SCD_L2ECC_BAD_T(cntr);
+ csr_out32(0, IOADDR(A_BUS_L2_ERRORS));
+
+ stats->memio_err = cntr = csr_in32(IOADDR(A_BUS_MEM_IO_ERRORS));
+ stats->mem_cor_d += G_SCD_MEM_ECC_CORR(cntr);
+ stats->mem_bad_d += G_SCD_MEM_ECC_BAD(cntr);
+ stats->bus_error += G_SCD_MEM_BUSERR(cntr);
+ csr_out32(0, IOADDR(A_BUS_MEM_IO_ERRORS));
+
+#ifndef CONFIG_PROC_FS
+ bw_print_buffer(bw_buf, stats);
+ printk(bw_buf);
+#endif
+
+ return IRQ_HANDLED;
+}
+
+int __init sibyte_bus_watcher(void)
+{
+ memset(&bw_stats, 0, sizeof(struct bw_stats_struct));
+ bw_stats.status_printed = 1;
+
+ if (request_irq(K_INT_BAD_ECC, sibyte_bw_int, 0, "Bus watcher", &bw_stats)) {
+ printk("Failed to register bus watcher BAD_ECC irq\n");
+ return -1;
+ }
+ if (request_irq(K_INT_COR_ECC, sibyte_bw_int, 0, "Bus watcher", &bw_stats)) {
+ free_irq(K_INT_BAD_ECC, &bw_stats);
+ printk("Failed to register bus watcher COR_ECC irq\n");
+ return -1;
+ }
+ if (request_irq(K_INT_IO_BUS, sibyte_bw_int, 0, "Bus watcher", &bw_stats)) {
+ free_irq(K_INT_BAD_ECC, &bw_stats);
+ free_irq(K_INT_COR_ECC, &bw_stats);
+ printk("Failed to register bus watcher IO_BUS irq\n");
+ return -1;
+ }
+
+#ifdef CONFIG_PROC_FS
+ create_proc_decoder(&bw_stats);
+#endif
+
+#ifdef CONFIG_SIBYTE_BW_TRACE
+ csr_out32((M_SCD_TRSEQ_ASAMPLE | M_SCD_TRSEQ_DSAMPLE |
+ K_SCD_TRSEQ_TRIGGER_ALL),
+ IOADDR(A_SCD_TRACE_SEQUENCE_0));
+ csr_out32(M_SCD_TRACE_CFG_RESET, IOADDR(A_SCD_TRACE_CFG));
+ csr_out32(M_SCD_TRACE_CFG_START, IOADDR(A_SCD_TRACE_CFG));
+#endif
+
+ return 0;
+}
+
+__initcall(sibyte_bus_watcher);
diff --git a/arch/mips/sibyte/sb1250/irq.c b/arch/mips/sibyte/sb1250/irq.c
new file mode 100644
index 0000000..2728abb
--- /dev/null
+++ b/arch/mips/sibyte/sb1250/irq.c
@@ -0,0 +1,431 @@
+/*
+ * Copyright (C) 2000, 2001, 2002, 2003 Broadcom Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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 <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/linkage.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/smp.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/kernel_stat.h>
+
+#include <asm/errno.h>
+#include <asm/signal.h>
+#include <asm/system.h>
+#include <asm/ptrace.h>
+#include <asm/io.h>
+
+#include <asm/sibyte/sb1250_regs.h>
+#include <asm/sibyte/sb1250_int.h>
+#include <asm/sibyte/sb1250_uart.h>
+#include <asm/sibyte/sb1250_scd.h>
+#include <asm/sibyte/sb1250.h>
+
+/*
+ * These are the routines that handle all the low level interrupt stuff.
+ * Actions handled here are: initialization of the interrupt map, requesting of
+ * interrupt lines by handlers, dispatching if interrupts to handlers, probing
+ * for interrupt lines
+ */
+
+
+#define shutdown_sb1250_irq disable_sb1250_irq
+static void end_sb1250_irq(unsigned int irq);
+static void enable_sb1250_irq(unsigned int irq);
+static void disable_sb1250_irq(unsigned int irq);
+static unsigned int startup_sb1250_irq(unsigned int irq);
+static void ack_sb1250_irq(unsigned int irq);
+#ifdef CONFIG_SMP
+static void sb1250_set_affinity(unsigned int irq, unsigned long mask);
+#endif
+
+#ifdef CONFIG_SIBYTE_HAS_LDT
+extern unsigned long ldt_eoi_space;
+#endif
+
+#ifdef CONFIG_KGDB
+static int kgdb_irq;
+
+/* Default to UART1 */
+int kgdb_port = 1;
+#ifdef CONFIG_SIBYTE_SB1250_DUART
+extern char sb1250_duart_present[];
+#endif
+#endif
+
+static struct hw_interrupt_type sb1250_irq_type = {
+ "SB1250-IMR",
+ startup_sb1250_irq,
+ shutdown_sb1250_irq,
+ enable_sb1250_irq,
+ disable_sb1250_irq,
+ ack_sb1250_irq,
+ end_sb1250_irq,
+#ifdef CONFIG_SMP
+ sb1250_set_affinity
+#else
+ NULL
+#endif
+};
+
+/* Store the CPU id (not the logical number) */
+int sb1250_irq_owner[SB1250_NR_IRQS];
+
+DEFINE_SPINLOCK(sb1250_imr_lock);
+
+void sb1250_mask_irq(int cpu, int irq)
+{
+ unsigned long flags;
+ u64 cur_ints;
+
+ spin_lock_irqsave(&sb1250_imr_lock, flags);
+ cur_ints = __bus_readq(IOADDR(A_IMR_MAPPER(cpu) +
+ R_IMR_INTERRUPT_MASK));
+ cur_ints |= (((u64) 1) << irq);
+ __bus_writeq(cur_ints, IOADDR(A_IMR_MAPPER(cpu) +
+ R_IMR_INTERRUPT_MASK));
+ spin_unlock_irqrestore(&sb1250_imr_lock, flags);
+}
+
+void sb1250_unmask_irq(int cpu, int irq)
+{
+ unsigned long flags;
+ u64 cur_ints;
+
+ spin_lock_irqsave(&sb1250_imr_lock, flags);
+ cur_ints = __bus_readq(IOADDR(A_IMR_MAPPER(cpu) +
+ R_IMR_INTERRUPT_MASK));
+ cur_ints &= ~(((u64) 1) << irq);
+ __bus_writeq(cur_ints, IOADDR(A_IMR_MAPPER(cpu) +
+ R_IMR_INTERRUPT_MASK));
+ spin_unlock_irqrestore(&sb1250_imr_lock, flags);
+}
+
+#ifdef CONFIG_SMP
+static void sb1250_set_affinity(unsigned int irq, unsigned long mask)
+{
+ int i = 0, old_cpu, cpu, int_on;
+ u64 cur_ints;
+ irq_desc_t *desc = irq_desc + irq;
+ unsigned long flags;
+
+ while (mask) {
+ if (mask & 1) {
+ mask >>= 1;
+ break;
+ }
+ mask >>= 1;
+ i++;
+ }
+
+ if (mask) {
+ printk("attempted to set irq affinity for irq %d to multiple CPUs\n", irq);
+ return;
+ }
+
+ /* Convert logical CPU to physical CPU */
+ cpu = cpu_logical_map(i);
+
+ /* Protect against other affinity changers and IMR manipulation */
+ spin_lock_irqsave(&desc->lock, flags);
+ spin_lock(&sb1250_imr_lock);
+
+ /* Swizzle each CPU's IMR (but leave the IP selection alone) */
+ old_cpu = sb1250_irq_owner[irq];
+ cur_ints = __bus_readq(IOADDR(A_IMR_MAPPER(old_cpu) +
+ R_IMR_INTERRUPT_MASK));
+ int_on = !(cur_ints & (((u64) 1) << irq));
+ if (int_on) {
+ /* If it was on, mask it */
+ cur_ints |= (((u64) 1) << irq);
+ __bus_writeq(cur_ints, IOADDR(A_IMR_MAPPER(old_cpu) +
+ R_IMR_INTERRUPT_MASK));
+ }
+ sb1250_irq_owner[irq] = cpu;
+ if (int_on) {
+ /* unmask for the new CPU */
+ cur_ints = __bus_readq(IOADDR(A_IMR_MAPPER(cpu) +
+ R_IMR_INTERRUPT_MASK));
+ cur_ints &= ~(((u64) 1) << irq);
+ __bus_writeq(cur_ints, IOADDR(A_IMR_MAPPER(cpu) +
+ R_IMR_INTERRUPT_MASK));
+ }
+ spin_unlock(&sb1250_imr_lock);
+ spin_unlock_irqrestore(&desc->lock, flags);
+}
+#endif
+
+
+/* Defined in arch/mips/sibyte/sb1250/irq_handler.S */
+extern void sb1250_irq_handler(void);
+
+/*****************************************************************************/
+
+static unsigned int startup_sb1250_irq(unsigned int irq)
+{
+ sb1250_unmask_irq(sb1250_irq_owner[irq], irq);
+
+ return 0; /* never anything pending */
+}
+
+
+static void disable_sb1250_irq(unsigned int irq)
+{
+ sb1250_mask_irq(sb1250_irq_owner[irq], irq);
+}
+
+static void enable_sb1250_irq(unsigned int irq)
+{
+ sb1250_unmask_irq(sb1250_irq_owner[irq], irq);
+}
+
+
+static void ack_sb1250_irq(unsigned int irq)
+{
+#ifdef CONFIG_SIBYTE_HAS_LDT
+ u64 pending;
+
+ /*
+ * If the interrupt was an HT interrupt, now is the time to
+ * clear it. NOTE: we assume the HT bridge was set up to
+ * deliver the interrupts to all CPUs (which makes affinity
+ * changing easier for us)
+ */
+ pending = bus_readq(IOADDR(A_IMR_REGISTER(sb1250_irq_owner[irq],
+ R_IMR_LDT_INTERRUPT)));
+ pending &= ((u64)1 << (irq));
+ if (pending) {
+ int i;
+ for (i=0; i<NR_CPUS; i++) {
+ int cpu;
+#ifdef CONFIG_SMP
+ cpu = cpu_logical_map(i);
+#else
+ cpu = i;
+#endif
+ /*
+ * Clear for all CPUs so an affinity switch
+ * doesn't find an old status
+ */
+ bus_writeq(pending,
+ IOADDR(A_IMR_REGISTER(cpu,
+ R_IMR_LDT_INTERRUPT_CLR)));
+ }
+
+ /*
+ * Generate EOI. For Pass 1 parts, EOI is a nop. For
+ * Pass 2, the LDT world may be edge-triggered, but
+ * this EOI shouldn't hurt. If they are
+ * level-sensitive, the EOI is required.
+ */
+ *(uint32_t *)(ldt_eoi_space+(irq<<16)+(7<<2)) = 0;
+ }
+#endif
+ sb1250_mask_irq(sb1250_irq_owner[irq], irq);
+}
+
+
+static void end_sb1250_irq(unsigned int irq)
+{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
+ sb1250_unmask_irq(sb1250_irq_owner[irq], irq);
+ }
+}
+
+
+void __init init_sb1250_irqs(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;
+ if (i < SB1250_NR_IRQS) {
+ irq_desc[i].handler = &sb1250_irq_type;
+ sb1250_irq_owner[i] = 0;
+ } else {
+ irq_desc[i].handler = &no_irq_type;
+ }
+ }
+}
+
+
+static irqreturn_t sb1250_dummy_handler(int irq, void *dev_id,
+ struct pt_regs *regs)
+{
+ return IRQ_NONE;
+}
+
+static struct irqaction sb1250_dummy_action = {
+ .handler = sb1250_dummy_handler,
+ .flags = 0,
+ .mask = CPU_MASK_NONE,
+ .name = "sb1250-private",
+ .next = NULL,
+ .dev_id = 0
+};
+
+int sb1250_steal_irq(int irq)
+{
+ irq_desc_t *desc = irq_desc + irq;
+ unsigned long flags;
+ int retval = 0;
+
+ if (irq >= SB1250_NR_IRQS)
+ return -EINVAL;
+
+ spin_lock_irqsave(&desc->lock,flags);
+ /* Don't allow sharing at all for these */
+ if (desc->action != NULL)
+ retval = -EBUSY;
+ else {
+ desc->action = &sb1250_dummy_action;
+ desc->depth = 0;
+ }
+ spin_unlock_irqrestore(&desc->lock,flags);
+ return 0;
+}
+
+/*
+ * arch_init_irq is called early in the boot sequence from init/main.c via
+ * init_IRQ. It is responsible for setting up the interrupt mapper and
+ * installing the handler that will be responsible for dispatching interrupts
+ * to the "right" place.
+ */
+/*
+ * For now, map all interrupts to IP[2]. We could save
+ * some cycles by parceling out system interrupts to different
+ * IP lines, but keep it simple for bringup. We'll also direct
+ * all interrupts to a single CPU; we should probably route
+ * PCI and LDT to one cpu and everything else to the other
+ * to balance the load a bit.
+ *
+ * On the second cpu, everything is set to IP5, which is
+ * ignored, EXCEPT the mailbox interrupt. That one is
+ * set to IP[2] so it is handled. This is needed so we
+ * can do cross-cpu function calls, as requred by SMP
+ */
+
+#define IMR_IP2_VAL K_INT_MAP_I0
+#define IMR_IP3_VAL K_INT_MAP_I1
+#define IMR_IP4_VAL K_INT_MAP_I2
+#define IMR_IP5_VAL K_INT_MAP_I3
+#define IMR_IP6_VAL K_INT_MAP_I4
+
+void __init arch_init_irq(void)
+{
+
+ unsigned int i;
+ u64 tmp;
+ unsigned int imask = STATUSF_IP4 | STATUSF_IP3 | STATUSF_IP2 |
+ STATUSF_IP1 | STATUSF_IP0;
+
+ /* Default everything to IP2 */
+ for (i = 0; i < SB1250_NR_IRQS; i++) { /* was I0 */
+ bus_writeq(IMR_IP2_VAL,
+ IOADDR(A_IMR_REGISTER(0, R_IMR_INTERRUPT_MAP_BASE) +
+ (i << 3)));
+ bus_writeq(IMR_IP2_VAL,
+ IOADDR(A_IMR_REGISTER(1, R_IMR_INTERRUPT_MAP_BASE) +
+ (i << 3)));
+ }
+
+ init_sb1250_irqs();
+
+ /*
+ * Map the high 16 bits of the mailbox registers to IP[3], for
+ * inter-cpu messages
+ */
+ /* Was I1 */
+ bus_writeq(IMR_IP3_VAL,
+ IOADDR(A_IMR_REGISTER(0, R_IMR_INTERRUPT_MAP_BASE) +
+ (K_INT_MBOX_0 << 3)));
+ bus_writeq(IMR_IP3_VAL,
+ IOADDR(A_IMR_REGISTER(1, R_IMR_INTERRUPT_MAP_BASE) +
+ (K_INT_MBOX_0 << 3)));
+
+ /* Clear the mailboxes. The firmware may leave them dirty */
+ bus_writeq(0xffffffffffffffffULL,
+ IOADDR(A_IMR_REGISTER(0, R_IMR_MAILBOX_CLR_CPU)));
+ bus_writeq(0xffffffffffffffffULL,
+ IOADDR(A_IMR_REGISTER(1, R_IMR_MAILBOX_CLR_CPU)));
+
+ /* Mask everything except the mailbox registers for both cpus */
+ tmp = ~((u64) 0) ^ (((u64) 1) << K_INT_MBOX_0);
+ bus_writeq(tmp, IOADDR(A_IMR_REGISTER(0, R_IMR_INTERRUPT_MASK)));
+ bus_writeq(tmp, IOADDR(A_IMR_REGISTER(1, R_IMR_INTERRUPT_MASK)));
+
+ sb1250_steal_irq(K_INT_MBOX_0);
+
+ /*
+ * Note that the timer interrupts are also mapped, but this is
+ * done in sb1250_time_init(). Also, the profiling driver
+ * does its own management of IP7.
+ */
+
+#ifdef CONFIG_KGDB
+ imask |= STATUSF_IP6;
+#endif
+ /* Enable necessary IPs, disable the rest */
+ change_c0_status(ST0_IM, imask);
+ set_except_vector(0, sb1250_irq_handler);
+
+#ifdef CONFIG_KGDB
+ if (kgdb_flag) {
+ kgdb_irq = K_INT_UART_0 + kgdb_port;
+
+#ifdef CONFIG_SIBYTE_SB1250_DUART
+ sb1250_duart_present[kgdb_port] = 0;
+#endif
+ /* Setup uart 1 settings, mapper */
+ bus_writeq(M_DUART_IMR_BRK, IOADDR(A_DUART_IMRREG(kgdb_port)));
+
+ sb1250_steal_irq(kgdb_irq);
+ bus_writeq(IMR_IP6_VAL,
+ IOADDR(A_IMR_REGISTER(0, R_IMR_INTERRUPT_MAP_BASE) +
+ (kgdb_irq<<3)));
+ sb1250_unmask_irq(0, kgdb_irq);
+ }
+#endif
+}
+
+#ifdef CONFIG_KGDB
+
+#include <linux/delay.h>
+
+#define duart_out(reg, val) csr_out32(val, IOADDR(A_DUART_CHANREG(kgdb_port,reg)))
+#define duart_in(reg) csr_in32(IOADDR(A_DUART_CHANREG(kgdb_port,reg)))
+
+void sb1250_kgdb_interrupt(struct pt_regs *regs)
+{
+ /*
+ * Clear break-change status (allow some time for the remote
+ * host to stop the break, since we would see another
+ * interrupt on the end-of-break too)
+ */
+ kstat_this_cpu.irqs[kgdb_irq]++;
+ mdelay(500);
+ duart_out(R_DUART_CMD, V_DUART_MISC_CMD_RESET_BREAK_INT |
+ M_DUART_RX_EN | M_DUART_TX_EN);
+ set_async_breakpoint(®s->cp0_epc);
+}
+
+#endif /* CONFIG_KGDB */
diff --git a/arch/mips/sibyte/sb1250/irq_handler.S b/arch/mips/sibyte/sb1250/irq_handler.S
new file mode 100644
index 0000000..60edc8f
--- /dev/null
+++ b/arch/mips/sibyte/sb1250/irq_handler.S
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2000, 2001, 2002, 2003 Broadcom Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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.
+ */
+
+/*
+ * sb1250_handle_int() is the routine that is actually called when an interrupt
+ * occurs. It is installed as the exception vector handler in arch_init_irq()
+ * in arch/mips/sibyte/sb1250/irq.c
+ *
+ * In the handle we figure out which interrupts need handling, and use that to
+ * call the dispatcher, which will take care of actually calling registered
+ * handlers
+ *
+ * Note that we take care of all raised interrupts in one go at the handler.
+ * This is more BSDish than the Indy code, and also, IMHO, more sane.
+ */
+#include <linux/config.h>
+
+#include <asm/addrspace.h>
+#include <asm/asm.h>
+#include <asm/mipsregs.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+#include <asm/sibyte/sb1250_defs.h>
+#include <asm/sibyte/sb1250_regs.h>
+#include <asm/sibyte/sb1250_int.h>
+
+/*
+ * What a pain. We have to be really careful saving the upper 32 bits of any
+ * register across function calls if we don't want them trashed--since were
+ * running in -o32, the calling routing never saves the full 64 bits of a
+ * register across a function call. Being the interrupt handler, we're
+ * guaranteed that interrupts are disabled during this code so we don't have
+ * to worry about random interrupts blasting the high 32 bits.
+ */
+
+ .text
+ .set push
+ .set noreorder
+ .set noat
+ .set mips64
+ .align 5
+ NESTED(sb1250_irq_handler, PT_SIZE, sp)
+ SAVE_ALL
+ CLI
+
+#ifdef CONFIG_SIBYTE_SB1250_PROF
+ /* Set compare to count to silence count/compare timer interrupts */
+ mfc0 t1, CP0_COUNT
+ mtc0 t1, CP0_COMPARE /* pause to clear IP[7] bit of cause ? */
+#endif
+ /* Read cause */
+ mfc0 s0, CP0_CAUSE
+
+#ifdef CONFIG_SIBYTE_SB1250_PROF
+ /* Cpu performance counter interrupt is routed to IP[7] */
+ andi t1, s0, CAUSEF_IP7
+ beqz t1, 0f
+ srl t1, s0, (CAUSEB_BD-2) /* Shift BD bit to bit 2 */
+ and t1, t1, 0x4 /* mask to get just BD bit */
+ mfc0 a0, CP0_EPC
+ jal sbprof_cpu_intr
+ addu a0, a0, t1 /* a0 = EPC + (BD ? 4 : 0) */
+ j ret_from_irq
+ nop
+0:
+#endif
+
+ /* Timer interrupt is routed to IP[4] */
+ andi t1, s0, CAUSEF_IP4
+ beqz t1, 1f
+ nop
+ jal sb1250_timer_interrupt
+ move a0, sp /* Pass the registers along */
+ j ret_from_irq
+ nop # delay slot
+1:
+
+#ifdef CONFIG_SMP
+ /* Mailbox interrupt is routed to IP[3] */
+ andi t1, s0, CAUSEF_IP3
+ beqz t1, 2f
+ nop
+ jal sb1250_mailbox_interrupt
+ move a0, sp
+ j ret_from_irq
+ nop # delay slot
+2:
+#endif
+
+#ifdef CONFIG_KGDB
+ /* KGDB (uart 1) interrupt is routed to IP[6] */
+ andi t1, s0, CAUSEF_IP6
+ beqz t1, 1f
+ nop # delay slot
+ jal sb1250_kgdb_interrupt
+ move a0, sp
+ j ret_from_irq
+ nop # delay slot
+1:
+#endif
+
+ and t1, s0, CAUSEF_IP2
+ beqz t1, 4f
+ nop
+
+ /*
+ * Default...we've hit an IP[2] interrupt, which means we've got to
+ * check the 1250 interrupt registers to figure out what to do
+ * Need to detect which CPU we're on, now that smp_affinity is supported.
+ */
+ PTR_LA v0, CKSEG1 + A_IMR_CPU0_BASE
+#ifdef CONFIG_SMP
+ lw t1, TI_CPU($28)
+ sll t1, IMR_REGISTER_SPACING_SHIFT
+ addu v0, t1
+#endif
+ ld s0, R_IMR_INTERRUPT_STATUS_BASE(v0) /* read IP[2] status */
+
+ beqz s0, 4f /* No interrupts. Return */
+ move a1, sp
+
+3: dclz s1, s0 /* Find the next interrupt */
+ dsubu a0, zero, s1
+ daddiu a0, a0, 63
+ jal do_IRQ
+ nop
+
+4: j ret_from_irq
+ nop
+
+ .set pop
+ END(sb1250_irq_handler)
diff --git a/arch/mips/sibyte/sb1250/prom.c b/arch/mips/sibyte/sb1250/prom.c
new file mode 100644
index 0000000..de62ab0
--- /dev/null
+++ b/arch/mips/sibyte/sb1250/prom.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2000, 2001 Broadcom Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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 <linux/config.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/blkdev.h>
+#include <linux/bootmem.h>
+#include <linux/smp.h>
+#include <linux/initrd.h>
+
+#include <asm/bootinfo.h>
+#include <asm/reboot.h>
+
+#define MAX_RAM_SIZE ((CONFIG_SIBYTE_STANDALONE_RAM_SIZE * 1024 * 1024) - 1)
+
+static __init void prom_meminit(void)
+{
+#ifdef CONFIG_BLK_DEV_INITRD
+ unsigned long initrd_pstart;
+ unsigned long initrd_pend;
+
+ initrd_pstart = __pa(initrd_start);
+ initrd_pend = __pa(initrd_end);
+ if (initrd_start &&
+ ((initrd_pstart > MAX_RAM_SIZE)
+ || (initrd_pend > MAX_RAM_SIZE))) {
+ panic("initrd out of addressable memory");
+ }
+
+ add_memory_region(0, initrd_pstart,
+ BOOT_MEM_RAM);
+ add_memory_region(initrd_pstart, initrd_pend - initrd_pstart,
+ BOOT_MEM_RESERVED);
+ add_memory_region(initrd_pend,
+ (CONFIG_SIBYTE_STANDALONE_RAM_SIZE * 1024 * 1024) - initrd_pend,
+ BOOT_MEM_RAM);
+#else
+ add_memory_region(0, CONFIG_SIBYTE_STANDALONE_RAM_SIZE * 1024 * 1024,
+ BOOT_MEM_RAM);
+#endif
+}
+
+void prom_cpu0_exit(void *unused)
+{
+ while (1) ;
+}
+
+static void prom_linux_exit(void)
+{
+#ifdef CONFIG_SMP
+ if (smp_processor_id()) {
+ smp_call_function(prom_cpu0_exit,NULL,1,1);
+ }
+#endif
+ while(1);
+}
+
+/*
+ * prom_init is called just after the cpu type is determined, from setup_arch()
+ */
+void __init prom_init(void)
+{
+ _machine_restart = (void (*)(char *))prom_linux_exit;
+ _machine_halt = prom_linux_exit;
+ _machine_power_off = prom_linux_exit;
+
+ strcpy(arcs_cmdline, "root=/dev/ram0 ");
+
+ mips_machgroup = MACH_GROUP_SIBYTE;
+ prom_meminit();
+}
+
+unsigned long __init prom_free_prom_memory(void)
+{
+ /* Not sure what I'm supposed to do here. Nothing, I think */
+ return 0;
+}
+
+void prom_putchar(char c)
+{
+}
diff --git a/arch/mips/sibyte/sb1250/setup.c b/arch/mips/sibyte/sb1250/setup.c
new file mode 100644
index 0000000..f8c605b
--- /dev/null
+++ b/arch/mips/sibyte/sb1250/setup.c
@@ -0,0 +1,206 @@
+/*
+ * Copyright (C) 2000, 2001, 2002, 2003 Broadcom Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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 <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/reboot.h>
+#include <linux/string.h>
+
+#include <asm/bootinfo.h>
+#include <asm/mipsregs.h>
+#include <asm/io.h>
+#include <asm/sibyte/sb1250.h>
+#include <asm/sibyte/sb1250_regs.h>
+#include <asm/sibyte/sb1250_scd.h>
+
+unsigned int sb1_pass;
+unsigned int soc_pass;
+unsigned int soc_type;
+unsigned int periph_rev;
+unsigned int zbbus_mhz;
+
+static char *soc_str;
+static char *pass_str;
+static unsigned int war_pass; /* XXXKW don't overload PASS defines? */
+
+static inline int setup_bcm1250(void);
+static inline int setup_bcm112x(void);
+
+/* Setup code likely to be common to all SiByte platforms */
+
+static inline int sys_rev_decode(void)
+{
+ int ret = 0;
+
+ war_pass = soc_pass;
+ switch (soc_type) {
+ case K_SYS_SOC_TYPE_BCM1250:
+ case K_SYS_SOC_TYPE_BCM1250_ALT:
+ case K_SYS_SOC_TYPE_BCM1250_ALT2:
+ soc_str = "BCM1250";
+ ret = setup_bcm1250();
+ break;
+ case K_SYS_SOC_TYPE_BCM1120:
+ soc_str = "BCM1120";
+ ret = setup_bcm112x();
+ break;
+ case K_SYS_SOC_TYPE_BCM1125:
+ soc_str = "BCM1125";
+ ret = setup_bcm112x();
+ break;
+ case K_SYS_SOC_TYPE_BCM1125H:
+ soc_str = "BCM1125H";
+ ret = setup_bcm112x();
+ break;
+ default:
+ prom_printf("Unknown SOC type %x\n", soc_type);
+ ret = 1;
+ break;
+ }
+ return ret;
+}
+
+static inline int setup_bcm1250(void)
+{
+ int ret = 0;
+
+ switch (soc_pass) {
+ case K_SYS_REVISION_BCM1250_PASS1:
+ periph_rev = 1;
+ pass_str = "Pass 1";
+ break;
+ case K_SYS_REVISION_BCM1250_A10:
+ periph_rev = 2;
+ pass_str = "A8/A10";
+ /* XXXKW different war_pass? */
+ war_pass = K_SYS_REVISION_BCM1250_PASS2;
+ break;
+ case K_SYS_REVISION_BCM1250_PASS2_2:
+ periph_rev = 2;
+ pass_str = "B1";
+ break;
+ case K_SYS_REVISION_BCM1250_B2:
+ periph_rev = 2;
+ pass_str = "B2";
+ war_pass = K_SYS_REVISION_BCM1250_PASS2_2;
+ break;
+ case K_SYS_REVISION_BCM1250_PASS3:
+ periph_rev = 3;
+ pass_str = "C0";
+ break;
+ case K_SYS_REVISION_BCM1250_C1:
+ periph_rev = 3;
+ pass_str = "C1";
+ break;
+ default:
+ if (soc_pass < K_SYS_REVISION_BCM1250_PASS2_2) {
+ periph_rev = 2;
+ pass_str = "A0-A6";
+ war_pass = K_SYS_REVISION_BCM1250_PASS2;
+ } else {
+ prom_printf("Unknown BCM1250 rev %x\n", soc_pass);
+ ret = 1;
+ }
+ break;
+ }
+ return ret;
+}
+
+static inline int setup_bcm112x(void)
+{
+ int ret = 0;
+
+ switch (soc_pass) {
+ case 0:
+ /* Early build didn't have revid set */
+ periph_rev = 3;
+ pass_str = "A1";
+ war_pass = K_SYS_REVISION_BCM112x_A1;
+ break;
+ case K_SYS_REVISION_BCM112x_A1:
+ periph_rev = 3;
+ pass_str = "A1";
+ break;
+ case K_SYS_REVISION_BCM112x_A2:
+ periph_rev = 3;
+ pass_str = "A2";
+ break;
+ default:
+ prom_printf("Unknown %s rev %x\n", soc_str, soc_pass);
+ ret = 1;
+ }
+ return ret;
+}
+
+void sb1250_setup(void)
+{
+ uint64_t sys_rev;
+ int plldiv;
+ int bad_config = 0;
+
+ sb1_pass = read_c0_prid() & 0xff;
+ sys_rev = bus_readq(IOADDR(A_SCD_SYSTEM_REVISION));
+ soc_type = SYS_SOC_TYPE(sys_rev);
+ soc_pass = G_SYS_REVISION(sys_rev);
+
+ if (sys_rev_decode()) {
+ prom_printf("Restart after failure to identify SiByte chip\n");
+ machine_restart(NULL);
+ }
+
+ plldiv = G_SYS_PLL_DIV(bus_readq(IOADDR(A_SCD_SYSTEM_CFG)));
+ zbbus_mhz = ((plldiv >> 1) * 50) + ((plldiv & 1) * 25);
+
+ prom_printf("Broadcom SiByte %s %s @ %d MHz (SB1 rev %d)\n",
+ soc_str, pass_str, zbbus_mhz * 2, sb1_pass);
+ prom_printf("Board type: %s\n", get_system_type());
+
+ switch(war_pass) {
+ case K_SYS_REVISION_BCM1250_PASS1:
+#ifndef CONFIG_SB1_PASS_1_WORKAROUNDS
+ prom_printf("@@@@ This is a BCM1250 A0-A2 (Pass 1) board, and the kernel doesn't have the proper workarounds compiled in. @@@@\n");
+ bad_config = 1;
+#endif
+ break;
+ case K_SYS_REVISION_BCM1250_PASS2:
+ /* Pass 2 - easiest as default for now - so many numbers */
+#if !defined(CONFIG_SB1_PASS_2_WORKAROUNDS) || !defined(CONFIG_SB1_PASS_2_1_WORKAROUNDS)
+ prom_printf("@@@@ This is a BCM1250 A3-A10 board, and the kernel doesn't have the proper workarounds compiled in. @@@@\n");
+ bad_config = 1;
+#endif
+#ifdef CONFIG_CPU_HAS_PREFETCH
+ prom_printf("@@@@ Prefetches may be enabled in this kernel, but are buggy on this board. @@@@\n");
+ bad_config = 1;
+#endif
+ break;
+ case K_SYS_REVISION_BCM1250_PASS2_2:
+#ifndef CONFIG_SB1_PASS_2_WORKAROUNDS
+ prom_printf("@@@@ This is a BCM1250 B1/B2. board, and the kernel doesn't have the proper workarounds compiled in. @@@@\n");
+ bad_config = 1;
+#endif
+#if defined(CONFIG_SB1_PASS_2_1_WORKAROUNDS) || !defined(CONFIG_CPU_HAS_PREFETCH)
+ prom_printf("@@@@ This is a BCM1250 B1/B2, but the kernel is conservatively configured for an 'A' stepping. @@@@\n");
+#endif
+ break;
+ default:
+ break;
+ }
+ if (bad_config) {
+ prom_printf("Invalid configuration for this chip.\n");
+ machine_restart(NULL);
+ }
+}
diff --git a/arch/mips/sibyte/sb1250/smp.c b/arch/mips/sibyte/sb1250/smp.c
new file mode 100644
index 0000000..be91b39
--- /dev/null
+++ b/arch/mips/sibyte/sb1250/smp.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2001, 2002, 2003 Broadcom Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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 <linux/init.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/smp.h>
+#include <linux/kernel_stat.h>
+
+#include <asm/mmu_context.h>
+#include <asm/io.h>
+#include <asm/sibyte/sb1250.h>
+#include <asm/sibyte/sb1250_regs.h>
+#include <asm/sibyte/sb1250_int.h>
+
+static void *mailbox_set_regs[] = {
+ (void *)IOADDR(A_IMR_CPU0_BASE + R_IMR_MAILBOX_SET_CPU),
+ (void *)IOADDR(A_IMR_CPU1_BASE + R_IMR_MAILBOX_SET_CPU)
+};
+
+static void *mailbox_clear_regs[] = {
+ (void *)IOADDR(A_IMR_CPU0_BASE + R_IMR_MAILBOX_CLR_CPU),
+ (void *)IOADDR(A_IMR_CPU1_BASE + R_IMR_MAILBOX_CLR_CPU)
+};
+
+static void *mailbox_regs[] = {
+ (void *)IOADDR(A_IMR_CPU0_BASE + R_IMR_MAILBOX_CPU),
+ (void *)IOADDR(A_IMR_CPU1_BASE + R_IMR_MAILBOX_CPU)
+};
+
+/*
+ * SMP init and finish on secondary CPUs
+ */
+void sb1250_smp_init(void)
+{
+ unsigned int imask = STATUSF_IP4 | STATUSF_IP3 | STATUSF_IP2 |
+ STATUSF_IP1 | STATUSF_IP0;
+
+ /* Set interrupt mask, but don't enable */
+ change_c0_status(ST0_IM, imask);
+}
+
+void sb1250_smp_finish(void)
+{
+ extern void sb1250_time_init(void);
+ sb1250_time_init();
+ local_irq_enable();
+}
+
+/*
+ * These are routines for dealing with the sb1250 smp capabilities
+ * independent of board/firmware
+ */
+
+/*
+ * Simple enough; everything is set up, so just poke the appropriate mailbox
+ * register, and we should be set
+ */
+void core_send_ipi(int cpu, unsigned int action)
+{
+ bus_writeq((((u64)action) << 48), mailbox_set_regs[cpu]);
+}
+
+void sb1250_mailbox_interrupt(struct pt_regs *regs)
+{
+ int cpu = smp_processor_id();
+ unsigned int action;
+
+ kstat_this_cpu.irqs[K_INT_MBOX_0]++;
+ /* Load the mailbox register to figure out what we're supposed to do */
+ action = (__bus_readq(mailbox_regs[cpu]) >> 48) & 0xffff;
+
+ /* Clear the mailbox to clear the interrupt */
+ __bus_writeq(((u64)action) << 48, mailbox_clear_regs[cpu]);
+
+ /*
+ * Nothing to do for SMP_RESCHEDULE_YOURSELF; returning from the
+ * interrupt will do the reschedule for us
+ */
+
+ if (action & SMP_CALL_FUNCTION)
+ smp_call_function_interrupt();
+}
diff --git a/arch/mips/sibyte/sb1250/time.c b/arch/mips/sibyte/sb1250/time.c
new file mode 100644
index 0000000..8b4c848
--- /dev/null
+++ b/arch/mips/sibyte/sb1250/time.c
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2000, 2001 Broadcom Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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.
+ */
+
+/*
+ * These are routines to set up and handle interrupts from the
+ * sb1250 general purpose timer 0. We're using the timer as a
+ * system clock, so we set it up to run at 100 Hz. On every
+ * interrupt, we update our idea of what the time of day is,
+ * then call do_timer() in the architecture-independent kernel
+ * code to do general bookkeeping (e.g. update jiffies, run
+ * bottom halves, etc.)
+ */
+#include <linux/config.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/kernel_stat.h>
+
+#include <asm/irq.h>
+#include <asm/ptrace.h>
+#include <asm/addrspace.h>
+#include <asm/time.h>
+#include <asm/io.h>
+
+#include <asm/sibyte/sb1250.h>
+#include <asm/sibyte/sb1250_regs.h>
+#include <asm/sibyte/sb1250_int.h>
+#include <asm/sibyte/sb1250_scd.h>
+
+
+#define IMR_IP2_VAL K_INT_MAP_I0
+#define IMR_IP3_VAL K_INT_MAP_I1
+#define IMR_IP4_VAL K_INT_MAP_I2
+
+extern int sb1250_steal_irq(int irq);
+
+void sb1250_time_init(void)
+{
+ int cpu = smp_processor_id();
+ int irq = K_INT_TIMER_0+cpu;
+
+ /* Only have 4 general purpose timers */
+ if (cpu > 3) {
+ BUG();
+ }
+
+ if (!cpu) {
+ /* Use our own gettimeoffset() routine */
+ do_gettimeoffset = sb1250_gettimeoffset;
+ }
+
+ sb1250_mask_irq(cpu, irq);
+
+ /* Map the timer interrupt to ip[4] of this cpu */
+ bus_writeq(IMR_IP4_VAL,
+ IOADDR(A_IMR_REGISTER(cpu, R_IMR_INTERRUPT_MAP_BASE) +
+ (irq << 3)));
+
+ /* the general purpose timer ticks at 1 Mhz independent if the rest of the system */
+ /* Disable the timer and set up the count */
+ bus_writeq(0, IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)));
+#ifdef CONFIG_SIMULATION
+ bus_writeq(50000 / HZ,
+ IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_INIT)));
+#else
+ bus_writeq(1000000/HZ,
+ IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_INIT)));
+#endif
+
+ /* Set the timer running */
+ bus_writeq(M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS,
+ IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)));
+
+ sb1250_unmask_irq(cpu, irq);
+ sb1250_steal_irq(irq);
+ /*
+ * This interrupt is "special" in that it doesn't use the request_irq
+ * way to hook the irq line. The timer interrupt is initialized early
+ * enough to make this a major pain, and it's also firing enough to
+ * warrant a bit of special case code. sb1250_timer_interrupt is
+ * called directly from irq_handler.S when IP[4] is set during an
+ * interrupt
+ */
+}
+
+void sb1250_timer_interrupt(struct pt_regs *regs)
+{
+ extern asmlinkage void ll_local_timer_interrupt(int irq, struct pt_regs *regs);
+ int cpu = smp_processor_id();
+ int irq = K_INT_TIMER_0 + cpu;
+
+ /* Reset the timer */
+ __bus_writeq(M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS,
+ IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)));
+
+ /*
+ * CPU 0 handles the global timer interrupt job
+ */
+ if (cpu == 0) {
+ ll_timer_interrupt(irq, regs);
+ }
+
+ /*
+ * every CPU should do profiling and process accouting
+ */
+ ll_local_timer_interrupt(irq, regs);
+}
+
+/*
+ * We use our own do_gettimeoffset() instead of the generic one,
+ * because the generic one does not work for SMP case.
+ * In addition, since we use general timer 0 for system time,
+ * we can get accurate intra-jiffy offset without calibration.
+ */
+unsigned long sb1250_gettimeoffset(void)
+{
+ unsigned long count =
+ bus_readq(IOADDR(A_SCD_TIMER_REGISTER(0, R_SCD_TIMER_CNT)));
+
+ return 1000000/HZ - count;
+ }
diff --git a/arch/mips/sibyte/swarm/Makefile b/arch/mips/sibyte/swarm/Makefile
new file mode 100644
index 0000000..2d62603
--- /dev/null
+++ b/arch/mips/sibyte/swarm/Makefile
@@ -0,0 +1,3 @@
+lib-y = setup.o rtc_xicor1241.o rtc_m41t81.o
+
+lib-$(CONFIG_KGDB) += dbg_io.o
diff --git a/arch/mips/sibyte/swarm/dbg_io.c b/arch/mips/sibyte/swarm/dbg_io.c
new file mode 100644
index 0000000..75ce14c
--- /dev/null
+++ b/arch/mips/sibyte/swarm/dbg_io.c
@@ -0,0 +1,76 @@
+/*
+ * kgdb debug routines for SiByte boards.
+ *
+ * Copyright (C) 2001 MontaVista Software Inc.
+ * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+
+/* -------------------- BEGINNING OF CONFIG --------------------- */
+
+#include <linux/delay.h>
+#include <asm/io.h>
+#include <asm/sibyte/sb1250.h>
+#include <asm/sibyte/sb1250_regs.h>
+#include <asm/sibyte/sb1250_uart.h>
+#include <asm/sibyte/sb1250_int.h>
+#include <asm/addrspace.h>
+
+/*
+ * We use the second serial port for kgdb traffic.
+ * 115200, 8, N, 1.
+ */
+
+#define BAUD_RATE 115200
+#define CLK_DIVISOR V_DUART_BAUD_RATE(BAUD_RATE)
+#define DATA_BITS V_DUART_BITS_PER_CHAR_8 /* or 7 */
+#define PARITY V_DUART_PARITY_MODE_NONE /* or even */
+#define STOP_BITS M_DUART_STOP_BIT_LEN_1 /* or 2 */
+
+static int duart_initialized = 0; /* 0: need to be init'ed by kgdb */
+
+/* -------------------- END OF CONFIG --------------------- */
+extern int kgdb_port;
+
+#define duart_out(reg, val) csr_out32(val, IOADDR(A_DUART_CHANREG(kgdb_port,reg)))
+#define duart_in(reg) csr_in32(IOADDR(A_DUART_CHANREG(kgdb_port,reg)))
+
+void putDebugChar(unsigned char c);
+unsigned char getDebugChar(void);
+static void
+duart_init(int clk_divisor, int data, int parity, int stop)
+{
+ duart_out(R_DUART_MODE_REG_1, data | parity);
+ duart_out(R_DUART_MODE_REG_2, stop);
+ duart_out(R_DUART_CLK_SEL, clk_divisor);
+
+ duart_out(R_DUART_CMD, M_DUART_RX_EN | M_DUART_TX_EN); /* enable rx and tx */
+}
+
+void
+putDebugChar(unsigned char c)
+{
+ if (!duart_initialized) {
+ duart_initialized = 1;
+ duart_init(CLK_DIVISOR, DATA_BITS, PARITY, STOP_BITS);
+ }
+ while ((duart_in(R_DUART_STATUS) & M_DUART_TX_RDY) == 0);
+ duart_out(R_DUART_TX_HOLD, c);
+}
+
+unsigned char
+getDebugChar(void)
+{
+ if (!duart_initialized) {
+ duart_initialized = 1;
+ duart_init(CLK_DIVISOR, DATA_BITS, PARITY, STOP_BITS);
+ }
+ while ((duart_in(R_DUART_STATUS) & M_DUART_RX_RDY) == 0) ;
+ return duart_in(R_DUART_RX_HOLD);
+}
+
diff --git a/arch/mips/sibyte/swarm/rtc_m41t81.c b/arch/mips/sibyte/swarm/rtc_m41t81.c
new file mode 100644
index 0000000..0e633ee
--- /dev/null
+++ b/arch/mips/sibyte/swarm/rtc_m41t81.c
@@ -0,0 +1,224 @@
+/*
+ * Copyright (C) 2000, 2001 Broadcom Corporation
+ *
+ * Copyright (C) 2002 MontaVista Software Inc.
+ * Author: jsun@mvista.com or jsun@junsun.net
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+#include <linux/bcd.h>
+#include <linux/types.h>
+#include <linux/time.h>
+
+#include <asm/time.h>
+#include <asm/addrspace.h>
+#include <asm/io.h>
+
+#include <asm/sibyte/sb1250.h>
+#include <asm/sibyte/sb1250_regs.h>
+#include <asm/sibyte/sb1250_smbus.h>
+
+
+/* M41T81 definitions */
+
+/*
+ * Register bits
+ */
+
+#define M41T81REG_SC_ST 0x80 /* stop bit */
+#define M41T81REG_HR_CB 0x40 /* century bit */
+#define M41T81REG_HR_CEB 0x80 /* century enable bit */
+#define M41T81REG_CTL_S 0x20 /* sign bit */
+#define M41T81REG_CTL_FT 0x40 /* frequency test bit */
+#define M41T81REG_CTL_OUT 0x80 /* output level */
+#define M41T81REG_WD_RB0 0x01 /* watchdog resolution bit 0 */
+#define M41T81REG_WD_RB1 0x02 /* watchdog resolution bit 1 */
+#define M41T81REG_WD_BMB0 0x04 /* watchdog multiplier bit 0 */
+#define M41T81REG_WD_BMB1 0x08 /* watchdog multiplier bit 1 */
+#define M41T81REG_WD_BMB2 0x10 /* watchdog multiplier bit 2 */
+#define M41T81REG_WD_BMB3 0x20 /* watchdog multiplier bit 3 */
+#define M41T81REG_WD_BMB4 0x40 /* watchdog multiplier bit 4 */
+#define M41T81REG_AMO_ABE 0x20 /* alarm in "battery back-up mode" enable bit */
+#define M41T81REG_AMO_SQWE 0x40 /* square wave enable */
+#define M41T81REG_AMO_AFE 0x80 /* alarm flag enable flag */
+#define M41T81REG_ADT_RPT5 0x40 /* alarm repeat mode bit 5 */
+#define M41T81REG_ADT_RPT4 0x80 /* alarm repeat mode bit 4 */
+#define M41T81REG_AHR_RPT3 0x80 /* alarm repeat mode bit 3 */
+#define M41T81REG_AHR_HT 0x40 /* halt update bit */
+#define M41T81REG_AMN_RPT2 0x80 /* alarm repeat mode bit 2 */
+#define M41T81REG_ASC_RPT1 0x80 /* alarm repeat mode bit 1 */
+#define M41T81REG_FLG_AF 0x40 /* alarm flag (read only) */
+#define M41T81REG_FLG_WDF 0x80 /* watchdog flag (read only) */
+#define M41T81REG_SQW_RS0 0x10 /* sqw frequency bit 0 */
+#define M41T81REG_SQW_RS1 0x20 /* sqw frequency bit 1 */
+#define M41T81REG_SQW_RS2 0x40 /* sqw frequency bit 2 */
+#define M41T81REG_SQW_RS3 0x80 /* sqw frequency bit 3 */
+
+
+/*
+ * Register numbers
+ */
+
+#define M41T81REG_TSC 0x00 /* tenths/hundredths of second */
+#define M41T81REG_SC 0x01 /* seconds */
+#define M41T81REG_MN 0x02 /* minute */
+#define M41T81REG_HR 0x03 /* hour/century */
+#define M41T81REG_DY 0x04 /* day of week */
+#define M41T81REG_DT 0x05 /* date of month */
+#define M41T81REG_MO 0x06 /* month */
+#define M41T81REG_YR 0x07 /* year */
+#define M41T81REG_CTL 0x08 /* control */
+#define M41T81REG_WD 0x09 /* watchdog */
+#define M41T81REG_AMO 0x0A /* alarm: month */
+#define M41T81REG_ADT 0x0B /* alarm: date */
+#define M41T81REG_AHR 0x0C /* alarm: hour */
+#define M41T81REG_AMN 0x0D /* alarm: minute */
+#define M41T81REG_ASC 0x0E /* alarm: second */
+#define M41T81REG_FLG 0x0F /* flags */
+#define M41T81REG_SQW 0x13 /* square wave register */
+
+#define M41T81_CCR_ADDRESS 0x68
+#define SMB_CSR(reg) ((u8 *) (IOADDR(A_SMB_REGISTER(1, reg))))
+
+static int m41t81_read(uint8_t addr)
+{
+ while (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
+ ;
+
+ bus_writeq(addr & 0xff, SMB_CSR(R_SMB_CMD));
+ bus_writeq((V_SMB_ADDR(M41T81_CCR_ADDRESS) | V_SMB_TT_WR1BYTE),
+ SMB_CSR(R_SMB_START));
+
+ while (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
+ ;
+
+ bus_writeq((V_SMB_ADDR(M41T81_CCR_ADDRESS) | V_SMB_TT_RD1BYTE),
+ SMB_CSR(R_SMB_START));
+
+ while (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
+ ;
+
+ if (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_ERROR) {
+ /* Clear error bit by writing a 1 */
+ bus_writeq(M_SMB_ERROR, SMB_CSR(R_SMB_STATUS));
+ return -1;
+ }
+
+ return (bus_readq(SMB_CSR(R_SMB_DATA)) & 0xff);
+}
+
+static int m41t81_write(uint8_t addr, int b)
+{
+ while (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
+ ;
+
+ bus_writeq((addr & 0xFF), SMB_CSR(R_SMB_CMD));
+ bus_writeq((b & 0xff), SMB_CSR(R_SMB_DATA));
+ bus_writeq(V_SMB_ADDR(M41T81_CCR_ADDRESS) | V_SMB_TT_WR2BYTE,
+ SMB_CSR(R_SMB_START));
+
+ while (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
+ ;
+
+ if (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_ERROR) {
+ /* Clear error bit by writing a 1 */
+ bus_writeq(M_SMB_ERROR, SMB_CSR(R_SMB_STATUS));
+ return -1;
+ }
+
+ /* read the same byte again to make sure it is written */
+ bus_writeq(V_SMB_ADDR(M41T81_CCR_ADDRESS) | V_SMB_TT_RD1BYTE,
+ SMB_CSR(R_SMB_START));
+
+ while (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
+ ;
+
+ return 0;
+}
+
+int m41t81_set_time(unsigned long t)
+{
+ struct rtc_time tm;
+
+ to_tm(t, &tm);
+
+ /*
+ * Note the write order matters as it ensures the correctness.
+ * When we write sec, 10th sec is clear. It is reasonable to
+ * believe we should finish writing min within a second.
+ */
+
+ tm.tm_sec = BIN2BCD(tm.tm_sec);
+ m41t81_write(M41T81REG_SC, tm.tm_sec);
+
+ tm.tm_min = BIN2BCD(tm.tm_min);
+ m41t81_write(M41T81REG_MN, tm.tm_min);
+
+ tm.tm_hour = BIN2BCD(tm.tm_hour);
+ tm.tm_hour = (tm.tm_hour & 0x3f) | (m41t81_read(M41T81REG_HR) & 0xc0);
+ m41t81_write(M41T81REG_HR, tm.tm_hour);
+
+ /* tm_wday starts from 0 to 6 */
+ if (tm.tm_wday == 0) tm.tm_wday = 7;
+ tm.tm_wday = BIN2BCD(tm.tm_wday);
+ m41t81_write(M41T81REG_DY, tm.tm_wday);
+
+ tm.tm_mday = BIN2BCD(tm.tm_mday);
+ m41t81_write(M41T81REG_DT, tm.tm_mday);
+
+ /* tm_mon starts from 0, *ick* */
+ tm.tm_mon ++;
+ tm.tm_mon = BIN2BCD(tm.tm_mon);
+ m41t81_write(M41T81REG_MO, tm.tm_mon);
+
+ /* we don't do century, everything is beyond 2000 */
+ tm.tm_year %= 100;
+ tm.tm_year = BIN2BCD(tm.tm_year);
+ m41t81_write(M41T81REG_YR, tm.tm_year);
+
+ return 0;
+}
+
+unsigned long m41t81_get_time(void)
+{
+ unsigned int year, mon, day, hour, min, sec;
+
+ /*
+ * min is valid if two reads of sec are the same.
+ */
+ for (;;) {
+ sec = m41t81_read(M41T81REG_SC);
+ min = m41t81_read(M41T81REG_MN);
+ if (sec == m41t81_read(M41T81REG_SC)) break;
+ }
+ hour = m41t81_read(M41T81REG_HR) & 0x3f;
+ day = m41t81_read(M41T81REG_DT);
+ mon = m41t81_read(M41T81REG_MO);
+ year = m41t81_read(M41T81REG_YR);
+
+ sec = BCD2BIN(sec);
+ min = BCD2BIN(min);
+ hour = BCD2BIN(hour);
+ day = BCD2BIN(day);
+ mon = BCD2BIN(mon);
+ year = BCD2BIN(year);
+
+ year += 2000;
+
+ return mktime(year, mon, day, hour, min, sec);
+}
+
+int m41t81_probe(void)
+{
+ unsigned int tmp;
+
+ /* enable chip if it is not enabled yet */
+ tmp = m41t81_read(M41T81REG_SC);
+ m41t81_write(M41T81REG_SC, tmp & 0x7f);
+
+ return (m41t81_read(M41T81REG_SC) != -1);
+}
diff --git a/arch/mips/sibyte/swarm/rtc_xicor1241.c b/arch/mips/sibyte/swarm/rtc_xicor1241.c
new file mode 100644
index 0000000..981d21f
--- /dev/null
+++ b/arch/mips/sibyte/swarm/rtc_xicor1241.c
@@ -0,0 +1,203 @@
+/*
+ * Copyright (C) 2000, 2001 Broadcom Corporation
+ *
+ * Copyright (C) 2002 MontaVista Software Inc.
+ * Author: jsun@mvista.com or jsun@junsun.net
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+#include <linux/bcd.h>
+#include <linux/types.h>
+#include <linux/time.h>
+
+#include <asm/time.h>
+#include <asm/addrspace.h>
+#include <asm/io.h>
+
+#include <asm/sibyte/sb1250.h>
+#include <asm/sibyte/sb1250_regs.h>
+#include <asm/sibyte/sb1250_smbus.h>
+
+
+/* Xicor 1241 definitions */
+
+/*
+ * Register bits
+ */
+
+#define X1241REG_SR_BAT 0x80 /* currently on battery power */
+#define X1241REG_SR_RWEL 0x04 /* r/w latch is enabled, can write RTC */
+#define X1241REG_SR_WEL 0x02 /* r/w latch is unlocked, can enable r/w now */
+#define X1241REG_SR_RTCF 0x01 /* clock failed */
+#define X1241REG_BL_BP2 0x80 /* block protect 2 */
+#define X1241REG_BL_BP1 0x40 /* block protect 1 */
+#define X1241REG_BL_BP0 0x20 /* block protect 0 */
+#define X1241REG_BL_WD1 0x10
+#define X1241REG_BL_WD0 0x08
+#define X1241REG_HR_MIL 0x80 /* military time format */
+
+/*
+ * Register numbers
+ */
+
+#define X1241REG_BL 0x10 /* block protect bits */
+#define X1241REG_INT 0x11 /* */
+#define X1241REG_SC 0x30 /* Seconds */
+#define X1241REG_MN 0x31 /* Minutes */
+#define X1241REG_HR 0x32 /* Hours */
+#define X1241REG_DT 0x33 /* Day of month */
+#define X1241REG_MO 0x34 /* Month */
+#define X1241REG_YR 0x35 /* Year */
+#define X1241REG_DW 0x36 /* Day of Week */
+#define X1241REG_Y2K 0x37 /* Year 2K */
+#define X1241REG_SR 0x3F /* Status register */
+
+#define X1241_CCR_ADDRESS 0x6F
+
+#define SMB_CSR(reg) ((u8 *) (IOADDR(A_SMB_REGISTER(1, reg))))
+
+static int xicor_read(uint8_t addr)
+{
+ while (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
+ ;
+
+ bus_writeq((addr >> 8) & 0x7, SMB_CSR(R_SMB_CMD));
+ bus_writeq((addr & 0xff), SMB_CSR(R_SMB_DATA));
+ bus_writeq((V_SMB_ADDR(X1241_CCR_ADDRESS) | V_SMB_TT_WR2BYTE),
+ SMB_CSR(R_SMB_START));
+
+ while (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
+ ;
+
+ bus_writeq((V_SMB_ADDR(X1241_CCR_ADDRESS) | V_SMB_TT_RD1BYTE),
+ SMB_CSR(R_SMB_START));
+
+ while (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
+ ;
+
+ if (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_ERROR) {
+ /* Clear error bit by writing a 1 */
+ bus_writeq(M_SMB_ERROR, SMB_CSR(R_SMB_STATUS));
+ return -1;
+ }
+
+ return (bus_readq(SMB_CSR(R_SMB_DATA)) & 0xff);
+}
+
+static int xicor_write(uint8_t addr, int b)
+{
+ while (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
+ ;
+
+ bus_writeq(addr, SMB_CSR(R_SMB_CMD));
+ bus_writeq((addr & 0xff) | ((b & 0xff) << 8), SMB_CSR(R_SMB_DATA));
+ bus_writeq(V_SMB_ADDR(X1241_CCR_ADDRESS) | V_SMB_TT_WR3BYTE,
+ SMB_CSR(R_SMB_START));
+
+ while (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
+ ;
+
+ if (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_ERROR) {
+ /* Clear error bit by writing a 1 */
+ bus_writeq(M_SMB_ERROR, SMB_CSR(R_SMB_STATUS));
+ return -1;
+ } else {
+ return 0;
+ }
+}
+
+int xicor_set_time(unsigned long t)
+{
+ struct rtc_time tm;
+ int tmp;
+
+ to_tm(t, &tm);
+
+ /* unlock writes to the CCR */
+ xicor_write(X1241REG_SR, X1241REG_SR_WEL);
+ xicor_write(X1241REG_SR, X1241REG_SR_WEL | X1241REG_SR_RWEL);
+
+ /* trivial ones */
+ tm.tm_sec = BIN2BCD(tm.tm_sec);
+ xicor_write(X1241REG_SC, tm.tm_sec);
+
+ tm.tm_min = BIN2BCD(tm.tm_min);
+ xicor_write(X1241REG_MN, tm.tm_min);
+
+ tm.tm_mday = BIN2BCD(tm.tm_mday);
+ xicor_write(X1241REG_DT, tm.tm_mday);
+
+ /* tm_mon starts from 0, *ick* */
+ tm.tm_mon ++;
+ tm.tm_mon = BIN2BCD(tm.tm_mon);
+ xicor_write(X1241REG_MO, tm.tm_mon);
+
+ /* year is split */
+ tmp = tm.tm_year / 100;
+ tm.tm_year %= 100;
+ xicor_write(X1241REG_YR, tm.tm_year);
+ xicor_write(X1241REG_Y2K, tmp);
+
+ /* hour is the most tricky one */
+ tmp = xicor_read(X1241REG_HR);
+ if (tmp & X1241REG_HR_MIL) {
+ /* 24 hour format */
+ tm.tm_hour = BIN2BCD(tm.tm_hour);
+ tmp = (tmp & ~0x3f) | (tm.tm_hour & 0x3f);
+ } else {
+ /* 12 hour format, with 0x2 for pm */
+ tmp = tmp & ~0x3f;
+ if (tm.tm_hour >= 12) {
+ tmp |= 0x20;
+ tm.tm_hour -= 12;
+ }
+ tm.tm_hour = BIN2BCD(tm.tm_hour);
+ tmp |= tm.tm_hour;
+ }
+ xicor_write(X1241REG_HR, tmp);
+
+ xicor_write(X1241REG_SR, 0);
+
+ return 0;
+}
+
+unsigned long xicor_get_time(void)
+{
+ unsigned int year, mon, day, hour, min, sec, y2k;
+
+ sec = xicor_read(X1241REG_SC);
+ min = xicor_read(X1241REG_MN);
+ hour = xicor_read(X1241REG_HR);
+
+ if (hour & X1241REG_HR_MIL) {
+ hour &= 0x3f;
+ } else {
+ if (hour & 0x20)
+ hour = (hour & 0xf) + 0x12;
+ }
+
+ day = xicor_read(X1241REG_DT);
+ mon = xicor_read(X1241REG_MO);
+ year = xicor_read(X1241REG_YR);
+ y2k = xicor_read(X1241REG_Y2K);
+
+ sec = BCD2BIN(sec);
+ min = BCD2BIN(min);
+ hour = BCD2BIN(hour);
+ day = BCD2BIN(day);
+ mon = BCD2BIN(mon);
+ year = BCD2BIN(year);
+ y2k = BCD2BIN(y2k);
+
+ year += (y2k * 100);
+
+ return mktime(year, mon, day, hour, min, sec);
+}
+
+int xicor_probe(void)
+{
+ return (xicor_read(X1241REG_SC) != -1);
+}
diff --git a/arch/mips/sibyte/swarm/setup.c b/arch/mips/sibyte/swarm/setup.c
new file mode 100644
index 0000000..457aeb7
--- /dev/null
+++ b/arch/mips/sibyte/swarm/setup.c
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2000, 2001, 2002, 2003 Broadcom Corporation
+ * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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 code for the SWARM board
+ */
+
+#include <linux/config.h>
+#include <linux/spinlock.h>
+#include <linux/mm.h>
+#include <linux/bootmem.h>
+#include <linux/blkdev.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/tty.h>
+#include <linux/initrd.h>
+
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/bootinfo.h>
+#include <asm/mipsregs.h>
+#include <asm/reboot.h>
+#include <asm/time.h>
+#include <asm/traps.h>
+#include <asm/sibyte/sb1250.h>
+#include <asm/sibyte/sb1250_regs.h>
+#include <asm/sibyte/sb1250_genbus.h>
+#include <asm/sibyte/board.h>
+
+extern void sb1250_setup(void);
+
+extern int xicor_probe(void);
+extern int xicor_set_time(unsigned long);
+extern unsigned long xicor_get_time(void);
+
+extern int m41t81_probe(void);
+extern int m41t81_set_time(unsigned long);
+extern unsigned long m41t81_get_time(void);
+
+const char *get_system_type(void)
+{
+ return "SiByte " SIBYTE_BOARD_NAME;
+}
+
+void __init swarm_timer_setup(struct irqaction *irq)
+{
+ /*
+ * we don't set up irqaction, because we will deliver timer
+ * interrupts through low-level (direct) meachanism.
+ */
+
+ /* We only need to setup the generic timer */
+ sb1250_time_init();
+}
+
+int swarm_be_handler(struct pt_regs *regs, int is_fixup)
+{
+ if (!is_fixup && (regs->cp0_cause & 4)) {
+ /* Data bus error - print PA */
+#ifdef CONFIG_MIPS64
+ printk("DBE physical address: %010lx\n",
+ __read_64bit_c0_register($26, 1));
+#else
+ printk("DBE physical address: %010llx\n",
+ __read_64bit_c0_split($26, 1));
+#endif
+ }
+ return (is_fixup ? MIPS_BE_FIXUP : MIPS_BE_FATAL);
+}
+
+static int __init swarm_setup(void)
+{
+ sb1250_setup();
+
+ panic_timeout = 5; /* For debug. */
+
+ board_timer_setup = swarm_timer_setup;
+ board_be_handler = swarm_be_handler;
+
+ if (xicor_probe()) {
+ printk("swarm setup: Xicor 1241 RTC detected.\n");
+ rtc_get_time = xicor_get_time;
+ rtc_set_time = xicor_set_time;
+ }
+
+ if (m41t81_probe()) {
+ printk("swarm setup: M41T81 RTC detected.\n");
+ rtc_get_time = m41t81_get_time;
+ rtc_set_time = m41t81_set_time;
+ }
+
+ printk("This kernel optimized for "
+#ifdef CONFIG_SIMULATION
+ "simulation"
+#else
+ "board"
+#endif
+ " runs "
+#ifdef CONFIG_SIBYTE_CFE
+ "with"
+#else
+ "without"
+#endif
+ " CFE\n");
+
+#ifdef CONFIG_VT
+ screen_info = (struct screen_info) {
+ 0, 0, /* orig-x, orig-y */
+ 0, /* unused */
+ 52, /* orig_video_page */
+ 3, /* orig_video_mode */
+ 80, /* orig_video_cols */
+ 4626, 3, 9, /* unused, ega_bx, unused */
+ 25, /* orig_video_lines */
+ 0x22, /* orig_video_isVGA */
+ 16 /* orig_video_points */
+ };
+ /* XXXKW for CFE, get lines/cols from environment */
+#endif
+
+ return 0;
+}
+
+early_initcall(swarm_setup);
+
+#ifdef LEDS_PHYS
+
+#ifdef CONFIG_SIBYTE_CARMEL
+/* XXXKW need to detect Monterey/LittleSur/etc */
+#undef LEDS_PHYS
+#define LEDS_PHYS MLEDS_PHYS
+#endif
+
+#define setled(index, c) \
+ ((unsigned char *)(IOADDR(LEDS_PHYS)+0x20))[(3-(index))<<3] = (c)
+void setleds(char *str)
+{
+ int i;
+ for (i = 0; i < 4; i++) {
+ if (!str[i]) {
+ setled(i, ' ');
+ } else {
+ setled(i, str[i]);
+ }
+ }
+}
+#endif
diff --git a/arch/mips/sibyte/swarm/time.c b/arch/mips/sibyte/swarm/time.c
new file mode 100644
index 0000000..c1f1a9de
--- /dev/null
+++ b/arch/mips/sibyte/swarm/time.c
@@ -0,0 +1,244 @@
+/*
+ * Copyright (C) 2000, 2001 Broadcom Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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.
+ */
+
+/*
+ * Time routines for the swarm board. We pass all the hard stuff
+ * through to the sb1250 handling code. Only thing we really keep
+ * track of here is what time of day we think it is. And we don't
+ * really even do a good job of that...
+ */
+
+
+#include <linux/bcd.h>
+#include <linux/init.h>
+#include <linux/time.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <asm/system.h>
+#include <asm/addrspace.h>
+#include <asm/io.h>
+
+#include <asm/sibyte/sb1250.h>
+#include <asm/sibyte/sb1250_regs.h>
+#include <asm/sibyte/sb1250_smbus.h>
+
+static unsigned long long sec_bias = 0;
+static unsigned int usec_bias = 0;
+
+/* Xicor 1241 definitions */
+
+/*
+ * Register bits
+ */
+
+#define X1241REG_SR_BAT 0x80 /* currently on battery power */
+#define X1241REG_SR_RWEL 0x04 /* r/w latch is enabled, can write RTC */
+#define X1241REG_SR_WEL 0x02 /* r/w latch is unlocked, can enable r/w now */
+#define X1241REG_SR_RTCF 0x01 /* clock failed */
+#define X1241REG_BL_BP2 0x80 /* block protect 2 */
+#define X1241REG_BL_BP1 0x40 /* block protect 1 */
+#define X1241REG_BL_BP0 0x20 /* block protect 0 */
+#define X1241REG_BL_WD1 0x10
+#define X1241REG_BL_WD0 0x08
+#define X1241REG_HR_MIL 0x80 /* military time format */
+
+/*
+ * Register numbers
+ */
+
+#define X1241REG_BL 0x10 /* block protect bits */
+#define X1241REG_INT 0x11 /* */
+#define X1241REG_SC 0x30 /* Seconds */
+#define X1241REG_MN 0x31 /* Minutes */
+#define X1241REG_HR 0x32 /* Hours */
+#define X1241REG_DT 0x33 /* Day of month */
+#define X1241REG_MO 0x34 /* Month */
+#define X1241REG_YR 0x35 /* Year */
+#define X1241REG_DW 0x36 /* Day of Week */
+#define X1241REG_Y2K 0x37 /* Year 2K */
+#define X1241REG_SR 0x3F /* Status register */
+
+#define X1241_CCR_ADDRESS 0x6F
+
+#define SMB_CSR(reg) (IOADDR(A_SMB_REGISTER(1, reg)))
+
+static int xicor_read(uint8_t addr)
+{
+ while (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
+ ;
+
+ bus_writeq((addr >> 8) & 0x7, SMB_CSR(R_SMB_CMD));
+ bus_writeq((addr & 0xff), SMB_CSR(R_SMB_DATA));
+ bus_writeq((V_SMB_ADDR(X1241_CCR_ADDRESS) | V_SMB_TT_WR2BYTE),
+ SMB_CSR(R_SMB_START));
+
+ while (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
+ ;
+
+ bus_writeq((V_SMB_ADDR(X1241_CCR_ADDRESS) | V_SMB_TT_RD1BYTE),
+ SMB_CSR(R_SMB_START));
+
+ while (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
+ ;
+
+ if (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_ERROR) {
+ /* Clear error bit by writing a 1 */
+ bus_writeq(M_SMB_ERROR, SMB_CSR(R_SMB_STATUS));
+ return -1;
+ }
+
+ return (bus_readq(SMB_CSR(R_SMB_DATA)) & 0xff);
+}
+
+static int xicor_write(uint8_t addr, int b)
+{
+ while (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
+ ;
+
+ bus_writeq(addr, SMB_CSR(R_SMB_CMD));
+ bus_writeq((addr & 0xff) | ((b & 0xff) << 8), SMB_CSR(R_SMB_DATA));
+ bus_writeq(V_SMB_ADDR(X1241_CCR_ADDRESS) | V_SMB_TT_WR3BYTE,
+ SMB_CSR(R_SMB_START));
+
+ while (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
+ ;
+
+ if (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_ERROR) {
+ /* Clear error bit by writing a 1 */
+ bus_writeq(M_SMB_ERROR, SMB_CSR(R_SMB_STATUS));
+ return -1;
+ } else {
+ return 0;
+ }
+}
+
+/*
+ * In order to set the CMOS clock precisely, set_rtc_mmss has to be
+ * called 500 ms after the second nowtime has started, because when
+ * nowtime is written into the registers of the CMOS clock, it will
+ * jump to the next second precisely 500 ms later. Check the Motorola
+ * MC146818A or Dallas DS12887 data sheet for details.
+ *
+ * BUG: This routine does not handle hour overflow properly; it just
+ * sets the minutes. Usually you'll only notice that after reboot!
+ */
+int set_rtc_mmss(unsigned long nowtime)
+{
+ int retval = 0;
+ int real_seconds, real_minutes, cmos_minutes;
+
+ cmos_minutes = xicor_read(X1241REG_MN);
+ cmos_minutes = BCD2BIN(cmos_minutes);
+
+ /*
+ * since we're only adjusting minutes and seconds,
+ * don't interfere with hour overflow. This avoids
+ * messing with unknown time zones but requires your
+ * RTC not to be off by more than 15 minutes
+ */
+ real_seconds = nowtime % 60;
+ real_minutes = nowtime / 60;
+ if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1)
+ real_minutes += 30; /* correct for half hour time zone */
+ real_minutes %= 60;
+
+ /* unlock writes to the CCR */
+ xicor_write(X1241REG_SR, X1241REG_SR_WEL);
+ xicor_write(X1241REG_SR, X1241REG_SR_WEL | X1241REG_SR_RWEL);
+
+ if (abs(real_minutes - cmos_minutes) < 30) {
+ real_seconds = BIN2BCD(real_seconds);
+ real_minutes = BIN2BCD(real_minutes);
+ xicor_write(X1241REG_SC, real_seconds);
+ xicor_write(X1241REG_MN, real_minutes);
+ } else {
+ printk(KERN_WARNING
+ "set_rtc_mmss: can't update from %d to %d\n",
+ cmos_minutes, real_minutes);
+ retval = -1;
+ }
+
+ xicor_write(X1241REG_SR, 0);
+
+ printk("set_rtc_mmss: %02d:%02d\n", real_minutes, real_seconds);
+
+ return retval;
+}
+
+static unsigned long __init get_swarm_time(void)
+{
+ unsigned int year, mon, day, hour, min, sec, y2k;
+
+ sec = xicor_read(X1241REG_SC);
+ min = xicor_read(X1241REG_MN);
+ hour = xicor_read(X1241REG_HR);
+
+ if (hour & X1241REG_HR_MIL) {
+ hour &= 0x3f;
+ } else {
+ if (hour & 0x20)
+ hour = (hour & 0xf) + 0x12;
+ }
+
+ sec = BCD2BIN(sec);
+ min = BCD2BIN(min);
+ hour = BCD2BIN(hour);
+
+ day = xicor_read(X1241REG_DT);
+ mon = xicor_read(X1241REG_MO);
+ year = xicor_read(X1241REG_YR);
+ y2k = xicor_read(X1241REG_Y2K);
+
+ day = BCD2BIN(day);
+ mon = BCD2BIN(mon);
+ year = BCD2BIN(year);
+ y2k = BCD2BIN(y2k);
+
+ year += (y2k * 100);
+
+ return mktime(year, mon, day, hour, min, sec);
+}
+
+/*
+ * Bring up the timer at 100 Hz.
+ */
+void __init swarm_time_init(void)
+{
+ unsigned int flags;
+ int status;
+
+ /* Set up the scd general purpose timer 0 to cpu 0 */
+ sb1250_time_init();
+
+ /* Establish communication with the Xicor 1241 RTC */
+ /* XXXKW how do I share the SMBus with the I2C subsystem? */
+
+ bus_writeq(K_SMB_FREQ_400KHZ, SMB_CSR(R_SMB_FREQ));
+ bus_writeq(0, SMB_CSR(R_SMB_CONTROL));
+
+ if ((status = xicor_read(X1241REG_SR_RTCF)) < 0) {
+ printk("x1241: couldn't detect on SWARM SMBus 1\n");
+ } else {
+ if (status & X1241REG_SR_RTCF)
+ printk("x1241: battery failed -- time is probably wrong\n");
+ write_seqlock_irqsave(&xtime_lock, flags);
+ xtime.tv_sec = get_swarm_time();
+ xtime.tv_nsec = 0;
+ write_sequnlock_irqrestore(&xtime_lock, flags);
+ }
+}
diff --git a/arch/mips/sni/Makefile b/arch/mips/sni/Makefile
new file mode 100644
index 0000000..1e5676e
--- /dev/null
+++ b/arch/mips/sni/Makefile
@@ -0,0 +1,7 @@
+#
+# Makefile for the SNI specific part of the kernel
+#
+
+obj-y += int-handler.o irq.o pcimt_scache.o reset.o setup.o
+
+EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/sni/int-handler.S b/arch/mips/sni/int-handler.S
new file mode 100644
index 0000000..2cdc09f
--- /dev/null
+++ b/arch/mips/sni/int-handler.S
@@ -0,0 +1,106 @@
+/*
+ * SNI RM200 PCI specific interrupt handler code.
+ *
+ * Copyright (C) 1994, 95, 96, 97, 98, 1999, 2000, 01 by Ralf Baechle
+ */
+#include <asm/asm.h>
+#include <asm/mipsregs.h>
+#include <asm/regdef.h>
+#include <asm/sni.h>
+#include <asm/stackframe.h>
+
+/*
+ * The PCI ASIC has the nasty property that it may delay writes if it is busy.
+ * As a consequence from writes that have not graduated when we exit from the
+ * interrupt handler we might catch a spurious interrupt. To avoid this we
+ * force the PCI ASIC to graduate all writes by executing a read from the
+ * PCI bus.
+ */
+ .set noreorder
+ .set noat
+ .align 5
+ NESTED(sni_rm200_pci_handle_int, PT_SIZE, sp)
+ SAVE_ALL
+ CLI
+ .set at
+
+ /* Blinken light ... */
+ lb t0, led_cache
+ addiu t0, 1
+ sb t0, led_cache
+ sb t0, PCIMT_CSLED # write only register
+ .data
+led_cache: .byte 0
+ .text
+
+ mfc0 t0, CP0_STATUS
+ mfc0 t1, CP0_CAUSE
+ and t0, t1
+
+ andi t1, t0, 0x0800 # hardware interrupt 1
+ bnez t1, _hwint1
+ andi t1, t0, 0x4000 # hardware interrupt 4
+ bnez t1, _hwint4
+ andi t1, t0, 0x2000 # hardware interrupt 3
+ bnez t1, _hwint3
+ andi t1, t0, 0x1000 # hardware interrupt 2
+ bnez t1, _hwint2
+ andi t1, t0, 0x8000 # hardware interrupt 5
+ bnez t1, _hwint5
+ andi t1, t0, 0x0400 # hardware interrupt 0
+ bnez t1, _hwint0
+ nop
+
+ j restore_all # spurious interrupt
+ nop
+
+ ##############################################################################
+
+/* hwint0 should deal with MP agent, ASIC PCI, EISA NMI and debug
+ button interrupts. */
+_hwint0: jal pciasic_hwint0
+ move a0, sp
+ j ret_from_irq
+ nop
+
+/*
+ * hwint 1 deals with EISA and SCSI interrupts
+ */
+_hwint1: jal pciasic_hwint1
+ move a0, sp
+ j ret_from_irq
+ nop
+
+
+/*
+ * This interrupt was used for the com1 console on the first prototypes;
+ * it's unsed otherwise
+ */
+_hwint2: jal pciasic_hwint2
+ move a0, sp
+ j ret_from_irq
+ nop
+
+/*
+ * hwint 3 are the PCI interrupts A - D
+ */
+_hwint3: jal pciasic_hwint3
+ move a0, sp
+ j ret_from_irq
+ nop
+
+/*
+ * hwint 4 is used for only the onboard PCnet 32.
+ */
+_hwint4: jal pciasic_hwint4
+ move a0, sp
+ j ret_from_irq
+ nop
+
+/* hwint5 is the r4k count / compare interrupt */
+_hwint5: jal pciasic_hwint5
+ move a0, sp
+ j ret_from_irq
+ nop
+
+ END(sni_rm200_pci_handle_int)
diff --git a/arch/mips/sni/irq.c b/arch/mips/sni/irq.c
new file mode 100644
index 0000000..62c760f
--- /dev/null
+++ b/arch/mips/sni/irq.c
@@ -0,0 +1,194 @@
+/*
+ * 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) 1992 Linus Torvalds
+ * Copyright (C) 1994 - 2000 Ralf Baechle
+ */
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+
+#include <asm/i8259.h>
+#include <asm/io.h>
+#include <asm/sni.h>
+
+DEFINE_SPINLOCK(pciasic_lock);
+
+extern asmlinkage void sni_rm200_pci_handle_int(void);
+
+static void enable_pciasic_irq(unsigned int irq)
+{
+ unsigned int mask = 1 << (irq - PCIMT_IRQ_INT2);
+ unsigned long flags;
+
+ spin_lock_irqsave(&pciasic_lock, flags);
+ *(volatile u8 *) PCIMT_IRQSEL |= mask;
+ spin_unlock_irqrestore(&pciasic_lock, flags);
+}
+
+static unsigned int startup_pciasic_irq(unsigned int irq)
+{
+ enable_pciasic_irq(irq);
+ return 0; /* never anything pending */
+}
+
+#define shutdown_pciasic_irq disable_pciasic_irq
+
+void disable_pciasic_irq(unsigned int irq)
+{
+ unsigned int mask = ~(1 << (irq - PCIMT_IRQ_INT2));
+ unsigned long flags;
+
+ spin_lock_irqsave(&pciasic_lock, flags);
+ *(volatile u8 *) PCIMT_IRQSEL &= mask;
+ spin_unlock_irqrestore(&pciasic_lock, flags);
+}
+
+#define mask_and_ack_pciasic_irq disable_pciasic_irq
+
+static void end_pciasic_irq(unsigned int irq)
+{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+ enable_pciasic_irq(irq);
+}
+
+static struct hw_interrupt_type pciasic_irq_type = {
+ "ASIC-PCI",
+ startup_pciasic_irq,
+ shutdown_pciasic_irq,
+ enable_pciasic_irq,
+ disable_pciasic_irq,
+ mask_and_ack_pciasic_irq,
+ end_pciasic_irq,
+ NULL
+};
+
+/*
+ * hwint0 should deal with MP agent, ASIC PCI, EISA NMI and debug
+ * button interrupts. Later ...
+ */
+void pciasic_hwint0(struct pt_regs *regs)
+{
+ panic("Received int0 but no handler yet ...");
+}
+
+/* This interrupt was used for the com1 console on the first prototypes. */
+void pciasic_hwint2(struct pt_regs *regs)
+{
+ /* I think this shouldn't happen on production machines. */
+ panic("hwint2 and no handler yet");
+}
+
+/* hwint5 is the r4k count / compare interrupt */
+void pciasic_hwint5(struct pt_regs *regs)
+{
+ panic("hwint5 and no handler yet");
+}
+
+static unsigned int ls1bit8(unsigned int x)
+{
+ int b = 7, s;
+
+ s = 4; if ((x & 0x0f) == 0) s = 0; b -= s; x <<= s;
+ s = 2; if ((x & 0x30) == 0) s = 0; b -= s; x <<= s;
+ s = 1; if ((x & 0x40) == 0) s = 0; b -= s;
+
+ return b;
+}
+
+/*
+ * hwint 1 deals with EISA and SCSI interrupts,
+ *
+ * The EISA_INT bit in CSITPEND is high active, all others are low active.
+ */
+void pciasic_hwint1(struct pt_regs *regs)
+{
+ u8 pend = *(volatile char *)PCIMT_CSITPEND;
+ unsigned long flags;
+
+ if (pend & IT_EISA) {
+ int irq;
+ /*
+ * Note: ASIC PCI's builtin interrupt achknowledge feature is
+ * broken. Using it may result in loss of some or all i8259
+ * interupts, so don't use PCIMT_INT_ACKNOWLEDGE ...
+ */
+ irq = i8259_irq();
+ if (unlikely(irq < 0))
+ return;
+
+ do_IRQ(irq, regs);
+ }
+
+ if (!(pend & IT_SCSI)) {
+ flags = read_c0_status();
+ clear_c0_status(ST0_IM);
+ do_IRQ(PCIMT_IRQ_SCSI, regs);
+ write_c0_status(flags);
+ }
+}
+
+/*
+ * hwint 3 should deal with the PCI A - D interrupts,
+ */
+void pciasic_hwint3(struct pt_regs *regs)
+{
+ u8 pend = *(volatile char *)PCIMT_CSITPEND;
+ int irq;
+
+ pend &= (IT_INTA | IT_INTB | IT_INTC | IT_INTD);
+ clear_c0_status(IE_IRQ3);
+ irq = PCIMT_IRQ_INT2 + ls1bit8(pend);
+ do_IRQ(irq, regs);
+ set_c0_status(IE_IRQ3);
+}
+
+/*
+ * hwint 4 is used for only the onboard PCnet 32.
+ */
+void pciasic_hwint4(struct pt_regs *regs)
+{
+ clear_c0_status(IE_IRQ4);
+ do_IRQ(PCIMT_IRQ_ETHERNET, regs);
+ set_c0_status(IE_IRQ4);
+}
+
+void __init init_pciasic(void)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&pciasic_lock, flags);
+ * (volatile u8 *) PCIMT_IRQSEL =
+ IT_EISA | IT_INTA | IT_INTB | IT_INTC | IT_INTD;
+ spin_unlock_irqrestore(&pciasic_lock, flags);
+}
+
+/*
+ * On systems with i8259-style interrupt controllers we assume for
+ * driver compatibility reasons interrupts 0 - 15 to be the i8295
+ * interrupts even if the hardware uses a different interrupt numbering.
+ */
+void __init arch_init_irq(void)
+{
+ int i;
+
+ set_except_vector(0, sni_rm200_pci_handle_int);
+
+ init_i8259_irqs(); /* Integrated i8259 */
+ init_pciasic();
+
+ /* Actually we've got more interrupts to handle ... */
+ for (i = PCIMT_IRQ_INT2; i <= PCIMT_IRQ_ETHERNET; i++) {
+ irq_desc[i].status = IRQ_DISABLED;
+ irq_desc[i].action = 0;
+ irq_desc[i].depth = 1;
+ irq_desc[i].handler = &pciasic_irq_type;
+ }
+
+ change_c0_status(ST0_IM, IE_IRQ1|IE_IRQ2|IE_IRQ3|IE_IRQ4);
+}
diff --git a/arch/mips/sni/pcimt_scache.c b/arch/mips/sni/pcimt_scache.c
new file mode 100644
index 0000000..a59d457
--- /dev/null
+++ b/arch/mips/sni/pcimt_scache.c
@@ -0,0 +1,37 @@
+/*
+ * arch/mips/sni/pcimt_scache.c
+ *
+ * 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) 1997, 1998 by Ralf Baechle
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <asm/bcache.h>
+#include <asm/sni.h>
+
+#define cacheconf (*(volatile unsigned int *)PCIMT_CACHECONF)
+#define invspace (*(volatile unsigned int *)PCIMT_INVSPACE)
+
+void __init sni_pcimt_sc_init(void)
+{
+ unsigned int scsiz, sc_size;
+
+ scsiz = cacheconf & 7;
+ if (scsiz == 0) {
+ printk("Second level cache is deactived.\n");
+ return;
+ }
+ if (scsiz >= 6) {
+ printk("Invalid second level cache size configured, "
+ "deactivating second level cache.\n");
+ cacheconf = 0;
+ return;
+ }
+
+ sc_size = 128 << scsiz;
+ printk("%dkb second level cache detected, deactivating.\n", sc_size);
+ cacheconf = 0;
+}
diff --git a/arch/mips/sni/reset.c b/arch/mips/sni/reset.c
new file mode 100644
index 0000000..be85bec
--- /dev/null
+++ b/arch/mips/sni/reset.c
@@ -0,0 +1,51 @@
+/*
+ * linux/arch/mips/sni/process.c
+ *
+ * Reset a SNI machine.
+ */
+#include <asm/io.h>
+#include <asm/reboot.h>
+#include <asm/system.h>
+#include <asm/sni.h>
+
+/*
+ * This routine reboots the machine by asking the keyboard
+ * controller to pulse the reset-line low. We try that for a while,
+ * and if it doesn't work, we do some other stupid things.
+ */
+static inline void
+kb_wait(void)
+{
+ int i;
+
+ for (i=0; i<0x10000; i++)
+ if ((inb_p(0x64) & 0x02) == 0)
+ break;
+}
+
+/* XXX This ends up at the ARC firmware prompt ... */
+void sni_machine_restart(char *command)
+{
+ int i, j;
+
+ /* This does a normal via the keyboard controller like a PC.
+ We can do that easier ... */
+ local_irq_disable();
+ for (;;) {
+ for (i=0; i<100; i++) {
+ kb_wait();
+ for(j = 0; j < 100000 ; j++)
+ /* nothing */;
+ outb_p(0xfe,0x64); /* pulse reset low */
+ }
+ }
+}
+
+void sni_machine_halt(void)
+{
+}
+
+void sni_machine_power_off(void)
+{
+ *(volatile unsigned char *)PCIMT_CSWCSM = 0xfd;
+}
diff --git a/arch/mips/sni/setup.c b/arch/mips/sni/setup.c
new file mode 100644
index 0000000..8f67cee
--- /dev/null
+++ b/arch/mips/sni/setup.c
@@ -0,0 +1,203 @@
+/*
+ * Setup pointers to hardware-dependent routines.
+ *
+ * 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) 1996, 97, 98, 2000, 03, 04 Ralf Baechle (ralf@linux-mips.org)
+ */
+#include <linux/config.h>
+#include <linux/eisa.h>
+#include <linux/hdreg.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/mc146818rtc.h>
+#include <linux/pci.h>
+#include <linux/console.h>
+#include <linux/fb.h>
+#include <linux/tty.h>
+
+#include <asm/arc/types.h>
+#include <asm/sgialib.h>
+#include <asm/bcache.h>
+#include <asm/bootinfo.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mc146818-time.h>
+#include <asm/processor.h>
+#include <asm/ptrace.h>
+#include <asm/reboot.h>
+#include <asm/sni.h>
+#include <asm/time.h>
+#include <asm/traps.h>
+
+extern void sni_machine_restart(char *command);
+extern void sni_machine_halt(void);
+extern void sni_machine_power_off(void);
+
+static void __init sni_rm200_pci_timer_setup(struct irqaction *irq)
+{
+ /* set the clock to 100 Hz */
+ outb_p(0x34,0x43); /* binary, mode 2, LSB/MSB, ch 0 */
+ outb_p(LATCH & 0xff , 0x40); /* LSB */
+ outb(LATCH >> 8 , 0x40); /* MSB */
+ setup_irq(0, irq);
+}
+
+/*
+ * A bit more gossip about the iron we're running on ...
+ */
+static inline void sni_pcimt_detect(void)
+{
+ char boardtype[80];
+ unsigned char csmsr;
+ char *p = boardtype;
+ unsigned int asic;
+
+ csmsr = *(volatile unsigned char *)PCIMT_CSMSR;
+
+ p += sprintf(p, "%s PCI", (csmsr & 0x80) ? "RM200" : "RM300");
+ if ((csmsr & 0x80) == 0)
+ p += sprintf(p, ", board revision %s",
+ (csmsr & 0x20) ? "D" : "C");
+ asic = csmsr & 0x80;
+ asic = (csmsr & 0x08) ? asic : !asic;
+ p += sprintf(p, ", ASIC PCI Rev %s", asic ? "1.0" : "1.1");
+ printk("%s.\n", boardtype);
+}
+
+static void __init sni_display_setup(void)
+{
+#ifdef CONFIG_VT
+#if defined(CONFIG_VGA_CONSOLE)
+ struct screen_info *si = &screen_info;
+ DISPLAY_STATUS *di;
+
+ di = ArcGetDisplayStatus(1);
+
+ if (di) {
+ si->orig_x = di->CursorXPosition;
+ si->orig_y = di->CursorYPosition;
+ si->orig_video_cols = di->CursorMaxXPosition;
+ si->orig_video_lines = di->CursorMaxYPosition;
+ si->orig_video_isVGA = VIDEO_TYPE_VGAC;
+ si->orig_video_points = 16;
+ }
+#endif
+#endif
+}
+
+static struct resource sni_io_resource = {
+ "PCIMT IO MEM", 0x00001000UL, 0x03bfffffUL, IORESOURCE_IO,
+};
+
+static struct resource pcimt_io_resources[] = {
+ { "dma1", 0x00, 0x1f, IORESOURCE_BUSY },
+ { "timer", 0x40, 0x5f, IORESOURCE_BUSY },
+ { "keyboard", 0x60, 0x6f, IORESOURCE_BUSY },
+ { "dma page reg", 0x80, 0x8f, IORESOURCE_BUSY },
+ { "dma2", 0xc0, 0xdf, IORESOURCE_BUSY },
+ { "PCI config data", 0xcfc, 0xcff, IORESOURCE_BUSY }
+};
+
+static struct resource sni_mem_resource = {
+ "PCIMT PCI MEM", 0x10000000UL, 0xffffffffUL, IORESOURCE_MEM
+};
+
+/*
+ * The RM200/RM300 has a few holes in it's PCI/EISA memory address space used
+ * for other purposes. Be paranoid and allocate all of the before the PCI
+ * code gets a chance to to map anything else there ...
+ *
+ * This leaves the following areas available:
+ *
+ * 0x10000000 - 0x1009ffff (640kB) PCI/EISA/ISA Bus Memory
+ * 0x10100000 - 0x13ffffff ( 15MB) PCI/EISA/ISA Bus Memory
+ * 0x18000000 - 0x1fbfffff (124MB) PCI/EISA Bus Memory
+ * 0x1ff08000 - 0x1ffeffff (816kB) PCI/EISA Bus Memory
+ * 0xa0000000 - 0xffffffff (1.5GB) PCI/EISA Bus Memory
+ */
+static struct resource pcimt_mem_resources[] = {
+ { "Video RAM area", 0x100a0000, 0x100bffff, IORESOURCE_BUSY },
+ { "ISA Reserved", 0x100c0000, 0x100fffff, IORESOURCE_BUSY },
+ { "PCI IO", 0x14000000, 0x17bfffff, IORESOURCE_BUSY },
+ { "Cache Replacement Area", 0x17c00000, 0x17ffffff, IORESOURCE_BUSY},
+ { "PCI INT Acknowledge", 0x1a000000, 0x1a000003, IORESOURCE_BUSY },
+ { "Boot PROM", 0x1fc00000, 0x1fc7ffff, IORESOURCE_BUSY},
+ { "Diag PROM", 0x1fc80000, 0x1fcfffff, IORESOURCE_BUSY},
+ { "X-Bus", 0x1fd00000, 0x1fdfffff, IORESOURCE_BUSY},
+ { "BIOS map", 0x1fe00000, 0x1fefffff, IORESOURCE_BUSY},
+ { "NVRAM / EEPROM", 0x1ff00000, 0x1ff7ffff, IORESOURCE_BUSY},
+ { "ASIC PCI", 0x1fff0000, 0x1fffefff, IORESOURCE_BUSY},
+ { "MP Agent", 0x1ffff000, 0x1fffffff, IORESOURCE_BUSY},
+ { "Main Memory", 0x20000000, 0x9fffffff, IORESOURCE_BUSY}
+};
+
+static void __init sni_resource_init(void)
+{
+ int i;
+
+ /* request I/O space for devices used on all i[345]86 PCs */
+ for (i = 0; i < ARRAY_SIZE(pcimt_io_resources); i++)
+ request_resource(&ioport_resource, pcimt_io_resources + i);
+
+ /* request mem space for pcimt-specific devices */
+ for (i = 0; i < ARRAY_SIZE(pcimt_mem_resources); i++)
+ request_resource(&sni_mem_resource, pcimt_mem_resources + i);
+
+ ioport_resource.end = sni_io_resource.end;
+}
+
+extern struct pci_ops sni_pci_ops;
+
+static struct pci_controller sni_controller = {
+ .pci_ops = &sni_pci_ops,
+ .mem_resource = &sni_mem_resource,
+ .mem_offset = 0x10000000UL,
+ .io_resource = &sni_io_resource,
+ .io_offset = 0x00000000UL
+};
+
+static inline void sni_pcimt_time_init(void)
+{
+ rtc_get_time = mc146818_get_cmos_time;
+ rtc_set_time = mc146818_set_rtc_mmss;
+}
+
+static int __init sni_rm200_pci_setup(void)
+{
+ sni_pcimt_detect();
+ sni_pcimt_sc_init();
+ sni_pcimt_time_init();
+
+ set_io_port_base(SNI_PORT_BASE);
+ ioport_resource.end = sni_io_resource.end;
+
+ /*
+ * Setup (E)ISA I/O memory access stuff
+ */
+ isa_slot_offset = 0xb0000000;
+#ifdef CONFIG_EISA
+ EISA_bus = 1;
+#endif
+
+ sni_resource_init();
+ board_timer_setup = sni_rm200_pci_timer_setup;
+
+ _machine_restart = sni_machine_restart;
+ _machine_halt = sni_machine_halt;
+ _machine_power_off = sni_machine_power_off;
+
+ sni_display_setup();
+
+#ifdef CONFIG_PCI
+ register_pci_controller(&sni_controller);
+#endif
+
+ return 0;
+}
+
+early_initcall(sni_rm200_pci_setup);
diff --git a/arch/mips/tx4927/common/Makefile b/arch/mips/tx4927/common/Makefile
new file mode 100644
index 0000000..8fa126b
--- /dev/null
+++ b/arch/mips/tx4927/common/Makefile
@@ -0,0 +1,12 @@
+#
+# Makefile for common code for Toshiba TX4927 based systems
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+
+obj-y += tx4927_prom.o tx4927_setup.o tx4927_irq.o tx4927_irq_handler.o
+
+obj-$(CONFIG_TOSHIBA_FPCIB0) += smsc_fdc37m81x.o
+obj-$(CONFIG_KGDB) += tx4927_dbgio.o
diff --git a/arch/mips/tx4927/common/tx4927_dbgio.c b/arch/mips/tx4927/common/tx4927_dbgio.c
new file mode 100644
index 0000000..09bdf2b
--- /dev/null
+++ b/arch/mips/tx4927/common/tx4927_dbgio.c
@@ -0,0 +1,47 @@
+/*
+ * linux/arch/mips/tx4927/common/tx4927_dbgio.c
+ *
+ * kgdb interface for gdb
+ *
+ * Author: MontaVista Software, Inc.
+ * source@mvista.com
+ *
+ * Copyright 2001-2002 MontaVista Software Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <asm/mipsregs.h>
+#include <asm/system.h>
+#include <asm/tx4927/tx4927_mips.h>
+
+u8 getDebugChar(void)
+{
+ extern u8 txx9_sio_kdbg_rd(void);
+ return (txx9_sio_kdbg_rd());
+}
+
+
+int putDebugChar(u8 byte)
+{
+ extern int txx9_sio_kdbg_wr( u8 ch );
+ return (txx9_sio_kdbg_wr(byte));
+}
diff --git a/arch/mips/tx4927/common/tx4927_irq.c b/arch/mips/tx4927/common/tx4927_irq.c
new file mode 100644
index 0000000..5ab2e2b
--- /dev/null
+++ b/arch/mips/tx4927/common/tx4927_irq.c
@@ -0,0 +1,584 @@
+/*
+ * Common tx4927 irq handler
+ *
+ * Author: MontaVista Software, Inc.
+ * source@mvista.com
+ *
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel_stat.h>
+#include <linux/module.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/timex.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+#include <linux/irq.h>
+#include <linux/bitops.h>
+#include <asm/bootinfo.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mipsregs.h>
+#include <asm/system.h>
+#include <asm/tx4927/tx4927.h>
+
+/*
+ * DEBUG
+ */
+
+#undef TX4927_IRQ_DEBUG
+
+#ifdef TX4927_IRQ_DEBUG
+#define TX4927_IRQ_NONE 0x00000000
+
+#define TX4927_IRQ_INFO ( 1 << 0 )
+#define TX4927_IRQ_WARN ( 1 << 1 )
+#define TX4927_IRQ_EROR ( 1 << 2 )
+
+#define TX4927_IRQ_INIT ( 1 << 5 )
+#define TX4927_IRQ_NEST1 ( 1 << 6 )
+#define TX4927_IRQ_NEST2 ( 1 << 7 )
+#define TX4927_IRQ_NEST3 ( 1 << 8 )
+#define TX4927_IRQ_NEST4 ( 1 << 9 )
+
+#define TX4927_IRQ_CP0_INIT ( 1 << 10 )
+#define TX4927_IRQ_CP0_STARTUP ( 1 << 11 )
+#define TX4927_IRQ_CP0_SHUTDOWN ( 1 << 12 )
+#define TX4927_IRQ_CP0_ENABLE ( 1 << 13 )
+#define TX4927_IRQ_CP0_DISABLE ( 1 << 14 )
+#define TX4927_IRQ_CP0_MASK ( 1 << 15 )
+#define TX4927_IRQ_CP0_ENDIRQ ( 1 << 16 )
+
+#define TX4927_IRQ_PIC_INIT ( 1 << 20 )
+#define TX4927_IRQ_PIC_STARTUP ( 1 << 21 )
+#define TX4927_IRQ_PIC_SHUTDOWN ( 1 << 22 )
+#define TX4927_IRQ_PIC_ENABLE ( 1 << 23 )
+#define TX4927_IRQ_PIC_DISABLE ( 1 << 24 )
+#define TX4927_IRQ_PIC_MASK ( 1 << 25 )
+#define TX4927_IRQ_PIC_ENDIRQ ( 1 << 26 )
+
+#define TX4927_IRQ_ALL 0xffffffff
+#endif
+
+#ifdef TX4927_IRQ_DEBUG
+static const u32 tx4927_irq_debug_flag = (TX4927_IRQ_NONE
+ | TX4927_IRQ_INFO
+ | TX4927_IRQ_WARN | TX4927_IRQ_EROR
+// | TX4927_IRQ_CP0_INIT
+// | TX4927_IRQ_CP0_STARTUP
+// | TX4927_IRQ_CP0_SHUTDOWN
+// | TX4927_IRQ_CP0_ENABLE
+// | TX4927_IRQ_CP0_DISABLE
+// | TX4927_IRQ_CP0_MASK
+// | TX4927_IRQ_CP0_ENDIRQ
+// | TX4927_IRQ_PIC_INIT
+// | TX4927_IRQ_PIC_STARTUP
+// | TX4927_IRQ_PIC_SHUTDOWN
+// | TX4927_IRQ_PIC_ENABLE
+// | TX4927_IRQ_PIC_DISABLE
+// | TX4927_IRQ_PIC_MASK
+// | TX4927_IRQ_PIC_ENDIRQ
+// | TX4927_IRQ_INIT
+// | TX4927_IRQ_NEST1
+// | TX4927_IRQ_NEST2
+// | TX4927_IRQ_NEST3
+// | TX4927_IRQ_NEST4
+ );
+#endif
+
+#ifdef TX4927_IRQ_DEBUG
+#define TX4927_IRQ_DPRINTK(flag,str...) \
+ if ( (tx4927_irq_debug_flag) & (flag) ) \
+ { \
+ char tmp[100]; \
+ sprintf( tmp, str ); \
+ printk( "%s(%s:%u)::%s", __FUNCTION__, __FILE__, __LINE__, tmp ); \
+ }
+#else
+#define TX4927_IRQ_DPRINTK(flag,str...)
+#endif
+
+/*
+ * Forwad definitions for all pic's
+ */
+
+static unsigned int tx4927_irq_cp0_startup(unsigned int irq);
+static void tx4927_irq_cp0_shutdown(unsigned int irq);
+static void tx4927_irq_cp0_enable(unsigned int irq);
+static void tx4927_irq_cp0_disable(unsigned int irq);
+static void tx4927_irq_cp0_mask_and_ack(unsigned int irq);
+static void tx4927_irq_cp0_end(unsigned int irq);
+
+static unsigned int tx4927_irq_pic_startup(unsigned int irq);
+static void tx4927_irq_pic_shutdown(unsigned int irq);
+static void tx4927_irq_pic_enable(unsigned int irq);
+static void tx4927_irq_pic_disable(unsigned int irq);
+static void tx4927_irq_pic_mask_and_ack(unsigned int irq);
+static void tx4927_irq_pic_end(unsigned int irq);
+
+/*
+ * Kernel structs for all pic's
+ */
+
+static DEFINE_SPINLOCK(tx4927_cp0_lock);
+static DEFINE_SPINLOCK(tx4927_pic_lock);
+
+#define TX4927_CP0_NAME "TX4927-CP0"
+static struct hw_interrupt_type tx4927_irq_cp0_type = {
+ .typename = TX4927_CP0_NAME,
+ .startup = tx4927_irq_cp0_startup,
+ .shutdown = tx4927_irq_cp0_shutdown,
+ .enable = tx4927_irq_cp0_enable,
+ .disable = tx4927_irq_cp0_disable,
+ .ack = tx4927_irq_cp0_mask_and_ack,
+ .end = tx4927_irq_cp0_end,
+ .set_affinity = NULL
+};
+
+#define TX4927_PIC_NAME "TX4927-PIC"
+static struct hw_interrupt_type tx4927_irq_pic_type = {
+ .typename = TX4927_PIC_NAME,
+ .startup = tx4927_irq_pic_startup,
+ .shutdown = tx4927_irq_pic_shutdown,
+ .enable = tx4927_irq_pic_enable,
+ .disable = tx4927_irq_pic_disable,
+ .ack = tx4927_irq_pic_mask_and_ack,
+ .end = tx4927_irq_pic_end,
+ .set_affinity = NULL
+};
+
+#define TX4927_PIC_ACTION(s) { no_action, 0, CPU_MASK_NONE, s, NULL, NULL }
+static struct irqaction tx4927_irq_pic_action =
+TX4927_PIC_ACTION(TX4927_PIC_NAME);
+
+#define CCP0_STATUS 12
+#define CCP0_CAUSE 13
+
+/*
+ * Functions for cp0
+ */
+
+#define tx4927_irq_cp0_mask(irq) ( 1 << ( irq-TX4927_IRQ_CP0_BEG+8 ) )
+
+static void
+tx4927_irq_cp0_modify(unsigned cp0_reg, unsigned clr_bits, unsigned set_bits)
+{
+ unsigned long val = 0;
+
+ switch (cp0_reg) {
+ case CCP0_STATUS:
+ val = read_c0_status();
+ break;
+
+ case CCP0_CAUSE:
+ val = read_c0_cause();
+ break;
+
+ }
+
+ val &= (~clr_bits);
+ val |= (set_bits);
+
+ switch (cp0_reg) {
+ case CCP0_STATUS:{
+ write_c0_status(val);
+ break;
+ }
+ case CCP0_CAUSE:{
+ write_c0_cause(val);
+ break;
+ }
+ }
+
+ return;
+}
+
+static void __init tx4927_irq_cp0_init(void)
+{
+ int i;
+
+ TX4927_IRQ_DPRINTK(TX4927_IRQ_CP0_INIT, "beg=%d end=%d\n",
+ TX4927_IRQ_CP0_BEG, TX4927_IRQ_CP0_END);
+
+ for (i = TX4927_IRQ_CP0_BEG; i <= TX4927_IRQ_CP0_END; i++) {
+ irq_desc[i].status = IRQ_DISABLED;
+ irq_desc[i].action = 0;
+ irq_desc[i].depth = 1;
+ irq_desc[i].handler = &tx4927_irq_cp0_type;
+ }
+
+ return;
+}
+
+static unsigned int tx4927_irq_cp0_startup(unsigned int irq)
+{
+ TX4927_IRQ_DPRINTK(TX4927_IRQ_CP0_STARTUP, "irq=%d \n", irq);
+
+ tx4927_irq_cp0_enable(irq);
+
+ return (0);
+}
+
+static void tx4927_irq_cp0_shutdown(unsigned int irq)
+{
+ TX4927_IRQ_DPRINTK(TX4927_IRQ_CP0_SHUTDOWN, "irq=%d \n", irq);
+
+ tx4927_irq_cp0_disable(irq);
+
+ return;
+}
+
+static void tx4927_irq_cp0_enable(unsigned int irq)
+{
+ unsigned long flags;
+
+ TX4927_IRQ_DPRINTK(TX4927_IRQ_CP0_ENABLE, "irq=%d \n", irq);
+
+ spin_lock_irqsave(&tx4927_cp0_lock, flags);
+
+ tx4927_irq_cp0_modify(CCP0_STATUS, 0, tx4927_irq_cp0_mask(irq));
+
+ spin_unlock_irqrestore(&tx4927_cp0_lock, flags);
+
+ return;
+}
+
+static void tx4927_irq_cp0_disable(unsigned int irq)
+{
+ unsigned long flags;
+
+ TX4927_IRQ_DPRINTK(TX4927_IRQ_CP0_DISABLE, "irq=%d \n", irq);
+
+ spin_lock_irqsave(&tx4927_cp0_lock, flags);
+
+ tx4927_irq_cp0_modify(CCP0_STATUS, tx4927_irq_cp0_mask(irq), 0);
+
+ spin_unlock_irqrestore(&tx4927_cp0_lock, flags);
+
+ return;
+}
+
+static void tx4927_irq_cp0_mask_and_ack(unsigned int irq)
+{
+ TX4927_IRQ_DPRINTK(TX4927_IRQ_CP0_MASK, "irq=%d \n", irq);
+
+ tx4927_irq_cp0_disable(irq);
+
+ return;
+}
+
+static void tx4927_irq_cp0_end(unsigned int irq)
+{
+ TX4927_IRQ_DPRINTK(TX4927_IRQ_CP0_ENDIRQ, "irq=%d \n", irq);
+
+ if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
+ tx4927_irq_cp0_enable(irq);
+ }
+
+ return;
+}
+
+/*
+ * Functions for pic
+ */
+u32 tx4927_irq_pic_addr(int irq)
+{
+ /* MVMCP -- need to formulize this */
+ irq -= TX4927_IRQ_PIC_BEG;
+ switch (irq) {
+ case 17:
+ case 16:
+ case 1:
+ case 0:
+ return (0xff1ff610);
+
+ case 19:
+ case 18:
+ case 3:
+ case 2:
+ return (0xff1ff614);
+
+ case 21:
+ case 20:
+ case 5:
+ case 4:
+ return (0xff1ff618);
+
+ case 23:
+ case 22:
+ case 7:
+ case 6:
+ return (0xff1ff61c);
+
+ case 25:
+ case 24:
+ case 9:
+ case 8:
+ return (0xff1ff620);
+
+ case 27:
+ case 26:
+ case 11:
+ case 10:
+ return (0xff1ff624);
+
+ case 29:
+ case 28:
+ case 13:
+ case 12:
+ return (0xff1ff628);
+
+ case 31:
+ case 30:
+ case 15:
+ case 14:
+ return (0xff1ff62c);
+
+ }
+ return (0);
+}
+
+u32 tx4927_irq_pic_mask(int irq)
+{
+ /* MVMCP -- need to formulize this */
+ irq -= TX4927_IRQ_PIC_BEG;
+ switch (irq) {
+ case 31:
+ case 29:
+ case 27:
+ case 25:
+ case 23:
+ case 21:
+ case 19:
+ case 17:{
+ return (0x07000000);
+ }
+ case 30:
+ case 28:
+ case 26:
+ case 24:
+ case 22:
+ case 20:
+ case 18:
+ case 16:{
+ return (0x00070000);
+ }
+ case 15:
+ case 13:
+ case 11:
+ case 9:
+ case 7:
+ case 5:
+ case 3:
+ case 1:{
+ return (0x00000700);
+ }
+ case 14:
+ case 12:
+ case 10:
+ case 8:
+ case 6:
+ case 4:
+ case 2:
+ case 0:{
+ return (0x00000007);
+ }
+ }
+ return (0x00000000);
+}
+
+static void tx4927_irq_pic_modify(unsigned pic_reg, unsigned clr_bits,
+ unsigned set_bits)
+{
+ unsigned long val = 0;
+
+ val = TX4927_RD(pic_reg);
+ val &= (~clr_bits);
+ val |= (set_bits);
+ TX4927_WR(pic_reg, val);
+
+ return;
+}
+
+static void __init tx4927_irq_pic_init(void)
+{
+ unsigned long flags;
+ int i;
+
+ TX4927_IRQ_DPRINTK(TX4927_IRQ_PIC_INIT, "beg=%d end=%d\n",
+ TX4927_IRQ_PIC_BEG, TX4927_IRQ_PIC_END);
+
+ for (i = TX4927_IRQ_PIC_BEG; i <= TX4927_IRQ_PIC_END; i++) {
+ irq_desc[i].status = IRQ_DISABLED;
+ irq_desc[i].action = 0;
+ irq_desc[i].depth = 2;
+ irq_desc[i].handler = &tx4927_irq_pic_type;
+ }
+
+ setup_irq(TX4927_IRQ_NEST_PIC_ON_CP0, &tx4927_irq_pic_action);
+
+ spin_lock_irqsave(&tx4927_pic_lock, flags);
+
+ TX4927_WR(0xff1ff640, 0x6); /* irq level mask -- only accept hightest */
+ TX4927_WR(0xff1ff600, TX4927_RD(0xff1ff600) | 0x1); /* irq enable */
+
+ spin_unlock_irqrestore(&tx4927_pic_lock, flags);
+
+ return;
+}
+
+static unsigned int tx4927_irq_pic_startup(unsigned int irq)
+{
+ TX4927_IRQ_DPRINTK(TX4927_IRQ_PIC_STARTUP, "irq=%d\n", irq);
+
+ tx4927_irq_pic_enable(irq);
+
+ return (0);
+}
+
+static void tx4927_irq_pic_shutdown(unsigned int irq)
+{
+ TX4927_IRQ_DPRINTK(TX4927_IRQ_PIC_SHUTDOWN, "irq=%d\n", irq);
+
+ tx4927_irq_pic_disable(irq);
+
+ return;
+}
+
+static void tx4927_irq_pic_enable(unsigned int irq)
+{
+ unsigned long flags;
+
+ TX4927_IRQ_DPRINTK(TX4927_IRQ_PIC_ENABLE, "irq=%d\n", irq);
+
+ spin_lock_irqsave(&tx4927_pic_lock, flags);
+
+ tx4927_irq_pic_modify(tx4927_irq_pic_addr(irq), 0,
+ tx4927_irq_pic_mask(irq));
+
+ spin_unlock_irqrestore(&tx4927_pic_lock, flags);
+
+ return;
+}
+
+static void tx4927_irq_pic_disable(unsigned int irq)
+{
+ unsigned long flags;
+
+ TX4927_IRQ_DPRINTK(TX4927_IRQ_PIC_DISABLE, "irq=%d\n", irq);
+
+ spin_lock_irqsave(&tx4927_pic_lock, flags);
+
+ tx4927_irq_pic_modify(tx4927_irq_pic_addr(irq),
+ tx4927_irq_pic_mask(irq), 0);
+
+ spin_unlock_irqrestore(&tx4927_pic_lock, flags);
+
+ return;
+}
+
+static void tx4927_irq_pic_mask_and_ack(unsigned int irq)
+{
+ TX4927_IRQ_DPRINTK(TX4927_IRQ_PIC_MASK, "irq=%d\n", irq);
+
+ tx4927_irq_pic_disable(irq);
+
+ return;
+}
+
+static void tx4927_irq_pic_end(unsigned int irq)
+{
+ TX4927_IRQ_DPRINTK(TX4927_IRQ_PIC_ENDIRQ, "irq=%d\n", irq);
+
+ if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
+ tx4927_irq_pic_enable(irq);
+ }
+
+ return;
+}
+
+/*
+ * Main init functions
+ */
+void __init tx4927_irq_init(void)
+{
+ extern asmlinkage void tx4927_irq_handler(void);
+
+ TX4927_IRQ_DPRINTK(TX4927_IRQ_INIT, "-\n");
+
+ TX4927_IRQ_DPRINTK(TX4927_IRQ_INIT, "=Calling tx4927_irq_cp0_init()\n");
+ tx4927_irq_cp0_init();
+
+ TX4927_IRQ_DPRINTK(TX4927_IRQ_INIT, "=Calling tx4927_irq_pic_init()\n");
+ tx4927_irq_pic_init();
+
+ TX4927_IRQ_DPRINTK(TX4927_IRQ_INIT,
+ "=Calling set_except_vector(tx4927_irq_handler)\n");
+ set_except_vector(0, tx4927_irq_handler);
+
+ TX4927_IRQ_DPRINTK(TX4927_IRQ_INIT, "+\n");
+
+ return;
+}
+
+int tx4927_irq_nested(void)
+{
+ int sw_irq = 0;
+ u32 level2;
+
+ TX4927_IRQ_DPRINTK(TX4927_IRQ_NEST1, "-\n");
+
+ level2 = TX4927_RD(0xff1ff6a0);
+ TX4927_IRQ_DPRINTK(TX4927_IRQ_NEST2, "=level2a=0x%x\n", level2);
+
+ if ((level2 & 0x10000) == 0) {
+ level2 &= 0x1f;
+ TX4927_IRQ_DPRINTK(TX4927_IRQ_NEST3, "=level2b=0x%x\n", level2);
+
+ sw_irq = TX4927_IRQ_PIC_BEG + level2;
+ TX4927_IRQ_DPRINTK(TX4927_IRQ_NEST3, "=sw_irq=%d\n", sw_irq);
+
+ if (sw_irq == 27) {
+ TX4927_IRQ_DPRINTK(TX4927_IRQ_NEST4, "=irq-%d\n",
+ sw_irq);
+
+#ifdef CONFIG_TOSHIBA_RBTX4927
+ {
+ sw_irq = toshiba_rbtx4927_irq_nested(sw_irq);
+ }
+#endif
+
+ TX4927_IRQ_DPRINTK(TX4927_IRQ_NEST4, "=irq+%d\n",
+ sw_irq);
+ }
+ }
+
+ TX4927_IRQ_DPRINTK(TX4927_IRQ_NEST2, "=sw_irq=%d\n", sw_irq);
+
+ TX4927_IRQ_DPRINTK(TX4927_IRQ_NEST1, "+\n");
+
+ return (sw_irq);
+}
diff --git a/arch/mips/tx4927/common/tx4927_irq_handler.S b/arch/mips/tx4927/common/tx4927_irq_handler.S
new file mode 100644
index 0000000..ca123e2
--- /dev/null
+++ b/arch/mips/tx4927/common/tx4927_irq_handler.S
@@ -0,0 +1,103 @@
+/*
+ * linux/arch/mips/tx4927/common/tx4927_irq_handler.S
+ *
+ * Primary interrupt handler for tx4927 based systems
+ *
+ * Author: MontaVista Software, Inc.
+ * Author: jsun@mvista.com or jsun@junsun.net
+ * source@mvista.com
+ *
+ * Copyright 2001-2002 MontaVista Software Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <asm/asm.h>
+#include <asm/mipsregs.h>
+#include <asm/addrspace.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+#include <asm/tx4927/tx4927.h>
+
+ .align 5
+ NESTED(tx4927_irq_handler, PT_SIZE, sp)
+ SAVE_ALL
+ CLI
+ .set at
+
+ mfc0 t0, CP0_CAUSE
+ mfc0 t1, CP0_STATUS
+ and t0, t1
+
+ andi t1, t0, STATUSF_IP7 /* cpu timer */
+ bnez t1, ll_ip7
+
+ /* IP6..IP3 multiplexed -- do not use */
+
+ andi t1, t0, STATUSF_IP2 /* tx4927 pic */
+ bnez t1, ll_ip2
+
+ andi t1, t0, STATUSF_IP0 /* user line 0 */
+ bnez t1, ll_ip0
+
+ andi t1, t0, STATUSF_IP1 /* user line 1 */
+ bnez t1, ll_ip1
+
+ .set reorder
+
+ /* wrong alarm or masked ... */
+ j spurious_interrupt
+ nop
+ END(tx4927_irq_handler)
+
+ .align 5
+
+
+ll_ip7:
+ li a0, TX4927_IRQ_CPU_TIMER
+ move a1, sp
+ jal do_IRQ
+ j ret_from_irq
+
+ll_ip2:
+ jal tx4927_irq_nested
+ nop
+ beqz v0, goto_spurious_interrupt
+ nop
+ move a0, v0
+ move a1, sp
+ jal do_IRQ
+ j ret_from_irq
+
+goto_spurious_interrupt:
+ j spurious_interrupt
+ nop
+
+ll_ip1:
+ li a0, TX4927_IRQ_USER1
+ move a1, sp
+ jal do_IRQ
+ j ret_from_irq
+
+ll_ip0:
+ li a0, TX4927_IRQ_USER0
+ move a1, sp
+ jal do_IRQ
+ j ret_from_irq
diff --git a/arch/mips/tx4927/common/tx4927_prom.c b/arch/mips/tx4927/common/tx4927_prom.c
new file mode 100644
index 0000000..7d4cbf5
--- /dev/null
+++ b/arch/mips/tx4927/common/tx4927_prom.c
@@ -0,0 +1,146 @@
+/*
+ * linux/arch/mips/tx4927/common/tx4927_prom.c
+ *
+ * common tx4927 memory interface
+ *
+ * Author: MontaVista Software, Inc.
+ * source@mvista.com
+ *
+ * Copyright 2001-2002 MontaVista Software Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/bootmem.h>
+
+#include <asm/addrspace.h>
+#include <asm/bootinfo.h>
+#include <asm/tx4927/tx4927.h>
+
+static unsigned int __init tx4927_process_sdccr(u64 * addr)
+{
+ u64 val;
+ unsigned int sdccr_ce;
+ unsigned int sdccr_bs;
+ unsigned int sdccr_rs;
+ unsigned int sdccr_cs;
+ unsigned int sdccr_mw;
+ unsigned int bs = 0;
+ unsigned int rs = 0;
+ unsigned int cs = 0;
+ unsigned int mw = 0;
+ unsigned int msize = 0;
+
+ val = (*((vu64 *) (addr)));
+
+ /* MVMCP -- need #defs for these bits masks */
+ sdccr_ce = ((val & (1 << 10)) >> 10);
+ sdccr_bs = ((val & (1 << 8)) >> 8);
+ sdccr_rs = ((val & (3 << 5)) >> 5);
+ sdccr_cs = ((val & (3 << 2)) >> 2);
+ sdccr_mw = ((val & (1 << 0)) >> 0);
+
+ if (sdccr_ce) {
+ switch (sdccr_bs) {
+ case 0:{
+ bs = 2;
+ break;
+ }
+ case 1:{
+ bs = 4;
+ break;
+ }
+ }
+ switch (sdccr_rs) {
+ case 0:{
+ rs = 2048;
+ break;
+ }
+ case 1:{
+ rs = 4096;
+ break;
+ }
+ case 2:{
+ rs = 8192;
+ break;
+ }
+ case 3:{
+ rs = 0;
+ break;
+ }
+ }
+ switch (sdccr_cs) {
+ case 0:{
+ cs = 256;
+ break;
+ }
+ case 1:{
+ cs = 512;
+ break;
+ }
+ case 2:{
+ cs = 1024;
+ break;
+ }
+ case 3:{
+ cs = 2048;
+ break;
+ }
+ }
+ switch (sdccr_mw) {
+ case 0:{
+ mw = 8;
+ break;
+ } /* 8 bytes = 64 bits */
+ case 1:{
+ mw = 4;
+ break;
+ } /* 4 bytes = 32 bits */
+ }
+ }
+
+ /* bytes per chip MB per chip num chips */
+ msize = (((rs * cs * mw) / (1024 * 1024)) * bs);
+
+ return (msize);
+}
+
+
+unsigned int __init tx4927_get_mem_size(void)
+{
+ unsigned int c0;
+ unsigned int c1;
+ unsigned int c2;
+ unsigned int c3;
+ unsigned int total;
+
+ /* MVMCP -- need #defs for these registers */
+ c0 = tx4927_process_sdccr((u64 *) 0xff1f8000);
+ c1 = tx4927_process_sdccr((u64 *) 0xff1f8008);
+ c2 = tx4927_process_sdccr((u64 *) 0xff1f8010);
+ c3 = tx4927_process_sdccr((u64 *) 0xff1f8018);
+ total = c0 + c1 + c2 + c3;
+
+ return (total);
+}
diff --git a/arch/mips/tx4927/common/tx4927_setup.c b/arch/mips/tx4927/common/tx4927_setup.c
new file mode 100644
index 0000000..16bcbdc
--- /dev/null
+++ b/arch/mips/tx4927/common/tx4927_setup.c
@@ -0,0 +1,237 @@
+/*
+ * Author: MontaVista Software, Inc.
+ * source@mvista.com
+ *
+ * Copyright 2001-2002 MontaVista Software Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel_stat.h>
+#include <linux/module.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/timex.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+#include <linux/irq.h>
+#include <linux/bitops.h>
+#include <asm/bootinfo.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mipsregs.h>
+#include <asm/system.h>
+#include <asm/time.h>
+#include <asm/tx4927/tx4927.h>
+
+
+#undef DEBUG
+
+void __init tx4927_time_init(void);
+void __init tx4927_timer_setup(struct irqaction *irq);
+void dump_cp0(char *key);
+
+
+void (*__wbflush) (void);
+
+static void tx4927_write_buffer_flush(void)
+{
+ __asm__ __volatile__
+ ("sync\n\t" "nop\n\t" "loop: bc0f loop\n\t" "nop\n\t");
+}
+
+
+static void __init tx4927_setup(void)
+{
+ board_time_init = tx4927_time_init;
+ board_timer_setup = tx4927_timer_setup;
+ __wbflush = tx4927_write_buffer_flush;
+
+#ifdef CONFIG_TOSHIBA_RBTX4927
+ {
+ extern void toshiba_rbtx4927_setup(void);
+ toshiba_rbtx4927_setup();
+ }
+#endif
+
+ return;
+}
+
+early_initcall(tx4927_setup);
+
+void __init tx4927_time_init(void)
+{
+
+#ifdef CONFIG_TOSHIBA_RBTX4927
+ {
+ extern void toshiba_rbtx4927_time_init(void);
+ toshiba_rbtx4927_time_init();
+ }
+#endif
+
+ return;
+}
+
+
+void __init tx4927_timer_setup(struct irqaction *irq)
+{
+ u32 count;
+ u32 c1;
+ u32 c2;
+
+ setup_irq(TX4927_IRQ_CPU_TIMER, irq);
+
+ /* to generate the first timer interrupt */
+ c1 = read_c0_count();
+ count = c1 + (mips_hpt_frequency / HZ);
+ write_c0_compare(count);
+ c2 = read_c0_count();
+
+#ifdef CONFIG_TOSHIBA_RBTX4927
+ {
+ extern void toshiba_rbtx4927_timer_setup(struct irqaction
+ *irq);
+ toshiba_rbtx4927_timer_setup(irq);
+ }
+#endif
+
+ return;
+}
+
+
+#ifdef DEBUG
+void print_cp0(char *key, int num, char *name, u32 val)
+{
+ printk("%s cp0:%02d:%s=0x%08x\n", key, num, name, val);
+ return;
+}
+
+indent: Standard input:25: Error:Unexpected end of file
+
+void
+dump_cp0(char *key)
+{
+ if (key == NULL)
+ key = "";
+
+ print_cp0(key, 0, "INDEX ", read_c0_index());
+ print_cp0(key, 2, "ENTRYLO1", read_c0_entrylo0());
+ print_cp0(key, 3, "ENTRYLO2", read_c0_entrylo1());
+ print_cp0(key, 4, "CONTEXT ", read_c0_context());
+ print_cp0(key, 5, "PAGEMASK", read_c0_pagemask());
+ print_cp0(key, 6, "WIRED ", read_c0_wired());
+ //print_cp0(key, 8, "BADVADDR", read_c0_badvaddr());
+ print_cp0(key, 9, "COUNT ", read_c0_count());
+ print_cp0(key, 10, "ENTRYHI ", read_c0_entryhi());
+ print_cp0(key, 11, "COMPARE ", read_c0_compare());
+ print_cp0(key, 12, "STATUS ", read_c0_status());
+ print_cp0(key, 13, "CAUSE ", read_c0_cause() & 0xffff87ff);
+ print_cp0(key, 16, "CONFIG ", read_c0_config());
+ return;
+}
+
+void print_pic(char *key, u32 reg, char *name)
+{
+ printk("%s pic:0x%08x:%s=0x%08x\n", key, reg, name,
+ TX4927_RD(reg));
+ return;
+}
+
+
+void dump_pic(char *key)
+{
+ if (key == NULL)
+ key = "";
+
+ print_pic(key, 0xff1ff600, "IRDEN ");
+ print_pic(key, 0xff1ff604, "IRDM0 ");
+ print_pic(key, 0xff1ff608, "IRDM1 ");
+
+ print_pic(key, 0xff1ff610, "IRLVL0 ");
+ print_pic(key, 0xff1ff614, "IRLVL1 ");
+ print_pic(key, 0xff1ff618, "IRLVL2 ");
+ print_pic(key, 0xff1ff61c, "IRLVL3 ");
+ print_pic(key, 0xff1ff620, "IRLVL4 ");
+ print_pic(key, 0xff1ff624, "IRLVL5 ");
+ print_pic(key, 0xff1ff628, "IRLVL6 ");
+ print_pic(key, 0xff1ff62c, "IRLVL7 ");
+
+ print_pic(key, 0xff1ff640, "IRMSK ");
+ print_pic(key, 0xff1ff660, "IREDC ");
+ print_pic(key, 0xff1ff680, "IRPND ");
+ print_pic(key, 0xff1ff6a0, "IRCS ");
+
+ print_pic(key, 0xff1ff514, "IRFLAG1 "); /* don't read IRLAG0 -- it hangs system */
+
+ print_pic(key, 0xff1ff518, "IRPOL ");
+ print_pic(key, 0xff1ff51c, "IRRCNT ");
+ print_pic(key, 0xff1ff520, "IRMASKINT");
+ print_pic(key, 0xff1ff524, "IRMASKEXT");
+
+ return;
+}
+
+
+void print_addr(char *hdr, char *key, u32 addr)
+{
+ printk("%s %s:0x%08x=0x%08x\n", hdr, key, addr, TX4927_RD(addr));
+ return;
+}
+
+
+void dump_180(char *key)
+{
+ u32 i;
+
+ for (i = 0x80000180; i < 0x80000180 + 0x80; i += 4) {
+ print_addr("180", key, i);
+ }
+ return;
+}
+
+
+void dump_eh0(char *key)
+{
+ int i;
+ extern unsigned long exception_handlers[];
+
+ for (i = (int) exception_handlers;
+ i < (int) (exception_handlers + 20); i += 4) {
+ print_addr("eh0", key, i);
+ }
+
+ return;
+}
+
+void pk0(void)
+{
+ volatile u32 val;
+
+ __asm__ __volatile__("ori %0, $26, 0":"=r"(val)
+ );
+ printk("k0=[0x%08x]\n", val);
+}
+#endif
diff --git a/arch/mips/tx4927/toshiba_rbtx4927/Makefile b/arch/mips/tx4927/toshiba_rbtx4927/Makefile
new file mode 100644
index 0000000..86ca4cf
--- /dev/null
+++ b/arch/mips/tx4927/toshiba_rbtx4927/Makefile
@@ -0,0 +1,5 @@
+obj-y += toshiba_rbtx4927_prom.o
+obj-y += toshiba_rbtx4927_setup.o
+obj-y += toshiba_rbtx4927_irq.o
+
+EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_irq.c b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_irq.c
new file mode 100644
index 0000000..fd5b433
--- /dev/null
+++ b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_irq.c
@@ -0,0 +1,786 @@
+/*
+ * linux/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_irq.c
+ *
+ * Toshiba RBTX4927 specific interrupt handlers
+ *
+ * Author: MontaVista Software, Inc.
+ * source@mvista.com
+ *
+ * Copyright 2001-2002 MontaVista Software Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+/*
+IRQ Device
+00 RBTX4927-ISA/00
+01 RBTX4927-ISA/01 PS2/Keyboard
+02 RBTX4927-ISA/02 Cascade RBTX4927-ISA (irqs 8-15)
+03 RBTX4927-ISA/03
+04 RBTX4927-ISA/04
+05 RBTX4927-ISA/05
+06 RBTX4927-ISA/06
+07 RBTX4927-ISA/07
+08 RBTX4927-ISA/08
+09 RBTX4927-ISA/09
+10 RBTX4927-ISA/10
+11 RBTX4927-ISA/11
+12 RBTX4927-ISA/12 PS2/Mouse (not supported at this time)
+13 RBTX4927-ISA/13
+14 RBTX4927-ISA/14 IDE
+15 RBTX4927-ISA/15
+
+16 TX4927-CP0/00 Software 0
+17 TX4927-CP0/01 Software 1
+18 TX4927-CP0/02 Cascade TX4927-CP0
+19 TX4927-CP0/03 Multiplexed -- do not use
+20 TX4927-CP0/04 Multiplexed -- do not use
+21 TX4927-CP0/05 Multiplexed -- do not use
+22 TX4927-CP0/06 Multiplexed -- do not use
+23 TX4927-CP0/07 CPU TIMER
+
+24 TX4927-PIC/00
+25 TX4927-PIC/01
+26 TX4927-PIC/02
+27 TX4927-PIC/03 Cascade RBTX4927-IOC
+28 TX4927-PIC/04
+29 TX4927-PIC/05 RBTX4927 RTL-8019AS ethernet
+30 TX4927-PIC/06
+31 TX4927-PIC/07
+32 TX4927-PIC/08 TX4927 SerialIO Channel 0
+33 TX4927-PIC/09 TX4927 SerialIO Channel 1
+34 TX4927-PIC/10
+35 TX4927-PIC/11
+36 TX4927-PIC/12
+37 TX4927-PIC/13
+38 TX4927-PIC/14
+39 TX4927-PIC/15
+40 TX4927-PIC/16 TX4927 PCI PCI-C
+41 TX4927-PIC/17
+42 TX4927-PIC/18
+43 TX4927-PIC/19
+44 TX4927-PIC/20
+45 TX4927-PIC/21
+46 TX4927-PIC/22 TX4927 PCI PCI-ERR
+47 TX4927-PIC/23 TX4927 PCI PCI-PMA (not used)
+48 TX4927-PIC/24
+49 TX4927-PIC/25
+50 TX4927-PIC/26
+51 TX4927-PIC/27
+52 TX4927-PIC/28
+53 TX4927-PIC/29
+54 TX4927-PIC/30
+55 TX4927-PIC/31
+
+56 RBTX4927-IOC/00 FPCIB0 PCI-D PJ4/A PJ5/B SB/C PJ6/D PJ7/A (SouthBridge/NotUsed) [RTL-8139=PJ4]
+57 RBTX4927-IOC/01 FPCIB0 PCI-C PJ4/D PJ5/A SB/B PJ6/C PJ7/D (SouthBridge/NotUsed) [RTL-8139=PJ5]
+58 RBTX4927-IOC/02 FPCIB0 PCI-B PJ4/C PJ5/D SB/A PJ6/B PJ7/C (SouthBridge/IDE/pin=1,INTR) [RTL-8139=NotSupported]
+59 RBTX4927-IOC/03 FPCIB0 PCI-A PJ4/B PJ5/C SB/D PJ6/A PJ7/B (SouthBridge/USB/pin=4) [RTL-8139=PJ6]
+60 RBTX4927-IOC/04
+61 RBTX4927-IOC/05
+62 RBTX4927-IOC/06
+63 RBTX4927-IOC/07
+
+NOTES:
+SouthBridge/INTR is mapped to SouthBridge/A=PCI-B/#58
+SouthBridge/ISA/pin=0 no pci irq used by this device
+SouthBridge/IDE/pin=1 no pci irq used by this device, using INTR via ISA IRQ14
+SouthBridge/USB/pin=4 using pci irq SouthBridge/D=PCI-A=#59
+SouthBridge/PMC/pin=0 no pci irq used by this device
+SuperIO/PS2/Keyboard, using INTR via ISA IRQ1
+SuperIO/PS2/Mouse, using INTR via ISA IRQ12 (mouse not currently supported)
+JP7 is not bus master -- do NOT use -- only 4 pci bus master's allowed -- SouthBridge, JP4, JP5, JP6
+*/
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/swap.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/timex.h>
+#include <asm/bootinfo.h>
+#include <asm/page.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/pci.h>
+#include <asm/processor.h>
+#include <asm/ptrace.h>
+#include <asm/reboot.h>
+#include <asm/time.h>
+#include <linux/bootmem.h>
+#include <linux/blkdev.h>
+#ifdef CONFIG_RTC_DS1742
+#include <linux/ds1742rtc.h>
+#endif
+#ifdef CONFIG_TOSHIBA_FPCIB0
+#include <asm/tx4927/smsc_fdc37m81x.h>
+#endif
+#include <asm/tx4927/toshiba_rbtx4927.h>
+
+
+#undef TOSHIBA_RBTX4927_IRQ_DEBUG
+
+#ifdef TOSHIBA_RBTX4927_IRQ_DEBUG
+#define TOSHIBA_RBTX4927_IRQ_NONE 0x00000000
+
+#define TOSHIBA_RBTX4927_IRQ_INFO ( 1 << 0 )
+#define TOSHIBA_RBTX4927_IRQ_WARN ( 1 << 1 )
+#define TOSHIBA_RBTX4927_IRQ_EROR ( 1 << 2 )
+
+#define TOSHIBA_RBTX4927_IRQ_IOC_INIT ( 1 << 10 )
+#define TOSHIBA_RBTX4927_IRQ_IOC_STARTUP ( 1 << 11 )
+#define TOSHIBA_RBTX4927_IRQ_IOC_SHUTDOWN ( 1 << 12 )
+#define TOSHIBA_RBTX4927_IRQ_IOC_ENABLE ( 1 << 13 )
+#define TOSHIBA_RBTX4927_IRQ_IOC_DISABLE ( 1 << 14 )
+#define TOSHIBA_RBTX4927_IRQ_IOC_MASK ( 1 << 15 )
+#define TOSHIBA_RBTX4927_IRQ_IOC_ENDIRQ ( 1 << 16 )
+
+#define TOSHIBA_RBTX4927_IRQ_ISA_INIT ( 1 << 20 )
+#define TOSHIBA_RBTX4927_IRQ_ISA_STARTUP ( 1 << 21 )
+#define TOSHIBA_RBTX4927_IRQ_ISA_SHUTDOWN ( 1 << 22 )
+#define TOSHIBA_RBTX4927_IRQ_ISA_ENABLE ( 1 << 23 )
+#define TOSHIBA_RBTX4927_IRQ_ISA_DISABLE ( 1 << 24 )
+#define TOSHIBA_RBTX4927_IRQ_ISA_MASK ( 1 << 25 )
+#define TOSHIBA_RBTX4927_IRQ_ISA_ENDIRQ ( 1 << 26 )
+
+#define TOSHIBA_RBTX4927_SETUP_ALL 0xffffffff
+#endif
+
+
+#ifdef TOSHIBA_RBTX4927_IRQ_DEBUG
+static const u32 toshiba_rbtx4927_irq_debug_flag =
+ (TOSHIBA_RBTX4927_IRQ_NONE | TOSHIBA_RBTX4927_IRQ_INFO |
+ TOSHIBA_RBTX4927_IRQ_WARN | TOSHIBA_RBTX4927_IRQ_EROR
+// | TOSHIBA_RBTX4927_IRQ_IOC_INIT
+// | TOSHIBA_RBTX4927_IRQ_IOC_STARTUP
+// | TOSHIBA_RBTX4927_IRQ_IOC_SHUTDOWN
+// | TOSHIBA_RBTX4927_IRQ_IOC_ENABLE
+// | TOSHIBA_RBTX4927_IRQ_IOC_DISABLE
+// | TOSHIBA_RBTX4927_IRQ_IOC_MASK
+// | TOSHIBA_RBTX4927_IRQ_IOC_ENDIRQ
+// | TOSHIBA_RBTX4927_IRQ_ISA_INIT
+// | TOSHIBA_RBTX4927_IRQ_ISA_STARTUP
+// | TOSHIBA_RBTX4927_IRQ_ISA_SHUTDOWN
+// | TOSHIBA_RBTX4927_IRQ_ISA_ENABLE
+// | TOSHIBA_RBTX4927_IRQ_ISA_DISABLE
+// | TOSHIBA_RBTX4927_IRQ_ISA_MASK
+// | TOSHIBA_RBTX4927_IRQ_ISA_ENDIRQ
+ );
+#endif
+
+
+#ifdef TOSHIBA_RBTX4927_IRQ_DEBUG
+#define TOSHIBA_RBTX4927_IRQ_DPRINTK(flag,str...) \
+ if ( (toshiba_rbtx4927_irq_debug_flag) & (flag) ) \
+ { \
+ char tmp[100]; \
+ sprintf( tmp, str ); \
+ printk( "%s(%s:%u)::%s", __FUNCTION__, __FILE__, __LINE__, tmp ); \
+ }
+#else
+#define TOSHIBA_RBTX4927_IRQ_DPRINTK(flag,str...)
+#endif
+
+
+
+
+#define TOSHIBA_RBTX4927_IRQ_IOC_RAW_BEG 0
+#define TOSHIBA_RBTX4927_IRQ_IOC_RAW_END 7
+
+#define TOSHIBA_RBTX4927_IRQ_IOC_BEG ((TX4927_IRQ_PIC_END+1)+TOSHIBA_RBTX4927_IRQ_IOC_RAW_BEG) /* 56 */
+#define TOSHIBA_RBTX4927_IRQ_IOC_END ((TX4927_IRQ_PIC_END+1)+TOSHIBA_RBTX4927_IRQ_IOC_RAW_END) /* 63 */
+
+
+#define TOSHIBA_RBTX4927_IRQ_ISA_BEG MI8259_IRQ_ISA_BEG
+#define TOSHIBA_RBTX4927_IRQ_ISA_END MI8259_IRQ_ISA_END
+#define TOSHIBA_RBTX4927_IRQ_ISA_MID ((TOSHIBA_RBTX4927_IRQ_ISA_BEG+TOSHIBA_RBTX4927_IRQ_ISA_END+1)/2)
+
+
+#define TOSHIBA_RBTX4927_IRQ_NEST_IOC_ON_PIC TX4927_IRQ_NEST_EXT_ON_PIC
+#define TOSHIBA_RBTX4927_IRQ_NEST_ISA_ON_IOC (TOSHIBA_RBTX4927_IRQ_IOC_BEG+2)
+#define TOSHIBA_RBTX4927_IRQ_NEST_ISA_ON_ISA (TOSHIBA_RBTX4927_IRQ_ISA_BEG+2)
+
+extern int tx4927_using_backplane;
+
+#ifdef CONFIG_TOSHIBA_FPCIB0
+extern void enable_8259A_irq(unsigned int irq);
+extern void disable_8259A_irq(unsigned int irq);
+extern void mask_and_ack_8259A(unsigned int irq);
+#endif
+
+static unsigned int toshiba_rbtx4927_irq_ioc_startup(unsigned int irq);
+static void toshiba_rbtx4927_irq_ioc_shutdown(unsigned int irq);
+static void toshiba_rbtx4927_irq_ioc_enable(unsigned int irq);
+static void toshiba_rbtx4927_irq_ioc_disable(unsigned int irq);
+static void toshiba_rbtx4927_irq_ioc_mask_and_ack(unsigned int irq);
+static void toshiba_rbtx4927_irq_ioc_end(unsigned int irq);
+
+#ifdef CONFIG_TOSHIBA_FPCIB0
+static unsigned int toshiba_rbtx4927_irq_isa_startup(unsigned int irq);
+static void toshiba_rbtx4927_irq_isa_shutdown(unsigned int irq);
+static void toshiba_rbtx4927_irq_isa_enable(unsigned int irq);
+static void toshiba_rbtx4927_irq_isa_disable(unsigned int irq);
+static void toshiba_rbtx4927_irq_isa_mask_and_ack(unsigned int irq);
+static void toshiba_rbtx4927_irq_isa_end(unsigned int irq);
+#endif
+
+static DEFINE_SPINLOCK(toshiba_rbtx4927_ioc_lock);
+
+
+#define TOSHIBA_RBTX4927_IOC_NAME "RBTX4927-IOC"
+static struct hw_interrupt_type toshiba_rbtx4927_irq_ioc_type = {
+ .typename = TOSHIBA_RBTX4927_IOC_NAME,
+ .startup = toshiba_rbtx4927_irq_ioc_startup,
+ .shutdown = toshiba_rbtx4927_irq_ioc_shutdown,
+ .enable = toshiba_rbtx4927_irq_ioc_enable,
+ .disable = toshiba_rbtx4927_irq_ioc_disable,
+ .ack = toshiba_rbtx4927_irq_ioc_mask_and_ack,
+ .end = toshiba_rbtx4927_irq_ioc_end,
+ .set_affinity = NULL
+};
+#define TOSHIBA_RBTX4927_IOC_INTR_ENAB 0xbc002000
+#define TOSHIBA_RBTX4927_IOC_INTR_STAT 0xbc002006
+
+
+#ifdef CONFIG_TOSHIBA_FPCIB0
+#define TOSHIBA_RBTX4927_ISA_NAME "RBTX4927-ISA"
+static struct hw_interrupt_type toshiba_rbtx4927_irq_isa_type = {
+ .typename = TOSHIBA_RBTX4927_ISA_NAME,
+ .startup = toshiba_rbtx4927_irq_isa_startup,
+ .shutdown = toshiba_rbtx4927_irq_isa_shutdown,
+ .enable = toshiba_rbtx4927_irq_isa_enable,
+ .disable = toshiba_rbtx4927_irq_isa_disable,
+ .ack = toshiba_rbtx4927_irq_isa_mask_and_ack,
+ .end = toshiba_rbtx4927_irq_isa_end,
+ .set_affinity = NULL
+};
+#endif
+
+
+u32 bit2num(u32 num)
+{
+ u32 i;
+
+ for (i = 0; i < (sizeof(num) * 8); i++) {
+ if (num & (1 << i)) {
+ return (i);
+ }
+ }
+ return (0);
+}
+
+int toshiba_rbtx4927_irq_nested(int sw_irq)
+{
+ u32 level3;
+ u32 level4;
+ u32 level5;
+
+ level3 = reg_rd08(TOSHIBA_RBTX4927_IOC_INTR_STAT) & 0x1f;
+ if (level3) {
+ sw_irq = TOSHIBA_RBTX4927_IRQ_IOC_BEG + bit2num(level3);
+ if (sw_irq != TOSHIBA_RBTX4927_IRQ_NEST_ISA_ON_IOC) {
+ goto RETURN;
+ }
+ }
+#ifdef CONFIG_TOSHIBA_FPCIB0
+ {
+ if (tx4927_using_backplane) {
+ outb(0x0A, 0x20);
+ level4 = inb(0x20) & 0xff;
+ if (level4) {
+ sw_irq =
+ TOSHIBA_RBTX4927_IRQ_ISA_BEG +
+ bit2num(level4);
+ if (sw_irq !=
+ TOSHIBA_RBTX4927_IRQ_NEST_ISA_ON_ISA) {
+ goto RETURN;
+ }
+ }
+
+ outb(0x0A, 0xA0);
+ level5 = inb(0xA0) & 0xff;
+ if (level5) {
+ sw_irq =
+ TOSHIBA_RBTX4927_IRQ_ISA_MID +
+ bit2num(level5);
+ goto RETURN;
+ }
+ }
+ }
+#endif
+
+ RETURN:
+ return (sw_irq);
+}
+
+//#define TOSHIBA_RBTX4927_PIC_ACTION(s) { no_action, 0, CPU_MASK_NONE, s, NULL, NULL }
+#define TOSHIBA_RBTX4927_PIC_ACTION(s) { no_action, SA_SHIRQ, CPU_MASK_NONE, s, NULL, NULL }
+static struct irqaction toshiba_rbtx4927_irq_ioc_action =
+TOSHIBA_RBTX4927_PIC_ACTION(TOSHIBA_RBTX4927_IOC_NAME);
+#ifdef CONFIG_TOSHIBA_FPCIB0
+static struct irqaction toshiba_rbtx4927_irq_isa_master =
+TOSHIBA_RBTX4927_PIC_ACTION(TOSHIBA_RBTX4927_ISA_NAME "/M");
+static struct irqaction toshiba_rbtx4927_irq_isa_slave =
+TOSHIBA_RBTX4927_PIC_ACTION(TOSHIBA_RBTX4927_ISA_NAME "/S");
+#endif
+
+
+/**********************************************************************************/
+/* Functions for ioc */
+/**********************************************************************************/
+
+
+static void __init toshiba_rbtx4927_irq_ioc_init(void)
+{
+ int i;
+
+ TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_IOC_INIT,
+ "beg=%d end=%d\n",
+ TOSHIBA_RBTX4927_IRQ_IOC_BEG,
+ TOSHIBA_RBTX4927_IRQ_IOC_END);
+
+ for (i = TOSHIBA_RBTX4927_IRQ_IOC_BEG;
+ i <= TOSHIBA_RBTX4927_IRQ_IOC_END; i++) {
+ irq_desc[i].status = IRQ_DISABLED;
+ irq_desc[i].action = 0;
+ irq_desc[i].depth = 3;
+ irq_desc[i].handler = &toshiba_rbtx4927_irq_ioc_type;
+ }
+
+ setup_irq(TOSHIBA_RBTX4927_IRQ_NEST_IOC_ON_PIC,
+ &toshiba_rbtx4927_irq_ioc_action);
+
+ return;
+}
+
+static unsigned int toshiba_rbtx4927_irq_ioc_startup(unsigned int irq)
+{
+ TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_IOC_STARTUP,
+ "irq=%d\n", irq);
+
+ if (irq < TOSHIBA_RBTX4927_IRQ_IOC_BEG
+ || irq > TOSHIBA_RBTX4927_IRQ_IOC_END) {
+ TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_EROR,
+ "bad irq=%d\n", irq);
+ panic("\n");
+ }
+
+ toshiba_rbtx4927_irq_ioc_enable(irq);
+
+ return (0);
+}
+
+
+static void toshiba_rbtx4927_irq_ioc_shutdown(unsigned int irq)
+{
+ TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_IOC_SHUTDOWN,
+ "irq=%d\n", irq);
+
+ if (irq < TOSHIBA_RBTX4927_IRQ_IOC_BEG
+ || irq > TOSHIBA_RBTX4927_IRQ_IOC_END) {
+ TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_EROR,
+ "bad irq=%d\n", irq);
+ panic("\n");
+ }
+
+ toshiba_rbtx4927_irq_ioc_disable(irq);
+
+ return;
+}
+
+
+static void toshiba_rbtx4927_irq_ioc_enable(unsigned int irq)
+{
+ unsigned long flags;
+ volatile unsigned char v;
+
+ TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_IOC_ENABLE,
+ "irq=%d\n", irq);
+
+ if (irq < TOSHIBA_RBTX4927_IRQ_IOC_BEG
+ || irq > TOSHIBA_RBTX4927_IRQ_IOC_END) {
+ TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_EROR,
+ "bad irq=%d\n", irq);
+ panic("\n");
+ }
+
+ spin_lock_irqsave(&toshiba_rbtx4927_ioc_lock, flags);
+
+ v = TX4927_RD08(TOSHIBA_RBTX4927_IOC_INTR_ENAB);
+ v |= (1 << (irq - TOSHIBA_RBTX4927_IRQ_IOC_BEG));
+ TOSHIBA_RBTX4927_WR08(TOSHIBA_RBTX4927_IOC_INTR_ENAB, v);
+
+ spin_unlock_irqrestore(&toshiba_rbtx4927_ioc_lock, flags);
+
+ return;
+}
+
+
+static void toshiba_rbtx4927_irq_ioc_disable(unsigned int irq)
+{
+ unsigned long flags;
+ volatile unsigned char v;
+
+ TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_IOC_DISABLE,
+ "irq=%d\n", irq);
+
+ if (irq < TOSHIBA_RBTX4927_IRQ_IOC_BEG
+ || irq > TOSHIBA_RBTX4927_IRQ_IOC_END) {
+ TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_EROR,
+ "bad irq=%d\n", irq);
+ panic("\n");
+ }
+
+ spin_lock_irqsave(&toshiba_rbtx4927_ioc_lock, flags);
+
+ v = TX4927_RD08(TOSHIBA_RBTX4927_IOC_INTR_ENAB);
+ v &= ~(1 << (irq - TOSHIBA_RBTX4927_IRQ_IOC_BEG));
+ TOSHIBA_RBTX4927_WR08(TOSHIBA_RBTX4927_IOC_INTR_ENAB, v);
+
+ spin_unlock_irqrestore(&toshiba_rbtx4927_ioc_lock, flags);
+
+ return;
+}
+
+
+static void toshiba_rbtx4927_irq_ioc_mask_and_ack(unsigned int irq)
+{
+ TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_IOC_MASK,
+ "irq=%d\n", irq);
+
+ if (irq < TOSHIBA_RBTX4927_IRQ_IOC_BEG
+ || irq > TOSHIBA_RBTX4927_IRQ_IOC_END) {
+ TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_EROR,
+ "bad irq=%d\n", irq);
+ panic("\n");
+ }
+
+ toshiba_rbtx4927_irq_ioc_disable(irq);
+
+ return;
+}
+
+
+static void toshiba_rbtx4927_irq_ioc_end(unsigned int irq)
+{
+ TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_IOC_ENDIRQ,
+ "irq=%d\n", irq);
+
+ if (irq < TOSHIBA_RBTX4927_IRQ_IOC_BEG
+ || irq > TOSHIBA_RBTX4927_IRQ_IOC_END) {
+ TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_EROR,
+ "bad irq=%d\n", irq);
+ panic("\n");
+ }
+
+ if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
+ toshiba_rbtx4927_irq_ioc_enable(irq);
+ }
+
+ return;
+}
+
+
+/**********************************************************************************/
+/* Functions for isa */
+/**********************************************************************************/
+
+
+#ifdef CONFIG_TOSHIBA_FPCIB0
+static void __init toshiba_rbtx4927_irq_isa_init(void)
+{
+ int i;
+
+ TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_ISA_INIT,
+ "beg=%d end=%d\n",
+ TOSHIBA_RBTX4927_IRQ_ISA_BEG,
+ TOSHIBA_RBTX4927_IRQ_ISA_END);
+
+ for (i = TOSHIBA_RBTX4927_IRQ_ISA_BEG;
+ i <= TOSHIBA_RBTX4927_IRQ_ISA_END; i++) {
+ irq_desc[i].status = IRQ_DISABLED;
+ irq_desc[i].action = 0;
+ irq_desc[i].depth =
+ ((i < TOSHIBA_RBTX4927_IRQ_ISA_MID) ? (4) : (5));
+ irq_desc[i].handler = &toshiba_rbtx4927_irq_isa_type;
+ }
+
+ setup_irq(TOSHIBA_RBTX4927_IRQ_NEST_ISA_ON_IOC,
+ &toshiba_rbtx4927_irq_isa_master);
+ setup_irq(TOSHIBA_RBTX4927_IRQ_NEST_ISA_ON_ISA,
+ &toshiba_rbtx4927_irq_isa_slave);
+
+ /* make sure we are looking at IRR (not ISR) */
+ outb(0x0A, 0x20);
+ outb(0x0A, 0xA0);
+
+ return;
+}
+#endif
+
+
+#ifdef CONFIG_TOSHIBA_FPCIB0
+static unsigned int toshiba_rbtx4927_irq_isa_startup(unsigned int irq)
+{
+ TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_ISA_STARTUP,
+ "irq=%d\n", irq);
+
+ if (irq < TOSHIBA_RBTX4927_IRQ_ISA_BEG
+ || irq > TOSHIBA_RBTX4927_IRQ_ISA_END) {
+ TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_EROR,
+ "bad irq=%d\n", irq);
+ panic("\n");
+ }
+
+ toshiba_rbtx4927_irq_isa_enable(irq);
+
+ return (0);
+}
+#endif
+
+
+#ifdef CONFIG_TOSHIBA_FPCIB0
+static void toshiba_rbtx4927_irq_isa_shutdown(unsigned int irq)
+{
+ TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_ISA_SHUTDOWN,
+ "irq=%d\n", irq);
+
+ if (irq < TOSHIBA_RBTX4927_IRQ_ISA_BEG
+ || irq > TOSHIBA_RBTX4927_IRQ_ISA_END) {
+ TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_EROR,
+ "bad irq=%d\n", irq);
+ panic("\n");
+ }
+
+ toshiba_rbtx4927_irq_isa_disable(irq);
+
+ return;
+}
+#endif
+
+
+#ifdef CONFIG_TOSHIBA_FPCIB0
+static void toshiba_rbtx4927_irq_isa_enable(unsigned int irq)
+{
+ TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_ISA_ENABLE,
+ "irq=%d\n", irq);
+
+ if (irq < TOSHIBA_RBTX4927_IRQ_ISA_BEG
+ || irq > TOSHIBA_RBTX4927_IRQ_ISA_END) {
+ TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_EROR,
+ "bad irq=%d\n", irq);
+ panic("\n");
+ }
+
+ enable_8259A_irq(irq);
+
+ return;
+}
+#endif
+
+
+#ifdef CONFIG_TOSHIBA_FPCIB0
+static void toshiba_rbtx4927_irq_isa_disable(unsigned int irq)
+{
+ TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_ISA_DISABLE,
+ "irq=%d\n", irq);
+
+ if (irq < TOSHIBA_RBTX4927_IRQ_ISA_BEG
+ || irq > TOSHIBA_RBTX4927_IRQ_ISA_END) {
+ TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_EROR,
+ "bad irq=%d\n", irq);
+ panic("\n");
+ }
+
+ disable_8259A_irq(irq);
+
+ return;
+}
+#endif
+
+
+#ifdef CONFIG_TOSHIBA_FPCIB0
+static void toshiba_rbtx4927_irq_isa_mask_and_ack(unsigned int irq)
+{
+ TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_ISA_MASK,
+ "irq=%d\n", irq);
+
+ if (irq < TOSHIBA_RBTX4927_IRQ_ISA_BEG
+ || irq > TOSHIBA_RBTX4927_IRQ_ISA_END) {
+ TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_EROR,
+ "bad irq=%d\n", irq);
+ panic("\n");
+ }
+
+ mask_and_ack_8259A(irq);
+
+ return;
+}
+#endif
+
+
+#ifdef CONFIG_TOSHIBA_FPCIB0
+static void toshiba_rbtx4927_irq_isa_end(unsigned int irq)
+{
+ TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_ISA_ENDIRQ,
+ "irq=%d\n", irq);
+
+ if (irq < TOSHIBA_RBTX4927_IRQ_ISA_BEG
+ || irq > TOSHIBA_RBTX4927_IRQ_ISA_END) {
+ TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_EROR,
+ "bad irq=%d\n", irq);
+ panic("\n");
+ }
+
+ if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
+ toshiba_rbtx4927_irq_isa_enable(irq);
+ }
+
+ return;
+}
+#endif
+
+
+void __init arch_init_irq(void)
+{
+ extern void tx4927_irq_init(void);
+
+ local_irq_disable();
+
+ tx4927_irq_init();
+ toshiba_rbtx4927_irq_ioc_init();
+#ifdef CONFIG_TOSHIBA_FPCIB0
+ {
+ if (tx4927_using_backplane) {
+ toshiba_rbtx4927_irq_isa_init();
+ }
+ }
+#endif
+
+ wbflush();
+
+ return;
+}
+
+void toshiba_rbtx4927_irq_dump(char *key)
+{
+#ifdef TOSHIBA_RBTX4927_IRQ_DEBUG
+ {
+ u32 i, j = 0;
+ for (i = 0; i < NR_IRQS; i++) {
+ if (strcmp(irq_desc[i].handler->typename, "none")
+ == 0)
+ continue;
+
+ if ((i >= 1)
+ && (irq_desc[i - 1].handler->typename ==
+ irq_desc[i].handler->typename)) {
+ j++;
+ } else {
+ j = 0;
+ }
+ TOSHIBA_RBTX4927_IRQ_DPRINTK
+ (TOSHIBA_RBTX4927_IRQ_INFO,
+ "%s irq=0x%02x/%3d s=0x%08x h=0x%08x a=0x%08x ah=0x%08x d=%1d n=%s/%02d\n",
+ key, i, i, irq_desc[i].status,
+ (u32) irq_desc[i].handler,
+ (u32) irq_desc[i].action,
+ (u32) (irq_desc[i].action ? irq_desc[i].
+ action->handler : 0),
+ irq_desc[i].depth,
+ irq_desc[i].handler->typename, j);
+ }
+ }
+#endif
+ return;
+}
+
+void toshiba_rbtx4927_irq_dump_pics(char *s)
+{
+ u32 level0_m;
+ u32 level0_s;
+ u32 level1_m;
+ u32 level1_s;
+ u32 level2;
+ u32 level2_p;
+ u32 level2_s;
+ u32 level3_m;
+ u32 level3_s;
+ u32 level4_m;
+ u32 level4_s;
+ u32 level5_m;
+ u32 level5_s;
+
+ if (s == NULL)
+ s = "null";
+
+ level0_m = (read_c0_status() & 0x0000ff00) >> 8;
+ level0_s = (read_c0_cause() & 0x0000ff00) >> 8;
+
+ level1_m = level0_m;
+ level1_s = level0_s & 0x87;
+
+ level2 = TX4927_RD(0xff1ff6a0);
+ level2_p = (((level2 & 0x10000)) ? 0 : 1);
+ level2_s = (((level2 & 0x1f) == 0x1f) ? 0 : (level2 & 0x1f));
+
+ level3_m = reg_rd08(TOSHIBA_RBTX4927_IOC_INTR_ENAB) & 0x1f;
+ level3_s = reg_rd08(TOSHIBA_RBTX4927_IOC_INTR_STAT) & 0x1f;
+
+ level4_m = inb(0x21);
+ outb(0x0A, 0x20);
+ level4_s = inb(0x20);
+
+ level5_m = inb(0xa1);
+ outb(0x0A, 0xa0);
+ level5_s = inb(0xa0);
+
+ TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_INFO,
+ "dump_raw_pic() ");
+ TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_INFO,
+ "cp0:m=0x%02x/s=0x%02x ", level0_m,
+ level0_s);
+ TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_INFO,
+ "cp0:m=0x%02x/s=0x%02x ", level1_m,
+ level1_s);
+ TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_INFO,
+ "pic:e=0x%02x/s=0x%02x ", level2_p,
+ level2_s);
+ TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_INFO,
+ "ioc:m=0x%02x/s=0x%02x ", level3_m,
+ level3_s);
+ TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_INFO,
+ "sbm:m=0x%02x/s=0x%02x ", level4_m,
+ level4_s);
+ TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_INFO,
+ "sbs:m=0x%02x/s=0x%02x ", level5_m,
+ level5_s);
+ TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_INFO, "[%s]\n",
+ s);
+
+ return;
+}
diff --git a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_prom.c b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_prom.c
new file mode 100644
index 0000000..e4d095d
--- /dev/null
+++ b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_prom.c
@@ -0,0 +1,97 @@
+/*
+ * rbtx4927 specific prom routines
+ *
+ * Author: MontaVista Software, Inc.
+ * source@mvista.com
+ *
+ * Copyright 2001-2002 MontaVista Software Inc.
+ *
+ * Copyright (C) 2004 MontaVista Software Inc.
+ * Author: Manish Lachwani, mlachwani@mvista.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/bootmem.h>
+
+#include <asm/addrspace.h>
+#include <asm/bootinfo.h>
+#include <asm/cpu.h>
+#include <asm/tx4927/tx4927.h>
+
+void __init prom_init_cmdline(void)
+{
+ int argc = (int) fw_arg0;
+ char **argv = (char **) fw_arg1;
+ int i; /* Always ignore the "-c" at argv[0] */
+
+ /* ignore all built-in args if any f/w args given */
+ if (argc > 1) {
+ *arcs_cmdline = '\0';
+ }
+
+ for (i = 1; i < argc; i++) {
+ if (i != 1) {
+ strcat(arcs_cmdline, " ");
+ }
+ strcat(arcs_cmdline, argv[i]);
+ }
+}
+
+void __init prom_init(void)
+{
+ const char* toshiba_name_list[] = GROUP_TOSHIBA_NAMES;
+ extern int tx4927_get_mem_size(void);
+ extern char* toshiba_name;
+ int msize;
+
+ prom_init_cmdline();
+
+ mips_machgroup = MACH_GROUP_TOSHIBA;
+
+ if ((read_c0_prid() & 0xff) == PRID_REV_TX4927)
+ mips_machtype = MACH_TOSHIBA_RBTX4927;
+ else
+ mips_machtype = MACH_TOSHIBA_RBTX4937;
+
+ toshiba_name = toshiba_name_list[mips_machtype];
+
+ msize = tx4927_get_mem_size();
+ add_memory_region(0, msize << 20, BOOT_MEM_RAM);
+}
+
+unsigned long __init prom_free_prom_memory(void)
+{
+ return 0;
+}
+
+const char *get_system_type(void)
+{
+ return "Toshiba RBTX4927/RBTX4937";
+}
+
+char * __init prom_getcmdline(void)
+{
+ return &(arcs_cmdline[0]);
+}
+
diff --git a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c
new file mode 100644
index 0000000..8724ea3
--- /dev/null
+++ b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c
@@ -0,0 +1,1024 @@
+/*
+ * Toshiba rbtx4927 specific setup
+ *
+ * Author: MontaVista Software, Inc.
+ * source@mvista.com
+ *
+ * Copyright 2001-2002 MontaVista Software Inc.
+ *
+ * Copyright (C) 1996, 97, 2001, 04 Ralf Baechle (ralf@linux-mips.org)
+ * Copyright (C) 2000 RidgeRun, Inc.
+ * Author: RidgeRun, Inc.
+ * glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: jsun@mvista.com or jsun@junsun.net
+ *
+ * Copyright 2002 MontaVista Software Inc.
+ * Author: Michael Pruznick, michael_pruznick@mvista.com
+ *
+ * Copyright (C) 2000-2001 Toshiba Corporation
+ *
+ * Copyright (C) 2004 MontaVista Software Inc.
+ * Author: Manish Lachwani, mlachwani@mvista.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/swap.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/timex.h>
+#include <asm/bootinfo.h>
+#include <asm/page.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/processor.h>
+#include <asm/ptrace.h>
+#include <asm/reboot.h>
+#include <asm/time.h>
+#include <linux/bootmem.h>
+#include <linux/blkdev.h>
+#ifdef CONFIG_RTC_DS1742
+#include <linux/ds1742rtc.h>
+#endif
+#ifdef CONFIG_TOSHIBA_FPCIB0
+#include <asm/tx4927/smsc_fdc37m81x.h>
+#endif
+#include <asm/tx4927/toshiba_rbtx4927.h>
+#ifdef CONFIG_PCI
+#include <asm/tx4927/tx4927_pci.h>
+#endif
+#ifdef CONFIG_BLK_DEV_IDEPCI
+#include <linux/hdreg.h>
+#include <linux/ide.h>
+#endif
+
+#undef TOSHIBA_RBTX4927_SETUP_DEBUG
+
+#ifdef TOSHIBA_RBTX4927_SETUP_DEBUG
+#define TOSHIBA_RBTX4927_SETUP_NONE 0x00000000
+
+#define TOSHIBA_RBTX4927_SETUP_INFO ( 1 << 0 )
+#define TOSHIBA_RBTX4927_SETUP_WARN ( 1 << 1 )
+#define TOSHIBA_RBTX4927_SETUP_EROR ( 1 << 2 )
+
+#define TOSHIBA_RBTX4927_SETUP_EFWFU ( 1 << 3 )
+#define TOSHIBA_RBTX4927_SETUP_SETUP ( 1 << 4 )
+#define TOSHIBA_RBTX4927_SETUP_TIME_INIT ( 1 << 5 )
+#define TOSHIBA_RBTX4927_SETUP_TIMER_SETUP ( 1 << 6 )
+#define TOSHIBA_RBTX4927_SETUP_PCIBIOS ( 1 << 7 )
+#define TOSHIBA_RBTX4927_SETUP_PCI1 ( 1 << 8 )
+#define TOSHIBA_RBTX4927_SETUP_PCI2 ( 1 << 9 )
+#define TOSHIBA_RBTX4927_SETUP_PCI66 ( 1 << 10 )
+
+#define TOSHIBA_RBTX4927_SETUP_ALL 0xffffffff
+#endif
+
+#ifdef TOSHIBA_RBTX4927_SETUP_DEBUG
+static const u32 toshiba_rbtx4927_setup_debug_flag =
+ (TOSHIBA_RBTX4927_SETUP_NONE | TOSHIBA_RBTX4927_SETUP_INFO |
+ TOSHIBA_RBTX4927_SETUP_WARN | TOSHIBA_RBTX4927_SETUP_EROR |
+ TOSHIBA_RBTX4927_SETUP_EFWFU | TOSHIBA_RBTX4927_SETUP_SETUP |
+ TOSHIBA_RBTX4927_SETUP_TIME_INIT | TOSHIBA_RBTX4927_SETUP_TIMER_SETUP
+ | TOSHIBA_RBTX4927_SETUP_PCIBIOS | TOSHIBA_RBTX4927_SETUP_PCI1 |
+ TOSHIBA_RBTX4927_SETUP_PCI2 | TOSHIBA_RBTX4927_SETUP_PCI66);
+#endif
+
+#ifdef TOSHIBA_RBTX4927_SETUP_DEBUG
+#define TOSHIBA_RBTX4927_SETUP_DPRINTK(flag,str...) \
+ if ( (toshiba_rbtx4927_setup_debug_flag) & (flag) ) \
+ { \
+ char tmp[100]; \
+ sprintf( tmp, str ); \
+ printk( "%s(%s:%u)::%s", __FUNCTION__, __FILE__, __LINE__, tmp ); \
+ }
+#else
+#define TOSHIBA_RBTX4927_SETUP_DPRINTK(flag,str...)
+#endif
+
+/* These functions are used for rebooting or halting the machine*/
+extern void toshiba_rbtx4927_restart(char *command);
+extern void toshiba_rbtx4927_halt(void);
+extern void toshiba_rbtx4927_power_off(void);
+
+int tx4927_using_backplane = 0;
+
+extern void gt64120_time_init(void);
+extern void toshiba_rbtx4927_irq_setup(void);
+
+#ifdef CONFIG_PCI
+#define CONFIG_TX4927BUG_WORKAROUND
+#undef TX4927_SUPPORT_COMMAND_IO
+#undef TX4927_SUPPORT_PCI_66
+int tx4927_cpu_clock = 100000000; /* 100MHz */
+unsigned long mips_pci_io_base;
+unsigned long mips_pci_io_size;
+unsigned long mips_pci_mem_base;
+unsigned long mips_pci_mem_size;
+/* for legacy I/O, PCI I/O PCI Bus address must be 0 */
+unsigned long mips_pci_io_pciaddr = 0;
+unsigned long mips_memory_upper;
+static int tx4927_ccfg_toeon = 1;
+static int tx4927_pcic_trdyto = 0; /* default: disabled */
+unsigned long tx4927_ce_base[8];
+void tx4927_pci_setup(void);
+void tx4927_reset_pci_pcic(void);
+int tx4927_pci66 = 0; /* 0:auto */
+#endif
+
+char *toshiba_name = "";
+
+#ifdef CONFIG_PCI
+static void tx4927_pcierr_interrupt(int irq, void *dev_id,
+ struct pt_regs *regs)
+{
+#ifdef CONFIG_BLK_DEV_IDEPCI
+ /* ignore MasterAbort for ide probing... */
+ if (irq == TX4927_IRQ_IRC_PCIERR &&
+ ((tx4927_pcicptr->pcistatus >> 16) & 0xf900) ==
+ PCI_STATUS_REC_MASTER_ABORT) {
+ tx4927_pcicptr->pcistatus =
+ (tx4927_pcicptr->
+ pcistatus & 0x0000ffff) | (PCI_STATUS_REC_MASTER_ABORT
+ << 16);
+
+ return;
+ }
+#endif
+ printk("PCI error interrupt (irq 0x%x).\n", irq);
+
+ printk("pcistat:%04x, g2pstatus:%08lx, pcicstatus:%08lx\n",
+ (unsigned short) (tx4927_pcicptr->pcistatus >> 16),
+ tx4927_pcicptr->g2pstatus, tx4927_pcicptr->pcicstatus);
+ printk("ccfg:%08lx, tear:%02lx_%08lx\n",
+ (unsigned long) tx4927_ccfgptr->ccfg,
+ (unsigned long) (tx4927_ccfgptr->tear >> 32),
+ (unsigned long) tx4927_ccfgptr->tear);
+ show_regs(regs);
+}
+
+void __init toshiba_rbtx4927_pci_irq_init(void)
+{
+ return;
+}
+
+void tx4927_reset_pci_pcic(void)
+{
+ /* Reset PCI Bus */
+ *tx4927_pcireset_ptr = 1;
+ /* Reset PCIC */
+ tx4927_ccfgptr->clkctr |= TX4927_CLKCTR_PCIRST;
+ udelay(10000);
+ /* clear PCIC reset */
+ tx4927_ccfgptr->clkctr &= ~TX4927_CLKCTR_PCIRST;
+ *tx4927_pcireset_ptr = 0;
+}
+#endif /* CONFIG_PCI */
+
+#ifdef CONFIG_PCI
+void print_pci_status(void)
+{
+ printk("PCI STATUS %lx\n", tx4927_pcicptr->pcistatus);
+ printk("PCIC STATUS %lx\n", tx4927_pcicptr->pcicstatus);
+}
+
+extern struct pci_controller tx4927_controller;
+
+static struct pci_dev *fake_pci_dev(struct pci_controller *hose,
+ int top_bus, int busnr, int devfn)
+{
+ static struct pci_dev dev;
+ static struct pci_bus bus;
+
+ dev.sysdata = (void *)hose;
+ dev.devfn = devfn;
+ bus.number = busnr;
+ bus.ops = hose->pci_ops;
+ bus.parent = NULL;
+ dev.bus = &bus;
+
+ return &dev;
+}
+
+#define EARLY_PCI_OP(rw, size, type) \
+static int early_##rw##_config_##size(struct pci_controller *hose, \
+ int top_bus, int bus, int devfn, int offset, type value) \
+{ \
+ return pci_##rw##_config_##size( \
+ fake_pci_dev(hose, top_bus, bus, devfn), \
+ offset, value); \
+}
+
+EARLY_PCI_OP(read, byte, u8 *)
+EARLY_PCI_OP(read, word, u16 *)
+EARLY_PCI_OP(read, dword, u32 *)
+EARLY_PCI_OP(write, byte, u8)
+EARLY_PCI_OP(write, word, u16)
+EARLY_PCI_OP(write, dword, u32)
+
+static int __init tx4927_pcibios_init(void)
+{
+ unsigned int id;
+ u32 pci_devfn;
+ int devfn_start = 0;
+ int devfn_stop = 0xff;
+ int busno = 0; /* One bus on the Toshiba */
+ struct pci_controller *hose = &tx4927_controller;
+
+ TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_PCIBIOS,
+ "-\n");
+
+ for (pci_devfn = devfn_start; pci_devfn < devfn_stop; pci_devfn++) {
+ early_read_config_dword(hose, busno, busno, pci_devfn,
+ PCI_VENDOR_ID, &id);
+
+ if (id == 0xffffffff) {
+ continue;
+ }
+
+ if (id == 0x94601055) {
+ u8 v08_64;
+ u32 v32_b0;
+ u8 v08_e1;
+ char *s = " sb/isa --";
+
+ TOSHIBA_RBTX4927_SETUP_DPRINTK
+ (TOSHIBA_RBTX4927_SETUP_PCIBIOS, ":%s beg\n",
+ s);
+
+ early_read_config_byte(hose, busno, busno,
+ pci_devfn, 0x64, &v08_64);
+ early_read_config_dword(hose, busno, busno,
+ pci_devfn, 0xb0, &v32_b0);
+ early_read_config_byte(hose, busno, busno,
+ pci_devfn, 0xe1, &v08_e1);
+
+ TOSHIBA_RBTX4927_SETUP_DPRINTK
+ (TOSHIBA_RBTX4927_SETUP_PCIBIOS,
+ ":%s beg 0x64 = 0x%02x\n", s, v08_64);
+ TOSHIBA_RBTX4927_SETUP_DPRINTK
+ (TOSHIBA_RBTX4927_SETUP_PCIBIOS,
+ ":%s beg 0xb0 = 0x%02x\n", s, v32_b0);
+ TOSHIBA_RBTX4927_SETUP_DPRINTK
+ (TOSHIBA_RBTX4927_SETUP_PCIBIOS,
+ ":%s beg 0xe1 = 0x%02x\n", s, v08_e1);
+
+ /* serial irq control */
+ v08_64 = 0xd0;
+
+ /* serial irq pin */
+ v32_b0 |= 0x00010000;
+
+ /* ide irq on isa14 */
+ v08_e1 &= 0xf0;
+ v08_e1 |= 0x0d;
+
+ TOSHIBA_RBTX4927_SETUP_DPRINTK
+ (TOSHIBA_RBTX4927_SETUP_PCIBIOS,
+ ":%s mid 0x64 = 0x%02x\n", s, v08_64);
+ TOSHIBA_RBTX4927_SETUP_DPRINTK
+ (TOSHIBA_RBTX4927_SETUP_PCIBIOS,
+ ":%s mid 0xb0 = 0x%02x\n", s, v32_b0);
+ TOSHIBA_RBTX4927_SETUP_DPRINTK
+ (TOSHIBA_RBTX4927_SETUP_PCIBIOS,
+ ":%s mid 0xe1 = 0x%02x\n", s, v08_e1);
+
+ early_write_config_byte(hose, busno, busno,
+ pci_devfn, 0x64, v08_64);
+ early_write_config_dword(hose, busno, busno,
+ pci_devfn, 0xb0, v32_b0);
+ early_write_config_byte(hose, busno, busno,
+ pci_devfn, 0xe1, v08_e1);
+
+#ifdef TOSHIBA_RBTX4927_SETUP_DEBUG
+ {
+ early_read_config_byte(hose, busno, busno,
+ pci_devfn, 0x64,
+ &v08_64);
+ early_read_config_dword(hose, busno, busno,
+ pci_devfn, 0xb0,
+ &v32_b0);
+ early_read_config_byte(hose, busno, busno,
+ pci_devfn, 0xe1,
+ &v08_e1);
+
+ TOSHIBA_RBTX4927_SETUP_DPRINTK
+ (TOSHIBA_RBTX4927_SETUP_PCIBIOS,
+ ":%s end 0x64 = 0x%02x\n", s, v08_64);
+ TOSHIBA_RBTX4927_SETUP_DPRINTK
+ (TOSHIBA_RBTX4927_SETUP_PCIBIOS,
+ ":%s end 0xb0 = 0x%02x\n", s, v32_b0);
+ TOSHIBA_RBTX4927_SETUP_DPRINTK
+ (TOSHIBA_RBTX4927_SETUP_PCIBIOS,
+ ":%s end 0xe1 = 0x%02x\n", s, v08_e1);
+ }
+#endif
+
+ TOSHIBA_RBTX4927_SETUP_DPRINTK
+ (TOSHIBA_RBTX4927_SETUP_PCIBIOS, ":%s end\n",
+ s);
+ }
+
+ if (id == 0x91301055) {
+ u8 v08_04;
+ u8 v08_09;
+ u8 v08_41;
+ u8 v08_43;
+ u8 v08_5c;
+ char *s = " sb/ide --";
+
+ TOSHIBA_RBTX4927_SETUP_DPRINTK
+ (TOSHIBA_RBTX4927_SETUP_PCIBIOS, ":%s beg\n",
+ s);
+
+ early_read_config_byte(hose, busno, busno,
+ pci_devfn, 0x04, &v08_04);
+ early_read_config_byte(hose, busno, busno,
+ pci_devfn, 0x09, &v08_09);
+ early_read_config_byte(hose, busno, busno,
+ pci_devfn, 0x41, &v08_41);
+ early_read_config_byte(hose, busno, busno,
+ pci_devfn, 0x43, &v08_43);
+ early_read_config_byte(hose, busno, busno,
+ pci_devfn, 0x5c, &v08_5c);
+
+ TOSHIBA_RBTX4927_SETUP_DPRINTK
+ (TOSHIBA_RBTX4927_SETUP_PCIBIOS,
+ ":%s beg 0x04 = 0x%02x\n", s, v08_04);
+ TOSHIBA_RBTX4927_SETUP_DPRINTK
+ (TOSHIBA_RBTX4927_SETUP_PCIBIOS,
+ ":%s beg 0x09 = 0x%02x\n", s, v08_09);
+ TOSHIBA_RBTX4927_SETUP_DPRINTK
+ (TOSHIBA_RBTX4927_SETUP_PCIBIOS,
+ ":%s beg 0x41 = 0x%02x\n", s, v08_41);
+ TOSHIBA_RBTX4927_SETUP_DPRINTK
+ (TOSHIBA_RBTX4927_SETUP_PCIBIOS,
+ ":%s beg 0x43 = 0x%02x\n", s, v08_43);
+ TOSHIBA_RBTX4927_SETUP_DPRINTK
+ (TOSHIBA_RBTX4927_SETUP_PCIBIOS,
+ ":%s beg 0x5c = 0x%02x\n", s, v08_5c);
+
+ /* enable ide master/io */
+ v08_04 |= (PCI_COMMAND_MASTER | PCI_COMMAND_IO);
+
+ /* enable ide native mode */
+ v08_09 |= 0x05;
+
+ /* enable primary ide */
+ v08_41 |= 0x80;
+
+ /* enable secondary ide */
+ v08_43 |= 0x80;
+
+ /*
+ * !!! DO NOT REMOVE THIS COMMENT IT IS REQUIRED BY SMSC !!!
+ *
+ * This line of code is intended to provide the user with a work
+ * around solution to the anomalies cited in SMSC's anomaly sheet
+ * entitled, "SLC90E66 Functional Rev.J_0.1 Anomalies"".
+ *
+ * !!! DO NOT REMOVE THIS COMMENT IT IS REQUIRED BY SMSC !!!
+ */
+ v08_5c |= 0x01;
+
+ TOSHIBA_RBTX4927_SETUP_DPRINTK
+ (TOSHIBA_RBTX4927_SETUP_PCIBIOS,
+ ":%s mid 0x04 = 0x%02x\n", s, v08_04);
+ TOSHIBA_RBTX4927_SETUP_DPRINTK
+ (TOSHIBA_RBTX4927_SETUP_PCIBIOS,
+ ":%s mid 0x09 = 0x%02x\n", s, v08_09);
+ TOSHIBA_RBTX4927_SETUP_DPRINTK
+ (TOSHIBA_RBTX4927_SETUP_PCIBIOS,
+ ":%s mid 0x41 = 0x%02x\n", s, v08_41);
+ TOSHIBA_RBTX4927_SETUP_DPRINTK
+ (TOSHIBA_RBTX4927_SETUP_PCIBIOS,
+ ":%s mid 0x43 = 0x%02x\n", s, v08_43);
+ TOSHIBA_RBTX4927_SETUP_DPRINTK
+ (TOSHIBA_RBTX4927_SETUP_PCIBIOS,
+ ":%s mid 0x5c = 0x%02x\n", s, v08_5c);
+
+ early_write_config_byte(hose, busno, busno,
+ pci_devfn, 0x5c, v08_5c);
+ early_write_config_byte(hose, busno, busno,
+ pci_devfn, 0x04, v08_04);
+ early_write_config_byte(hose, busno, busno,
+ pci_devfn, 0x09, v08_09);
+ early_write_config_byte(hose, busno, busno,
+ pci_devfn, 0x41, v08_41);
+ early_write_config_byte(hose, busno, busno,
+ pci_devfn, 0x43, v08_43);
+
+#ifdef TOSHIBA_RBTX4927_SETUP_DEBUG
+ {
+ early_read_config_byte(hose, busno, busno,
+ pci_devfn, 0x04,
+ &v08_04);
+ early_read_config_byte(hose, busno, busno,
+ pci_devfn, 0x09,
+ &v08_09);
+ early_read_config_byte(hose, busno, busno,
+ pci_devfn, 0x41,
+ &v08_41);
+ early_read_config_byte(hose, busno, busno,
+ pci_devfn, 0x43,
+ &v08_43);
+ early_read_config_byte(hose, busno, busno,
+ pci_devfn, 0x5c,
+ &v08_5c);
+
+ TOSHIBA_RBTX4927_SETUP_DPRINTK
+ (TOSHIBA_RBTX4927_SETUP_PCIBIOS,
+ ":%s end 0x04 = 0x%02x\n", s, v08_04);
+ TOSHIBA_RBTX4927_SETUP_DPRINTK
+ (TOSHIBA_RBTX4927_SETUP_PCIBIOS,
+ ":%s end 0x09 = 0x%02x\n", s, v08_09);
+ TOSHIBA_RBTX4927_SETUP_DPRINTK
+ (TOSHIBA_RBTX4927_SETUP_PCIBIOS,
+ ":%s end 0x41 = 0x%02x\n", s, v08_41);
+ TOSHIBA_RBTX4927_SETUP_DPRINTK
+ (TOSHIBA_RBTX4927_SETUP_PCIBIOS,
+ ":%s end 0x43 = 0x%02x\n", s, v08_43);
+ TOSHIBA_RBTX4927_SETUP_DPRINTK
+ (TOSHIBA_RBTX4927_SETUP_PCIBIOS,
+ ":%s end 0x5c = 0x%02x\n", s, v08_5c);
+ }
+#endif
+
+ TOSHIBA_RBTX4927_SETUP_DPRINTK
+ (TOSHIBA_RBTX4927_SETUP_PCIBIOS, ":%s end\n",
+ s);
+ }
+
+ }
+
+ register_pci_controller(&tx4927_controller);
+ TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_PCIBIOS,
+ "+\n");
+
+ return 0;
+}
+
+arch_initcall(tx4927_pcibios_init);
+
+extern struct resource pci_io_resource;
+extern struct resource pci_mem_resource;
+
+void tx4927_pci_setup(void)
+{
+ static int called = 0;
+ extern unsigned int tx4927_get_mem_size(void);
+
+ TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_PCI2, "-\n");
+
+ mips_memory_upper = tx4927_get_mem_size() << 20;
+ mips_memory_upper += KSEG0;
+ TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_PCI2,
+ "0x%08lx=mips_memory_upper\n",
+ mips_memory_upper);
+ mips_pci_io_base = TX4927_PCIIO;
+ mips_pci_io_size = TX4927_PCIIO_SIZE;
+ mips_pci_mem_base = TX4927_PCIMEM;
+ mips_pci_mem_size = TX4927_PCIMEM_SIZE;
+
+ TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_PCI2,
+ "0x%08lx=mips_pci_io_base\n",
+ mips_pci_io_base);
+ TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_PCI2,
+ "0x%08lx=mips_pci_io_size\n",
+ mips_pci_io_size);
+ TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_PCI2,
+ "0x%08lx=mips_pci_mem_base\n",
+ mips_pci_mem_base);
+ TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_PCI2,
+ "0x%08lx=mips_pci_mem_size\n",
+ mips_pci_mem_size);
+ TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_PCI2,
+ "0x%08lx=pci_io_resource.start\n",
+ pci_io_resource.start);
+ TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_PCI2,
+ "0x%08lx=pci_io_resource.end\n",
+ pci_io_resource.end);
+ TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_PCI2,
+ "0x%08lx=pci_mem_resource.start\n",
+ pci_mem_resource.start);
+ TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_PCI2,
+ "0x%08lx=pci_mem_resource.end\n",
+ pci_mem_resource.end);
+ TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_PCI2,
+ "0x%08lx=mips_io_port_base",
+ mips_io_port_base);
+
+ TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_PCI2,
+ "setup pci_io_resource to 0x%08lx 0x%08lx\n",
+ pci_io_resource.start,
+ pci_io_resource.end);
+ TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_PCI2,
+ "setup pci_mem_resource to 0x%08lx 0x%08lx\n",
+ pci_mem_resource.start,
+ pci_mem_resource.end);
+
+ if (!called) {
+ printk
+ ("TX4927 PCIC -- DID:%04x VID:%04x RID:%02x Arbiter:%s\n",
+ (unsigned short) (tx4927_pcicptr->pciid >> 16),
+ (unsigned short) (tx4927_pcicptr->pciid & 0xffff),
+ (unsigned short) (tx4927_pcicptr->pciccrev & 0xff),
+ (!(tx4927_ccfgptr->
+ ccfg & TX4927_CCFG_PCIXARB)) ? "External" :
+ "Internal");
+ called = 1;
+ }
+ printk("%s PCIC --%s PCICLK:",toshiba_name,
+ (tx4927_ccfgptr->ccfg & TX4927_CCFG_PCI66) ? " PCI66" : "");
+ if (tx4927_ccfgptr->pcfg & TX4927_PCFG_PCICLKEN_ALL) {
+ int pciclk = 0;
+ switch ((unsigned long) tx4927_ccfgptr->
+ ccfg & TX4927_CCFG_PCIDIVMODE_MASK) {
+ case TX4927_CCFG_PCIDIVMODE_2_5:
+ pciclk = tx4927_cpu_clock * 2 / 5;
+ break;
+ case TX4927_CCFG_PCIDIVMODE_3:
+ pciclk = tx4927_cpu_clock / 3;
+ break;
+ case TX4927_CCFG_PCIDIVMODE_5:
+ pciclk = tx4927_cpu_clock / 5;
+ break;
+ case TX4927_CCFG_PCIDIVMODE_6:
+ pciclk = tx4927_cpu_clock / 6;
+ break;
+ }
+ printk("Internal(%dMHz)", pciclk / 1000000);
+ } else {
+ int pciclk = 0;
+ int pciclk_setting = *tx4927_pci_clk_ptr;
+ switch (pciclk_setting & TX4927_PCI_CLK_MASK) {
+ case TX4927_PCI_CLK_33:
+ pciclk = 33333333;
+ break;
+ case TX4927_PCI_CLK_25:
+ pciclk = 25000000;
+ break;
+ case TX4927_PCI_CLK_66:
+ pciclk = 66666666;
+ break;
+ case TX4927_PCI_CLK_50:
+ pciclk = 50000000;
+ break;
+ }
+ printk("External(%dMHz)", pciclk / 1000000);
+ }
+ printk("\n");
+
+
+
+ /* GB->PCI mappings */
+ tx4927_pcicptr->g2piomask = (mips_pci_io_size - 1) >> 4;
+ tx4927_pcicptr->g2piogbase = mips_pci_io_base |
+#ifdef __BIG_ENDIAN
+ TX4927_PCIC_G2PIOGBASE_ECHG
+#else
+ TX4927_PCIC_G2PIOGBASE_BSDIS
+#endif
+ ;
+
+ tx4927_pcicptr->g2piopbase = 0;
+
+ tx4927_pcicptr->g2pmmask[0] = (mips_pci_mem_size - 1) >> 4;
+ tx4927_pcicptr->g2pmgbase[0] = mips_pci_mem_base |
+#ifdef __BIG_ENDIAN
+ TX4927_PCIC_G2PMnGBASE_ECHG
+#else
+ TX4927_PCIC_G2PMnGBASE_BSDIS
+#endif
+ ;
+ tx4927_pcicptr->g2pmpbase[0] = mips_pci_mem_base;
+
+ tx4927_pcicptr->g2pmmask[1] = 0;
+ tx4927_pcicptr->g2pmgbase[1] = 0;
+ tx4927_pcicptr->g2pmpbase[1] = 0;
+ tx4927_pcicptr->g2pmmask[2] = 0;
+ tx4927_pcicptr->g2pmgbase[2] = 0;
+ tx4927_pcicptr->g2pmpbase[2] = 0;
+
+
+ /* PCI->GB mappings (I/O 256B) */
+ tx4927_pcicptr->p2giopbase = 0; /* 256B */
+
+ /* PCI->GB mappings (MEM 512MB) M0 gets all of memory */
+ tx4927_pcicptr->p2gm0plbase = 0;
+ tx4927_pcicptr->p2gm0pubase = 0;
+ tx4927_pcicptr->p2gmgbase[0] = 0 | TX4927_PCIC_P2GMnGBASE_TMEMEN |
+#ifdef __BIG_ENDIAN
+ TX4927_PCIC_P2GMnGBASE_TECHG
+#else
+ TX4927_PCIC_P2GMnGBASE_TBSDIS
+#endif
+ ;
+
+ /* PCI->GB mappings (MEM 16MB) -not used */
+ tx4927_pcicptr->p2gm1plbase = 0xffffffff;
+#ifdef CONFIG_TX4927BUG_WORKAROUND
+ /*
+ * TX4927-PCIC-BUG: P2GM1PUBASE must be 0
+ * if P2GM0PUBASE was 0.
+ */
+ tx4927_pcicptr->p2gm1pubase = 0;
+#else
+ tx4927_pcicptr->p2gm1pubase = 0xffffffff;
+#endif
+ tx4927_pcicptr->p2gmgbase[1] = 0;
+
+ /* PCI->GB mappings (MEM 1MB) -not used */
+ tx4927_pcicptr->p2gm2pbase = 0xffffffff;
+ tx4927_pcicptr->p2gmgbase[2] = 0;
+
+
+ /* Enable Initiator Memory 0 Space, I/O Space, Config */
+ tx4927_pcicptr->pciccfg &= TX4927_PCIC_PCICCFG_LBWC_MASK;
+ tx4927_pcicptr->pciccfg |=
+ TX4927_PCIC_PCICCFG_IMSE0 | TX4927_PCIC_PCICCFG_IISE |
+ TX4927_PCIC_PCICCFG_ICAE | TX4927_PCIC_PCICCFG_ATR;
+
+
+ /* Do not use MEMMUL, MEMINF: YMFPCI card causes M_ABORT. */
+ tx4927_pcicptr->pcicfg1 = 0;
+
+ if (tx4927_pcic_trdyto >= 0) {
+ tx4927_pcicptr->g2ptocnt &= ~0xff;
+ tx4927_pcicptr->g2ptocnt |= (tx4927_pcic_trdyto & 0xff);
+ }
+
+ /* Clear All Local Bus Status */
+ tx4927_pcicptr->pcicstatus = TX4927_PCIC_PCICSTATUS_ALL;
+ /* Enable All Local Bus Interrupts */
+ tx4927_pcicptr->pcicmask = TX4927_PCIC_PCICSTATUS_ALL;
+ /* Clear All Initiator Status */
+ tx4927_pcicptr->g2pstatus = TX4927_PCIC_G2PSTATUS_ALL;
+ /* Enable All Initiator Interrupts */
+ tx4927_pcicptr->g2pmask = TX4927_PCIC_G2PSTATUS_ALL;
+ /* Clear All PCI Status Error */
+ tx4927_pcicptr->pcistatus =
+ (tx4927_pcicptr->pcistatus & 0x0000ffff) |
+ (TX4927_PCIC_PCISTATUS_ALL << 16);
+ /* Enable All PCI Status Error Interrupts */
+ tx4927_pcicptr->pcimask = TX4927_PCIC_PCISTATUS_ALL;
+
+ /* PCIC Int => IRC IRQ16 */
+ tx4927_pcicptr->pcicfg2 =
+ (tx4927_pcicptr->pcicfg2 & 0xffffff00) | TX4927_IR_PCIC;
+
+ if (!(tx4927_ccfgptr->ccfg & TX4927_CCFG_PCIXARB)) {
+ /* XXX */
+ } else {
+ /* Reset Bus Arbiter */
+ tx4927_pcicptr->pbacfg = TX4927_PCIC_PBACFG_RPBA;
+ /* Enable Bus Arbiter */
+ tx4927_pcicptr->pbacfg = TX4927_PCIC_PBACFG_PBAEN;
+ }
+
+ tx4927_pcicptr->pcistatus = PCI_COMMAND_MASTER |
+ PCI_COMMAND_MEMORY |
+ PCI_COMMAND_PARITY | PCI_COMMAND_SERR;
+
+ TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_PCI2,
+ ":pci setup complete:\n");
+ TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_PCI2, "+\n");
+}
+
+#endif /* CONFIG_PCI */
+
+void toshiba_rbtx4927_restart(char *command)
+{
+ printk(KERN_NOTICE "System Rebooting...\n");
+
+ /* enable the s/w reset register */
+ reg_wr08(RBTX4927_SW_RESET_ENABLE, RBTX4927_SW_RESET_ENABLE_SET);
+
+ /* wait for enable to be seen */
+ while ((reg_rd08(RBTX4927_SW_RESET_ENABLE) &
+ RBTX4927_SW_RESET_ENABLE_SET) == 0x00);
+
+ /* do a s/w reset */
+ reg_wr08(RBTX4927_SW_RESET_DO, RBTX4927_SW_RESET_DO_SET);
+
+ /* do something passive while waiting for reset */
+ local_irq_disable();
+ while (1)
+ asm_wait();
+
+ /* no return */
+}
+
+
+void toshiba_rbtx4927_halt(void)
+{
+ printk(KERN_NOTICE "System Halted\n");
+ local_irq_disable();
+ while (1) {
+ asm_wait();
+ }
+ /* no return */
+}
+
+void toshiba_rbtx4927_power_off(void)
+{
+ toshiba_rbtx4927_halt();
+ /* no return */
+}
+
+void __init toshiba_rbtx4927_setup(void)
+{
+ vu32 cp0_config;
+ char *argptr;
+
+ printk("CPU is %s\n", toshiba_name);
+
+ TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_SETUP,
+ "-\n");
+
+ /* f/w leaves this on at startup */
+ TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_SETUP,
+ ":Clearing STO_ERL.\n");
+ clear_c0_status(ST0_ERL);
+
+ /* enable caches -- HCP5 does this, pmon does not */
+ TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_SETUP,
+ ":Enabling TX49_CONF_IC,TX49_CONF_DC.\n");
+ cp0_config = read_c0_config();
+ cp0_config = cp0_config & ~(TX49_CONF_IC | TX49_CONF_DC);
+ write_c0_config(cp0_config);
+
+#ifdef TOSHIBA_RBTX4927_SETUP_DEBUG
+ {
+ extern void dump_cp0(char *);
+ dump_cp0("toshiba_rbtx4927_early_fw_fixup");
+ }
+#endif
+
+ /* setup irq stuff */
+ TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_SETUP,
+ ":Setting up tx4927 pic.\n");
+ TX4927_WR(0xff1ff604, 0x00000400); /* irq trigger */
+ TX4927_WR(0xff1ff608, 0x00000000); /* irq trigger */
+
+ /* setup serial stuff */
+ TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_SETUP,
+ ":Setting up tx4927 sio.\n");
+ TX4927_WR(0xff1ff314, 0x00000000); /* h/w flow control off */
+ TX4927_WR(0xff1ff414, 0x00000000); /* h/w flow control off */
+
+ TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_SETUP,
+ "+\n");
+
+ set_io_port_base(KSEG1 + TBTX4927_ISA_IO_OFFSET);
+ TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_SETUP,
+ ":mips_io_port_base=0x%08lx\n",
+ mips_io_port_base);
+
+ TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_SETUP,
+ ":Resource\n");
+ ioport_resource.end = 0xffffffff;
+ iomem_resource.end = 0xffffffff;
+
+ TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_SETUP,
+ ":ResetRoutines\n");
+ _machine_restart = toshiba_rbtx4927_restart;
+ _machine_halt = toshiba_rbtx4927_halt;
+ _machine_power_off = toshiba_rbtx4927_power_off;
+
+#ifdef CONFIG_PCI
+
+ /* PCIC */
+ /*
+ * ASSUMPTION: PCIDIVMODE is configured for PCI 33MHz or 66MHz.
+ * PCIDIVMODE[12:11]'s initial value are given by S9[4:3] (ON:0, OFF:1).
+ * CPU 166MHz: PCI 66MHz : PCIDIVMODE: 00 (1/2.5)
+ * CPU 200MHz: PCI 66MHz : PCIDIVMODE: 01 (1/3)
+ * CPU 166MHz: PCI 33MHz : PCIDIVMODE: 10 (1/5)
+ * CPU 200MHz: PCI 33MHz : PCIDIVMODE: 11 (1/6)
+ * i.e. S9[3]: ON (83MHz), OFF (100MHz)
+ */
+ TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_PCI1,
+ "ccfg is %lx, DIV is %x\n",
+ (unsigned long) tx4927_ccfgptr->
+ ccfg, TX4927_CCFG_PCIDIVMODE_MASK);
+
+ TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_PCI1,
+ "PCI66 mode is %lx, PCI mode is %lx, pci arb is %lx\n",
+ (unsigned long) tx4927_ccfgptr->
+ ccfg & TX4927_CCFG_PCI66,
+ (unsigned long) tx4927_ccfgptr->
+ ccfg & TX4927_CCFG_PCIMIDE,
+ (unsigned long) tx4927_ccfgptr->
+ ccfg & TX4927_CCFG_PCIXARB);
+
+ TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_PCI1,
+ "PCIDIVMODE is %lx\n",
+ (unsigned long) tx4927_ccfgptr->
+ ccfg & TX4927_CCFG_PCIDIVMODE_MASK);
+
+ switch ((unsigned long) tx4927_ccfgptr->
+ ccfg & TX4927_CCFG_PCIDIVMODE_MASK) {
+ case TX4927_CCFG_PCIDIVMODE_2_5:
+ case TX4927_CCFG_PCIDIVMODE_5:
+ tx4927_cpu_clock = 166000000; /* 166MHz */
+ break;
+ default:
+ tx4927_cpu_clock = 200000000; /* 200MHz */
+ }
+
+ /* CCFG */
+ /* enable Timeout BusError */
+ if (tx4927_ccfg_toeon)
+ tx4927_ccfgptr->ccfg |= TX4927_CCFG_TOE;
+
+ /* SDRAMC fixup */
+#ifdef CONFIG_TX4927BUG_WORKAROUND
+ /*
+ * TX4927-BUG: INF 01-01-18/ BUG 01-01-22
+ * G-bus timeout error detection is incorrect
+ */
+ if (tx4927_ccfg_toeon)
+ tx4927_sdramcptr->tr |= 0x02000000; /* RCD:3tck */
+#endif
+
+ tx4927_pci_setup();
+ if (tx4927_using_backplane == 1)
+ printk("backplane board IS installed\n");
+ else
+ printk("No Backplane \n");
+
+ /* this is on ISA bus behind PCI bus, so need PCI up first */
+#ifdef CONFIG_TOSHIBA_FPCIB0
+ {
+ if (tx4927_using_backplane) {
+ TOSHIBA_RBTX4927_SETUP_DPRINTK
+ (TOSHIBA_RBTX4927_SETUP_SETUP,
+ ":fpcibo=yes\n");
+
+ TOSHIBA_RBTX4927_SETUP_DPRINTK
+ (TOSHIBA_RBTX4927_SETUP_SETUP,
+ ":smsc_fdc37m81x_init()\n");
+ smsc_fdc37m81x_init(0x3f0);
+
+ TOSHIBA_RBTX4927_SETUP_DPRINTK
+ (TOSHIBA_RBTX4927_SETUP_SETUP,
+ ":smsc_fdc37m81x_config_beg()\n");
+ smsc_fdc37m81x_config_beg();
+
+ TOSHIBA_RBTX4927_SETUP_DPRINTK
+ (TOSHIBA_RBTX4927_SETUP_SETUP,
+ ":smsc_fdc37m81x_config_set(KBD)\n");
+ smsc_fdc37m81x_config_set(SMSC_FDC37M81X_DNUM,
+ SMSC_FDC37M81X_KBD);
+ smsc_fdc37m81x_config_set(SMSC_FDC37M81X_INT, 1);
+ smsc_fdc37m81x_config_set(SMSC_FDC37M81X_INT2, 12);
+ smsc_fdc37m81x_config_set(SMSC_FDC37M81X_ACTIVE,
+ 1);
+
+ smsc_fdc37m81x_config_end();
+ TOSHIBA_RBTX4927_SETUP_DPRINTK
+ (TOSHIBA_RBTX4927_SETUP_SETUP,
+ ":smsc_fdc37m81x_config_end()\n");
+ } else {
+ TOSHIBA_RBTX4927_SETUP_DPRINTK
+ (TOSHIBA_RBTX4927_SETUP_SETUP,
+ ":fpcibo=not_found\n");
+ }
+ }
+#else
+ {
+ TOSHIBA_RBTX4927_SETUP_DPRINTK
+ (TOSHIBA_RBTX4927_SETUP_SETUP, ":fpcibo=no\n");
+ }
+#endif
+
+#endif /* CONFIG_PCI */
+
+#ifdef CONFIG_SERIAL_TXX9_CONSOLE
+ argptr = prom_getcmdline();
+ if (strstr(argptr, "console=") == NULL) {
+ strcat(argptr, " console=ttyS0,38400");
+ }
+#endif
+
+#ifdef CONFIG_ROOT_NFS
+ argptr = prom_getcmdline();
+ if (strstr(argptr, "root=") == NULL) {
+ strcat(argptr, " root=/dev/nfs rw");
+ }
+#endif
+
+
+#ifdef CONFIG_IP_PNP
+ argptr = prom_getcmdline();
+ if (strstr(argptr, "ip=") == NULL) {
+ strcat(argptr, " ip=any");
+ }
+#endif
+
+
+ TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_SETUP,
+ "+\n");
+}
+
+#ifdef CONFIG_RTC_DS1742
+extern unsigned long rtc_ds1742_get_time(void);
+extern int rtc_ds1742_set_time(unsigned long);
+extern void rtc_ds1742_wait(void);
+#endif
+
+void __init
+toshiba_rbtx4927_time_init(void)
+{
+ u32 c1;
+ u32 c2;
+
+ TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_TIME_INIT, "-\n");
+
+#ifdef CONFIG_RTC_DS1742
+
+ rtc_get_time = rtc_ds1742_get_time;
+ rtc_set_time = rtc_ds1742_set_time;
+
+ TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_TIME_INIT,
+ ":rtc_ds1742_init()-\n");
+ rtc_ds1742_init(0xbc010000);
+ TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_TIME_INIT,
+ ":rtc_ds1742_init()+\n");
+
+ TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_TIME_INIT,
+ ":Calibrate mips_hpt_frequency-\n");
+ rtc_ds1742_wait();
+
+ /* get the count */
+ c1 = read_c0_count();
+
+ /* wait for the seconds to change again */
+ rtc_ds1742_wait();
+
+ /* get the count again */
+ c2 = read_c0_count();
+
+ TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_TIME_INIT,
+ ":Calibrate mips_hpt_frequency+\n");
+ TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_TIME_INIT,
+ ":c1=%12u\n", c1);
+ TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_TIME_INIT,
+ ":c2=%12u\n", c2);
+
+ /* this diff is as close as we are going to get to counter ticks per sec */
+ mips_hpt_frequency = abs(c2 - c1);
+ TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_TIME_INIT,
+ ":f1=%12u\n", mips_hpt_frequency);
+
+ /* round to 1/10th of a MHz */
+ mips_hpt_frequency /= (100 * 1000);
+ mips_hpt_frequency *= (100 * 1000);
+ TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_TIME_INIT,
+ ":f2=%12u\n", mips_hpt_frequency);
+
+ TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_INFO,
+ ":mips_hpt_frequency=%uHz (%uMHz)\n",
+ mips_hpt_frequency,
+ mips_hpt_frequency / 1000000);
+#else
+ mips_hpt_frequency = 100000000;
+#endif
+
+ TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_TIME_INIT, "+\n");
+
+}
+
+void __init toshiba_rbtx4927_timer_setup(struct irqaction *irq)
+{
+ TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_TIMER_SETUP,
+ "-\n");
+ TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_TIMER_SETUP,
+ "+\n");
+}
diff --git a/arch/mips/vr4181/common/Makefile b/arch/mips/vr4181/common/Makefile
new file mode 100644
index 0000000..f7587ca
--- /dev/null
+++ b/arch/mips/vr4181/common/Makefile
@@ -0,0 +1,7 @@
+#
+# Makefile for common code of NEC vr4181 based boards
+#
+
+obj-y := irq.o int_handler.o serial.o time.o
+
+EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/vr4181/common/int_handler.S b/arch/mips/vr4181/common/int_handler.S
new file mode 100644
index 0000000..2c041b8
--- /dev/null
+++ b/arch/mips/vr4181/common/int_handler.S
@@ -0,0 +1,206 @@
+/*
+ * arch/mips/vr4181/common/int_handler.S
+ *
+ * Adapted to the VR4181 and almost entirely rewritten:
+ * Copyright (C) 1999 Bradley D. LaRonde and Michael Klar
+ *
+ * Clean up to conform to the new IRQ
+ * Copyright (C) 2001 MontaVista Software Inc.
+ * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
+ *
+ * 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.
+ *
+ */
+
+#include <asm/asm.h>
+#include <asm/regdef.h>
+#include <asm/mipsregs.h>
+#include <asm/stackframe.h>
+
+#include <asm/vr4181/vr4181.h>
+
+/*
+ * [jsun]
+ * See include/asm/vr4181/irq.h for IRQ assignment and strategy.
+ */
+
+ .text
+ .set noreorder
+
+ .align 5
+ NESTED(vr4181_handle_irq, PT_SIZE, ra)
+
+ .set noat
+ SAVE_ALL
+ CLI
+
+ .set at
+ .set noreorder
+
+ mfc0 t0, CP0_CAUSE
+ mfc0 t2, CP0_STATUS
+
+ and t0, t2
+
+ /* we check IP3 first; it happens most frequently */
+ andi t1, t0, STATUSF_IP3
+ bnez t1, ll_cpu_ip3
+ andi t1, t0, STATUSF_IP2
+ bnez t1, ll_cpu_ip2
+ andi t1, t0, STATUSF_IP7 /* cpu timer */
+ bnez t1, ll_cputimer_irq
+ andi t1, t0, STATUSF_IP4
+ bnez t1, ll_cpu_ip4
+ andi t1, t0, STATUSF_IP5
+ bnez t1, ll_cpu_ip5
+ andi t1, t0, STATUSF_IP6
+ bnez t1, ll_cpu_ip6
+ andi t1, t0, STATUSF_IP0 /* software int 0 */
+ bnez t1, ll_cpu_ip0
+ andi t1, t0, STATUSF_IP1 /* software int 1 */
+ bnez t1, ll_cpu_ip1
+ nop
+
+ .set reorder
+do_spurious:
+ j spurious_interrupt
+
+/*
+ * regular CPU irqs
+ */
+ll_cputimer_irq:
+ li a0, VR4181_IRQ_TIMER
+ move a1, sp
+ jal do_IRQ
+ j ret_from_irq
+
+
+ll_cpu_ip0:
+ li a0, VR4181_IRQ_SW1
+ move a1, sp
+ jal do_IRQ
+ j ret_from_irq
+
+ll_cpu_ip1:
+ li a0, VR4181_IRQ_SW2
+ move a1, sp
+ jal do_IRQ
+ j ret_from_irq
+
+ll_cpu_ip3:
+ li a0, VR4181_IRQ_INT1
+ move a1, sp
+ jal do_IRQ
+ j ret_from_irq
+
+ll_cpu_ip4:
+ li a0, VR4181_IRQ_INT2
+ move a1, sp
+ jal do_IRQ
+ j ret_from_irq
+
+ll_cpu_ip5:
+ li a0, VR4181_IRQ_INT3
+ move a1, sp
+ jal do_IRQ
+ j ret_from_irq
+
+ll_cpu_ip6:
+ li a0, VR4181_IRQ_INT4
+ move a1, sp
+ jal do_IRQ
+ j ret_from_irq
+
+/*
+ * One of the sys irq has happend.
+ *
+ * In the interest of speed, we first determine in the following order
+ * which 16-irq block have pending interrupts:
+ * sysint1 (16 sources, including cascading intrs from GPIO)
+ * sysint2
+ * gpio (16 intr sources)
+ *
+ * Then we do binary search to find the exact interrupt source.
+ */
+ll_cpu_ip2:
+
+ lui t3,%hi(VR4181_SYSINT1REG)
+ lhu t0,%lo(VR4181_SYSINT1REG)(t3)
+ lhu t2,%lo(VR4181_MSYSINT1REG)(t3)
+ and t0, 0xfffb /* hack - remove RTC Long 1 intr */
+ and t0, t2
+ beqz t0, check_sysint2
+
+ /* check for GPIO interrupts */
+ andi t1, t0, 0x0100
+ bnez t1, check_gpio_int
+
+ /* so we have an interrupt in sysint1 which is not gpio int */
+ li a0, VR4181_SYS_IRQ_BASE - 1
+ j check_16
+
+check_sysint2:
+
+ lhu t0,%lo(VR4181_SYSINT2REG)(t3)
+ lhu t2,%lo(VR4181_MSYSINT2REG)(t3)
+ and t0, 0xfffe /* hack - remove RTC Long 2 intr */
+ and t0, t2
+ li a0, VR4181_SYS_IRQ_BASE + 16 - 1
+ j check_16
+
+check_gpio_int:
+ lui t3,%hi(VR4181_GPINTMSK)
+ lhu t0,%lo(VR4181_GPINTMSK)(t3)
+ lhu t2,%lo(VR4181_GPINTSTAT)(t3)
+ xori t0, 0xffff /* why? reverse logic? */
+ and t0, t2
+ li a0, VR4181_GPIO_IRQ_BASE - 1
+ j check_16
+
+/*
+ * When we reach check_16, we have 16-bit status in t0 and base irq number
+ * in a0.
+ */
+check_16:
+ andi t1, t0, 0xff
+ bnez t1, check_8
+
+ srl t0, 8
+ addi a0, 8
+ j check_8
+
+/*
+ * When we reach check_8, we have 8-bit status in t0 and base irq number
+ * in a0.
+ */
+check_8:
+ andi t1, t0, 0xf
+ bnez t1, check_4
+
+ srl t0, 4
+ addi a0, 4
+ j check_4
+
+/*
+ * When we reach check_4, we have 4-bit status in t0 and base irq number
+ * in a0.
+ */
+check_4:
+ andi t0, t0, 0xf
+ beqz t0, do_spurious
+
+loop:
+ andi t2, t0, 0x1
+ srl t0, 1
+ addi a0, 1
+ beqz t2, loop
+
+found_it:
+ move a1, sp
+ jal do_IRQ
+
+ j ret_from_irq
+
+ END(vr4181_handle_irq)
diff --git a/arch/mips/vr4181/common/irq.c b/arch/mips/vr4181/common/irq.c
new file mode 100644
index 0000000..2cdf77c
--- /dev/null
+++ b/arch/mips/vr4181/common/irq.c
@@ -0,0 +1,239 @@
+/*
+ * Copyright (C) 2001 MontaVista Software Inc.
+ * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
+ * Copyright (C) 2005 Ralf Baechle (ralf@linux-mips.org)
+ *
+ * linux/arch/mips/vr4181/common/irq.c
+ * Completely re-written to use the new irq.c
+ *
+ * Credits to Bradley D. LaRonde and Michael Klar for writing the original
+ * irq.c file which was derived from the common irq.c file.
+ *
+ * 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.
+ */
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/kernel_stat.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+
+#include <asm/irq.h>
+#include <asm/mipsregs.h>
+#include <asm/gdb-stub.h>
+
+#include <asm/vr4181/vr4181.h>
+
+/*
+ * Strategy:
+ *
+ * We essentially have three irq controllers, CPU, system, and gpio.
+ *
+ * CPU irq controller is taken care by arch/mips/kernel/irq_cpu.c and
+ * CONFIG_IRQ_CPU config option.
+ *
+ * We here provide sys_irq and gpio_irq controller code.
+ */
+
+static int sys_irq_base;
+static int gpio_irq_base;
+
+/* ---------------------- sys irq ------------------------ */
+static void
+sys_irq_enable(unsigned int irq)
+{
+ irq -= sys_irq_base;
+ if (irq < 16) {
+ *VR4181_MSYSINT1REG |= (u16)(1 << irq);
+ } else {
+ irq -= 16;
+ *VR4181_MSYSINT2REG |= (u16)(1 << irq);
+ }
+}
+
+static void
+sys_irq_disable(unsigned int irq)
+{
+ irq -= sys_irq_base;
+ if (irq < 16) {
+ *VR4181_MSYSINT1REG &= ~((u16)(1 << irq));
+ } else {
+ irq -= 16;
+ *VR4181_MSYSINT2REG &= ~((u16)(1 << irq));
+ }
+
+}
+
+static unsigned int
+sys_irq_startup(unsigned int irq)
+{
+ sys_irq_enable(irq);
+ return 0;
+}
+
+#define sys_irq_shutdown sys_irq_disable
+#define sys_irq_ack sys_irq_disable
+
+static void
+sys_irq_end(unsigned int irq)
+{
+ if(!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
+ sys_irq_enable(irq);
+}
+
+static hw_irq_controller sys_irq_controller = {
+ "vr4181_sys_irq",
+ sys_irq_startup,
+ sys_irq_shutdown,
+ sys_irq_enable,
+ sys_irq_disable,
+ sys_irq_ack,
+ sys_irq_end,
+ NULL /* no affinity stuff for UP */
+};
+
+/* ---------------------- gpio irq ------------------------ */
+/* gpio irq lines use reverse logic */
+static void
+gpio_irq_enable(unsigned int irq)
+{
+ irq -= gpio_irq_base;
+ *VR4181_GPINTMSK &= ~((u16)(1 << irq));
+}
+
+static void
+gpio_irq_disable(unsigned int irq)
+{
+ irq -= gpio_irq_base;
+ *VR4181_GPINTMSK |= (u16)(1 << irq);
+}
+
+static unsigned int
+gpio_irq_startup(unsigned int irq)
+{
+ gpio_irq_enable(irq);
+
+ irq -= gpio_irq_base;
+ *VR4181_GPINTEN |= (u16)(1 << irq );
+
+ return 0;
+}
+
+static void
+gpio_irq_shutdown(unsigned int irq)
+{
+ gpio_irq_disable(irq);
+
+ irq -= gpio_irq_base;
+ *VR4181_GPINTEN &= ~((u16)(1 << irq ));
+}
+
+static void
+gpio_irq_ack(unsigned int irq)
+{
+ u16 irqtype;
+ u16 irqshift;
+
+ gpio_irq_disable(irq);
+
+ /* we clear interrupt if it is edge triggered */
+ irq -= gpio_irq_base;
+ if (irq < 8) {
+ irqtype = *VR4181_GPINTTYPL;
+ irqshift = 2 << (irq*2);
+ } else {
+ irqtype = *VR4181_GPINTTYPH;
+ irqshift = 2 << ((irq-8)*2);
+ }
+ if ( ! (irqtype & irqshift) ) {
+ *VR4181_GPINTSTAT = (u16) (1 << irq);
+ }
+}
+
+static void
+gpio_irq_end(unsigned int irq)
+{
+ if(!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
+ gpio_irq_enable(irq);
+}
+
+static hw_irq_controller gpio_irq_controller = {
+ "vr4181_gpio_irq",
+ gpio_irq_startup,
+ gpio_irq_shutdown,
+ gpio_irq_enable,
+ gpio_irq_disable,
+ gpio_irq_ack,
+ gpio_irq_end,
+ NULL /* no affinity stuff for UP */
+};
+
+/* --------------------- IRQ init stuff ---------------------- */
+
+extern asmlinkage void vr4181_handle_irq(void);
+extern void breakpoint(void);
+extern int setup_irq(unsigned int irq, struct irqaction *irqaction);
+extern void mips_cpu_irq_init(u32 irq_base);
+
+static struct irqaction cascade =
+ { no_action, SA_INTERRUPT, CPU_MASK_NONE, "cascade", NULL, NULL };
+static struct irqaction reserved =
+ { no_action, SA_INTERRUPT, CPU_MASK_NONE, "cascade", NULL, NULL };
+
+void __init arch_init_irq(void)
+{
+ int i;
+
+ set_except_vector(0, vr4181_handle_irq);
+
+ /* init CPU irqs */
+ mips_cpu_irq_init(VR4181_CPU_IRQ_BASE);
+
+ /* init sys irqs */
+ sys_irq_base = VR4181_SYS_IRQ_BASE;
+ for (i=sys_irq_base; i < sys_irq_base + VR4181_NUM_SYS_IRQ; i++) {
+ irq_desc[i].status = IRQ_DISABLED;
+ irq_desc[i].action = NULL;
+ irq_desc[i].depth = 1;
+ irq_desc[i].handler = &sys_irq_controller;
+ }
+
+ /* init gpio irqs */
+ gpio_irq_base = VR4181_GPIO_IRQ_BASE;
+ for (i=gpio_irq_base; i < gpio_irq_base + VR4181_NUM_GPIO_IRQ; i++) {
+ irq_desc[i].status = IRQ_DISABLED;
+ irq_desc[i].action = NULL;
+ irq_desc[i].depth = 1;
+ irq_desc[i].handler = &gpio_irq_controller;
+ }
+
+ /* Default all ICU IRQs to off ... */
+ *VR4181_MSYSINT1REG = 0;
+ *VR4181_MSYSINT2REG = 0;
+
+ /* We initialize the level 2 ICU registers to all bits disabled. */
+ *VR4181_MPIUINTREG = 0;
+ *VR4181_MAIUINTREG = 0;
+ *VR4181_MKIUINTREG = 0;
+
+ /* disable all GPIO intrs */
+ *VR4181_GPINTMSK = 0xffff;
+
+ /* vector handler. What these do is register the IRQ as non-sharable */
+ setup_irq(VR4181_IRQ_INT0, &cascade);
+ setup_irq(VR4181_IRQ_GIU, &cascade);
+
+ /*
+ * RTC interrupts are interesting. They have two destinations.
+ * One is at sys irq controller, and the other is at CPU IP3 and IP4.
+ * RTC timer is used as system timer.
+ * We enable them here, but timer routine will register later
+ * with CPU IP3/IP4.
+ */
+ setup_irq(VR4181_IRQ_RTCL1, &reserved);
+ setup_irq(VR4181_IRQ_RTCL2, &reserved);
+}
diff --git a/arch/mips/vr4181/common/serial.c b/arch/mips/vr4181/common/serial.c
new file mode 100644
index 0000000..3f62c62
--- /dev/null
+++ b/arch/mips/vr4181/common/serial.c
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
+ *
+ * arch/mips/vr4181/common/serial.c
+ * initialize serial port on vr4181.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+
+/*
+ * [jsun, 010925]
+ * You need to make sure rs_table has at least one element in
+ * drivers/char/serial.c file. There is no good way to do it right
+ * now. A workaround is to include CONFIG_SERIAL_MANY_PORTS in your
+ * configure file, which would gives you 64 ports and wastes 11K ram.
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/serial.h>
+
+#include <asm/vr4181/vr4181.h>
+
+void __init vr4181_init_serial(void)
+{
+ struct serial_struct s;
+
+ /* turn on UART clock */
+ *VR4181_CMUCLKMSK |= VR4181_CMUCLKMSK_MSKSIU;
+
+ /* clear memory */
+ memset(&s, 0, sizeof(s));
+
+ s.line = 0; /* we set the first one */
+ s.baud_base = 1152000;
+ s.irq = VR4181_IRQ_SIU;
+ s.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST; /* STD_COM_FLAGS */
+ s.iomem_base = (u8*)VR4181_SIURB;
+ s.iomem_reg_shift = 0;
+ s.io_type = SERIAL_IO_MEM;
+ if (early_serial_setup(&s) != 0) {
+ panic("vr4181_init_serial() failed!");
+ }
+}
+
diff --git a/arch/mips/vr4181/common/time.c b/arch/mips/vr4181/common/time.c
new file mode 100644
index 0000000..1781407
--- /dev/null
+++ b/arch/mips/vr4181/common/time.c
@@ -0,0 +1,145 @@
+/*
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: jsun@mvista.com or jsun@junsun.net
+ *
+ * rtc and time ops for vr4181. Part of code is drived from
+ * linux-vr, originally written by Bradley D. LaRonde & Michael Klar.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/param.h> /* for HZ */
+#include <linux/time.h>
+#include <linux/interrupt.h>
+
+#include <asm/system.h>
+#include <asm/time.h>
+
+#include <asm/vr4181/vr4181.h>
+
+#define COUNTS_PER_JIFFY ((32768 + HZ/2) / HZ)
+
+/*
+ * RTC ops
+ */
+
+DEFINE_SPINLOCK(rtc_lock);
+
+/* per VR41xx docs, bad data can be read if between 2 counts */
+static inline unsigned short
+read_time_reg(volatile unsigned short *reg)
+{
+ unsigned short value;
+ do {
+ value = *reg;
+ barrier();
+ } while (value != *reg);
+ return value;
+}
+
+static unsigned long
+vr4181_rtc_get_time(void)
+{
+ unsigned short regh, regm, regl;
+
+ // why this crazy order, you ask? to guarantee that neither m
+ // nor l wrap before all 3 read
+ do {
+ regm = read_time_reg(VR4181_ETIMEMREG);
+ barrier();
+ regh = read_time_reg(VR4181_ETIMEHREG);
+ barrier();
+ regl = read_time_reg(VR4181_ETIMELREG);
+ } while (regm != read_time_reg(VR4181_ETIMEMREG));
+ return ((regh << 17) | (regm << 1) | (regl >> 15));
+}
+
+static int
+vr4181_rtc_set_time(unsigned long timeval)
+{
+ unsigned short intreg;
+ unsigned long flags;
+
+ spin_lock_irqsave(&rtc_lock, flags);
+ intreg = *VR4181_RTCINTREG & 0x05;
+ barrier();
+ *VR4181_ETIMELREG = timeval << 15;
+ *VR4181_ETIMEMREG = timeval >> 1;
+ *VR4181_ETIMEHREG = timeval >> 17;
+ barrier();
+ // assume that any ints that just triggered are invalid, since the
+ // time value is written non-atomically in 3 separate regs
+ *VR4181_RTCINTREG = 0x05 ^ intreg;
+ spin_unlock_irqrestore(&rtc_lock, flags);
+
+ return 0;
+}
+
+
+/*
+ * timer interrupt routine (wrapper)
+ *
+ * we need our own interrupt routine because we need to clear
+ * RTC1 interrupt.
+ */
+static void
+vr4181_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ /* Clear the interrupt. */
+ *VR4181_RTCINTREG = 0x2;
+
+ /* call the generic one */
+ timer_interrupt(irq, dev_id, regs);
+}
+
+
+/*
+ * vr4181_time_init:
+ *
+ * We pick the following choices:
+ * . we use elapsed timer as the RTC. We set some reasonable init data since
+ * it does not persist across reset
+ * . we use RTC1 as the system timer interrupt source.
+ * . we use CPU counter for fast_gettimeoffset and we calivrate the cpu
+ * frequency. In other words, we use calibrate_div64_gettimeoffset().
+ * . we use our own timer interrupt routine which clears the interrupt
+ * and then calls the generic high-level timer interrupt routine.
+ *
+ */
+
+extern int setup_irq(unsigned int irq, struct irqaction *irqaction);
+
+static void
+vr4181_timer_setup(struct irqaction *irq)
+{
+ /* over-write the handler to be our own one */
+ irq->handler = vr4181_timer_interrupt;
+
+ /* sets up the frequency */
+ *VR4181_RTCL1LREG = COUNTS_PER_JIFFY;
+ *VR4181_RTCL1HREG = 0;
+
+ /* and ack any pending ints */
+ *VR4181_RTCINTREG = 0x2;
+
+ /* setup irqaction */
+ setup_irq(VR4181_IRQ_INT1, irq);
+
+}
+
+void
+vr4181_init_time(void)
+{
+ /* setup hookup functions */
+ rtc_get_time = vr4181_rtc_get_time;
+ rtc_set_time = vr4181_rtc_set_time;
+
+ board_timer_setup = vr4181_timer_setup;
+}
+
diff --git a/arch/mips/vr4181/osprey/Makefile b/arch/mips/vr4181/osprey/Makefile
new file mode 100644
index 0000000..34be057
--- /dev/null
+++ b/arch/mips/vr4181/osprey/Makefile
@@ -0,0 +1,7 @@
+#
+# Makefile for common code of NEC Osprey board
+#
+
+obj-y := setup.o prom.o reset.o
+
+obj-$(CONFIG_KGDB) += dbg_io.o
diff --git a/arch/mips/vr4181/osprey/dbg_io.c b/arch/mips/vr4181/osprey/dbg_io.c
new file mode 100644
index 0000000..5e8a840
--- /dev/null
+++ b/arch/mips/vr4181/osprey/dbg_io.c
@@ -0,0 +1,136 @@
+/*
+ * kgdb io functions for osprey. We use the serial port on debug board.
+ *
+ * Copyright (C) 2001 MontaVista Software Inc.
+ * Author: jsun@mvista.com or jsun@junsun.net
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+
+/* ======================= CONFIG ======================== */
+
+/* [jsun] we use the second serial port for kdb */
+#define BASE 0xb7fffff0
+#define MAX_BAUD 115200
+
+/* distance in bytes between two serial registers */
+#define REG_OFFSET 1
+
+/*
+ * 0 - kgdb does serial init
+ * 1 - kgdb skip serial init
+ */
+static int remoteDebugInitialized = 1;
+
+/*
+ * the default baud rate *if* kgdb does serial init
+ */
+#define BAUD_DEFAULT UART16550_BAUD_38400
+
+/* ======================= END OF CONFIG ======================== */
+
+typedef unsigned char uint8;
+typedef unsigned int uint32;
+
+#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
+
+/* register offset */
+#define OFS_RCV_BUFFER 0
+#define OFS_TRANS_HOLD 0
+#define OFS_SEND_BUFFER 0
+#define OFS_INTR_ENABLE (1*REG_OFFSET)
+#define OFS_INTR_ID (2*REG_OFFSET)
+#define OFS_DATA_FORMAT (3*REG_OFFSET)
+#define OFS_LINE_CONTROL (3*REG_OFFSET)
+#define OFS_MODEM_CONTROL (4*REG_OFFSET)
+#define OFS_RS232_OUTPUT (4*REG_OFFSET)
+#define OFS_LINE_STATUS (5*REG_OFFSET)
+#define OFS_MODEM_STATUS (6*REG_OFFSET)
+#define OFS_RS232_INPUT (6*REG_OFFSET)
+#define OFS_SCRATCH_PAD (7*REG_OFFSET)
+
+#define OFS_DIVISOR_LSB (0*REG_OFFSET)
+#define OFS_DIVISOR_MSB (1*REG_OFFSET)
+
+
+/* memory-mapped read/write of the port */
+#define UART16550_READ(y) (*((volatile uint8*)(BASE + y)))
+#define UART16550_WRITE(y, z) ((*((volatile uint8*)(BASE + y))) = z)
+
+void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop)
+{
+ /* disable interrupts */
+ UART16550_WRITE(OFS_INTR_ENABLE, 0);
+
+ /* set up buad rate */
+ {
+ uint32 divisor;
+
+ /* set DIAB bit */
+ UART16550_WRITE(OFS_LINE_CONTROL, 0x80);
+
+ /* set divisor */
+ divisor = MAX_BAUD / baud;
+ UART16550_WRITE(OFS_DIVISOR_LSB, divisor & 0xff);
+ UART16550_WRITE(OFS_DIVISOR_MSB, (divisor & 0xff00) >> 8);
+
+ /* clear DIAB bit */
+ UART16550_WRITE(OFS_LINE_CONTROL, 0x0);
+ }
+
+ /* set data format */
+ UART16550_WRITE(OFS_DATA_FORMAT, data | parity | stop);
+}
+
+
+uint8 getDebugChar(void)
+{
+ if (!remoteDebugInitialized) {
+ remoteDebugInitialized = 1;
+ debugInit(BAUD_DEFAULT,
+ UART16550_DATA_8BIT,
+ UART16550_PARITY_NONE, UART16550_STOP_1BIT);
+ }
+
+ while ((UART16550_READ(OFS_LINE_STATUS) & 0x1) == 0);
+ return UART16550_READ(OFS_RCV_BUFFER);
+}
+
+
+int putDebugChar(uint8 byte)
+{
+ if (!remoteDebugInitialized) {
+ remoteDebugInitialized = 1;
+ debugInit(BAUD_DEFAULT,
+ UART16550_DATA_8BIT,
+ UART16550_PARITY_NONE, UART16550_STOP_1BIT);
+ }
+
+ while ((UART16550_READ(OFS_LINE_STATUS) & 0x20) == 0);
+ UART16550_WRITE(OFS_SEND_BUFFER, byte);
+ return 1;
+}
diff --git a/arch/mips/vr4181/osprey/prom.c b/arch/mips/vr4181/osprey/prom.c
new file mode 100644
index 0000000..af0d145
--- /dev/null
+++ b/arch/mips/vr4181/osprey/prom.c
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: jsun@mvista.com or jsun@junsun.net
+ *
+ * arch/mips/vr4181/osprey/prom.c
+ * prom code for osprey.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/bootmem.h>
+#include <asm/bootinfo.h>
+#include <asm/addrspace.h>
+
+const char *get_system_type(void)
+{
+ return "NEC_Vr41xx Osprey";
+}
+
+/*
+ * [jsun] right now we assume it is the nec debug monitor, which does
+ * not pass any arguments.
+ */
+void __init prom_init(void)
+{
+ // cmdline is now set in default config
+ // strcpy(arcs_cmdline, "ip=bootp ");
+ // strcat(arcs_cmdline, "ether=46,0x03fe0300,eth0 ");
+ // strcpy(arcs_cmdline, "ether=0,0x0300,eth0 "
+ // strcat(arcs_cmdline, "video=vr4181fb:xres:240,yres:320,bpp:8 ");
+
+ mips_machgroup = MACH_GROUP_NEC_VR41XX;
+ mips_machtype = MACH_NEC_OSPREY;
+
+ /* 16MB fixed */
+ add_memory_region(0, 16 << 20, BOOT_MEM_RAM);
+}
+
+unsigned long __init prom_free_prom_memory(void)
+{
+ return 0;
+}
diff --git a/arch/mips/vr4181/osprey/reset.c b/arch/mips/vr4181/osprey/reset.c
new file mode 100644
index 0000000..036ae83
--- /dev/null
+++ b/arch/mips/vr4181/osprey/reset.c
@@ -0,0 +1,40 @@
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * Copyright (C) 1997, 2001 Ralf Baechle
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: jsun@mvista.com or jsun@junsun.net
+ */
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <asm/io.h>
+#include <asm/cacheflush.h>
+#include <asm/processor.h>
+#include <asm/reboot.h>
+#include <asm/system.h>
+
+void nec_osprey_restart(char *command)
+{
+ set_c0_status(ST0_ERL);
+ change_c0_config(CONF_CM_CMASK, CONF_CM_UNCACHED);
+ flush_cache_all();
+ write_c0_wired(0);
+ __asm__ __volatile__("jr\t%0"::"r"(0xbfc00000));
+}
+
+void nec_osprey_halt(void)
+{
+ printk(KERN_NOTICE "\n** You can safely turn off the power\n");
+ while (1)
+ __asm__(".set\tmips3\n\t"
+ "wait\n\t"
+ ".set\tmips0");
+}
+
+void nec_osprey_power_off(void)
+{
+ nec_osprey_halt();
+}
diff --git a/arch/mips/vr4181/osprey/setup.c b/arch/mips/vr4181/osprey/setup.c
new file mode 100644
index 0000000..2ff7140
--- /dev/null
+++ b/arch/mips/vr4181/osprey/setup.c
@@ -0,0 +1,68 @@
+/*
+ * linux/arch/mips/vr4181/setup.c
+ *
+ * VR41xx setup routines
+ *
+ * Copyright (C) 1999 Bradley D. LaRonde
+ * Copyright (C) 1999, 2000 Michael Klar
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: jsun@mvista.com or jsun@junsun.net
+ * Copyright (C) 2005 Ralf Baechle (ralf@linux-mips.org)
+ *
+ * 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.
+ *
+ */
+
+#include <linux/ide.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <asm/reboot.h>
+#include <asm/vr4181/vr4181.h>
+#include <asm/io.h>
+
+
+extern void nec_osprey_restart(char* c);
+extern void nec_osprey_halt(void);
+extern void nec_osprey_power_off(void);
+
+extern void vr4181_init_serial(void);
+extern void vr4181_init_time(void);
+
+static void __init nec_osprey_setup(void)
+{
+ set_io_port_base(VR4181_PORT_BASE);
+ isa_slot_offset = VR4181_ISAMEM_BASE;
+
+ vr4181_init_serial();
+ vr4181_init_time();
+
+ _machine_restart = nec_osprey_restart;
+ _machine_halt = nec_osprey_halt;
+ _machine_power_off = nec_osprey_power_off;
+
+ /* setup resource limit */
+ ioport_resource.end = 0xffffffff;
+ iomem_resource.end = 0xffffffff;
+
+ /* [jsun] hack */
+ /*
+ printk("[jsun] hack to change external ISA control register, %x -> %x\n",
+ (*VR4181_XISACTL),
+ (*VR4181_XISACTL) | 0x2);
+ *VR4181_XISACTL |= 0x2;
+ */
+
+ // *VR4181_GPHIBSTH = 0x2000;
+ // *VR4181_GPMD0REG = 0x00c0;
+ // *VR4181_GPINTEN = 1<<6;
+
+ /* [jsun] I believe this will get the interrupt type right
+ * for the ether port.
+ */
+ *VR4181_GPINTTYPL = 0x3000;
+}
+
+early_initcall(nec_osprey_setup);
diff --git a/arch/mips/vr41xx/casio-e55/Makefile b/arch/mips/vr41xx/casio-e55/Makefile
new file mode 100644
index 0000000..d4c03cc
--- /dev/null
+++ b/arch/mips/vr41xx/casio-e55/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for the CASIO CASSIOPEIA E-55/65 specific parts of the kernel
+#
+
+obj-y += setup.o
diff --git a/arch/mips/vr41xx/casio-e55/setup.c b/arch/mips/vr41xx/casio-e55/setup.c
new file mode 100644
index 0000000..aa8605a
--- /dev/null
+++ b/arch/mips/vr41xx/casio-e55/setup.c
@@ -0,0 +1,40 @@
+/*
+ * setup.c, Setup for the CASIO CASSIOPEIA E-11/15/55/65.
+ *
+ * Copyright (C) 2002-2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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 <linux/init.h>
+#include <linux/ioport.h>
+
+#include <asm/io.h>
+#include <asm/vr41xx/e55.h>
+
+const char *get_system_type(void)
+{
+ return "CASIO CASSIOPEIA E-11/15/55/65";
+}
+
+static int __init casio_e55_setup(void)
+{
+ set_io_port_base(IO_PORT_BASE);
+ ioport_resource.start = IO_PORT_RESOURCE_START;
+ ioport_resource.end = IO_PORT_RESOURCE_END;
+
+ return 0;
+}
+
+arch_initcall(casio_e55_setup);
diff --git a/arch/mips/vr41xx/common/Makefile b/arch/mips/vr41xx/common/Makefile
new file mode 100644
index 0000000..92c11e9
--- /dev/null
+++ b/arch/mips/vr41xx/common/Makefile
@@ -0,0 +1,8 @@
+#
+# Makefile for common code of the NEC VR4100 series.
+#
+
+obj-y += bcu.o cmu.o giu.o icu.o init.o int-handler.o pmu.o
+obj-$(CONFIG_VRC4173) += vrc4173.o
+
+EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/vr41xx/common/bcu.c b/arch/mips/vr41xx/common/bcu.c
new file mode 100644
index 0000000..cdfa427
--- /dev/null
+++ b/arch/mips/vr41xx/common/bcu.c
@@ -0,0 +1,222 @@
+/*
+ * bcu.c, Bus Control Unit routines for the NEC VR4100 series.
+ *
+ * Copyright (C) 2002 MontaVista Software Inc.
+ * Author: Yoichi Yuasa <yyuasa@mvista.com, or source@mvista.com>
+ * Copyright (C) 2003-2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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
+ */
+/*
+ * Changes:
+ * MontaVista Software Inc. <yyuasa@mvista.com> or <source@mvista.com>
+ * - New creation, NEC VR4122 and VR4131 are supported.
+ * - Added support for NEC VR4111 and VR4121.
+ *
+ * Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ * - Added support for NEC VR4133.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/smp.h>
+#include <linux/types.h>
+
+#include <asm/cpu.h>
+#include <asm/io.h>
+
+#define CLKSPEEDREG_TYPE1 (void __iomem *)KSEG1ADDR(0x0b000014)
+#define CLKSPEEDREG_TYPE2 (void __iomem *)KSEG1ADDR(0x0f000014)
+ #define CLKSP(x) ((x) & 0x001f)
+ #define CLKSP_VR4133(x) ((x) & 0x0007)
+
+ #define DIV2B 0x8000
+ #define DIV3B 0x4000
+ #define DIV4B 0x2000
+
+ #define DIVT(x) (((x) & 0xf000) >> 12)
+ #define DIVVT(x) (((x) & 0x0f00) >> 8)
+
+ #define TDIVMODE(x) (2 << (((x) & 0x1000) >> 12))
+ #define VTDIVMODE(x) (((x) & 0x0700) >> 8)
+
+static unsigned long vr41xx_vtclock;
+static unsigned long vr41xx_tclock;
+
+unsigned long vr41xx_get_vtclock_frequency(void)
+{
+ return vr41xx_vtclock;
+}
+
+EXPORT_SYMBOL_GPL(vr41xx_get_vtclock_frequency);
+
+unsigned long vr41xx_get_tclock_frequency(void)
+{
+ return vr41xx_tclock;
+}
+
+EXPORT_SYMBOL_GPL(vr41xx_get_tclock_frequency);
+
+static inline uint16_t read_clkspeed(void)
+{
+ switch (current_cpu_data.cputype) {
+ case CPU_VR4111:
+ case CPU_VR4121: return readw(CLKSPEEDREG_TYPE1);
+ case CPU_VR4122:
+ case CPU_VR4131:
+ case CPU_VR4133: return readw(CLKSPEEDREG_TYPE2);
+ default:
+ printk(KERN_INFO "Unexpected CPU of NEC VR4100 series\n");
+ break;
+ }
+
+ return 0;
+}
+
+static inline unsigned long calculate_pclock(uint16_t clkspeed)
+{
+ unsigned long pclock = 0;
+
+ switch (current_cpu_data.cputype) {
+ case CPU_VR4111:
+ case CPU_VR4121:
+ pclock = 18432000 * 64;
+ pclock /= CLKSP(clkspeed);
+ break;
+ case CPU_VR4122:
+ pclock = 18432000 * 98;
+ pclock /= CLKSP(clkspeed);
+ break;
+ case CPU_VR4131:
+ pclock = 18432000 * 108;
+ pclock /= CLKSP(clkspeed);
+ break;
+ case CPU_VR4133:
+ switch (CLKSP_VR4133(clkspeed)) {
+ case 0:
+ pclock = 133000000;
+ break;
+ case 1:
+ pclock = 149000000;
+ break;
+ case 2:
+ pclock = 165900000;
+ break;
+ case 3:
+ pclock = 199100000;
+ break;
+ case 4:
+ pclock = 265900000;
+ break;
+ default:
+ printk(KERN_INFO "Unknown PClock speed for NEC VR4133\n");
+ break;
+ }
+ break;
+ default:
+ printk(KERN_INFO "Unexpected CPU of NEC VR4100 series\n");
+ break;
+ }
+
+ printk(KERN_INFO "PClock: %ldHz\n", pclock);
+
+ return pclock;
+}
+
+static inline unsigned long calculate_vtclock(uint16_t clkspeed, unsigned long pclock)
+{
+ unsigned long vtclock = 0;
+
+ switch (current_cpu_data.cputype) {
+ case CPU_VR4111:
+ /* The NEC VR4111 doesn't have the VTClock. */
+ break;
+ case CPU_VR4121:
+ vtclock = pclock;
+ /* DIVVT == 9 Divide by 1.5 . VTClock = (PClock * 6) / 9 */
+ if (DIVVT(clkspeed) == 9)
+ vtclock = pclock * 6;
+ /* DIVVT == 10 Divide by 2.5 . VTClock = (PClock * 4) / 10 */
+ else if (DIVVT(clkspeed) == 10)
+ vtclock = pclock * 4;
+ vtclock /= DIVVT(clkspeed);
+ printk(KERN_INFO "VTClock: %ldHz\n", vtclock);
+ break;
+ case CPU_VR4122:
+ if(VTDIVMODE(clkspeed) == 7)
+ vtclock = pclock / 1;
+ else if(VTDIVMODE(clkspeed) == 1)
+ vtclock = pclock / 2;
+ else
+ vtclock = pclock / VTDIVMODE(clkspeed);
+ printk(KERN_INFO "VTClock: %ldHz\n", vtclock);
+ break;
+ case CPU_VR4131:
+ case CPU_VR4133:
+ vtclock = pclock / VTDIVMODE(clkspeed);
+ printk(KERN_INFO "VTClock: %ldHz\n", vtclock);
+ break;
+ default:
+ printk(KERN_INFO "Unexpected CPU of NEC VR4100 series\n");
+ break;
+ }
+
+ return vtclock;
+}
+
+static inline unsigned long calculate_tclock(uint16_t clkspeed, unsigned long pclock,
+ unsigned long vtclock)
+{
+ unsigned long tclock = 0;
+
+ switch (current_cpu_data.cputype) {
+ case CPU_VR4111:
+ if (!(clkspeed & DIV2B))
+ tclock = pclock / 2;
+ else if (!(clkspeed & DIV3B))
+ tclock = pclock / 3;
+ else if (!(clkspeed & DIV4B))
+ tclock = pclock / 4;
+ break;
+ case CPU_VR4121:
+ tclock = pclock / DIVT(clkspeed);
+ break;
+ case CPU_VR4122:
+ case CPU_VR4131:
+ case CPU_VR4133:
+ tclock = vtclock / TDIVMODE(clkspeed);
+ break;
+ default:
+ printk(KERN_INFO "Unexpected CPU of NEC VR4100 series\n");
+ break;
+ }
+
+ printk(KERN_INFO "TClock: %ldHz\n", tclock);
+
+ return tclock;
+}
+
+void vr41xx_calculate_clock_frequency(void)
+{
+ unsigned long pclock;
+ uint16_t clkspeed;
+
+ clkspeed = read_clkspeed();
+
+ pclock = calculate_pclock(clkspeed);
+ vr41xx_vtclock = calculate_vtclock(clkspeed, pclock);
+ vr41xx_tclock = calculate_tclock(clkspeed, pclock, vr41xx_vtclock);
+}
+
+EXPORT_SYMBOL_GPL(vr41xx_calculate_clock_frequency);
diff --git a/arch/mips/vr41xx/common/cmu.c b/arch/mips/vr41xx/common/cmu.c
new file mode 100644
index 0000000..fcd3cb8
--- /dev/null
+++ b/arch/mips/vr41xx/common/cmu.c
@@ -0,0 +1,257 @@
+/*
+ * cmu.c, Clock Mask Unit routines for the NEC VR4100 series.
+ *
+ * Copyright (C) 2001-2002 MontaVista Software Inc.
+ * Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com>
+ * Copuright (C) 2003-2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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
+ */
+/*
+ * Changes:
+ * MontaVista Software Inc. <yyuasa@mvista.com> or <source@mvista.com>
+ * - New creation, NEC VR4122 and VR4131 are supported.
+ * - Added support for NEC VR4111 and VR4121.
+ *
+ * Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ * - Added support for NEC VR4133.
+ */
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/module.h>
+#include <linux/smp.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+
+#include <asm/cpu.h>
+#include <asm/io.h>
+#include <asm/vr41xx/vr41xx.h>
+
+#define CMU_TYPE1_BASE 0x0b000060UL
+#define CMU_TYPE1_SIZE 0x4
+
+#define CMU_TYPE2_BASE 0x0f000060UL
+#define CMU_TYPE2_SIZE 0x4
+
+#define CMU_TYPE3_BASE 0x0f000060UL
+#define CMU_TYPE3_SIZE 0x8
+
+#define CMUCLKMSK 0x0
+ #define MSKPIU 0x0001
+ #define MSKSIU 0x0002
+ #define MSKAIU 0x0004
+ #define MSKKIU 0x0008
+ #define MSKFIR 0x0010
+ #define MSKDSIU 0x0820
+ #define MSKCSI 0x0040
+ #define MSKPCIU 0x0080
+ #define MSKSSIU 0x0100
+ #define MSKSHSP 0x0200
+ #define MSKFFIR 0x0400
+ #define MSKSCSI 0x1000
+ #define MSKPPCIU 0x2000
+#define CMUCLKMSK2 0x4
+ #define MSKCEU 0x0001
+ #define MSKMAC0 0x0002
+ #define MSKMAC1 0x0004
+
+static void __iomem *cmu_base;
+static uint16_t cmuclkmsk, cmuclkmsk2;
+static spinlock_t cmu_lock;
+
+#define cmu_read(offset) readw(cmu_base + (offset))
+#define cmu_write(offset, value) writew((value), cmu_base + (offset))
+
+void vr41xx_supply_clock(vr41xx_clock_t clock)
+{
+ spin_lock_irq(&cmu_lock);
+
+ switch (clock) {
+ case PIU_CLOCK:
+ cmuclkmsk |= MSKPIU;
+ break;
+ case SIU_CLOCK:
+ cmuclkmsk |= MSKSIU | MSKSSIU;
+ break;
+ case AIU_CLOCK:
+ cmuclkmsk |= MSKAIU;
+ break;
+ case KIU_CLOCK:
+ cmuclkmsk |= MSKKIU;
+ break;
+ case FIR_CLOCK:
+ cmuclkmsk |= MSKFIR | MSKFFIR;
+ break;
+ case DSIU_CLOCK:
+ if (current_cpu_data.cputype == CPU_VR4111 ||
+ current_cpu_data.cputype == CPU_VR4121)
+ cmuclkmsk |= MSKDSIU;
+ else
+ cmuclkmsk |= MSKSIU | MSKDSIU;
+ break;
+ case CSI_CLOCK:
+ cmuclkmsk |= MSKCSI | MSKSCSI;
+ break;
+ case PCIU_CLOCK:
+ cmuclkmsk |= MSKPCIU;
+ break;
+ case HSP_CLOCK:
+ cmuclkmsk |= MSKSHSP;
+ break;
+ case PCI_CLOCK:
+ cmuclkmsk |= MSKPPCIU;
+ break;
+ case CEU_CLOCK:
+ cmuclkmsk2 |= MSKCEU;
+ break;
+ case ETHER0_CLOCK:
+ cmuclkmsk2 |= MSKMAC0;
+ break;
+ case ETHER1_CLOCK:
+ cmuclkmsk2 |= MSKMAC1;
+ break;
+ default:
+ break;
+ }
+
+ if (clock == CEU_CLOCK || clock == ETHER0_CLOCK ||
+ clock == ETHER1_CLOCK)
+ cmu_write(CMUCLKMSK2, cmuclkmsk2);
+ else
+ cmu_write(CMUCLKMSK, cmuclkmsk);
+
+ spin_unlock_irq(&cmu_lock);
+}
+
+EXPORT_SYMBOL_GPL(vr41xx_supply_clock);
+
+void vr41xx_mask_clock(vr41xx_clock_t clock)
+{
+ spin_lock_irq(&cmu_lock);
+
+ switch (clock) {
+ case PIU_CLOCK:
+ cmuclkmsk &= ~MSKPIU;
+ break;
+ case SIU_CLOCK:
+ if (current_cpu_data.cputype == CPU_VR4111 ||
+ current_cpu_data.cputype == CPU_VR4121) {
+ cmuclkmsk &= ~(MSKSIU | MSKSSIU);
+ } else {
+ if (cmuclkmsk & MSKDSIU)
+ cmuclkmsk &= ~MSKSSIU;
+ else
+ cmuclkmsk &= ~(MSKSIU | MSKSSIU);
+ }
+ break;
+ case AIU_CLOCK:
+ cmuclkmsk &= ~MSKAIU;
+ break;
+ case KIU_CLOCK:
+ cmuclkmsk &= ~MSKKIU;
+ break;
+ case FIR_CLOCK:
+ cmuclkmsk &= ~(MSKFIR | MSKFFIR);
+ break;
+ case DSIU_CLOCK:
+ if (current_cpu_data.cputype == CPU_VR4111 ||
+ current_cpu_data.cputype == CPU_VR4121) {
+ cmuclkmsk &= ~MSKDSIU;
+ } else {
+ if (cmuclkmsk & MSKSSIU)
+ cmuclkmsk &= ~MSKDSIU;
+ else
+ cmuclkmsk &= ~(MSKSIU | MSKDSIU);
+ }
+ break;
+ case CSI_CLOCK:
+ cmuclkmsk &= ~(MSKCSI | MSKSCSI);
+ break;
+ case PCIU_CLOCK:
+ cmuclkmsk &= ~MSKPCIU;
+ break;
+ case HSP_CLOCK:
+ cmuclkmsk &= ~MSKSHSP;
+ break;
+ case PCI_CLOCK:
+ cmuclkmsk &= ~MSKPPCIU;
+ break;
+ case CEU_CLOCK:
+ cmuclkmsk2 &= ~MSKCEU;
+ break;
+ case ETHER0_CLOCK:
+ cmuclkmsk2 &= ~MSKMAC0;
+ break;
+ case ETHER1_CLOCK:
+ cmuclkmsk2 &= ~MSKMAC1;
+ break;
+ default:
+ break;
+ }
+
+ if (clock == CEU_CLOCK || clock == ETHER0_CLOCK ||
+ clock == ETHER1_CLOCK)
+ cmu_write(CMUCLKMSK2, cmuclkmsk2);
+ else
+ cmu_write(CMUCLKMSK, cmuclkmsk);
+
+ spin_unlock_irq(&cmu_lock);
+}
+
+EXPORT_SYMBOL_GPL(vr41xx_mask_clock);
+
+static int __init vr41xx_cmu_init(void)
+{
+ unsigned long start, size;
+
+ switch (current_cpu_data.cputype) {
+ case CPU_VR4111:
+ case CPU_VR4121:
+ start = CMU_TYPE1_BASE;
+ size = CMU_TYPE1_SIZE;
+ break;
+ case CPU_VR4122:
+ case CPU_VR4131:
+ start = CMU_TYPE2_BASE;
+ size = CMU_TYPE2_SIZE;
+ break;
+ case CPU_VR4133:
+ start = CMU_TYPE3_BASE;
+ size = CMU_TYPE3_SIZE;
+ break;
+ default:
+ panic("Unexpected CPU of NEC VR4100 series");
+ break;
+ }
+
+ if (request_mem_region(start, size, "CMU") == NULL)
+ return -EBUSY;
+
+ cmu_base = ioremap(start, size);
+ if (cmu_base == NULL) {
+ release_mem_region(start, size);
+ return -EBUSY;
+ }
+
+ cmuclkmsk = cmu_read(CMUCLKMSK);
+ if (current_cpu_data.cputype == CPU_VR4133)
+ cmuclkmsk2 = cmu_read(CMUCLKMSK2);
+
+ spin_lock_init(&cmu_lock);
+
+ return 0;
+}
+
+core_initcall(vr41xx_cmu_init);
diff --git a/arch/mips/vr41xx/common/giu.c b/arch/mips/vr41xx/common/giu.c
new file mode 100644
index 0000000..9c6b21a
--- /dev/null
+++ b/arch/mips/vr41xx/common/giu.c
@@ -0,0 +1,455 @@
+/*
+ * giu.c, General-purpose I/O Unit Interrupt routines for NEC VR4100 series.
+ *
+ * Copyright (C) 2002 MontaVista Software Inc.
+ * Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com>
+ * Copyright (C) 2003-2004 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ * Copyright (C) 2005 Ralf Baechle (ralf@linux-mips.org)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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
+ */
+/*
+ * Changes:
+ * MontaVista Software Inc. <yyuasa@mvista.com> or <source@mvista.com>
+ * - New creation, NEC VR4111, VR4121, VR4122 and VR4131 are supported.
+ *
+ * Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ * - Added support for NEC VR4133.
+ * - Removed board_irq_init.
+ */
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/smp.h>
+#include <linux/types.h>
+
+#include <asm/cpu.h>
+#include <asm/io.h>
+#include <asm/vr41xx/vr41xx.h>
+
+#define GIUIOSELL_TYPE1 KSEG1ADDR(0x0b000100)
+#define GIUIOSELL_TYPE2 KSEG1ADDR(0x0f000140)
+
+#define GIUIOSELL 0x00
+#define GIUIOSELH 0x02
+#define GIUINTSTATL 0x08
+#define GIUINTSTATH 0x0a
+#define GIUINTENL 0x0c
+#define GIUINTENH 0x0e
+#define GIUINTTYPL 0x10
+#define GIUINTTYPH 0x12
+#define GIUINTALSELL 0x14
+#define GIUINTALSELH 0x16
+#define GIUINTHTSELL 0x18
+#define GIUINTHTSELH 0x1a
+#define GIUFEDGEINHL 0x20
+#define GIUFEDGEINHH 0x22
+#define GIUREDGEINHL 0x24
+#define GIUREDGEINHH 0x26
+
+static uint32_t giu_base;
+
+static struct irqaction giu_cascade = {
+ .handler = no_action,
+ .mask = CPU_MASK_NONE,
+ .name = "cascade",
+};
+
+#define read_giuint(offset) readw(giu_base + (offset))
+#define write_giuint(val, offset) writew((val), giu_base + (offset))
+
+#define GIUINT_HIGH_OFFSET 16
+
+static inline uint16_t set_giuint(uint8_t offset, uint16_t set)
+{
+ uint16_t res;
+
+ res = read_giuint(offset);
+ res |= set;
+ write_giuint(res, offset);
+
+ return res;
+}
+
+static inline uint16_t clear_giuint(uint8_t offset, uint16_t clear)
+{
+ uint16_t res;
+
+ res = read_giuint(offset);
+ res &= ~clear;
+ write_giuint(res, offset);
+
+ return res;
+}
+
+static unsigned int startup_giuint_low_irq(unsigned int irq)
+{
+ unsigned int pin;
+
+ pin = GIU_IRQ_TO_PIN(irq);
+ write_giuint((uint16_t)1 << pin, GIUINTSTATL);
+ set_giuint(GIUINTENL, (uint16_t)1 << pin);
+
+ return 0;
+}
+
+static void shutdown_giuint_low_irq(unsigned int irq)
+{
+ clear_giuint(GIUINTENL, (uint16_t)1 << GIU_IRQ_TO_PIN(irq));
+}
+
+static void enable_giuint_low_irq(unsigned int irq)
+{
+ set_giuint(GIUINTENL, (uint16_t)1 << GIU_IRQ_TO_PIN(irq));
+}
+
+#define disable_giuint_low_irq shutdown_giuint_low_irq
+
+static void ack_giuint_low_irq(unsigned int irq)
+{
+ unsigned int pin;
+
+ pin = GIU_IRQ_TO_PIN(irq);
+ clear_giuint(GIUINTENL, (uint16_t)1 << pin);
+ write_giuint((uint16_t)1 << pin, GIUINTSTATL);
+}
+
+static void end_giuint_low_irq(unsigned int irq)
+{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
+ set_giuint(GIUINTENL, (uint16_t)1 << GIU_IRQ_TO_PIN(irq));
+}
+
+static struct hw_interrupt_type giuint_low_irq_type = {
+ .typename = "GIUINTL",
+ .startup = startup_giuint_low_irq,
+ .shutdown = shutdown_giuint_low_irq,
+ .enable = enable_giuint_low_irq,
+ .disable = disable_giuint_low_irq,
+ .ack = ack_giuint_low_irq,
+ .end = end_giuint_low_irq,
+};
+
+static unsigned int startup_giuint_high_irq(unsigned int irq)
+{
+ unsigned int pin;
+
+ pin = GIU_IRQ_TO_PIN(irq - GIUINT_HIGH_OFFSET);
+ write_giuint((uint16_t)1 << pin, GIUINTSTATH);
+ set_giuint(GIUINTENH, (uint16_t)1 << pin);
+
+ return 0;
+}
+
+static void shutdown_giuint_high_irq(unsigned int irq)
+{
+ clear_giuint(GIUINTENH, (uint16_t)1 << GIU_IRQ_TO_PIN(irq - GIUINT_HIGH_OFFSET));
+}
+
+static void enable_giuint_high_irq(unsigned int irq)
+{
+ set_giuint(GIUINTENH, (uint16_t)1 << GIU_IRQ_TO_PIN(irq - GIUINT_HIGH_OFFSET));
+}
+
+#define disable_giuint_high_irq shutdown_giuint_high_irq
+
+static void ack_giuint_high_irq(unsigned int irq)
+{
+ unsigned int pin;
+
+ pin = GIU_IRQ_TO_PIN(irq - GIUINT_HIGH_OFFSET);
+ clear_giuint(GIUINTENH, (uint16_t)1 << pin);
+ write_giuint((uint16_t)1 << pin, GIUINTSTATH);
+}
+
+static void end_giuint_high_irq(unsigned int irq)
+{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
+ set_giuint(GIUINTENH, (uint16_t)1 << GIU_IRQ_TO_PIN(irq - GIUINT_HIGH_OFFSET));
+}
+
+static struct hw_interrupt_type giuint_high_irq_type = {
+ .typename = "GIUINTH",
+ .startup = startup_giuint_high_irq,
+ .shutdown = shutdown_giuint_high_irq,
+ .enable = enable_giuint_high_irq,
+ .disable = disable_giuint_high_irq,
+ .ack = ack_giuint_high_irq,
+ .end = end_giuint_high_irq,
+};
+
+void __init init_vr41xx_giuint_irq(void)
+{
+ int i;
+
+ for (i = GIU_IRQ_BASE; i <= GIU_IRQ_LAST; i++) {
+ if (i < (GIU_IRQ_BASE + GIUINT_HIGH_OFFSET))
+ irq_desc[i].handler = &giuint_low_irq_type;
+ else
+ irq_desc[i].handler = &giuint_high_irq_type;
+ }
+
+ setup_irq(GIUINT_CASCADE_IRQ, &giu_cascade);
+}
+
+void vr41xx_set_irq_trigger(int pin, int trigger, int hold)
+{
+ uint16_t mask;
+
+ if (pin < GIUINT_HIGH_OFFSET) {
+ mask = (uint16_t)1 << pin;
+ if (trigger != TRIGGER_LEVEL) {
+ set_giuint(GIUINTTYPL, mask);
+ if (hold == SIGNAL_HOLD)
+ set_giuint(GIUINTHTSELL, mask);
+ else
+ clear_giuint(GIUINTHTSELL, mask);
+ if (current_cpu_data.cputype == CPU_VR4133) {
+ switch (trigger) {
+ case TRIGGER_EDGE_FALLING:
+ set_giuint(GIUFEDGEINHL, mask);
+ clear_giuint(GIUREDGEINHL, mask);
+ break;
+ case TRIGGER_EDGE_RISING:
+ clear_giuint(GIUFEDGEINHL, mask);
+ set_giuint(GIUREDGEINHL, mask);
+ break;
+ default:
+ set_giuint(GIUFEDGEINHL, mask);
+ set_giuint(GIUREDGEINHL, mask);
+ break;
+ }
+ }
+ } else {
+ clear_giuint(GIUINTTYPL, mask);
+ clear_giuint(GIUINTHTSELL, mask);
+ }
+ write_giuint(mask, GIUINTSTATL);
+ } else {
+ mask = (uint16_t)1 << (pin - GIUINT_HIGH_OFFSET);
+ if (trigger != TRIGGER_LEVEL) {
+ set_giuint(GIUINTTYPH, mask);
+ if (hold == SIGNAL_HOLD)
+ set_giuint(GIUINTHTSELH, mask);
+ else
+ clear_giuint(GIUINTHTSELH, mask);
+ if (current_cpu_data.cputype == CPU_VR4133) {
+ switch (trigger) {
+ case TRIGGER_EDGE_FALLING:
+ set_giuint(GIUFEDGEINHH, mask);
+ clear_giuint(GIUREDGEINHH, mask);
+ break;
+ case TRIGGER_EDGE_RISING:
+ clear_giuint(GIUFEDGEINHH, mask);
+ set_giuint(GIUREDGEINHH, mask);
+ break;
+ default:
+ set_giuint(GIUFEDGEINHH, mask);
+ set_giuint(GIUREDGEINHH, mask);
+ break;
+ }
+ }
+ } else {
+ clear_giuint(GIUINTTYPH, mask);
+ clear_giuint(GIUINTHTSELH, mask);
+ }
+ write_giuint(mask, GIUINTSTATH);
+ }
+}
+
+EXPORT_SYMBOL(vr41xx_set_irq_trigger);
+
+void vr41xx_set_irq_level(int pin, int level)
+{
+ uint16_t mask;
+
+ if (pin < GIUINT_HIGH_OFFSET) {
+ mask = (uint16_t)1 << pin;
+ if (level == LEVEL_HIGH)
+ set_giuint(GIUINTALSELL, mask);
+ else
+ clear_giuint(GIUINTALSELL, mask);
+ write_giuint(mask, GIUINTSTATL);
+ } else {
+ mask = (uint16_t)1 << (pin - GIUINT_HIGH_OFFSET);
+ if (level == LEVEL_HIGH)
+ set_giuint(GIUINTALSELH, mask);
+ else
+ clear_giuint(GIUINTALSELH, mask);
+ write_giuint(mask, GIUINTSTATH);
+ }
+}
+
+EXPORT_SYMBOL(vr41xx_set_irq_level);
+
+#define GIUINT_NR_IRQS 32
+
+enum {
+ GIUINT_NO_CASCADE,
+ GIUINT_CASCADE
+};
+
+struct vr41xx_giuint_cascade {
+ unsigned int flag;
+ int (*get_irq_number)(int irq);
+};
+
+static struct vr41xx_giuint_cascade giuint_cascade[GIUINT_NR_IRQS];
+
+static int no_irq_number(int irq)
+{
+ return -EINVAL;
+}
+
+int vr41xx_cascade_irq(unsigned int irq, int (*get_irq_number)(int irq))
+{
+ unsigned int pin;
+ int retval;
+
+ if (irq < GIU_IRQ(0) || irq > GIU_IRQ(31))
+ return -EINVAL;
+
+ if(!get_irq_number)
+ return -EINVAL;
+
+ pin = GIU_IRQ_TO_PIN(irq);
+ giuint_cascade[pin].flag = GIUINT_CASCADE;
+ giuint_cascade[pin].get_irq_number = get_irq_number;
+
+ retval = setup_irq(irq, &giu_cascade);
+ if (retval != 0) {
+ giuint_cascade[pin].flag = GIUINT_NO_CASCADE;
+ giuint_cascade[pin].get_irq_number = no_irq_number;
+ }
+
+ return retval;
+}
+
+EXPORT_SYMBOL(vr41xx_cascade_irq);
+
+static inline int get_irq_pin_number(void)
+{
+ uint16_t pendl, pendh, maskl, maskh;
+ int i;
+
+ pendl = read_giuint(GIUINTSTATL);
+ pendh = read_giuint(GIUINTSTATH);
+ maskl = read_giuint(GIUINTENL);
+ maskh = read_giuint(GIUINTENH);
+
+ maskl &= pendl;
+ maskh &= pendh;
+
+ if (maskl) {
+ for (i = 0; i < 16; i++) {
+ if (maskl & ((uint16_t)1 << i))
+ return i;
+ }
+ } else if (maskh) {
+ for (i = 0; i < 16; i++) {
+ if (maskh & ((uint16_t)1 << i))
+ return i + GIUINT_HIGH_OFFSET;
+ }
+ }
+
+ printk(KERN_ERR "spurious GIU interrupt: %04x(%04x),%04x(%04x)\n",
+ maskl, pendl, maskh, pendh);
+
+ atomic_inc(&irq_err_count);
+
+ return -1;
+}
+
+static inline void ack_giuint_irq(int pin)
+{
+ if (pin < GIUINT_HIGH_OFFSET) {
+ clear_giuint(GIUINTENL, (uint16_t)1 << pin);
+ write_giuint((uint16_t)1 << pin, GIUINTSTATL);
+ } else {
+ pin -= GIUINT_HIGH_OFFSET;
+ clear_giuint(GIUINTENH, (uint16_t)1 << pin);
+ write_giuint((uint16_t)1 << pin, GIUINTSTATH);
+ }
+}
+
+static inline void end_giuint_irq(int pin)
+{
+ if (pin < GIUINT_HIGH_OFFSET)
+ set_giuint(GIUINTENL, (uint16_t)1 << pin);
+ else
+ set_giuint(GIUINTENH, (uint16_t)1 << (pin - GIUINT_HIGH_OFFSET));
+}
+
+void giuint_irq_dispatch(struct pt_regs *regs)
+{
+ struct vr41xx_giuint_cascade *cascade;
+ unsigned int giuint_irq;
+ int pin;
+
+ pin = get_irq_pin_number();
+ if (pin < 0)
+ return;
+
+ disable_irq(GIUINT_CASCADE_IRQ);
+
+ cascade = &giuint_cascade[pin];
+ giuint_irq = GIU_IRQ(pin);
+ if (cascade->flag == GIUINT_CASCADE) {
+ int irq = cascade->get_irq_number(giuint_irq);
+ ack_giuint_irq(pin);
+ if (irq >= 0)
+ do_IRQ(irq, regs);
+ end_giuint_irq(pin);
+ } else {
+ do_IRQ(giuint_irq, regs);
+ }
+
+ enable_irq(GIUINT_CASCADE_IRQ);
+}
+
+static int __init vr41xx_giu_init(void)
+{
+ int i;
+
+ switch (current_cpu_data.cputype) {
+ case CPU_VR4111:
+ case CPU_VR4121:
+ giu_base = GIUIOSELL_TYPE1;
+ break;
+ case CPU_VR4122:
+ case CPU_VR4131:
+ case CPU_VR4133:
+ giu_base = GIUIOSELL_TYPE2;
+ break;
+ default:
+ printk(KERN_ERR "GIU: Unexpected CPU of NEC VR4100 series\n");
+ return -EINVAL;
+ }
+
+ for (i = 0; i < GIUINT_NR_IRQS; i++) {
+ if (i < GIUINT_HIGH_OFFSET)
+ clear_giuint(GIUINTENL, (uint16_t)1 << i);
+ else
+ clear_giuint(GIUINTENH, (uint16_t)1 << (i - GIUINT_HIGH_OFFSET));
+ giuint_cascade[i].flag = GIUINT_NO_CASCADE;
+ giuint_cascade[i].get_irq_number = no_irq_number;
+ }
+
+ return 0;
+}
+
+early_initcall(vr41xx_giu_init);
diff --git a/arch/mips/vr41xx/common/icu.c b/arch/mips/vr41xx/common/icu.c
new file mode 100644
index 0000000..c842661
--- /dev/null
+++ b/arch/mips/vr41xx/common/icu.c
@@ -0,0 +1,757 @@
+/*
+ * icu.c, Interrupt Control Unit routines for the NEC VR4100 series.
+ *
+ * Copyright (C) 2001-2002 MontaVista Software Inc.
+ * Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com>
+ * Copyright (C) 2003-2004 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ * Copyright (C) 2005 Ralf Baechle (ralf@linux-mips.org)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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
+ */
+/*
+ * Changes:
+ * MontaVista Software Inc. <yyuasa@mvista.com> or <source@mvista.com>
+ * - New creation, NEC VR4122 and VR4131 are supported.
+ * - Added support for NEC VR4111 and VR4121.
+ *
+ * Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ * - Coped with INTASSIGN of NEC VR4133.
+ */
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <linux/smp.h>
+#include <linux/types.h>
+
+#include <asm/cpu.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/irq_cpu.h>
+#include <asm/vr41xx/vr41xx.h>
+
+extern asmlinkage void vr41xx_handle_interrupt(void);
+
+extern void init_vr41xx_giuint_irq(void);
+extern void giuint_irq_dispatch(struct pt_regs *regs);
+
+static uint32_t icu1_base;
+static uint32_t icu2_base;
+
+static struct irqaction icu_cascade = {
+ .handler = no_action,
+ .mask = CPU_MASK_NONE,
+ .name = "cascade",
+};
+
+static unsigned char sysint1_assign[16] = {
+ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+static unsigned char sysint2_assign[16] = {
+ 2, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+
+#define SYSINT1REG_TYPE1 KSEG1ADDR(0x0b000080)
+#define SYSINT2REG_TYPE1 KSEG1ADDR(0x0b000200)
+
+#define SYSINT1REG_TYPE2 KSEG1ADDR(0x0f000080)
+#define SYSINT2REG_TYPE2 KSEG1ADDR(0x0f0000a0)
+
+#define SYSINT1REG 0x00
+#define PIUINTREG 0x02
+#define INTASSIGN0 0x04
+#define INTASSIGN1 0x06
+#define GIUINTLREG 0x08
+#define DSIUINTREG 0x0a
+#define MSYSINT1REG 0x0c
+#define MPIUINTREG 0x0e
+#define MAIUINTREG 0x10
+#define MKIUINTREG 0x12
+#define MGIUINTLREG 0x14
+#define MDSIUINTREG 0x16
+#define NMIREG 0x18
+#define SOFTREG 0x1a
+#define INTASSIGN2 0x1c
+#define INTASSIGN3 0x1e
+
+#define SYSINT2REG 0x00
+#define GIUINTHREG 0x02
+#define FIRINTREG 0x04
+#define MSYSINT2REG 0x06
+#define MGIUINTHREG 0x08
+#define MFIRINTREG 0x0a
+#define PCIINTREG 0x0c
+ #define PCIINT0 0x0001
+#define SCUINTREG 0x0e
+ #define SCUINT0 0x0001
+#define CSIINTREG 0x10
+#define MPCIINTREG 0x12
+#define MSCUINTREG 0x14
+#define MCSIINTREG 0x16
+#define BCUINTREG 0x18
+ #define BCUINTR 0x0001
+#define MBCUINTREG 0x1a
+
+#define SYSINT1_IRQ_TO_PIN(x) ((x) - SYSINT1_IRQ_BASE) /* Pin 0-15 */
+#define SYSINT2_IRQ_TO_PIN(x) ((x) - SYSINT2_IRQ_BASE) /* Pin 0-15 */
+
+#define read_icu1(offset) readw(icu1_base + (offset))
+#define write_icu1(val, offset) writew((val), icu1_base + (offset))
+
+#define read_icu2(offset) readw(icu2_base + (offset))
+#define write_icu2(val, offset) writew((val), icu2_base + (offset))
+
+#define INTASSIGN_MAX 4
+#define INTASSIGN_MASK 0x0007
+
+static inline uint16_t set_icu1(uint8_t offset, uint16_t set)
+{
+ uint16_t res;
+
+ res = read_icu1(offset);
+ res |= set;
+ write_icu1(res, offset);
+
+ return res;
+}
+
+static inline uint16_t clear_icu1(uint8_t offset, uint16_t clear)
+{
+ uint16_t res;
+
+ res = read_icu1(offset);
+ res &= ~clear;
+ write_icu1(res, offset);
+
+ return res;
+}
+
+static inline uint16_t set_icu2(uint8_t offset, uint16_t set)
+{
+ uint16_t res;
+
+ res = read_icu2(offset);
+ res |= set;
+ write_icu2(res, offset);
+
+ return res;
+}
+
+static inline uint16_t clear_icu2(uint8_t offset, uint16_t clear)
+{
+ uint16_t res;
+
+ res = read_icu2(offset);
+ res &= ~clear;
+ write_icu2(res, offset);
+
+ return res;
+}
+
+/*=======================================================================*/
+
+void vr41xx_enable_piuint(uint16_t mask)
+{
+ irq_desc_t *desc = irq_desc + PIU_IRQ;
+ unsigned long flags;
+
+ if (current_cpu_data.cputype == CPU_VR4111 ||
+ current_cpu_data.cputype == CPU_VR4121) {
+ spin_lock_irqsave(&desc->lock, flags);
+ set_icu1(MPIUINTREG, mask);
+ spin_unlock_irqrestore(&desc->lock, flags);
+ }
+}
+
+EXPORT_SYMBOL(vr41xx_enable_piuint);
+
+void vr41xx_disable_piuint(uint16_t mask)
+{
+ irq_desc_t *desc = irq_desc + PIU_IRQ;
+ unsigned long flags;
+
+ if (current_cpu_data.cputype == CPU_VR4111 ||
+ current_cpu_data.cputype == CPU_VR4121) {
+ spin_lock_irqsave(&desc->lock, flags);
+ clear_icu1(MPIUINTREG, mask);
+ spin_unlock_irqrestore(&desc->lock, flags);
+ }
+}
+
+EXPORT_SYMBOL(vr41xx_disable_piuint);
+
+void vr41xx_enable_aiuint(uint16_t mask)
+{
+ irq_desc_t *desc = irq_desc + AIU_IRQ;
+ unsigned long flags;
+
+ if (current_cpu_data.cputype == CPU_VR4111 ||
+ current_cpu_data.cputype == CPU_VR4121) {
+ spin_lock_irqsave(&desc->lock, flags);
+ set_icu1(MAIUINTREG, mask);
+ spin_unlock_irqrestore(&desc->lock, flags);
+ }
+}
+
+EXPORT_SYMBOL(vr41xx_enable_aiuint);
+
+void vr41xx_disable_aiuint(uint16_t mask)
+{
+ irq_desc_t *desc = irq_desc + AIU_IRQ;
+ unsigned long flags;
+
+ if (current_cpu_data.cputype == CPU_VR4111 ||
+ current_cpu_data.cputype == CPU_VR4121) {
+ spin_lock_irqsave(&desc->lock, flags);
+ clear_icu1(MAIUINTREG, mask);
+ spin_unlock_irqrestore(&desc->lock, flags);
+ }
+}
+
+EXPORT_SYMBOL(vr41xx_disable_aiuint);
+
+void vr41xx_enable_kiuint(uint16_t mask)
+{
+ irq_desc_t *desc = irq_desc + KIU_IRQ;
+ unsigned long flags;
+
+ if (current_cpu_data.cputype == CPU_VR4111 ||
+ current_cpu_data.cputype == CPU_VR4121) {
+ spin_lock_irqsave(&desc->lock, flags);
+ set_icu1(MKIUINTREG, mask);
+ spin_unlock_irqrestore(&desc->lock, flags);
+ }
+}
+
+EXPORT_SYMBOL(vr41xx_enable_kiuint);
+
+void vr41xx_disable_kiuint(uint16_t mask)
+{
+ irq_desc_t *desc = irq_desc + KIU_IRQ;
+ unsigned long flags;
+
+ if (current_cpu_data.cputype == CPU_VR4111 ||
+ current_cpu_data.cputype == CPU_VR4121) {
+ spin_lock_irqsave(&desc->lock, flags);
+ clear_icu1(MKIUINTREG, mask);
+ spin_unlock_irqrestore(&desc->lock, flags);
+ }
+}
+
+EXPORT_SYMBOL(vr41xx_disable_kiuint);
+
+void vr41xx_enable_dsiuint(uint16_t mask)
+{
+ irq_desc_t *desc = irq_desc + DSIU_IRQ;
+ unsigned long flags;
+
+ spin_lock_irqsave(&desc->lock, flags);
+ set_icu1(MDSIUINTREG, mask);
+ spin_unlock_irqrestore(&desc->lock, flags);
+}
+
+EXPORT_SYMBOL(vr41xx_enable_dsiuint);
+
+void vr41xx_disable_dsiuint(uint16_t mask)
+{
+ irq_desc_t *desc = irq_desc + DSIU_IRQ;
+ unsigned long flags;
+
+ spin_lock_irqsave(&desc->lock, flags);
+ clear_icu1(MDSIUINTREG, mask);
+ spin_unlock_irqrestore(&desc->lock, flags);
+}
+
+EXPORT_SYMBOL(vr41xx_disable_dsiuint);
+
+void vr41xx_enable_firint(uint16_t mask)
+{
+ irq_desc_t *desc = irq_desc + FIR_IRQ;
+ unsigned long flags;
+
+ spin_lock_irqsave(&desc->lock, flags);
+ set_icu2(MFIRINTREG, mask);
+ spin_unlock_irqrestore(&desc->lock, flags);
+}
+
+EXPORT_SYMBOL(vr41xx_enable_firint);
+
+void vr41xx_disable_firint(uint16_t mask)
+{
+ irq_desc_t *desc = irq_desc + FIR_IRQ;
+ unsigned long flags;
+
+ spin_lock_irqsave(&desc->lock, flags);
+ clear_icu2(MFIRINTREG, mask);
+ spin_unlock_irqrestore(&desc->lock, flags);
+}
+
+EXPORT_SYMBOL(vr41xx_disable_firint);
+
+void vr41xx_enable_pciint(void)
+{
+ irq_desc_t *desc = irq_desc + PCI_IRQ;
+ unsigned long flags;
+
+ if (current_cpu_data.cputype == CPU_VR4122 ||
+ current_cpu_data.cputype == CPU_VR4131 ||
+ current_cpu_data.cputype == CPU_VR4133) {
+ spin_lock_irqsave(&desc->lock, flags);
+ write_icu2(PCIINT0, MPCIINTREG);
+ spin_unlock_irqrestore(&desc->lock, flags);
+ }
+}
+
+EXPORT_SYMBOL(vr41xx_enable_pciint);
+
+void vr41xx_disable_pciint(void)
+{
+ irq_desc_t *desc = irq_desc + PCI_IRQ;
+ unsigned long flags;
+
+ if (current_cpu_data.cputype == CPU_VR4122 ||
+ current_cpu_data.cputype == CPU_VR4131 ||
+ current_cpu_data.cputype == CPU_VR4133) {
+ spin_lock_irqsave(&desc->lock, flags);
+ write_icu2(0, MPCIINTREG);
+ spin_unlock_irqrestore(&desc->lock, flags);
+ }
+}
+
+EXPORT_SYMBOL(vr41xx_disable_pciint);
+
+void vr41xx_enable_scuint(void)
+{
+ irq_desc_t *desc = irq_desc + SCU_IRQ;
+ unsigned long flags;
+
+ if (current_cpu_data.cputype == CPU_VR4122 ||
+ current_cpu_data.cputype == CPU_VR4131 ||
+ current_cpu_data.cputype == CPU_VR4133) {
+ spin_lock_irqsave(&desc->lock, flags);
+ write_icu2(SCUINT0, MSCUINTREG);
+ spin_unlock_irqrestore(&desc->lock, flags);
+ }
+}
+
+EXPORT_SYMBOL(vr41xx_enable_scuint);
+
+void vr41xx_disable_scuint(void)
+{
+ irq_desc_t *desc = irq_desc + SCU_IRQ;
+ unsigned long flags;
+
+ if (current_cpu_data.cputype == CPU_VR4122 ||
+ current_cpu_data.cputype == CPU_VR4131 ||
+ current_cpu_data.cputype == CPU_VR4133) {
+ spin_lock_irqsave(&desc->lock, flags);
+ write_icu2(0, MSCUINTREG);
+ spin_unlock_irqrestore(&desc->lock, flags);
+ }
+}
+
+EXPORT_SYMBOL(vr41xx_disable_scuint);
+
+void vr41xx_enable_csiint(uint16_t mask)
+{
+ irq_desc_t *desc = irq_desc + CSI_IRQ;
+ unsigned long flags;
+
+ if (current_cpu_data.cputype == CPU_VR4122 ||
+ current_cpu_data.cputype == CPU_VR4131 ||
+ current_cpu_data.cputype == CPU_VR4133) {
+ spin_lock_irqsave(&desc->lock, flags);
+ set_icu2(MCSIINTREG, mask);
+ spin_unlock_irqrestore(&desc->lock, flags);
+ }
+}
+
+EXPORT_SYMBOL(vr41xx_enable_csiint);
+
+void vr41xx_disable_csiint(uint16_t mask)
+{
+ irq_desc_t *desc = irq_desc + CSI_IRQ;
+ unsigned long flags;
+
+ if (current_cpu_data.cputype == CPU_VR4122 ||
+ current_cpu_data.cputype == CPU_VR4131 ||
+ current_cpu_data.cputype == CPU_VR4133) {
+ spin_lock_irqsave(&desc->lock, flags);
+ clear_icu2(MCSIINTREG, mask);
+ spin_unlock_irqrestore(&desc->lock, flags);
+ }
+}
+
+EXPORT_SYMBOL(vr41xx_disable_csiint);
+
+void vr41xx_enable_bcuint(void)
+{
+ irq_desc_t *desc = irq_desc + BCU_IRQ;
+ unsigned long flags;
+
+ if (current_cpu_data.cputype == CPU_VR4122 ||
+ current_cpu_data.cputype == CPU_VR4131 ||
+ current_cpu_data.cputype == CPU_VR4133) {
+ spin_lock_irqsave(&desc->lock, flags);
+ write_icu2(BCUINTR, MBCUINTREG);
+ spin_unlock_irqrestore(&desc->lock, flags);
+ }
+}
+
+EXPORT_SYMBOL(vr41xx_enable_bcuint);
+
+void vr41xx_disable_bcuint(void)
+{
+ irq_desc_t *desc = irq_desc + BCU_IRQ;
+ unsigned long flags;
+
+ if (current_cpu_data.cputype == CPU_VR4122 ||
+ current_cpu_data.cputype == CPU_VR4131 ||
+ current_cpu_data.cputype == CPU_VR4133) {
+ spin_lock_irqsave(&desc->lock, flags);
+ write_icu2(0, MBCUINTREG);
+ spin_unlock_irqrestore(&desc->lock, flags);
+ }
+}
+
+EXPORT_SYMBOL(vr41xx_disable_bcuint);
+
+/*=======================================================================*/
+
+static unsigned int startup_sysint1_irq(unsigned int irq)
+{
+ set_icu1(MSYSINT1REG, (uint16_t)1 << SYSINT1_IRQ_TO_PIN(irq));
+
+ return 0; /* never anything pending */
+}
+
+static void shutdown_sysint1_irq(unsigned int irq)
+{
+ clear_icu1(MSYSINT1REG, (uint16_t)1 << SYSINT1_IRQ_TO_PIN(irq));
+}
+
+static void enable_sysint1_irq(unsigned int irq)
+{
+ set_icu1(MSYSINT1REG, (uint16_t)1 << SYSINT1_IRQ_TO_PIN(irq));
+}
+
+#define disable_sysint1_irq shutdown_sysint1_irq
+#define ack_sysint1_irq shutdown_sysint1_irq
+
+static void end_sysint1_irq(unsigned int irq)
+{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
+ set_icu1(MSYSINT1REG, (uint16_t)1 << SYSINT1_IRQ_TO_PIN(irq));
+}
+
+static struct hw_interrupt_type sysint1_irq_type = {
+ .typename = "SYSINT1",
+ .startup = startup_sysint1_irq,
+ .shutdown = shutdown_sysint1_irq,
+ .enable = enable_sysint1_irq,
+ .disable = disable_sysint1_irq,
+ .ack = ack_sysint1_irq,
+ .end = end_sysint1_irq,
+};
+
+/*=======================================================================*/
+
+static unsigned int startup_sysint2_irq(unsigned int irq)
+{
+ set_icu2(MSYSINT2REG, (uint16_t)1 << SYSINT2_IRQ_TO_PIN(irq));
+
+ return 0; /* never anything pending */
+}
+
+static void shutdown_sysint2_irq(unsigned int irq)
+{
+ clear_icu2(MSYSINT2REG, (uint16_t)1 << SYSINT2_IRQ_TO_PIN(irq));
+}
+
+static void enable_sysint2_irq(unsigned int irq)
+{
+ set_icu2(MSYSINT2REG, (uint16_t)1 << SYSINT2_IRQ_TO_PIN(irq));
+}
+
+#define disable_sysint2_irq shutdown_sysint2_irq
+#define ack_sysint2_irq shutdown_sysint2_irq
+
+static void end_sysint2_irq(unsigned int irq)
+{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
+ set_icu2(MSYSINT2REG, (uint16_t)1 << SYSINT2_IRQ_TO_PIN(irq));
+}
+
+static struct hw_interrupt_type sysint2_irq_type = {
+ .typename = "SYSINT2",
+ .startup = startup_sysint2_irq,
+ .shutdown = shutdown_sysint2_irq,
+ .enable = enable_sysint2_irq,
+ .disable = disable_sysint2_irq,
+ .ack = ack_sysint2_irq,
+ .end = end_sysint2_irq,
+};
+
+/*=======================================================================*/
+
+static inline int set_sysint1_assign(unsigned int irq, unsigned char assign)
+{
+ irq_desc_t *desc = irq_desc + irq;
+ uint16_t intassign0, intassign1;
+ unsigned int pin;
+
+ pin = SYSINT1_IRQ_TO_PIN(irq);
+
+ spin_lock_irq(&desc->lock);
+
+ intassign0 = read_icu1(INTASSIGN0);
+ intassign1 = read_icu1(INTASSIGN1);
+
+ switch (pin) {
+ case 0:
+ intassign0 &= ~INTASSIGN_MASK;
+ intassign0 |= (uint16_t)assign;
+ break;
+ case 1:
+ intassign0 &= ~(INTASSIGN_MASK << 3);
+ intassign0 |= (uint16_t)assign << 3;
+ break;
+ case 2:
+ intassign0 &= ~(INTASSIGN_MASK << 6);
+ intassign0 |= (uint16_t)assign << 6;
+ break;
+ case 3:
+ intassign0 &= ~(INTASSIGN_MASK << 9);
+ intassign0 |= (uint16_t)assign << 9;
+ break;
+ case 8:
+ intassign0 &= ~(INTASSIGN_MASK << 12);
+ intassign0 |= (uint16_t)assign << 12;
+ break;
+ case 9:
+ intassign1 &= ~INTASSIGN_MASK;
+ intassign1 |= (uint16_t)assign;
+ break;
+ case 11:
+ intassign1 &= ~(INTASSIGN_MASK << 6);
+ intassign1 |= (uint16_t)assign << 6;
+ break;
+ case 12:
+ intassign1 &= ~(INTASSIGN_MASK << 9);
+ intassign1 |= (uint16_t)assign << 9;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ sysint1_assign[pin] = assign;
+ write_icu1(intassign0, INTASSIGN0);
+ write_icu1(intassign1, INTASSIGN1);
+
+ spin_unlock_irq(&desc->lock);
+
+ return 0;
+}
+
+static inline int set_sysint2_assign(unsigned int irq, unsigned char assign)
+{
+ irq_desc_t *desc = irq_desc + irq;
+ uint16_t intassign2, intassign3;
+ unsigned int pin;
+
+ pin = SYSINT2_IRQ_TO_PIN(irq);
+
+ spin_lock_irq(&desc->lock);
+
+ intassign2 = read_icu1(INTASSIGN2);
+ intassign3 = read_icu1(INTASSIGN3);
+
+ switch (pin) {
+ case 0:
+ intassign2 &= ~INTASSIGN_MASK;
+ intassign2 |= (uint16_t)assign;
+ break;
+ case 1:
+ intassign2 &= ~(INTASSIGN_MASK << 3);
+ intassign2 |= (uint16_t)assign << 3;
+ break;
+ case 3:
+ intassign2 &= ~(INTASSIGN_MASK << 6);
+ intassign2 |= (uint16_t)assign << 6;
+ break;
+ case 4:
+ intassign2 &= ~(INTASSIGN_MASK << 9);
+ intassign2 |= (uint16_t)assign << 9;
+ break;
+ case 5:
+ intassign2 &= ~(INTASSIGN_MASK << 12);
+ intassign2 |= (uint16_t)assign << 12;
+ break;
+ case 6:
+ intassign3 &= ~INTASSIGN_MASK;
+ intassign3 |= (uint16_t)assign;
+ break;
+ case 7:
+ intassign3 &= ~(INTASSIGN_MASK << 3);
+ intassign3 |= (uint16_t)assign << 3;
+ break;
+ case 8:
+ intassign3 &= ~(INTASSIGN_MASK << 6);
+ intassign3 |= (uint16_t)assign << 6;
+ break;
+ case 9:
+ intassign3 &= ~(INTASSIGN_MASK << 9);
+ intassign3 |= (uint16_t)assign << 9;
+ break;
+ case 10:
+ intassign3 &= ~(INTASSIGN_MASK << 12);
+ intassign3 |= (uint16_t)assign << 12;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ sysint2_assign[pin] = assign;
+ write_icu1(intassign2, INTASSIGN2);
+ write_icu1(intassign3, INTASSIGN3);
+
+ spin_unlock_irq(&desc->lock);
+
+ return 0;
+}
+
+int vr41xx_set_intassign(unsigned int irq, unsigned char intassign)
+{
+ int retval = -EINVAL;
+
+ if (current_cpu_data.cputype != CPU_VR4133)
+ return -EINVAL;
+
+ if (intassign > INTASSIGN_MAX)
+ return -EINVAL;
+
+ if (irq >= SYSINT1_IRQ_BASE && irq <= SYSINT1_IRQ_LAST)
+ retval = set_sysint1_assign(irq, intassign);
+ else if (irq >= SYSINT2_IRQ_BASE && irq <= SYSINT2_IRQ_LAST)
+ retval = set_sysint2_assign(irq, intassign);
+
+ return retval;
+}
+
+EXPORT_SYMBOL(vr41xx_set_intassign);
+
+/*=======================================================================*/
+
+asmlinkage void irq_dispatch(unsigned char intnum, struct pt_regs *regs)
+{
+ uint16_t pend1, pend2;
+ uint16_t mask1, mask2;
+ int i;
+
+ pend1 = read_icu1(SYSINT1REG);
+ mask1 = read_icu1(MSYSINT1REG);
+
+ pend2 = read_icu2(SYSINT2REG);
+ mask2 = read_icu2(MSYSINT2REG);
+
+ mask1 &= pend1;
+ mask2 &= pend2;
+
+ if (mask1) {
+ for (i = 0; i < 16; i++) {
+ if (intnum == sysint1_assign[i] &&
+ (mask1 & ((uint16_t)1 << i))) {
+ if (i == 8)
+ giuint_irq_dispatch(regs);
+ else
+ do_IRQ(SYSINT1_IRQ(i), regs);
+ return;
+ }
+ }
+ }
+
+ if (mask2) {
+ for (i = 0; i < 16; i++) {
+ if (intnum == sysint2_assign[i] &&
+ (mask2 & ((uint16_t)1 << i))) {
+ do_IRQ(SYSINT2_IRQ(i), regs);
+ return;
+ }
+ }
+ }
+
+ printk(KERN_ERR "spurious ICU interrupt: %04x,%04x\n", pend1, pend2);
+
+ atomic_inc(&irq_err_count);
+}
+
+/*=======================================================================*/
+
+static int __init vr41xx_icu_init(void)
+{
+ switch (current_cpu_data.cputype) {
+ case CPU_VR4111:
+ case CPU_VR4121:
+ icu1_base = SYSINT1REG_TYPE1;
+ icu2_base = SYSINT2REG_TYPE1;
+ break;
+ case CPU_VR4122:
+ case CPU_VR4131:
+ case CPU_VR4133:
+ icu1_base = SYSINT1REG_TYPE2;
+ icu2_base = SYSINT2REG_TYPE2;
+ break;
+ default:
+ printk(KERN_ERR "ICU: Unexpected CPU of NEC VR4100 series\n");
+ return -EINVAL;
+ }
+
+ write_icu1(0, MSYSINT1REG);
+ write_icu1(0xffff, MGIUINTLREG);
+
+ write_icu2(0, MSYSINT2REG);
+ write_icu2(0xffff, MGIUINTHREG);
+
+ return 0;
+}
+
+early_initcall(vr41xx_icu_init);
+
+/*=======================================================================*/
+
+static inline void init_vr41xx_icu_irq(void)
+{
+ int i;
+
+ for (i = SYSINT1_IRQ_BASE; i <= SYSINT1_IRQ_LAST; i++)
+ irq_desc[i].handler = &sysint1_irq_type;
+
+ for (i = SYSINT2_IRQ_BASE; i <= SYSINT2_IRQ_LAST; i++)
+ irq_desc[i].handler = &sysint2_irq_type;
+
+ setup_irq(INT0_CASCADE_IRQ, &icu_cascade);
+ setup_irq(INT1_CASCADE_IRQ, &icu_cascade);
+ setup_irq(INT2_CASCADE_IRQ, &icu_cascade);
+ setup_irq(INT3_CASCADE_IRQ, &icu_cascade);
+ setup_irq(INT4_CASCADE_IRQ, &icu_cascade);
+}
+
+void __init arch_init_irq(void)
+{
+ mips_cpu_irq_init(MIPS_CPU_IRQ_BASE);
+ init_vr41xx_icu_irq();
+ init_vr41xx_giuint_irq();
+
+ set_except_vector(0, vr41xx_handle_interrupt);
+}
diff --git a/arch/mips/vr41xx/common/init.c b/arch/mips/vr41xx/common/init.c
new file mode 100644
index 0000000..e03be89
--- /dev/null
+++ b/arch/mips/vr41xx/common/init.c
@@ -0,0 +1,85 @@
+/*
+ * init.c, Common initialization routines for NEC VR4100 series.
+ *
+ * Copyright (C) 2003-2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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 <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/irq.h>
+#include <linux/string.h>
+
+#include <asm/bootinfo.h>
+#include <asm/time.h>
+#include <asm/vr41xx/vr41xx.h>
+
+#define IO_MEM_RESOURCE_START 0UL
+#define IO_MEM_RESOURCE_END 0x1fffffffUL
+
+static void __init iomem_resource_init(void)
+{
+ iomem_resource.start = IO_MEM_RESOURCE_START;
+ iomem_resource.end = IO_MEM_RESOURCE_END;
+}
+
+static void __init setup_timer_frequency(void)
+{
+ unsigned long tclock;
+
+ tclock = vr41xx_get_tclock_frequency();
+ if (current_cpu_data.processor_id == PRID_VR4131_REV2_0 ||
+ current_cpu_data.processor_id == PRID_VR4131_REV2_1)
+ mips_hpt_frequency = tclock / 2;
+ else
+ mips_hpt_frequency = tclock / 4;
+}
+
+static void __init setup_timer_irq(struct irqaction *irq)
+{
+ setup_irq(TIMER_IRQ, irq);
+}
+
+static void __init timer_init(void)
+{
+ board_time_init = setup_timer_frequency;
+ board_timer_setup = setup_timer_irq;
+}
+
+void __init prom_init(void)
+{
+ int argc, i;
+ char **argv;
+
+ argc = fw_arg0;
+ argv = (char **)fw_arg1;
+
+ for (i = 1; i < argc; i++) {
+ strcat(arcs_cmdline, argv[i]);
+ if (i < (argc - 1))
+ strcat(arcs_cmdline, " ");
+ }
+
+ vr41xx_calculate_clock_frequency();
+
+ timer_init();
+
+ iomem_resource_init();
+}
+
+unsigned long __init prom_free_prom_memory (void)
+{
+ return 0UL;
+}
diff --git a/arch/mips/vr41xx/common/int-handler.S b/arch/mips/vr41xx/common/int-handler.S
new file mode 100644
index 0000000..38ff89b
--- /dev/null
+++ b/arch/mips/vr41xx/common/int-handler.S
@@ -0,0 +1,114 @@
+/*
+ * FILE NAME
+ * arch/mips/vr41xx/common/int-handler.S
+ *
+ * BRIEF MODULE DESCRIPTION
+ * Interrupt dispatcher for the NEC VR4100 series.
+ *
+ * Author: Yoichi Yuasa
+ * yyuasa@mvista.com or source@mvista.com
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/*
+ * Changes:
+ * MontaVista Software Inc. <yyuasa@mvista.com> or <source@mvista.com>
+ * - New creation, NEC VR4100 series are supported.
+ *
+ * Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ * - Coped with INTASSIGN of NEC VR4133.
+ */
+#include <asm/asm.h>
+#include <asm/regdef.h>
+#include <asm/mipsregs.h>
+#include <asm/stackframe.h>
+
+ .text
+ .set noreorder
+
+ .align 5
+ NESTED(vr41xx_handle_interrupt, PT_SIZE, ra)
+ .set noat
+ SAVE_ALL
+ CLI
+ .set at
+ .set noreorder
+
+ /*
+ * Get the pending interrupts
+ */
+ mfc0 t0, CP0_CAUSE
+ mfc0 t1, CP0_STATUS
+ andi t0, 0xff00
+ and t0, t0, t1
+
+ andi t1, t0, CAUSEF_IP7 # MIPS timer interrupt
+ bnez t1, handle_irq
+ li a0, 7
+
+ andi t1, t0, 0x7800 # check for Int1-4
+ beqz t1, 1f
+
+ andi t1, t0, CAUSEF_IP3 # check for Int1
+ bnez t1, handle_int
+ li a0, 1
+
+ andi t1, t0, CAUSEF_IP4 # check for Int2
+ bnez t1, handle_int
+ li a0, 2
+
+ andi t1, t0, CAUSEF_IP5 # check for Int3
+ bnez t1, handle_int
+ li a0, 3
+
+ andi t1, t0, CAUSEF_IP6 # check for Int4
+ bnez t1, handle_int
+ li a0, 4
+
+1:
+ andi t1, t0, CAUSEF_IP2 # check for Int0
+ bnez t1, handle_int
+ li a0, 0
+
+ andi t1, t0, CAUSEF_IP0 # check for IP0
+ bnez t1, handle_irq
+ li a0, 0
+
+ andi t1, t0, CAUSEF_IP1 # check for IP1
+ bnez t1, handle_irq
+ li a0, 1
+
+ j spurious_interrupt
+ nop
+
+handle_int:
+ jal irq_dispatch
+ move a1, sp
+ j ret_from_irq
+ nop
+
+handle_irq:
+ jal do_IRQ
+ move a1, sp
+ j ret_from_irq
+ END(vr41xx_handle_interrupt)
diff --git a/arch/mips/vr41xx/common/pmu.c b/arch/mips/vr41xx/common/pmu.c
new file mode 100644
index 0000000..c5f1043
--- /dev/null
+++ b/arch/mips/vr41xx/common/pmu.c
@@ -0,0 +1,81 @@
+/*
+ * pmu.c, Power Management Unit routines for NEC VR4100 series.
+ *
+ * Copyright (C) 2003-2004 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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 <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/smp.h>
+#include <linux/types.h>
+
+#include <asm/cpu.h>
+#include <asm/io.h>
+#include <asm/reboot.h>
+#include <asm/system.h>
+
+#define PMUCNT2REG KSEG1ADDR(0x0f0000c6)
+ #define SOFTRST 0x0010
+
+static inline void software_reset(void)
+{
+ uint16_t val;
+
+ switch (current_cpu_data.cputype) {
+ case CPU_VR4122:
+ case CPU_VR4131:
+ case CPU_VR4133:
+ val = readw(PMUCNT2REG);
+ val |= SOFTRST;
+ writew(val, PMUCNT2REG);
+ break;
+ default:
+ break;
+ }
+}
+
+static void vr41xx_restart(char *command)
+{
+ local_irq_disable();
+ software_reset();
+ printk(KERN_NOTICE "\nYou can reset your system\n");
+ while (1) ;
+}
+
+static void vr41xx_halt(void)
+{
+ local_irq_disable();
+ printk(KERN_NOTICE "\nYou can turn off the power supply\n");
+ while (1) ;
+}
+
+static void vr41xx_power_off(void)
+{
+ local_irq_disable();
+ printk(KERN_NOTICE "\nYou can turn off the power supply\n");
+ while (1) ;
+}
+
+static int __init vr41xx_pmu_init(void)
+{
+ _machine_restart = vr41xx_restart;
+ _machine_halt = vr41xx_halt;
+ _machine_power_off = vr41xx_power_off;
+
+ return 0;
+}
+
+early_initcall(vr41xx_pmu_init);
diff --git a/arch/mips/vr41xx/common/vrc4173.c b/arch/mips/vr41xx/common/vrc4173.c
new file mode 100644
index 0000000..5475dd7
--- /dev/null
+++ b/arch/mips/vr41xx/common/vrc4173.c
@@ -0,0 +1,581 @@
+/*
+ * vrc4173.c, NEC VRC4173 base driver for NEC VR4122/VR4131.
+ *
+ * Copyright (C) 2001-2003 MontaVista Software Inc.
+ * Author: Yoichi Yuasa <yyuasa@mvista.com, or source@mvista.com>
+ * Copyright (C) 2004 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ * Copyright (C) 2005 Ralf Baechle (ralf@linux-mips.org)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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 <linux/init.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/pci.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+
+#include <asm/vr41xx/vr41xx.h>
+#include <asm/vr41xx/vrc4173.h>
+
+MODULE_DESCRIPTION("NEC VRC4173 base driver for NEC VR4122/4131");
+MODULE_AUTHOR("Yoichi Yuasa <yyuasa@mvista.com>");
+MODULE_LICENSE("GPL");
+
+#define VRC4173_CMUCLKMSK 0x040
+ #define MSKPIU 0x0001
+ #define MSKKIU 0x0002
+ #define MSKAIU 0x0004
+ #define MSKPS2CH1 0x0008
+ #define MSKPS2CH2 0x0010
+ #define MSKUSB 0x0020
+ #define MSKCARD1 0x0040
+ #define MSKCARD2 0x0080
+ #define MSKAC97 0x0100
+ #define MSK48MUSB 0x0400
+ #define MSK48MPIN 0x0800
+ #define MSK48MOSC 0x1000
+#define VRC4173_CMUSRST 0x042
+ #define USBRST 0x0001
+ #define CARD1RST 0x0002
+ #define CARD2RST 0x0004
+ #define AC97RST 0x0008
+
+#define VRC4173_SYSINT1REG 0x060
+#define VRC4173_MSYSINT1REG 0x06c
+#define VRC4173_MPIUINTREG 0x06e
+#define VRC4173_MAIUINTREG 0x070
+#define VRC4173_MKIUINTREG 0x072
+
+#define VRC4173_SELECTREG 0x09e
+ #define SEL3 0x0008
+ #define SEL2 0x0004
+ #define SEL1 0x0002
+ #define SEL0 0x0001
+
+static struct pci_device_id vrc4173_id_table[] __devinitdata = {
+ { .vendor = PCI_VENDOR_ID_NEC,
+ .device = PCI_DEVICE_ID_NEC_VRC4173,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID, },
+ { .vendor = 0, },
+};
+
+unsigned long vrc4173_io_offset = 0;
+
+EXPORT_SYMBOL(vrc4173_io_offset);
+
+static int vrc4173_initialized;
+static uint16_t vrc4173_cmuclkmsk;
+static uint16_t vrc4173_selectreg;
+static spinlock_t vrc4173_cmu_lock;
+static spinlock_t vrc4173_giu_lock;
+
+static inline void set_cmusrst(uint16_t val)
+{
+ uint16_t cmusrst;
+
+ cmusrst = vrc4173_inw(VRC4173_CMUSRST);
+ cmusrst |= val;
+ vrc4173_outw(cmusrst, VRC4173_CMUSRST);
+}
+
+static inline void clear_cmusrst(uint16_t val)
+{
+ uint16_t cmusrst;
+
+ cmusrst = vrc4173_inw(VRC4173_CMUSRST);
+ cmusrst &= ~val;
+ vrc4173_outw(cmusrst, VRC4173_CMUSRST);
+}
+
+void vrc4173_supply_clock(vrc4173_clock_t clock)
+{
+ if (vrc4173_initialized) {
+ spin_lock_irq(&vrc4173_cmu_lock);
+
+ switch (clock) {
+ case VRC4173_PIU_CLOCK:
+ vrc4173_cmuclkmsk |= MSKPIU;
+ break;
+ case VRC4173_KIU_CLOCK:
+ vrc4173_cmuclkmsk |= MSKKIU;
+ break;
+ case VRC4173_AIU_CLOCK:
+ vrc4173_cmuclkmsk |= MSKAIU;
+ break;
+ case VRC4173_PS2_CH1_CLOCK:
+ vrc4173_cmuclkmsk |= MSKPS2CH1;
+ break;
+ case VRC4173_PS2_CH2_CLOCK:
+ vrc4173_cmuclkmsk |= MSKPS2CH2;
+ break;
+ case VRC4173_USBU_PCI_CLOCK:
+ set_cmusrst(USBRST);
+ vrc4173_cmuclkmsk |= MSKUSB;
+ break;
+ case VRC4173_CARDU1_PCI_CLOCK:
+ set_cmusrst(CARD1RST);
+ vrc4173_cmuclkmsk |= MSKCARD1;
+ break;
+ case VRC4173_CARDU2_PCI_CLOCK:
+ set_cmusrst(CARD2RST);
+ vrc4173_cmuclkmsk |= MSKCARD2;
+ break;
+ case VRC4173_AC97U_PCI_CLOCK:
+ set_cmusrst(AC97RST);
+ vrc4173_cmuclkmsk |= MSKAC97;
+ break;
+ case VRC4173_USBU_48MHz_CLOCK:
+ set_cmusrst(USBRST);
+ vrc4173_cmuclkmsk |= MSK48MUSB;
+ break;
+ case VRC4173_EXT_48MHz_CLOCK:
+ if (vrc4173_cmuclkmsk & MSK48MOSC)
+ vrc4173_cmuclkmsk |= MSK48MPIN;
+ else
+ printk(KERN_WARNING
+ "vrc4173_supply_clock: "
+ "Please supply VRC4173_48MHz_CLOCK first "
+ "rather than VRC4173_EXT_48MHz_CLOCK.\n");
+ break;
+ case VRC4173_48MHz_CLOCK:
+ vrc4173_cmuclkmsk |= MSK48MOSC;
+ break;
+ default:
+ printk(KERN_WARNING
+ "vrc4173_supply_clock: Invalid CLOCK value %u\n", clock);
+ break;
+ }
+
+ vrc4173_outw(vrc4173_cmuclkmsk, VRC4173_CMUCLKMSK);
+
+ switch (clock) {
+ case VRC4173_USBU_PCI_CLOCK:
+ case VRC4173_USBU_48MHz_CLOCK:
+ clear_cmusrst(USBRST);
+ break;
+ case VRC4173_CARDU1_PCI_CLOCK:
+ clear_cmusrst(CARD1RST);
+ break;
+ case VRC4173_CARDU2_PCI_CLOCK:
+ clear_cmusrst(CARD2RST);
+ break;
+ case VRC4173_AC97U_PCI_CLOCK:
+ clear_cmusrst(AC97RST);
+ break;
+ default:
+ break;
+ }
+
+ spin_unlock_irq(&vrc4173_cmu_lock);
+ }
+}
+
+EXPORT_SYMBOL(vrc4173_supply_clock);
+
+void vrc4173_mask_clock(vrc4173_clock_t clock)
+{
+ if (vrc4173_initialized) {
+ spin_lock_irq(&vrc4173_cmu_lock);
+
+ switch (clock) {
+ case VRC4173_PIU_CLOCK:
+ vrc4173_cmuclkmsk &= ~MSKPIU;
+ break;
+ case VRC4173_KIU_CLOCK:
+ vrc4173_cmuclkmsk &= ~MSKKIU;
+ break;
+ case VRC4173_AIU_CLOCK:
+ vrc4173_cmuclkmsk &= ~MSKAIU;
+ break;
+ case VRC4173_PS2_CH1_CLOCK:
+ vrc4173_cmuclkmsk &= ~MSKPS2CH1;
+ break;
+ case VRC4173_PS2_CH2_CLOCK:
+ vrc4173_cmuclkmsk &= ~MSKPS2CH2;
+ break;
+ case VRC4173_USBU_PCI_CLOCK:
+ set_cmusrst(USBRST);
+ vrc4173_cmuclkmsk &= ~MSKUSB;
+ break;
+ case VRC4173_CARDU1_PCI_CLOCK:
+ set_cmusrst(CARD1RST);
+ vrc4173_cmuclkmsk &= ~MSKCARD1;
+ break;
+ case VRC4173_CARDU2_PCI_CLOCK:
+ set_cmusrst(CARD2RST);
+ vrc4173_cmuclkmsk &= ~MSKCARD2;
+ break;
+ case VRC4173_AC97U_PCI_CLOCK:
+ set_cmusrst(AC97RST);
+ vrc4173_cmuclkmsk &= ~MSKAC97;
+ break;
+ case VRC4173_USBU_48MHz_CLOCK:
+ set_cmusrst(USBRST);
+ vrc4173_cmuclkmsk &= ~MSK48MUSB;
+ break;
+ case VRC4173_EXT_48MHz_CLOCK:
+ vrc4173_cmuclkmsk &= ~MSK48MPIN;
+ break;
+ case VRC4173_48MHz_CLOCK:
+ vrc4173_cmuclkmsk &= ~MSK48MOSC;
+ break;
+ default:
+ printk(KERN_WARNING "vrc4173_mask_clock: Invalid CLOCK value %u\n", clock);
+ break;
+ }
+
+ vrc4173_outw(vrc4173_cmuclkmsk, VRC4173_CMUCLKMSK);
+
+ switch (clock) {
+ case VRC4173_USBU_PCI_CLOCK:
+ case VRC4173_USBU_48MHz_CLOCK:
+ clear_cmusrst(USBRST);
+ break;
+ case VRC4173_CARDU1_PCI_CLOCK:
+ clear_cmusrst(CARD1RST);
+ break;
+ case VRC4173_CARDU2_PCI_CLOCK:
+ clear_cmusrst(CARD2RST);
+ break;
+ case VRC4173_AC97U_PCI_CLOCK:
+ clear_cmusrst(AC97RST);
+ break;
+ default:
+ break;
+ }
+
+ spin_unlock_irq(&vrc4173_cmu_lock);
+ }
+}
+
+EXPORT_SYMBOL(vrc4173_mask_clock);
+
+static inline void vrc4173_cmu_init(void)
+{
+ vrc4173_cmuclkmsk = vrc4173_inw(VRC4173_CMUCLKMSK);
+
+ spin_lock_init(&vrc4173_cmu_lock);
+}
+
+void vrc4173_select_function(vrc4173_function_t function)
+{
+ if (vrc4173_initialized) {
+ spin_lock_irq(&vrc4173_giu_lock);
+
+ switch(function) {
+ case PS2_CHANNEL1:
+ vrc4173_selectreg |= SEL2;
+ break;
+ case PS2_CHANNEL2:
+ vrc4173_selectreg |= SEL1;
+ break;
+ case TOUCHPANEL:
+ vrc4173_selectreg &= SEL2 | SEL1 | SEL0;
+ break;
+ case KEYBOARD_8SCANLINES:
+ vrc4173_selectreg &= SEL3 | SEL2 | SEL1;
+ break;
+ case KEYBOARD_10SCANLINES:
+ vrc4173_selectreg &= SEL3 | SEL2;
+ break;
+ case KEYBOARD_12SCANLINES:
+ vrc4173_selectreg &= SEL3;
+ break;
+ case GPIO_0_15PINS:
+ vrc4173_selectreg |= SEL0;
+ break;
+ case GPIO_16_20PINS:
+ vrc4173_selectreg |= SEL3;
+ break;
+ }
+
+ vrc4173_outw(vrc4173_selectreg, VRC4173_SELECTREG);
+
+ spin_unlock_irq(&vrc4173_giu_lock);
+ }
+}
+
+EXPORT_SYMBOL(vrc4173_select_function);
+
+static inline void vrc4173_giu_init(void)
+{
+ vrc4173_selectreg = vrc4173_inw(VRC4173_SELECTREG);
+
+ spin_lock_init(&vrc4173_giu_lock);
+}
+
+void vrc4173_enable_piuint(uint16_t mask)
+{
+ irq_desc_t *desc = irq_desc + VRC4173_PIU_IRQ;
+ unsigned long flags;
+ uint16_t val;
+
+ spin_lock_irqsave(&desc->lock, flags);
+ val = vrc4173_inw(VRC4173_MPIUINTREG);
+ val |= mask;
+ vrc4173_outw(val, VRC4173_MPIUINTREG);
+ spin_unlock_irqrestore(&desc->lock, flags);
+}
+
+EXPORT_SYMBOL(vrc4173_enable_piuint);
+
+void vrc4173_disable_piuint(uint16_t mask)
+{
+ irq_desc_t *desc = irq_desc + VRC4173_PIU_IRQ;
+ unsigned long flags;
+ uint16_t val;
+
+ spin_lock_irqsave(&desc->lock, flags);
+ val = vrc4173_inw(VRC4173_MPIUINTREG);
+ val &= ~mask;
+ vrc4173_outw(val, VRC4173_MPIUINTREG);
+ spin_unlock_irqrestore(&desc->lock, flags);
+}
+
+EXPORT_SYMBOL(vrc4173_disable_piuint);
+
+void vrc4173_enable_aiuint(uint16_t mask)
+{
+ irq_desc_t *desc = irq_desc + VRC4173_AIU_IRQ;
+ unsigned long flags;
+ uint16_t val;
+
+ spin_lock_irqsave(&desc->lock, flags);
+ val = vrc4173_inw(VRC4173_MAIUINTREG);
+ val |= mask;
+ vrc4173_outw(val, VRC4173_MAIUINTREG);
+ spin_unlock_irqrestore(&desc->lock, flags);
+}
+
+EXPORT_SYMBOL(vrc4173_enable_aiuint);
+
+void vrc4173_disable_aiuint(uint16_t mask)
+{
+ irq_desc_t *desc = irq_desc + VRC4173_AIU_IRQ;
+ unsigned long flags;
+ uint16_t val;
+
+ spin_lock_irqsave(&desc->lock, flags);
+ val = vrc4173_inw(VRC4173_MAIUINTREG);
+ val &= ~mask;
+ vrc4173_outw(val, VRC4173_MAIUINTREG);
+ spin_unlock_irqrestore(&desc->lock, flags);
+}
+
+EXPORT_SYMBOL(vrc4173_disable_aiuint);
+
+void vrc4173_enable_kiuint(uint16_t mask)
+{
+ irq_desc_t *desc = irq_desc + VRC4173_KIU_IRQ;
+ unsigned long flags;
+ uint16_t val;
+
+ spin_lock_irqsave(&desc->lock, flags);
+ val = vrc4173_inw(VRC4173_MKIUINTREG);
+ val |= mask;
+ vrc4173_outw(val, VRC4173_MKIUINTREG);
+ spin_unlock_irqrestore(&desc->lock, flags);
+}
+
+EXPORT_SYMBOL(vrc4173_enable_kiuint);
+
+void vrc4173_disable_kiuint(uint16_t mask)
+{
+ irq_desc_t *desc = irq_desc + VRC4173_KIU_IRQ;
+ unsigned long flags;
+ uint16_t val;
+
+ spin_lock_irqsave(&desc->lock, flags);
+ val = vrc4173_inw(VRC4173_MKIUINTREG);
+ val &= ~mask;
+ vrc4173_outw(val, VRC4173_MKIUINTREG);
+ spin_unlock_irqrestore(&desc->lock, flags);
+}
+
+EXPORT_SYMBOL(vrc4173_disable_kiuint);
+
+static void enable_vrc4173_irq(unsigned int irq)
+{
+ uint16_t val;
+
+ val = vrc4173_inw(VRC4173_MSYSINT1REG);
+ val |= (uint16_t)1 << (irq - VRC4173_IRQ_BASE);
+ vrc4173_outw(val, VRC4173_MSYSINT1REG);
+}
+
+static void disable_vrc4173_irq(unsigned int irq)
+{
+ uint16_t val;
+
+ val = vrc4173_inw(VRC4173_MSYSINT1REG);
+ val &= ~((uint16_t)1 << (irq - VRC4173_IRQ_BASE));
+ vrc4173_outw(val, VRC4173_MSYSINT1REG);
+}
+
+static unsigned int startup_vrc4173_irq(unsigned int irq)
+{
+ enable_vrc4173_irq(irq);
+ return 0; /* never anything pending */
+}
+
+#define shutdown_vrc4173_irq disable_vrc4173_irq
+#define ack_vrc4173_irq disable_vrc4173_irq
+
+static void end_vrc4173_irq(unsigned int irq)
+{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
+ enable_vrc4173_irq(irq);
+}
+
+static struct hw_interrupt_type vrc4173_irq_type = {
+ .typename = "VRC4173",
+ .startup = startup_vrc4173_irq,
+ .shutdown = shutdown_vrc4173_irq,
+ .enable = enable_vrc4173_irq,
+ .disable = disable_vrc4173_irq,
+ .ack = ack_vrc4173_irq,
+ .end = end_vrc4173_irq,
+};
+
+static int vrc4173_get_irq_number(int irq)
+{
+ uint16_t status, mask;
+ int i;
+
+ status = vrc4173_inw(VRC4173_SYSINT1REG);
+ mask = vrc4173_inw(VRC4173_MSYSINT1REG);
+
+ status &= mask;
+ if (status) {
+ for (i = 0; i < 16; i++)
+ if (status & (0x0001 << i))
+ return VRC4173_IRQ(i);
+ }
+
+ return -EINVAL;
+}
+
+static inline int vrc4173_icu_init(int cascade_irq)
+{
+ int i;
+
+ if (cascade_irq < GIU_IRQ(0) || cascade_irq > GIU_IRQ(15))
+ return -EINVAL;
+
+ vrc4173_outw(0, VRC4173_MSYSINT1REG);
+
+ vr41xx_set_irq_trigger(GIU_IRQ_TO_PIN(cascade_irq), TRIGGER_LEVEL, SIGNAL_THROUGH);
+ vr41xx_set_irq_level(GIU_IRQ_TO_PIN(cascade_irq), LEVEL_LOW);
+
+ for (i = VRC4173_IRQ_BASE; i <= VRC4173_IRQ_LAST; i++)
+ irq_desc[i].handler = &vrc4173_irq_type;
+
+ return 0;
+}
+
+static int __devinit vrc4173_probe(struct pci_dev *dev,
+ const struct pci_device_id *id)
+{
+ unsigned long start, flags;
+ int err;
+
+ err = pci_enable_device(dev);
+ if (err < 0) {
+ printk(KERN_ERR "vrc4173: Failed to enable PCI device, aborting\n");
+ return err;
+ }
+
+ pci_set_master(dev);
+
+ start = pci_resource_start(dev, 0);
+ if (start == 0) {
+ printk(KERN_ERR "vrc4173:No such PCI I/O resource, aborting\n");
+ return -ENXIO;
+ }
+
+ flags = pci_resource_flags(dev, 0);
+ if ((flags & IORESOURCE_IO) == 0) {
+ printk(KERN_ERR "vrc4173: No such PCI I/O resource, aborting\n");
+ return -ENXIO;
+ }
+
+ err = pci_request_regions(dev, "NEC VRC4173");
+ if (err < 0) {
+ printk(KERN_ERR "vrc4173: PCI resources are busy, aborting\n");
+ return err;
+ }
+
+ set_vrc4173_io_offset(start);
+
+ vrc4173_cmu_init();
+ vrc4173_giu_init();
+
+ err = vrc4173_icu_init(dev->irq);
+ if (err < 0) {
+ printk(KERN_ERR "vrc4173: Invalid IRQ %d, aborting\n", dev->irq);
+ return err;
+ }
+
+ err = vr41xx_cascade_irq(dev->irq, vrc4173_get_irq_number);
+ if (err < 0) {
+ printk(KERN_ERR "vrc4173: IRQ resource %d is busy, aborting\n", dev->irq);
+ return err;
+ }
+
+ printk(KERN_INFO
+ "NEC VRC4173 at 0x%#08lx, IRQ is cascaded to %d\n", start, dev->irq);
+
+ return 0;
+}
+
+static void vrc4173_remove(struct pci_dev *dev)
+{
+ free_irq(dev->irq, NULL);
+
+ pci_release_regions(dev);
+}
+
+static struct pci_driver vrc4173_driver = {
+ .name = "NEC VRC4173",
+ .probe = vrc4173_probe,
+ .remove = vrc4173_remove,
+ .id_table = vrc4173_id_table,
+};
+
+static int __devinit vrc4173_init(void)
+{
+ int err;
+
+ err = pci_module_init(&vrc4173_driver);
+ if (err < 0)
+ return err;
+
+ vrc4173_initialized = 1;
+
+ return 0;
+}
+
+static void __devexit vrc4173_exit(void)
+{
+ vrc4173_initialized = 0;
+
+ pci_unregister_driver(&vrc4173_driver);
+}
+
+module_init(vrc4173_init);
+module_exit(vrc4173_exit);
diff --git a/arch/mips/vr41xx/ibm-workpad/Makefile b/arch/mips/vr41xx/ibm-workpad/Makefile
new file mode 100644
index 0000000..5ffaff0
--- /dev/null
+++ b/arch/mips/vr41xx/ibm-workpad/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for the IBM WorkPad z50 specific parts of the kernel
+#
+
+obj-y += setup.o
diff --git a/arch/mips/vr41xx/ibm-workpad/setup.c b/arch/mips/vr41xx/ibm-workpad/setup.c
new file mode 100644
index 0000000..cff4460
--- /dev/null
+++ b/arch/mips/vr41xx/ibm-workpad/setup.c
@@ -0,0 +1,40 @@
+/*
+ * setup.c, Setup for the IBM WorkPad z50.
+ *
+ * Copyright (C) 2002-2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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 <linux/init.h>
+#include <linux/ioport.h>
+
+#include <asm/io.h>
+#include <asm/vr41xx/workpad.h>
+
+const char *get_system_type(void)
+{
+ return "IBM WorkPad z50";
+}
+
+static int __init ibm_workpad_setup(void)
+{
+ set_io_port_base(IO_PORT_BASE);
+ ioport_resource.start = IO_PORT_RESOURCE_START;
+ ioport_resource.end = IO_PORT_RESOURCE_END;
+
+ return 0;
+}
+
+arch_initcall(ibm_workpad_setup);
diff --git a/arch/mips/vr41xx/nec-cmbvr4133/Makefile b/arch/mips/vr41xx/nec-cmbvr4133/Makefile
new file mode 100644
index 0000000..5835cae
--- /dev/null
+++ b/arch/mips/vr41xx/nec-cmbvr4133/Makefile
@@ -0,0 +1,8 @@
+#
+# Makefile for the NEC-CMBVR4133
+#
+
+obj-y := init.o setup.o
+
+obj-$(CONFIG_PCI) += m1535plus.o
+obj-$(CONFIG_ROCKHOPPER) += irq.o
diff --git a/arch/mips/vr41xx/nec-cmbvr4133/init.c b/arch/mips/vr41xx/nec-cmbvr4133/init.c
new file mode 100644
index 0000000..87f06b3
--- /dev/null
+++ b/arch/mips/vr41xx/nec-cmbvr4133/init.c
@@ -0,0 +1,78 @@
+/*
+ * arch/mips/vr41xx/nec-cmbvr4133/init.c
+ *
+ * PROM library initialisation code for NEC CMB-VR4133 board.
+ *
+ * Author: Yoichi Yuasa <yyuasa@mvista.com, or source@mvista.com> and
+ * Jun Sun <jsun@mvista.com, or source@mvista.com> and
+ * Alex Sapkov <asapkov@ru.mvista.com>
+ *
+ * 2001-2004 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ *
+ * Support for NEC-CMBVR4133 in 2.6
+ * Manish Lachwani (mlachwani@mvista.com)
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+
+#include <asm/bootinfo.h>
+
+#ifdef CONFIG_ROCKHOPPER
+#include <asm/io.h>
+#include <linux/pci.h>
+
+#define PCICONFDREG 0xaf000c14
+#define PCICONFAREG 0xaf000c18
+#endif
+
+const char *get_system_type(void)
+{
+ return "NEC CMB-VR4133";
+}
+
+#ifdef CONFIG_ROCKHOPPER
+void disable_pcnet(void)
+{
+ u32 data;
+
+ /*
+ * Workaround for the bug in PMON on VR4133. PMON leaves
+ * AMD PCNet controller (on Rockhopper) initialized and running in
+ * bus master mode. We have do disable it before doing any
+ * further initialization. Or we get problems with PCI bus 2
+ * and random lockups and crashes.
+ */
+
+ writel((2 << 16) |
+ (PCI_DEVFN(1,0) << 8) |
+ (0 & 0xfc) |
+ 1UL,
+ PCICONFAREG);
+
+ data = readl(PCICONFDREG);
+
+ writel((2 << 16) |
+ (PCI_DEVFN(1,0) << 8) |
+ (4 & 0xfc) |
+ 1UL,
+ PCICONFAREG);
+
+ data = readl(PCICONFDREG);
+
+ writel((2 << 16) |
+ (PCI_DEVFN(1,0) << 8) |
+ (4 & 0xfc) |
+ 1UL,
+ PCICONFAREG);
+
+ data &= ~4;
+
+ writel(data, PCICONFDREG);
+}
+#endif
+
diff --git a/arch/mips/vr41xx/nec-cmbvr4133/irq.c b/arch/mips/vr41xx/nec-cmbvr4133/irq.c
new file mode 100644
index 0000000..31db6b6
--- /dev/null
+++ b/arch/mips/vr41xx/nec-cmbvr4133/irq.c
@@ -0,0 +1,114 @@
+/*
+ * arch/mips/vr41xx/nec-cmbvr4133/irq.c
+ *
+ * Interrupt routines for the NEC CMB-VR4133 board.
+ *
+ * Author: Yoichi Yuasa <yyuasa@mvista.com, or source@mvista.com> and
+ * Alex Sapkov <asapkov@ru.mvista.com>
+ *
+ * 2003-2004 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ *
+ * Support for NEC-CMBVR4133 in 2.6
+ * Manish Lachwani (mlachwani@mvista.com)
+ */
+#include <linux/bitops.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+
+#include <asm/io.h>
+#include <asm/vr41xx/cmbvr4133.h>
+
+extern void enable_8259A_irq(unsigned int irq);
+extern void disable_8259A_irq(unsigned int irq);
+extern void mask_and_ack_8259A(unsigned int irq);
+extern void init_8259A(int hoge);
+
+extern int vr4133_rockhopper;
+
+static unsigned int startup_i8259_irq(unsigned int irq)
+{
+ enable_8259A_irq(irq - I8259_IRQ_BASE);
+ return 0;
+}
+
+static void shutdown_i8259_irq(unsigned int irq)
+{
+ disable_8259A_irq(irq - I8259_IRQ_BASE);
+}
+
+static void enable_i8259_irq(unsigned int irq)
+{
+ enable_8259A_irq(irq - I8259_IRQ_BASE);
+}
+
+static void disable_i8259_irq(unsigned int irq)
+{
+ disable_8259A_irq(irq - I8259_IRQ_BASE);
+}
+
+static void ack_i8259_irq(unsigned int irq)
+{
+ mask_and_ack_8259A(irq - I8259_IRQ_BASE);
+}
+
+static void end_i8259_irq(unsigned int irq)
+{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+ enable_8259A_irq(irq - I8259_IRQ_BASE);
+}
+
+static struct hw_interrupt_type i8259_irq_type = {
+ .typename = "XT-PIC",
+ .startup = startup_i8259_irq,
+ .shutdown = shutdown_i8259_irq,
+ .enable = enable_i8259_irq,
+ .disable = disable_i8259_irq,
+ .ack = ack_i8259_irq,
+ .end = end_i8259_irq,
+};
+
+static int i8259_get_irq_number(int irq)
+{
+ unsigned long isr;
+
+ isr = inb(0x20);
+ irq = ffz(~isr);
+ if (irq == 2) {
+ isr = inb(0xa0);
+ irq = 8 + ffz(~isr);
+ }
+
+ if (irq < 0 || irq > 15)
+ return -EINVAL;
+
+ return I8259_IRQ_BASE + irq;
+}
+
+static struct irqaction i8259_slave_cascade = {
+ .handler = &no_action,
+ .name = "cascade",
+};
+
+void __init rockhopper_init_irq(void)
+{
+ int i;
+
+ if(!vr4133_rockhopper) {
+ printk(KERN_ERR "Not a Rockhopper Board \n");
+ return;
+ }
+
+ for (i = I8259_IRQ_BASE; i <= I8259_IRQ_LAST; i++)
+ irq_desc[i].handler = &i8259_irq_type;
+
+ setup_irq(I8259_SLAVE_IRQ, &i8259_slave_cascade);
+
+ vr41xx_set_irq_trigger(CMBVR41XX_INTC_PIN, TRIGGER_LEVEL, SIGNAL_THROUGH);
+ vr41xx_set_irq_level(CMBVR41XX_INTC_PIN, LEVEL_HIGH);
+ vr41xx_cascade_irq(CMBVR41XX_INTC_IRQ, i8259_get_irq_number);
+}
diff --git a/arch/mips/vr41xx/nec-cmbvr4133/m1535plus.c b/arch/mips/vr41xx/nec-cmbvr4133/m1535plus.c
new file mode 100644
index 0000000..1f6b24e
--- /dev/null
+++ b/arch/mips/vr41xx/nec-cmbvr4133/m1535plus.c
@@ -0,0 +1,250 @@
+/*
+ * arch/mips/vr41xx/nec-cmbvr4133/m1535plus.c
+ *
+ * Initialize for ALi M1535+(included M5229 and M5237).
+ *
+ * Author: Yoichi Yuasa <yyuasa@mvista.com, or source@mvista.com> and
+ * Alex Sapkov <asapkov@ru.mvista.com>
+ *
+ * 2003-2004 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ *
+ * Support for NEC-CMBVR4133 in 2.6
+ * Author: Manish Lachwani (mlachwani@mvista.com)
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/serial.h>
+
+#include <asm/vr41xx/cmbvr4133.h>
+#include <linux/pci.h>
+#include <asm/io.h>
+
+#define CONFIG_PORT(port) ((port) ? 0x3f0 : 0x370)
+#define DATA_PORT(port) ((port) ? 0x3f1 : 0x371)
+#define INDEX_PORT(port) CONFIG_PORT(port)
+
+#define ENTER_CONFIG_MODE(port) \
+ do { \
+ outb_p(0x51, CONFIG_PORT(port)); \
+ outb_p(0x23, CONFIG_PORT(port)); \
+ } while(0)
+
+#define SELECT_LOGICAL_DEVICE(port, dev_no) \
+ do { \
+ outb_p(0x07, INDEX_PORT(port)); \
+ outb_p((dev_no), DATA_PORT(port)); \
+ } while(0)
+
+#define WRITE_CONFIG_DATA(port,index,data) \
+ do { \
+ outb_p((index), INDEX_PORT(port)); \
+ outb_p((data), DATA_PORT(port)); \
+ } while(0)
+
+#define EXIT_CONFIG_MODE(port) outb(0xbb, CONFIG_PORT(port))
+
+#define PCI_CONFIG_ADDR KSEG1ADDR(0x0f000c18)
+#define PCI_CONFIG_DATA KSEG1ADDR(0x0f000c14)
+
+#ifdef CONFIG_BLK_DEV_FD
+
+void __devinit ali_m1535plus_fdc_init(int port)
+{
+ ENTER_CONFIG_MODE(port);
+ SELECT_LOGICAL_DEVICE(port, 0); /* FDC */
+ WRITE_CONFIG_DATA(port, 0x30, 0x01); /* FDC: enable */
+ WRITE_CONFIG_DATA(port, 0x60, 0x03); /* I/O port base: 0x3f0 */
+ WRITE_CONFIG_DATA(port, 0x61, 0xf0);
+ WRITE_CONFIG_DATA(port, 0x70, 0x06); /* IRQ: 6 */
+ WRITE_CONFIG_DATA(port, 0x74, 0x02); /* DMA: channel 2 */
+ WRITE_CONFIG_DATA(port, 0xf0, 0x08);
+ WRITE_CONFIG_DATA(port, 0xf1, 0x00);
+ WRITE_CONFIG_DATA(port, 0xf2, 0xff);
+ WRITE_CONFIG_DATA(port, 0xf4, 0x00);
+ EXIT_CONFIG_MODE(port);
+}
+
+#endif
+
+void __devinit ali_m1535plus_parport_init(int port)
+{
+ ENTER_CONFIG_MODE(port);
+ SELECT_LOGICAL_DEVICE(port, 3); /* Parallel Port */
+ WRITE_CONFIG_DATA(port, 0x30, 0x01);
+ WRITE_CONFIG_DATA(port, 0x60, 0x03); /* I/O port base: 0x378 */
+ WRITE_CONFIG_DATA(port, 0x61, 0x78);
+ WRITE_CONFIG_DATA(port, 0x70, 0x07); /* IRQ: 7 */
+ WRITE_CONFIG_DATA(port, 0x74, 0x04); /* DMA: None */
+ WRITE_CONFIG_DATA(port, 0xf0, 0x8c); /* IRQ polarity: Active Low */
+ WRITE_CONFIG_DATA(port, 0xf1, 0xc5);
+ EXIT_CONFIG_MODE(port);
+}
+
+void __devinit ali_m1535plus_keyboard_init(int port)
+{
+ ENTER_CONFIG_MODE(port);
+ SELECT_LOGICAL_DEVICE(port, 7); /* KEYBOARD */
+ WRITE_CONFIG_DATA(port, 0x30, 0x01); /* KEYBOARD: eable */
+ WRITE_CONFIG_DATA(port, 0x70, 0x01); /* IRQ: 1 */
+ WRITE_CONFIG_DATA(port, 0x72, 0x0c); /* PS/2 Mouse IRQ: 12 */
+ WRITE_CONFIG_DATA(port, 0xf0, 0x00);
+ EXIT_CONFIG_MODE(port);
+}
+
+void __devinit ali_m1535plus_hotkey_init(int port)
+{
+ ENTER_CONFIG_MODE(port);
+ SELECT_LOGICAL_DEVICE(port, 0xc); /* HOTKEY */
+ WRITE_CONFIG_DATA(port, 0x30, 0x00);
+ WRITE_CONFIG_DATA(port, 0xf0, 0x35);
+ WRITE_CONFIG_DATA(port, 0xf1, 0x14);
+ WRITE_CONFIG_DATA(port, 0xf2, 0x11);
+ WRITE_CONFIG_DATA(port, 0xf3, 0x71);
+ WRITE_CONFIG_DATA(port, 0xf5, 0x05);
+ EXIT_CONFIG_MODE(port);
+}
+
+void ali_m1535plus_init(struct pci_dev *dev)
+{
+ pci_write_config_byte(dev, 0x40, 0x18); /* PCI Interface Control */
+ pci_write_config_byte(dev, 0x41, 0xc0); /* PS2 keyb & mouse enable */
+ pci_write_config_byte(dev, 0x42, 0x41); /* ISA bus cycle control */
+ pci_write_config_byte(dev, 0x43, 0x00); /* ISA bus cycle control 2 */
+ pci_write_config_byte(dev, 0x44, 0x5d); /* IDE enable & IRQ 14 */
+ pci_write_config_byte(dev, 0x45, 0x0b); /* PCI int polling mode */
+ pci_write_config_byte(dev, 0x47, 0x00); /* BIOS chip select control */
+
+ /* IRQ routing */
+ pci_write_config_byte(dev, 0x48, 0x03); /* INTA IRQ10, INTB disable */
+ pci_write_config_byte(dev, 0x49, 0x00); /* INTC and INTD disable */
+ pci_write_config_byte(dev, 0x4a, 0x00); /* INTE and INTF disable */
+ pci_write_config_byte(dev, 0x4b, 0x90); /* Audio IRQ11, Modem disable */
+
+ pci_write_config_word(dev, 0x50, 0x4000); /* Parity check IDE enable */
+ pci_write_config_word(dev, 0x52, 0x0000); /* USB & RTC disable */
+ pci_write_config_word(dev, 0x54, 0x0002); /* ??? no info */
+ pci_write_config_word(dev, 0x56, 0x0002); /* PCS1J signal disable */
+
+ pci_write_config_byte(dev, 0x59, 0x00); /* PCSDS */
+ pci_write_config_byte(dev, 0x5a, 0x00);
+ pci_write_config_byte(dev, 0x5b, 0x00);
+ pci_write_config_word(dev, 0x5c, 0x0000);
+ pci_write_config_byte(dev, 0x5e, 0x00);
+ pci_write_config_byte(dev, 0x5f, 0x00);
+ pci_write_config_word(dev, 0x60, 0x0000);
+
+ pci_write_config_byte(dev, 0x6c, 0x00);
+ pci_write_config_byte(dev, 0x6d, 0x48); /* ROM address mapping */
+ pci_write_config_byte(dev, 0x6e, 0x00); /* ??? what for? */
+
+ pci_write_config_byte(dev, 0x70, 0x12); /* Serial IRQ control */
+ pci_write_config_byte(dev, 0x71, 0xEF); /* DMA channel select */
+ pci_write_config_byte(dev, 0x72, 0x03); /* USB IDSEL */
+ pci_write_config_byte(dev, 0x73, 0x00); /* ??? no info */
+
+ /*
+ * IRQ setup ALi M5237 USB Host Controller
+ * IRQ: 9
+ */
+ pci_write_config_byte(dev, 0x74, 0x01); /* USB IRQ9 */
+
+ pci_write_config_byte(dev, 0x75, 0x1f); /* IDE2 IRQ 15 */
+ pci_write_config_byte(dev, 0x76, 0x80); /* ACPI disable */
+ pci_write_config_byte(dev, 0x77, 0x40); /* Modem disable */
+ pci_write_config_dword(dev, 0x78, 0x20000000); /* Pin select 2 */
+ pci_write_config_byte(dev, 0x7c, 0x00); /* Pin select 3 */
+ pci_write_config_byte(dev, 0x81, 0x00); /* ID read/write control */
+ pci_write_config_byte(dev, 0x90, 0x00); /* PCI PM block control */
+ pci_write_config_word(dev, 0xa4, 0x0000); /* PMSCR */
+
+#ifdef CONFIG_BLK_DEV_FD
+ ali_m1535plus_fdc_init(1);
+#endif
+
+ ali_m1535plus_keyboard_init(1);
+ ali_m1535plus_hotkey_init(1);
+}
+
+static inline void ali_config_writeb(u8 reg, u8 val, int devfn)
+{
+ u32 data;
+ int shift;
+
+ writel((1 << 16) | (devfn << 8) | (reg & 0xfc) | 1UL, PCI_CONFIG_ADDR);
+ data = readl(PCI_CONFIG_DATA);
+
+ shift = (reg & 3) << 3;
+ data &= ~(0xff << shift);
+ data |= (((u32)val) << shift);
+
+ writel(data, PCI_CONFIG_DATA);
+}
+
+static inline u8 ali_config_readb(u8 reg, int devfn)
+{
+ u32 data;
+
+ writel((1 << 16) | (devfn << 8) | (reg & 0xfc) | 1UL, PCI_CONFIG_ADDR);
+ data = readl(PCI_CONFIG_DATA);
+
+ return (u8)(data >> ((reg & 3) << 3));
+}
+
+static inline u16 ali_config_readw(u8 reg, int devfn)
+{
+ u32 data;
+
+ writel((1 << 16) | (devfn << 8) | (reg & 0xfc) | 1UL, PCI_CONFIG_ADDR);
+ data = readl(PCI_CONFIG_DATA);
+
+ return (u16)(data >> ((reg & 2) << 3));
+}
+
+int vr4133_rockhopper = 0;
+void __init ali_m5229_preinit(void)
+{
+ if (ali_config_readw(PCI_VENDOR_ID,16) == PCI_VENDOR_ID_AL &&
+ ali_config_readw(PCI_DEVICE_ID,16) == PCI_DEVICE_ID_AL_M1533) {
+ printk(KERN_INFO "Found an NEC Rockhopper \n");
+ vr4133_rockhopper = 1;
+ /*
+ * Enable ALi M5229 IDE Controller (both channels)
+ * IDSEL: A27
+ */
+ ali_config_writeb(0x58, 0x4c, 16);
+ }
+}
+
+void __init ali_m5229_init(struct pci_dev *dev)
+{
+ /*
+ * Enable Primary/Secondary Channel Cable Detect 40-Pin
+ */
+ pci_write_config_word(dev, 0x4a, 0xc023);
+
+ /*
+ * Set only the 3rd byteis for the master IDE's cycle and
+ * enable Internal IDE Function
+ */
+ pci_write_config_byte(dev, 0x50, 0x23); /* Class code attr register */
+
+ pci_write_config_byte(dev, 0x09, 0xff); /* Set native mode & stuff */
+ pci_write_config_byte(dev, 0x52, 0x00); /* use timing registers */
+ pci_write_config_byte(dev, 0x58, 0x02); /* Primary addr setup timing */
+ pci_write_config_byte(dev, 0x59, 0x22); /* Primary cmd block timing */
+ pci_write_config_byte(dev, 0x5a, 0x22); /* Pr drv 0 R/W timing */
+ pci_write_config_byte(dev, 0x5b, 0x22); /* Pr drv 1 R/W timing */
+ pci_write_config_byte(dev, 0x5c, 0x02); /* Sec addr setup timing */
+ pci_write_config_byte(dev, 0x5d, 0x22); /* Sec cmd block timing */
+ pci_write_config_byte(dev, 0x5e, 0x22); /* Sec drv 0 R/W timing */
+ pci_write_config_byte(dev, 0x5f, 0x22); /* Sec drv 1 R/W timing */
+ pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x20);
+ pci_write_config_word(dev, PCI_COMMAND,
+ PCI_COMMAND_PARITY | PCI_COMMAND_MASTER |
+ PCI_COMMAND_IO);
+}
+
diff --git a/arch/mips/vr41xx/nec-cmbvr4133/setup.c b/arch/mips/vr41xx/nec-cmbvr4133/setup.c
new file mode 100644
index 0000000..db686ce
--- /dev/null
+++ b/arch/mips/vr41xx/nec-cmbvr4133/setup.c
@@ -0,0 +1,96 @@
+/*
+ * arch/mips/vr41xx/nec-cmbvr4133/setup.c
+ *
+ * Setup for the NEC CMB-VR4133.
+ *
+ * Author: Yoichi Yuasa <yyuasa@mvista.com, or source@mvista.com> and
+ * Alex Sapkov <asapkov@ru.mvista.com>
+ *
+ * 2001-2004 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ *
+ * Support for CMBVR4133 board in 2.6
+ * Author: Manish Lachwani (mlachwani@mvista.com)
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/ide.h>
+#include <linux/ioport.h>
+
+#include <asm/reboot.h>
+#include <asm/time.h>
+#include <asm/vr41xx/cmbvr4133.h>
+#include <asm/bootinfo.h>
+
+#ifdef CONFIG_MTD
+#include <linux/mtd/physmap.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/map.h>
+
+static struct mtd_partition cmbvr4133_mtd_parts[] = {
+ {
+ .name = "User FS",
+ .size = 0x1be0000,
+ .offset = 0,
+ .mask_flags = 0,
+ },
+ {
+ .name = "PMON",
+ .size = 0x140000,
+ .offset = MTDPART_OFS_APPEND,
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ },
+ {
+ .name = "User FS2",
+ .size = MTDPART_SIZ_FULL,
+ .offset = MTDPART_OFS_APPEND,
+ .mask_flags = 0,
+ }
+};
+
+#define number_partitions (sizeof(cmbvr4133_mtd_parts)/sizeof(struct mtd_partition))
+#endif
+
+extern void i8259_init(void);
+
+static int __init nec_cmbvr4133_setup(void)
+{
+#ifdef CONFIG_ROCKHOPPER
+ extern void disable_pcnet(void);
+
+ disable_pcnet();
+#endif
+ set_io_port_base(KSEG1ADDR(0x16000000));
+
+ mips_machgroup = MACH_GROUP_NEC_VR41XX;
+ mips_machtype = MACH_NEC_CMBVR4133;
+
+#ifdef CONFIG_PCI
+#ifdef CONFIG_ROCKHOPPER
+ ali_m5229_preinit();
+#endif
+#endif
+
+#ifdef CONFIG_ROCKHOPPER
+ rockhopper_init_irq();
+#endif
+
+#ifdef CONFIG_MTD
+ /* we use generic physmap mapping driver and we use partitions */
+ physmap_configure(0x1C000000, 0x02000000, 4, NULL);
+ physmap_set_partitions(cmbvr4133_mtd_parts, number_partitions);
+#endif
+
+ /* 128 MB memory support */
+ add_memory_region(0, 0x08000000, BOOT_MEM_RAM);
+
+#ifdef CONFIG_ROCKHOPPER
+ i8259_init();
+#endif
+ return 0;
+}
+
+early_initcall(nec_cmbvr4133_setup);
diff --git a/arch/mips/vr41xx/tanbac-tb0226/Makefile b/arch/mips/vr41xx/tanbac-tb0226/Makefile
new file mode 100644
index 0000000..372f953
--- /dev/null
+++ b/arch/mips/vr41xx/tanbac-tb0226/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for the TANBAC TB0226 specific parts of the kernel
+#
+
+obj-y += setup.o
diff --git a/arch/mips/vr41xx/tanbac-tb0226/setup.c b/arch/mips/vr41xx/tanbac-tb0226/setup.c
new file mode 100644
index 0000000..60027e5
--- /dev/null
+++ b/arch/mips/vr41xx/tanbac-tb0226/setup.c
@@ -0,0 +1,24 @@
+/*
+ * setup.c, Setup for the TANBAC TB0226.
+ *
+ * Copyright (C) 2002-2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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
+ */
+
+const char *get_system_type(void)
+{
+ return "TANBAC TB0226";
+}
diff --git a/arch/mips/vr41xx/tanbac-tb0229/Makefile b/arch/mips/vr41xx/tanbac-tb0229/Makefile
new file mode 100644
index 0000000..9c6b864
--- /dev/null
+++ b/arch/mips/vr41xx/tanbac-tb0229/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for the TANBAC TB0229(VR4131DIMM) specific parts of the kernel
+#
+
+obj-y := setup.o
diff --git a/arch/mips/vr41xx/tanbac-tb0229/setup.c b/arch/mips/vr41xx/tanbac-tb0229/setup.c
new file mode 100644
index 0000000..5c1b757
--- /dev/null
+++ b/arch/mips/vr41xx/tanbac-tb0229/setup.c
@@ -0,0 +1,27 @@
+/*
+ * setup.c, Setup for the TANBAC TB0229 (VR4131DIMM)
+ *
+ * Copyright (C) 2002-2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ *
+ * Modified for TANBAC TB0229:
+ * Copyright (C) 2003 Megasolution Inc. <matsu@megasolution.jp>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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
+ */
+
+const char *get_system_type(void)
+{
+ return "TANBAC TB0229";
+}
diff --git a/arch/mips/vr41xx/victor-mpc30x/Makefile b/arch/mips/vr41xx/victor-mpc30x/Makefile
new file mode 100644
index 0000000..a2e8086
--- /dev/null
+++ b/arch/mips/vr41xx/victor-mpc30x/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for the Victor MP-C303/304 specific parts of the kernel
+#
+
+obj-y += setup.o
diff --git a/arch/mips/vr41xx/victor-mpc30x/setup.c b/arch/mips/vr41xx/victor-mpc30x/setup.c
new file mode 100644
index 0000000..f591e36
--- /dev/null
+++ b/arch/mips/vr41xx/victor-mpc30x/setup.c
@@ -0,0 +1,24 @@
+/*
+ * setup.c, Setup for the Victor MP-C303/304.
+ *
+ * Copyright (C) 2002-2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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
+ */
+
+const char *get_system_type(void)
+{
+ return "Victor MP-C303/304";
+}
diff --git a/arch/mips/vr41xx/zao-capcella/Makefile b/arch/mips/vr41xx/zao-capcella/Makefile
new file mode 100644
index 0000000..cf42019
--- /dev/null
+++ b/arch/mips/vr41xx/zao-capcella/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for the ZAO Networks Capcella specific parts of the kernel
+#
+
+obj-y += setup.o
diff --git a/arch/mips/vr41xx/zao-capcella/setup.c b/arch/mips/vr41xx/zao-capcella/setup.c
new file mode 100644
index 0000000..17bade2
--- /dev/null
+++ b/arch/mips/vr41xx/zao-capcella/setup.c
@@ -0,0 +1,24 @@
+/*
+ * setup.c, Setup for the ZAO Networks Capcella.
+ *
+ * Copyright (C) 2002-2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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
+ */
+
+const char *get_system_type(void)
+{
+ return "ZAO Networks Capcella";
+}