--- linux-2.6.11.2/arch/arm/mm/proc-xscale.S	2005-03-09 00:12:44.000000000 -0800
+++ linux-2.6.11.2/arch/arm/mm/proc-xscale.S	2005-06-18 15:39:22.701222319 -0700
@@ -137,23 +137,129 @@
  * same state as it would be if it had been reset, and branch
  * to what would be the reset vector.
  *
+ * This code is ixp425 specific with respect to the reset of
+ * the 'configuration register' - to be found at address
+ * 0xC40000020 'IXP425_EXP_CNFGO'
+ *
  * loc: location to jump to for soft reset
  */
 	.align	5
 ENTRY(cpu_xscale_reset)
+	@ always branch to 0
+	mov	r0, #0
+
+	@ disable both FIQ and IRQ, put us into 32 bit
+	@ SVC mode (no thumb).
 	mov	r1, #PSR_F_BIT|PSR_I_BIT|SVC_MODE
 	msr	cpsr_c, r1			@ reset CPSR
-	mrc	p15, 0, r1, c1, c0, 0		@ ctrl register
-	bic	r1, r1, #0x0086			@ ........B....CA.
-	bic	r1, r1, #0x3900			@ ..VIZ..S........
-	mcr	p15, 0, r1, c1, c0, 0		@ ctrl register
-	mcr	p15, 0, ip, c7, c7, 0		@ invalidate I,D caches & BTB
-	bic	r1, r1, #0x0001			@ ...............M
-	mcr	p15, 0, r1, c1, c0, 0		@ ctrl register
-	@ CAUTION: MMU turned off from this point. We count on the pipeline
-	@ already containing those two last instructions to survive.
+
+	@ disable debug, clock and power registers are
+	@ unimplemented.
+	mcr	p14, 0, r0, c10, c0, 0		@ disable debug
+
+	@ disable the performance monitor
+	mcr	p14, 0, r0, c0, c1, 0		@ PMNC (ctrl reg)
+	mcr	p14, 0, r0, c4, c1, 0		@ INTEN (intrpt enable)
+
+	@ wait for p14 to complete
+	mrc	p14, 0, ip, c4, c1, 0		@ arbitrary read
+	mov	ip, ip				@ sync
+
+	@ clear the PID register
+	mcr	p15, 0, r0, c13, c0, 0		@ OR nothing with address!
+
+	@ unlock the TLBs and the I/D cache locks
+	mcr	p15, 0, r0, c10, c8, 1		@ data TLB unlocked
+	mcr	p15, 0, r0, c10, c4, 1		@ instruction TLB unlocked
+	mcr	p15, 0, r0,  c9, c2, 1		@ unlock data cache
+	mcr	p15, 0, r0,  c9, c1, 1		@ unlock instruction cache
+
+	@ zap the minidata cache to write through with write coalescing
+	@ disabled.
+	mov	r1, #0x21			@ MD=b10, K=1
+	mcr	p15, 0, r0, c7, c10, 4		@ drain write buffer
+	mrc	p15, 0, ip, c1, c0, 0		@ read of ctrl register
+	mov	ip, ip				@ sync
+	mcr 	p15, 0, r1, c1, c0, 1		@ write through, no coalesc
+
+	@ set the control register, the MMU is enabled but everything else
+	@ is disabled at this point, r1 contains the control register flags
+	@ the process is now in little-endian mode (no matter, we aren't
+	@ going to do any <word access)
+	mov	r1, #0x79			@ 00vIz0rs.b1111caM
+	orr	r1, r1, #0x1000			@ I-cache enable
+	mcr	p15, 0, r1, c1, c0, 0
+	mrc	p15, 0, ip, c1, c0, 0
+	mov	ip, ip				@ sync to coproc
+	mov	r1, #0x78			@ 00viz0rs.b1111cam
+
+	@ and flush the I/D cache and BTB
+	mcr	p15, 0, r0, c7, c7, 0
+
+	@ that's most of the work.  The only thing which remains is to
+	@ remap the flash memory and disable the MMU.  Do some setup
+	@ for this, also get ready to set the LED to red and put in
+	@ a watchdog timer.
+
+	@ get ready to reset the configuration registers in the expansion
+	@ bus.  CFGN1 disables byte swap and interrupt.
+	ldr	r3, =IXP4XX_PERIPHERAL_BASE_VIRT
+	ldr	r4, [r3, #IXP4XX_EXP_CFG1_OFFSET]
+	bic	r4, r4, #0x13			@ -BYTE_SWAP_EN, -SW_INT?
+	str	r4, [r3, #IXP4XX_EXP_CFG1_OFFSET]
+
+	@ load the current configuration register from its
+	@ virtual address and set the MEM_MAP bit ready to map the
+	@ flash back to address 0, but don't write it yet.
+	ldr	r4, [r3, #IXP4XX_EXP_CFG0_OFFSET]
+	orr	r4, r4, #0x80000000
+
+	@ load the GPIO OUTR register address and current value,
+	@ set the low nibble to just red LED on.
+	ldr	r5, =IXP4XX_GPIO_BASE_VIRT
+	ldr	r6, [r5, #IXP4XX_GPIO_GPOUTR_OFFSET]
+	bic	r6, r6, #0xf
+	orr	r6, r6, #0xd
+
+	@ load the watchdog timer virtual address, set the key and
+	@ the timer and start the down counter
+	ldr	r7, =IXP4XX_TIMER_BASE_VIRT
+	ldr	r8, =IXP4XX_WDT_KEY		@ set key
+	str	r8, [r7, #IXP4XX_OSWK_OFFSET]
+	mov	r8, #0x1000000			@ about 0.25 seconds
+	str	r8, [r7, #IXP4XX_OSWT_OFFSET]	@ set timer
+	mov	r8, #(IXP4XX_WDT_RESET_ENABLE | IXP4XX_WDT_COUNT_ENABLE)
+	str	r8, [r7, #IXP4XX_OSWE_OFFSET]	@ enable reset
+
+	@ invalidate the TLBs to ensure that there isn't a match for
+	@ '0' there.
 	mcr	p15, 0, ip, c8, c7, 0		@ invalidate I & D TLBs
-	mov	pc, r0
+	mrc	p15, 0, ip, c1, c0, 0		@ read of ctrl register
+	mov	ip, ip				@ sync
+
+	@ remap the flash (after preloading instructions into the
+	@ I-cache) then turn off the MMU and branch to 0 when it is
+	@ off.  It seems that RedBoot relies on the page tables being
+	@ set up on boot, so set the page table head register too.
+	mov	r7, #0x4000			@ flash page table
+	ldr	r8, =IXP4XX_GPIO_BASE_PHYS	@ for led setting
+	bic	r9, r6, #0xc			@ disk1+disk2 led on
+	str	r6, [r5, #IXP4XX_GPIO_GPOUTR_OFFSET]	@ red led
+	b	cache
+
+	@ cached instructions  These 8 instructions are valid in the cache
+	@ along with the associated TLB as soon as the first is executed.
+	@ They are used to effect the transition back into the flash
+	@ ROM code.
+	.align	5
+cache:	str	r4, [r3, #IXP4XX_EXP_CFG0_OFFSET]	@0 no memory!
+	mcr	p15, 0, r7, c2, c0, 0			@1 set translation table base
+	mcr	p15, 0, r1, c1, c0, 0			@2 no MMU!
+	mrc	p15, 0, ip, c2, c0, 0			@3 arbitrary read of cp15
+	str	r9, [r8, #IXP4XX_GPIO_GPOUTR_OFFSET]	@4 red+disk1+disk2 led
+	sub	pc, r0, ip, LSR #32			@5 sync and branch to zero
+	nop						@6
+	nop						@7
 
 /*
  * cpu_xscale_do_idle()
@@ -168,8 +274,10 @@
 	.align	5
 
 ENTRY(cpu_xscale_do_idle)
-	mov	r0, #1
-	mcr	p14, 0, r0, c7, c0, 0		@ Go to IDLE
+	@ NSLU2/ixp420: not implemented in the hardware, docs
+	@ say do not write!
+	@mov	r0, #1
+	@mcr	p14, 0, r0, c7, c0, 0		@ Go to IDLE
 	mov	pc, lr
 
 /* ================================= CACHE ================================ */