123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354 |
- #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 */
- #define TODFREQ 1000000000LL
- /* 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;
- // ulong mecr;
- ulong clkd;
- vlong savedtod;
- extern void power_resume(void);
- power_pl = splhi();
- xlink = getcallerpc(&xlink);
- /* Power down */
- pcmciapower(0);
- 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);
- if(setpowerlabel()){
- /* return here with mmu back on */
- trapresume();
- 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);
- }
- clkd = clockpower(1);
- gpclkregs->r0 = 1<<0;
- todset(savedtod + clkd * TODFREQ, 0LL, 0);
- resetsuspendtimer();
- 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);
- pcmciapower(1);
- splx(power_pl);
- return;
- }
- cacheflush();
- delay(100);
- savedtod = todget(nil);
- 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);
- }
- static ulong suspendtime = 120 * HZ;
- static int lastsuspend;
- void
- resetsuspendtimer(void)
- {
- suspendtime = 60 * HZ;
- }
- static void
- suspendtimer(void)
- {
- #ifdef notdef
- uvlong now;
- if (suspendtime > 0)
- suspendtime--;
- if (suspendtime == 0){
- now = seconds();
- if (now < lastsuspend + 10){
- resetsuspendtimer();
- return;
- }
- lastsuspend = seconds();
- deepsleep();
- lastsuspend = seconds();
- return;
- }
- #endif /* notdef */
- }
- void
- powerinit(void)
- {
- extern ulong power_magic;
- extern ulong power_code;
- extern ulong doze_code;
- ulong *p, *q, i;
- p = (ulong*)(((ulong)&power_magic + 0x1f) & ~0x1f);
- q = &power_code;
- for (i = 0; i < 8; i++)
- *p++ = *q++;
- p = (ulong*)(((ulong)doze + 0x3f) & ~0x1f);
- q = &doze_code;
- for (i = 0; i < 3; i++)
- *p++ = *q++;
- *resumeaddr = (ulong) power_resume;
- addclock0link(blanktimer, 1000/HZ);
- addclock0link(suspendtimer, 1000/HZ);
- 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();
- }
- }
|