9fans - fans of the OS Plan 9 from Bell Labs
 help / color / mirror / Atom feed
* [9fans] bitsy suspend fix
@ 2002-05-17 11:25 Fco.J.Ballesteros
  0 siblings, 0 replies; only message in thread
From: Fco.J.Ballesteros @ 2002-05-17 11:25 UTC (permalink / raw)
  To: 9fans

[-- Attachment #1: Type: text/plain, Size: 379 bytes --]

I found that the code as distributed caused permanent hangs (i.e.
not resuming) some times and it looks like it was causing a panic some times.
(Perhaps that's why it was doing a reset at resume time?).

I think this version works; at least I'm using it and did not make
weird things (yet).

The files are attached.
Let me know if this code fails for any of you.

hth

[-- Attachment #2.1: Type: text/plain, Size: 303 bytes --]

The following attachment had content that we can't
prove to be harmless.  To avoid possible automatic
execution, we changed the content headers.
The original header was:

	Content-Disposition: attachment; filename=l.s
	Content-Type: text/plain; charset="US-ASCII"
	Content-Transfer-Encoding: 7bit

[-- Attachment #2.2: l.s.suspect --]
[-- Type: application/octet-stream, Size: 18237 bytes --]

#include "mem.h"

/*
 * Entered here from Compaq's bootldr with MMU disabled.
 */
TEXT _start(SB), $-4
	MOVW	$setR12(SB), R12		/* load the SB */
_main:
	/* SVC mode, interrupts disabled */
	MOVW	$(PsrDirq|PsrDfiq|PsrMsvc), R1
	MOVW	R1, CPSR

	/* disable the MMU */
	MOVW	$0x130, R1
	MCR     CpMMU, 0, R1, C(CpControl), C(0x0)

	/* flush caches */
	MCR	CpMMU, 0, R0, C(CpCacheFlush), C(0x7), 0
	/* drain prefetch */
	MOVW	R0,R0
	MOVW	R0,R0
	MOVW	R0,R0
	MOVW	R0,R0

	/* drain write buffer */
	MCR	CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 4

	MOVW	$(MACHADDR+4*BY2PG), R13		/* stack */
	SUB	$4, R13				/* link */
	BL	main(SB)
	BL	exit(SB)
	/* we shouldn't get here */
_mainloop:
	B	_mainloop
	BL	_div(SB)			/* hack to get _div etc loaded */

/* flush tlb's */
TEXT mmuinvalidate(SB), $-4
	MCR	CpMMU, 0, R0, C(CpTLBFlush), C(0x7)
	RET

/* flush tlb's */
TEXT mmuinvalidateaddr(SB), $-4
	MCR	CpMMU, 0, R0, C(CpTLBFlush), C(0x6), 1
	RET

/* write back and invalidate i and d caches */
TEXT cacheflush(SB), $-4
	/* splhi */
	MOVW	CPSR, R3
	ORR		$(PsrDirq), R3, R1
	MOVW	R1, CPSR

	/* write back any dirty data */
	MOVW	$0xe0000000,R0
	ADD		$(8*1024),R0,R1
_cfloop:
	MOVW.P	32(R0),R2
	CMP.S	R0,R1
	BGE	_cfloop

	/* drain write buffer and invalidate i cache contents */
	MCR		CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 4
	MCR		CpMMU, 0, R0, C(CpCacheFlush), C(0x5), 0

	/* drain prefetch */
	MOVW	R0,R0
	MOVW	R0,R0
	MOVW	R0,R0
	MOVW	R0,R0

	/* splx */
	MOVW	R3, CPSR
	RET

/* write back d cache */
TEXT cachewb(SB), $-4
	/* write back any dirty data */
_cachewb:
	MOVW	$0xe0000000,R0
	ADD		$(8*1024),R0,R1
_cwbloop:
	MOVW.P	32(R0),R2
	CMP.S	R0,R1
	BGE	_cwbloop

	/* drain write buffer */
	MCR	CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 4
	RET

/* write back a single cache line */
TEXT cachewbaddr(SB), $-4
	BIC	$31,R0
	MCR	CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 1
	B	_wbflush

/* write back a region of cache lines */
TEXT cachewbregion(SB), $-4
	MOVW	4(FP),R1
	CMP.S	$(4*1024),R1
	BGT	_cachewb
	ADD	R0,R1
	BIC	$31,R0
_cwbrloop:
	MCR	CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 1
	ADD	$32,R0
	CMP.S	R0,R1
	BGT	_cwbrloop
	B	_wbflush

/* invalidate the dcache */
TEXT dcacheinvalidate(SB), $-4
	MCR	CpMMU, 0, R0, C(CpCacheFlush), C(0x6)
	RET

/* invalidate the icache */
TEXT icacheinvalidate(SB), $-4
	MCR	CpMMU, 0, R0, C(CpCacheFlush), C(0x9)
	RET

/* drain write buffer */
TEXT wbflush(SB), $-4
_wbflush:
	MCR	CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 4
	RET

/* return cpu id */
TEXT getcpuid(SB), $-4
	MRC	CpMMU, 0, R0, C(CpCPUID), C(0x0)
	RET

/* return fault status */
TEXT getfsr(SB), $-4
	MRC	CpMMU, 0, R0, C(CpFSR), C(0x0)
	RET

/* return mmu control register */
TEXT getcontrol(SB), $-4
	SUB R0, R0
	MRC	CpMMU, 0, R0, C(CpControl), C(0x0)
	RET

/* return mmu dac register */
TEXT getdac(SB), $-4
	SUB R0, R0
	MRC	CpMMU, 0, R0, C(CpDAC), C(0x0)
	RET

/* return mmu ttb register */
TEXT getttb(SB), $-4
	SUB R0, R0
	MRC	CpMMU, 0, R0, C(CpTTB), C(0x0)
	RET

/* return fault address */
TEXT getfar(SB), $-4
	MRC	CpMMU, 0, R0, C(CpFAR), C(0x0)
	RET

/* set the translation table base */
TEXT putttb(SB), $-4
	MCR	CpMMU, 0, R0, C(CpTTB), C(0x0)
	RET

/*
 *  enable mmu, i and d caches
 */
TEXT mmuenable(SB), $-4
	MRC	CpMMU, 0, R0, C(CpControl), C(0x0)
	ORR	$(CpCmmuena|CpCdcache|CpCicache|CpCwb), R0
	MCR     CpMMU, 0, R0, C(CpControl), C(0x0)
	MOVW R0, R0
	MOVW R0, R0
	MOVW R0, R0
	MOVW R0, R0
	RET

TEXT mmudisable(SB), $-4
	MRC	CpMMU, 0, R0, C(CpControl), C(0x0)
	BIC	$(CpCmmuena|CpCdcache|CpCicache|CpCwb|CpCvivec), R0
	MCR     CpMMU, 0, R0, C(CpControl), C(0x0)
	RET

/*
 *  use exception vectors at 0xffff0000
 */
TEXT mappedIvecEnable(SB), $-4
	MRC	CpMMU, 0, R0, C(CpControl), C(0x0)
	ORR	$(CpCvivec), R0
	MCR     CpMMU, 0, R0, C(CpControl), C(0x0)
	RET
TEXT mappedIvecDisable(SB), $-4
	MRC	CpMMU, 0, R0, C(CpControl), C(0x0)
	BIC	$(CpCvivec), R0
	MCR     CpMMU, 0, R0, C(CpControl), C(0x0)
	RET

/* set the translation table base */
TEXT putdac(SB), $-4
	MCR	CpMMU, 0, R0, C(CpDAC), C(0x0)
	RET

/* set address translation pid */
TEXT putpid(SB), $-4
	MCR	CpMMU, 0, R0, C(CpPID), C(0x0)
	RET

/*
 *  set the stack value for the mode passed in R0
 */
TEXT setr13(SB), $-4
	MOVW	4(FP), R1

	MOVW	CPSR, R2
	BIC	$PsrMask, R2, R3
	ORR	R0, R3
	MOVW	R3, CPSR

	MOVW	R13, R0
	MOVW	R1, R13

	MOVW	R2, CPSR
	RET

/*
 *  exception vectors, copied by trapinit() to somewhere useful
 */

TEXT vectors(SB), $-4
	MOVW	0x18(R15), R15			/* reset */
	MOVW	0x18(R15), R15			/* undefined */
	MOVW	0x18(R15), R15			/* SWI */
	MOVW	0x18(R15), R15			/* prefetch abort */
	MOVW	0x18(R15), R15			/* data abort */
	MOVW	0x18(R15), R15			/* reserved */
	MOVW	0x18(R15), R15			/* IRQ */
	MOVW	0x18(R15), R15			/* FIQ */

TEXT vtable(SB), $-4
	WORD	$_vsvc(SB)			/* reset, in svc mode already */
	WORD	$_vund(SB)			/* undefined, switch to svc mode */
	WORD	$_vsvc(SB)			/* swi, in svc mode already */
	WORD	$_vpabt(SB)			/* prefetch abort, switch to svc mode */
	WORD	$_vdabt(SB)			/* data abort, switch to svc mode */
	WORD	$_vsvc(SB)			/* reserved */
	WORD	$_virq(SB)			/* IRQ, switch to svc mode */
	WORD	$_vfiq(SB)			/* FIQ, switch to svc mode */

TEXT _vrst(SB), $-4
	BL	resettrap(SB)

TEXT _vsvc(SB), $-4			/* SWI */
	MOVW.W	R14, -4(R13)		/* ureg->pc = interupted PC */
	MOVW	SPSR, R14		/* ureg->psr = SPSR */
	MOVW.W	R14, -4(R13)		/* ... */
	MOVW	$PsrMsvc, R14		/* ureg->type = PsrMsvc */
	MOVW.W	R14, -4(R13)		/* ... */
	MOVM.DB.W.S [R0-R14], (R13)	/* save user level registers, at end r13 points to ureg */
	MOVW	$setR12(SB), R12	/* Make sure we've got the kernel's SB loaded */
	MOVW	R13, R0			/* first arg is pointer to ureg */
	SUB	$8, R13			/* space for argument+link */

	BL	syscall(SB)

	ADD	$(8+4*15), R13		/* make r13 point to ureg->type */
	MOVW	8(R13), R14		/* restore link */
	MOVW	4(R13), R0		/* restore SPSR */
	MOVW	R0, SPSR		/* ... */
	MOVM.DB.S (R13), [R0-R14]	/* restore registers */
	ADD	$8, R13			/* pop past ureg->{type+psr} */
	RFE				/* MOVM.IA.S.W (R13), [R15] */

TEXT _vund(SB), $-4			/* undefined */
	MOVM.IA	[R0-R4], (R13)		/* free some working space */
	MOVW	$PsrMund, R0
	B	_vswitch

TEXT _vpabt(SB), $-4			/* prefetch abort */
	MOVM.IA	[R0-R4], (R13)		/* free some working space */
	MOVW	$PsrMabt, R0		/* r0 = type */
	B	_vswitch

TEXT _vdabt(SB), $-4			/* prefetch abort */
	MOVM.IA	[R0-R4], (R13)		/* free some working space */
	MOVW	$(PsrMabt+1), R0		/* r0 = type */
	B	_vswitch

TEXT _virq(SB), $-4			/* IRQ */
	MOVM.IA	[R0-R4], (R13)		/* free some working space */
	MOVW	$PsrMirq, R0		/* r0 = type */
	B	_vswitch

	/*
	 *  come here with type in R0 and R13 pointing above saved [r0-r4]
	 *  and type in r0.  we'll switch to SVC mode and then call trap.
	 */
_vswitch:
	MOVW	SPSR, R1		/* save SPSR for ureg */
	MOVW	R14, R2			/* save interrupted pc for ureg */
	MOVW	R13, R3			/* save pointer to where the original [R0-R3] are */

	/* switch to svc mode */
	MOVW	CPSR, R14
	BIC	$PsrMask, R14
	ORR	$(PsrDirq|PsrDfiq|PsrMsvc), R14
	MOVW	R14, CPSR

	/* interupted code kernel or user? */
	AND.S	$0xf, R1, R4
	BEQ	_userexcep

	/* here for trap from SVC mode */
	MOVM.DB.W [R0-R2], (R13)	/* set ureg->{type, psr, pc}; r13 points to ureg->type  */
	MOVM.IA	  (R3), [R0-R4]		/* restore [R0-R4] from previous mode's stack */
	MOVM.DB.W [R0-R14], (R13)	/* save kernel level registers, at end r13 points to ureg */
	MOVW	$setR12(SB), R12	/* Make sure we've got the kernel's SB loaded */
	MOVW	R13, R0			/* first arg is pointer to ureg */
	SUB	$8, R13			/* space for argument+link (for debugger) */
	MOVW	$0xdeaddead,R11		/* marker */

	BL	trap(SB)

	ADD	$(8+4*15), R13		/* make r13 point to ureg->type */
	MOVW	8(R13), R14		/* restore link */
	MOVW	4(R13), R0		/* restore SPSR */
	MOVW	R0, SPSR		/* ... */
	MOVM.DB (R13), [R0-R14]	/* restore registers */
	ADD	$8, R13			/* pop past ureg->{type+psr} */
	RFE				/* MOVM.IA.S.W (R13), [R15] */

	/* here for trap from USER mode */
_userexcep:
	MOVM.DB.W [R0-R2], (R13)	/* set ureg->{type, psr, pc}; r13 points to ureg->type  */
	MOVM.IA	  (R3), [R0-R4]		/* restore [R0-R4] from previous mode's stack */
	MOVM.DB.W.S [R0-R14], (R13)	/* save kernel level registers, at end r13 points to ureg */
	MOVW	$setR12(SB), R12	/* Make sure we've got the kernel's SB loaded */
	MOVW	R13, R0			/* first arg is pointer to ureg */
	SUB	$8, R13			/* space for argument+link (for debugger) */

	BL	trap(SB)

	ADD	$(8+4*15), R13		/* make r13 point to ureg->type */
	MOVW	8(R13), R14		/* restore link */
	MOVW	4(R13), R0		/* restore SPSR */
	MOVW	R0, SPSR		/* ... */
	MOVM.DB.S (R13), [R0-R14]	/* restore registers */
	ADD	$8, R13			/* pop past ureg->{type+psr} */
	RFE				/* MOVM.IA.S.W (R13), [R15] */

TEXT _vfiq(SB), $-4			/* FIQ */
	RFE				/* FIQ is special, ignore it for now */

/*
 *  This is the first jump from kernel to user mode.
 *  Fake a return from interrupt.
 *
 *  Enter with R0 containing the user stack pointer.
 *  UTZERO + 0x20 is always the entry point.
 *
 */
TEXT touser(SB),$-4
	/* store the user stack pointer into the USR_r13 */
	MOVM.DB.W [R0], (R13)
	MOVM.S.IA.W (R13),[R13]

	/* set up a PSR for user level */
	MOVW	$(PsrMusr), R0
	MOVW	R0,SPSR

	/* save the PC on the stack */
	MOVW	$(UTZERO+0x20), R0
	MOVM.DB.W [R0],(R13)

	/* return from interrupt */
	RFE				/* MOVM.IA.S.W (R13), [R15] */

/*
 *  here to jump to a newly forked process
 */
TEXT forkret(SB),$-4
	ADD	$(4*15), R13		/* make r13 point to ureg->type */
	MOVW	8(R13), R14		/* restore link */
	MOVW	4(R13), R0		/* restore SPSR */
	MOVW	R0, SPSR		/* ... */
	MOVM.DB.S (R13), [R0-R14]	/* restore registers */
	ADD	$8, R13			/* pop past ureg->{type+psr} */
	RFE				/* MOVM.IA.S.W (R13), [R15] */

TEXT splhi(SB), $-4
	/* save caller pc in Mach */
	MOVW	$(MACHADDR+0x04),R2
	MOVW	R14,0(R2)
	/* turn off interrupts */
	MOVW	CPSR, R0
	ORR	$(PsrDirq), R0, R1
	MOVW	R1, CPSR
	RET

TEXT spllo(SB), $-4
	MOVW	CPSR, R0
	BIC	$(PsrDirq), R0, R1
	MOVW	R1, CPSR
	RET

TEXT splx(SB), $-4
	/* save caller pc in Mach */
	MOVW	$(MACHADDR+0x04),R2
	MOVW	R14,0(R2)
	/* reset interrupt level */
	MOVW	R0, R1
	MOVW	CPSR, R0
	MOVW	R1, CPSR
	RET

TEXT splxpc(SB), $-4				/* for iunlock */
	MOVW	R0, R1
	MOVW	CPSR, R0
	MOVW	R1, CPSR
	RET

TEXT spldone(SB), $0
	RET

TEXT islo(SB), $-4
	MOVW	CPSR, R0
	AND	$(PsrDirq), R0
	EOR	$(PsrDirq), R0
	RET

TEXT cpsrr(SB), $-4
	MOVW	CPSR, R0
	RET

TEXT spsrr(SB), $-4
	MOVW	SPSR, R0
	RET

TEXT getsp(SB), $-4
	MOVW	R13, R0
	RET

TEXT getlink(SB), $-4
	MOVW	R14, R0
	RET

TEXT getcallerpc(SB), $-4
	MOVW	0(R13), R0
	RET

TEXT tas(SB), $-4
	MOVW	R0, R1
	MOVW	$0xDEADDEAD, R0
	MOVW	R0, R3
	SWPW	R0, (R1)
	CMP.S	R0, R3
	BEQ	_tasout
	EOR	R3, R3
	CMP.S	R0, R3
	BEQ	_tasout
	MOVW	$1,R15
_tasout:
	RET

TEXT setlabel(SB), $-4
	MOVW	R13, 0(R0)			/* sp */
	MOVW	R14, 4(R0)			/* pc */
	MOVW	$0, R0
	RET

TEXT gotolabel(SB), $-4
	MOVW	0(R0), R13			/* sp */
	MOVW	4(R0), R14			/* pc */
	MOVW	$1, R0
	RET

/* save the state machine in power_state[] for an upcoming suspend
 */
TEXT setpowerlabel(SB), $-4
	MOVW	$power_state+0(SB), R0
	/* svc */				/* power_state[]: what */
	MOVW	R1, 0(R0)
	MOVW	R2, 4(R0)
	MOVW	R3, 8(R0)
	MOVW	R4, 12(R0)
	MOVW	R5, 16(R0)
	MOVW	R6, 20(R0)
	MOVW	R7, 24(R0)
	MOVW	R8, 28(R0)
	MOVW	R9, 32(R0)
	MOVW	R10,36(R0)
	MOVW	R11,40(R0)
	MOVW	R12,44(R0)
	MOVW	R13,48(R0)
	MOVW	R14,52(R0)
	MOVW	SPSR, R1
	MOVW	R1, 56(R0)
	MOVW	CPSR, R2
	MOVW	R2, 60(R0)
	/* copro */
	MRC		CpMMU, 0, R3, C(CpDAC), C(0x0)
	MOVW	R3, 144(R0)
	MRC		CpMMU, 0, R3, C(CpTTB), C(0x0)
	MOVW	R3, 148(R0)
	MRC		CpMMU, 0, R3, C(CpControl), C(0x0)
	MOVW	R3, 152(R0)
	MRC		CpMMU, 0, R3, C(CpFSR), C(0x0)
	MOVW	R3, 156(R0)
	MRC		CpMMU, 0, R3, C(CpFAR), C(0x0)
	MOVW	R3, 160(R0)
	MRC		CpMMU, 0, R3, C(CpPID), C(0x0)
	MOVW	R3, 164(R0)
	/* usr */
	BIC		$(PsrMask), R2, R3
	ORR		$(0xdf), R3
	MOVW		R3, CPSR
	MOVW		SPSR, R11
	MOVW		R11, 168(R0)
	MOVW		R12, 172(R0)
	MOVW		R13, 176(R0)
	MOVW		R14, 180(R0)
	/* irq */
	BIC		$(PsrMask), R2, R3
	ORR		$(0xd2), R3
	MOVW	R3, CPSR
	MOVW	SPSR, R11
	MOVW	R11, 64(R0)
	MOVW	R12, 68(R0)
	MOVW	R13, 72(R0)
	MOVW	R14, 76(R0)
	/* und */
	BIC		$(PsrMask), R2, R3
	ORR		$(0xdb), R3
	MOVW	R3, CPSR
	MOVW	SPSR, R11
	MOVW	R11, 80(R0)
	MOVW	R12, 84(R0)
	MOVW	R13, 88(R0)
	MOVW	R14, 92(R0)
	/* abt */
	BIC		$(PsrMask), R2, R3
	ORR		$(0xd7), R3
	MOVW	R3, CPSR
	MOVW	SPSR, R11
	MOVW	R11, 96(R0)
	MOVW	R12, 100(R0)
	MOVW	R13, 104(R0)
	MOVW	R14, 108(R0)
	/* fiq */
	BIC		$(PsrMask), R2, R3
	ORR		$(0xd1), R3
	MOVW	R3, CPSR
	MOVW	SPSR, R7
	MOVW	R7, 112(R0)
	MOVW	R8, 116(R0)
	MOVW	R9, 120(R0)
	MOVW	R10,124(R0)
	MOVW	R11,128(R0)
	MOVW	R12,132(R0)
	MOVW	R13,136(R0)
	MOVW	R14,140(R0)
	/* done */
	MOVW	R2, CPSR
	MOVW	R1, SPSR
	MOVW	$0, R0
	RET

/* Entered after a resume from suspend state.
 * The bootldr jumps here after a processor reset.
 */
TEXT power_resume(SB), $-4
	MOVW	$setR12(SB), R12		/* load the SB */
	/* SVC mode, interrupts disabled */
	MOVW	$(PsrDirq|PsrDfiq|PsrMsvc), R1
	MOVW	R1, CPSR
	/* gotopowerlabel() */
	/* svc */

	MOVW	$power_state+0(SB), R0
	MOVW	56(R0), R1		/* R1: SPSR, R2: CPSR */
	MOVW	60(R0), R2
	MOVW	R1, SPSR
	MOVW	R2, CPSR
	/* copro */
	/* flush caches */
	MCR		CpMMU, 0, R0, C(CpCacheFlush), C(0x7), 0
	/* drain prefetch */
	MOVW	R0,R0
	MOVW	R0,R0
	MOVW	R0,R0
	MOVW	R0,R0
	/* drain write buffer */
	MCR		CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 4
	MCR		CpMMU, 0, R0, C(CpTLBFlush), C(0x7)
	MOVW	144(R0), R3
	MCR		CpMMU, 0, R3, C(CpDAC), C(0x0)
	MOVW	148(R0), R3
	MCR		CpMMU, 0, R3, C(CpTTB), C(0x0)
	MOVW	156(R0), R3
	MCR		CpMMU, 0, R3, C(CpFSR), C(0x0)
	MOVW	160(R0), R3
	MCR		CpMMU, 0, R3, C(CpFAR), C(0x0)
	MOVW	164(R0), R3
	MCR		CpMMU, 0, R3, C(CpPID), C(0x0)
	MOVW	152(R0), R3
	MCR		CpMMU, 0, R3, C(CpControl), C(0x0)	/* Enable cache */
	MOVW	R0,R0
	MOVW	R0,R0
	MOVW	R0,R0
	MOVW	R0,R0
	/* flush i&d caches */
	MCR		CpMMU, 0, R0, C(CpCacheFlush), C(0x7), 0
	/* flush tlb */
	MCR		CpMMU, 0, R0, C(CpTLBFlush), C(0x7), 0
	/* drain prefetch */
	MOVW	R0,R0
	MOVW	R0,R0
	MOVW	R0,R0
	MOVW	R0,R0
	/* usr */
	BIC		$(PsrMask), R2, R3
	ORR		$(0xdf), R3
	MOVW		168(R0), R11
	MOVW		172(R0), R12
	MOVW		176(R0), R13
	MOVW		180(R0), R14
	MOVW		R11, SPSR
	/* irq */
	BIC		$(PsrMask), R2, R3
	ORR		$(0xd2), R3
	MOVW	R3, CPSR
	MOVW	64(R0), R11
	MOVW	68(R0), R12
	MOVW	72(R0), R13
	MOVW	76(R0), R14
	MOVW	R11, SPSR
	/* und */
	BIC		$(PsrMask), R2, R3
	ORR		$(0xdb), R3
	MOVW	R3, CPSR
	MOVW	80(R0), R11
	MOVW	84(R0), R12
	MOVW	88(R0), R13
	MOVW	92(R0), R14
	MOVW	R11, SPSR
	/* abt */
	BIC		$(PsrMask), R2, R3
	ORR		$(0xd7), R3
	MOVW	R3, CPSR
	MOVW	96(R0), R11
	MOVW	100(R0), R12
	MOVW	104(R0), R13
	MOVW	108(R0), R14
	MOVW	R11, SPSR
	/* fiq */
	BIC		$(PsrMask), R2, R3
	ORR		$(0xd1), R3
	MOVW	R3, CPSR
	MOVW	112(R0), R7
	MOVW	116(R0), R8
	MOVW	120(R0), R9
	MOVW	124(R0), R10
	MOVW	128(R0), R11
	MOVW	132(R0), R12
	MOVW	136(R0), R13
	MOVW	140(R0), R14
	MOVW	R7, SPSR
	/* svc */
	MOVW	56(R0), R1
	MOVW	60(R0), R2
	MOVW	R1, SPSR
	MOVW	R2, CPSR
	MOVW	0(R0), R1
	MOVW	4(R0), R2
	MOVW	8(R0), R3
	MOVW	12(R0),R4
	MOVW	16(R0),R5
	MOVW	20(R0),R6
	MOVW	24(R0),R7
	MOVW	28(R0),R8
	MOVW	32(R0),R9
	MOVW	36(R0),R10
	MOVW	40(R0),R11
	MOVW	44(R0),R12
	MOVW	48(R0),R13
	MOVW	52(R0),R14
	RET
loop:
	B		loop

TEXT power_down(SB), $-4

	TEXT	sa1100_power_off<>+0(SB),$8
	MOVW	resetregs+0(SB),R7
	MOVW	gpioregs+0(SB),R6
	MOVW	memconfregs+0(SB),R5
	MOVW	powerregs+0(SB),R3


	/* wakeup on power | rtc */
	MOVW	$(PWR_rtc|PWR_gpio0),R2
	MOVW	R2,0xc(R3)

	/* clear reset status */
	MOVW	$(RCSR_all), R2
	MOVW	R2, 0x4(R7)
	/* float */
	MOVW	$(PCFR_opde|PCFR_fp|PCFR_fs), R2
	MOVW	R2,0x10(R3)
	/* sleep state */
	MOVW	$0,R2
	MOVW	R2,0x18(R3)
	/* set resume address (pspr)*/
	MOVW	$resumeaddr+0(SB),R1
	MOVW	0x0(R1), R2
	MOVW	R2,0x8(R3)

	BL	cacheflush(SB)

	/* disable clock switching */
	MCR   	CpPWR, 0, R1, C(CpTest), C(0x2), 2

	/* adjust mem timing */
	MOVW	memconfregs+0(SB),R5
	MOVW	0x1c(R5), R2
	ORR	$(MDREFR_k1db2), R2
	MOVW	R2, 0x1c(R5)

	/* set PLL to lower speed w/ delay (ppcr = 0)*/
	MOVW	powerregs+0(SB),R3
	MOVW	$(120*206),R0
l11:	SUB	$1,R0
	BGT	l11
	MOVW	$0, R2
	MOVW	R2, 0x14(R3)
	MOVW	$(120*206),R0
l12:	SUB	$1,R0
	BGT	l12

	/* setup registers for suspend procedure:
	 * 1. clear RT in mscx (R1, R7, R8)
	 * 2. clear DRI in mdrefr (R4)
	 * 3. set slfrsh in mdrefr (R6)
	 * 4. clear DE in mdcnfg (R9)
	 * 5. clear dram refresh (R10)
	 * 6. force sleep (R2)
	 */
	/* 1 */
	MOVW	0x10(R5), R2
	BIC	$(MSC_rt), R2
	MOVW	R2, R1
	MOVW	0x14(R5), R2
	BIC	$(MSC_rt), R2
	MOVW	R2, R7
	MOVW	0x2c(R5), R2
	BIC	$(MSC_rt), R2
	MOVW	R2, R8
	/* 2 */
	MOVW	0x1c(R5), R2
	BIC	$(0xff00), R2
	BIC	$(0x00f0), R2
	MOVW	R2, R4
	/* 3 */
	ORR	$(MDREFR_slfrsh), R2, R6
	/* 4 */
	MOVW	0x0(R5), R9
	BIC	$(MDCFNG_de), R9, R9
	/* 5 */
	MOVW	R4, R2
	BIC	$(MDREFR_slfrsh), R2, R2
	BIC	$(MDREFR_e1pin), R2, R2
	MOVW	R2, R10
	/* 6 */
	MOVW	$1,R2

	/* Follow the procedure */
	/* 1 */
	MOVW	R1, 0x10(R5)
	MOVW	R7, 0x14(R5)
	MOVW	R8, 0x2c(R5)
	/* 2 */
	MOVW	R4, 0x1c(R5)
	/* 3 */
	MOVW	R6, 0x1c(R5)
	/* 4 */
	MOVW	R9, 0x0(R5)
	/* 5 */
	MOVW	R10, 0x1c(R5)
	/* 6 */
	MOVW	R2, 0x0(R3)
slloop:
	B		slloop			/* loop waiting for sleep */

/* The first MCR instruction of this function needs to be on a cache-line
 * boundary; to make this happen, it will be copied (in trap.c).
 *
 * Doze puts the machine into idle mode.  Any interrupt will get it out
 * at the next instruction (the RET, to be precise).
 */
TEXT _doze(SB), $-4
	MOVW	$UCDRAMZERO, R1
	MOVW	R0,R0
	MOVW	R0,R0
	MOVW	R0,R0
	MOVW	R0,R0
	MOVW	R0,R0
	MOVW	R0,R0
	MOVW	R0,R0
	MCR   	CpPWR, 0, R0, C(CpTest), C(0x2), 2
	MOVW	(R1), R0
	MCR  	CpPWR, 0, R0, C(CpTest), C(0x8), 2
	RET

[-- Attachment #3: power.c --]
[-- Type: text/plain, Size: 6831 bytes --]

#include	"u.h"
#include	"../port/lib.h"
#include	"mem.h"
#include	"dat.h"
#include	"fns.h"
#include	"io.h"
#include	"ureg.h"
#include	"pool.h"

/* Power management for the bitsy */

/* saved state during power down.
 * it's only used up to 164/4.
 * it's only used by routines in l.s
 */
ulong	power_state[200/4];
ulong	resumeaddr[1];
Rendez	powerr;
ulong	powerflag = 0;	/* set to start power-off sequence */

extern void	power_resume(void);
extern int		setpowerlabel(void);
extern void	_start(void);
extern Uart	sa1110uart[];

GPIOregs savedgpioregs;
Intrregs savedintrregs;

#define R(p) ((Uartregs*)((p)->regs))

uchar *savedtext;


static void
checkflash(void)
{
	ulong *p;
	ulong s;

	s = 0;
	for (p = (ulong*)FLASHZERO; p < (ulong*)(FLASHZERO+8*1024*1024); p++)
		s += *p;
	iprint("flash checksum is 0x%lux\n", s);
}

static void
checkktext(void)
{
	ulong *p;
	ulong s;

	s = 0;
	for (p = (ulong*)_start; p < (ulong*)etext; p++){
		if(*p == 0)
			iprint("0x%lux->0\n", p);
		if (((ulong)p & 0x1fff) == 0){
			iprint("page 0x%lux checksum 0x%lux\n",
				(ulong)(p-1)&~0x1fff, s);
			s = 0;
		}
		s += *p;
	}
	iprint("page 0x%lux checksum 0x%lux\n", (ulong)(p-1)&~0x1fff, s);
}

static void
checkpagetab(void)
{
	extern ulong l1table;
	ulong *p;
	ulong s;

	s = 0;
	for (p = (ulong*)l1table; p < (ulong*)(l1table+16*1024); p++)
		s += *p;
	iprint("page table checksum is 0x%lux\n", s);
}


static void
dumpitall(void)
{
	extern ulong l1table;

	iprint("intr: icip %lux iclr %lux iccr %lux icmr %lux\n",
		intrregs->icip,
		intrregs->iclr, intrregs->iccr, intrregs->icmr );
	iprint("gpio: lvl %lux dir %lux, re %lux, fe %lux sts %lux alt %lux\n",
		gpioregs->level,
		gpioregs->direction, gpioregs->rising, gpioregs->falling,
		gpioregs->edgestatus, gpioregs->altfunc);
	iprint("uart1: %lux %lux %lux \nuart3: %lux %lux %lux\n",
		R(&sa1110uart[0])->ctl[0], R(&sa1110uart[0])->status[0], R(&sa1110uart[0])->status[1],
		R(&sa1110uart[1])->ctl[0], R(&sa1110uart[1])->status[0], R(&sa1110uart[1])->status[1]);
	iprint("tmr: osmr %lux %lux %lux %lux oscr %lux ossr %lux oier %lux\n",
		timerregs->osmr[0], timerregs->osmr[1],
		timerregs->osmr[2], timerregs->osmr[3],
		timerregs->oscr, timerregs->ossr, timerregs->oier);
	iprint("dram: mdcnfg %lux mdrefr %lux cas %lux %lux %lux %lux %lux %lux\n",
		memconfregs->mdcnfg, memconfregs->mdrefr,
		memconfregs->mdcas00, memconfregs->mdcas01,memconfregs->mdcas02,
		memconfregs->mdcas20, memconfregs->mdcas21,memconfregs->mdcas22);
	iprint("dram: mdcnfg msc %lux %lux %lux mecr %lux\n",
		memconfregs->msc0, memconfregs->msc1,memconfregs->msc2,
		memconfregs->mecr);
	iprint("mmu: CpControl %lux CpTTB %lux CpDAC %lux l1table 0x%lux\n",
		getcontrol(), getttb(), getdac(), l1table);
	iprint("powerregs: pmcr %lux pssr %lux pcfr %lux ppcr %lux pwer %lux pspr %lux pgsr %lux posr %lux\n",
		powerregs->pmcr, powerregs->pssr, powerregs->pcfr, powerregs->ppcr,
		powerregs->pwer, powerregs->pspr, powerregs->pgsr, powerregs->posr);
	checkpagetab();
	checkflash();
	checkktext();
	iprint("\n\n");
}

static void
intrcpy(Intrregs *to, Intrregs *from)
{
	to->iclr = from->iclr;
	to->iccr = from->iccr;
	to->icmr = from->icmr;	// interrupts enabled
}

static void
gpiosave(GPIOregs *to, GPIOregs *from)
{
	to->level = from->level;
	to->rising = from->rising;		// gpio intrs enabled
	to->falling= from->falling;		// gpio intrs enabled
	to->altfunc = from->altfunc;
	to->direction = from->direction;
}

static void
gpiorestore(GPIOregs *to, GPIOregs *from)
{
	to->direction = from->direction;
	to->altfunc = from->altfunc;
	to->set = from->level & 0x0fffffff;
	to->clear = ~from->level & 0x0fffffff;
	to->rising = from->rising;		// gpio intrs enabled
	to->falling= from->falling;		// gpio intrs enabled
}

void	(*restart)(void) = nil;

static int
bitno(ulong x)
{
	int i;

	for(i = 0; i < 8*sizeof(x); i++)
		if((1<<i) & x)
			break;
	return i;
}

int
powerdown(void *)
{
	return powerflag;
}

void
deepsleep(void) {
	static int power_pl;
	ulong xsp, xlink, mecr;
	extern void power_resume(void);

	power_pl = splhi();
	xlink = getcallerpc(&xlink);

//	*resumeaddr = (ulong) power_resume;
//	*resumeaddr = nil;
	/* Power down */
	irpower(0);
	audiopower(0);
	screenpower(0);
	µcpower(0);
	iprint("entering suspend mode, sp = 0x%lux, pc = 0x%lux, psw = 0x%ux\n", &xsp, xlink, power_pl);
//	dumpitall();
	delay(1000);
	uartpower(0);
	rs232power(0);
	clockpower(0);
	gpiosave(&savedgpioregs, gpioregs);
	intrcpy(&savedintrregs, intrregs);
	cacheflush();
	delay(50);
	mecr = memconfregs->mecr;
	if(setpowerlabel()){
		/* return here with mmu back on */
		trapresume();

		/* Turn off memory auto power */
//		memconfregs->mdrefr &= ~0x30000000;
//		memconfregs->mecr = mecr;

		gpiorestore(gpioregs, &savedgpioregs);
		delay(50);
		intrcpy(intrregs, &savedintrregs);
		if(intrregs->icip & (1<<IRQgpio0)){
			// don't want to sleep now. clear on/off irq.
			gpioregs->edgestatus = (1<<IRQgpio0);
			intrregs->icip = (1<<IRQgpio0);
		}
		clockpower(1);
		gpclkregs->r0 = 1<<0;
		rs232power(1);
		uartpower(1);
		delay(100);
		xlink = getcallerpc(&xlink);
		iprint("\nresuming execution, sp = 0x%lux, pc = 0x%lux, psw = 0x%ux\n", &xsp, xlink, splhi());
//		dumpitall();
		delay(1000);
//		irpower(1);
//		audiopower(1);
		µcpower(1);
		screenpower(1);
		splx(power_pl);
		return;
	}
	cacheflush();
	delay(100);
	power_down();
	/* no return */
}

void
powerkproc(void*)
{
	ulong xlink, xlink1;

	for(;;){
		while(powerflag == 0)
			sleep(&powerr, powerdown, 0);

		xlink = getcallerpc(&xlink);

//		iprint("call deepsleep, pc = 0x%lux, sp = 0x%lux\n", xlink, &xlink);
		deepsleep();
		xlink1 = getcallerpc(&xlink1);


		delay(2000);

//		iprint("deepsleep returned, pc = 0x%lux, sp = 0x%lux\n", xlink1, &xlink);
		powerflag = 0;
	}
}

void
onoffintr(Ureg* , void*)
{
	int i;

	/* Power down interrupt comes on power button release.
	 * Act only after button has been released a full 100 ms
	 */

	if (powerflag)
		return;

	for (i = 0; i < 100; i++) {
		delay(1);
		if ((gpioregs->level & GPIO_PWR_ON_i) == 0)
			return;	/* bounced */
	}

	powerflag = 1;
	wakeup(&powerr);
}

static void
blanktimer(void)
{
	drawactive(0);
}

void
powerinit(void)
{
	addclock0link(blanktimer);
	intrenable(GPIOrising, bitno(GPIO_PWR_ON_i), onoffintr, nil, "on/off");
}

void
idlehands(void)
{
	char *msgb = "idlehands called with splhi\n";
	char *msga = "doze returns with splhi\n";

	if(!islo()){
		uartputs(msga, strlen(msga));
		spllo();
	}
	doze();
	if(!islo()){
		uartputs(msgb, strlen(msgb));
		spllo();
	}
}

[-- Attachment #4: mem.h --]
[-- Type: text/plain, Size: 8281 bytes --]

/*
 * Memory and machine-specific definitions.  Used in C and assembler.
 */

/*
 * Sizes
 */
#define	BI2BY		8			/* bits per byte */
#define	BI2WD		32			/* bits per word */
#define	BY2WD		4			/* bytes per word */
#define	BY2V		8			/* bytes per double word */
#define	BY2PG		4096			/* bytes per page */
#define	WD2PG		(BY2PG/BY2WD)		/* words per page */
#define	PGSHIFT		12			/* log(BY2PG) */
#define	ROUND(s, sz)	(((s)+(sz-1))&~(sz-1))
#define	PGROUND(s)	ROUND(s, BY2PG)
#define	BLOCKALIGN	8

#define	MAXMACH	1			/* max # cpus system can run */

/*
 * Time
 */
#define	HZ		(20)				/* clock frequency */
#define	MS2HZ	(1000/HZ)		/* millisec per clock tick */
#define	TK2SEC(t)	((t)/HZ)			/* ticks to seconds */

/*
 *  Virtual addresses:
 *
 *  We direct map all discovered DRAM and the area twixt 0xe0000000 and
 *  0xe8000000 used to provide zeros for cache flushing.
 *
 *  Flash is mapped to 0xb0000000 and special registers are mapped
 *  on demand to areas starting at 0xa0000000.
 *
 *  The direct mapping is convenient but not necessary.  It means
 *  that we don't have to turn on the MMU till well into the
 *  kernel.  This can be changed by providing a mapping in l.s
 *  before calling main.
 */
#define	UZERO		0				/* base of user address space */
#define	UTZERO		(UZERO+BY2PG)	/* first address in user text */
#define	KZERO		0xC0000000		/* base of kernel address space */
#define	KTZERO		0xC0008000		/* first address in kernel text */
#define	EMEMZERO	0x90000000		/* 256 meg for add on memory */
#define	EMEMTOP		0xA0000000		/* ... */
#define	REGZERO		0xA0000000		/* 128 meg for mapspecial regs */
#define	REGTOP		0xA8000000		/* ... */
#define	FLASHZERO	0xB0000000		/* 128 meg for flash */
#define	FLASHTOP	0xB8000000		/* ... */
#define	DRAMZERO	0xC0000000		/* 128 meg for dram */
#define	DRAMTOP		0xC8000000		/* ... */
#define	UCDRAMZERO	0xC8000000		/* 128 meg for dram (uncached/unbuffered) */
#define	UCDRAMTOP	0xD0000000		/* ... */
#define	NULLZERO	0xE0000000		/* 128 meg for cache flush zeroes */
#define	NULLTOP		0xE8000000		/* ... */
#define	USTKTOP		0x2000000		/* byte just beyond user stack */
#define	USTKSIZE		(8*1024*1024)		/* size of user stack */
#define	TSTKTOP		(USTKTOP-USTKSIZE)	/* end of new stack in sysexec */
#define	TSTKSIZ	 	100
#define	MACHADDR	(KZERO+0x00001000)
#define	EVECTORS	0xFFFF0000		/* virt base of exception vectors */

#define	KSTACK		(16*1024)			/* Size of kernel stack */

/*
 *  Offsets into flash
 */
#define Flash_bootldr	(FLASHZERO+0x0)		/* boot loader */
#define Flash_kernel	(FLASHZERO+0x10000)	/* boot kernel */
#define Flash_tar		(FLASHZERO+0x200000)	/* fs.sac (tar file) */

/*
 *  virtual MMU
 */
#define PTEMAPMEM	(1024*1024)
#define	PTEPERTAB	(PTEMAPMEM/BY2PG)
#define SEGMAPSIZE	1984
#define SSEGMAPSIZE	16
#define PPN(x)		((x)&~(BY2PG-1))

/*
 *  SA1110 definitions
 */

/*
 *  memory physical addresses
 */
#define PHYSFLASH0	0x00000000
#define PHYSDRAM0	0xC0000000
#define	PHYSNULL0	0xE0000000

/*
 *  peripheral control module physical addresses
 */
#define USBREGS		0x80000000	/* serial port 0 - USB */
#define UART1REGS		0x80010000	/* serial port 1 - UART */
#define GPCLKREGS		0x80020060	/* serial port 1 - general purpose clock */
#define UART2REGS		0x80030000	/* serial port 2 - low speed IR */
#define HSSPREGS		0x80040060	/* serial port 2 - high speed IR */
#define UART3REGS		0x80050000	/* serial port 3 - RS232 UART */
#define MCPREGS		0x80060000	/* serial port 4 - multimedia comm port */
#define SSPREGS		0x80070060	/* serial port 4 - synchronous serial port */
#define OSTIMERREGS	0x90000000	/* operating system timer registers */
#define POWERREGS		0x90020000	/* power management */
#define RESETREGS		0x90030000	/* reset controller */
#define GPIOREGS		0x90040000	/* 28 general purpose IO pins */
#define INTRREGS		0x90050000	/* interrupt registers */
#define PPCREGS		0x90060000	/* peripheral pin controller */
#define MEMCONFREGS	0xA0000000	/* memory configuration */
#define LCDREGS		0xB0100000	/* display */

/*
 *  PCMCIA addresses
 */
#define PHYSPCM0REGS	0x20000000
#define PYHSPCM0ATTR	0x28000000
#define PYHSPCM0MEM	0x2C000000
#define PHYSPCM1REGS	0x30000000
#define PYHSPCM1ATTR	0x38000000
#define PYHSPCM1MEM	0x3C000000

/*
 *  Program Status Registers
 */
#define PsrMusr		0x00000010	/* mode */
#define PsrMfiq		0x00000011
#define PsrMirq		0x00000012
#define PsrMsvc		0x00000013
#define PsrMabt		0x00000017
#define PsrMund		0x0000001B
#define PsrMask		0x0000001F

#define PsrDfiq		0x00000040	/* disable FIQ interrupts */
#define PsrDirq		0x00000080	/* disable IRQ interrupts */

#define PsrV		0x10000000	/* overflow */
#define PsrC		0x20000000	/* carry/borrow/extend */
#define PsrZ		0x40000000	/* zero */
#define PsrN		0x80000000	/* negative/less than */

/*
 *  Coprocessors
 */
#define CpMMU		15
#define CpPWR		15

/*
 *  Internal MMU coprocessor registers
 */
#define CpCPUID		0		/* R: */
#define CpControl	1		/* R: */
#define CpTTB		2		/* RW: translation table base */
#define CpDAC		3		/* RW: domain access control */
#define CpFSR		5		/* RW: fault status */
#define CpFAR		6		/* RW: fault address */
#define CpCacheFlush	7		/* W: cache flushing, wb draining*/
#define CpTLBFlush	8		/* W: TLB flushing */
#define CpRBFlush	9		/* W: Read Buffer ops */
#define CpPID		13		/* RW: PID for virtual mapping */
#define CpBpt		14		/* W: Breakpoint register */
#define CpTest		15		/* W: Test, Clock and Idle Control */

/*
 *  CpControl
 */
#define CpCmmuena	0x00000001	/* M: MMU enable */
#define CpCalign	0x00000002	/* A: alignment fault enable */
#define CpCdcache	0x00000004	/* C: data cache on */
#define CpCwb		0x00000008	/* W: write buffer turned on */
#define CpCi32		0x00000010	/* P: 32-bit program space */
#define CpCd32		0x00000020	/* D: 32-bit data space */
#define CpCbe		0x00000080	/* B: big-endian operation */
#define CpCsystem	0x00000100	/* S: system permission */
#define CpCrom		0x00000200	/* R: ROM permission */
#define CpCicache	0x00001000	/* I: instruction cache on */
#define CpCvivec	0x00002000	/* X: virtual interrupt vector adjust */

/*
 *  fault codes
 */
#define	FCterm		0x2	/* terminal */
#define	FCvec		0x0	/* vector */
#define	FCalignf	0x1	/* unaligned full word data access */
#define	FCalignh	0x3	/* unaligned half word data access */
#define	FCl1abort	0xc	/* level 1 external abort on translation */
#define	FCl2abort	0xe	/* level 2 external abort on translation */
#define	FCtransSec	0x5	/* section translation */
#define	FCtransPage	0x7	/* page translation */
#define	FCdomainSec	0x9	/* section domain  */
#define	FCdomainPage	0x11	/* page domain */
#define	FCpermSec	0x9	/* section permissions  */
#define	FCpermPage	0x11	/* page permissions */
#define	FCabortLFSec	0x4	/* external abort on linefetch for section */
#define	FCabortLFPage	0x6	/* external abort on linefetch for page */
#define	FCabortNLFSec	0x8	/* external abort on non-linefetch for section */
#define	FCabortNLFPage	0xa	/* external abort on non-linefetch for page */

/*
 *  PTE bits used by fault.h.  mmu.c translates them to real values.
 */
#define	PTEVALID	(1<<0)
#define	PTERONLY	0	/* this is implied by the absence of PTEWRITE */
#define	PTEWRITE	(1<<1)
#define	PTEUNCACHED	(1<<2)
#define PTEKERNEL	(1<<3)	/* no user access */

/*
 *  H3650 specific definitions
 */
#define EGPIOREGS	0x49000000	/* Additional GPIO register */

/* Power management */

#define PWR_rtc		0x80000000	/* resume on RTC */
#define	PWR_gpio0	0x00000001	/* resume on power button */

#define RCSR_all	0x0000000f
#define PCFR_opde	0x00000001	/* oscillator power-down enable */
#define PCFR_suspend	0x00000001
#define PCFR_fp		0x00000002	/* float pcmcia */
#define PCFR_fs		0x00000004	/* float static memory */
#define PCFR_fo		0x00000008

#define MDREFR_k1db2	(1 << 22)
#define MDREFR_slfrsh	0x80000000	/* self refresh */
#define MDREFR_e1pin	(1 << 20)
#define MSC_rt		0x00030003

#define MDCNFG_de0	0x00000001	/* dram enable */
#define MDCNFG_de1	0x00000002
#define MDCNFG_de2	0x00000004
#define MDCNFG_de3	0x00000008
#define MDCFNG_de	0x0000000f
#define PMCR_sf		1

[-- Attachment #5: io.h --]
[-- Type: text/plain, Size: 8087 bytes --]

/*
 *  Definitions for IO devices.  Used only in C.
 */

enum
{
	/* hardware counter frequency */
	ClockFreq=	3686400,
};

/*
 *  IRQ's defined by SA1100
 */
enum
{
	IRQgpio0=	0,
	IRQgpio1=	1,
	IRQgpio2=	2,
	IRQgpio3=	3,
	IRQgpio4=	4,
	IRQgpio5=	5,
	IRQgpio6=	6,
	IRQgpio7=	7,
	IRQgpio8=	8,
	IRQgpio9=	9,
	IRQgpio10=	10,
	IRQgpiohi=	11,
	IRQlcd=		12,
	IRQudc=		13,
	IRQuart1b=	15,
	IRQuart2=	16,
	IRQuart3=	17,
	IRQmcp=		18,
	IRQssp=		19,
	IRQdma0=	20,
	IRQdma1=	21,
	IRQdma2=	22,
	IRQdma3=	23,
	IRQdma4=	24,
	IRQdma5=	25,
	IRQtimer0=	26,
	IRQtimer1=	27,
	IRQtimer2=	28,
	IRQtimer3=	29,
	IRQsecond=	30,
	IRQrtc=		31,
};

/*
 *  GPIO lines (signal names from compaq document).  _i indicates input
 *  and _o output.
 */
enum
{
	GPIO_PWR_ON_i=		1<<0,	/* power button */
	GPIO_UP_IRQ_i=		1<<1,	/* microcontroller interrupts */
	GPIO_LDD8_o=		1<<2,	/* LCD data 8-15 */
	GPIO_LDD9_o=		1<<3,
	GPIO_LDD10_o=		1<<4,
	GPIO_LDD11_o=		1<<5,
	GPIO_LDD12_o=		1<<6,
	GPIO_LDD13_o=		1<<7,
	GPIO_LDD14_o=		1<<8,
	GPIO_LDD15_o=		1<<9,
	GPIO_CARD_IND1_i=	1<<10,	/* card inserted in PCMCIA socket 1 */
	GPIO_CARD_IRQ1_i=	1<<11,	/* PCMCIA socket 1 interrupt */
	GPIO_CLK_SET0_o=	1<<12,	/* clock selects for audio codec */
	GPIO_CLK_SET1_o=	1<<13,
	GPIO_L3_SDA_io=		1<<14,	/* UDA1341 interface */
	GPIO_L3_MODE_o=		1<<15,
	GPIO_L3_SCLK_o=		1<<16,
	GPIO_CARD_IND0_i=	1<<17,	/* card inserted in PCMCIA socket 0 */
	GPIO_KEY_ACT_i=		1<<18,	/* hot key from cradle */
	GPIO_SYS_CLK_i=		1<<19,	/* clock from codec */
	GPIO_BAT_FAULT_i=	1<<20,	/* battery fault */
	GPIO_CARD_IRQ0_i=	1<<21,	/* PCMCIA socket 0 interrupt */
	GPIO_LOCK_i=		1<<22,	/* expansion pack lock/unlock */
	GPIO_COM_DCD_i=		1<<23,	/* DCD from UART3 */
	GPIO_OPT_IRQ_i=		1<<24,	/* expansion pack IRQ */
	GPIO_COM_CTS_i=		1<<25,	/* CTS from UART3 */
	GPIO_COM_RTS_o=		1<<26,	/* RTS to UART3 */
	GPIO_OPT_IND_i=		1<<27,	/* expansion pack inserted */

/* Peripheral Unit GPIO pin assignments: alternate functions */
	GPIO_SSP_TXD_o=		1<<10,	/* SSP Transmit Data */
	GPIO_SSP_RXD_i=		1<<11,	/* SSP Receive Data */
	GPIO_SSP_SCLK_o=	1<<12,	/* SSP Sample CLocK */
	GPIO_SSP_SFRM_o=	1<<13,	/* SSP Sample FRaMe */
	/* ser. port 1: */
	GPIO_UART_TXD_o=	1<<14,	/* UART Transmit Data */
	GPIO_UART_RXD_i=	1<<15,	/* UART Receive Data */
	GPIO_SDLC_SCLK_io=	1<<16,	/* SDLC Sample CLocK (I/O) */
	GPIO_SDLC_AAF_o=	1<<17,	/* SDLC Abort After Frame */
	GPIO_UART_SCLK1_i=	1<<18,	/* UART Sample CLocK 1 */
	/* ser. port 4: */
	GPIO_SSP_CLK_i=		1<<19,	/* SSP external CLocK */
	/* ser. port 3: */
	GPIO_UART_SCLK3_i=	1<<20,	/* UART Sample CLocK 3 */
	/* ser. port 4: */
	GPIO_MCP_CLK_i=		1<<21,	/* MCP CLocK */
	/* test controller: */
	GPIO_TIC_ACK_o=		1<<21,	/* TIC ACKnowledge */
	GPIO_MBGNT_o=		1<<21,	/* Memory Bus GraNT */
	GPIO_TREQA_i=		1<<22,	/* TIC REQuest A */
	GPIO_MBREQ_i=		1<<22,	/* Memory Bus REQuest */
	GPIO_TREQB_i=		1<<23,	/* TIC REQuest B */
	GPIO_1Hz_o=			1<<25,	/* 1 Hz clock */
	GPIO_RCLK_o=		1<<26,	/* internal (R) CLocK (O, fcpu/2) */
	GPIO_32_768kHz_o=	1<<27,	/* 32.768 kHz clock (O, RTC) */
};

/*
 *  types of interrupts
 */
enum
{
	GPIOrising,
	GPIOfalling,
	GPIOboth,
	IRQ,
};

/* hardware registers */
typedef struct Uartregs Uartregs;
struct Uartregs
{
	ulong	ctl[4];
	ulong	dummya;
	ulong	data;
	ulong	dummyb;
	ulong	status[2];
};
extern Uartregs *uart3regs;
extern Uartregs *uart1regs;

/* general purpose I/O lines control registers */
typedef struct GPIOregs GPIOregs;
struct GPIOregs
{
	ulong	level;		/* 1 == high */
	ulong	direction;	/* 1 == output */
	ulong	set;		/* a 1 sets the bit, 0 leaves it alone */
	ulong	clear;		/* a 1 clears the bit, 0 leaves it alone */
	ulong	rising;		/* rising edge detect enable */
	ulong	falling;	/* falling edge detect enable */
	ulong	edgestatus;	/* writing a 1 bit clears */
	ulong	altfunc;	/* turn on alternate function for any set bits */
};

extern GPIOregs *gpioregs;

/* extra general purpose I/O bits, output only */
enum
{
	EGPIO_prog_flash=	1<<0,
	EGPIO_pcmcia_reset=	1<<1,
	EGPIO_exppack_reset=	1<<2,
	EGPIO_codec_reset=	1<<3,
	EGPIO_exp_nvram_power=	1<<4,
	EGPIO_exp_full_power=	1<<5,
	EGPIO_lcd_3v=		1<<6,
	EGPIO_rs232_power=	1<<7,
	EGPIO_lcd_ic_power=	1<<8,
	EGPIO_ir_power=		1<<9,
	EGPIO_audio_power=	1<<10,
	EGPIO_audio_ic_power=	1<<11,
	EGPIO_audio_mute=	1<<12,
	EGPIO_fir=		1<<13,	/* not set is sir */
	EGPIO_lcd_5v=		1<<14,
	EGPIO_lcd_9v=		1<<15,
};
extern ulong *egpioreg;

/* Peripheral pin controller registers */
typedef struct PPCregs PPCregs;
struct PPCregs {
	ulong	direction;
	ulong	state;
	ulong	assignment;
	ulong	sleepdir;
	ulong	flags;
};
extern PPCregs *ppcregs;

/* Synchronous Serial Port controller registers */
typedef struct SSPregs SSPregs;
struct SSPregs {
	ulong	control0;
	ulong	control1;
	ulong	dummy0;
	ulong	data;
	ulong	dummy1;
	ulong	status;
};
extern SSPregs *sspregs;

/* Multimedia Communications Port controller registers */
typedef struct MCPregs MCPregs;
struct MCPregs {
	ulong	control0;
	ulong	reserved0;
	ulong	data0;
	ulong	data1;
	ulong	data2;
	ulong	reserved1;
	ulong	status;
	ulong	reserved[11];
	ulong	control1;
};
extern MCPregs *mcpregs;

/*
 *  memory configuration
 */
enum
{
	/* bit shifts for pcmcia access time counters */
	MECR_io0=	0,
	MECR_attr0=	5,
	MECR_mem0=	10,
	MECR_fast0=	11,
	MECR_io1=	MECR_io0+16,
	MECR_attr1=	MECR_attr0+16,
	MECR_mem1=	MECR_mem0+16,
	MECR_fast1=	MECR_fast0+16,

	REFR_kapd=	29,
	REFR_eapd=	28,
	REFR_k1db2=	22,
	REFR_slfrsh=	31,
};

typedef struct MemConfRegs MemConfRegs;
struct MemConfRegs
{
	ulong	mdcnfg;		/* 0x00	dram */
	ulong	mdcas00;		/* 0x04	dram banks 0/1 */
	ulong	mdcas01;		/* 0x08 */
	ulong	mdcas02;		/* 0x0c */
	ulong	msc0;		/* 0x10	static */
	ulong	msc1;		/* 0x14 */
	ulong	mecr;		/* 0x18	pcmcia */
	ulong	mdrefr;		/* 0x1c	dram refresh */
	ulong	mdcas20;		/* 0x20	dram banks 2/3 */
	ulong	mdcas21;		/* 0x24 */
	ulong	mdcas22;		/* 0x28 */
	ulong	msc2;		/* 0x2c	static */
	ulong	smcnfg;		/* 0x30	SMROM config */
};
extern MemConfRegs *memconfregs;

/*
 *  power management
 */

/* Power management ops */

typedef struct PowerRegs PowerRegs;
struct PowerRegs
{
	ulong	pmcr;	/* 0x0 Power manager control register */
	ulong	pssr;	/* 0x4 Power manager sleep status register */
	ulong	pspr;	/* 0x8 Power manager scratch pad register */
	ulong	pwer;	/* 0xc Power manager wakeup enable register */
	ulong	pcfr;	/* 0x10 Power manager general configuration register */
	ulong	ppcr;	/* 0x14 Power manager PPL configuration register */
	ulong	pgsr;	/* 0x18 Power manager GPIO sleep state register */
	ulong	posr;	/* 0x1c Power manager oscillator status register */
};
extern PowerRegs *powerregs;

/*
 *  reset controller
 */

enum
{
	RCSR_hwr = 0x00000001,	/* hw reset */
	RCSR_swr = 0x00000002,	/* sw reset */
	RCSR_wdr = 0x00000004,	/* watch dog */
	RCSR_smr = 0x00000008,	/* sleep mode reset */
};

typedef struct ResetRegs ResetRegs;
struct ResetRegs
{
	ulong	rsrr;	/* reset controller software reset register */
	ulong	rcsr;	/* reset controller status register */
};
extern ResetRegs *resetregs;

typedef  struct OSTimerRegs OSTimerRegs;
struct OSTimerRegs
{
	ulong	osmr[4];	/* match registers */
	ulong	oscr;		/* counter register */
	ulong	ossr;		/* status register */
	ulong	ower;		/* watchdog enable register */
	ulong	oier;		/* timer interrupt enable register */
};
extern OSTimerRegs* timerregs;

typedef struct Intrregs Intrregs;
struct Intrregs
{
	ulong	icip;	/* pending IRQs */
	ulong	icmr;	/* IRQ mask */
	ulong	iclr;	/* IRQ if bit == 0, FRIQ if 1 */
	ulong	iccr;	/* control register */
	ulong	icfp;	/* pending FIQs */
	ulong	dummy1[3];
	ulong	icpr;	/* pending interrupts */
};
extern Intrregs *intrregs;

typedef struct Gpclkregs Gpclkregs;
struct Gpclkregs
{
	ulong	r0;
	ulong	r1;
	ulong	dummya;
	ulong	r2;
	ulong	r3;
};
extern Gpclkregs *gpclkregs;

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2002-05-17 11:25 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2002-05-17 11:25 [9fans] bitsy suspend fix Fco.J.Ballesteros

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).