M bitsy/clock.c => bitsy/clock.c +12 -1
@@ 16,12 16,23 @@ typedef struct OSTimer
ulong oier; /* timer interrupt enable register */
} OSTimer;
-static OSTimer *timerregs = (OSTimer*)OSTIMERREGS;
+OSTimer *timerregs = (OSTimer*)OSTIMERREGS;
static int clockinited;
static void clockintr(Ureg*, void*);
void
+clockpower(int on)
+{
+
+ if (on){
+ timerregs->ossr |= 1<<0;
+ timerregs->oier = 1<<0;
+ timerregs->osmr[0] = timerregs->oscr + ClockFreq/HZ;
+ }
+}
+
+void
clockinit(void)
{
ulong x;
M bitsy/devµc.c => bitsy/devµc.c +14 -0
@@ 379,6 379,20 @@ static long
return n;
}
+void
+µcpower(int on)
+{
+ uchar data[16];
+ if (on == 0)
+ return;
+ /* maybe dangerous, not holding the lock */
+ data[0]= 2;
+ data[1]= 1;
+ data[2]= 0x80;
+ _sendmsg(0xd, data, 3);
+ wakeup(&ctlr.r);
+}
+
Dev µcdevtab = {
'r',
"µc",
M bitsy/fns.h => bitsy/fns.h +5 -0
@@ 9,10 9,12 @@ void dcacheinvalidate(void);
int cistrcmp(char*, char*);
int cistrncmp(char*, char*, int);
void clockinit(void);
+void clockpower(int);
#define coherence()
#define dcflush(a, b)
void delay(int);
void µdelay(ulong);
+void µcpower(int);
void dmainit(void);
void _doze(void);
void (*doze)(void);
@@ 67,6 69,7 @@ PCMmap* pcmmap(int, ulong, int, int);
void pcmunmap(int, PCMmap*);
void penbutton(int, int);
void pentrackxy(int x, int y);
+void powerinit(void);
#define procrestore(p)
void procsave(Proc*);
void procsetup(Proc*);
@@ 78,6 81,7 @@ void rs232power(int);
void uartspecial(Uart*, int, Queue**, Queue**, int (*)(Queue*, int));
void sa1110_uartsetup(int);
void screeninit(void);
+void screenpower(int);
int screenprint(char*, ...); /* debugging */
void serialµcputs(uchar *str, int n);
void setr13(int, ulong*);
@@ 85,6 89,7 @@ uchar* tarlookup(uchar*, char*, int*);
void touser(void*);
void trapdump(char *tag);
void trapinit(void);
+void trapresume(void);
int tas(void*);
int uartstageoutput(Uart*);
void uartkick(void*);
M bitsy/io.h => bitsy/io.h +69 -1
@@ 130,7 130,8 @@ struct Uartregs
ulong dummyb;
ulong status[2];
};
-Uartregs *uart3regs;
+extern Uartregs *uart3regs;
+extern Uartregs *uart1regs;
/* general purpose I/O lines control registers */
typedef struct GPIOregs GPIOregs;
@@ 246,6 247,17 @@ extern MemConfRegs *memconfregs;
/*
* power management
*/
+
+/* Power management ops */
+enum {
+ PCFR_suspend = 1,
+
+ PCFR_opde = 1,
+ PCFR_fp = 2,
+ PCFR_fs = 4,
+ PCFR_fo = 8,
+};
+
typedef struct PowerRegs PowerRegs;
struct PowerRegs
{
@@ 259,3 271,59 @@ struct PowerRegs
ulong posr; /* 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 */
+ RCSR_all = 0x0000000f,
+};
+
+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;
M bitsy/l.s => bitsy/l.s +182 -0
@@ 443,6 443,188 @@ TEXT gotolabel(SB), $-4
MOVW $1, R0
RET
+/* save the state machine in power_resume[] for an upcoming suspend
+ */
+TEXT setpowerlabel(SB), $-4
+ MOVW $power_resume+0(SB), R0
+ /* svc */ /* power_resume[]: 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)
+ /* irq */
+ BIC $(PsrMask), R2, R3
+ ORR $(PsrDirq|PsrMirq), 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 $(PsrDirq|PsrMund), 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 $(PsrDirq|PsrMabt), 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 $(PsrDirq|PsrMfiq), 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 sa1100_power_resume(SB), $-4
+ MOVW $setR12(SB), R12 /* load the SB */
+ /* SVC mode, interrupts disabled */
+ MOVW $(PsrDirq|PsrDfiq|PsrMsvc), R1
+ MOVW R1, CPSR
+ /* 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
+ /* gotopowerlabel() */
+ /* svc */
+ MOVW $power_resume+0(SB), R0
+ MOVW 56(R0), R1 /* R1: SPSR, R2: CPSR */
+ MOVW 60(R0), R2
+ /* copro */
+ MOVW 148(R0), R3
+ MCR CpMMU, 0, R3, C(CpTTB), C(0x0)
+ MOVW 144(R0), R3
+ MCR CpMMU, 0, R3, C(CpDAC), C(0x0)
+ MOVW 152(R0), R3
+ MCR CpMMU, 0, R3, C(CpControl), 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)
+ MCR CpMMU, 0, R0, C(CpTLBFlush), C(0x7)
+ /* irq */
+ BIC $(PsrMask), R2, R3
+ ORR $(PsrDirq|PsrMirq), 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 $(PsrDirq|PsrMund), 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 $(PsrDirq|PsrMabt), 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 $(PsrDirq|PsrMfiq), 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
+
+
/* 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).
M bitsy/main.c => bitsy/main.c +6 -0
@@ 37,6 37,7 @@ main(void)
trapinit();
sa1110_uartsetup(1);
rs232power(1);
+ powerinit();
dmainit();
screeninit();
printinit(); /* from here on, print works, before this we need iprint */
@@ 362,6 363,8 @@ ulong *egpioreg = (ulong*)EGPIOREGS;
PPCregs *ppcregs;
MemConfRegs *memconfregs;
PowerRegs *powerregs;
+ResetRegs *resetregs;
+OSTimerRegs *timerregs = (OSTimerRegs*)OSTIMERREGS;
/*
* configure the machine
@@ 395,6 398,9 @@ machinit(void)
/* memory configuraton */
memconfregs = mapspecial(MEMCONFREGS, 32);
+
+ /* reset controller */
+ resetregs = mapspecial(RESETREGS, 32);
}
M bitsy/mem.h => bitsy/mem.h +23 -22
@@ 6,23 6,23 @@
* Sizes
*/
#define BI2BY 8 /* bits per byte */
-#define BI2WD 32 /* bits per word */
+#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 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 */
+#define MAXMACH 1 /* max # cpus system can run */
/*
* Time
*/
#define HZ (20) /* clock frequency */
-#define MS2HZ (1000/HZ) /* millisec per clock tick */
+#define MS2HZ (1000/HZ) /* millisec per clock tick */
#define TK2SEC(t) ((t)/HZ) /* ticks to seconds */
#define TK2MS(t) ((((ulong)(t))*1000)/HZ) /* ticks to milliseconds */
#define MS2TK(t) ((((ulong)(t))*HZ)/1000) /* milliseconds to ticks */
@@ 41,8 41,8 @@
* 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 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 */
@@ 52,19 52,19 @@
#define FLASHZERO 0xB0000000 /* 128 meg for flash */
#define FLASHTOP 0xB8000000 /* ... */
#define DRAMZERO 0xC0000000 /* 128 meg for dram */
-#define DRAMTOP 0xC8000000 /* ... */
+#define DRAMTOP 0xC8000000 /* ... */
#define UCDRAMZERO 0xC8000000 /* 128 meg for dram (uncached/unbuffered) */
-#define UCDRAMTOP 0xD0000000 /* ... */
+#define UCDRAMTOP 0xD0000000 /* ... */
#define NULLZERO 0xE0000000 /* 128 meg for cache flush zeroes */
-#define NULLTOP 0xE8000000 /* ... */
+#define NULLTOP 0xE8000000 /* ... */
#define USTKTOP 0x2000000 /* byte just beyond user stack */
-#define USTKSIZE (8*1024*1024) /* size of 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 TSTKSIZ 100
+#define MACHADDR (KZERO+0x00001000)
#define EVECTORS 0xFFFF0000 /* virt base of exception vectors */
-#define KSTACK (32*1024) /* Size of kernel stack */
+#define KSTACK (16*1024) /* Size of kernel stack */
/*
* Offsets into flash
@@ 97,17 97,18 @@
* 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 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 GPIOREGS 0x90040000 /* 28 general purpose IO pins */
-#define INTRREGS 0x90050000 /* interrupt 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 */
M bitsy/power.c => bitsy/power.c +152 -35
@@ 9,73 9,188 @@
/* Power management for the bitsy */
-#ifdef NOTDEF
-enum {
- pmcr_sf = 0,
+/* saved state during power down.
+ * it's only used up to 164/4.
+ * it's only used by routines in l.s
+ */
+ulong power_resume[200/4];
- pcfr_opde = 0,
- pcfr_fp = 1,
- pcfr_fs = 2,
- pcfr_fo = 3,
-};
+extern void sa1100_power_resume(void);
+extern int setpowerlabel(void);
+
+
+GPIOregs savedgpioregs;
+Uartregs saveduart3regs;
+Uartregs saveduart1regs;
+Intrregs savedintrregs;
-jmp_buf power_resume;
static void
-onoffintr(Ureg*, void *x)
+dumpitall(void)
{
- /* On/off button interrupt */
- int i;
+ 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",
+ uart1regs->ctl[0], uart1regs->status[0], uart1regs->status[1],
+ uart3regs->ctl[0], uart3regs->status[0], uart3regs->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);
+
+
+}
+
+static void
+intrcpy(Intrregs *to, Intrregs *from)
+{
+ to->iclr = from->iclr;
+ to->iccr = from->iccr;
+ to->icmr = from->icmr; // interrupts enabled
+}
+
+static void
+uartcpy(Uartregs *to, Uartregs *from)
+{
+ to->ctl[0] = from->ctl[0];
+// to->ctl[1] = from->ctl[1];
+// to->ctl[2] = from->ctl[2];
+ to->ctl[3] = from->ctl[3];
+
+}
+
+static void
+gpiocpy(GPIOregs *to, GPIOregs *from)
+{
+ to->rising = from->rising; // gpio intrs enabled
+ to->falling= from->falling; // gpio intrs enabled
+ to->altfunc = from->altfunc;
+ to->direction = from->direction;
+}
+
+static void
+sa1100_power_off(void)
+{
+ /* enable wakeup by µcontroller, on/off switch or real-time clock alarm */
+ powerregs->pwer = 1 << IRQrtc | 1 << IRQgpio0 | 1 << IRQgpio1;
+
+ /* clear previous reset status */
+ resetregs->rcsr = RCSR_all;
+
+ /* disable internal oscillator, float CS lines */
+ powerregs->pcfr = PCFR_opde | PCFR_fp | PCFR_fs;
+ powerregs->pgsr = 0;
+ /* set resume address. The loader jumps to it */
+ powerregs->pspr = (ulong)sa1100_power_resume;
+ /* set lowest clock; delay to avoid resume hangs on fast sa1110 */
+ delay(90);
+ powerregs->ppcr = 0;
+ delay(90);
+
+ /* set all GPIOs to input mode */
+ gpioregs->direction = 0;
+ delay(100);
+ /* enter sleep mode */
+ powerregs->pmcr = PCFR_suspend;
+ for(;;);
+}
- /* debounce, 50 ms*/
- for (i = 0; i < 50; i++) {
+void
+onoffintr(Ureg* , void*)
+{
+ static int power_pl;
+ int i;
+ for (i = 0; i < 100; i++) {
delay(1);
if ((gpioregs->level & GPIO_PWR_ON_i) == 0)
return; /* bounced */
}
- if (i = setjmp(power_resume)) {
- /* power back up */
+ power_pl = splhi();
+ cachewb();
+ delay(500);
+ if (setpowerlabel()) {
+ mmuinvalidate();
+ mmuenable();
+ cacheflush();
+ trapresume();
rs232power(1);
- lcdpower(1);
- audiopower(1);
irpower(1);
+ audiopower(1);
+ clockpower(1);
+ gpclkregs->r0 = 1<<0;
+ gpiocpy(gpioregs, &savedgpioregs);
+ 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);
+ }
+ uartcpy(uart3regs,&saveduart3regs);
+ uart3regs->status[0] = uart3regs->status[0];
+ uartcpy(uart1regs,&saveduart1regs);
+ uart1regs->status[0] = uart1regs->status[0];
+ µcpower(1);
+ screenpower(1);
+ iprint("\nresuming execution\n");
+// dumpitall();
+ delay(800);
+ splx(power_pl);
return;
}
/* Power down */
+ iprint("\nentering suspend mode\n");
+ gpiocpy(&savedgpioregs, gpioregs);
+ intrcpy(&savedintrregs, intrregs);
+ uartcpy(&saveduart3regs, uart3regs);
+ uartcpy(&saveduart1regs, uart1regs);
+ delay(400);
+ clockpower(0);
irpower(0);
audiopower(0);
- lcdpower(0);
+ screenpower(0);
+ µcpower(0);
rs232power(0);
sa1100_power_off();
/* no return */
}
-static void
-sa1100_power_off(void)
+
+
+static int
+bitno(ulong x)
{
- delay(100);
- splhi();
- /* enable wakeup by µcontroller, on/off switch or real-time clock alarm */
- powerregs->pwer = 0x80000003;
- /* disable internal oscillator, float CS lines */
- powerregs->pcfr = 1<<pcfr_opde | 1<<pcfr_fp | 1<<pcfr_fs;
- /* set lowest clock */
- powerregs->ppcr = 0;
- /* set all GPIOs to input mode */
- gpioregs->direction = 0;
- /* enter sleep mode */
- powerregs->pmcr = 1<<pmcr_sf;
+ int i;
+
+ for(i = 0; i < 8*sizeof(x); i++)
+ if((1<<i) & x)
+ break;
+ return i;
}
void
-idlehands(void)
+powerinit(void)
{
+ intrenable(GPIOrising, bitno(GPIO_PWR_ON_i), onoffintr, (void*)0x12344321, "on/off");
}
-#endif
+
+
void
idlehands(void)
{
+#ifdef notdef
char *msgb = "idlehands called with splhi\n";
char *msga = "doze returns with splhi\n";
@@ 88,4 203,6 @@ idlehands(void)
serialputs(msgb, strlen(msgb));
spllo();
}
+#endif
}
+
M bitsy/screen.c => bitsy/screen.c +14 -0
@@ 40,6 40,8 @@ struct sa1110fb {
ushort pixel[Wid*Ht]; /* Pixel data */
} *framebuf;
+short savedpalette[16]; /* saved during suspend mode */
+
enum {
/* LCD Control Register 0, lcd->lccr0 */
LEN = 0, /* 1 bit */
@@ 208,6 210,18 @@ lcdtweak(Cmdbuf *cmd)
}
void
+screenpower(int on)
+{
+ if (on == 0){
+ memmove(savedpalette, framebuf->palette, sizeof framebuf->palette);
+ blankscreen(1);
+ } else {
+ memmove(framebuf->palette, savedpalette, sizeof framebuf->palette);
+ blankscreen(0);
+ }
+}
+
+void
screeninit(void)
{
int i;
M bitsy/trap.c => bitsy/trap.c +21 -14
@@ 7,18 7,7 @@
#include "ureg.h"
#include "../port/error.h"
-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 */
-};
-
-struct Intrregs *intrregs;
+Intrregs *intrregs;
typedef struct Vctl {
Vctl* next; /* handlers on this vector */
@@ 49,8 38,24 @@ void (*doze)(void);
static void irq(Ureg*);
static void gpiointr(Ureg*, void*);
+/* recover state after power suspend
+ * NB: to help debugging bad suspend code,
+ * I changed some prints below to iprints,
+ * to avoid deadlocks when a panic is being
+ * issued during the suspend/resume handler.
+ */
+void
+trapresume(void)
+{
+ vpage0 = (Vpage0*)EVECTORS;
+ memmove(vpage0->vectors, vectors, sizeof(vpage0->vectors));
+ memmove(vpage0->vtable, vtable, sizeof(vpage0->vtable));
+ wbflush();
+ mappedIvecEnable();
+}
+
/*
- * set up for exceptioons
+ * set up for exceptions
*/
void
trapinit(void)
@@ 751,8 756,10 @@ _dumpstack(Ureg *ureg)
ulong *p;
extern ulong etext;
- if(up == 0)
+ if(up == 0){
+ print("no current proc\n");
return;
+ }
print("ktrace /kernel/path %.8lux %.8lux %.8lux\n", ureg->pc, ureg->sp, ureg->r14);
i = 0;
M bitsy/uartsa1110.c => bitsy/uartsa1110.c +0 -10
@@ 436,16 436,6 @@ serialµcputs(uchar *str, int n)
;
}
-typedef struct Gpclkregs Gpclkregs;
-struct Gpclkregs
-{
- ulong r0;
- ulong r1;
- ulong dummya;
- ulong r2;
- ulong r3;
-};
-
enum
{
/* gpclk register 0 */