2 #include "../port/lib.h"
10 /* Power management for the bitsy */
12 #define TODFREQ 1000000000LL
14 /* saved state during power down.
15 * it's only used up to 164/4.
16 * it's only used by routines in l.s
18 ulong power_state[200/4];
22 ulong powerflag = 0; /* set to start power-off sequence */
24 extern void power_resume(void);
25 extern int setpowerlabel(void);
26 extern void _start(void);
27 extern Uart sa1110uart[];
29 GPIOregs savedgpioregs;
30 Intrregs savedintrregs;
32 #define R(p) ((Uartregs*)((p)->regs))
43 for (p = (ulong*)FLASHZERO; p < (ulong*)(FLASHZERO+8*1024*1024); p++)
45 iprint("flash checksum is 0x%lux\n", s);
55 for (p = (ulong*)_start; p < (ulong*)etext; p++){
57 iprint("%#p->0\n", p);
58 if (((ulong)p & 0x1fff) == 0){
59 iprint("page 0x%lux checksum 0x%lux\n",
60 (ulong)(p-1)&~0x1fff, s);
65 iprint("page 0x%lux checksum 0x%lux\n", (ulong)(p-1)&~0x1fff, s);
76 for (p = (ulong*)l1table; p < (ulong*)(l1table+16*1024); p++)
78 iprint("page table checksum is 0x%lux\n", s);
87 iprint("intr: icip %lux iclr %lux iccr %lux icmr %lux\n",
89 intrregs->iclr, intrregs->iccr, intrregs->icmr );
90 iprint("gpio: lvl %lux dir %lux, re %lux, fe %lux sts %lux alt %lux\n",
92 gpioregs->direction, gpioregs->rising, gpioregs->falling,
93 gpioregs->edgestatus, gpioregs->altfunc);
94 iprint("uart1: %lux %lux %lux \nuart3: %lux %lux %lux\n",
95 R(&sa1110uart[0])->ctl[0], R(&sa1110uart[0])->status[0], R(&sa1110uart[0])->status[1],
96 R(&sa1110uart[1])->ctl[0], R(&sa1110uart[1])->status[0], R(&sa1110uart[1])->status[1]);
97 iprint("tmr: osmr %lux %lux %lux %lux oscr %lux ossr %lux oier %lux\n",
98 timerregs->osmr[0], timerregs->osmr[1],
99 timerregs->osmr[2], timerregs->osmr[3],
100 timerregs->oscr, timerregs->ossr, timerregs->oier);
101 iprint("dram: mdcnfg %lux mdrefr %lux cas %lux %lux %lux %lux %lux %lux\n",
102 memconfregs->mdcnfg, memconfregs->mdrefr,
103 memconfregs->mdcas00, memconfregs->mdcas01,memconfregs->mdcas02,
104 memconfregs->mdcas20, memconfregs->mdcas21,memconfregs->mdcas22);
105 iprint("dram: mdcnfg msc %lux %lux %lux mecr %lux\n",
106 memconfregs->msc0, memconfregs->msc1,memconfregs->msc2,
108 iprint("mmu: CpControl %lux CpTTB %lux CpDAC %lux l1table 0x%lux\n",
109 getcontrol(), getttb(), getdac(), l1table);
110 iprint("powerregs: pmcr %lux pssr %lux pcfr %lux ppcr %lux pwer %lux pspr %lux pgsr %lux posr %lux\n",
111 powerregs->pmcr, powerregs->pssr, powerregs->pcfr, powerregs->ppcr,
112 powerregs->pwer, powerregs->pspr, powerregs->pgsr, powerregs->posr);
120 intrcpy(Intrregs *to, Intrregs *from)
122 to->iclr = from->iclr;
123 to->iccr = from->iccr;
124 to->icmr = from->icmr; // interrupts enabled
128 gpiosave(GPIOregs *to, GPIOregs *from)
130 to->level = from->level;
131 to->rising = from->rising; // gpio intrs enabled
132 to->falling= from->falling; // gpio intrs enabled
133 to->altfunc = from->altfunc;
134 to->direction = from->direction;
138 gpiorestore(GPIOregs *to, GPIOregs *from)
140 to->direction = from->direction;
141 to->altfunc = from->altfunc;
142 to->set = from->level & 0x0fffffff;
143 to->clear = ~from->level & 0x0fffffff;
144 to->rising = from->rising; // gpio intrs enabled
145 to->falling= from->falling; // gpio intrs enabled
148 void (*restart)(void) = nil;
155 for(i = 0; i < 8*sizeof(x); i++)
174 extern void power_resume(void);
177 xlink = getcallerpc(&xlink);
185 iprint("entering suspend mode, sp = %#p, pc = 0x%lux, psw = 0x%ux\n",
186 &xsp, xlink, power_pl);
192 gpiosave(&savedgpioregs, gpioregs);
193 intrcpy(&savedintrregs, intrregs);
197 /* return here with mmu back on */
200 gpiorestore(gpioregs, &savedgpioregs);
202 intrcpy(intrregs, &savedintrregs);
203 if(intrregs->icip & (1<<IRQgpio0)){
204 // don't want to sleep now. clear on/off irq.
205 gpioregs->edgestatus = (1<<IRQgpio0);
206 intrregs->icip = (1<<IRQgpio0);
208 clkd = clockpower(1);
209 gpclkregs->r0 = 1<<0;
210 todset(savedtod + clkd * TODFREQ, 0LL, 0);
215 xlink = getcallerpc(&xlink);
216 iprint("\nresuming execution, sp = %#p, pc = 0x%lux, psw = 0x%ux\n",
217 &xsp, xlink, splhi());
230 savedtod = todget(nil);
241 while(powerflag == 0)
242 sleep(&powerr, powerdown, 0);
244 xlink = getcallerpc(&xlink);
246 // iprint("call deepsleep, pc = 0x%lux, sp = 0x%lux\n", xlink, &xlink);
248 xlink1 = getcallerpc(&xlink1);
253 // iprint("deepsleep returned, pc = 0x%lux, sp = 0x%lux\n", xlink1, &xlink);
259 onoffintr(Ureg* , void*)
263 /* Power down interrupt comes on power button release.
264 * Act only after button has been released a full 100 ms
270 for (i = 0; i < 100; i++) {
272 if ((gpioregs->level & GPIO_PWR_ON_i) == 0)
273 return; /* bounced */
286 static ulong suspendtime = 120 * HZ;
287 static int lastsuspend;
290 resetsuspendtimer(void)
292 suspendtime = 60 * HZ;
303 if (suspendtime == 0){
305 if (now < lastsuspend + 10){
309 lastsuspend = seconds();
311 lastsuspend = seconds();
320 extern ulong power_magic;
321 extern ulong power_code;
322 extern ulong doze_code;
325 p = (ulong*)(((ulong)&power_magic + 0x1f) & ~0x1f);
327 for (i = 0; i < 8; i++)
329 p = (ulong*)(((ulong)doze + 0x3f) & ~0x1f);
331 for (i = 0; i < 3; i++)
334 *resumeaddr = (ulong) power_resume;
335 addclock0link(blanktimer, 1000/HZ);
336 addclock0link(suspendtimer, 1000/HZ);
337 intrenable(GPIOrising, bitno(GPIO_PWR_ON_i), onoffintr, nil, "on/off");
343 char *msgb = "idlehands called with splhi\n";
344 char *msga = "doze returns with splhi\n";
347 uartputs(msga, strlen(msga));
352 uartputs(msgb, strlen(msgb));