#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_resume[200/4]; Rendez powerr; ulong powerflag = 0; /* set to start power-off sequence */ extern void sa1100_power_resume(void); extern int setpowerlabel(void); extern void _start(void); extern Uart sa1110uart[]; GPIOregs savedgpioregs; Intrregs savedintrregs; #define R(p) ((Uartregs*)((p)->regs)) static void dumpitall(void) { 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); } static void intrcpy(Intrregs *to, Intrregs *from) { to->iclr = from->iclr; to->iccr = from->iccr; to->icmr = from->icmr; // interrupts enabled } 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; } void (*restart)(void) = nil; 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(;;); } static int bitno(ulong x) { int i; for(i = 0; i < 8*sizeof(x); i++) if((1<r0 = 1<<0; gpiocpy(gpioregs, &savedgpioregs); intrcpy(intrregs, &savedintrregs); if (intrregs->icip & (1<edgestatus = (1<icip = (1<level & GPIO_PWR_ON_i) == 0) return; /* bounced */ } powerflag = 1; wakeup(&powerr); } void powerinit(void) { intrenable(GPIOrising, bitno(GPIO_PWR_ON_i), onoffintr, nil, "on/off"); } void idlehands(void) { #ifdef notdef char *msgb = "idlehands called with splhi\n"; char *msga = "doze returns with splhi\n"; if(!islo()){ serialputs(msga, strlen(msga)); spllo(); } doze(); if(!islo()){ serialputs(msgb, strlen(msgb)); spllo(); } #endif }